1 #include "die.h"
2 #include "mime.h"
3
author_name(stralloc * out,const char * s,unsigned int l)4 void author_name(stralloc *out,const char *s,unsigned int l)
5 /* s is a string that contains a from: line argument\n. We parse */
6 /* s as follows: If there is an unquoted '<' we eliminate everything after */
7 /* it else if there is a unquoted ';' we eliminate everything after it. */
8 /* Then, we eliminate LWSP and '"' from the beginning and end. Note that */
9 /* this is not strict rfc822, but all we need is a display handle that */
10 /* doesn't show the address. If in the remaining text there is a '@' we put*/
11 /* in a '.' instead. Also, there are some non-rfc822 from lines out there */
12 /* and we still want to maximize the chance of getting a handle, even if it*/
13 /* costs a little extra work.*/
14 {
15 int squote = 0;
16 int dquote = 0;
17 int level = 0;
18 int flagdone;
19 unsigned int len;
20 char ch;
21 const char *cpfirst,*cp;
22 const char *cpcomlast = 0;
23 const char *cpquotlast = 0;
24 const char *cpquot = 0;
25 const char *cpcom = 0;
26 const char *cplt = 0;
27 char *cpout;
28
29 if (!s || !l) /* Yuck - pass the buck */
30 if (!stralloc_copyb(out,"",0)) die_nomem();
31 cp = s; len = l;
32
33 while (len--) {
34 ch = *(cp++);
35 if (squote)
36 squote = 0;
37 else if (ch == '\\')
38 squote = 1;
39 else if (ch == '"') { /* "name" <address@host> */
40 if (dquote) {
41 cpquotlast = cp - 2;
42 break;
43 } else {
44 cpquot = cp;
45 dquote = 1;
46 }
47 }
48 else if (dquote)
49 ;
50 else if (ch == '(') {
51 if (!level) cpcom = cp;
52 level++;
53 }
54 else if (ch == ')') {
55 level--;
56 if (!level)
57 cpcomlast = cp - 2; /* address@host (name) */
58 }
59 else if (!level) {
60 if (ch == '<') { /* name <address@host> */
61 cplt = cp - 2;
62 break;
63 } else if (ch == ';') break; /* address@host ;garbage */
64 }
65 }
66 if (cplt) { /* non-comment '<' */
67 cp = cplt;
68 cpfirst = s;
69 } else if (cpquot && cpquotlast >= cpquot) {
70 cpfirst = cpquot;
71 cp = cpquotlast;
72 } else if (cpcom && cpcomlast >= cpcom) {
73 cpfirst = cpcom;
74 cp = cpcomlast;
75 } else {
76 cp = s + l - 1;
77 cpfirst = s;
78 }
79 flagdone = 0;
80 for (;;) { /* e.g. LWSP <user@host> */
81 while (cpfirst <= cp &&
82 (*cpfirst == ' ' || *cpfirst == '\t' || *cpfirst == '<')) cpfirst++;
83 while (cp >= cpfirst &&
84 (*cp == ' ' || *cp == '\t' || *cp == '\n' || *cp == '>')) cp--;
85 if (cp >= cpfirst || flagdone)
86 break;
87 cp = s + l - 1;
88 cpfirst = s;
89 flagdone = 1;
90 }
91
92 decodeHDR(cpfirst,cp - cpfirst + 1,out);
93 for (cpout = out->s, len = out->len; len > 0; --len, ++cpout)
94 if (*cpout == '@')
95 *cpout = '.';
96 }
97
author_addr(stralloc * out,const char * s,unsigned int l)98 void author_addr(stralloc *out,const char *s,unsigned int l)
99 /* s is a string that contains a from: line argument\n. We parse */
100 /* s as follows: If there is an unquoted '<' we eliminate everything after */
101 /* it else if there is a unquoted ';' we eliminate everything after it. */
102 /* Then, we eliminate LWSP and '"' from the beginning and end. Note that */
103 /* this is not strict rfc822, but all we need is a display handle that */
104 /* doesn't show the address. If in the remaining text there is a '@' we put*/
105 /* in a '.' instead. Also, there are some non-rfc822 from lines out there */
106 /* and we still want to maximize the chance of getting a handle, even if it*/
107 /* costs a little extra work.*/
108 {
109 int squote = 0;
110 int dquote = 0;
111 int level = 0;
112 unsigned int len;
113 char ch;
114 const char *cp;
115 const char *cpgt = 0;
116 const char *cplt = 0;
117 const char *cpat = 0;
118 const char *cplast = 0;
119
120 if (!s || !l) /* Yuck - pass the buck */
121 if (!stralloc_copyb(out,"",0)) die_nomem();
122 cp = s; len = l;
123 cplast = s + len;
124
125 for (cp = s, len = l; len > 0; --len, ++cp) {
126 ch = *cp;
127 if (squote)
128 squote = 0;
129 else if (ch == '\\')
130 squote = 1;
131 else if (ch == '"') /* "name" <address@host> */
132 dquote = !dquote;
133 else if (dquote)
134 ;
135 else if (ch == '(') {
136 level++;
137 }
138 else if (ch == ')') {
139 level--;
140 }
141 else if (!level) {
142 if (ch == '<') { /* name <address@host> */
143 cplt = cp;
144 }
145 else if (ch == '>') {
146 cpgt = cp;
147 if (cplt)
148 break;
149 }
150 else if (ch == ';') { /* address@host ;garbage */
151 cplast = cp;
152 break;
153 }
154 else if (ch == '@')
155 cpat = cp;
156 }
157 }
158 /* make cplt point to first character of address, cpgt point to one character after end */
159 if (cplt && cpgt)
160 ++cplt;
161 else if (cpat) {
162 /* backup strategy, we found an @, grab everything from before and after. */
163 for (cplt = cpat - 1; cplt > cp && (*cplt != ' ' && *cplt != '\t'); --cplt)
164 ;
165 for (cpgt = cpat + 1; cpgt < cplast && (*cpgt != ' ' && *cpgt != '\t'); ++cpgt)
166 ;
167 }
168 else
169 cpgt = cplt = cp; /* Empty result means no address found */
170 stralloc_copyb(out,cplt,cpgt-cplt);
171 }
172