/[pkg-mixmaster]/branches/mixmaster_2_9_STABLE/Mix/Src/pool.c
ViewVC logotype

Contents of /branches/mixmaster_2_9_STABLE/Mix/Src/pool.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 525 - (show annotations) (download)
Sun Jun 1 23:39:11 2003 UTC (9 years, 11 months ago) by rabbi
File MIME type: text/plain
File size: 21516 byte(s)
Windows buld support changes.
1 /* Mixmaster version 2.9 -- (C) 1999 - 2002 Anonymizer Inc. and others.
2
3 Mixmaster may be redistributed and modified under certain conditions.
4 This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
5 ANY KIND, either express or implied. See the file COPYRIGHT for
6 details.
7
8 Send messages from pool
9 $Id: pool.c,v 1.10.2.6 2003/06/01 23:39:10 rabbi Exp $ */
10
11 #include "mix3.h"
12 #include <stdlib.h>
13 #include <string.h>
14 #include <ctype.h>
15 #include <sys/types.h>
16 #include <time.h>
17 #ifdef POSIX
18 #include <unistd.h>
19 #else /* end of POSIX */
20 #include <io.h>
21 #endif /* else if not POSIX */
22 #ifndef _MSC_VER
23 #include <dirent.h>
24 #endif /* not _MSC_VER */
25 #include <assert.h>
26
27 #ifdef USE_PCRE
28 #include "pcre.h"
29 #endif /* USE_PCRE */
30
31 int msg_send(char *name);
32
33 int mix_send(void)
34 {
35 return (mix_regular(FORCE_POOL));
36 }
37
38 /* Message pool: Unix DOS
39 * latent messages: l* *.lat
40 * pooled messages: m* *.msg
41 * messages to be sent: s* *.snd
42 * temporary files: t* *.tmp
43 * files in user editor: x*
44 * incoming mail: i* *.inf
45 * partial messages: p* p*.*
46 * error messages: e* *.err
47 * outgoing messages: out *.txt (to be used by external program)
48 */
49
50 static int is(char *path, char *type)
51 {
52 #ifdef SHORTNAMES
53 int s;
54
55 s = strlen(path);
56 if (s <= 4)
57 return 0;
58 return (path[s - 4] == '.' && streq(path + s - 3, type));
59 #else /* end of SHORTNAMES */
60 return (path[0] == type[0]);
61 #endif /* else if not SHORTNAMES */
62 }
63
64 static void mv(char *name, char *newtype)
65 {
66 char old[PATHMAX], new[PATHMAX];
67
68 sprintf(old, "%s%c%s", POOLDIR, DIRSEP, name);
69 #ifdef SHORTNAMES
70 assert(strlen(name) > 4);
71 strcpy(name + strlen(name) - 3, newtype);
72 #else /* end of SHORTNAMES */
73 name[0] = newtype[0];
74 #endif /* else if not SHORTNAMES */
75 sprintf(new, "%s%c%s", POOLDIR, DIRSEP, name);
76 rename(old, new);
77 }
78
79 int latent_read(void)
80 {
81 char path[PATHMAX];
82 DIR *d;
83 FILE *f;
84 struct dirent *e;
85 int size = 0;
86 long now, then;
87
88 now = time(NULL);
89 d = opendir(POOLDIR);
90 if (d != NULL)
91 for (;;) {
92 e = readdir(d);
93 if (e == NULL)
94 break;
95 if (is(e->d_name, "lat")) {
96 sprintf(path, "%s%c%s", POOLDIR, DIRSEP, e->d_name);
97 f = fopen(path, "rb");
98 if (f != NULL) {
99 fscanf(f, "%*d %ld\n", &then);
100 fclose(f);
101 if (now > then)
102 mv(e->d_name, "msg");
103 }
104 }
105 }
106 closedir(d);
107 return (size);
108 }
109
110 int infile_read(void)
111 {
112 char path[PATHMAX];
113 BUFFER *msg;
114 DIR *d;
115 FILE *f;
116 struct dirent *e;
117 int size = 0;
118
119 msg = buf_new();
120 d = opendir(POOLDIR);
121 if (d != NULL)
122 for (;;) {
123 e = readdir(d);
124 if (e == NULL)
125 break;
126 if (is(e->d_name, "inf")) {
127 mv(e->d_name, "tmp");
128 sprintf(path, "%s%c%s", POOLDIR, DIRSEP, e->d_name);
129 f = fopen(path, "rb");
130 if (f != NULL) {
131 buf_clear(msg);
132 buf_read(msg, f);
133 fclose(f);
134 unlink(path);
135 mix_decrypt(msg);
136 }
137 }
138 }
139 closedir(d);
140 buf_free(msg);
141 return (size);
142 }
143
144 int mailin_maildir_one(char *dir)
145 /** Read mails from one directory
146 This function reads all files from the directory passed and passes
147 them on to mix_decrypt(). Each file is unlinked when its is read.
148
149 @param dir The directory in which files are to be read. No path finding
150 voodoo is done to the path; It's passed it opendir() as is.
151 @author PP
152 @return Number of files read
153 */
154 {
155 BUFFER *msg;
156 DIR *d;
157 FILE *f;
158 struct dirent *e;
159 int size = 0;
160 char path[PATHMAX];
161
162 msg = buf_new();
163 d = opendir(dir);
164 if (d != NULL)
165 for (;;) {
166 e = readdir(d);
167 if (e == NULL)
168 break;
169 if (e->d_name[0] != '.') {
170 sprintf(path, "%s%c%s", dir, DIRSEP, e->d_name);
171 path[PATHMAX-1]='\0';
172 f = fopen(path, "rb");
173 if (f != NULL) {
174 buf_clear(msg);
175 buf_read(msg, f);
176 fclose(f);
177 unlink(path);
178 mix_decrypt(msg);
179 size++;
180 }
181 }
182 }
183 closedir(d);
184 buf_free(msg);
185 return (size);
186 }
187
188 int mailin_maildir(char *maildir)
189 /** Read mails from a mail folder in Maildir format
190 Reads all files from the Maildir using mailin_maildir_one().
191 All mails are removed after this function returns.
192
193 @param maildir The Maildir to open. mixfile() is called to normalize the path.
194 @author PP
195 @return 0
196 */
197 {
198 char normalized[PATHMAX];
199 char path[PATHMAX];
200
201 mixfile(normalized, maildir);
202 sprintf(path, "%s%c%s", normalized, DIRSEP, "new");
203 path[PATHMAX-1]='\0';
204 mailin_maildir_one(path);
205 sprintf(path, "%s%c%s", normalized, DIRSEP, "cur");
206 path[PATHMAX-1]='\0';
207 mailin_maildir_one(path);
208 return (0);
209 }
210
211 int mailin_mbox(char *path)
212 /** Read mails from a mail folder in mbox format
213 Reads all messages from the mbox filder passes as an argument. Mails are
214 handed over to mix_decrypt. After all mails have been read the mailbox
215 is truncated to zero size i.e. all mails are deleted. The mbox is
216 locked using lock() and unlock() during this operation.
217
218 @param maildir Path to the mbox mail folder.
219 @author PP
220 @return 0 on sucess, other on error
221 */
222 {
223 char line[LINELEN];
224 FILE *f;
225 int state, eof;
226 BUFFER *msg;
227 int err=0;
228
229 msg = buf_new();
230
231 f = mix_openfile(path, "r+");
232 if (f != NULL) {
233 if (lock(f) != 0) {
234 /* Locking failed */
235 err = 1;
236 goto end;
237 }
238 /* State machine
239 * 1 - Look for the first ^From_ line
240 * 2 - add messages as they come
241 */
242 state = 1;
243 eof = 0;
244 for(;;) {
245 if (fgets(line, sizeof(line), f) == NULL)
246 eof = 1;
247
248 switch (state) {
249 case 1:
250 /* Initial state - Looking for first appearance of From_ */
251 if (eof)
252 goto end_state;
253 if (strleft(line, "From ")) {
254 #if 0
255 buf_appends(msg, line);
256 #endif /* 0 */
257 state = 2;
258 break;
259 };
260 break;
261 case 2:
262 /* Within one mail - Adding lines to mail until we encounter another From_ or eof */
263 if (eof || strleft(line, "From ")) {
264 mix_decrypt(msg);
265 buf_clear(msg);
266 }
267 if (eof)
268 goto end_state;
269 if (!strleft(line, "From "))
270 buf_appends(msg, line);
271 break;
272 default:
273 assert(0);
274 err=1;
275 goto end_state;
276 }
277 }
278 end_state:
279 #ifndef WIN32
280 rewind(f);
281 ftruncate(fileno(f), 0);
282 #else /* end of not WIN32 */
283 chsize(fileno(f), 0);
284 #endif /* else if WIN32 */
285 unlock(f);
286 fclose(f);
287 }
288 end:
289 buf_free(msg);
290 return (err);
291 }
292
293 /** Process MAILIN if applicable
294 If MAILIN is defined this function calls either mailin_maildir() or
295 mailin_mbox() depending on whether the last character of MAILIN
296 is DIRSEP.
297
298 @param mailbox Path to the mbox or Maildir mail folder.
299 @author PP
300 @return 0 on sucess, other on error
301 */
302 int mailin(char *mailbox)
303 {
304 if (mailbox != NULL && (strcmp(mailbox, "") != 0))
305 if (mailbox[strlen(mailbox)-1] == DIRSEP)
306 return mailin_maildir(mailbox);
307 else
308 return mailin_mbox(mailbox);
309 else
310 return 0;
311 };
312
313 int pool_add(BUFFER *msg, char *type)
314 {
315 char path[PATHMAX], pathtmp[PATHMAX];
316 FILE *f;
317 int err = -1;
318
319 f = pool_new(type, pathtmp, path);
320 if (f != NULL) {
321 err = buf_write(msg, f);
322 fclose(f);
323 }
324 if (err == 0) {
325 rename(pathtmp, path);
326 errlog(DEBUGINFO, "Added %s file to pool.\n", type);
327 }
328 return (err);
329
330 }
331
332 FILE *pool_new(char *type, char *tmpname, char *path)
333 {
334 FILE *f;
335
336 assert(strlen(type) == 3);
337 #ifdef SHORTNAMES
338 sprintf(tmpname, "%s%c%02x%02x%02x%02x.tmp", POOLDIR, DIRSEP, rnd_byte(), rnd_byte(),
339 rnd_byte(), rnd_byte());
340 strcpy(path, tmpname);
341 memcpy(path + strlen(path) - 3, type, 3);
342 #else /* end of SHORTNAMES */
343 sprintf(tmpname, "%s%ct%02x%02x%02x%02x%02x%02x%01x", POOLDIR, DIRSEP, rnd_byte(),
344 rnd_byte(), rnd_byte(), rnd_byte(), rnd_byte(),
345 rnd_byte(), rnd_byte() & 15);
346 strcpy(path, tmpname);
347 strrchr(path, DIRSEP)[1] = type[0];
348 #endif /* else if not SHORTNAMES */
349 f = fopen(tmpname, "wb");
350 if (f == NULL)
351 errlog(ERRORMSG, "Error creating temporary file %s\n", tmpname);
352 return (f);
353 }
354
355 int pool_read(BUFFER *pool)
356 {
357 DIR *d;
358 struct dirent *e;
359 int size = 0;
360
361 d = opendir(POOLDIR);
362 if (d != NULL)
363 for (;;) {
364 e = readdir(d);
365 if (e == NULL)
366 break;
367 if (is(e->d_name, "msg")) {
368 if (pool != NULL) {
369 buf_appends(pool, e->d_name);
370 buf_appendc(pool, 0);
371 }
372 size++;
373 }
374 }
375 closedir(d);
376 return (size);
377 }
378
379 void pool_dosend(void)
380 {
381 DIR *d;
382 struct dirent *e;
383 char path[PATHMAX];
384
385 d = opendir(POOLDIR);
386 if (d != NULL) {
387 for (;;) {
388 e = readdir(d);
389 if (e == NULL)
390 break;
391 if (is(e->d_name, "snd")) {
392 sendmail_begin();
393 mv(e->d_name, "tmp");
394 sprintf(path, "%s%c%s", POOLDIR, DIRSEP, e->d_name);
395 if (msg_send(path) == 1)
396 mv(e->d_name, "err");
397 }
398 }
399 closedir(d);
400 }
401 sendmail_end();
402 }
403
404 int process_mailin()
405 {
406 mailin(MAILIN);
407 infile_read();
408 return(0);
409 }
410
411 int pool_send(void)
412 {
413 int size, max, i, r;
414 BUFFER *pool;
415 long int *ptr;
416
417 latent_read();
418 pool = buf_new();
419 size = pool_read(pool);
420 if (size <= POOLSIZE)
421 goto end;
422
423 ptr = malloc(size * sizeof(long int));
424
425 if (ptr == NULL)
426 goto end;
427 for (i = 0; i < size; i++) {
428 ptr[i] = pool->ptr;
429 buf_getline(pool, NULL);
430 }
431
432 max = size * RATE / 100; /* send no more than RATE % of the messages */
433 if (max < 0)
434 max = 1;
435
436 for (i = 0; i < size - POOLSIZE && i < max; i++) {
437 do
438 r = rnd_number(size); /* chose a new random message */
439 while (is(pool->data + ptr[r], "snd"));
440 mv(pool->data + ptr[r], "snd");
441 }
442 stats_out(size - --i);
443 pool_dosend();
444 free(ptr);
445
446 end:
447 buf_free(pool);
448 return (size);
449 }
450
451 int msg_send(char *name)
452 {
453 FILE *f;
454 int type = -1;
455 BUFFER *m, *addr;
456 int err = 0;
457 char line[LINELEN];
458 int userfrom = 0;
459
460 m = buf_new();
461 addr = buf_new();
462 if ((f = fopen(name, "rb")) == NULL) {
463 err = -1;
464 goto end;
465 }
466 fscanf(f, "%d %*d\n", &type);
467 if (type == INTERMEDIATE) {
468 fgets(line, sizeof(line), f);
469 buf_sets(addr, line);
470 buf_chop(addr);
471 err = buf_read(m, f);
472 if (err == -1)
473 goto end;
474 err = mix_armor(m);
475 if (err == -1)
476 goto end;
477 err = sendmail(m, REMAILERADDR, addr);
478 } else if (type == MSG_MAIL || type == MSG_POST) {
479 err = buf_read(m, f);
480 if (err == -1)
481 goto end;
482 if (MIDDLEMAN && ! allowmessage(m))
483 mix2_encrypt(type, m, FORWARDTO, 1, NULL);
484 else {
485 err = filtermsg(m);
486 if (err == 1)
487 userfrom = 1, err = 0;
488 if (err != -1) {
489 /* message has recipients */
490 errlog(DEBUGINFO, "Sending message (%ld bytes)\n", m->length);
491
492 if (type == MSG_MAIL)
493 err = sendmail(m, userfrom ? NULL : ANONNAME, NULL);
494 else if (type == MSG_POST) {
495 if (strchr(NEWS, '@') && !strchr(NEWS, ' ')) {
496 errlog(LOG, "Mailing article to %s.\n", NEWS);
497 buf_sets(addr, NEWS);
498 err = sendmail(m, userfrom ? NULL : ANONNAME, addr);
499 } else if (NEWS[0] != '\0') {
500 FILE *f;
501
502 f = openpipe(NEWS);
503 if (f == NULL)
504 goto end;
505 errlog(LOG, "Posting article.\n");
506 if (!userfrom)
507 fprintf(f, "From: %s\n", ANONNAME);
508 if (ORGANIZATION[0] != '\0')
509 fprintf(f, "Organization: %s\n", ORGANIZATION);
510 buf_write(m, f);
511 closepipe(f);
512 } else
513 errlog(NOTICE, "Rejecting news article.\n");
514 }
515 } else
516 errlog(ERRORMSG, "Bad message file.\n");
517 }
518 }
519 end:
520 if (f != NULL)
521 fclose(f);
522 if (err != 1) /* problem sending mail */
523 unlink(name);
524 buf_free(m);
525 buf_free(addr);
526 return (err);
527 }
528
529 int allowmessage(BUFFER *in)
530 /* Only called if remailer is middleman. Checks whether all Recipient
531 * addresses are in dest.allow. If yes return 1; 0 otherwhise
532 */
533 {
534 BUFFER *out, *allow, *line, *line2;
535 int err=1;
536 FILE *f;
537
538 allow = buf_new();
539 out = buf_new();
540 line = buf_new();
541 line2 = buf_new();
542
543 f = mix_openfile(DESTALLOW, "r");
544 if (f != NULL) {
545 buf_read(allow, f);
546 fclose(f);
547 }
548
549 /* Do header lines */
550 while (buf_getline(in, line) == 0) {
551 for (;;) {
552 buf_lookahead(in, line2);
553 if (!bufleft(line2, " ") && !bufleft(line2, "\t"))
554 break;
555 buf_getline(in, line2);
556 buf_cat(line, line2);
557 }
558
559 if (bufileft(line, "to:") || bufileft(line, "cc:") ||
560 bufileft(line, "bcc:") || bufileft(line, "newsgroups:"))
561 if (! doallow(line, allow))
562 err = 0;
563
564 if (line->length > 0) {
565 if (!buffind(line, ":"))
566 buf_appends(out, "X-Invalid: ");
567 buf_cat(out, line);
568 buf_nl(out);
569 }
570 }
571 buf_nl(out);
572
573 /* Rest of the message */
574 buf_append(out, in->data + in->ptr, in->length - in->ptr);
575
576 buf_move(in, out);
577 buf_free(out);
578 buf_free(allow);
579 buf_free(line);
580 buf_free(line2);
581 return (err);
582 }
583
584 int doallow(BUFFER *line, BUFFER *filter)
585 /* line is a To, CC or BCC line.
586 * problem is: there may be multiple addresses in one header
587 * line but we only want to allow if _all_ are allowed
588 *
589 * So to not send direct if we do not want, we _never_ send
590 * direct if there is more than one address: This is
591 * assumed to be the case when there is a
592 * comma in the header line.
593 *
594 * this should probably be rewritten somehwhen. therefore: FIXME
595 *
596 * returns: 1 if allowed
597 * 0 if message should be send indirectly
598 */
599 {
600 if (strchr( line->data, ',')) return 0;
601 return doblock(line, filter, 0);
602 }
603
604 int filtermsg(BUFFER *in)
605 {
606 BUFFER *out, *line, *line2, *mboundary, *block, *filter, *mid;
607 FILE *f;
608 int from = 0, dest = 0;
609 int inbinary = 0, inpgp = 0, l = 80;
610 int err = -1;
611
612 line = buf_new();
613 line2 = buf_new();
614 filter = buf_new();
615 mid = buf_new();
616 mboundary = buf_new();
617 out = buf_new();
618 block = NULL;
619
620 if (SIZELIMIT > 0 && in->length > SIZELIMIT * 1024) {
621 errlog(NOTICE, "Message rejected: %ld bytes\n", in->length);
622 goto end;
623 }
624
625 block = readdestblk( );
626 if ( !block ) block = buf_new( );
627
628 f = mix_openfile(HDRFILTER, "r");
629 if (f != NULL) {
630 buf_read(filter, f);
631 fclose(f);
632 }
633
634 f = mix_openfile(DISCLAIMFILE, "r");
635 if (f != NULL) {
636 buf_read(out, f);
637 fclose(f);
638 } else {
639 if (strfind(DISCLAIMER, "%s"))
640 buf_appendf(out, DISCLAIMER, COMPLAINTS);
641 else
642 buf_appends(out, DISCLAIMER);
643 }
644
645 while (buf_getline(in, line) == 0) {
646 for (;;) {
647 buf_lookahead(in, line2);
648 if (!bufleft(line2, " ") && !bufleft(line2, "\t"))
649 break;
650 buf_getline(in, line2);
651 buf_cat(line, line2);
652 }
653
654 if (bufileft(line, "to:") || bufileft(line, "cc:") ||
655 bufileft(line, "bcc:") || bufileft(line, "newsgroups:"))
656 if (doblock(line, block, 1) == 0)
657 dest++;
658 if (doblock(line, filter, 1) == -1)
659 goto end;
660 if (bufileft(line, "from:"))
661 from = 1;
662
663 if (bufileft(line, "content-type:") && bufileft(line, "multipart"))
664 get_parameter(line, "boundary", mboundary);
665
666 if (line->length > 0) {
667 if (!buffind(line, ":"))
668 buf_appends(out, "X-Invalid: ");
669 buf_cat(out, line);
670 buf_nl(out);
671 }
672 }
673
674 if (MID[0] != '\0' && tolower(MID[0]) != 'n') {
675 char txt[LINELEN];
676
677 digestmem_md5(in->data + in->ptr, in->length - in->ptr, mid);
678 id_encode(mid->data, txt);
679
680 if (MID[0] == '@')
681 strcatn(txt, MID, sizeof(txt));
682 else {
683 if (strchr(REMAILERADDR, '@'))
684 strcatn(txt, strchr(REMAILERADDR, '@'), sizeof(txt));
685 else if (strchr(COMPLAINTS, '@'))
686 strcatn(txt, strchr(COMPLAINTS, '@'), sizeof(txt));
687 }
688 buf_appendf(out, "Message-ID: <%s>\n", txt);
689 }
690 buf_nl(out);
691
692 if (from) {
693 /* prepend Sender line to message header */
694 buf_setf(line, "Sender: %s\n", ANONNAME);
695 buf_cat(line, out);
696 buf_move(out, line);
697
698 f = mix_openfile(FROMDSCLFILE, "r");
699 if (f != NULL) {
700 buf_read(out, f);
701 fclose(f);
702 } else
703 buf_appends(out, FROMDISCLAIMER);
704 }
705
706 #if 0
707 buf_append(out, in->data + in->ptr, in->length - in->ptr);
708 #endif /* 0 */
709 while (buf_getline(in, line) != -1) {
710 if (boundary(line, mboundary)) {
711 buf_cat(out, line);
712 buf_nl(out);
713 while (buf_getline(in, line) == 0) { /* MIME body part header */
714 err = doblock(line, filter, 1);
715 if (err == -1)
716 goto end;
717 buf_cat(out, line);
718 buf_nl(out);
719 }
720 }
721 if (BINFILTER && l > 20 && line->length == l &&
722 (bufleft(line, "M") || !buffind(line, " ")))
723 inbinary++;
724 else
725 inbinary = 0, l = line->length;
726 if (bufileft(line, begin_pgp) || bufileft(line, begin_key))
727 inpgp = 1;
728 if (bufileft(line, end_pgp) || bufileft(line, end_key))
729 inpgp = 0;
730 if (inbinary < 10 || inpgp) {
731 buf_cat(out, line);
732 buf_nl(out);
733 } else if (inbinary == 10) {
734 errlog(NOTICE, "Binary message detected.\n");
735 if (BINFILTER > 1) {
736 err = -1;
737 goto end;
738 }
739 buf_appends(out, BINDISCLAIMER);
740 buf_nl(out);
741 }
742 }
743
744 f = mix_openfile(MSGFOOTERFILE, "r");
745 if (f != NULL) {
746 buf_read(out, f);
747 fclose(f);
748 } else
749 buf_appends(out, MSGFOOTER);
750
751 /* return 1 for user supplied From line */
752 err = from;
753 if (dest == 0)
754 err = -1;
755
756 end:
757 buf_move(in, out);
758 buf_free(out);
759 buf_free(line);
760 buf_free(line2);
761 if (block) buf_free(block);
762 buf_free(filter);
763 buf_free(mid);
764 buf_free(mboundary);
765 return (err);
766 }
767
768 BUFFER *readdestblk( )
769 {
770 char *destblklst = (char *)malloc( strlen( DESTBLOCK )+1 );
771 char *destblk = NULL;
772 FILE *f;
773 BUFFER *addresses;
774 BUFFER *temp;
775 int err = 1;
776
777 addresses = buf_new( );
778 temp = buf_new( );
779
780 strcpy( destblklst, DESTBLOCK );
781
782 while ( (destblk = strtok( destblk ? NULL : destblklst, " " )) )
783 {
784 if ( (f = mix_openfile( destblk, "r" )) )
785 {
786 if ( !buf_read( temp, f ) )
787 {
788 buf_cat( addresses, temp );
789 err = 0;
790 }
791 fclose( f );
792 }
793 }
794
795 free( destblklst );
796 buf_free( temp );
797
798 if ( err ) { buf_free( addresses ); return NULL; }
799 else return addresses;
800 }
801
802 int doblock(BUFFER *line, BUFFER *filter, int logandreset)
803 /* logandreset is usually 0
804 * it is only set to 1 when called from doallow
805 * which only checks whether messages are allowed to
806 * be sent directly
807 */
808 {
809 int block = 0;
810 BUFFER *pattern, *result;
811 char *t;
812 #ifdef USE_PCRE
813 int errptr, match;
814 const char *error;
815 pcre *compiled;
816 int ovector[21];
817 char *newstr;
818 #endif /* USE_PCRE */
819
820 pattern = buf_new();
821 result = buf_new();
822 assert(filter != NULL);
823
824 buf_rewind(filter);
825 while (buf_getline(filter, pattern) != -1)
826 if (pattern->length > 0 && !bufleft(pattern, "#")) {
827 if (bufleft(pattern, "/") && (t = strchr(pattern->data + 1, '/'))
828 != NULL) {
829 #ifdef USE_PCRE
830 *t = '\0';
831 compiled = pcre_compile(pattern->data + 1, PCRE_CASELESS,
832 &error, &errptr
833 #ifndef USE_PCRE_OLD
834 ,NULL
835 #endif /* not USE_PCRE_OLD */
836 );
837 if (compiled) {
838 match = pcre_exec(compiled, NULL, line->data,
839 line->length,
840 #if (PCRE_MAJOR == 2 && PCRE_MINOR >= 06)
841 0,
842 #endif /* (PCRE_MAJOR == 2 && PCRE_MINOR >= 06) */
843 #if (PCRE_MAJOR >= 3)
844 0,
845 #endif /* (PCRE_MAJOR >= 3) */
846 0, ovector, sizeof(ovector) / sizeof(int));
847 free(compiled);
848
849 if (match < -1) {
850 *t = '/';
851 errlog(ERRORMSG, "Bad regexp %b\n", pattern);
852 }
853 else if (match >= 0) {
854 /* "/pattern/q" kills the entire message */
855 if (logandreset
856 && strlen(pattern->data + 1) + 1 < pattern->length
857 && pattern->data[pattern->length - 1] == 'q') {
858 *t = '/';
859 errlog(NOTICE,
860 "Message rejected: %b matches %b.\n", line, pattern);
861 block = -1;
862 break;
863 }
864 if (strlen(pattern->data + 1) + 1 < pattern->length
865 && pattern->data[pattern->length - 1] == '/') {
866 pattern->data[pattern->length - 1] = '\0';
867 newstr = pattern->data + strlen(pattern->data) + 1;
868 buf_reset(result);
869 buf_append(result, line->data, ovector[0]);
870 while (strchr(newstr, '$')) {
871 strchr(newstr, '$')[0] = '\0';
872 buf_appends(result, newstr);
873 newstr += strlen(newstr) + 1;
874 if (*newstr >= '1' && *newstr <= '9')
875 buf_append(result, line->data +
876 ovector[2 * (*newstr - '0')],
877 ovector[2 * (*newstr - '0') + 1] -
878 ovector[2 * (*newstr - '0')]);
879 newstr++;
880 }
881 buf_appends(result, newstr);
882 buf_appends(result, line->data + ovector[1]);
883 buf_clear(line);
884 buf_appends(line, result->data);
885 } else {
886 block = 1;
887 *t = '/';
888 if (logandreset)
889 errlog(NOTICE, "Blocked header line: %b matches %b.\n",
890 line, pattern);
891 }
892 }
893 } else {
894 *t = '/';
895 errlog(ERRORMSG, "Bad regexp %b\n", pattern);
896 }
897 #else /* end of USE_PCRE */
898 errlog(ERRORMSG, "No regexp support! Ignoring %b\n", pattern);
899 #endif /* else if not USE_PCRE */
900 } else if (bufifind(line, pattern->data)) {
901 if (logandreset )
902 errlog(NOTICE, "Blocked header line: %b matches %b.\n",
903 line, pattern);
904 block = 1;
905 }
906 }
907
908 if (logandreset && (block == 1))
909 buf_reset(line);
910
911 buf_free(pattern);
912 buf_free(result);
913 return (block);
914 }
915
916 int mix_armor(BUFFER *in)
917 {
918 BUFFER *out, *md;
919
920 md = buf_new();
921 out = buf_new();
922
923 if (in->length != 20480)
924 return (-1);
925
926 buf_sets(out, "\n::\n");
927 buf_appends(out, remailer_type);
928 buf_appends(out, VERSION);
929 buf_nl(out);
930 buf_nl(out);
931 buf_appends(out, begin_remailer);
932 buf_nl(out);
933 buf_appends(out, "20480\n");
934 digest_md5(in, md);
935 encode(md, 0);
936 buf_cat(out, md);
937 buf_nl(out);
938 encode(in, 40);
939 buf_cat(out, in);
940 buf_appends(out, end_remailer);
941 buf_nl(out);
942
943 buf_move(in, out);
944 buf_free(out);
945 buf_free(md);
946 return (0);
947 }

  ViewVC Help
Powered by ViewVC 1.1.5