]>
diplodocus.org Git - nmh/blob - sbr/mf.c
3 * mf.c -- mail filter subroutines
5 * This code is Copyright (c) 2002, by the authors of nmh. See the
6 * COPYRIGHT file in the root directory of the nmh distribution for
7 * complete copyright information.
18 static char *getcpy (char *);
19 static int isat (char *);
20 static int parse_address (void);
21 static int phrase (char *);
22 static int route_addr (char *);
23 static int local_part (char *);
24 static int domain (char *);
25 static int route (char *);
26 static int my_lex (char *);
35 /* causes compiles to blow up because the symbol _cleanup is undefined
36 where did this ever come from? */
42 p
= mh_xmalloc ((size_t) (strlen (s
) + 2));
51 return (strncmp (string
, "From ", 5) == 0
52 || strncmp (string
, ">From ", 6) == 0);
57 lequal (char *a
, char *b
)
63 char c1
= islower ((unsigned char) *a
) ?
64 toupper ((unsigned char) *a
) : *a
;
65 char c2
= islower ((unsigned char) *b
) ?
66 toupper ((unsigned char) *b
) : *b
;
78 return (strncmp (p
, " AT ", 4)
79 && strncmp (p
, " At ", 4)
80 && strncmp (p
, " aT ", 4)
81 && strncmp (p
, " at ", 4) ? FALSE
: TRUE
);
87 * getadrx() implements a partial 822-style address parser. The parser
88 * is neither complete nor correct. It does however recognize nearly all
89 * of the 822 address syntax. In addition it handles the majority of the
90 * 733 syntax as well. Most problems arise from trying to accomodate both.
92 * In terms of 822, the route-specification in
94 * "<" [route] local-part "@" domain ">"
96 * is parsed and returned unchanged. Multiple at-signs are compressed
97 * via source-routing. Recursive groups are not allowed as per the
100 * In terms of 733, " at " is recognized as equivalent to "@".
102 * In terms of both the parser will not complain about missing hosts.
106 * We should not allow addresses like
108 * Marshall T. Rose <MRose@UCI>
110 * but should insist on
112 * "Marshall T. Rose" <MRose@UCI>
114 * Unfortunately, a lot of mailers stupidly let people get away with this.
118 * We should not allow addresses like
122 * but should insist on
126 * Unfortunately, a lot of mailers stupidly let people's UAs get away with
131 * We should not allow addresses like
133 * @UCI:MRose@UCI-750a
135 * but should insist on
137 * Marshall Rose <@UCI:MRose@UCI-750a>
139 * Unfortunately, a lot of mailers stupidly do this.
163 static struct specials special
[] = {
180 static int glevel
= 0;
181 static int ingrp
= 0;
182 static int last_lex
= LX_END
;
184 static char *dp
= NULL
;
185 static char *cp
= NULL
;
186 static char *ap
= NULL
;
187 static char *pers
= NULL
;
188 static char *mbox
= NULL
;
189 static char *host
= NULL
;
190 static char *path
= NULL
;
191 static char *grp
= NULL
;
192 static char *note
= NULL
;
193 static char err
[BUFSIZ
];
194 static char adr
[BUFSIZ
];
196 static struct adrx adrxs2
;
200 getadrx (char *addrs
)
203 register struct adrx
*adrxp
= &adrxs2
;
217 pers
= mbox
= host
= path
= grp
= note
= NULL
;
221 dp
= cp
= getcpy (addrs
? addrs
: "");
231 switch (parse_address ()) {
243 default: /* catch trailing comments */
268 while (isspace ((unsigned char) *ap
))
271 sprintf (adr
, "%.*s", (int)(cp
- ap
), ap
);
274 bp
= adr
+ strlen (adr
) - 1;
275 if (*bp
== ',' || *bp
== ';' || *bp
== '\n')
284 adrxp
->ingrp
= ingrp
;
286 adrxp
->err
= err
[0] ? err
: NULL
;
299 switch (my_lex (buffer
)) {
302 pers
= getcpy (buffer
);
307 strcpy (err
, "extraneous semi-colon");
320 case LX_LBRK
: /* sigh (2) */
323 case LX_AT
: /* sigh (3) */
325 if (route_addr (buffer
) == NOTOK
)
327 return OK
; /* why be choosy? */
330 sprintf (err
, "illegal address construct (%s)", buffer
);
334 switch (my_lex (buffer
)) {
337 pers
= add (buffer
, add (" ", pers
));
338 more_phrase
: ; /* sigh (1) */
339 if (phrase (buffer
) == NOTOK
)
345 if (route_addr (buffer
) == NOTOK
)
347 if (last_lex
== LX_RBRK
)
349 sprintf (err
, "missing right-bracket (%s)", buffer
);
355 sprintf (err
, "nested groups not allowed (%s)", pers
);
358 grp
= add (": ", pers
);
364 switch (my_lex (buffer
)) {
366 case LX_END
: /* tsk, tsk */
375 return parse_address ();
379 case LX_DOT
: /* sigh (1) */
380 pers
= add (".", pers
);
384 sprintf (err
, "no mailbox in address, only a phrase (%s%s)",
396 mbox
= add (buffer
, pers
);
398 if (route_addr (buffer
) == NOTOK
)
406 if (domain (buffer
) == NOTOK
)
412 strcpy (err
, "extraneous semi-colon");
420 sprintf (err
, "junk after local@domain (%s)", buffer
);
424 case LX_SEMI
: /* no host */
428 if (last_lex
== LX_SEMI
&& glevel
-- <= 0) {
429 strcpy (err
, "extraneous semi-colon");
437 sprintf (err
, "missing mailbox (%s)", buffer
);
444 phrase (char *buffer
)
447 switch (my_lex (buffer
)) {
450 pers
= add (buffer
, add (" ", pers
));
460 route_addr (char *buffer
)
462 register char *pp
= cp
;
464 if (my_lex (buffer
) == LX_AT
) {
465 if (route (buffer
) == NOTOK
)
471 if (local_part (buffer
) == NOTOK
)
476 return domain (buffer
);
478 case LX_SEMI
: /* if in group */
479 case LX_RBRK
: /* no host */
485 sprintf (err
, "no at-sign after local-part (%s)", buffer
);
492 local_part (char *buffer
)
497 switch (my_lex (buffer
)) {
500 mbox
= add (buffer
, mbox
);
504 sprintf (err
, "no mailbox in local-part (%s)", buffer
);
508 switch (my_lex (buffer
)) {
510 mbox
= add (buffer
, mbox
);
521 domain (char *buffer
)
524 switch (my_lex (buffer
)) {
527 host
= add (buffer
, host
);
531 sprintf (err
, "no sub-domain in domain-part of address (%s)", buffer
);
535 switch (my_lex (buffer
)) {
537 host
= add (buffer
, host
);
540 case LX_AT
: /* sigh (0) */
541 mbox
= add (host
, add ("%", mbox
));
559 switch (my_lex (buffer
)) {
562 path
= add (buffer
, path
);
566 sprintf (err
, "no sub-domain in domain-part of address (%s)", buffer
);
569 switch (my_lex (buffer
)) {
571 path
= add (buffer
, path
);
573 switch (my_lex (buffer
)) {
578 path
= add (buffer
, path
);
582 sprintf (err
, "no at-sign found for next domain in route (%s)",
589 case LX_AT
: /* XXX */
591 path
= add (buffer
, path
);
595 path
= add (buffer
, path
);
599 sprintf (err
, "no colon found to terminate route (%s)", buffer
);
607 my_lex (char *buffer
)
609 /* buffer should be at least BUFSIZ bytes long */
613 /* Add C to the buffer bp. After use of this macro *bp is guaranteed to be within the buffer. */
614 #define ADDCHR(C) do { *bp++ = (C); if ((bp - buffer) == (BUFSIZ-1)) goto my_lex_buffull; } while (0)
619 return (last_lex
= LX_END
);
623 while (isspace ((unsigned char) c
))
627 return (last_lex
= LX_END
);
636 return (last_lex
= LX_ERR
);
639 if ((c
= *cp
++) == 0) {
641 return (last_lex
= LX_ERR
);
654 note
= note
? add (buffer
, add (" ", note
))
656 return my_lex (buffer
);
667 return (last_lex
= LX_ERR
);
670 if ((c
= *cp
++) == 0) {
672 return (last_lex
= LX_ERR
);
680 return (last_lex
= LX_QSTR
);
690 return (last_lex
= LX_ERR
);
693 if ((c
= *cp
++) == 0) {
695 return (last_lex
= LX_ERR
);
703 return (last_lex
= LX_DLIT
);
709 for (i
= 0; special
[i
].lx_chr
!= 0; i
++)
710 if (c
== special
[i
].lx_chr
)
711 return (last_lex
= special
[i
].lx_val
);
713 if (iscntrl ((unsigned char) c
))
714 return (last_lex
= LX_ERR
);
717 if ((c
= *cp
++) == 0)
719 for (i
= 0; special
[i
].lx_chr
!= 0; i
++)
720 if (c
== special
[i
].lx_chr
)
722 if (iscntrl ((unsigned char) c
) || isspace ((unsigned char) c
))
732 last_lex
= !gotat
|| cp
== NULL
|| strchr(cp
, '<') != NULL
737 /* Out of buffer space. *bp is the last byte in the buffer */
739 return (last_lex
= LX_ERR
);
744 legal_person (char *p
)
748 static char buffer
[BUFSIZ
];
752 for (cp
= p
; *cp
; cp
++)
753 for (i
= 0; special
[i
].lx_chr
; i
++)
754 if (*cp
== special
[i
].lx_chr
) {
755 sprintf (buffer
, "\"%s\"", p
);
764 mfgets (FILE *in
, char **bp
)
767 register char *cp
, *dp
, *ep
;
769 static char *pp
= NULL
;
772 pp
= mh_xmalloc ((size_t) (len
= BUFSIZ
));
774 for (ep
= (cp
= pp
) + len
- 2;;) {
775 switch (i
= getc (in
)) {
793 if (cp
== pp
) /* end of headers, gobble it */
795 switch (i
= getc (in
)) {
796 default: /* end of line */
797 case '\n': /* end of headers, save for next call */
801 case ' ': /* continue headers */
805 } /* fall into default case */
812 dp
= mh_xrealloc (pp
, (size_t) (len
+= BUFSIZ
));
813 cp
+= dp
- pp
, ep
= (pp
= cp
) + len
- 2;