ezmlmx 0.68
ezmlmx
Loading...
Searching...
No Matches
ezmlm-send.c
Go to the documentation of this file.
1#include <sys/types.h>
2#include <sys/stat.h>
3#include <stdio.h>
4#include <unistd.h>
5#include "stralloc.h"
6#include "logmsg.h"
7#include "error.h"
8#include "qmail.h"
9#include "env.h"
10#include "lock.h"
11#include "sig.h"
12#include "open.h"
13#include "getln.h"
14#include "case.h"
15#include "scan.h"
16#include "str.h"
17#include "fmt.h"
18#include "readwrite.h"
19#include "exit.h"
20#include "buffer.h"
21#include "getconf.h"
22#include "constmap.h"
23#include "byte.h"
24#include "getoptb.h"
25#include "quote.h"
26#include "subscribe.h"
27#include "mime.h"
28#include "errtxt.h"
29#include "makehash.h"
30#include "cookie.h"
31#include "hdr.h"
32#include "idx.h"
33#include "ezcopy.h"
34#include "auto_version.h"
35#include "lockfile.h"
36
37#define WHO "ezmlm-send"
38
44
45int flagnoreceived = 1; /* suppress received headers by default. */
46 /* They are still archived. =0 => archived and copied. */
47int flaglog = 1; /* for lists with mysql support, use tags */
48 /* and log traffic to the database */
49
50static void die_usage() { logmsg(WHO,100,USAGE,"ezmlm-send [-cClLqQrR] [-h header] dir"); }
51static void die_nomem() { logmsg(WHO,111,FATAL,ERR_NOMEM); }
52
53/* for writing new index file indexn later moved to index. */
54
55buffer bxn;
56char indexnbuf[1024];
57
58static char strnum[FMT_ULONG];
59char szmsgnum[FMT_ULONG];
60char hash[HASHLEN];
62
63stralloc fnadir = {0};
64stralloc fnaf = {0};
65stralloc fnif = {0};
66stralloc fnifn = {0};
67stralloc fnsub = {0};
68stralloc line = {0};
69stralloc qline = {0};
70stralloc lines = {0};
71stralloc subject = {0};
72stralloc from = {0};
73stralloc received = {0};
74stralloc prefix = {0};
75stralloc content = {0};
76stralloc charset = {0};
77stralloc dcprefix = {0};
78stralloc dummy = {0};
79stralloc qmqpservers = {0};
80stralloc boundary = {0};
81
82void die_indexn() { logmsg(WHO,111,FATAL,B(ERR_WRITE,fnifn.s)); }
83
84unsigned long innum;
85unsigned long outnum;
86unsigned long msgnum;
87unsigned long hash_lo = 0L;
88unsigned long hash_hi = 52L;
89unsigned long msgsize = 0L;
90unsigned long cumsize = 0L; /* cumulative archive size bytes / 256 */
91char flagcd = '\0'; /* no transfer-encoding for trailer */
92char encin = '\0';
94int flagfoundokpart; /* Found something to pass on. If multipart */
95 /* we set to 0 and then set to 1 for any */
96 /* acceptable mime part. If 0 -> reject */
99unsigned int serial = 0;
105
106buffer bar;
107char archivebuf[1024];
108
109stralloc outhost = {0};
110stralloc outlocal = {0};
111
113stralloc sublist = {0};
114stralloc mailinglist = {0};
115stralloc headerremove = {0};
116struct constmap headerremovemap;
117stralloc mimeremove = {0};
118struct constmap mimeremovemap;
119char *dir;
120
121struct qmail qq;
122buffer bi;
123char inbuf[1024];
124buffer bo;
125char outbuf[1];
126
127char textbuf[512];
128buffer bt;
129
130ssize_t mywrite(int fd,char *buf,unsigned int len)
131{
133 return len;
134}
135
136int subto(char *s,unsigned int l)
137{
138 qmail_put(&qq,"T",1);
139 qmail_put(&qq,s,l);
140 qmail_put(&qq,"",1);
141 return (int) l;
142}
143
144void die_archive() { logmsg(WHO,111,FATAL,B(ERR_WRITE,fnaf.s)); }
145void die_numnew() { logmsg(WHO,111,FATAL,B(ERR_CREATE,"numnew")); }
146
147void qa_put(char *buf,unsigned int len)
148{
150 if (flagarchived)
151 if (buffer_put(&bar,buf,len) == -1) die_archive();
152}
153
154void qa_puts(char *buf)
155{
156 qmail_puts(&qq,buf);
157 if (flagarchived)
158 if (buffer_puts(&bar,buf) == -1) die_archive();
159}
160
161int sublistmatch(char *sender)
162{
163 unsigned int i;
164 unsigned int j;
165
166 j = str_len(sender);
167 if (j < sublist.len) return 0;
168
169 i = byte_rchr(sublist.s,sublist.len,'@');
170 if (i == sublist.len) return 1;
171
172 if (byte_diff(sublist.s,i,sender)) return 0;
173 if (case_diffb(sublist.s + i,sublist.len - i,sender + j - (sublist.len - i)))
174 return 0;
175
176 return 1;
177}
178
179buffer bn;
180char numnewbuf[16];
181
182/* this one deals with msgnum, not outnum! */
183
185{
186 int fd;
187
188 fd = open_trunc("numnew");
189 if (fd == -1) die_numnew();
190 buffer_init(&bn,buffer_unixwrite,fd,numnewbuf,sizeof(numnewbuf));
191 if (buffer_put(&bn,strnum,fmt_ulong(strnum,msgnum)) == -1)
192 die_numnew();
193 if (buffer_puts(&bn,":") == -1) die_numnew();
194 if (buffer_put(&bn,strnum,fmt_ulong(strnum,cumsize)) == -1)
195 die_numnew();
196
197 if (buffer_puts(&bn,"\n") == -1) die_numnew();
198 if (buffer_flush(&bn) == -1) die_numnew();
199 if (fsync(fd) == -1) die_numnew();
200 if (close(fd) == -1) die_numnew(); /* NFS stupidity */
201 if (rename("numnew","num") == -1)
202 logmsg(WHO,111,FATAL,B(ERR_MOVE,"numnew"));
203}
204
205stralloc mydtline = {0};
206
218
220{
221 char *cp;
222 unsigned long idx;
223 int match;
224 int r;
225 unsigned int pos;
226 int k;
227
228 if (!stralloc_copys(&fnadir,"archive/")) die_nomem();
229 if (!stralloc_catb(&fnadir,strnum,fmt_ulong(strnum,outnum / 100))) die_nomem();
230 if (!stralloc_copy(&fnif,&fnadir)) die_nomem();
231 if (!stralloc_copy(&fnifn,&fnif)) die_nomem();
232 if (!stralloc_cats(&fnif,"/index")) die_nomem();
233 if (!stralloc_cats(&fnifn,"/indexn")) die_nomem();
234 if (!stralloc_0(&fnif)) die_nomem();
235 if (!stralloc_0(&fnifn)) die_nomem();
236 if (!stralloc_0(&fnadir)) die_nomem();
237
238 /* may not exists since we run before ezmlm-send */
239
240 if (mkdir(fnadir.s,0755) == -1)
241 if (errno != EEXIST)
242 logmsg(WHO,111,FATAL,B(ERR_CREATE,fnadir.s));
243
244 fdindexn = open_trunc(fnifn.s); /* Open indexn */
245 if (fdindexn == -1)
246 logmsg(WHO,111,FATAL,B(ERR_WRITE,fnifn.s));
247
248 /* set up buffers for indexn */
249
250 buffer_init(&bxn,buffer_unixwrite,fdindexn,indexnbuf,sizeof(indexnbuf));
251
252 concat_hdr(subject.s,subject.len,&lines); /* make 1 line */
253 decode_hdr(lines.s,lines.len,&qline); /* decode mime */
254 r = unfold_hdr(qline.s,qline.len,&lines,charset.s,&dcprefix,1); /* trim mime */
255
256 fdindex = open_read(fnif.s);
257 if (fdindex == -1) {
258 if (errno != ENOENT)
259 logmsg(WHO,111,FATAL,B(ERR_OPEN,fnif.s));
260 } else {
261 buffer_init(&bi,buffer_unixread,fdindex,inbuf,sizeof(inbuf));
262 for(;;) {
263 if (getln(&bi,&qline,&match,'\n') == -1)
264 logmsg(WHO,111,FATAL,B(ERR_READ,fnif.s));
265 if (!match)
266 break;
267 pos = scan_ulong(qline.s,&idx);
268 if (!idx) /* "impossible!" */
269 logmsg(WHO,111,FATAL,ERR_BAD_INDEX);
270 if (idx >= outnum)
271 break; /* messages always come in order */
272 if (buffer_put(&bxn,qline.s,qline.len) == -1)
273 die_indexn();
274 if (qline.s[pos] == ':') { /* has author line */
275 if (getln(&bi,&qline,&match,'\n') == -1)
276 logmsg(WHO,111,FATAL,B(ERR_READ,fnif.s));
277 if (!match && qline.s[0] != '\t') /* "impossible! */
278 logmsg(WHO,111,FATAL,ERR_BAD_INDEX);
279 if (buffer_put(&bxn,qline.s,qline.len) == -1)
280 die_indexn();
281 }
282 }
283 close(fdindex);
284 }
285 if (!stralloc_copyb(&qline,strnum,fmt_ulong(strnum,outnum))) die_nomem();
286 if (!stralloc_cats(&qline,": ")) die_nomem(); /* ':' for new ver */
287 makehash(lines.s,lines.len,hash);
288 if (!stralloc_catb(&qline,hash,HASHLEN)) die_nomem();
289 if (!stralloc_cats(&qline," ")) die_nomem();
290 if (r & 1) /* reply */
291 if (!stralloc_cats(&qline,"Re: ")) die_nomem();
292 if (!stralloc_cat(&qline,&lines)) die_nomem();
293 if (!stralloc_cats(&qline,"\n\t")) die_nomem();
294 if (!stralloc_cat(&qline,&received)) die_nomem();
295 if (!stralloc_cats(&qline,";")) die_nomem();
296
297 concat_hdr(from.s,from.len,&lines);
298 mkauthhash(lines.s,lines.len,hash);
299
300 if (!stralloc_catb(&qline,hash,HASHLEN)) die_nomem();
301 if (!stralloc_cats(&qline," ")) die_nomem();
302
303 k = author_name(&cp,lines.s,lines.len);
304 decode_hdr(cp,k,&from);
305
307 if (!stralloc_cat(&qline,&lines)) die_nomem();
308
309 if (!stralloc_cats(&qline,"\n")) die_nomem();
310 if (buffer_put(&bxn,qline.s,qline.len) == -1) die_indexn();
311 if (buffer_flush(&bxn) == -1) die_indexn();
312 if (fsync(fdindexn) == -1) die_indexn();
313 if (fchmod(fdindexn,MODE_ARCHIVE | 0700) == -1) die_indexn();
314 if (close(fdindexn) == -1) die_indexn(); /* NFS stupidity */
315 if (rename(fnifn.s,fnif.s) == -1)
316 logmsg(WHO,111,FATAL,B(ERR_MOVE,fnifn.s));
317 return r;
318}
319
321{
322 if (getconf_line(&charset,"charset",0,dir)) {
323 if (charset.len >= 2 && charset.s[charset.len - 2] == ':') {
324 if (charset.s[charset.len - 1] == 'B' ||
325 charset.s[charset.len - 1] == 'Q') {
326 flagcd = charset.s[charset.len - 1];
327 charset.s[charset.len - 2] = '\0';
328 }
329 }
330 } else
331 if (!stralloc_copys(&charset,TXT_DEF_CHARSET)) die_nomem();
332
333 if (!stralloc_0(&charset)) die_nomem();
334}
335
336int main(int argc,char **argv)
337{
338 unsigned long subs;
339 int fdlock;
340 char *sender;
341 char *mlheader = (char *) 0;
342 const char *ret;
343 const char *err;
344 int flagmlwasthere;
345 int flaglistid = 0; /* no listid header added */
346 int match;
347 unsigned int i;
348 int r,fd;
349 int flaginheader;
350 int flagbadfield;
351 int flagbadpart;
352 int flagseenext;
353 int flagsubline;
354 int flagfromline;
355 int flagcontline;
356 int flagarchiveonly;
357 int flagtrailer;
358 unsigned int pos;
359 int opt;
360 char *cp, *cpstart, *cpafter;
361
362 umask(022);
363 sig_pipeignore();
364
365 while ((opt = getoptb(argc,argv,"cCh:H:lLrRqQs:S:vV")) != opteof)
366 switch(opt) {
367 case 'c': case 'C': break; /* ignore for backwards compat */
368 case 'h':
369 case 'H': mlheader = (char*)optarg; /* Alternative sublist check header */
370 mlheader[str_chr(mlheader,':')] = '\0';
371 break;
372 case 'l': flaglog = 1; break;
373 case 'L': flaglog = 0; break;
374 case 'r': flagnoreceived = 0; break;
375 case 'R': flagnoreceived = 1; break;
376 case 's':
377 case 'S': pos = scan_ulong(optarg,&hash_lo);
378 if (!optarg[pos++]) break;
379 scan_ulong(optarg+pos,&hash_hi);
380 if (hash_hi > 52L) hash_hi = 52L;
382 break;
383 case 'q': break;
384 case 'Q': break;
385 case 'v':
386 case 'V': logmsg(WHO,0,VERSION,auto_version);
387 default: die_usage();
388 }
389
390
391 dir = argv[optind++];
392 if (!dir) die_usage();
393
394 sender = env_get("SENDER");
395
396 if (chdir(dir) == -1)
397 logmsg(WHO,111,FATAL,B(ERR_SWITCH,dir));
398
399 fdlock = lockfile("lock");
400
401 flagarchived = getconf_line(&line,"archived",0,dir);
402 flagindexed = getconf_line(&line,"indexed",0,dir);
403 getcharset();
404 flagprefixed = getconf_line(&prefix,"prefix",0,dir);
405 if (prefix.len) { /* encoding and serial # support */
406 /* no sanity checks - you put '\n' or '\0' */
407 /* into the coded string, you pay */
408
409 decode_hdr(prefix.s,prefix.len,&line);
410 unfold_hdr(line.s,line.len,&dcprefix,charset.s,&dummy,0);
411 if (!stralloc_copy(&dcprefix,&line)) die_nomem();
412 serial = byte_rchr(prefix.s,prefix.len,'#');
413 }
414 if ((fd = open_read("text/trailer")) == -1) { /* see if there is a trailer */
415 if (errno == ENOENT) flagtrailer = 0;
416 else logmsg(WHO,111,FATAL,B(ERR_OPEN,"text/trailer"));
417 } else {
418 close(fd);
419 flagtrailer = 1;
420 }
421
422 getconf(&mimeremove,"mimeremove",0,dir);
423
424 if (getconf_line(&line,"num",0,dir)) { /* Now non-FATAL, def=0 */
425 if (!stralloc_0(&line)) die_nomem();
426 cp = line.s + scan_ulong(line.s,&msgnum);
427 ++msgnum;
428 if (*cp++ == ':')
429 scan_ulong(cp,&cumsize);
430 } else
431 msgnum = 1L; /* if num not there */
432
433 getconf_line(&outhost,"outhost",1,dir);
434 getconf_line(&outlocal,"outlocal",1,dir);
435 set_cpoutlocal(&outlocal);
436 set_cpouthost(&outhost);
437 flagsublist = getconf_line(&sublist,"sublist",0,dir);
438
439 if (!stralloc_copys(&line,QMQPSERVERS)) die_nomem();
440 if (!stralloc_cats(&line,"/0")) die_nomem();
441 if (!stralloc_0(&line)) die_nomem();
442 getconf(&qmqpservers,line.s,0,dir);
443
444 getconf(&headerremove,"headerremove",1,dir);
445 if (!constmap_init(&headerremovemap,headerremove.s,headerremove.len,0))
446 die_nomem();
447
448 if (!stralloc_copys(&mydtline,"Delivered-To: mailing list ")) die_nomem();
449 if (!stralloc_catb(&mydtline,outlocal.s,outlocal.len)) die_nomem();
450 if (!stralloc_cats(&mydtline,"@")) die_nomem();
451 if (!stralloc_catb(&mydtline,outhost.s,outhost.len)) die_nomem();
452 if (!stralloc_cats(&mydtline,"\n")) die_nomem();
453
454 if (sender) {
455 if (!*sender)
456 logmsg(WHO,100,FATAL,ERR_BOUNCE);
457 if (str_equal(sender,"#@[]"))
458 logmsg(WHO,100,FATAL,ERR_BOUNCE);
459 if (flagsublist)
460 if (!sublistmatch(sender))
461 logmsg(WHO,100,FATAL,ERR_NOT_PARENT);
462 }
463
464 innum = msgnum; /* innum = incoming */
465 outnum = msgnum; /* outnum = outgoing */
466 if (flagsublist && !flagarchived) { /* msgnum = archive */
467 pos = byte_rchr(sublist.s,sublist.len,'@'); /* checked in sublistmatch */
468 if (str_start(sender+pos,"-return-"))
469 pos += 8;
470 pos += scan_ulong(sender+pos,&innum);
471 if (!flagarchived && innum && sender[pos] == '-')
472 outnum = innum;
473 }
474 szmsgnum[fmt_ulong(szmsgnum,outnum)] = '\0';
475 set_cpnum(szmsgnum); /* for copy */
476
477 if (flagarchived) {
478 if (!stralloc_copys(&fnadir,"archive/")) die_nomem();
479 if (!stralloc_catb(&fnadir,strnum,
480 fmt_ulong(strnum,outnum / 100))) die_nomem();
481 if (!stralloc_copy(&fnaf,&fnadir)) die_nomem();
482 if (!stralloc_cats(&fnaf,"/")) die_nomem();
483 if (!stralloc_catb(&fnaf,strnum,fmt_uint0(strnum,
484 (unsigned int) (outnum % 100),2))) die_nomem();
485 if (!stralloc_0(&fnadir)) die_nomem();
486 if (!stralloc_0(&fnaf)) die_nomem();
487
488 if (mkdir(fnadir.s,0755) == -1)
489 if (errno != EEXIST)
490 logmsg(WHO,111,FATAL,B(ERR_CREATE,fnadir.s));
491 fdarchive = open_trunc(fnaf.s);
492 if (fdarchive == -1)
493 logmsg(WHO,111,FATAL,B(ERR_WRITE,fnaf.s));
494
495 buffer_init(&bar,write,fdarchive,archivebuf,sizeof(archivebuf));
496
497 /* return-path to archive */
498
499 if (!stralloc_copys(&line,"Return-Path: <")) die_nomem();
500 if (sender) { /* same as qmail-local */
501 if (!quote2(&qline,sender)) die_nomem();
502 for (i = 0; i < qline.len; ++i)
503 if (qline.s[i] == '\n') qline.s[i] = '_';
504 if (!stralloc_cat(&line,&qline)) die_nomem();
505 }
506 if (!stralloc_cats(&line,">\n")) die_nomem();
507 if (buffer_put(&bar,line.s,line.len) == -1) die_archive();
508 }
509
510 if (qmail_open(&qq,&qmqpservers) == -1) /* open qmqp */
511 logmsg(WHO,111,FATAL,ERR_QMAIL_QUEUE);
512
513 if (!flagsublist) {
514 getconf_line(&mailinglist,"mailinglist",1,dir);
515 qa_puts("Mailing-List: ");
517 if (getconf_line(&line,"listid",0,dir)) {
518 flaglistid = 1;
519 qmail_puts(&qq,"\nList-ID: ");
520 qmail_put(&qq,line.s,line.len);
521 }
522 qa_puts("\n");
523 }
524
525 ezcopy(&qq,"headeradd",'H');
526 qa_put(mydtline.s,mydtline.len);
527
528 flagmlwasthere = 0;
529 flaginheader = 1;
530 flagfoundokpart = 1;
531 flagbadfield = 0;
532 flagbadpart = 0;
533 flagseenext = 0;
534 flagsubline = 0;
535 flagfromline = 0;
536 flagreceived = 0;
537
538 for (;;) {
539 if (getln(buffer_0,&line,&match,'\n') == -1)
540 logmsg(WHO,111,FATAL,ERR_READ_INPUT);
541 if (flaginheader && match) {
542 if (line.len == 1) { /* end of header */
543 flaginheader = 0;
544 if (flagindexed) /* std entry */
545 r = idx_copy_insertsubject(); /* all indexed lists */
546 if (flagprefixed && !flagsublist) {
547 qa_puts("Subject:");
548 if (!flagindexed) { /* non-indexed prefixed lists */
550 decode_hdr(lines.s,lines.len,&qline);
551 r = unfold_hdr(qline.s,qline.len,&lines,
552 charset.s,&dcprefix,1);
553 }
554 if (!(r & 2)) {
555 qmail_puts(&qq," ");
556 if (serial == prefix.len)
557 qmail_put(&qq,prefix.s,prefix.len);
558 else {
560 qmail_puts(&qq,szmsgnum);
562 }
563 }
564 qa_put(subject.s,subject.len);
565 }
566
567 /* do other stuff to do with post header procebig here */
568
569 if (content.len) { /* get MIME sboundary, if exists */
570 concat_hdr(content.s,content.len,&qline);
571 if (!stralloc_copy(&content,&qline)) die_nomem();
572
573 if (flagtrailer &&
574 case_startb(content.s,content.len,"multipart/")) /* trailer only for some multipart */
575 if (!case_startb(content.s+10,content.len-10,"mixed") &&
576 !case_startb(content.s+10,content.len-10,"digest") &&
577 !case_startb(content.s+10,content.len-10,"parallel"))
578 flagtrailer = 0;
579
580 cp = content.s;
581 cpafter = cp + content.len; /* check after each ';' */
582 while ((cp += byte_chr(cp,cpafter-cp,';')) != cpafter) {
583 ++cp;
584 while (cp < cpafter && (*cp == ' ' || *cp == '\t' || *cp == '\n'))
585 ++cp;
586 if (case_startb(cp,cpafter-cp,"boundary=")) {
587 cp += 9; /* after boundary= */
588 if (*cp == '"') { /* quoted boundary */
589 ++cp;
590 cpstart = cp;
591 while (cp < cpafter && *cp != '"')
592 ++cp;
593 if (cp == cpafter)
594 logmsg(WHO,100,FATAL,ERR_MIME_QUOTE);
595 } else { /* non-quoted boundary */
596 cpstart = cp; /* find terminator of boundary */
597 while (cp < cpafter && *cp != ';' &&
598 *cp != ' ' && *cp != '\t' && *cp != '\n')
599 ++cp;
600 }
601 if (!stralloc_copys(&boundary,"--")) die_nomem();
602 if (!stralloc_catb(&boundary,cpstart,cp-cpstart))
603 die_nomem();
604 flagfoundokpart = 0;
605 if (!constmap_init(&mimeremovemap,mimeremove.s,mimeremove.len,0))
606 die_nomem();
607 flagbadpart = 1; /* skip before first boundary */
608 qa_puts("\n"); /* to make up for the lost '\n' */
609 }
610 }
611 } // content.len finshed
612 } else if ((*line.s != ' ') && (*line.s != '\t')) {
613 flagsubline = 0;
614 flagfromline = 0;
615 flagbadfield = 0;
616 flagarchiveonly = 0;
617 flagcontline = 0;
618
619 if (constmap(&headerremovemap,line.s,byte_chr(line.s,line.len,':')))
620 flagbadfield = 1;
621 if ((flagnoreceived || !flagreceived) &&
622 case_startb(line.s,line.len,"Received:")) {
623 if (!flagreceived) { /* get date from first rec'd */
624 flagreceived = 1; /* line (done by qmail) */
625 pos = byte_chr(line.s,line.len,';');
626 if (pos != line.len) /* has '\n' */
627 if (!stralloc_copyb(&received,line.s+pos+2,line.len - pos - 3)) die_nomem();
628 } else { /* suppress, but archive */
629 flagarchiveonly = 1; /* but do not suppress the */
630 flagbadfield = 1; /* top one added by qmail */
631 }
632 } else if (case_startb(line.s,line.len,"Mailing-List:")) {
633 flagmlwasthere = 1; /* sublists always ok ezmlm masters */
634 } else if (mlheader && case_startb(line.s,line.len,mlheader)) {
635 flagmlwasthere = 1; /* mlheader treated as ML */
636 } else if ((mimeremove.len || flagtrailer) && /* else no MIME need*/
637 case_startb(line.s,line.len,"Content-Type:")) {
638 if (!stralloc_copyb(&content,line.s+13,line.len-13)) die_nomem();
639 flagcontline = 1;
640 } else if (case_startb(line.s,line.len,"Subject:")) {
641 if (!stralloc_copyb(&subject,line.s+8,line.len-8)) die_nomem();
642 flagsubline = 1;
643 if (flagprefixed && !flagsublist) /* don't prefix for sublists */
644 flagbadfield = 1; /* we'll print our own */
645 } else if (flagtrailer && case_startb(line.s,line.len,"Content-Transfer-Encoding:")) {
646 cp = line.s + 26;
647 cpafter = cp + line.len;
648 while (cp < cpafter && (*cp == ' ' || *cp == '\t'))
649 ++cp;
650 if (case_startb(cp,cpafter-cp,"base64")) encin = 'B';
651 else if (case_startb(cp,cpafter-cp,"Quoted-Printable")) encin = 'Q';
652 } else if (flaglistid && case_startb(line.s,line.len,"list-id:")) {
653 flagbadfield = 1; /* suppress if we added our own */
654 } else if (flagindexed) {
655 if (case_startb(line.s,line.len,"From:")) {
656 flagfromline = 1;
657 if (!stralloc_copyb(&from,line.s+5,line.len-5)) die_nomem();
658 }
659 } else if (line.len == mydtline.len)
660 if (!byte_diff(line.s,line.len,mydtline.s))
661 logmsg(WHO,100,FATAL,ERR_LOOPING);
662 } else { /* continuation lines */
663 if (flagsubline) {
664 if (!stralloc_cat(&subject,&line)) die_nomem();
665 } else if (flagfromline) {
666 if (!stralloc_cat(&from,&line)) die_nomem();
667 } else if (flagcontline) {
668 if (!stralloc_cat(&content,&line)) die_nomem();
669 }
670 }
671 } else /* body */
672 msgsize += line.len; /* always for tstdig support */
673
674 if (!(flaginheader && flagbadfield)) {
675 if (boundary.len && line.len > boundary.len &&
676 !str_diffn(line.s,boundary.s,boundary.len)) {
677 if (line.s[boundary.len] == '-' && line.s[boundary.len+1] == '-') {
678 flagbadpart = 0; /* end boundary should be output */
679 if (flagtrailer) {
680 qmail_puts(&qq,"\n");
683 hdr_transferenc(); /* trailer for multipart message */
684 ezcopy(&qq,"text/trailer",flagcd);
685 if (flagcd == 'B') { /* need to do our own flushing */
686 encode_b64("",0,&qline,2);
687 qmail_put(&qq,qline.s,qline.len);
688 }
689 }
690 } else { /* new part */
691 flagbadpart = 1; /* skip lines */
692 if (!stralloc_copy(&lines,&line)) die_nomem(); /* but save */
693 flagseenext = 1; /* need to check Cont-type */
694 }
695 } else if (flagseenext) { /* last was boundary, now stored */
696 if (case_startb(line.s,line.len,"content-type:")) {
697 flagseenext = 0; /* done thinking about it */
698 cp = line.s + 13; /* start of type */
699 while (*cp == ' ' || *cp == '\t')
700 ++cp;
701 cpstart = cp; /* end of type */
702 while (*cp != '\n' && *cp != '\t' && *cp != ' ' && *cp != ';')
703 ++cp;
704 if (constmap(&mimeremovemap,cpstart,cp-cpstart)) {
705 flagbadpart = 1;
706 } else {
707 flagfoundokpart = 1;
708 qa_put(lines.s,lines.len); /* saved lines */
709 flagbadpart = 0; /* do this part */
710 }
711 } else if (line.len == 1) { /* end of content desc */
712 flagbadpart = 0; /* default type, so ok */
713 flagfoundokpart = 1; /* this is part of a multipart msg */
714 flagseenext = 0; /* done thinking about it */
715 qa_put(lines.s,lines.len); /* saved lines */
716 } else /* save line in cont desc */
717 if (!stralloc_cat(&lines,&line)) die_nomem();
718 }
719 if (!flagbadpart)
720 qa_put(line.s,line.len);
721
722 } else if (flagarchiveonly && flagarchived) /* received headers */
723 if (buffer_put(&bar,line.s,line.len) == -1) die_archive();
724 if (!match)
725 break;
726 }
727 if (!boundary.len && flagtrailer) {
728 qmail_puts(&qq,"\n"); /* trailer for non-multipart message */
729 if (!encin || encin == 'Q') { /* can add for QP, but not for base64 */
730 ezcopy(&qq,"text/trailer",encin);
731 qmail_puts(&qq,"\n"); /* no need to flush for plain/QP */
732 }
733 }
734
735 cumsize += (msgsize + 128L) >> 8; /* round to 256 byte 'records' */
736 /* check message tag */
737 if (flagsublist) { /* sublists need tag if selected/suppt*/
738 if (flaglog)
739 if ((ret = checktag(dir,innum,hash_lo+1L,"m",(char *) 0,hashout))) {
740 if (*ret) logmsg(WHO,111,FATAL,ret);
741 else logmsg(WHO,100,FATAL,ERR_NOT_PARENT);
742 }
743 if (!flagmlwasthere) /* sublists need ML header */
744 logmsg(WHO,100,FATAL,ERR_SUBLIST);
745 } else /* others are not allowed to have one */
746 if (flagmlwasthere)
747 logmsg(WHO,100,FATAL,ERR_MAILING_LIST);
748
749 if (!flagfoundokpart) /* all parts were on the strip list */
750 logmsg(WHO,100,FATAL,ERR_BAD_ALL);
751
752 if (flagarchived) {
753 if (buffer_flush(&bar) == -1) die_archive();
754 if (fsync(fdarchive) == -1) die_archive();
755 if (fchmod(fdarchive,MODE_ARCHIVE | 0700) == -1) die_archive();
756 if (close(fdarchive) == -1) die_archive(); /* NFS stupidity */
757 }
758
759 if (flaglog) {
760 tagmsg(dir,innum,sender,"m",hashout,qq.msgsize,53L);
761 hashout[COOKIE] = '\0';
762 }
763
764 numwrite();
765 if (!stralloc_copy(&line,&outlocal)) die_nomem();
766 if (!stralloc_cats(&line,"-return-")) die_nomem();
767 if (!stralloc_cats(&line,szmsgnum)) die_nomem();
768 if (!stralloc_cats(&line,"-@")) die_nomem();
769 if (!stralloc_cat(&line,&outhost)) die_nomem();
770 if (!stralloc_cats(&line,"-@[]")) die_nomem();
771 if (!stralloc_0(&line)) die_nomem();
772 qmail_from(&qq,line.s); /* envelope sender */
773
774 subs = putsubs(dir,hash_lo,hash_hi,subto,1); /* subscribers */
775 if (flagsublist) hash_lo++;
776
777 if (*(err = qmail_close(&qq)) == '\0') {
778 if (flaglog) /* mysql logging */
779 loginfo(dir,outnum,hash_lo,subs,flagsublist ? 3 : 4); // FIXME
780 closesql();
781 strnum[fmt_ulong(strnum,qmail_qp(&qq))] = 0;
782 logmsg(WHO,0,DONEIT,B("qp ",strnum));
783 } else {
784 --msgnum;
785 cumsize -= (msgsize + 128L) >> 8;
786 numwrite();
787 logmsg(WHO,111,FATAL,B(ERR_TMP_QMAIL_QUEUE,err + 1));
788 }
789
790 return 0;
791}
#define COOKIE
Definition cookie.h:4
#define TXT_DEF_CHARSET
Definition idx.h:93
#define QMQPSERVERS
Definition idx.h:306
#define MODE_ARCHIVE
Definition idx.h:183
void mkauthhash(const char *s, unsigned int len, char *h)
Definition makehash.c:133
void makehash(const char *indata, unsigned int inlen, char *hash)
Definition makehash.c:104
int quote2(stralloc *sa, const char *s)
Definition quote.c:65
const char auto_version[]
@ CTYPE_TEXT
Definition hdr.h:13
int unfold_hdr(char *, unsigned long, stralloc *, const char *, stralloc *, int)
Definition unfold_hdr.c:160
Error messages. If you translate these, I would urge you to keep the English version as well....
#define ERR_BAD_INDEX
Definition errtxt.h:64
#define ERR_NOMEM
Definition errtxt.h:14
#define ERR_OPEN
Definition errtxt.h:30
#define ERR_MOVE
Definition errtxt.h:29
#define ERR_READ_INPUT
Definition errtxt.h:26
#define ERR_MAILING_LIST
Definition errtxt.h:57
#define ERR_READ
Definition errtxt.h:18
#define ERR_LOOPING
Definition errtxt.h:58
#define ERR_CREATE
Definition errtxt.h:28
#define ERR_QMAIL_QUEUE
Definition errtxt.h:53
#define ERR_NOT_PARENT
Definition errtxt.h:55
#define ERR_SWITCH
Definition errtxt.h:42
#define ERR_WRITE
Definition errtxt.h:17
#define ERR_MIME_QUOTE
Definition errtxt.h:68
#define ERR_TMP_QMAIL_QUEUE
Definition errtxt.h:54
#define ERR_BOUNCE
Definition errtxt.h:38
#define ERR_SUBLIST
Definition errtxt.h:56
#define ERR_BAD_ALL
Definition errtxt.h:67
int lockfile(const char *)
Definition lockfile.c:15
const char * qmail_close(struct qmail *)
Definition qmail.c:120
void qmail_puts(struct qmail *, const char *)
Definition qmail.c:94
void qmail_put(struct qmail *, const char *, int)
Definition qmail.c:87
void qmail_from(struct qmail *, const char *)
Definition qmail.c:103
unsigned long qmail_qp(struct qmail *)
Definition qmail.c:77
int qmail_open(struct qmail *, const stralloc *)
Definition qmail.c:25
const char * loginfo(const char *dir, unsigned long msgnum, unsigned long, unsigned long subs, int done)
Definition loginfo.c:12
void tagmsg(const char *dir, unsigned long msgnum, const char *seed, const char *action, char *hashout, unsigned long bodysize, unsigned long chunk)
Definition tagmsg.c:45
void closesql(void)
close connection to SQL server, if open
Definition opensql.c:21
unsigned long putsubs(const char *dir, unsigned long hash_lo, unsigned long hash_hi, int subwrite(), int flagsql)
Definition putsubs.c:49
void die_nomem()
Definition getconf.c:17
int getconf(stralloc *sa, const char *fn, int flagrequired, const char *dir)
Definition getconf.c:21
int getconf_line(stralloc *sa, const char *fn, int flagrequired, const char *dir)
Definition getconf.c:53
void ezcopy(struct qmail *qqp, const char *fn, char q)
Definition ezcopy.c:128
void set_cpoutlocal(const stralloc *ln)
Definition ezcopy.c:67
void set_cpnum(const char *cf)
Definition ezcopy.c:95
void set_cpouthost(const stralloc *ln)
Definition ezcopy.c:73
unsigned int author_name(char **sout, char *s, unsigned int l)
Definition author.c:19
#define WHO
Definition author.c:1
char boundary[COOKIE]
Definition ezmlm-get.c:89
int flagindexed
Definition ezmlm-get.c:125
stralloc mydtline
Definition ezmlm-get.c:72
unsigned long cumsize
Definition ezmlm-get.c:81
int subto(char *s, unsigned int l)
Definition ezmlm-get.c:141
int flagarchived
Definition ezmlm-get.c:124
unsigned long msgsize
Definition ezmlm-get.c:84
char hashout[COOKIE]
Definition ezmlm-get.c:90
stralloc qmqpservers
Definition ezmlm-get.c:69
stralloc mimeremove
struct constmap mimeremovemap
char inbuf[1024]
buffer bn
char outbuf[1024]
char * dir
buffer bi
buffer bo
char encin
stralloc from
int main()
Definition ezmlm-weed.c:69
stralloc headerremove
struct constmap headerremovemap
const char * checktag(const char *dir, unsigned long num, unsigned long listno, const char *action, const char *seed, const char *hash)
Definition checktag.c:27
void concat_hdr(char *indata, unsigned int n, stralloc *outdata)
Definition concat_hdr.c:25
int opt
Definition ezmlm-cron.c:53
const char * cp
Definition ezmlm-cron.c:76
unsigned int len
Definition ezmlm-cron.c:68
int fdlock
Definition ezmlm-cron.c:71
char buf[256]
Definition install.c:113
int flagsublist
Definition ezmlm-send.c:112
int fdindex
Definition ezmlm-send.c:102
int idx_copy_insertsubject()
copies old index file up to but not including msg, then adds a line with 'sub' trimmed of reply indic...
Definition ezmlm-send.c:219
unsigned long outnum
Definition ezmlm-send.c:85
char archivebuf[1024]
Definition ezmlm-send.c:107
void qa_puts(char *buf)
Definition ezmlm-send.c:154
void getcharset()
Definition ezmlm-send.c:320
void die_archive()
Definition ezmlm-send.c:144
int fdarchive
Definition ezmlm-send.c:101
unsigned long hash_lo
Definition ezmlm-send.c:87
void numwrite()
Definition ezmlm-send.c:184
int subto(char *s, unsigned int l)
Definition ezmlm-send.c:136
stralloc sublist
Definition ezmlm-send.c:113
buffer bxn
Definition ezmlm-send.c:55
void die_indexn()
Definition ezmlm-send.c:82
void die_numnew()
Definition ezmlm-send.c:145
int flagprefixed
Definition ezmlm-send.c:98
unsigned long innum
Definition ezmlm-send.c:84
int flaglog
Definition ezmlm-send.c:47
int flagfoundokpart
Definition ezmlm-send.c:94
char numnewbuf[16]
Definition ezmlm-send.c:180
ssize_t mywrite(int fd, char *buf, unsigned int len)
Definition ezmlm-send.c:130
stralloc dcprefix
Definition ezmlm-send.c:77
int flagreceived
Definition ezmlm-send.c:97
int flagnoreceived
Definition ezmlm-send.c:45
unsigned long hash_hi
Definition ezmlm-send.c:88
char indexnbuf[1024]
Definition ezmlm-send.c:56
unsigned int serial
Definition ezmlm-send.c:99
void qa_put(char *buf, unsigned int len)
Definition ezmlm-send.c:147
int sublistmatch(char *sender)
Definition ezmlm-send.c:161
buffer bar
Definition ezmlm-send.c:106
int fd
Definition ezmlm-cgi.c:141
stralloc content
Definition ezmlm-cgi.c:128
const char * charset
Definition ezmlm-cgi.c:110
int match
Definition ezmlm-cgi.c:140
stralloc subject
Definition ezmlm-cgi.c:119
void decode_hdr(const char *indata, unsigned int n, stralloc *outdata)
Definition decode_hdr.c:24
#define HASHLEN
Definition idxthread.c:25
stralloc fnaf
Definition ezmlm-idx.c:44
stralloc prefix
Definition ezmlm-idx.c:69
int fdindexn
Definition ezmlm-idx.c:50
stralloc fnif
Definition ezmlm-idx.c:42
stralloc lines
Definition ezmlm-idx.c:47
stralloc fnadir
Definition ezmlm-idx.c:41
stralloc dummy
Definition ezmlm-idx.c:48
stralloc fnifn
Definition ezmlm-idx.c:43
stralloc received
Definition ezmlm-idx.c:68
unsigned long msgnum
stralloc mailinglist
Definition ezmlm-clean.c:93
char hboundary[HASHLEN]
Definition ezmlm-clean.c:86
char flagcd
Definition ezmlm-clean.c:59
struct qmail qq
Definition ezmlm-clean.c:73
void hdr_transferenc(void)
stralloc fnsub
void hdr_add(const char *line, unsigned int len)
Definition hdr_add.c:13
void encode_b64(const unsigned char *indata, unsigned int n, stralloc *outdata, int control)
Definition encode_b64.c:75
void hdr_ctype(enum ctype ctype)
Definition hdr_mime.c:24
Definition qmail.h:10
const char * logmsg(const char *dir, unsigned long num, unsigned long listno, unsigned long subs, int done)
Definition loginfo.c:32