File: rfc822.c

package info (click to toggle)
gup 0.5.17
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 200 kB
  • sloc: ansic: 1,609; sh: 211; makefile: 34
file content (160 lines) | stat: -rw-r--r-- 3,720 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
/*
 *  Routines to read and write mail and news headers.  The code here
 *  is gross and complicated.
 */
#include "gup.h"
#include "rfc822.h"

#define QUESTIONABLE(c) \
	((c) == '"' || (c) == '(' || (c) == ')' || (c) == '\\')

/*
 *  Crack an RFC822 from header field into address and fullname.  We do
 *  this to make sure we write things out in official form.  "Be liberal
 *  in what you accept, conservative in what you generate."  Anyhow, we
 *  read things into three buffers, one for all <...> text, one for all
 *  (...) text, and a third for stuff not in either.  Either the first or
 *  third buffer will be the real address, depending on whether there is
 *  anything in buffer two or not.
 */
int CrackFrom(ADDRCHAR *addr, char *name, char *p)
{
    register ADDRCHAR *adp;
    register char *bp;
    register char *ap;
    register ADDRCHAR *cp = NULL;	/* keep gcc 2 happy */
    register ADDRCHAR CurrChar;
    register int comment;
    register int address;
    register int addrfound;
    register int QuoteNext;
    register int InQuotes;
    ADDRCHAR *xp;
    ADDRCHAR comm[LG_SIZE];
    ADDRCHAR commbuf[LG_SIZE];
    ADDRCHAR addrbuf[LG_SIZE];

    /* Just to make sure. */
    *name = '\0';
    *addr = '\0';

    if (p == NULL)
	return FALSE;

    /* Eat leading white space. */
    while (*p && isspace(*p))
	p++;

    /* Set defaults. */
    comm[0] = '\0';
    commbuf[0] = '\0';
    addrbuf[0] = '\0';
    adp = addrbuf;
    comment = 0;
    addrfound = 0;
    address = 0;
    QuoteNext = 0;
    InQuotes = 0;
    for (; *p; p++) {
	CurrChar = (*p & UNQUOTE_MASK) | QuoteNext;
	QuoteNext = CurrChar == '\\' ? QUOTE_MASK : 0;
	if (!comment && CurrChar == '"')
	    InQuotes = InQuotes ? 0 : QUOTE_MASK;
	else
	    CurrChar |= InQuotes;
	switch (CurrChar) {
	case '(':
	    if (comment == 0) {
		cp = commbuf;
		*cp = '\0';
	    }
	    comment++;
	    break;
	case ')':
	    if (comment > 0 && --comment == 0) {
		*cp = '\0';
		xp = comm;
		if (*xp) {
		    while (*xp)
			xp++;
		    *xp++ = ',';
		    *xp++ = ' ';
		}
		for (cp = &commbuf[1]; (*xp++ = *cp) != '\0'; cp++)
		    continue;
		cp = NULL;
		continue;
	    }
	    break;
	case '<':
	    if (address)
		return FALSE;	/* AWK! Abort! */
	    if (!comment) {
		address++;
		*adp = '\0';
		adp = addr;
	    }
	    break;
	case '>':
	    if (!comment && address) {
		address--;
		addrfound++;
		for (*adp = '\0', adp = addrbuf; *adp;)
		    adp++;
		continue;
	    }
	    break;
	}

	if (comment)
	    *cp++ = CurrChar;
	else if (!address || CurrChar != '<')
	    *adp++ = CurrChar;
	if (*p == '\0')
	    break;
    }

    *adp++ = '\0';

    if (addrfound)
	for (ap = name, xp = addrbuf; (*ap++ = (*xp & UNQUOTE_MASK)) != 0; xp++)
	    continue;
    else {
	for (cp = addr, xp = addrbuf; (*cp++ = *xp) != 0; xp++)
	    continue;
	*name = '\0';
    }

    /* Just to be sure that we got the full name, we'll take all of
     * the comments. */
    if (*comm) {
	ap = name;
	if (*ap) {
	    while (*ap)
		ap++;
	    *ap++ = ',';
	    *ap++ = ' ';
	}
	for (xp = comm; (*ap = (*xp++ & UNQUOTE_MASK)) != 0; ap++)
	    continue;
    }
    /* Copy back, skipping leading spaces and trailing spaces. */
    for (cp = addr; isspace(*cp); cp++)
	continue;
    for (xp = addr; (*xp = *cp++) != 0;)
	xp++;
    while (*addr && isspace(*--xp))
	*xp = '\0';

    /* Since characters in (comments) are interpreted differently from
     * those in "phrase" <address>, play it safe and remove all
     * questionable characters. */
    for (ap = name, bp = name; isspace(*bp) || QUESTIONABLE(*bp); bp++)
	continue;
    while ((*ap = *bp++) != '\0')
	if (!QUESTIONABLE(*ap))
	    ap++;
    while (*name && isspace(*--ap))
	*ap = '\0';
    return TRUE;
}