1 #include "lsg2.h"
2 #include <string.h>
3 #include <stdlib.h>
4 #include <ctype.h>
5 
6 extern int flag_cmp(const void *, const void *);
7 
lsg2_admin_validate()8 int lsg2_admin_validate()
9 {
10    char cookiebuf[BIG_BUF];
11    const char *list, *fromaddy;
12    struct list_user user;
13 
14    if (!lsg2_validate(cookiebuf, sizeof(cookiebuf) - 1)) {
15       return 0;
16    }
17 
18    list = LMAPI->get_var("lcgi-list");
19    fromaddy = LMAPI->get_var("lcgi-user");
20 
21    if (!list || !fromaddy) {
22       lsg2_internal_error("Mode initialized incorrectly.");
23       return 0;
24    }
25 
26    if (!LMAPI->user_find_list(list,fromaddy,&user)) {
27       lsg2_internal_error("Mode initialized incorrectly.");
28       return 0;
29    }
30 
31    if (LMAPI->get_bool("lsg2-paranoia")) {
32       lsg2_internal_error("Attempt to use admin mode when paranoia is enabled!");
33       return 0;
34    }
35 
36    if (!LMAPI->user_hasflag(&user,"ADMIN")) {
37       lsg2_internal_error("A non-admin user tried to use admin mode.");
38       return 0;
39    }
40 
41    return 1;
42 }
43 
CGI_MODE(cgimode_admin)44 CGI_MODE(cgimode_admin)
45 {
46    if (!lsg2_admin_validate()) {
47       return;
48    }
49 
50    if (!LMAPI->cgi_unparse_template("adminmenu")) {
51       lsg2_internal_error("No 'adminmenu' template.");
52    }
53 
54    return;
55 }
56 
CGI_MODE(cgimode_config)57 CGI_MODE(cgimode_config)
58 {
59    if (!lsg2_admin_validate()) {
60       return;
61    }
62 
63    if (!LMAPI->cgi_unparse_template("config")) {
64       lsg2_internal_error("No 'config' template.");
65    }
66 
67    return;
68 }
69 
CGI_HANDLER(cgihook_configfile)70 CGI_HANDLER(cgihook_configfile)
71 {
72    const char *fromaddy, *list;
73    struct list_user user;
74    struct var_data *vartemp;
75    char lastsect[BIG_BUF];
76    int counter, trusted;
77 
78    fromaddy = LMAPI->get_var("lcgi-user");
79    list = LMAPI->get_var("lcgi-list");
80 
81    if (!fromaddy || !list) return 0;
82 
83    if (!LMAPI->user_find_list(list,fromaddy,&user))
84       return 0;
85 
86    if (!LMAPI->user_hasflag(&user,"ADMIN"))
87       return 0;
88 
89    trusted = LMAPI->is_trusted(list);
90 
91    printf("<table border=0 width=100%%>\n");
92 
93    counter = 0;
94 
95    vartemp = LMAPI->start_varlist();
96 
97    while (vartemp) {
98       const char *val;
99 
100       if (!(vartemp->flags & VAR_LIST) || (vartemp->flags & VAR_INTERNAL)) {
101          vartemp = LMAPI->next_varlist();
102          continue;
103       }
104 
105       if ((vartemp->flags & VAR_RESTRICTED) && !trusted) {
106          vartemp = LMAPI->next_varlist();
107          continue;
108       }
109 
110       if (counter ? (vartemp->section ? strcasecmp(lastsect,vartemp->section) : 0 ) : 1) {
111          stringcpy(lastsect,vartemp->section);
112          if (counter) {
113             printf("<tr><td colspan=4><HR></td></tr>\n");
114          }
115          printf("<tr>\n");
116          printf("<td colspan=4><a name=\"%s\"><font size=+1><b>%s</b></font></td>\n",
117            lastsect, lastsect);
118          printf("</tr>\n");
119       }
120 
121       if (!vartemp->section && lastsect[0]) {
122          lastsect[0] = 0;
123          if (counter) {
124             printf("<tr><td colspan=4><HR></td></tr>\n");
125          }
126          printf("<tr><td colspan=4><a name=\"misc\"><font size=+1><b>(Unclassified/Misc)</b></font></td></tr>\n");
127       }
128 
129       counter++;
130 
131       printf("<tr>\n");
132 
133       val = LMAPI->get_cur_varval_level(vartemp, VAR_LIST);
134       if (val) {
135          printf(" <td valign=top><input name=\"lcgipl-%s-set\" type=checkbox",
136           vartemp->name);
137          printf(" checked=\"true\"");
138          printf("></td>\n");
139       } else {
140          val = LMAPI->get_cur_varval_level_default(vartemp, VAR_LIST);
141          printf("<td>&nbsp;</td>\n");
142       }
143 
144       LMAPI->log_printf(18,"CGI: %s = %s\n", vartemp->name, val);
145 
146       printf(" <td valign=top>%s</td>\n", vartemp->name);
147       printf(" <td valign=top>");
148 
149       switch (vartemp->type) {
150          case VAR_STRING:
151          case VAR_INT:
152          case VAR_TIME:
153             printf("  <input name=\"lcgipl-%s-value\"", vartemp->name);
154             if (vartemp->type == VAR_STRING) {
155                printf(" size=30");
156             }
157             if (val) {
158                printf(" value=\"%s\"", val);
159             }
160             printf(">\n");
161             break;
162 
163          case VAR_DURATION:
164             {
165                int days, hours, mins, secs;
166                int parse;
167                const char *tchr;
168 
169                days = hours = mins = secs = 0;
170 
171                parse = 0;
172 
173                tchr = val;
174 
175                while (tchr ? *tchr : 0) {
176                   while (*tchr && isspace((int)(*tchr))) tchr++;
177                   while (*tchr && isdigit((int)(*tchr))) { parse = parse * 10 + (*tchr - '0'); tchr++; }
178                   while (*tchr && isspace((int)(*tchr))) tchr++;
179                   if (*tchr) {
180                      switch(*tchr) {
181                         case 'd': days = parse; parse = 0; tchr++; break;
182                         case 'h': hours = parse; parse = 0; tchr++; break;
183                         case 'm': mins = parse; parse = 0; tchr++; break;
184                         default: secs = parse; parse = 0; tchr++; break;
185                      }
186                   }
187                }
188 
189                printf("\n   <input name=\"lcgipl-%s-value-days\" value=\"%d\" size=2> d\n", vartemp->name, days);
190                printf("   <input name=\"lcgipl-%s-value-hours\" value=\"%d\" size=2> h\n", vartemp->name, hours);
191                printf("   <input name=\"lcgipl-%s-value-mins\" value=\"%d\" size=2> m\n", vartemp->name, mins);
192                printf("   <input name=\"lcgipl-%s-value-secs\" value=\"%d\" size=2> s\n  ", vartemp->name, secs);
193             }
194             break;
195 
196          case VAR_BOOL:
197             printf("<input type=checkbox name=\"lcgipl-%s-value\"",
198                vartemp->name);
199             if (val ? (*val == '1') : 0) {
200                printf(" checked=true");
201             }
202             printf(">");
203             break;
204 
205          case VAR_CHOICE:
206             {
207                char choices[BIG_BUF], *tmpptr, *tmpptr2;
208 
209                LMAPI->log_printf(18,"CGI: %s (%s)\n", vartemp->name, vartemp->choices);
210 
211                printf("\n   <select name=\"lcgipl-%s-value\" size=1>\n",
212                   vartemp->name);
213                stringcpy(choices, vartemp->choices);
214 
215                tmpptr = &choices[1];
216                while(*tmpptr) {
217                   tmpptr2 = strchr(tmpptr,'|');
218                   *tmpptr2++ = 0;
219 
220                   if (strcasecmp(tmpptr,val) == 0) {
221                     printf("    <option value=\"%s\" selected> %s\n",
222                       tmpptr, tmpptr);
223                   } else {
224                     printf("    <option value=\"%s\"> %s\n", tmpptr, tmpptr);
225                   }
226 
227                   tmpptr = tmpptr2;
228                }
229                printf("   </select>\n");
230             }
231             break;
232 
233          default:
234             printf("<b>UNSETTABLE VARIABLE!  ERROR!</b>");
235             break;
236       }
237 
238       printf("</td>\n");
239       if (vartemp->description) {
240          printf(" <td valign=top>%s\n",
241            vartemp->description);
242          printf("<BR>&nbsp;</td>\n");
243       } else {
244          printf(" <td>&nbsp;<BR><BR>&nbsp;</td>\n");
245       }
246       printf("</tr>");
247 
248       vartemp = LMAPI->next_varlist();
249    }
250    LMAPI->finish_varlist();
251 
252    printf("</table>\n");
253 
254    return 1;
255 }
256 
CGI_MODE(cgimode_setconfig)257 CGI_MODE(cgimode_setconfig)
258 {
259    char buffer[BIG_BUF];
260    const char *tempval;
261    struct var_data *var;
262    struct listserver_cgi_tempvar *cvar;
263    int override, durtotal;
264 
265    durtotal = 0;
266 
267    if (!lsg2_admin_validate())
268       return;
269 
270    var = LMAPI->start_varlist();
271 
272    while (var) {
273       if (!(var->flags & VAR_LIST) || (var->flags & VAR_INTERNAL)) {
274          var = LMAPI->next_varlist();
275          continue;
276       }
277 
278       LMAPI->log_printf(18,"CGI: Config submit: checking '%s'...\n",
279         var->name);
280 
281       LMAPI->buffer_printf(buffer, sizeof(buffer) - 1, "%s-set",
282          var->name);
283 
284       cvar = LMAPI->find_cgi_tempvar(buffer);
285 
286       tempval = LMAPI->get_cur_varval_level(var,VAR_LIST);
287 
288       override = 0;
289 
290       if (cvar) LMAPI->log_printf(18,"CGI: Config (%s set '%s')\n",
291          var->name, cvar->value);
292 
293       if (cvar ? strcasecmp(cvar->value,"on") == 0 : !tempval) {
294          char varbuffer[BIG_BUF];
295 
296          LMAPI->log_printf(18,"CGI: Entering the variable check loop...\n");
297 
298          if (cvar ? strcasecmp(cvar->value,"on") == 0 : 0) override = 1;
299 
300             switch(var->type) {
301                case VAR_STRING:
302                case VAR_INT:
303                case VAR_TIME:
304                case VAR_CHOICE:
305                   LMAPI->buffer_printf(buffer, sizeof(buffer) - 1, "%s-value",
306                      var->name);
307                   cvar = LMAPI->find_cgi_tempvar(buffer);
308                   if (cvar) {
309                      LMAPI->buffer_printf(varbuffer, sizeof(varbuffer) - 1,
310                         "%s", cvar->value);
311                   } else {
312                      memset(varbuffer, 0, sizeof(varbuffer));
313                      LMAPI->clean_var(var->name,VAR_LIST);
314                   }
315                   break;
316 
317                case VAR_DURATION:
318                   {
319                      int days, hours, mins, secs;
320                      char daystr[SMALL_BUF], hourstr[SMALL_BUF], minstr[SMALL_BUF], secstr[SMALL_BUF];
321 
322                      days = hours = mins = secs = 0;
323 
324                      LMAPI->buffer_printf(buffer, sizeof(buffer) - 1, "%s-value-days",
325                          var->name);
326                      cvar = LMAPI->find_cgi_tempvar(buffer);
327                      if (cvar)
328                         days = atoi(cvar->value);
329                      LMAPI->buffer_printf(buffer, sizeof(buffer) - 1, "%s-value-hours",
330                          var->name);
331                      cvar = LMAPI->find_cgi_tempvar(buffer);
332                      if (cvar)
333                         hours = atoi(cvar->value);
334                      LMAPI->buffer_printf(buffer, sizeof(buffer) - 1, "%s-value-mins",
335                          var->name);
336                      cvar = LMAPI->find_cgi_tempvar(buffer);
337                      if (cvar)
338                         mins = atoi(cvar->value);
339                      LMAPI->buffer_printf(buffer, sizeof(buffer) - 1, "%s-value-secs",
340                          var->name);
341                      cvar = LMAPI->find_cgi_tempvar(buffer);
342                      if (cvar)
343                         secs = atoi(cvar->value);
344 
345                      LMAPI->buffer_printf(daystr, sizeof(daystr) - 1, "%d d ", days);
346                      LMAPI->buffer_printf(hourstr, sizeof(hourstr) - 1, "%d h ", hours);
347                      LMAPI->buffer_printf(minstr, sizeof(minstr) - 1, "%d m ", mins);
348                      LMAPI->buffer_printf(secstr, sizeof(secstr) - 1, "%d s", secs);
349 
350                      durtotal = secs + (mins * 60) + (hours * 3600) +
351                                 (days * 86400);
352 
353                      LMAPI->buffer_printf(varbuffer, sizeof(varbuffer) - 1,
354                        "%s%s%s%s",
355                        days ? daystr : "", hours ? hourstr : "",
356                        mins ? minstr : "", secs ? secstr : "");
357                   }
358                   break;
359 
360                case VAR_BOOL:
361                   LMAPI->buffer_printf(buffer, sizeof(buffer) - 1, "%s-value",
362                      var->name);
363                   if ((cvar = LMAPI->find_cgi_tempvar(buffer))) {
364                      if (strcasecmp(cvar->value,"on") == 0) {
365                         LMAPI->buffer_printf(varbuffer, sizeof(varbuffer) - 1, "true");
366                      } else {
367                         LMAPI->buffer_printf(varbuffer, sizeof(varbuffer) - 1, "false");
368                      }
369                   } else {
370                      LMAPI->buffer_printf(varbuffer, sizeof(varbuffer) - 1, "false");
371                   }
372                   break;
373 
374                default:
375                   break;
376             }
377 
378             if (!override) {
379                const char *val;
380 
381                val = LMAPI->get_cur_varval_level(var,VAR_LIST);
382 
383                if (!val) {
384                   val = LMAPI->get_cur_varval_level_default(var,VAR_LIST);
385 
386                   LMAPI->log_printf(18, "CGI: %s = %s (now %s)\n",
387                     var->name, val, varbuffer);
388 
389                   if (val) {
390                      switch (var->type) {
391                         case VAR_STRING:
392                         case VAR_CHOICE:
393                           if (strcasecmp(val,varbuffer) != 0) {
394                              LMAPI->set_var(var->name,varbuffer,VAR_LIST);
395                           }
396                           break;
397 
398                         case VAR_INT:
399                         case VAR_TIME:
400                           if (LMAPI->get_number(var->name) != atoi(varbuffer)) {
401                              LMAPI->set_var(var->name,varbuffer,VAR_LIST);
402                           }
403                           break;
404 
405                         case VAR_BOOL:
406                           LMAPI->log_printf(18,"CGI: %s: %d / %d\n",
407                              var->name, LMAPI->get_bool(var->name),
408                              (strcasecmp("true",varbuffer) == 0));
409                           if (LMAPI->get_bool(var->name) !=
410                               (strcasecmp("true",varbuffer) == 0)) {
411                              LMAPI->set_var(var->name,varbuffer,VAR_LIST);
412                           }
413                           break;
414 
415                         case VAR_DURATION:
416                           if (LMAPI->get_seconds(var->name) != durtotal) {
417                              LMAPI->set_var(var->name,varbuffer,VAR_LIST);
418                           }
419                           break;
420 
421                         default:
422                           break;
423                      }
424                   } else {
425                      if (varbuffer[0]) {
426                         LMAPI->set_var(var->name,varbuffer,VAR_LIST);
427                      }
428                   }
429                } else {
430                   LMAPI->clean_var(var->name,VAR_LIST);
431                }
432             } else {
433                LMAPI->set_var(var->name,varbuffer,VAR_LIST);
434             }
435       } else {
436          LMAPI->clean_var(var->name,VAR_LIST);
437       }
438 
439       var = LMAPI->next_varlist();
440    }
441 
442    LMAPI->finish_varlist();
443 
444    LMAPI->log_printf(18,"CGI: strip-mdn = %s\n",
445      LMAPI->get_bool("strip-mdn") ? "true" : "false");
446 
447    LMAPI->listdir_file(buffer,LMAPI->get_string("lcgi-list"),"config");
448    LMAPI->write_configfile(buffer,VAR_LIST,NULL);
449 
450    LMAPI->log_printf(1,"CGI: %s: %s sent new config\n",
451       LMAPI->get_string("lcgi-list"), LMAPI->get_string("lcgi-user"));
452 
453    if (!LMAPI->cgi_unparse_template("adminmenu")) {
454       lsg2_internal_error("No 'adminmenu' template.");
455    }
456 
457    return;
458 }
459 
CGI_MODE(cgimode_getfile)460 CGI_MODE(cgimode_getfile)
461 {
462    const char *getfile;
463    struct list_file *tfile;
464 
465    if (!lsg2_admin_validate()) {
466       return;
467    }
468 
469    getfile = LMAPI->get_var("lcgi-adminfile");
470    if (!getfile) {
471       lsg2_internal_error("Mode initialized wrong.");
472       return;
473    }
474 
475    tfile = LMAPI->find_file(getfile);
476    if (!tfile) {
477       lsg2_internal_error("Attempt to retrieve a nonexistant file.");
478       return;
479    }
480 
481    LMAPI->set_var("tlcgi-editfile", LMAPI->get_var(tfile->varname),
482      VAR_TEMP);
483 
484    LMAPI->set_var("tlcgi-editfile-desc", tfile->desc, VAR_TEMP);
485 
486    if (!LMAPI->cgi_unparse_template("fileedit")) {
487       lsg2_internal_error("No 'fileedit' template.");
488    }
489 
490    return;
491 }
492 
file_cmp(const void * e1,const void * e2)493 int file_cmp(const void *e1, const void *e2)
494 {
495    struct list_file *f1, *f2;
496    f1 = *(struct list_file **)e1;
497    f2 = *(struct list_file **)e2;
498 
499    return (strcasecmp(f1->name,f2->name));
500 }
501 
CGI_HANDLER(cgihook_adminfilelistdrop)502 CGI_HANDLER(cgihook_adminfilelistdrop)
503 {
504    struct list_file *tfile;
505    struct list_file **filearr;
506    int counter, i;
507 
508    tfile = LMAPI->get_files();
509 
510    counter = 0;
511 
512    while (tfile) {
513       tfile = tfile->next;
514       counter++;
515    }
516 
517 
518    filearr = (struct list_file **)malloc(sizeof(struct list_file *) * counter);
519 
520    tfile = LMAPI->get_files();
521    for (i = 0; i < counter; i++) {
522       filearr[i] = tfile;
523       tfile = tfile->next;
524    }
525 
526    qsort(filearr,counter,sizeof(struct list_file *),file_cmp);
527 
528    printf("<select name=\"lcgi-adminfile\" size=6>\n");
529 
530    for (i = 0; i < counter; i++) {
531       if (!(filearr[i]->flags & FILE_NOWEBEDIT))
532          printf("<option value=\"%s\"> %s\n", filearr[i]->name,
533             filearr[i]->name);
534    }
535    printf("</select>\n");
536 
537    free(filearr);
538 
539    return 1;
540 }
541 
CGI_HANDLER(cgihook_fileedit)542 CGI_HANDLER(cgihook_fileedit)
543 {
544    const char *filepath;
545    FILE *infile;
546    char buffer[BIG_BUF];
547 
548    filepath = LMAPI->get_var("tlcgi-editfile");
549    if (!filepath) return 0;
550 
551    LMAPI->listdir_file(buffer,LMAPI->get_string("lcgi-list"),filepath);
552 
553    infile = LMAPI->open_file(buffer,"r");
554 
555    printf("<textarea name=\"lcgipl-textbody\" rows=18 cols=76 wrap=physical>");
556 
557    if (infile) {
558       while(LMAPI->read_file(buffer, sizeof(buffer), infile)) {
559          printf("%s",buffer);
560       }
561       LMAPI->close_file(infile);
562    } else {
563       printf("** File was empty **\n");
564    }
565    printf("</textarea>");
566 
567    return 1;
568 }
569 
CGI_MODE(cgimode_putfile)570 CGI_MODE(cgimode_putfile)
571 {
572    const char *getfile;
573    struct list_file *tfile;
574    FILE *outfile;
575    char buffer[BIG_BUF];
576    struct listserver_cgi_tempvar *cvar;
577 
578    if (!lsg2_admin_validate()) {
579       return;
580    }
581 
582    getfile = LMAPI->get_var("lcgi-adminfile");
583    if (!getfile) {
584       lsg2_internal_error("Mode initialized wrong.");
585       return;
586    }
587 
588    LMAPI->log_printf(18,"CGI: Made it into putfile...\n");
589 
590    tfile = LMAPI->find_file(getfile);
591    if (!tfile) {
592       lsg2_internal_error("Attempt to replace a nonexistant file.");
593       return;
594    }
595 
596    cvar = LMAPI->find_cgi_tempvar("textbody");
597 
598    if (!cvar) {
599       /* The entire textbox contents were deleted... the file is gone */
600 
601       LMAPI->listdir_file(buffer,LMAPI->get_string("lcgi-list"),
602             LMAPI->get_string(tfile->varname));
603       LMAPI->unlink_file(buffer);
604       return;
605    }
606 
607    LMAPI->log_printf(18,"CGI: We have our textbody...\n");
608 
609    LMAPI->listdir_file(buffer,LMAPI->get_string("lcgi-list"),LMAPI->get_string(tfile->varname));
610 
611    LMAPI->log_printf(18,"CGI: Attempting to put file %s\n", buffer);
612 
613    if ((outfile = LMAPI->open_file(buffer,"w")) == NULL) {
614       lsg2_internal_error("File access error.");
615       return;
616    }
617 
618    LMAPI->write_file(outfile,"%s",cvar->value);
619    LMAPI->close_file(outfile);
620 
621    LMAPI->log_printf(1,"CGI: %s: %s replaced '%s' \n",
622       LMAPI->get_string("lcgi-list"), LMAPI->get_string("lcgi-user"),
623       tfile->name);
624 
625    if (!LMAPI->cgi_unparse_template("adminmenu")) {
626       lsg2_internal_error("No 'adminmenu' template.");
627    }
628 
629    return;
630 }
631 
CGI_MODE(cgimode_admin_subscribe)632 CGI_MODE(cgimode_admin_subscribe)
633 {
634    char userfile[BIG_BUF];
635    char tempbuf[BIG_BUF];
636    const char *from;
637    char *inputbuffer, *ptr1, *ptr2;
638    struct listserver_cgi_tempvar *cvar;
639 
640    if (!lsg2_admin_validate()) {
641       return;
642    }
643 
644    from = LMAPI->get_var("lcgi-user");
645 
646    cvar = LMAPI->find_cgi_tempvar("subscribe-userlist");
647 
648    if (!cvar) {
649       lsg2_internal_error("No users provided.");
650    }
651 
652    inputbuffer = strdup(cvar->value);
653 
654    LMAPI->set_var("adminmode","true",VAR_GLOBAL);
655    LMAPI->set_var("fromaddress",from,VAR_GLOBAL);
656    LMAPI->set_var("realsender",from,VAR_GLOBAL);
657 
658    ptr1 = inputbuffer;
659 
660 
661    while(ptr1 && *ptr1) {
662       char *tptr;
663 
664       while(isspace((int)(*ptr1))) ptr1++;
665 
666       ptr2 = strchr(ptr1,'\n');
667 
668       tptr = NULL;
669 
670       if (ptr2) {
671          *ptr2++ = 0;
672          if (*ptr2 == 0x0d) *ptr2++ = 0;
673       }
674 
675       tptr = strchr(ptr1,0x0d);
676       if (tptr) *tptr = 0;
677 
678       if (!strlen(ptr1) || !strchr(ptr1,'@') || !strchr(ptr1,'.')) {
679          ptr1 = ptr2;
680          continue;
681       }
682 
683       LMAPI->buffer_printf(tempbuf, sizeof(tempbuf) - 1, "subscribe %s",
684         ptr1);
685       LMAPI->set_var("cur-parse-line", tempbuf, VAR_GLOBAL);
686       LMAPI->set_var("subscribe-me",ptr1,VAR_GLOBAL);
687 
688       if (LMAPI->do_hooks("PRESUB") == HOOK_RESULT_FAIL) {
689          ptr1 = ptr2;
690          continue;
691       }
692 
693       LMAPI->listdir_file(userfile,LMAPI->get_string("list"),"users");
694 
695       if (LMAPI->user_add(userfile,ptr1)) {
696           LMAPI->spit_status("Filesystem error while subscribing user.");
697           ptr1 = ptr2;
698           continue;
699       }
700 
701       LMAPI->log_printf(0, "%s subscribed to %s by %s\n",ptr1,
702          LMAPI->get_string("listname"),from);
703 
704       LMAPI->do_hooks("POSTSUB");
705 
706       ptr1 = ptr2;
707    }
708 
709    LMAPI->buffer_printf(tempbuf, sizeof(tempbuf) - 1, "%s.perr");
710    if (LMAPI->exists_file(tempbuf)) {
711       LMAPI->set_var("tlcgi-textfile",tempbuf,VAR_TEMP);
712       if (!LMAPI->cgi_unparse_template("textfile")) {
713           lsg2_internal_error("No 'textfile' template.");
714       }
715       LMAPI->unlink_file(tempbuf);
716       return;
717    }
718 
719    if (!LMAPI->cgi_unparse_template("adminmenu")) {
720       lsg2_internal_error("No 'adminmenu' template.");
721    }
722 
723    return;
724 }
725 
CGI_MODE(cgimode_admin_unsubscribe)726 CGI_MODE(cgimode_admin_unsubscribe)
727 {
728    char userfile[BIG_BUF];
729    const char *from, *userfor;
730    char tempbuf[BIG_BUF];
731 
732    if (!lsg2_admin_validate()) {
733       return;
734    }
735 
736    from = LMAPI->get_var("lcgi-user");
737    userfor = LMAPI->get_var("lcgi-userfor");
738 
739    LMAPI->set_var("adminmode","true",VAR_GLOBAL);
740 
741    if (!userfor) {
742       lsg2_internal_error("Mode initialized wrong.");
743       return;
744    }
745 
746    LMAPI->set_var("subscribe-me",userfor,VAR_GLOBAL);
747    LMAPI->set_var("fromaddress",from,VAR_GLOBAL);
748    LMAPI->set_var("realsender",from,VAR_GLOBAL);
749 
750    if (LMAPI->do_hooks("PREUNSUB") == HOOK_RESULT_FAIL) {
751       char tempbuf[BIG_BUF];
752 
753       LMAPI->buffer_printf(tempbuf, sizeof(tempbuf) - 1, "%s.perr",
754          LMAPI->get_string("queuefile"));
755       LMAPI->set_var("tlcgi-textfile",tempbuf,VAR_TEMP);
756       if (!LMAPI->cgi_unparse_template("textfile")) {
757          lsg2_internal_error("No textfile template.");
758       }
759       return;
760    }
761 
762    LMAPI->listdir_file(userfile,LMAPI->get_string("list"),"users");
763 
764    if (LMAPI->user_remove(userfile,userfor)) {
765        lsg2_internal_error("Filesystem error while unsubscribing user.");
766        LMAPI->filesys_error(userfile);
767        LMAPI->buffer_printf(tempbuf, sizeof(tempbuf) - 1, "%s.perr",
768           LMAPI->get_string("queuefile"));
769        LMAPI->unlink_file(tempbuf);
770        return;
771    }
772 
773    LMAPI->log_printf(0, "%s unsubscribed from %s by %s\n",userfor,
774       LMAPI->get_string("listname"),from);
775 
776    LMAPI->do_hooks("POSTUNSUB");
777 
778    if (!LMAPI->cgi_unparse_template("adminmenu")) {
779       lsg2_internal_error("No 'adminmenu' template.");
780       return;
781    }
782 
783    return;
784 }
785 
CGI_MODE(cgimode_admin_setflags)786 CGI_MODE(cgimode_admin_setflags)
787 {
788    struct list_user user;
789    const char *list, *fromaddy;
790    struct listserver_flag *tflag;
791    int isadmin;
792    char tbuf[BIG_BUF];
793 
794    if (!lsg2_admin_validate()) {
795       return;
796    }
797 
798    list = LMAPI->get_var("lcgi-list");
799    fromaddy = LMAPI->get_var("lcgi-userfor");
800 
801    LMAPI->set_var("realsender",LMAPI->get_var("lcgi-user"),VAR_GLOBAL);
802    LMAPI->set_var("fromaddress",LMAPI->get_var("lcgi-user"),VAR_GLOBAL);
803 
804    if (!list || !fromaddy) {
805       lsg2_internal_error("Invalid state for flag setting.");
806    }
807 
808    if (!LMAPI->user_find_list(list, fromaddy, &user)) {
809       char errbuf[BIG_BUF];
810 
811       LMAPI->buffer_printf(errbuf, sizeof(errbuf) - 1, "%s is not a member of %s",
812         fromaddy, list);
813 
814       lsg2_internal_error(errbuf);
815    }
816 
817    isadmin = LMAPI->user_hasflag(&user,"ADMIN");
818 
819    tflag = LMAPI->get_flags();
820    while (tflag) {
821       if (!strcasecmp(tflag->name,"superadmin") ||
822           (tflag->admin & ADMIN_UNSETTABLE)) {
823          tflag = tflag->next;
824          continue;
825       }
826 
827       if (LMAPI->find_cgi_tempvar(tflag->name)) {
828          LMAPI->log_printf(18,"CGI: %s is selected.\n", tflag->name);
829          if (!LMAPI->user_hasflag(&user,tflag->name)) {
830             LMAPI->set_var("setflag-user",user.address,VAR_TEMP);
831             LMAPI->set_var("setflag-flag",tflag->name,VAR_TEMP);
832             if (LMAPI->do_hooks("SETFLAG") != HOOK_RESULT_FAIL) {
833                /* Re-read the user in case they were modified by the
834                 * hooks. */
835                LMAPI->user_find_list(list,fromaddy,&user);
836                if (!LMAPI->user_hasflag(&user,tflag->name)) {
837                   char userlistfile[BIG_BUF];
838 
839                   LMAPI->listdir_file(userlistfile, list, "users");
840                   LMAPI->user_setflag(&user,tflag->name,1);
841                   LMAPI->user_write(userlistfile, &user);
842                }
843             }
844          }
845       } else {
846          LMAPI->log_printf(18,"CGI: %s is unselected.\n", tflag->name);
847          if (LMAPI->user_hasflag(&user,tflag->name)) {
848             LMAPI->set_var("setflag-user",user.address,VAR_TEMP);
849             LMAPI->set_var("setflag-flag",tflag->name,VAR_TEMP);
850             if (LMAPI->do_hooks("UNSETFLAG") != HOOK_RESULT_FAIL) {
851                /* Re-read the user in case they were modified by the
852                 * hooks. */
853                LMAPI->user_find_list(list,fromaddy,&user);
854                if (LMAPI->user_hasflag(&user,tflag->name)) {
855                   char userlistfile[BIG_BUF];
856 
857                   LMAPI->listdir_file(userlistfile, list, "users");
858                   LMAPI->user_unsetflag(&user,tflag->name,1);
859                   LMAPI->user_write(userlistfile, &user);
860                }
861             }
862          }
863       }
864       tflag = tflag->next;
865    }
866 
867    LMAPI->buffer_printf(tbuf, sizeof(tbuf) - 1, "%s.perr",
868      LMAPI->get_string("queuefile"));
869 
870    if (LMAPI->exists_file(tbuf)) {
871       LMAPI->set_var("tlcgi-textfile",tbuf,VAR_TEMP);
872       if (!LMAPI->cgi_unparse_template("textfile")) {
873          lsg2_internal_error("No 'textfile' template.");
874       }
875       LMAPI->unlink_file(tbuf);
876    } else {
877       if (!LMAPI->cgi_unparse_template("admin-userinfo")) {
878          lsg2_internal_error("No 'admin-userinfo' template.");
879       }
880    }
881 }
882 
CGI_MODE(cgimode_admin_setname)883 CGI_MODE(cgimode_admin_setname)
884 {
885    const char *list, *user, *name;
886 
887    if (!lsg2_admin_validate()) {
888       return;
889    }
890 
891    list = LMAPI->get_var("lcgi-list");
892    user = LMAPI->get_var("lcgi-userfor");
893    name = LMAPI->get_var("lcgi-fullname");
894 
895    if (!list || !user || !name) {
896       lsg2_internal_error("Mode not initialized properly.");
897       return;
898    }
899 
900    LMAPI->userstat_set_stat(list,user,"realname",name);
901 
902    if (!LMAPI->cgi_unparse_template("admin-userinfo")) {
903       lsg2_internal_error("No 'admin-userinfo' template.");
904    }
905 
906    return;
907 }
908 
CGI_MODE(cgimode_admin_userinfo)909 CGI_MODE(cgimode_admin_userinfo)
910 {
911    const char *list, *user;
912 
913    if (!lsg2_admin_validate()) {
914       return;
915    }
916 
917    list = LMAPI->get_var("lcgi-list");
918    user = LMAPI->get_var("lcgi-userfor");
919 
920    if (!list || !user) {
921       lsg2_internal_error("Mode not initialized properly.");
922       return;
923    }
924 
925    if (!LMAPI->cgi_unparse_template("admin-userinfo")) {
926       lsg2_internal_error("No 'admin-userinfo' template.");
927    }
928 
929    return;
930 }
931 
CGI_MODE(cgimode_admin_usersetinfo)932 CGI_MODE(cgimode_admin_usersetinfo)
933 {
934    const char *list, *user, *target;
935    struct list_user realuser, realtarget;
936 
937    if (!lsg2_admin_validate()) {
938       return;
939    }
940 
941    list = LMAPI->get_var("lcgi-list");
942    user = LMAPI->get_var("lcgi-user");
943    target = LMAPI->get_var("lcgi-userfor");
944 
945    if (!list || !user) {
946       lsg2_internal_error("Mode not initialized properly.");
947       return;
948    }
949 
950    if (LMAPI->user_find_list(list,target,&realtarget)) {
951       if (LMAPI->user_find_list(list,user,&realuser)) {
952 
953          if (LMAPI->user_hasflag(&realtarget,"ADMIN") &&
954              !LMAPI->user_hasflag(&realuser,"SUPERADMIN")) {
955                 lsg2_internal_error("You are not a SUPERADMIN and cannot alter options on other admins.");
956                 return;
957          }
958       }
959    }
960 
961    if (!LMAPI->cgi_unparse_template("admin-usersetinfo")) {
962       lsg2_internal_error("No 'admin-usersetinfo' template.");
963    }
964 
965    return;
966 }
967 
CGI_MODE(cgimode_admin_userfor_generic)968 CGI_MODE(cgimode_admin_userfor_generic)
969 {
970    if (!lsg2_admin_validate()) {
971       return;
972    }
973 
974    if (LMAPI->find_cgi_tempvar("unsubscribe")) {
975       cgimode_admin_unsubscribe();
976       return;
977    }
978 
979    if (LMAPI->find_cgi_tempvar("userinfo")) {
980       cgimode_admin_userinfo();
981       return;
982    }
983 
984    if (LMAPI->find_cgi_tempvar("usersetinfo")) {
985       cgimode_admin_usersetinfo();
986    }
987 }
988 
CGI_HANDLER(cgihook_admin_flaglist)989 CGI_HANDLER(cgihook_admin_flaglist)
990 {
991   int cols, curcol;
992   struct listserver_flag *tflag;
993   struct listserver_flag **flagarr;
994   struct list_user user;
995   int isadmin, counter, i;
996 
997   cols = 2;
998 
999   if (param && *param) {
1000     cols = atoi(param);
1001     if (!cols) cols = 2;
1002   }
1003 
1004   if (cols < 1) cols = 1;
1005 
1006   tflag = LMAPI->get_flags();
1007 
1008   curcol = 1;
1009 
1010   if (!LMAPI->user_find_list(LMAPI->get_string("lcgi-list"),
1011         LMAPI->get_string("lcgi-userfor"), &user)) {
1012      printf("<b>You are not subscribed to this list.</b>");
1013      return 0;
1014   }
1015 
1016   isadmin = LMAPI->user_hasflag(&user,"ADMIN");
1017 
1018   printf("<table border=0 width=100%%>\n");
1019   printf(" <tr>\n");
1020 
1021   counter = 0;
1022 
1023   while(tflag) {
1024      counter++;
1025      tflag = tflag->next;
1026   }
1027 
1028   flagarr = (struct listserver_flag **)malloc(sizeof(struct listserver_flag *) * counter);
1029 
1030   tflag = LMAPI->get_flags();
1031 
1032   for (i = 0; i < counter; i++) {
1033      flagarr[i] = tflag;
1034      tflag = tflag->next;
1035   }
1036 
1037   qsort(flagarr,counter,sizeof(struct listserver_flag *),flag_cmp);
1038 
1039   for (i = 0; i < counter; i++) {
1040      if (!curcol) curcol = 1;
1041 
1042      tflag = flagarr[i];
1043 
1044      if (strcasecmp(tflag->name,"superadmin") ||
1045         !(tflag->admin & ADMIN_UNSETTABLE)) {
1046 
1047         printf("  <td valign=top width=%d%%>\n", 100 / cols);
1048         printf("   <input type=\"checkbox\" name=\"lcgipl-%s\"",
1049           tflag->name);
1050         if (LMAPI->user_hasflag(&user,tflag->name)) {
1051           printf(" checked=\"true\"");
1052         }
1053         printf("> %s\n", tflag->name);
1054         printf("   <ul>%s</ul>\n", tflag->desc);
1055         printf("  </td>");
1056 
1057         curcol++;
1058 
1059         if (curcol > cols) {
1060            printf(" </tr>\n<tr>\n");
1061            curcol = 0;
1062         }
1063      }
1064   }
1065 
1066   if (curcol != 0) {
1067      while(curcol < cols) {
1068         printf("  <td>&nbsp;</td>\n");
1069         curcol++;
1070      }
1071      printf(" </tr>\n");
1072   }
1073 
1074   free(flagarr);
1075 
1076   printf("</table>");
1077   return 1;
1078 }
1079 
CGI_HANDLER(cgihook_admin_setname)1080 CGI_HANDLER(cgihook_admin_setname)
1081 {
1082   char fullname[256];
1083   const char *user, *list;
1084 
1085   user = LMAPI->get_var("lcgi-userfor");
1086   list = LMAPI->get_var("lcgi-list");
1087 
1088   if (!user || !list) return 0;
1089 
1090   if (LMAPI->userstat_get_stat(list,user,"realname",&fullname[0],255)) {
1091      printf("<input name=\"lcgi-fullname\" length=255 value=\"%s\">\n",
1092         fullname);
1093   } else {
1094      printf("<input name=\"lcgi-fullname\" length=255>\n");
1095   }
1096   printf("<input name=\"lcgi-userfor\" type=hidden value=\"%s\">\n",
1097         LMAPI->get_var("lcgi-userfor"));
1098 
1099   return 1;
1100 }
1101 
CGI_HANDLER(cgihook_admin_showflags)1102 CGI_HANDLER(cgihook_admin_showflags)
1103 {
1104   int cols, curcol, width;
1105   struct listserver_flag *tflag;
1106   struct listserver_flag **flagarr;
1107   struct list_user user;
1108   int counter, i;
1109 
1110   cols = 2;
1111   width = 100;
1112 
1113   if (param && *param) {
1114     char *parseme;
1115     char unparse[BIG_BUF];
1116 
1117     stringcpy(unparse,param);
1118 
1119     if ((parseme = strchr(unparse,','))) {
1120        *parseme++ = 0;
1121        width = atoi(parseme);
1122     }
1123     cols = atoi(unparse);
1124     if (!cols) cols = 2;
1125   }
1126 
1127   if (cols < 1) cols = 1;
1128   if (width > 100) width = 100;
1129   if (width < 0) width = 0;
1130 
1131   tflag = LMAPI->get_flags();
1132 
1133   curcol = 1;
1134 
1135   if (!LMAPI->user_find_list(LMAPI->get_string("lcgi-list"),
1136         LMAPI->get_string("lcgi-userfor"), &user)) {
1137      printf("<b>%s is not subscribed to this list.</b>",
1138         LMAPI->get_string("lcgi-userfor"));
1139      return 0;
1140   }
1141 
1142   counter = 0;
1143 
1144   while(tflag) {
1145      counter++;
1146      tflag = tflag->next;
1147   }
1148 
1149   flagarr = (struct listserver_flag **)malloc(sizeof(struct listserver_flag *) * counter);
1150 
1151   tflag = LMAPI->get_flags();
1152 
1153   for (i = 0; i < counter; i++) {
1154      flagarr[i] = tflag;
1155      tflag = tflag->next;
1156   }
1157 
1158   qsort(flagarr,counter,sizeof(struct listserver_flag *),flag_cmp);
1159 
1160   printf("<table border=0");
1161   if (width) {
1162      printf(" width=%d%%", width);
1163   }
1164   printf(">\n");
1165   printf(" <tr>\n");
1166 
1167   for(i = 0; i < counter; i++) {
1168      if (!curcol) curcol = 1;
1169      tflag = flagarr[i];
1170      if (!LMAPI->user_hasflag(&user,tflag->name)) {
1171         tflag = tflag->next;
1172         continue;
1173      }
1174 
1175      printf("  <td valign=top>\n");
1176      printf("<b>%s</b>\n", tflag->name);
1177      printf("  </td><td valign=top>\n");
1178      printf("   %s\n", tflag->desc);
1179      printf("  </td>");
1180 
1181      tflag = tflag->next;
1182      curcol++;
1183 
1184      if (curcol > cols) {
1185         printf(" </tr>\n<tr>\n");
1186         curcol = 0;
1187      }
1188   }
1189 
1190   if (curcol != 0) {
1191      while(curcol < cols) {
1192         printf("  <td>&nbsp;</td><td>&nbsp;</td>\n");
1193         curcol++;
1194      }
1195      printf(" </tr>\n");
1196   }
1197 
1198   free(flagarr);
1199 
1200   printf("</table>");
1201   return 1;
1202 }
1203 
1204 /*
1205  * kjh: qsort compare function for e-mail addresses
1206  */
user_compare(const void * p1,const void * p2)1207 static int user_compare(const void *p1, const void *p2)
1208 {
1209   /* convert params to their "real" type */
1210   const char *u1 = (const char *) *((const char **) p1);
1211   const char *u2 = (const char *) *((const char **) p2);
1212   /* parse out the domain */
1213   const char *domain1 = strchr(u1, '@');
1214   const char *domain2 = strchr(u2, '@');
1215   int   rv = 0;
1216 
1217   /* skip past the '@' sign, otherwise make sure that we have an ptr to a
1218    * deferenceable string (just in case there wasn't a domain)
1219    */
1220   if (domain1 != 0)
1221     domain1++;
1222   else
1223     domain1 = "";
1224 
1225   if (domain2 != 0)
1226     domain2++;
1227   else
1228     domain2 = "";
1229 
1230   rv = strcasecmp(domain1, domain2);  /* compare the domain */
1231 
1232 //  if (rv == 0)                        /* if same domain, compare user */
1233     rv = strcasecmp(u1, u2);
1234 
1235   return rv;
1236 }
1237 
1238 
1239 
CGI_HANDLER(cgihook_admin_userlistbox)1240 CGI_HANDLER(cgihook_admin_userlistbox)
1241 {
1242   FILE *infile;
1243   char filename[BIG_BUF];
1244   struct list_user user;
1245   int   n_users = 256;
1246   const char **users = 0;
1247   int   n = 0;
1248 
1249   LMAPI->listdir_file(filename,LMAPI->get_string("lcgi-list"),"users");
1250 
1251   if ((infile = LMAPI->open_file(filename,"r")) == NULL)
1252      return 0;
1253 
1254   printf("<select name=\"lcgi-userfor\"");
1255   if (param) {
1256     int size;
1257 
1258     size = atoi(param);
1259     if (size < 1) size = 1;
1260     printf(" size=%d", size);
1261   } else {
1262     printf(" size=20");
1263   }
1264   printf(">\n");
1265 
1266   if (LMAPI->get_bool("lsg2-sort-userlist")) {
1267      users = (const char **)malloc(n_users * sizeof(char *));
1268 
1269      while(LMAPI->user_read(infile,&user)) {
1270        if (n == n_users) {
1271          n_users *= 2;
1272          users = realloc((void*)users, n_users*sizeof(char *));
1273        }
1274        users[n++] = strdup(user.address);
1275      }
1276 
1277      /* kjh: sort users by e-mail address */
1278      qsort((void*)users, n, sizeof(const char *), user_compare);
1279 
1280      {
1281        const char **userp;
1282        for (userp = users; userp < users+n; userp++) {
1283          printf("<option value=\"%s\"> %s\n",
1284                 *userp, *userp);
1285          free((char *) *userp);
1286        }
1287      }
1288      free((void*)users);
1289   }
1290   else {
1291      while(LMAPI->user_read(infile,&user)) {
1292         printf("<option value=\"%s\"> %s\n",
1293           user.address, user.address);
1294      }
1295      printf("</select>\n");
1296   }
1297 
1298   printf("</select>\n");
1299 
1300 
1301   return 1;
1302 }
1303 
1304