1 5cdb1798 2005-10-29 devnull #include "common.h"
2 5cdb1798 2005-10-29 devnull #include <ctype.h>
3 5cdb1798 2005-10-29 devnull #include <plumb.h>
4 5cdb1798 2005-10-29 devnull #include <libsec.h>
5 5cdb1798 2005-10-29 devnull #include <thread.h>
6 5cdb1798 2005-10-29 devnull #include "dat.h"
8 5cdb1798 2005-10-29 devnull extern char* dirtab[]; /* jpc */
10 5cdb1798 2005-10-29 devnull typedef struct Header Header;
12 5cdb1798 2005-10-29 devnull struct Header {
13 5cdb1798 2005-10-29 devnull char *type;
14 5cdb1798 2005-10-29 devnull void (*f)(Message*, Header*, char*);
18 5cdb1798 2005-10-29 devnull /* headers */
19 5cdb1798 2005-10-29 devnull static void ctype(Message*, Header*, char*);
20 5cdb1798 2005-10-29 devnull static void cencoding(Message*, Header*, char*);
21 5cdb1798 2005-10-29 devnull static void cdisposition(Message*, Header*, char*);
22 5cdb1798 2005-10-29 devnull static void date822(Message*, Header*, char*);
23 5cdb1798 2005-10-29 devnull static void from822(Message*, Header*, char*);
24 5cdb1798 2005-10-29 devnull static void to822(Message*, Header*, char*);
25 5cdb1798 2005-10-29 devnull static void sender822(Message*, Header*, char*);
26 5cdb1798 2005-10-29 devnull static void replyto822(Message*, Header*, char*);
27 5cdb1798 2005-10-29 devnull static void subject822(Message*, Header*, char*);
28 5cdb1798 2005-10-29 devnull static void inreplyto822(Message*, Header*, char*);
29 5cdb1798 2005-10-29 devnull static void cc822(Message*, Header*, char*);
30 5cdb1798 2005-10-29 devnull static void bcc822(Message*, Header*, char*);
31 5cdb1798 2005-10-29 devnull static void messageid822(Message*, Header*, char*);
32 5cdb1798 2005-10-29 devnull static void mimeversion(Message*, Header*, char*);
33 5cdb1798 2005-10-29 devnull static void nullsqueeze(Message*);
36 5cdb1798 2005-10-29 devnull Mhead= 11, /* offset of first mime header */
39 5cdb1798 2005-10-29 devnull Header head[] =
41 5cdb1798 2005-10-29 devnull { "date:", date822, },
42 5cdb1798 2005-10-29 devnull { "from:", from822, },
43 5cdb1798 2005-10-29 devnull { "to:", to822, },
44 5cdb1798 2005-10-29 devnull { "sender:", sender822, },
45 5cdb1798 2005-10-29 devnull { "reply-to:", replyto822, },
46 5cdb1798 2005-10-29 devnull { "subject:", subject822, },
47 5cdb1798 2005-10-29 devnull { "cc:", cc822, },
48 5cdb1798 2005-10-29 devnull { "bcc:", bcc822, },
49 5cdb1798 2005-10-29 devnull { "in-reply-to:", inreplyto822, },
50 5cdb1798 2005-10-29 devnull { "mime-version:", mimeversion, },
51 5cdb1798 2005-10-29 devnull { "message-id:", messageid822, },
53 5cdb1798 2005-10-29 devnull [Mhead] { "content-type:", ctype, },
54 5cdb1798 2005-10-29 devnull { "content-transfer-encoding:", cencoding, },
55 5cdb1798 2005-10-29 devnull { "content-disposition:", cdisposition, },
59 5cdb1798 2005-10-29 devnull /* static void fatal(char *fmt, ...); jpc */
60 5cdb1798 2005-10-29 devnull static void initquoted(void);
61 5cdb1798 2005-10-29 devnull /* static void startheader(Message*);
62 5cdb1798 2005-10-29 devnull static void startbody(Message*); jpc */
63 5cdb1798 2005-10-29 devnull static char* skipwhite(char*);
64 5cdb1798 2005-10-29 devnull static char* skiptosemi(char*);
65 5cdb1798 2005-10-29 devnull static char* getstring(char*, String*, int);
66 5cdb1798 2005-10-29 devnull static void setfilename(Message*, char*);
67 5cdb1798 2005-10-29 devnull /* static char* lowercase(char*); jpc */
68 5cdb1798 2005-10-29 devnull static int is8bit(Message*);
69 5cdb1798 2005-10-29 devnull static int headerline(char**, String*);
70 5cdb1798 2005-10-29 devnull static void initheaders(void);
71 5cdb1798 2005-10-29 devnull static void parseattachments(Message*, Mailbox*);
73 5cdb1798 2005-10-29 devnull int debug;
75 5cdb1798 2005-10-29 devnull char *Enotme = "path not served by this file server";
79 cbeb0b26 2006-04-01 devnull Chunksize = 1024
82 5cdb1798 2005-10-29 devnull Mailboxinit *boxinit[] = {
83 5cdb1798 2005-10-29 devnull imap4mbox,
84 5cdb1798 2005-10-29 devnull pop3mbox,
85 cbeb0b26 2006-04-01 devnull plan9mbox
89 5cdb1798 2005-10-29 devnull syncmbox(Mailbox *mb, int doplumb)
91 5cdb1798 2005-10-29 devnull return (*mb->sync)(mb, doplumb);
94 5cdb1798 2005-10-29 devnull /* create a new mailbox */
96 5cdb1798 2005-10-29 devnull newmbox(char *path, char *name, int std)
98 5cdb1798 2005-10-29 devnull Mailbox *mb, **l;
99 5cdb1798 2005-10-29 devnull char *p, *rv;
102 5cdb1798 2005-10-29 devnull initheaders();
104 5cdb1798 2005-10-29 devnull mb = emalloc(sizeof(*mb));
105 5cdb1798 2005-10-29 devnull strncpy(mb->path, path, sizeof(mb->path)-1);
106 5cdb1798 2005-10-29 devnull if(name == nil){
107 5cdb1798 2005-10-29 devnull p = strrchr(path, '/');
108 5cdb1798 2005-10-29 devnull if(p == nil)
109 5cdb1798 2005-10-29 devnull p = path;
112 5cdb1798 2005-10-29 devnull if(*p == 0){
113 5cdb1798 2005-10-29 devnull free(mb);
114 5cdb1798 2005-10-29 devnull return "bad mbox name";
116 5cdb1798 2005-10-29 devnull strncpy(mb->name, p, sizeof(mb->name)-1);
117 5cdb1798 2005-10-29 devnull } else {
118 5cdb1798 2005-10-29 devnull strncpy(mb->name, name, sizeof(mb->name)-1);
121 5cdb1798 2005-10-29 devnull rv = nil;
122 cbeb0b26 2006-04-01 devnull /* check for a mailbox type */
123 5cdb1798 2005-10-29 devnull for(i=0; i<nelem(boxinit); i++)
124 5cdb1798 2005-10-29 devnull if((rv = (*boxinit[i])(mb, path)) != Enotme)
126 5cdb1798 2005-10-29 devnull if(i == nelem(boxinit)){
127 5cdb1798 2005-10-29 devnull free(mb);
128 5cdb1798 2005-10-29 devnull return "bad path";
131 cbeb0b26 2006-04-01 devnull /* on error, give up */
133 5cdb1798 2005-10-29 devnull free(mb);
134 5cdb1798 2005-10-29 devnull return rv;
137 cbeb0b26 2006-04-01 devnull /* make sure name isn't taken */
138 5cdb1798 2005-10-29 devnull qlock(&mbllock);
139 5cdb1798 2005-10-29 devnull for(l = &mbl; *l != nil; l = &(*l)->next){
140 5cdb1798 2005-10-29 devnull if(strcmp((*l)->name, mb->name) == 0){
141 5cdb1798 2005-10-29 devnull if(strcmp(path, (*l)->path) == 0)
142 5cdb1798 2005-10-29 devnull rv = nil;
144 5cdb1798 2005-10-29 devnull rv = "mbox name in use";
145 5cdb1798 2005-10-29 devnull if(mb->close)
146 5cdb1798 2005-10-29 devnull (*mb->close)(mb);
147 5cdb1798 2005-10-29 devnull free(mb);
148 5cdb1798 2005-10-29 devnull qunlock(&mbllock);
149 5cdb1798 2005-10-29 devnull return rv;
153 cbeb0b26 2006-04-01 devnull /* always try locking */
154 5cdb1798 2005-10-29 devnull mb->dolock = 1;
156 5cdb1798 2005-10-29 devnull mb->refs = 1;
157 5cdb1798 2005-10-29 devnull mb->next = nil;
158 5cdb1798 2005-10-29 devnull mb->id = newid();
159 5cdb1798 2005-10-29 devnull mb->root = newmessage(nil);
160 5cdb1798 2005-10-29 devnull mb->std = std;
161 5cdb1798 2005-10-29 devnull *l = mb;
162 5cdb1798 2005-10-29 devnull qunlock(&mbllock);
164 5cdb1798 2005-10-29 devnull qlock(&mb->ql);
165 5cdb1798 2005-10-29 devnull if(mb->ctl){
166 5cdb1798 2005-10-29 devnull henter(PATH(mb->id, Qmbox), "ctl",
167 5cdb1798 2005-10-29 devnull (Qid){PATH(mb->id, Qmboxctl), 0, QTFILE}, nil, mb);
169 5cdb1798 2005-10-29 devnull rv = syncmbox(mb, 0);
170 5cdb1798 2005-10-29 devnull qunlock(&mb->ql);
172 5cdb1798 2005-10-29 devnull return rv;
175 cbeb0b26 2006-04-01 devnull /* close the named mailbox */
177 5cdb1798 2005-10-29 devnull freembox(char *name)
179 5cdb1798 2005-10-29 devnull Mailbox **l, *mb;
181 5cdb1798 2005-10-29 devnull qlock(&mbllock);
182 5cdb1798 2005-10-29 devnull for(l=&mbl; *l != nil; l=&(*l)->next){
183 5cdb1798 2005-10-29 devnull if(strcmp(name, (*l)->name) == 0){
184 5cdb1798 2005-10-29 devnull mb = *l;
185 5cdb1798 2005-10-29 devnull *l = mb->next;
186 5cdb1798 2005-10-29 devnull mboxdecref(mb);
190 5cdb1798 2005-10-29 devnull hfree(PATH(0, Qtop), name);
191 5cdb1798 2005-10-29 devnull qunlock(&mbllock);
194 5cdb1798 2005-10-29 devnull static void
195 5cdb1798 2005-10-29 devnull initheaders(void)
197 5cdb1798 2005-10-29 devnull Header *h;
198 5cdb1798 2005-10-29 devnull static int already;
200 5cdb1798 2005-10-29 devnull if(already)
202 5cdb1798 2005-10-29 devnull already = 1;
204 5cdb1798 2005-10-29 devnull for(h = head; h->type != nil; h++)
205 5cdb1798 2005-10-29 devnull h->len = strlen(h->type);
209 5cdb1798 2005-10-29 devnull * parse a Unix style header
212 5cdb1798 2005-10-29 devnull parseunix(Message *m)
214 5cdb1798 2005-10-29 devnull char *p;
215 5cdb1798 2005-10-29 devnull String *h;
217 5cdb1798 2005-10-29 devnull h = s_new();
218 5cdb1798 2005-10-29 devnull for(p = m->start + 5; *p && *p != '\r' && *p != '\n'; p++)
219 5cdb1798 2005-10-29 devnull s_putc(h, *p);
220 5cdb1798 2005-10-29 devnull s_terminate(h);
221 5cdb1798 2005-10-29 devnull s_restart(h);
223 5cdb1798 2005-10-29 devnull m->unixfrom = s_parse(h, s_reset(m->unixfrom));
224 5cdb1798 2005-10-29 devnull m->unixdate = s_append(s_reset(m->unixdate), h->ptr);
226 5cdb1798 2005-10-29 devnull s_free(h);
230 5cdb1798 2005-10-29 devnull * parse a message
233 5cdb1798 2005-10-29 devnull parseheaders(Message *m, int justmime, Mailbox *mb, int addfrom)
235 5cdb1798 2005-10-29 devnull String *hl;
236 5cdb1798 2005-10-29 devnull Header *h;
237 5cdb1798 2005-10-29 devnull char *p, *q;
240 5cdb1798 2005-10-29 devnull if(m->whole == m->whole->whole){
241 5cdb1798 2005-10-29 devnull henter(PATH(mb->id, Qmbox), m->name,
242 5cdb1798 2005-10-29 devnull (Qid){PATH(m->id, Qdir), 0, QTDIR}, m, mb);
243 5cdb1798 2005-10-29 devnull } else {
244 5cdb1798 2005-10-29 devnull henter(PATH(m->whole->id, Qdir), m->name,
245 5cdb1798 2005-10-29 devnull (Qid){PATH(m->id, Qdir), 0, QTDIR}, m, mb);
247 5cdb1798 2005-10-29 devnull for(i = 0; i < Qmax; i++)
248 5cdb1798 2005-10-29 devnull henter(PATH(m->id, Qdir), dirtab[i],
249 5cdb1798 2005-10-29 devnull (Qid){PATH(m->id, i), 0, QTFILE}, m, mb);
251 cbeb0b26 2006-04-01 devnull /* parse mime headers */
252 5cdb1798 2005-10-29 devnull p = m->header;
253 5cdb1798 2005-10-29 devnull hl = s_new();
254 5cdb1798 2005-10-29 devnull while(headerline(&p, hl)){
255 5cdb1798 2005-10-29 devnull if(justmime)
256 5cdb1798 2005-10-29 devnull h = &head[Mhead];
258 5cdb1798 2005-10-29 devnull h = head;
259 5cdb1798 2005-10-29 devnull for(; h->type; h++){
260 5cdb1798 2005-10-29 devnull if(cistrncmp(s_to_c(hl), h->type, h->len) == 0){
261 5cdb1798 2005-10-29 devnull (*h->f)(m, h, s_to_c(hl));
265 5cdb1798 2005-10-29 devnull s_reset(hl);
267 5cdb1798 2005-10-29 devnull s_free(hl);
269 cbeb0b26 2006-04-01 devnull /* the blank line isn't really part of the body or header */
270 5cdb1798 2005-10-29 devnull if(justmime){
271 5cdb1798 2005-10-29 devnull m->mhend = p;
272 5cdb1798 2005-10-29 devnull m->hend = m->header;
273 5cdb1798 2005-10-29 devnull } else {
274 5cdb1798 2005-10-29 devnull m->hend = p;
276 5cdb1798 2005-10-29 devnull if(*p == '\n')
278 5cdb1798 2005-10-29 devnull m->rbody = m->body = p;
280 cbeb0b26 2006-04-01 devnull /* if type is text, get any nulls out of the body. This is */
281 cbeb0b26 2006-04-01 devnull /* for the two seans and imap clients that get confused. */
282 5cdb1798 2005-10-29 devnull if(strncmp(s_to_c(m->type), "text/", 5) == 0)
283 5cdb1798 2005-10-29 devnull nullsqueeze(m);
286 cbeb0b26 2006-04-01 devnull /* cobble together Unix-style from line */
287 cbeb0b26 2006-04-01 devnull /* for local mailbox messages, we end up recreating the */
288 cbeb0b26 2006-04-01 devnull /* original header. */
289 cbeb0b26 2006-04-01 devnull /* for pop3 messages, the best we can do is */
290 cbeb0b26 2006-04-01 devnull /* use the From: information and the RFC822 date. */
292 5cdb1798 2005-10-29 devnull if(m->unixdate == nil || strcmp(s_to_c(m->unixdate), "???") == 0
293 5cdb1798 2005-10-29 devnull || strcmp(s_to_c(m->unixdate), "Thu Jan 1 00:00:00 GMT 1970") == 0){
294 5cdb1798 2005-10-29 devnull if(m->unixdate){
295 5cdb1798 2005-10-29 devnull s_free(m->unixdate);
296 5cdb1798 2005-10-29 devnull m->unixdate = nil;
298 cbeb0b26 2006-04-01 devnull /* look for the date in the first Received: line. */
299 cbeb0b26 2006-04-01 devnull /* it's likely to be the right time zone (it's */
300 cbeb0b26 2006-04-01 devnull /* the local system) and in a convenient format. */
301 5cdb1798 2005-10-29 devnull if(cistrncmp(m->header, "received:", 9)==0){
302 5cdb1798 2005-10-29 devnull if((q = strchr(m->header, ';')) != nil){
304 5cdb1798 2005-10-29 devnull while((p = strchr(p, '\n')) != nil){
305 5cdb1798 2005-10-29 devnull if(p[1] != ' ' && p[1] != '\t' && p[1] != '\n')
310 5cdb1798 2005-10-29 devnull *p = '\0';
311 5cdb1798 2005-10-29 devnull m->unixdate = date822tounix(q+1);
312 5cdb1798 2005-10-29 devnull *p = '\n';
317 cbeb0b26 2006-04-01 devnull /* fall back on the rfc822 date */
318 5cdb1798 2005-10-29 devnull if(m->unixdate==nil && m->date822)
319 5cdb1798 2005-10-29 devnull m->unixdate = date822tounix(s_to_c(m->date822));
322 5cdb1798 2005-10-29 devnull if(m->unixheader != nil)
323 5cdb1798 2005-10-29 devnull s_free(m->unixheader);
325 cbeb0b26 2006-04-01 devnull /* only fake header for top-level messages for pop3 and imap4 */
326 cbeb0b26 2006-04-01 devnull /* clients (those protocols don't include the unix header). */
327 cbeb0b26 2006-04-01 devnull /* adding the unix header all the time screws up mime-attached */
328 cbeb0b26 2006-04-01 devnull /* rfc822 messages. */
329 5cdb1798 2005-10-29 devnull if(!addfrom && !m->unixfrom){
330 5cdb1798 2005-10-29 devnull m->unixheader = nil;
334 5cdb1798 2005-10-29 devnull m->unixheader = s_copy("From ");
335 5cdb1798 2005-10-29 devnull if(m->unixfrom && strcmp(s_to_c(m->unixfrom), "???") != 0)
336 5cdb1798 2005-10-29 devnull s_append(m->unixheader, s_to_c(m->unixfrom));
337 5cdb1798 2005-10-29 devnull else if(m->from822)
338 5cdb1798 2005-10-29 devnull s_append(m->unixheader, s_to_c(m->from822));
340 5cdb1798 2005-10-29 devnull s_append(m->unixheader, "???");
342 5cdb1798 2005-10-29 devnull s_append(m->unixheader, " ");
343 5cdb1798 2005-10-29 devnull if(m->unixdate)
344 5cdb1798 2005-10-29 devnull s_append(m->unixheader, s_to_c(m->unixdate));
346 5cdb1798 2005-10-29 devnull s_append(m->unixheader, "Thu Jan 1 00:00:00 GMT 1970");
348 5cdb1798 2005-10-29 devnull s_append(m->unixheader, "\n");
352 5cdb1798 2005-10-29 devnull promote(String **sp)
354 5cdb1798 2005-10-29 devnull String *s;
356 5cdb1798 2005-10-29 devnull if(*sp != nil)
357 5cdb1798 2005-10-29 devnull s = s_clone(*sp);
359 5cdb1798 2005-10-29 devnull s = nil;
360 5cdb1798 2005-10-29 devnull return s;
364 5cdb1798 2005-10-29 devnull parsebody(Message *m, Mailbox *mb)
366 5cdb1798 2005-10-29 devnull Message *nm;
368 cbeb0b26 2006-04-01 devnull /* recurse */
369 5cdb1798 2005-10-29 devnull if(strncmp(s_to_c(m->type), "multipart/", 10) == 0){
370 5cdb1798 2005-10-29 devnull parseattachments(m, mb);
371 5cdb1798 2005-10-29 devnull } else if(strcmp(s_to_c(m->type), "message/rfc822") == 0){
372 5cdb1798 2005-10-29 devnull decode(m);
373 5cdb1798 2005-10-29 devnull parseattachments(m, mb);
374 5cdb1798 2005-10-29 devnull nm = m->part;
376 cbeb0b26 2006-04-01 devnull /* promote headers */
377 5cdb1798 2005-10-29 devnull if(m->replyto822 == nil && m->from822 == nil && m->sender822 == nil){
378 5cdb1798 2005-10-29 devnull m->from822 = promote(&nm->from822);
379 5cdb1798 2005-10-29 devnull m->to822 = promote(&nm->to822);
380 5cdb1798 2005-10-29 devnull m->date822 = promote(&nm->date822);
381 5cdb1798 2005-10-29 devnull m->sender822 = promote(&nm->sender822);
382 5cdb1798 2005-10-29 devnull m->replyto822 = promote(&nm->replyto822);
383 5cdb1798 2005-10-29 devnull m->subject822 = promote(&nm->subject822);
384 5cdb1798 2005-10-29 devnull m->unixdate = promote(&nm->unixdate);
390 5cdb1798 2005-10-29 devnull parse(Message *m, int justmime, Mailbox *mb, int addfrom)
392 5cdb1798 2005-10-29 devnull parseheaders(m, justmime, mb, addfrom);
393 5cdb1798 2005-10-29 devnull parsebody(m, mb);
396 5cdb1798 2005-10-29 devnull static void
397 5cdb1798 2005-10-29 devnull parseattachments(Message *m, Mailbox *mb)
399 5cdb1798 2005-10-29 devnull Message *nm, **l;
400 5cdb1798 2005-10-29 devnull char *p, *x;
402 cbeb0b26 2006-04-01 devnull /* if there's a boundary, recurse... */
403 5cdb1798 2005-10-29 devnull if(m->boundary != nil){
404 5cdb1798 2005-10-29 devnull p = m->body;
405 5cdb1798 2005-10-29 devnull nm = nil;
406 5cdb1798 2005-10-29 devnull l = &m->part;
407 5cdb1798 2005-10-29 devnull for(;;){
408 5cdb1798 2005-10-29 devnull x = strstr(p, s_to_c(m->boundary));
410 5cdb1798 2005-10-29 devnull /* no boundary, we're done */
411 5cdb1798 2005-10-29 devnull if(x == nil){
412 5cdb1798 2005-10-29 devnull if(nm != nil)
413 5cdb1798 2005-10-29 devnull nm->rbend = nm->bend = nm->end = m->bend;
417 5cdb1798 2005-10-29 devnull /* boundary must be at the start of a line */
418 5cdb1798 2005-10-29 devnull if(x != m->body && *(x-1) != '\n'){
419 5cdb1798 2005-10-29 devnull p = x+1;
420 5cdb1798 2005-10-29 devnull continue;
423 5cdb1798 2005-10-29 devnull if(nm != nil)
424 5cdb1798 2005-10-29 devnull nm->rbend = nm->bend = nm->end = x;
425 5cdb1798 2005-10-29 devnull x += strlen(s_to_c(m->boundary));
427 5cdb1798 2005-10-29 devnull /* is this the last part? ignore anything after it */
428 5cdb1798 2005-10-29 devnull if(strncmp(x, "--", 2) == 0)
431 5cdb1798 2005-10-29 devnull p = strchr(x, '\n');
432 5cdb1798 2005-10-29 devnull if(p == nil)
434 5cdb1798 2005-10-29 devnull nm = newmessage(m);
435 5cdb1798 2005-10-29 devnull nm->start = nm->header = nm->body = nm->rbody = ++p;
436 5cdb1798 2005-10-29 devnull nm->mheader = nm->header;
437 5cdb1798 2005-10-29 devnull *l = nm;
438 5cdb1798 2005-10-29 devnull l = &nm->next;
440 5cdb1798 2005-10-29 devnull for(nm = m->part; nm != nil; nm = nm->next)
441 5cdb1798 2005-10-29 devnull parse(nm, 1, mb, 0);
445 cbeb0b26 2006-04-01 devnull /* if we've got an rfc822 message, recurse... */
446 5cdb1798 2005-10-29 devnull if(strcmp(s_to_c(m->type), "message/rfc822") == 0){
447 5cdb1798 2005-10-29 devnull nm = newmessage(m);
448 5cdb1798 2005-10-29 devnull m->part = nm;
449 5cdb1798 2005-10-29 devnull nm->start = nm->header = nm->body = nm->rbody = m->body;
450 5cdb1798 2005-10-29 devnull nm->end = nm->bend = nm->rbend = m->bend;
451 5cdb1798 2005-10-29 devnull parse(nm, 0, mb, 0);
456 5cdb1798 2005-10-29 devnull * pick up a header line
458 5cdb1798 2005-10-29 devnull static int
459 5cdb1798 2005-10-29 devnull headerline(char **pp, String *hl)
461 5cdb1798 2005-10-29 devnull char *p, *x;
463 5cdb1798 2005-10-29 devnull s_reset(hl);
464 5cdb1798 2005-10-29 devnull p = *pp;
465 5cdb1798 2005-10-29 devnull x = strpbrk(p, ":\n");
466 5cdb1798 2005-10-29 devnull if(x == nil || *x == '\n')
467 5cdb1798 2005-10-29 devnull return 0;
468 5cdb1798 2005-10-29 devnull for(;;){
469 5cdb1798 2005-10-29 devnull x = strchr(p, '\n');
470 5cdb1798 2005-10-29 devnull if(x == nil)
471 5cdb1798 2005-10-29 devnull x = p + strlen(p);
472 5cdb1798 2005-10-29 devnull s_nappend(hl, p, x-p);
474 5cdb1798 2005-10-29 devnull if(*p != '\n' || *++p != ' ' && *p != '\t')
476 5cdb1798 2005-10-29 devnull while(*p == ' ' || *p == '\t')
478 5cdb1798 2005-10-29 devnull s_putc(hl, ' ');
480 5cdb1798 2005-10-29 devnull *pp = p;
481 5cdb1798 2005-10-29 devnull return 1;
484 5cdb1798 2005-10-29 devnull static String*
485 5cdb1798 2005-10-29 devnull addr822(char *p)
487 5cdb1798 2005-10-29 devnull String *s, *list;
488 5cdb1798 2005-10-29 devnull int incomment, addrdone, inanticomment, quoted;
492 5cdb1798 2005-10-29 devnull list = s_new();
493 5cdb1798 2005-10-29 devnull s = s_new();
494 5cdb1798 2005-10-29 devnull quoted = incomment = addrdone = inanticomment = 0;
496 5cdb1798 2005-10-29 devnull for(; *p; p++){
499 cbeb0b26 2006-04-01 devnull /* whitespace is ignored */
500 5cdb1798 2005-10-29 devnull if(!quoted && isspace(c) || c == '\r')
501 5cdb1798 2005-10-29 devnull continue;
503 cbeb0b26 2006-04-01 devnull /* strings are always treated as atoms */
504 5cdb1798 2005-10-29 devnull if(!quoted && c == '"'){
505 5cdb1798 2005-10-29 devnull if(!addrdone && !incomment)
506 5cdb1798 2005-10-29 devnull s_putc(s, c);
507 5cdb1798 2005-10-29 devnull for(p++; *p; p++){
508 5cdb1798 2005-10-29 devnull if(!addrdone && !incomment)
509 5cdb1798 2005-10-29 devnull s_putc(s, *p);
510 5cdb1798 2005-10-29 devnull if(!quoted && *p == '"')
512 5cdb1798 2005-10-29 devnull if(*p == '\\')
513 5cdb1798 2005-10-29 devnull quoted = 1;
515 5cdb1798 2005-10-29 devnull quoted = 0;
517 5cdb1798 2005-10-29 devnull if(*p == 0)
519 5cdb1798 2005-10-29 devnull quoted = 0;
520 5cdb1798 2005-10-29 devnull continue;
523 cbeb0b26 2006-04-01 devnull /* ignore everything in an expicit comment */
524 5cdb1798 2005-10-29 devnull if(!quoted && c == '('){
525 5cdb1798 2005-10-29 devnull incomment = 1;
526 5cdb1798 2005-10-29 devnull continue;
528 5cdb1798 2005-10-29 devnull if(incomment){
529 5cdb1798 2005-10-29 devnull if(!quoted && c == ')')
530 5cdb1798 2005-10-29 devnull incomment = 0;
531 5cdb1798 2005-10-29 devnull quoted = 0;
532 5cdb1798 2005-10-29 devnull continue;
535 cbeb0b26 2006-04-01 devnull /* anticomments makes everything outside of them comments */
536 5cdb1798 2005-10-29 devnull if(!quoted && c == '<' && !inanticomment){
537 5cdb1798 2005-10-29 devnull inanticomment = 1;
538 5cdb1798 2005-10-29 devnull s = s_reset(s);
539 5cdb1798 2005-10-29 devnull continue;
541 5cdb1798 2005-10-29 devnull if(!quoted && c == '>' && inanticomment){
542 5cdb1798 2005-10-29 devnull addrdone = 1;
543 5cdb1798 2005-10-29 devnull inanticomment = 0;
544 5cdb1798 2005-10-29 devnull continue;
547 cbeb0b26 2006-04-01 devnull /* commas separate addresses */
548 5cdb1798 2005-10-29 devnull if(!quoted && c == ',' && !inanticomment){
549 5cdb1798 2005-10-29 devnull s_terminate(s);
550 5cdb1798 2005-10-29 devnull addrdone = 0;
551 5cdb1798 2005-10-29 devnull if(n++ != 0)
552 5cdb1798 2005-10-29 devnull s_append(list, " ");
553 5cdb1798 2005-10-29 devnull s_append(list, s_to_c(s));
554 5cdb1798 2005-10-29 devnull s = s_reset(s);
555 5cdb1798 2005-10-29 devnull continue;
558 cbeb0b26 2006-04-01 devnull /* what's left is part of the address */
559 5cdb1798 2005-10-29 devnull s_putc(s, c);
561 cbeb0b26 2006-04-01 devnull /* quoted characters are recognized only as characters */
562 5cdb1798 2005-10-29 devnull if(c == '\\')
563 5cdb1798 2005-10-29 devnull quoted = 1;
565 5cdb1798 2005-10-29 devnull quoted = 0;
569 5cdb1798 2005-10-29 devnull if(*s_to_c(s) != 0){
570 5cdb1798 2005-10-29 devnull s_terminate(s);
571 5cdb1798 2005-10-29 devnull if(n++ != 0)
572 5cdb1798 2005-10-29 devnull s_append(list, " ");
573 5cdb1798 2005-10-29 devnull s_append(list, s_to_c(s));
575 5cdb1798 2005-10-29 devnull s_free(s);
577 5cdb1798 2005-10-29 devnull if(n == 0){
578 5cdb1798 2005-10-29 devnull s_free(list);
579 5cdb1798 2005-10-29 devnull return nil;
581 5cdb1798 2005-10-29 devnull return list;
584 5cdb1798 2005-10-29 devnull static void
585 5cdb1798 2005-10-29 devnull to822(Message *m, Header *h, char *p)
587 5cdb1798 2005-10-29 devnull p += strlen(h->type);
588 5cdb1798 2005-10-29 devnull s_free(m->to822);
589 5cdb1798 2005-10-29 devnull m->to822 = addr822(p);
592 5cdb1798 2005-10-29 devnull static void
593 5cdb1798 2005-10-29 devnull cc822(Message *m, Header *h, char *p)
595 5cdb1798 2005-10-29 devnull p += strlen(h->type);
596 5cdb1798 2005-10-29 devnull s_free(m->cc822);
597 5cdb1798 2005-10-29 devnull m->cc822 = addr822(p);
600 5cdb1798 2005-10-29 devnull static void
601 5cdb1798 2005-10-29 devnull bcc822(Message *m, Header *h, char *p)
603 5cdb1798 2005-10-29 devnull p += strlen(h->type);
604 5cdb1798 2005-10-29 devnull s_free(m->bcc822);
605 5cdb1798 2005-10-29 devnull m->bcc822 = addr822(p);
608 5cdb1798 2005-10-29 devnull static void
609 5cdb1798 2005-10-29 devnull from822(Message *m, Header *h, char *p)
611 5cdb1798 2005-10-29 devnull p += strlen(h->type);
612 5cdb1798 2005-10-29 devnull s_free(m->from822);
613 5cdb1798 2005-10-29 devnull m->from822 = addr822(p);
616 5cdb1798 2005-10-29 devnull static void
617 5cdb1798 2005-10-29 devnull sender822(Message *m, Header *h, char *p)
619 5cdb1798 2005-10-29 devnull p += strlen(h->type);
620 5cdb1798 2005-10-29 devnull s_free(m->sender822);
621 5cdb1798 2005-10-29 devnull m->sender822 = addr822(p);
624 5cdb1798 2005-10-29 devnull static void
625 5cdb1798 2005-10-29 devnull replyto822(Message *m, Header *h, char *p)
627 5cdb1798 2005-10-29 devnull p += strlen(h->type);
628 5cdb1798 2005-10-29 devnull s_free(m->replyto822);
629 5cdb1798 2005-10-29 devnull m->replyto822 = addr822(p);
632 5cdb1798 2005-10-29 devnull static void
633 5cdb1798 2005-10-29 devnull mimeversion(Message *m, Header *h, char *p)
635 5cdb1798 2005-10-29 devnull p += strlen(h->type);
636 5cdb1798 2005-10-29 devnull s_free(m->mimeversion);
637 5cdb1798 2005-10-29 devnull m->mimeversion = addr822(p);
640 5cdb1798 2005-10-29 devnull static void
641 5cdb1798 2005-10-29 devnull killtrailingwhite(char *p)
643 5cdb1798 2005-10-29 devnull char *e;
645 5cdb1798 2005-10-29 devnull e = p + strlen(p) - 1;
646 5cdb1798 2005-10-29 devnull while(e > p && isspace(*e))
647 5cdb1798 2005-10-29 devnull *e-- = 0;
650 5cdb1798 2005-10-29 devnull static void
651 5cdb1798 2005-10-29 devnull date822(Message *m, Header *h, char *p)
653 5cdb1798 2005-10-29 devnull p += strlen(h->type);
654 5cdb1798 2005-10-29 devnull p = skipwhite(p);
655 5cdb1798 2005-10-29 devnull s_free(m->date822);
656 5cdb1798 2005-10-29 devnull m->date822 = s_copy(p);
657 5cdb1798 2005-10-29 devnull p = s_to_c(m->date822);
658 5cdb1798 2005-10-29 devnull killtrailingwhite(p);
661 5cdb1798 2005-10-29 devnull static void
662 5cdb1798 2005-10-29 devnull subject822(Message *m, Header *h, char *p)
664 5cdb1798 2005-10-29 devnull p += strlen(h->type);
665 5cdb1798 2005-10-29 devnull p = skipwhite(p);
666 5cdb1798 2005-10-29 devnull s_free(m->subject822);
667 5cdb1798 2005-10-29 devnull m->subject822 = s_copy(p);
668 5cdb1798 2005-10-29 devnull p = s_to_c(m->subject822);
669 5cdb1798 2005-10-29 devnull killtrailingwhite(p);
672 5cdb1798 2005-10-29 devnull static void
673 5cdb1798 2005-10-29 devnull inreplyto822(Message *m, Header *h, char *p)
675 5cdb1798 2005-10-29 devnull p += strlen(h->type);
676 5cdb1798 2005-10-29 devnull p = skipwhite(p);
677 5cdb1798 2005-10-29 devnull s_free(m->inreplyto822);
678 5cdb1798 2005-10-29 devnull m->inreplyto822 = s_copy(p);
679 5cdb1798 2005-10-29 devnull p = s_to_c(m->inreplyto822);
680 5cdb1798 2005-10-29 devnull killtrailingwhite(p);
683 5cdb1798 2005-10-29 devnull static void
684 5cdb1798 2005-10-29 devnull messageid822(Message *m, Header *h, char *p)
686 5cdb1798 2005-10-29 devnull p += strlen(h->type);
687 5cdb1798 2005-10-29 devnull p = skipwhite(p);
688 5cdb1798 2005-10-29 devnull s_free(m->messageid822);
689 5cdb1798 2005-10-29 devnull m->messageid822 = s_copy(p);
690 5cdb1798 2005-10-29 devnull p = s_to_c(m->messageid822);
691 5cdb1798 2005-10-29 devnull killtrailingwhite(p);
694 5cdb1798 2005-10-29 devnull static int
695 5cdb1798 2005-10-29 devnull isattribute(char **pp, char *attr)
697 5cdb1798 2005-10-29 devnull char *p;
700 5cdb1798 2005-10-29 devnull n = strlen(attr);
701 5cdb1798 2005-10-29 devnull p = *pp;
702 5cdb1798 2005-10-29 devnull if(cistrncmp(p, attr, n) != 0)
703 5cdb1798 2005-10-29 devnull return 0;
705 5cdb1798 2005-10-29 devnull while(*p == ' ')
707 5cdb1798 2005-10-29 devnull if(*p++ != '=')
708 5cdb1798 2005-10-29 devnull return 0;
709 5cdb1798 2005-10-29 devnull while(*p == ' ')
711 5cdb1798 2005-10-29 devnull *pp = p;
712 5cdb1798 2005-10-29 devnull return 1;
715 5cdb1798 2005-10-29 devnull static void
716 5cdb1798 2005-10-29 devnull ctype(Message *m, Header *h, char *p)
718 5cdb1798 2005-10-29 devnull String *s;
720 5cdb1798 2005-10-29 devnull p += h->len;
721 5cdb1798 2005-10-29 devnull p = skipwhite(p);
723 5cdb1798 2005-10-29 devnull p = getstring(p, m->type, 1);
725 5cdb1798 2005-10-29 devnull while(*p){
726 5cdb1798 2005-10-29 devnull if(isattribute(&p, "boundary")){
727 5cdb1798 2005-10-29 devnull s = s_new();
728 5cdb1798 2005-10-29 devnull p = getstring(p, s, 0);
729 5cdb1798 2005-10-29 devnull m->boundary = s_reset(m->boundary);
730 5cdb1798 2005-10-29 devnull s_append(m->boundary, "--");
731 5cdb1798 2005-10-29 devnull s_append(m->boundary, s_to_c(s));
732 5cdb1798 2005-10-29 devnull s_free(s);
733 5cdb1798 2005-10-29 devnull } else if(cistrncmp(p, "multipart", 9) == 0){
735 5cdb1798 2005-10-29 devnull * the first unbounded part of a multipart message,
736 5cdb1798 2005-10-29 devnull * the preamble, is not displayed or saved
738 5cdb1798 2005-10-29 devnull } else if(isattribute(&p, "name")){
739 5cdb1798 2005-10-29 devnull if(m->filename == nil)
740 5cdb1798 2005-10-29 devnull setfilename(m, p);
741 5cdb1798 2005-10-29 devnull } else if(isattribute(&p, "charset")){
742 5cdb1798 2005-10-29 devnull p = getstring(p, s_reset(m->charset), 0);
745 5cdb1798 2005-10-29 devnull p = skiptosemi(p);
749 5cdb1798 2005-10-29 devnull static void
750 5cdb1798 2005-10-29 devnull cencoding(Message *m, Header *h, char *p)
752 5cdb1798 2005-10-29 devnull p += h->len;
753 5cdb1798 2005-10-29 devnull p = skipwhite(p);
754 5cdb1798 2005-10-29 devnull if(cistrncmp(p, "base64", 6) == 0)
755 5cdb1798 2005-10-29 devnull m->encoding = Ebase64;
756 5cdb1798 2005-10-29 devnull else if(cistrncmp(p, "quoted-printable", 16) == 0)
757 5cdb1798 2005-10-29 devnull m->encoding = Equoted;
760 5cdb1798 2005-10-29 devnull static void
761 5cdb1798 2005-10-29 devnull cdisposition(Message *m, Header *h, char *p)
763 5cdb1798 2005-10-29 devnull p += h->len;
764 5cdb1798 2005-10-29 devnull p = skipwhite(p);
765 5cdb1798 2005-10-29 devnull while(*p){
766 5cdb1798 2005-10-29 devnull if(cistrncmp(p, "inline", 6) == 0){
767 5cdb1798 2005-10-29 devnull m->disposition = Dinline;
768 5cdb1798 2005-10-29 devnull } else if(cistrncmp(p, "attachment", 10) == 0){
769 5cdb1798 2005-10-29 devnull m->disposition = Dfile;
770 5cdb1798 2005-10-29 devnull } else if(cistrncmp(p, "filename=", 9) == 0){
772 5cdb1798 2005-10-29 devnull setfilename(m, p);
774 5cdb1798 2005-10-29 devnull p = skiptosemi(p);
779 5cdb1798 2005-10-29 devnull ulong msgallocd, msgfreed;
781 5cdb1798 2005-10-29 devnull Message*
782 5cdb1798 2005-10-29 devnull newmessage(Message *parent)
784 5cdb1798 2005-10-29 devnull /* static int id; jpc */
785 5cdb1798 2005-10-29 devnull Message *m;
787 5cdb1798 2005-10-29 devnull msgallocd++;
789 5cdb1798 2005-10-29 devnull m = emalloc(sizeof(*m));
790 5cdb1798 2005-10-29 devnull memset(m, 0, sizeof(*m));
791 5cdb1798 2005-10-29 devnull m->disposition = Dnone;
792 5cdb1798 2005-10-29 devnull m->type = s_copy("text/plain");
793 5cdb1798 2005-10-29 devnull m->charset = s_copy("iso-8859-1");
794 5cdb1798 2005-10-29 devnull m->id = newid();
795 5cdb1798 2005-10-29 devnull if(parent)
796 5cdb1798 2005-10-29 devnull sprint(m->name, "%d", ++(parent->subname));
797 5cdb1798 2005-10-29 devnull if(parent == nil)
798 5cdb1798 2005-10-29 devnull parent = m;
799 5cdb1798 2005-10-29 devnull m->whole = parent;
800 5cdb1798 2005-10-29 devnull m->hlen = -1;
801 5cdb1798 2005-10-29 devnull return m;
804 cbeb0b26 2006-04-01 devnull /* delete a message from a mailbox */
806 5cdb1798 2005-10-29 devnull delmessage(Mailbox *mb, Message *m)
808 5cdb1798 2005-10-29 devnull Message **l;
811 5cdb1798 2005-10-29 devnull mb->vers++;
812 5cdb1798 2005-10-29 devnull msgfreed++;
814 5cdb1798 2005-10-29 devnull if(m->whole != m){
815 cbeb0b26 2006-04-01 devnull /* unchain from parent */
816 5cdb1798 2005-10-29 devnull for(l = &m->whole->part; *l && *l != m; l = &(*l)->next)
818 5cdb1798 2005-10-29 devnull if(*l != nil)
819 5cdb1798 2005-10-29 devnull *l = m->next;
821 cbeb0b26 2006-04-01 devnull /* clear out of name lookup hash table */
822 5cdb1798 2005-10-29 devnull if(m->whole->whole == m->whole)
823 5cdb1798 2005-10-29 devnull hfree(PATH(mb->id, Qmbox), m->name);
825 5cdb1798 2005-10-29 devnull hfree(PATH(m->whole->id, Qdir), m->name);
826 5cdb1798 2005-10-29 devnull for(i = 0; i < Qmax; i++)
827 5cdb1798 2005-10-29 devnull hfree(PATH(m->id, Qdir), dirtab[i]);
830 5cdb1798 2005-10-29 devnull /* recurse through sub-parts */
831 5cdb1798 2005-10-29 devnull while(m->part)
832 5cdb1798 2005-10-29 devnull delmessage(mb, m->part);
834 5cdb1798 2005-10-29 devnull /* free memory */
835 5cdb1798 2005-10-29 devnull if(m->mallocd)
836 5cdb1798 2005-10-29 devnull free(m->start);
837 5cdb1798 2005-10-29 devnull if(m->hallocd)
838 5cdb1798 2005-10-29 devnull free(m->header);
839 5cdb1798 2005-10-29 devnull if(m->ballocd)
840 5cdb1798 2005-10-29 devnull free(m->body);
841 5cdb1798 2005-10-29 devnull s_free(m->unixfrom);
842 5cdb1798 2005-10-29 devnull s_free(m->unixdate);
843 5cdb1798 2005-10-29 devnull s_free(m->unixheader);
844 5cdb1798 2005-10-29 devnull s_free(m->from822);
845 5cdb1798 2005-10-29 devnull s_free(m->sender822);
846 5cdb1798 2005-10-29 devnull s_free(m->to822);
847 5cdb1798 2005-10-29 devnull s_free(m->bcc822);
848 5cdb1798 2005-10-29 devnull s_free(m->cc822);
849 5cdb1798 2005-10-29 devnull s_free(m->replyto822);
850 5cdb1798 2005-10-29 devnull s_free(m->date822);
851 5cdb1798 2005-10-29 devnull s_free(m->inreplyto822);
852 5cdb1798 2005-10-29 devnull s_free(m->subject822);
853 5cdb1798 2005-10-29 devnull s_free(m->messageid822);
854 5cdb1798 2005-10-29 devnull s_free(m->addrs);
855 5cdb1798 2005-10-29 devnull s_free(m->mimeversion);
856 5cdb1798 2005-10-29 devnull s_free(m->sdigest);
857 5cdb1798 2005-10-29 devnull s_free(m->boundary);
858 5cdb1798 2005-10-29 devnull s_free(m->type);
859 5cdb1798 2005-10-29 devnull s_free(m->charset);
860 5cdb1798 2005-10-29 devnull s_free(m->filename);
862 5cdb1798 2005-10-29 devnull free(m);
865 cbeb0b26 2006-04-01 devnull /* mark messages (identified by path) for deletion */
867 5cdb1798 2005-10-29 devnull delmessages(int ac, char **av)
869 5cdb1798 2005-10-29 devnull Mailbox *mb;
870 5cdb1798 2005-10-29 devnull Message *m;
871 5cdb1798 2005-10-29 devnull int i, needwrite;
873 5cdb1798 2005-10-29 devnull qlock(&mbllock);
874 5cdb1798 2005-10-29 devnull for(mb = mbl; mb != nil; mb = mb->next)
875 5cdb1798 2005-10-29 devnull if(strcmp(av[0], mb->name) == 0){
876 5cdb1798 2005-10-29 devnull qlock(&mb->ql);
879 5cdb1798 2005-10-29 devnull qunlock(&mbllock);
880 5cdb1798 2005-10-29 devnull if(mb == nil)
883 5cdb1798 2005-10-29 devnull needwrite = 0;
884 5cdb1798 2005-10-29 devnull for(i = 1; i < ac; i++){
885 5cdb1798 2005-10-29 devnull for(m = mb->root->part; m != nil; m = m->next)
886 5cdb1798 2005-10-29 devnull if(strcmp(m->name, av[i]) == 0){
887 5cdb1798 2005-10-29 devnull if(!m->deleted){
888 5cdb1798 2005-10-29 devnull mailplumb(mb, m, 1);
889 5cdb1798 2005-10-29 devnull needwrite = 1;
890 5cdb1798 2005-10-29 devnull m->deleted = 1;
891 5cdb1798 2005-10-29 devnull logmsg("deleting", m);
896 5cdb1798 2005-10-29 devnull if(needwrite)
897 5cdb1798 2005-10-29 devnull syncmbox(mb, 1);
898 5cdb1798 2005-10-29 devnull qunlock(&mb->ql);
902 5cdb1798 2005-10-29 devnull * the following are called with the mailbox qlocked
905 5cdb1798 2005-10-29 devnull msgincref(Message *m)
907 5cdb1798 2005-10-29 devnull m->refs++;
910 5cdb1798 2005-10-29 devnull msgdecref(Mailbox *mb, Message *m)
912 5cdb1798 2005-10-29 devnull m->refs--;
913 5cdb1798 2005-10-29 devnull if(m->refs == 0 && m->deleted)
914 5cdb1798 2005-10-29 devnull syncmbox(mb, 1);
918 5cdb1798 2005-10-29 devnull * the following are called with mbllock'd
921 5cdb1798 2005-10-29 devnull mboxincref(Mailbox *mb)
923 5cdb1798 2005-10-29 devnull assert(mb->refs > 0);
924 5cdb1798 2005-10-29 devnull mb->refs++;
927 5cdb1798 2005-10-29 devnull mboxdecref(Mailbox *mb)
929 5cdb1798 2005-10-29 devnull assert(mb->refs > 0);
930 5cdb1798 2005-10-29 devnull qlock(&mb->ql);
931 5cdb1798 2005-10-29 devnull mb->refs--;
932 5cdb1798 2005-10-29 devnull if(mb->refs == 0){
933 5cdb1798 2005-10-29 devnull delmessage(mb, mb->root);
934 5cdb1798 2005-10-29 devnull if(mb->ctl)
935 5cdb1798 2005-10-29 devnull hfree(PATH(mb->id, Qmbox), "ctl");
936 5cdb1798 2005-10-29 devnull if(mb->close)
937 5cdb1798 2005-10-29 devnull (*mb->close)(mb);
938 5cdb1798 2005-10-29 devnull free(mb);
940 5cdb1798 2005-10-29 devnull qunlock(&mb->ql);
944 5cdb1798 2005-10-29 devnull cistrncmp(char *a, char *b, int n)
946 5cdb1798 2005-10-29 devnull while(n-- > 0){
947 5cdb1798 2005-10-29 devnull if(tolower(*a++) != tolower(*b++))
948 5cdb1798 2005-10-29 devnull return -1;
950 5cdb1798 2005-10-29 devnull return 0;
954 5cdb1798 2005-10-29 devnull cistrcmp(char *a, char *b)
956 5cdb1798 2005-10-29 devnull for(;;){
957 5cdb1798 2005-10-29 devnull if(tolower(*a) != tolower(*b++))
958 5cdb1798 2005-10-29 devnull return -1;
959 5cdb1798 2005-10-29 devnull if(*a++ == 0)
962 5cdb1798 2005-10-29 devnull return 0;
965 5cdb1798 2005-10-29 devnull static char*
966 5cdb1798 2005-10-29 devnull skipwhite(char *p)
968 5cdb1798 2005-10-29 devnull while(isspace(*p))
970 5cdb1798 2005-10-29 devnull return p;
973 5cdb1798 2005-10-29 devnull static char*
974 5cdb1798 2005-10-29 devnull skiptosemi(char *p)
976 5cdb1798 2005-10-29 devnull while(*p && *p != ';')
978 5cdb1798 2005-10-29 devnull while(*p == ';' || isspace(*p))
980 5cdb1798 2005-10-29 devnull return p;
983 5cdb1798 2005-10-29 devnull static char*
984 5cdb1798 2005-10-29 devnull getstring(char *p, String *s, int dolower)
986 5cdb1798 2005-10-29 devnull s = s_reset(s);
987 5cdb1798 2005-10-29 devnull p = skipwhite(p);
988 5cdb1798 2005-10-29 devnull if(*p == '"'){
990 5cdb1798 2005-10-29 devnull for(;*p && *p != '"'; p++)
991 5cdb1798 2005-10-29 devnull if(dolower)
992 5cdb1798 2005-10-29 devnull s_putc(s, tolower(*p));
994 5cdb1798 2005-10-29 devnull s_putc(s, *p);
995 5cdb1798 2005-10-29 devnull if(*p == '"')
997 5cdb1798 2005-10-29 devnull s_terminate(s);
999 5cdb1798 2005-10-29 devnull return p;
1002 5cdb1798 2005-10-29 devnull for(; *p && !isspace(*p) && *p != ';'; p++)
1003 5cdb1798 2005-10-29 devnull if(dolower)
1004 5cdb1798 2005-10-29 devnull s_putc(s, tolower(*p));
1006 5cdb1798 2005-10-29 devnull s_putc(s, *p);
1007 5cdb1798 2005-10-29 devnull s_terminate(s);
1009 5cdb1798 2005-10-29 devnull return p;
1012 5cdb1798 2005-10-29 devnull static void
1013 5cdb1798 2005-10-29 devnull setfilename(Message *m, char *p)
1015 5cdb1798 2005-10-29 devnull m->filename = s_reset(m->filename);
1016 5cdb1798 2005-10-29 devnull getstring(p, m->filename, 0);
1017 5cdb1798 2005-10-29 devnull for(p = s_to_c(m->filename); *p; p++)
1018 5cdb1798 2005-10-29 devnull if(*p == ' ' || *p == '\t' || *p == ';')
1019 5cdb1798 2005-10-29 devnull *p = '_';
1023 cbeb0b26 2006-04-01 devnull /* undecode message body */
1026 5cdb1798 2005-10-29 devnull decode(Message *m)
1028 5cdb1798 2005-10-29 devnull int i, len;
1029 5cdb1798 2005-10-29 devnull char *x;
1031 5cdb1798 2005-10-29 devnull if(m->decoded)
1032 5cdb1798 2005-10-29 devnull return;
1033 5cdb1798 2005-10-29 devnull switch(m->encoding){
1034 5cdb1798 2005-10-29 devnull case Ebase64:
1035 5cdb1798 2005-10-29 devnull len = m->bend - m->body;
1036 cbeb0b26 2006-04-01 devnull i = (len*3)/4+1; /* room for max chars + null */
1037 5cdb1798 2005-10-29 devnull x = emalloc(i);
1038 5cdb1798 2005-10-29 devnull len = dec64((uchar*)x, i, m->body, len);
1039 5cdb1798 2005-10-29 devnull if(m->ballocd)
1040 5cdb1798 2005-10-29 devnull free(m->body);
1041 5cdb1798 2005-10-29 devnull m->body = x;
1042 5cdb1798 2005-10-29 devnull m->bend = x + len;
1043 5cdb1798 2005-10-29 devnull m->ballocd = 1;
1045 5cdb1798 2005-10-29 devnull case Equoted:
1046 5cdb1798 2005-10-29 devnull len = m->bend - m->body;
1047 cbeb0b26 2006-04-01 devnull x = emalloc(len+2); /* room for null and possible extra nl */
1048 5cdb1798 2005-10-29 devnull len = decquoted(x, m->body, m->bend);
1049 5cdb1798 2005-10-29 devnull if(m->ballocd)
1050 5cdb1798 2005-10-29 devnull free(m->body);
1051 5cdb1798 2005-10-29 devnull m->body = x;
1052 5cdb1798 2005-10-29 devnull m->bend = x + len;
1053 5cdb1798 2005-10-29 devnull m->ballocd = 1;
1055 5cdb1798 2005-10-29 devnull default:
1058 5cdb1798 2005-10-29 devnull m->decoded = 1;
1061 cbeb0b26 2006-04-01 devnull /* convert latin1 to utf */
1063 5cdb1798 2005-10-29 devnull convert(Message *m)
1065 5cdb1798 2005-10-29 devnull int len;
1066 5cdb1798 2005-10-29 devnull char *x;
1068 cbeb0b26 2006-04-01 devnull /* don't convert if we're not a leaf, not text, or already converted */
1069 5cdb1798 2005-10-29 devnull if(m->converted)
1070 5cdb1798 2005-10-29 devnull return;
1071 5cdb1798 2005-10-29 devnull if(m->part != nil)
1072 5cdb1798 2005-10-29 devnull return;
1073 5cdb1798 2005-10-29 devnull if(cistrncmp(s_to_c(m->type), "text", 4) != 0)
1074 5cdb1798 2005-10-29 devnull return;
1076 5cdb1798 2005-10-29 devnull if(cistrcmp(s_to_c(m->charset), "us-ascii") == 0 ||
1077 5cdb1798 2005-10-29 devnull cistrcmp(s_to_c(m->charset), "iso-8859-1") == 0){
1078 5cdb1798 2005-10-29 devnull len = is8bit(m);
1079 5cdb1798 2005-10-29 devnull if(len > 0){
1080 5cdb1798 2005-10-29 devnull len = 2*len + m->bend - m->body + 1;
1081 5cdb1798 2005-10-29 devnull x = emalloc(len);
1082 5cdb1798 2005-10-29 devnull len = latin1toutf(x, m->body, m->bend);
1083 5cdb1798 2005-10-29 devnull if(m->ballocd)
1084 5cdb1798 2005-10-29 devnull free(m->body);
1085 5cdb1798 2005-10-29 devnull m->body = x;
1086 5cdb1798 2005-10-29 devnull m->bend = x + len;
1087 5cdb1798 2005-10-29 devnull m->ballocd = 1;
1089 5cdb1798 2005-10-29 devnull } else if(cistrcmp(s_to_c(m->charset), "iso-8859-2") == 0){
1090 5cdb1798 2005-10-29 devnull len = xtoutf("8859-2", &x, m->body, m->bend);
1091 5cdb1798 2005-10-29 devnull if(len != 0){
1092 5cdb1798 2005-10-29 devnull if(m->ballocd)
1093 5cdb1798 2005-10-29 devnull free(m->body);
1094 5cdb1798 2005-10-29 devnull m->body = x;
1095 5cdb1798 2005-10-29 devnull m->bend = x + len;
1096 5cdb1798 2005-10-29 devnull m->ballocd = 1;
1098 5cdb1798 2005-10-29 devnull } else if(cistrcmp(s_to_c(m->charset), "iso-8859-15") == 0){
1099 5cdb1798 2005-10-29 devnull len = xtoutf("8859-15", &x, m->body, m->bend);
1100 5cdb1798 2005-10-29 devnull if(len != 0){
1101 5cdb1798 2005-10-29 devnull if(m->ballocd)
1102 5cdb1798 2005-10-29 devnull free(m->body);
1103 5cdb1798 2005-10-29 devnull m->body = x;
1104 5cdb1798 2005-10-29 devnull m->bend = x + len;
1105 5cdb1798 2005-10-29 devnull m->ballocd = 1;
1107 5cdb1798 2005-10-29 devnull } else if(cistrcmp(s_to_c(m->charset), "big5") == 0){
1108 5cdb1798 2005-10-29 devnull len = xtoutf("big5", &x, m->body, m->bend);
1109 5cdb1798 2005-10-29 devnull if(len != 0){
1110 5cdb1798 2005-10-29 devnull if(m->ballocd)
1111 5cdb1798 2005-10-29 devnull free(m->body);
1112 5cdb1798 2005-10-29 devnull m->body = x;
1113 5cdb1798 2005-10-29 devnull m->bend = x + len;
1114 5cdb1798 2005-10-29 devnull m->ballocd = 1;
1116 5cdb1798 2005-10-29 devnull } else if(cistrcmp(s_to_c(m->charset), "iso-2022-jp") == 0){
1117 5cdb1798 2005-10-29 devnull len = xtoutf("jis", &x, m->body, m->bend);
1118 5cdb1798 2005-10-29 devnull if(len != 0){
1119 5cdb1798 2005-10-29 devnull if(m->ballocd)
1120 5cdb1798 2005-10-29 devnull free(m->body);
1121 5cdb1798 2005-10-29 devnull m->body = x;
1122 5cdb1798 2005-10-29 devnull m->bend = x + len;
1123 5cdb1798 2005-10-29 devnull m->ballocd = 1;
1125 5cdb1798 2005-10-29 devnull } else if(cistrcmp(s_to_c(m->charset), "windows-1257") == 0
1126 5cdb1798 2005-10-29 devnull || cistrcmp(s_to_c(m->charset), "windows-1252") == 0){
1127 5cdb1798 2005-10-29 devnull len = is8bit(m);
1128 5cdb1798 2005-10-29 devnull if(len > 0){
1129 5cdb1798 2005-10-29 devnull len = 2*len + m->bend - m->body + 1;
1130 5cdb1798 2005-10-29 devnull x = emalloc(len);
1131 5cdb1798 2005-10-29 devnull len = windows1257toutf(x, m->body, m->bend);
1132 5cdb1798 2005-10-29 devnull if(m->ballocd)
1133 5cdb1798 2005-10-29 devnull free(m->body);
1134 5cdb1798 2005-10-29 devnull m->body = x;
1135 5cdb1798 2005-10-29 devnull m->bend = x + len;
1136 5cdb1798 2005-10-29 devnull m->ballocd = 1;
1138 5cdb1798 2005-10-29 devnull } else if(cistrcmp(s_to_c(m->charset), "windows-1251") == 0){
1139 5cdb1798 2005-10-29 devnull len = xtoutf("cp1251", &x, m->body, m->bend);
1140 5cdb1798 2005-10-29 devnull if(len != 0){
1141 5cdb1798 2005-10-29 devnull if(m->ballocd)
1142 5cdb1798 2005-10-29 devnull free(m->body);
1143 5cdb1798 2005-10-29 devnull m->body = x;
1144 5cdb1798 2005-10-29 devnull m->bend = x + len;
1145 5cdb1798 2005-10-29 devnull m->ballocd = 1;
1147 5cdb1798 2005-10-29 devnull } else if(cistrcmp(s_to_c(m->charset), "koi8-r") == 0){
1148 5cdb1798 2005-10-29 devnull len = xtoutf("koi8", &x, m->body, m->bend);
1149 5cdb1798 2005-10-29 devnull if(len != 0){
1150 5cdb1798 2005-10-29 devnull if(m->ballocd)
1151 5cdb1798 2005-10-29 devnull free(m->body);
1152 5cdb1798 2005-10-29 devnull m->body = x;
1153 5cdb1798 2005-10-29 devnull m->bend = x + len;
1154 5cdb1798 2005-10-29 devnull m->ballocd = 1;
1158 5cdb1798 2005-10-29 devnull m->converted = 1;
1163 5cdb1798 2005-10-29 devnull Self= 1,
1166 5cdb1798 2005-10-29 devnull uchar tableqp[256];
1168 5cdb1798 2005-10-29 devnull static void
1169 5cdb1798 2005-10-29 devnull initquoted(void)
1173 5cdb1798 2005-10-29 devnull memset(tableqp, 0, 256);
1174 5cdb1798 2005-10-29 devnull for(c = ' '; c <= '<'; c++)
1175 5cdb1798 2005-10-29 devnull tableqp[c] = Self;
1176 5cdb1798 2005-10-29 devnull for(c = '>'; c <= '~'; c++)
1177 5cdb1798 2005-10-29 devnull tableqp[c] = Self;
1178 5cdb1798 2005-10-29 devnull tableqp['\t'] = Self;
1179 5cdb1798 2005-10-29 devnull tableqp['='] = Hex;
1182 5cdb1798 2005-10-29 devnull static int
1183 5cdb1798 2005-10-29 devnull hex2int(int x)
1185 5cdb1798 2005-10-29 devnull if(x >= '0' && x <= '9')
1186 5cdb1798 2005-10-29 devnull return x - '0';
1187 5cdb1798 2005-10-29 devnull if(x >= 'A' && x <= 'F')
1188 5cdb1798 2005-10-29 devnull return (x - 'A') + 10;
1189 5cdb1798 2005-10-29 devnull if(x >= 'a' && x <= 'f')
1190 5cdb1798 2005-10-29 devnull return (x - 'a') + 10;
1191 5cdb1798 2005-10-29 devnull return 0;
1194 5cdb1798 2005-10-29 devnull static char*
1195 5cdb1798 2005-10-29 devnull decquotedline(char *out, char *in, char *e)
1197 5cdb1798 2005-10-29 devnull int c, soft;
1199 5cdb1798 2005-10-29 devnull /* dump trailing white space */
1200 5cdb1798 2005-10-29 devnull while(e >= in && (*e == ' ' || *e == '\t' || *e == '\r' || *e == '\n'))
1203 5cdb1798 2005-10-29 devnull /* trailing '=' means no newline */
1204 5cdb1798 2005-10-29 devnull if(*e == '='){
1205 5cdb1798 2005-10-29 devnull soft = 1;
1208 5cdb1798 2005-10-29 devnull soft = 0;
1210 5cdb1798 2005-10-29 devnull while(in <= e){
1211 5cdb1798 2005-10-29 devnull c = (*in++) & 0xff;
1212 5cdb1798 2005-10-29 devnull switch(tableqp[c]){
1213 5cdb1798 2005-10-29 devnull case Self:
1214 5cdb1798 2005-10-29 devnull *out++ = c;
1216 5cdb1798 2005-10-29 devnull case Hex:
1217 5cdb1798 2005-10-29 devnull c = hex2int(*in++)<<4;
1218 5cdb1798 2005-10-29 devnull c |= hex2int(*in++);
1219 5cdb1798 2005-10-29 devnull *out++ = c;
1223 5cdb1798 2005-10-29 devnull if(!soft)
1224 5cdb1798 2005-10-29 devnull *out++ = '\n';
1225 5cdb1798 2005-10-29 devnull *out = 0;
1227 5cdb1798 2005-10-29 devnull return out;
1231 5cdb1798 2005-10-29 devnull decquoted(char *out, char *in, char *e)
1233 5cdb1798 2005-10-29 devnull char *p, *nl;
1235 5cdb1798 2005-10-29 devnull if(tableqp[' '] == 0)
1236 5cdb1798 2005-10-29 devnull initquoted();
1238 5cdb1798 2005-10-29 devnull p = out;
1239 5cdb1798 2005-10-29 devnull while((nl = strchr(in, '\n')) != nil && nl < e){
1240 5cdb1798 2005-10-29 devnull p = decquotedline(p, in, nl);
1241 5cdb1798 2005-10-29 devnull in = nl + 1;
1243 5cdb1798 2005-10-29 devnull if(in < e)
1244 5cdb1798 2005-10-29 devnull p = decquotedline(p, in, e-1);
1246 cbeb0b26 2006-04-01 devnull /* make sure we end with a new line */
1247 5cdb1798 2005-10-29 devnull if(*(p-1) != '\n'){
1248 5cdb1798 2005-10-29 devnull *p++ = '\n';
1249 5cdb1798 2005-10-29 devnull *p = 0;
1252 5cdb1798 2005-10-29 devnull return p - out;
1255 5cdb1798 2005-10-29 devnull #if 0 /* jpc */
1256 5cdb1798 2005-10-29 devnull static char*
1257 5cdb1798 2005-10-29 devnull lowercase(char *p)
1259 5cdb1798 2005-10-29 devnull char *op;
1262 5cdb1798 2005-10-29 devnull for(op = p; c = *p; p++)
1263 5cdb1798 2005-10-29 devnull if(isupper(c))
1264 5cdb1798 2005-10-29 devnull *p = tolower(c);
1265 5cdb1798 2005-10-29 devnull return op;
1270 5cdb1798 2005-10-29 devnull * return number of 8 bit characters
1272 5cdb1798 2005-10-29 devnull static int
1273 5cdb1798 2005-10-29 devnull is8bit(Message *m)
1275 5cdb1798 2005-10-29 devnull int count = 0;
1276 5cdb1798 2005-10-29 devnull char *p;
1278 5cdb1798 2005-10-29 devnull for(p = m->body; p < m->bend; p++)
1279 5cdb1798 2005-10-29 devnull if(*p & 0x80)
1280 5cdb1798 2005-10-29 devnull count++;
1281 5cdb1798 2005-10-29 devnull return count;
1284 cbeb0b26 2006-04-01 devnull /* translate latin1 directly since it fits neatly in utf */
1286 5cdb1798 2005-10-29 devnull latin1toutf(char *out, char *in, char *e)
1288 5cdb1798 2005-10-29 devnull Rune r;
1289 5cdb1798 2005-10-29 devnull char *p;
1291 5cdb1798 2005-10-29 devnull p = out;
1292 5cdb1798 2005-10-29 devnull for(; in < e; in++){
1293 5cdb1798 2005-10-29 devnull r = (*in) & 0xff;
1294 5cdb1798 2005-10-29 devnull p += runetochar(p, &r);
1296 5cdb1798 2005-10-29 devnull *p = 0;
1297 5cdb1798 2005-10-29 devnull return p - out;
1300 cbeb0b26 2006-04-01 devnull /* translate any thing else using the tcs program */
1302 5cdb1798 2005-10-29 devnull xtoutf(char *charset, char **out, char *in, char *e)
1304 5cdb1798 2005-10-29 devnull char *av[4];
1305 5cdb1798 2005-10-29 devnull int totcs[2];
1306 5cdb1798 2005-10-29 devnull int fromtcs[2];
1307 5cdb1798 2005-10-29 devnull int n, len, sofar;
1308 5cdb1798 2005-10-29 devnull char *p;
1310 5cdb1798 2005-10-29 devnull len = e-in+1;
1311 5cdb1798 2005-10-29 devnull sofar = 0;
1312 5cdb1798 2005-10-29 devnull *out = p = malloc(len+1);
1313 5cdb1798 2005-10-29 devnull if(p == nil)
1314 5cdb1798 2005-10-29 devnull return 0;
1316 5cdb1798 2005-10-29 devnull av[0] = charset;
1317 5cdb1798 2005-10-29 devnull av[1] = "-f";
1318 5cdb1798 2005-10-29 devnull av[2] = charset;
1319 5cdb1798 2005-10-29 devnull av[3] = 0;
1320 5cdb1798 2005-10-29 devnull if(pipe(totcs) < 0)
1321 5cdb1798 2005-10-29 devnull return 0;
1322 5cdb1798 2005-10-29 devnull if(pipe(fromtcs) < 0){
1323 5cdb1798 2005-10-29 devnull close(totcs[0]); close(totcs[1]);
1324 5cdb1798 2005-10-29 devnull return 0;
1326 5cdb1798 2005-10-29 devnull switch(rfork(RFPROC|RFFDG|RFNOWAIT)){
1327 5cdb1798 2005-10-29 devnull case -1:
1328 5cdb1798 2005-10-29 devnull close(fromtcs[0]); close(fromtcs[1]);
1329 5cdb1798 2005-10-29 devnull close(totcs[0]); close(totcs[1]);
1330 5cdb1798 2005-10-29 devnull return 0;
1331 5cdb1798 2005-10-29 devnull case 0:
1332 5cdb1798 2005-10-29 devnull close(fromtcs[0]); close(totcs[1]);
1333 5cdb1798 2005-10-29 devnull dup(fromtcs[1], 1);
1334 5cdb1798 2005-10-29 devnull dup(totcs[0], 0);
1335 5cdb1798 2005-10-29 devnull close(fromtcs[1]); close(totcs[0]);
1336 5cdb1798 2005-10-29 devnull dup(open("/dev/null", OWRITE), 2);
1337 cbeb0b26 2006-04-01 devnull /*jpc exec("/bin/tcs", av); */
1338 5cdb1798 2005-10-29 devnull exec(unsharp("#9/bin/tcs"), av);
1339 5cdb1798 2005-10-29 devnull /* _exits(0); */
1340 5cdb1798 2005-10-29 devnull threadexits(nil);
1341 5cdb1798 2005-10-29 devnull default:
1342 5cdb1798 2005-10-29 devnull close(fromtcs[1]); close(totcs[0]);
1343 5cdb1798 2005-10-29 devnull switch(rfork(RFPROC|RFFDG|RFNOWAIT)){
1344 5cdb1798 2005-10-29 devnull case -1:
1345 5cdb1798 2005-10-29 devnull close(fromtcs[0]); close(totcs[1]);
1346 5cdb1798 2005-10-29 devnull return 0;
1347 5cdb1798 2005-10-29 devnull case 0:
1348 5cdb1798 2005-10-29 devnull close(fromtcs[0]);
1349 5cdb1798 2005-10-29 devnull while(in < e){
1350 5cdb1798 2005-10-29 devnull n = write(totcs[1], in, e-in);
1351 5cdb1798 2005-10-29 devnull if(n <= 0)
1353 5cdb1798 2005-10-29 devnull in += n;
1355 5cdb1798 2005-10-29 devnull close(totcs[1]);
1356 5cdb1798 2005-10-29 devnull /* _exits(0); */
1357 5cdb1798 2005-10-29 devnull threadexits(nil);
1358 5cdb1798 2005-10-29 devnull default:
1359 5cdb1798 2005-10-29 devnull close(totcs[1]);
1360 5cdb1798 2005-10-29 devnull for(;;){
1361 5cdb1798 2005-10-29 devnull n = read(fromtcs[0], &p[sofar], len-sofar);
1362 5cdb1798 2005-10-29 devnull if(n <= 0)
1364 5cdb1798 2005-10-29 devnull sofar += n;
1365 5cdb1798 2005-10-29 devnull p[sofar] = 0;
1366 5cdb1798 2005-10-29 devnull if(sofar == len){
1367 5cdb1798 2005-10-29 devnull len += 1024;
1368 5cdb1798 2005-10-29 devnull *out = p = realloc(p, len+1);
1369 5cdb1798 2005-10-29 devnull if(p == nil)
1370 5cdb1798 2005-10-29 devnull return 0;
1373 5cdb1798 2005-10-29 devnull close(fromtcs[0]);
1378 5cdb1798 2005-10-29 devnull return sofar;
1382 5cdb1798 2005-10-29 devnull Winstart= 0x7f,
1383 cbeb0b26 2006-04-01 devnull Winend= 0x9f
1386 5cdb1798 2005-10-29 devnull Rune winchars[] = {
1388 5cdb1798 2005-10-29 devnull L'•', L'•', L'‚', L'ƒ', L'„', L'…', L'†', L'‡',
1389 5cdb1798 2005-10-29 devnull L'ˆ', L'‰', L'Š', L'‹', L'Œ', L'•', L'•', L'•',
1390 5cdb1798 2005-10-29 devnull L'•', L'‘', L'’', L'“', L'”', L'•', L'–', L'—',
1391 cbeb0b26 2006-04-01 devnull L'˜', L'™', L'š', L'›', L'œ', L'•', L'•', L'Ÿ'
1395 5cdb1798 2005-10-29 devnull windows1257toutf(char *out, char *in, char *e)
1397 5cdb1798 2005-10-29 devnull Rune r;
1398 5cdb1798 2005-10-29 devnull char *p;
1400 5cdb1798 2005-10-29 devnull p = out;
1401 5cdb1798 2005-10-29 devnull for(; in < e; in++){
1402 5cdb1798 2005-10-29 devnull r = (*in) & 0xff;
1403 5cdb1798 2005-10-29 devnull if(r >= 0x7f && r <= 0x9f)
1404 5cdb1798 2005-10-29 devnull r = winchars[r-0x7f];
1405 5cdb1798 2005-10-29 devnull p += runetochar(p, &r);
1407 5cdb1798 2005-10-29 devnull *p = 0;
1408 5cdb1798 2005-10-29 devnull return p - out;
1412 5cdb1798 2005-10-29 devnull emalloc(ulong n)
1414 5cdb1798 2005-10-29 devnull void *p;
1416 5cdb1798 2005-10-29 devnull p = mallocz(n, 1);
1417 5cdb1798 2005-10-29 devnull if(!p){
1418 5cdb1798 2005-10-29 devnull fprint(2, "%s: out of memory alloc %lud\n", argv0, n);
1419 5cdb1798 2005-10-29 devnull threadexits("out of memory");
1421 5cdb1798 2005-10-29 devnull setmalloctag(p, getcallerpc(&n));
1422 5cdb1798 2005-10-29 devnull return p;
1426 5cdb1798 2005-10-29 devnull erealloc(void *p, ulong n)
1428 5cdb1798 2005-10-29 devnull if(n == 0)
1430 5cdb1798 2005-10-29 devnull p = realloc(p, n);
1431 5cdb1798 2005-10-29 devnull if(!p){
1432 5cdb1798 2005-10-29 devnull fprint(2, "%s: out of memory realloc %lud\n", argv0, n);
1433 5cdb1798 2005-10-29 devnull threadexits("out of memory");
1435 5cdb1798 2005-10-29 devnull setrealloctag(p, getcallerpc(&p));
1436 5cdb1798 2005-10-29 devnull return p;
1440 5cdb1798 2005-10-29 devnull mailplumb(Mailbox *mb, Message *m, int delete)
1442 5cdb1798 2005-10-29 devnull Plumbmsg p;
1443 5cdb1798 2005-10-29 devnull Plumbattr a[7];
1444 5cdb1798 2005-10-29 devnull char buf[256];
1445 5cdb1798 2005-10-29 devnull int ai;
1446 5cdb1798 2005-10-29 devnull char lenstr[10], *from, *subject, *date;
1447 5cdb1798 2005-10-29 devnull static int fd = -1;
1449 5cdb1798 2005-10-29 devnull if(m->subject822 == nil)
1450 5cdb1798 2005-10-29 devnull subject = "";
1452 5cdb1798 2005-10-29 devnull subject = s_to_c(m->subject822);
1454 5cdb1798 2005-10-29 devnull if(m->from822 != nil)
1455 5cdb1798 2005-10-29 devnull from = s_to_c(m->from822);
1456 5cdb1798 2005-10-29 devnull else if(m->unixfrom != nil)
1457 5cdb1798 2005-10-29 devnull from = s_to_c(m->unixfrom);
1459 5cdb1798 2005-10-29 devnull from = "";
1461 5cdb1798 2005-10-29 devnull if(m->unixdate != nil)
1462 5cdb1798 2005-10-29 devnull date = s_to_c(m->unixdate);
1464 5cdb1798 2005-10-29 devnull date = "";
1466 5cdb1798 2005-10-29 devnull sprint(lenstr, "%ld", m->end-m->start);
1468 5cdb1798 2005-10-29 devnull if(biffing && !delete)
1469 5cdb1798 2005-10-29 devnull print("[ %s / %s / %s ]\n", from, subject, lenstr);
1471 5cdb1798 2005-10-29 devnull if(!plumbing)
1472 5cdb1798 2005-10-29 devnull return;
1474 5cdb1798 2005-10-29 devnull if(fd < 0)
1475 5cdb1798 2005-10-29 devnull fd = plumbopen("send", OWRITE);
1476 5cdb1798 2005-10-29 devnull if(fd < 0)
1477 5cdb1798 2005-10-29 devnull return;
1479 5cdb1798 2005-10-29 devnull p.src = "mailfs";
1480 5cdb1798 2005-10-29 devnull p.dst = "seemail";
1481 5cdb1798 2005-10-29 devnull p.wdir = "/mail/fs";
1482 5cdb1798 2005-10-29 devnull p.type = "text";
1484 5cdb1798 2005-10-29 devnull ai = 0;
1485 5cdb1798 2005-10-29 devnull a[ai].name = "filetype";
1486 5cdb1798 2005-10-29 devnull a[ai].value = "mail";
1488 5cdb1798 2005-10-29 devnull a[++ai].name = "sender";
1489 5cdb1798 2005-10-29 devnull a[ai].value = from;
1490 5cdb1798 2005-10-29 devnull a[ai-1].next = &a[ai];
1492 5cdb1798 2005-10-29 devnull a[++ai].name = "length";
1493 5cdb1798 2005-10-29 devnull a[ai].value = lenstr;
1494 5cdb1798 2005-10-29 devnull a[ai-1].next = &a[ai];
1496 5cdb1798 2005-10-29 devnull a[++ai].name = "mailtype";
1497 5cdb1798 2005-10-29 devnull a[ai].value = delete?"delete":"new";
1498 5cdb1798 2005-10-29 devnull a[ai-1].next = &a[ai];
1500 5cdb1798 2005-10-29 devnull a[++ai].name = "date";
1501 5cdb1798 2005-10-29 devnull a[ai].value = date;
1502 5cdb1798 2005-10-29 devnull a[ai-1].next = &a[ai];
1504 5cdb1798 2005-10-29 devnull if(m->sdigest){
1505 5cdb1798 2005-10-29 devnull a[++ai].name = "digest";
1506 5cdb1798 2005-10-29 devnull a[ai].value = s_to_c(m->sdigest);
1507 5cdb1798 2005-10-29 devnull a[ai-1].next = &a[ai];
1510 5cdb1798 2005-10-29 devnull a[ai].next = nil;
1512 5cdb1798 2005-10-29 devnull p.attr = a;
1513 5cdb1798 2005-10-29 devnull snprint(buf, sizeof(buf), "%s/%s/%s",
1514 5cdb1798 2005-10-29 devnull mntpt, mb->name, m->name);
1515 5cdb1798 2005-10-29 devnull p.ndata = strlen(buf);
1516 5cdb1798 2005-10-29 devnull p.data = buf;
1518 5cdb1798 2005-10-29 devnull plumbsend(fd, &p);
1522 cbeb0b26 2006-04-01 devnull /* count the number of lines in the body (for imap4) */
1525 5cdb1798 2005-10-29 devnull countlines(Message *m)
1528 5cdb1798 2005-10-29 devnull char *p;
1531 5cdb1798 2005-10-29 devnull for(p = strchr(m->rbody, '\n'); p != nil && p < m->rbend; p = strchr(p+1, '\n'))
1533 5cdb1798 2005-10-29 devnull sprint(m->lines, "%d", i);
1536 5cdb1798 2005-10-29 devnull char *LOG = "fs";
1539 5cdb1798 2005-10-29 devnull logmsg(char *s, Message *m)
1541 5cdb1798 2005-10-29 devnull int pid;
1543 5cdb1798 2005-10-29 devnull if(!logging)
1544 5cdb1798 2005-10-29 devnull return;
1545 5cdb1798 2005-10-29 devnull pid = getpid();
1546 5cdb1798 2005-10-29 devnull if(m == nil)
1547 5cdb1798 2005-10-29 devnull syslog(0, LOG, "%s.%d: %s", user, pid, s);
1549 5cdb1798 2005-10-29 devnull syslog(0, LOG, "%s.%d: %s msg from %s digest %s",
1550 5cdb1798 2005-10-29 devnull user, pid, s,
1551 5cdb1798 2005-10-29 devnull m->from822 ? s_to_c(m->from822) : "?",
1552 5cdb1798 2005-10-29 devnull s_to_c(m->sdigest));
1556 5cdb1798 2005-10-29 devnull * squeeze nulls out of the body
1558 5cdb1798 2005-10-29 devnull static void
1559 5cdb1798 2005-10-29 devnull nullsqueeze(Message *m)
1561 5cdb1798 2005-10-29 devnull char *p, *q;
1563 5cdb1798 2005-10-29 devnull q = memchr(m->body, 0, m->end-m->body);
1564 5cdb1798 2005-10-29 devnull if(q == nil)
1565 5cdb1798 2005-10-29 devnull return;
1567 5cdb1798 2005-10-29 devnull for(p = m->body; q < m->end; q++){
1568 5cdb1798 2005-10-29 devnull if(*q == 0)
1569 5cdb1798 2005-10-29 devnull continue;
1570 5cdb1798 2005-10-29 devnull *p++ = *q;
1572 5cdb1798 2005-10-29 devnull m->bend = m->rbend = m->end = p;
1577 cbeb0b26 2006-04-01 devnull /* convert an RFC822 date into a Unix style date */
1578 cbeb0b26 2006-04-01 devnull /* for when the Unix From line isn't there (e.g. POP3). */
1579 cbeb0b26 2006-04-01 devnull /* enough client programs depend on having a Unix date */
1580 cbeb0b26 2006-04-01 devnull /* that it's easiest to write this conversion code once, right here. */
1582 cbeb0b26 2006-04-01 devnull /* people don't follow RFC822 particularly closely, */
1583 cbeb0b26 2006-04-01 devnull /* so we use strtotm, which is a bunch of heuristics. */
1586 5cdb1798 2005-10-29 devnull extern int strtotm(char*, Tm*);
1587 5cdb1798 2005-10-29 devnull String*
1588 5cdb1798 2005-10-29 devnull date822tounix(char *s)
1590 5cdb1798 2005-10-29 devnull char *p, *q;
1593 5cdb1798 2005-10-29 devnull if(strtotm(s, &tm) < 0)
1594 5cdb1798 2005-10-29 devnull return nil;
1596 5cdb1798 2005-10-29 devnull p = asctime(&tm);
1597 5cdb1798 2005-10-29 devnull if(q = strchr(p, '\n'))
1598 5cdb1798 2005-10-29 devnull *q = '\0';
1599 5cdb1798 2005-10-29 devnull return s_copy(p);