Blame


1 5cdb1798 2005-10-29 devnull #include "common.h"
2 5cdb1798 2005-10-29 devnull #include "send.h"
3 5cdb1798 2005-10-29 devnull
4 5cdb1798 2005-10-29 devnull #include "../smtp/smtp.h"
5 5cc53af9 2006-02-12 devnull #include "../smtp/rfc822.tab.h"
6 5cdb1798 2005-10-29 devnull
7 5cdb1798 2005-10-29 devnull /* global to this file */
8 5cdb1798 2005-10-29 devnull static Reprog *rfprog;
9 5cdb1798 2005-10-29 devnull static Reprog *fprog;
10 5cdb1798 2005-10-29 devnull
11 5cdb1798 2005-10-29 devnull #define VMLIMIT (64*1024)
12 5cdb1798 2005-10-29 devnull #define MSGLIMIT (128*1024*1024)
13 5cdb1798 2005-10-29 devnull
14 5cdb1798 2005-10-29 devnull int received; /* from rfc822.y */
15 5cdb1798 2005-10-29 devnull
16 5cdb1798 2005-10-29 devnull static String* getstring(Node *p);
17 5cdb1798 2005-10-29 devnull static String* getaddr(Node *p);
18 5cdb1798 2005-10-29 devnull
19 5cdb1798 2005-10-29 devnull extern int
20 5cdb1798 2005-10-29 devnull default_from(message *mp)
21 5cdb1798 2005-10-29 devnull {
22 5cdb1798 2005-10-29 devnull char *cp, *lp;
23 5cdb1798 2005-10-29 devnull
24 5cdb1798 2005-10-29 devnull cp = getenv("upasname");
25 5cdb1798 2005-10-29 devnull lp = getlog();
26 5cdb1798 2005-10-29 devnull if(lp == nil)
27 5cdb1798 2005-10-29 devnull return -1;
28 5cdb1798 2005-10-29 devnull
29 5cdb1798 2005-10-29 devnull if(cp && *cp)
30 5cdb1798 2005-10-29 devnull s_append(mp->sender, cp);
31 5cdb1798 2005-10-29 devnull else
32 5cdb1798 2005-10-29 devnull s_append(mp->sender, lp);
33 5cdb1798 2005-10-29 devnull s_append(mp->date, thedate());
34 5cdb1798 2005-10-29 devnull return 0;
35 5cdb1798 2005-10-29 devnull }
36 5cdb1798 2005-10-29 devnull
37 5cdb1798 2005-10-29 devnull extern message *
38 5cdb1798 2005-10-29 devnull m_new(void)
39 5cdb1798 2005-10-29 devnull {
40 5cdb1798 2005-10-29 devnull message *mp;
41 5cdb1798 2005-10-29 devnull
42 5cdb1798 2005-10-29 devnull mp = (message *)mallocz(sizeof(message), 1);
43 5cdb1798 2005-10-29 devnull if (mp == 0) {
44 5cdb1798 2005-10-29 devnull perror("message:");
45 5cdb1798 2005-10-29 devnull exit(1);
46 5cdb1798 2005-10-29 devnull }
47 5cdb1798 2005-10-29 devnull mp->sender = s_new();
48 5cdb1798 2005-10-29 devnull mp->replyaddr = s_new();
49 5cdb1798 2005-10-29 devnull mp->date = s_new();
50 5cdb1798 2005-10-29 devnull mp->body = s_new();
51 5cdb1798 2005-10-29 devnull mp->size = 0;
52 5cdb1798 2005-10-29 devnull mp->fd = -1;
53 5cdb1798 2005-10-29 devnull return mp;
54 5cdb1798 2005-10-29 devnull }
55 5cdb1798 2005-10-29 devnull
56 5cdb1798 2005-10-29 devnull extern void
57 5cdb1798 2005-10-29 devnull m_free(message *mp)
58 5cdb1798 2005-10-29 devnull {
59 5cdb1798 2005-10-29 devnull if(mp->fd >= 0){
60 5cdb1798 2005-10-29 devnull close(mp->fd);
61 5cdb1798 2005-10-29 devnull sysremove(s_to_c(mp->tmp));
62 5cdb1798 2005-10-29 devnull s_free(mp->tmp);
63 5cdb1798 2005-10-29 devnull }
64 5cdb1798 2005-10-29 devnull s_free(mp->sender);
65 5cdb1798 2005-10-29 devnull s_free(mp->date);
66 5cdb1798 2005-10-29 devnull s_free(mp->body);
67 5cdb1798 2005-10-29 devnull s_free(mp->havefrom);
68 5cdb1798 2005-10-29 devnull s_free(mp->havesender);
69 5cdb1798 2005-10-29 devnull s_free(mp->havereplyto);
70 5cdb1798 2005-10-29 devnull s_free(mp->havesubject);
71 5cdb1798 2005-10-29 devnull free((char *)mp);
72 5cdb1798 2005-10-29 devnull }
73 5cdb1798 2005-10-29 devnull
74 5cdb1798 2005-10-29 devnull /* read a message into a temp file , return an open fd to it */
75 5cdb1798 2005-10-29 devnull static int
76 5cdb1798 2005-10-29 devnull m_read_to_file(Biobuf *fp, message *mp)
77 5cdb1798 2005-10-29 devnull {
78 5cdb1798 2005-10-29 devnull int fd;
79 5cdb1798 2005-10-29 devnull int n;
80 5cdb1798 2005-10-29 devnull String *file;
81 5cdb1798 2005-10-29 devnull char buf[4*1024];
82 5cdb1798 2005-10-29 devnull
83 5cdb1798 2005-10-29 devnull file = s_new();
84 5cdb1798 2005-10-29 devnull /*
85 5cdb1798 2005-10-29 devnull * create temp file to be remove on close
86 5cdb1798 2005-10-29 devnull */
87 5cdb1798 2005-10-29 devnull abspath("mtXXXXXX", UPASTMP, file);
88 5cdb1798 2005-10-29 devnull mktemp(s_to_c(file));
89 5cdb1798 2005-10-29 devnull if((fd = syscreate(s_to_c(file), ORDWR|ORCLOSE, 0600))<0){
90 5cdb1798 2005-10-29 devnull s_free(file);
91 5cdb1798 2005-10-29 devnull return -1;
92 5cdb1798 2005-10-29 devnull }
93 5cdb1798 2005-10-29 devnull mp->tmp = file;
94 5cdb1798 2005-10-29 devnull
95 5cdb1798 2005-10-29 devnull /*
96 5cdb1798 2005-10-29 devnull * read the rest into the temp file
97 5cdb1798 2005-10-29 devnull */
98 5cdb1798 2005-10-29 devnull while((n = Bread(fp, buf, sizeof(buf))) > 0){
99 5cdb1798 2005-10-29 devnull if(write(fd, buf, n) != n){
100 5cdb1798 2005-10-29 devnull close(fd);
101 5cdb1798 2005-10-29 devnull return -1;
102 5cdb1798 2005-10-29 devnull }
103 5cdb1798 2005-10-29 devnull mp->size += n;
104 5cdb1798 2005-10-29 devnull if(mp->size > MSGLIMIT){
105 5cdb1798 2005-10-29 devnull mp->size = -1;
106 5cdb1798 2005-10-29 devnull break;
107 5cdb1798 2005-10-29 devnull }
108 5cdb1798 2005-10-29 devnull }
109 5cdb1798 2005-10-29 devnull
110 5cdb1798 2005-10-29 devnull mp->fd = fd;
111 5cdb1798 2005-10-29 devnull return 0;
112 5cdb1798 2005-10-29 devnull }
113 5cdb1798 2005-10-29 devnull
114 5cdb1798 2005-10-29 devnull /* get the first address from a node */
115 5cdb1798 2005-10-29 devnull static String*
116 5cdb1798 2005-10-29 devnull getaddr(Node *p)
117 5cdb1798 2005-10-29 devnull {
118 5cdb1798 2005-10-29 devnull for(; p; p = p->next)
119 5cdb1798 2005-10-29 devnull if(p->s && p->addr)
120 5cdb1798 2005-10-29 devnull return s_copy(s_to_c(p->s));
121 a79cd783 2006-02-12 devnull return nil;
122 5cdb1798 2005-10-29 devnull }
123 5cdb1798 2005-10-29 devnull
124 5cdb1798 2005-10-29 devnull /* get the text of a header line minus the field name */
125 5cdb1798 2005-10-29 devnull static String*
126 5cdb1798 2005-10-29 devnull getstring(Node *p)
127 5cdb1798 2005-10-29 devnull {
128 5cdb1798 2005-10-29 devnull String *s;
129 5cdb1798 2005-10-29 devnull
130 5cdb1798 2005-10-29 devnull s = s_new();
131 5cdb1798 2005-10-29 devnull if(p == nil)
132 5cdb1798 2005-10-29 devnull return s;
133 5cdb1798 2005-10-29 devnull
134 5cdb1798 2005-10-29 devnull for(p = p->next; p; p = p->next){
135 5cdb1798 2005-10-29 devnull if(p->s){
136 5cdb1798 2005-10-29 devnull s_append(s, s_to_c(p->s));
137 5cdb1798 2005-10-29 devnull }else{
138 5cdb1798 2005-10-29 devnull s_putc(s, p->c);
139 5cdb1798 2005-10-29 devnull s_terminate(s);
140 5cdb1798 2005-10-29 devnull }
141 5cdb1798 2005-10-29 devnull if(p->white)
142 5cdb1798 2005-10-29 devnull s_append(s, s_to_c(p->white));
143 5cdb1798 2005-10-29 devnull }
144 5cdb1798 2005-10-29 devnull return s;
145 5cdb1798 2005-10-29 devnull }
146 5cdb1798 2005-10-29 devnull
147 b5f65921 2006-02-11 devnull #if 0
148 5cdb1798 2005-10-29 devnull static char *fieldname[] =
149 5cdb1798 2005-10-29 devnull {
150 5cdb1798 2005-10-29 devnull [WORD-WORD] "WORD",
151 5cdb1798 2005-10-29 devnull [DATE-WORD] "DATE",
152 5cdb1798 2005-10-29 devnull [RESENT_DATE-WORD] "RESENT_DATE",
153 5cdb1798 2005-10-29 devnull [RETURN_PATH-WORD] "RETURN_PATH",
154 5cdb1798 2005-10-29 devnull [FROM-WORD] "FROM",
155 5cdb1798 2005-10-29 devnull [SENDER-WORD] "SENDER",
156 5cdb1798 2005-10-29 devnull [REPLY_TO-WORD] "REPLY_TO",
157 5cdb1798 2005-10-29 devnull [RESENT_FROM-WORD] "RESENT_FROM",
158 5cdb1798 2005-10-29 devnull [RESENT_SENDER-WORD] "RESENT_SENDER",
159 5cdb1798 2005-10-29 devnull [RESENT_REPLY_TO-WORD] "RESENT_REPLY_TO",
160 5cdb1798 2005-10-29 devnull [SUBJECT-WORD] "SUBJECT",
161 5cdb1798 2005-10-29 devnull [TO-WORD] "TO",
162 5cdb1798 2005-10-29 devnull [CC-WORD] "CC",
163 5cdb1798 2005-10-29 devnull [BCC-WORD] "BCC",
164 5cdb1798 2005-10-29 devnull [RESENT_TO-WORD] "RESENT_TO",
165 5cdb1798 2005-10-29 devnull [RESENT_CC-WORD] "RESENT_CC",
166 5cdb1798 2005-10-29 devnull [RESENT_BCC-WORD] "RESENT_BCC",
167 5cdb1798 2005-10-29 devnull [REMOTE-WORD] "REMOTE",
168 5cdb1798 2005-10-29 devnull [PRECEDENCE-WORD] "PRECEDENCE",
169 5cdb1798 2005-10-29 devnull [MIMEVERSION-WORD] "MIMEVERSION",
170 5cdb1798 2005-10-29 devnull [CONTENTTYPE-WORD] "CONTENTTYPE",
171 5cdb1798 2005-10-29 devnull [MESSAGEID-WORD] "MESSAGEID",
172 5cdb1798 2005-10-29 devnull [RECEIVED-WORD] "RECEIVED",
173 5cdb1798 2005-10-29 devnull [MAILER-WORD] "MAILER",
174 cbeb0b26 2006-04-01 devnull [BADTOKEN-WORD] "BADTOKEN"
175 5cdb1798 2005-10-29 devnull };
176 b5f65921 2006-02-11 devnull #endif
177 5cdb1798 2005-10-29 devnull
178 5cdb1798 2005-10-29 devnull /* fix 822 addresses */
179 5cdb1798 2005-10-29 devnull static void
180 5cdb1798 2005-10-29 devnull rfc822cruft(message *mp)
181 5cdb1798 2005-10-29 devnull {
182 5cdb1798 2005-10-29 devnull Field *f;
183 5cdb1798 2005-10-29 devnull Node *p;
184 5cdb1798 2005-10-29 devnull String *body, *s;
185 5cdb1798 2005-10-29 devnull char *cp;
186 5cdb1798 2005-10-29 devnull
187 5cdb1798 2005-10-29 devnull /*
188 5cdb1798 2005-10-29 devnull * parse headers in in-core part
189 5cdb1798 2005-10-29 devnull */
190 5cdb1798 2005-10-29 devnull yyinit(s_to_c(mp->body), s_len(mp->body));
191 5cdb1798 2005-10-29 devnull mp->rfc822headers = 0;
192 5cdb1798 2005-10-29 devnull yyparse();
193 5cdb1798 2005-10-29 devnull mp->rfc822headers = 1;
194 5cdb1798 2005-10-29 devnull mp->received = received;
195 5cdb1798 2005-10-29 devnull
196 5cdb1798 2005-10-29 devnull /*
197 5cdb1798 2005-10-29 devnull * remove equivalent systems in all addresses
198 5cdb1798 2005-10-29 devnull */
199 5cdb1798 2005-10-29 devnull body = s_new();
200 5cdb1798 2005-10-29 devnull cp = s_to_c(mp->body);
201 5cdb1798 2005-10-29 devnull for(f = firstfield; f; f = f->next){
202 5cdb1798 2005-10-29 devnull if(f->node->c == MIMEVERSION)
203 5cdb1798 2005-10-29 devnull mp->havemime = 1;
204 5cdb1798 2005-10-29 devnull if(f->node->c == FROM)
205 5cdb1798 2005-10-29 devnull mp->havefrom = getaddr(f->node);
206 5cdb1798 2005-10-29 devnull if(f->node->c == SENDER)
207 5cdb1798 2005-10-29 devnull mp->havesender = getaddr(f->node);
208 5cdb1798 2005-10-29 devnull if(f->node->c == REPLY_TO)
209 5cdb1798 2005-10-29 devnull mp->havereplyto = getaddr(f->node);
210 5cdb1798 2005-10-29 devnull if(f->node->c == TO)
211 5cdb1798 2005-10-29 devnull mp->haveto = 1;
212 5cdb1798 2005-10-29 devnull if(f->node->c == DATE)
213 5cdb1798 2005-10-29 devnull mp->havedate = 1;
214 5cdb1798 2005-10-29 devnull if(f->node->c == SUBJECT)
215 5cdb1798 2005-10-29 devnull mp->havesubject = getstring(f->node);
216 5cdb1798 2005-10-29 devnull if(f->node->c == PRECEDENCE && f->node->next && f->node->next->next){
217 5cdb1798 2005-10-29 devnull s = f->node->next->next->s;
218 5cdb1798 2005-10-29 devnull if(s && (strcmp(s_to_c(s), "bulk") == 0
219 5cdb1798 2005-10-29 devnull || strcmp(s_to_c(s), "Bulk") == 0))
220 5cdb1798 2005-10-29 devnull mp->bulk = 1;
221 5cdb1798 2005-10-29 devnull }
222 5cdb1798 2005-10-29 devnull for(p = f->node; p; p = p->next){
223 5cdb1798 2005-10-29 devnull if(p->s){
224 5cdb1798 2005-10-29 devnull if(p->addr){
225 5cdb1798 2005-10-29 devnull cp = skipequiv(s_to_c(p->s));
226 5cdb1798 2005-10-29 devnull s_append(body, cp);
227 5cdb1798 2005-10-29 devnull } else
228 5cdb1798 2005-10-29 devnull s_append(body, s_to_c(p->s));
229 5cdb1798 2005-10-29 devnull }else{
230 5cdb1798 2005-10-29 devnull s_putc(body, p->c);
231 5cdb1798 2005-10-29 devnull s_terminate(body);
232 5cdb1798 2005-10-29 devnull }
233 5cdb1798 2005-10-29 devnull if(p->white)
234 5cdb1798 2005-10-29 devnull s_append(body, s_to_c(p->white));
235 5cdb1798 2005-10-29 devnull cp = p->end+1;
236 5cdb1798 2005-10-29 devnull }
237 5cdb1798 2005-10-29 devnull s_append(body, "\n");
238 5cdb1798 2005-10-29 devnull }
239 5cdb1798 2005-10-29 devnull
240 5cdb1798 2005-10-29 devnull if(*s_to_c(body) == 0){
241 5cdb1798 2005-10-29 devnull s_free(body);
242 5cdb1798 2005-10-29 devnull return;
243 5cdb1798 2005-10-29 devnull }
244 5cdb1798 2005-10-29 devnull
245 5cdb1798 2005-10-29 devnull if(*cp != '\n')
246 5cdb1798 2005-10-29 devnull s_append(body, "\n");
247 5cdb1798 2005-10-29 devnull s_memappend(body, cp, s_len(mp->body) - (cp - s_to_c(mp->body)));
248 5cdb1798 2005-10-29 devnull s_terminate(body);
249 5cdb1798 2005-10-29 devnull
250 5cdb1798 2005-10-29 devnull firstfield = 0;
251 5cdb1798 2005-10-29 devnull mp->size += s_len(body) - s_len(mp->body);
252 5cdb1798 2005-10-29 devnull s_free(mp->body);
253 5cdb1798 2005-10-29 devnull mp->body = body;
254 5cdb1798 2005-10-29 devnull }
255 5cdb1798 2005-10-29 devnull
256 5cdb1798 2005-10-29 devnull /* read in a message, interpret the 'From' header */
257 5cdb1798 2005-10-29 devnull extern message *
258 5cdb1798 2005-10-29 devnull m_read(Biobuf *fp, int rmail, int interactive)
259 5cdb1798 2005-10-29 devnull {
260 5cdb1798 2005-10-29 devnull message *mp;
261 5cdb1798 2005-10-29 devnull Resub subexp[10];
262 5cdb1798 2005-10-29 devnull char *line;
263 5cdb1798 2005-10-29 devnull int first;
264 5cdb1798 2005-10-29 devnull int n;
265 5cdb1798 2005-10-29 devnull
266 5cdb1798 2005-10-29 devnull mp = m_new();
267 5cdb1798 2005-10-29 devnull
268 5cdb1798 2005-10-29 devnull /* parse From lines if remote */
269 5cdb1798 2005-10-29 devnull if (rmail) {
270 5cdb1798 2005-10-29 devnull /* get remote address */
271 5cdb1798 2005-10-29 devnull String *sender=s_new();
272 5cdb1798 2005-10-29 devnull
273 5cdb1798 2005-10-29 devnull if (rfprog == 0)
274 5cdb1798 2005-10-29 devnull rfprog = regcomp(REMFROMRE);
275 5cdb1798 2005-10-29 devnull first = 1;
276 5cdb1798 2005-10-29 devnull while(s_read_line(fp, s_restart(mp->body)) != 0) {
277 5cdb1798 2005-10-29 devnull memset(subexp, 0, sizeof(subexp));
278 5cdb1798 2005-10-29 devnull if (regexec(rfprog, s_to_c(mp->body), subexp, 10) == 0){
279 5cdb1798 2005-10-29 devnull if(first == 0)
280 5cdb1798 2005-10-29 devnull break;
281 5cdb1798 2005-10-29 devnull if (fprog == 0)
282 5cdb1798 2005-10-29 devnull fprog = regcomp(FROMRE);
283 5cdb1798 2005-10-29 devnull memset(subexp, 0, sizeof(subexp));
284 5cdb1798 2005-10-29 devnull if(regexec(fprog, s_to_c(mp->body), subexp,10) == 0)
285 5cdb1798 2005-10-29 devnull break;
286 5cdb1798 2005-10-29 devnull s_restart(mp->body);
287 5cdb1798 2005-10-29 devnull append_match(subexp, s_restart(sender), SENDERMATCH);
288 5cdb1798 2005-10-29 devnull append_match(subexp, s_restart(mp->date), DATEMATCH);
289 5cdb1798 2005-10-29 devnull break;
290 5cdb1798 2005-10-29 devnull }
291 5cdb1798 2005-10-29 devnull append_match(subexp, s_restart(sender), REMSENDERMATCH);
292 5cdb1798 2005-10-29 devnull append_match(subexp, s_restart(mp->date), REMDATEMATCH);
293 5cdb1798 2005-10-29 devnull if(subexp[REMSYSMATCH].s.sp!=subexp[REMSYSMATCH].e.ep){
294 5cdb1798 2005-10-29 devnull append_match(subexp, mp->sender, REMSYSMATCH);
295 5cdb1798 2005-10-29 devnull s_append(mp->sender, "!");
296 5cdb1798 2005-10-29 devnull }
297 5cdb1798 2005-10-29 devnull first = 0;
298 5cdb1798 2005-10-29 devnull }
299 5cdb1798 2005-10-29 devnull s_append(mp->sender, s_to_c(sender));
300 5cdb1798 2005-10-29 devnull
301 5cdb1798 2005-10-29 devnull s_free(sender);
302 5cdb1798 2005-10-29 devnull }
303 5cdb1798 2005-10-29 devnull if(*s_to_c(mp->sender)=='\0')
304 5cdb1798 2005-10-29 devnull default_from(mp);
305 5cdb1798 2005-10-29 devnull
306 5cdb1798 2005-10-29 devnull /* if sender address is unreturnable, treat message as bulk mail */
307 5cdb1798 2005-10-29 devnull if(!returnable(s_to_c(mp->sender)))
308 5cdb1798 2005-10-29 devnull mp->bulk = 1;
309 5cdb1798 2005-10-29 devnull
310 5cdb1798 2005-10-29 devnull /* get body */
311 5cdb1798 2005-10-29 devnull if(interactive && !rmail){
312 5cdb1798 2005-10-29 devnull /* user typing on terminal: terminator == '.' or EOF */
313 5cdb1798 2005-10-29 devnull for(;;) {
314 5cdb1798 2005-10-29 devnull line = s_read_line(fp, mp->body);
315 5cdb1798 2005-10-29 devnull if (line == 0)
316 5cdb1798 2005-10-29 devnull break;
317 5cdb1798 2005-10-29 devnull if (strcmp(".\n", line)==0) {
318 5cdb1798 2005-10-29 devnull mp->body->ptr -= 2;
319 5cdb1798 2005-10-29 devnull *mp->body->ptr = '\0';
320 5cdb1798 2005-10-29 devnull break;
321 5cdb1798 2005-10-29 devnull }
322 5cdb1798 2005-10-29 devnull }
323 5cdb1798 2005-10-29 devnull mp->size = mp->body->ptr - mp->body->base;
324 5cdb1798 2005-10-29 devnull } else {
325 5cdb1798 2005-10-29 devnull /*
326 5cdb1798 2005-10-29 devnull * read up to VMLIMIT bytes (more or less) into main memory.
327 5cdb1798 2005-10-29 devnull * if message is longer put the rest in a tmp file.
328 5cdb1798 2005-10-29 devnull */
329 5cdb1798 2005-10-29 devnull mp->size = mp->body->ptr - mp->body->base;
330 5cdb1798 2005-10-29 devnull n = s_read(fp, mp->body, VMLIMIT);
331 5cdb1798 2005-10-29 devnull if(n < 0){
332 5cdb1798 2005-10-29 devnull perror("m_read");
333 5cdb1798 2005-10-29 devnull exit(1);
334 5cdb1798 2005-10-29 devnull }
335 5cdb1798 2005-10-29 devnull mp->size += n;
336 5cdb1798 2005-10-29 devnull if(n == VMLIMIT){
337 5cdb1798 2005-10-29 devnull if(m_read_to_file(fp, mp) < 0){
338 7ce2007c 2006-02-12 devnull perror("m_read_to_file");
339 5cdb1798 2005-10-29 devnull exit(1);
340 5cdb1798 2005-10-29 devnull }
341 5cdb1798 2005-10-29 devnull }
342 5cdb1798 2005-10-29 devnull }
343 5cdb1798 2005-10-29 devnull
344 5cdb1798 2005-10-29 devnull /*
345 5cdb1798 2005-10-29 devnull * ignore 0 length messages from a terminal
346 5cdb1798 2005-10-29 devnull */
347 5cdb1798 2005-10-29 devnull if (!rmail && mp->size == 0)
348 5cdb1798 2005-10-29 devnull return 0;
349 5cdb1798 2005-10-29 devnull
350 5cdb1798 2005-10-29 devnull rfc822cruft(mp);
351 5cdb1798 2005-10-29 devnull
352 5cdb1798 2005-10-29 devnull return mp;
353 5cdb1798 2005-10-29 devnull }
354 5cdb1798 2005-10-29 devnull
355 5cdb1798 2005-10-29 devnull /* return a piece of message starting at `offset' */
356 5cdb1798 2005-10-29 devnull extern int
357 5cdb1798 2005-10-29 devnull m_get(message *mp, long offset, char **pp)
358 5cdb1798 2005-10-29 devnull {
359 5cdb1798 2005-10-29 devnull static char buf[4*1024];
360 5cdb1798 2005-10-29 devnull
361 5cdb1798 2005-10-29 devnull /*
362 5cdb1798 2005-10-29 devnull * are we past eof?
363 5cdb1798 2005-10-29 devnull */
364 5cdb1798 2005-10-29 devnull if(offset >= mp->size)
365 5cdb1798 2005-10-29 devnull return 0;
366 5cdb1798 2005-10-29 devnull
367 5cdb1798 2005-10-29 devnull /*
368 5cdb1798 2005-10-29 devnull * are we in the virtual memory portion?
369 5cdb1798 2005-10-29 devnull */
370 5cdb1798 2005-10-29 devnull if(offset < s_len(mp->body)){
371 5cdb1798 2005-10-29 devnull *pp = mp->body->base + offset;
372 5cdb1798 2005-10-29 devnull return mp->body->ptr - mp->body->base - offset;
373 5cdb1798 2005-10-29 devnull }
374 5cdb1798 2005-10-29 devnull
375 5cdb1798 2005-10-29 devnull /*
376 5cdb1798 2005-10-29 devnull * read it from the temp file
377 5cdb1798 2005-10-29 devnull */
378 5cdb1798 2005-10-29 devnull offset -= s_len(mp->body);
379 5cdb1798 2005-10-29 devnull if(mp->fd < 0)
380 5cdb1798 2005-10-29 devnull return -1;
381 5cdb1798 2005-10-29 devnull if(seek(mp->fd, offset, 0)<0)
382 5cdb1798 2005-10-29 devnull return -1;
383 5cdb1798 2005-10-29 devnull *pp = buf;
384 5cdb1798 2005-10-29 devnull return read(mp->fd, buf, sizeof buf);
385 5cdb1798 2005-10-29 devnull }
386 5cdb1798 2005-10-29 devnull
387 5cdb1798 2005-10-29 devnull /* output the message body without ^From escapes */
388 5cdb1798 2005-10-29 devnull static int
389 5cdb1798 2005-10-29 devnull m_noescape(message *mp, Biobuf *fp)
390 5cdb1798 2005-10-29 devnull {
391 5cdb1798 2005-10-29 devnull long offset;
392 5cdb1798 2005-10-29 devnull int n;
393 5cdb1798 2005-10-29 devnull char *p;
394 5cdb1798 2005-10-29 devnull
395 5cdb1798 2005-10-29 devnull for(offset = 0; offset < mp->size; offset += n){
396 5cdb1798 2005-10-29 devnull n = m_get(mp, offset, &p);
397 5cdb1798 2005-10-29 devnull if(n <= 0){
398 5cdb1798 2005-10-29 devnull Bflush(fp);
399 5cdb1798 2005-10-29 devnull return -1;
400 5cdb1798 2005-10-29 devnull }
401 5cdb1798 2005-10-29 devnull if(Bwrite(fp, p, n) < 0)
402 5cdb1798 2005-10-29 devnull return -1;
403 5cdb1798 2005-10-29 devnull }
404 5cdb1798 2005-10-29 devnull return Bflush(fp);
405 5cdb1798 2005-10-29 devnull }
406 5cdb1798 2005-10-29 devnull
407 5cdb1798 2005-10-29 devnull /*
408 5cdb1798 2005-10-29 devnull * Output the message body with '^From ' escapes.
409 5cdb1798 2005-10-29 devnull * Ensures that any line starting with a 'From ' gets a ' ' stuck
410 5cdb1798 2005-10-29 devnull * in front of it.
411 5cdb1798 2005-10-29 devnull */
412 5cdb1798 2005-10-29 devnull static int
413 5cdb1798 2005-10-29 devnull m_escape(message *mp, Biobuf *fp)
414 5cdb1798 2005-10-29 devnull {
415 5cdb1798 2005-10-29 devnull char *p, *np;
416 5cdb1798 2005-10-29 devnull char *end;
417 5cdb1798 2005-10-29 devnull long offset;
418 5cdb1798 2005-10-29 devnull int m, n;
419 5cdb1798 2005-10-29 devnull char *start;
420 5cdb1798 2005-10-29 devnull
421 5cdb1798 2005-10-29 devnull for(offset = 0; offset < mp->size; offset += n){
422 5cdb1798 2005-10-29 devnull n = m_get(mp, offset, &start);
423 5cdb1798 2005-10-29 devnull if(n < 0){
424 5cdb1798 2005-10-29 devnull Bflush(fp);
425 5cdb1798 2005-10-29 devnull return -1;
426 5cdb1798 2005-10-29 devnull }
427 5cdb1798 2005-10-29 devnull
428 5cdb1798 2005-10-29 devnull p = start;
429 5cdb1798 2005-10-29 devnull for(end = p+n; p < end; p += m){
430 5cdb1798 2005-10-29 devnull np = memchr(p, '\n', end-p);
431 5cdb1798 2005-10-29 devnull if(np == 0){
432 5cdb1798 2005-10-29 devnull Bwrite(fp, p, end-p);
433 5cdb1798 2005-10-29 devnull break;
434 5cdb1798 2005-10-29 devnull }
435 5cdb1798 2005-10-29 devnull m = np - p + 1;
436 5cdb1798 2005-10-29 devnull if(m > 5 && strncmp(p, "From ", 5) == 0)
437 5cdb1798 2005-10-29 devnull Bputc(fp, ' ');
438 5cdb1798 2005-10-29 devnull Bwrite(fp, p, m);
439 5cdb1798 2005-10-29 devnull }
440 5cdb1798 2005-10-29 devnull }
441 5cdb1798 2005-10-29 devnull Bflush(fp);
442 5cdb1798 2005-10-29 devnull return 0;
443 5cdb1798 2005-10-29 devnull }
444 5cdb1798 2005-10-29 devnull
445 5cdb1798 2005-10-29 devnull static int
446 5cdb1798 2005-10-29 devnull printfrom(message *mp, Biobuf *fp)
447 5cdb1798 2005-10-29 devnull {
448 5cdb1798 2005-10-29 devnull String *s;
449 5cdb1798 2005-10-29 devnull int rv;
450 5cdb1798 2005-10-29 devnull
451 5cdb1798 2005-10-29 devnull if(!returnable(s_to_c(mp->sender)))
452 5cdb1798 2005-10-29 devnull return Bprint(fp, "From: Postmaster\n");
453 5cdb1798 2005-10-29 devnull
454 5cdb1798 2005-10-29 devnull s = username(mp->sender);
455 5cdb1798 2005-10-29 devnull if(s) {
456 5cdb1798 2005-10-29 devnull s_append(s, " <");
457 5cdb1798 2005-10-29 devnull s_append(s, s_to_c(mp->sender));
458 5cdb1798 2005-10-29 devnull s_append(s, ">");
459 5cdb1798 2005-10-29 devnull } else {
460 5cdb1798 2005-10-29 devnull s = s_copy(s_to_c(mp->sender));
461 5cdb1798 2005-10-29 devnull }
462 5cdb1798 2005-10-29 devnull s = unescapespecial(s);
463 5cdb1798 2005-10-29 devnull rv = Bprint(fp, "From: %s\n", s_to_c(s));
464 5cdb1798 2005-10-29 devnull s_free(s);
465 5cdb1798 2005-10-29 devnull return rv;
466 5cdb1798 2005-10-29 devnull }
467 5cdb1798 2005-10-29 devnull
468 5cdb1798 2005-10-29 devnull static char *
469 5cdb1798 2005-10-29 devnull rewritezone(char *z)
470 5cdb1798 2005-10-29 devnull {
471 5cdb1798 2005-10-29 devnull int mindiff;
472 5cdb1798 2005-10-29 devnull char s;
473 5cdb1798 2005-10-29 devnull Tm *tm;
474 5cdb1798 2005-10-29 devnull static char x[7];
475 5cdb1798 2005-10-29 devnull
476 5cdb1798 2005-10-29 devnull tm = localtime(time(0));
477 5cdb1798 2005-10-29 devnull mindiff = tm->tzoff/60;
478 5cdb1798 2005-10-29 devnull
479 5cdb1798 2005-10-29 devnull /* if not in my timezone, don't change anything */
480 5cdb1798 2005-10-29 devnull if(strcmp(tm->zone, z) != 0)
481 5cdb1798 2005-10-29 devnull return z;
482 5cdb1798 2005-10-29 devnull
483 5cdb1798 2005-10-29 devnull if(mindiff < 0){
484 5cdb1798 2005-10-29 devnull s = '-';
485 5cdb1798 2005-10-29 devnull mindiff = -mindiff;
486 5cdb1798 2005-10-29 devnull } else
487 5cdb1798 2005-10-29 devnull s = '+';
488 5cdb1798 2005-10-29 devnull
489 5cdb1798 2005-10-29 devnull sprint(x, "%c%.2d%.2d", s, mindiff/60, mindiff%60);
490 5cdb1798 2005-10-29 devnull return x;
491 5cdb1798 2005-10-29 devnull }
492 5cdb1798 2005-10-29 devnull
493 5cdb1798 2005-10-29 devnull int
494 5cdb1798 2005-10-29 devnull isutf8(String *s)
495 5cdb1798 2005-10-29 devnull {
496 5cdb1798 2005-10-29 devnull char *p;
497 5cdb1798 2005-10-29 devnull
498 5cdb1798 2005-10-29 devnull for(p = s_to_c(s); *p; p++)
499 5cdb1798 2005-10-29 devnull if(*p&0x80)
500 5cdb1798 2005-10-29 devnull return 1;
501 5cdb1798 2005-10-29 devnull return 0;
502 5cdb1798 2005-10-29 devnull }
503 5cdb1798 2005-10-29 devnull
504 5cdb1798 2005-10-29 devnull void
505 5cdb1798 2005-10-29 devnull printutf8mime(Biobuf *b)
506 5cdb1798 2005-10-29 devnull {
507 5cdb1798 2005-10-29 devnull Bprint(b, "MIME-Version: 1.0\n");
508 5cdb1798 2005-10-29 devnull Bprint(b, "Content-Type: text/plain; charset=\"UTF-8\"\n");
509 5cdb1798 2005-10-29 devnull Bprint(b, "Content-Transfer-Encoding: 8bit\n");
510 5cdb1798 2005-10-29 devnull }
511 5cdb1798 2005-10-29 devnull
512 5cdb1798 2005-10-29 devnull /* output a message */
513 5cdb1798 2005-10-29 devnull extern int
514 5cdb1798 2005-10-29 devnull m_print(message *mp, Biobuf *fp, char *remote, int mbox)
515 5cdb1798 2005-10-29 devnull {
516 5cdb1798 2005-10-29 devnull String *date, *sender;
517 5cdb1798 2005-10-29 devnull char *f[6];
518 5cdb1798 2005-10-29 devnull int n;
519 5cdb1798 2005-10-29 devnull
520 5cdb1798 2005-10-29 devnull sender = unescapespecial(s_clone(mp->sender));
521 5cdb1798 2005-10-29 devnull
522 5cdb1798 2005-10-29 devnull if (remote != 0){
523 5cdb1798 2005-10-29 devnull if(print_remote_header(fp,s_to_c(sender),s_to_c(mp->date),remote) < 0){
524 5cdb1798 2005-10-29 devnull s_free(sender);
525 5cdb1798 2005-10-29 devnull return -1;
526 5cdb1798 2005-10-29 devnull }
527 5cdb1798 2005-10-29 devnull } else {
528 5cdb1798 2005-10-29 devnull if(print_header(fp, s_to_c(sender), s_to_c(mp->date)) < 0){
529 5cdb1798 2005-10-29 devnull s_free(sender);
530 5cdb1798 2005-10-29 devnull return -1;
531 5cdb1798 2005-10-29 devnull }
532 5cdb1798 2005-10-29 devnull }
533 5cdb1798 2005-10-29 devnull s_free(sender);
534 5cdb1798 2005-10-29 devnull if(!rmail && !mp->havedate){
535 5cdb1798 2005-10-29 devnull /* add a date: line Date: Sun, 19 Apr 1998 12:27:52 -0400 */
536 5cdb1798 2005-10-29 devnull date = s_copy(s_to_c(mp->date));
537 5cdb1798 2005-10-29 devnull n = getfields(s_to_c(date), f, 6, 1, " \t");
538 5cdb1798 2005-10-29 devnull if(n == 6)
539 5cdb1798 2005-10-29 devnull Bprint(fp, "Date: %s, %s %s %s %s %s\n", f[0], f[2], f[1],
540 5cdb1798 2005-10-29 devnull f[5], f[3], rewritezone(f[4]));
541 5cdb1798 2005-10-29 devnull }
542 5cdb1798 2005-10-29 devnull if(!rmail && !mp->havemime && isutf8(mp->body))
543 5cdb1798 2005-10-29 devnull printutf8mime(fp);
544 5cdb1798 2005-10-29 devnull if(mp->to){
545 5cdb1798 2005-10-29 devnull /* add the to: line */
546 5cdb1798 2005-10-29 devnull if (Bprint(fp, "%s\n", s_to_c(mp->to)) < 0)
547 5cdb1798 2005-10-29 devnull return -1;
548 5cdb1798 2005-10-29 devnull /* add the from: line */
549 5cdb1798 2005-10-29 devnull if (!mp->havefrom && printfrom(mp, fp) < 0)
550 5cdb1798 2005-10-29 devnull return -1;
551 5cdb1798 2005-10-29 devnull if(!mp->rfc822headers && *s_to_c(mp->body) != '\n')
552 5cdb1798 2005-10-29 devnull if (Bprint(fp, "\n") < 0)
553 5cdb1798 2005-10-29 devnull return -1;
554 5cdb1798 2005-10-29 devnull } else if(!rmail){
555 5cdb1798 2005-10-29 devnull /* add the from: line */
556 5cdb1798 2005-10-29 devnull if (!mp->havefrom && printfrom(mp, fp) < 0)
557 5cdb1798 2005-10-29 devnull return -1;
558 5cdb1798 2005-10-29 devnull if(!mp->rfc822headers && *s_to_c(mp->body) != '\n')
559 5cdb1798 2005-10-29 devnull if (Bprint(fp, "\n") < 0)
560 5cdb1798 2005-10-29 devnull return -1;
561 5cdb1798 2005-10-29 devnull }
562 5cdb1798 2005-10-29 devnull
563 5cdb1798 2005-10-29 devnull if (!mbox)
564 5cdb1798 2005-10-29 devnull return m_noescape(mp, fp);
565 5cdb1798 2005-10-29 devnull return m_escape(mp, fp);
566 5cdb1798 2005-10-29 devnull }
567 5cdb1798 2005-10-29 devnull
568 5cdb1798 2005-10-29 devnull /* print just the message body */
569 5cdb1798 2005-10-29 devnull extern int
570 5cdb1798 2005-10-29 devnull m_bprint(message *mp, Biobuf *fp)
571 5cdb1798 2005-10-29 devnull {
572 5cdb1798 2005-10-29 devnull return m_noescape(mp, fp);
573 5cdb1798 2005-10-29 devnull }