Blame


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"
7 5cdb1798 2005-10-29 devnull
8 5cdb1798 2005-10-29 devnull extern char* dirtab[]; /* jpc */
9 5cdb1798 2005-10-29 devnull
10 5cdb1798 2005-10-29 devnull typedef struct Header Header;
11 5cdb1798 2005-10-29 devnull
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*);
15 5cdb1798 2005-10-29 devnull int len;
16 5cdb1798 2005-10-29 devnull };
17 5cdb1798 2005-10-29 devnull
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*);
34 5cdb1798 2005-10-29 devnull enum
35 5cdb1798 2005-10-29 devnull {
36 5cdb1798 2005-10-29 devnull Mhead= 11, /* offset of first mime header */
37 5cdb1798 2005-10-29 devnull };
38 5cdb1798 2005-10-29 devnull
39 5cdb1798 2005-10-29 devnull Header head[] =
40 5cdb1798 2005-10-29 devnull {
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, },
52 5cdb1798 2005-10-29 devnull
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, },
56 cbeb0b26 2006-04-01 devnull { 0, }
57 5cdb1798 2005-10-29 devnull };
58 5cdb1798 2005-10-29 devnull
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*);
72 5cdb1798 2005-10-29 devnull
73 5cdb1798 2005-10-29 devnull int debug;
74 5cdb1798 2005-10-29 devnull
75 5cdb1798 2005-10-29 devnull char *Enotme = "path not served by this file server";
76 5cdb1798 2005-10-29 devnull
77 5cdb1798 2005-10-29 devnull enum
78 5cdb1798 2005-10-29 devnull {
79 cbeb0b26 2006-04-01 devnull Chunksize = 1024
80 5cdb1798 2005-10-29 devnull };
81 5cdb1798 2005-10-29 devnull
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
86 5cdb1798 2005-10-29 devnull };
87 5cdb1798 2005-10-29 devnull
88 5cdb1798 2005-10-29 devnull char*
89 5cdb1798 2005-10-29 devnull syncmbox(Mailbox *mb, int doplumb)
90 5cdb1798 2005-10-29 devnull {
91 5cdb1798 2005-10-29 devnull return (*mb->sync)(mb, doplumb);
92 5cdb1798 2005-10-29 devnull }
93 5cdb1798 2005-10-29 devnull
94 5cdb1798 2005-10-29 devnull /* create a new mailbox */
95 5cdb1798 2005-10-29 devnull char*
96 5cdb1798 2005-10-29 devnull newmbox(char *path, char *name, int std)
97 5cdb1798 2005-10-29 devnull {
98 5cdb1798 2005-10-29 devnull Mailbox *mb, **l;
99 5cdb1798 2005-10-29 devnull char *p, *rv;
100 5cdb1798 2005-10-29 devnull int i;
101 5cdb1798 2005-10-29 devnull
102 5cdb1798 2005-10-29 devnull initheaders();
103 5cdb1798 2005-10-29 devnull
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;
110 5cdb1798 2005-10-29 devnull else
111 5cdb1798 2005-10-29 devnull p++;
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";
115 5cdb1798 2005-10-29 devnull }
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);
119 5cdb1798 2005-10-29 devnull }
120 5cdb1798 2005-10-29 devnull
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)
125 5cdb1798 2005-10-29 devnull break;
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";
129 5cdb1798 2005-10-29 devnull }
130 5cdb1798 2005-10-29 devnull
131 cbeb0b26 2006-04-01 devnull /* on error, give up */
132 5cdb1798 2005-10-29 devnull if(rv){
133 5cdb1798 2005-10-29 devnull free(mb);
134 5cdb1798 2005-10-29 devnull return rv;
135 5cdb1798 2005-10-29 devnull }
136 5cdb1798 2005-10-29 devnull
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;
143 5cdb1798 2005-10-29 devnull else
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;
150 5cdb1798 2005-10-29 devnull }
151 5cdb1798 2005-10-29 devnull }
152 5cdb1798 2005-10-29 devnull
153 cbeb0b26 2006-04-01 devnull /* always try locking */
154 5cdb1798 2005-10-29 devnull mb->dolock = 1;
155 5cdb1798 2005-10-29 devnull
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);
163 5cdb1798 2005-10-29 devnull
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);
168 5cdb1798 2005-10-29 devnull }
169 5cdb1798 2005-10-29 devnull rv = syncmbox(mb, 0);
170 5cdb1798 2005-10-29 devnull qunlock(&mb->ql);
171 5cdb1798 2005-10-29 devnull
172 5cdb1798 2005-10-29 devnull return rv;
173 5cdb1798 2005-10-29 devnull }
174 5cdb1798 2005-10-29 devnull
175 cbeb0b26 2006-04-01 devnull /* close the named mailbox */
176 5cdb1798 2005-10-29 devnull void
177 5cdb1798 2005-10-29 devnull freembox(char *name)
178 5cdb1798 2005-10-29 devnull {
179 5cdb1798 2005-10-29 devnull Mailbox **l, *mb;
180 5cdb1798 2005-10-29 devnull
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);
187 5cdb1798 2005-10-29 devnull break;
188 5cdb1798 2005-10-29 devnull }
189 5cdb1798 2005-10-29 devnull }
190 5cdb1798 2005-10-29 devnull hfree(PATH(0, Qtop), name);
191 5cdb1798 2005-10-29 devnull qunlock(&mbllock);
192 5cdb1798 2005-10-29 devnull }
193 5cdb1798 2005-10-29 devnull
194 5cdb1798 2005-10-29 devnull static void
195 5cdb1798 2005-10-29 devnull initheaders(void)
196 5cdb1798 2005-10-29 devnull {
197 5cdb1798 2005-10-29 devnull Header *h;
198 5cdb1798 2005-10-29 devnull static int already;
199 5cdb1798 2005-10-29 devnull
200 5cdb1798 2005-10-29 devnull if(already)
201 5cdb1798 2005-10-29 devnull return;
202 5cdb1798 2005-10-29 devnull already = 1;
203 5cdb1798 2005-10-29 devnull
204 5cdb1798 2005-10-29 devnull for(h = head; h->type != nil; h++)
205 5cdb1798 2005-10-29 devnull h->len = strlen(h->type);
206 5cdb1798 2005-10-29 devnull }
207 5cdb1798 2005-10-29 devnull
208 5cdb1798 2005-10-29 devnull /*
209 5cdb1798 2005-10-29 devnull * parse a Unix style header
210 5cdb1798 2005-10-29 devnull */
211 5cdb1798 2005-10-29 devnull void
212 5cdb1798 2005-10-29 devnull parseunix(Message *m)
213 5cdb1798 2005-10-29 devnull {
214 5cdb1798 2005-10-29 devnull char *p;
215 5cdb1798 2005-10-29 devnull String *h;
216 5cdb1798 2005-10-29 devnull
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);
222 5cdb1798 2005-10-29 devnull
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);
225 5cdb1798 2005-10-29 devnull
226 5cdb1798 2005-10-29 devnull s_free(h);
227 5cdb1798 2005-10-29 devnull }
228 5cdb1798 2005-10-29 devnull
229 5cdb1798 2005-10-29 devnull /*
230 5cdb1798 2005-10-29 devnull * parse a message
231 5cdb1798 2005-10-29 devnull */
232 5cdb1798 2005-10-29 devnull void
233 5cdb1798 2005-10-29 devnull parseheaders(Message *m, int justmime, Mailbox *mb, int addfrom)
234 5cdb1798 2005-10-29 devnull {
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;
238 5cdb1798 2005-10-29 devnull int i;
239 5cdb1798 2005-10-29 devnull
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);
246 5cdb1798 2005-10-29 devnull }
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);
250 5cdb1798 2005-10-29 devnull
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];
257 5cdb1798 2005-10-29 devnull else
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));
262 5cdb1798 2005-10-29 devnull break;
263 5cdb1798 2005-10-29 devnull }
264 5cdb1798 2005-10-29 devnull }
265 5cdb1798 2005-10-29 devnull s_reset(hl);
266 5cdb1798 2005-10-29 devnull }
267 5cdb1798 2005-10-29 devnull s_free(hl);
268 5cdb1798 2005-10-29 devnull
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;
275 5cdb1798 2005-10-29 devnull }
276 5cdb1798 2005-10-29 devnull if(*p == '\n')
277 5cdb1798 2005-10-29 devnull p++;
278 5cdb1798 2005-10-29 devnull m->rbody = m->body = p;
279 5cdb1798 2005-10-29 devnull
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);
284 5cdb1798 2005-10-29 devnull
285 cbeb0b26 2006-04-01 devnull /* */
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. */
291 cbeb0b26 2006-04-01 devnull /* */
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;
297 5cdb1798 2005-10-29 devnull }
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){
303 5cdb1798 2005-10-29 devnull p = q;
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')
306 5cdb1798 2005-10-29 devnull break;
307 5cdb1798 2005-10-29 devnull p++;
308 5cdb1798 2005-10-29 devnull }
309 5cdb1798 2005-10-29 devnull if(p){
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';
313 5cdb1798 2005-10-29 devnull }
314 5cdb1798 2005-10-29 devnull }
315 5cdb1798 2005-10-29 devnull }
316 5cdb1798 2005-10-29 devnull
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));
320 5cdb1798 2005-10-29 devnull }
321 5cdb1798 2005-10-29 devnull
322 5cdb1798 2005-10-29 devnull if(m->unixheader != nil)
323 5cdb1798 2005-10-29 devnull s_free(m->unixheader);
324 5cdb1798 2005-10-29 devnull
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;
331 5cdb1798 2005-10-29 devnull return;
332 5cdb1798 2005-10-29 devnull }
333 5cdb1798 2005-10-29 devnull
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));
339 5cdb1798 2005-10-29 devnull else
340 5cdb1798 2005-10-29 devnull s_append(m->unixheader, "???");
341 5cdb1798 2005-10-29 devnull
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));
345 5cdb1798 2005-10-29 devnull else
346 5cdb1798 2005-10-29 devnull s_append(m->unixheader, "Thu Jan 1 00:00:00 GMT 1970");
347 5cdb1798 2005-10-29 devnull
348 5cdb1798 2005-10-29 devnull s_append(m->unixheader, "\n");
349 5cdb1798 2005-10-29 devnull }
350 5cdb1798 2005-10-29 devnull
351 5cdb1798 2005-10-29 devnull String*
352 5cdb1798 2005-10-29 devnull promote(String **sp)
353 5cdb1798 2005-10-29 devnull {
354 5cdb1798 2005-10-29 devnull String *s;
355 5cdb1798 2005-10-29 devnull
356 5cdb1798 2005-10-29 devnull if(*sp != nil)
357 5cdb1798 2005-10-29 devnull s = s_clone(*sp);
358 5cdb1798 2005-10-29 devnull else
359 5cdb1798 2005-10-29 devnull s = nil;
360 5cdb1798 2005-10-29 devnull return s;
361 5cdb1798 2005-10-29 devnull }
362 5cdb1798 2005-10-29 devnull
363 5cdb1798 2005-10-29 devnull void
364 5cdb1798 2005-10-29 devnull parsebody(Message *m, Mailbox *mb)
365 5cdb1798 2005-10-29 devnull {
366 5cdb1798 2005-10-29 devnull Message *nm;
367 5cdb1798 2005-10-29 devnull
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;
375 5cdb1798 2005-10-29 devnull
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);
385 5cdb1798 2005-10-29 devnull }
386 5cdb1798 2005-10-29 devnull }
387 5cdb1798 2005-10-29 devnull }
388 5cdb1798 2005-10-29 devnull
389 5cdb1798 2005-10-29 devnull void
390 5cdb1798 2005-10-29 devnull parse(Message *m, int justmime, Mailbox *mb, int addfrom)
391 5cdb1798 2005-10-29 devnull {
392 5cdb1798 2005-10-29 devnull parseheaders(m, justmime, mb, addfrom);
393 5cdb1798 2005-10-29 devnull parsebody(m, mb);
394 5cdb1798 2005-10-29 devnull }
395 5cdb1798 2005-10-29 devnull
396 5cdb1798 2005-10-29 devnull static void
397 5cdb1798 2005-10-29 devnull parseattachments(Message *m, Mailbox *mb)
398 5cdb1798 2005-10-29 devnull {
399 5cdb1798 2005-10-29 devnull Message *nm, **l;
400 5cdb1798 2005-10-29 devnull char *p, *x;
401 5cdb1798 2005-10-29 devnull
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));
409 5cdb1798 2005-10-29 devnull
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;
414 5cdb1798 2005-10-29 devnull break;
415 5cdb1798 2005-10-29 devnull }
416 5cdb1798 2005-10-29 devnull
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;
421 5cdb1798 2005-10-29 devnull }
422 5cdb1798 2005-10-29 devnull
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));
426 5cdb1798 2005-10-29 devnull
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)
429 5cdb1798 2005-10-29 devnull break;
430 5cdb1798 2005-10-29 devnull
431 5cdb1798 2005-10-29 devnull p = strchr(x, '\n');
432 5cdb1798 2005-10-29 devnull if(p == nil)
433 5cdb1798 2005-10-29 devnull break;
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;
439 5cdb1798 2005-10-29 devnull }
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);
442 5cdb1798 2005-10-29 devnull return;
443 5cdb1798 2005-10-29 devnull }
444 5cdb1798 2005-10-29 devnull
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);
452 5cdb1798 2005-10-29 devnull }
453 5cdb1798 2005-10-29 devnull }
454 5cdb1798 2005-10-29 devnull
455 5cdb1798 2005-10-29 devnull /*
456 5cdb1798 2005-10-29 devnull * pick up a header line
457 5cdb1798 2005-10-29 devnull */
458 5cdb1798 2005-10-29 devnull static int
459 5cdb1798 2005-10-29 devnull headerline(char **pp, String *hl)
460 5cdb1798 2005-10-29 devnull {
461 5cdb1798 2005-10-29 devnull char *p, *x;
462 5cdb1798 2005-10-29 devnull
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);
473 5cdb1798 2005-10-29 devnull p = x;
474 5cdb1798 2005-10-29 devnull if(*p != '\n' || *++p != ' ' && *p != '\t')
475 5cdb1798 2005-10-29 devnull break;
476 5cdb1798 2005-10-29 devnull while(*p == ' ' || *p == '\t')
477 5cdb1798 2005-10-29 devnull p++;
478 5cdb1798 2005-10-29 devnull s_putc(hl, ' ');
479 5cdb1798 2005-10-29 devnull }
480 5cdb1798 2005-10-29 devnull *pp = p;
481 5cdb1798 2005-10-29 devnull return 1;
482 5cdb1798 2005-10-29 devnull }
483 5cdb1798 2005-10-29 devnull
484 5cdb1798 2005-10-29 devnull static String*
485 5cdb1798 2005-10-29 devnull addr822(char *p)
486 5cdb1798 2005-10-29 devnull {
487 5cdb1798 2005-10-29 devnull String *s, *list;
488 5cdb1798 2005-10-29 devnull int incomment, addrdone, inanticomment, quoted;
489 5cdb1798 2005-10-29 devnull int n;
490 5cdb1798 2005-10-29 devnull int c;
491 5cdb1798 2005-10-29 devnull
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;
495 5cdb1798 2005-10-29 devnull n = 0;
496 5cdb1798 2005-10-29 devnull for(; *p; p++){
497 5cdb1798 2005-10-29 devnull c = *p;
498 5cdb1798 2005-10-29 devnull
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;
502 5cdb1798 2005-10-29 devnull
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 == '"')
511 5cdb1798 2005-10-29 devnull break;
512 5cdb1798 2005-10-29 devnull if(*p == '\\')
513 5cdb1798 2005-10-29 devnull quoted = 1;
514 5cdb1798 2005-10-29 devnull else
515 5cdb1798 2005-10-29 devnull quoted = 0;
516 5cdb1798 2005-10-29 devnull }
517 5cdb1798 2005-10-29 devnull if(*p == 0)
518 5cdb1798 2005-10-29 devnull break;
519 5cdb1798 2005-10-29 devnull quoted = 0;
520 5cdb1798 2005-10-29 devnull continue;
521 5cdb1798 2005-10-29 devnull }
522 5cdb1798 2005-10-29 devnull
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;
527 5cdb1798 2005-10-29 devnull }
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;
533 5cdb1798 2005-10-29 devnull }
534 5cdb1798 2005-10-29 devnull
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;
540 5cdb1798 2005-10-29 devnull }
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;
545 5cdb1798 2005-10-29 devnull }
546 5cdb1798 2005-10-29 devnull
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;
556 5cdb1798 2005-10-29 devnull }
557 5cdb1798 2005-10-29 devnull
558 cbeb0b26 2006-04-01 devnull /* what's left is part of the address */
559 5cdb1798 2005-10-29 devnull s_putc(s, c);
560 5cdb1798 2005-10-29 devnull
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;
564 5cdb1798 2005-10-29 devnull else
565 5cdb1798 2005-10-29 devnull quoted = 0;
566 5cdb1798 2005-10-29 devnull
567 5cdb1798 2005-10-29 devnull }
568 5cdb1798 2005-10-29 devnull
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));
574 5cdb1798 2005-10-29 devnull }
575 5cdb1798 2005-10-29 devnull s_free(s);
576 5cdb1798 2005-10-29 devnull
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;
580 5cdb1798 2005-10-29 devnull }
581 5cdb1798 2005-10-29 devnull return list;
582 5cdb1798 2005-10-29 devnull }
583 5cdb1798 2005-10-29 devnull
584 5cdb1798 2005-10-29 devnull static void
585 5cdb1798 2005-10-29 devnull to822(Message *m, Header *h, char *p)
586 5cdb1798 2005-10-29 devnull {
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);
590 5cdb1798 2005-10-29 devnull }
591 5cdb1798 2005-10-29 devnull
592 5cdb1798 2005-10-29 devnull static void
593 5cdb1798 2005-10-29 devnull cc822(Message *m, Header *h, char *p)
594 5cdb1798 2005-10-29 devnull {
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);
598 5cdb1798 2005-10-29 devnull }
599 5cdb1798 2005-10-29 devnull
600 5cdb1798 2005-10-29 devnull static void
601 5cdb1798 2005-10-29 devnull bcc822(Message *m, Header *h, char *p)
602 5cdb1798 2005-10-29 devnull {
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);
606 5cdb1798 2005-10-29 devnull }
607 5cdb1798 2005-10-29 devnull
608 5cdb1798 2005-10-29 devnull static void
609 5cdb1798 2005-10-29 devnull from822(Message *m, Header *h, char *p)
610 5cdb1798 2005-10-29 devnull {
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);
614 5cdb1798 2005-10-29 devnull }
615 5cdb1798 2005-10-29 devnull
616 5cdb1798 2005-10-29 devnull static void
617 5cdb1798 2005-10-29 devnull sender822(Message *m, Header *h, char *p)
618 5cdb1798 2005-10-29 devnull {
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);
622 5cdb1798 2005-10-29 devnull }
623 5cdb1798 2005-10-29 devnull
624 5cdb1798 2005-10-29 devnull static void
625 5cdb1798 2005-10-29 devnull replyto822(Message *m, Header *h, char *p)
626 5cdb1798 2005-10-29 devnull {
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);
630 5cdb1798 2005-10-29 devnull }
631 5cdb1798 2005-10-29 devnull
632 5cdb1798 2005-10-29 devnull static void
633 5cdb1798 2005-10-29 devnull mimeversion(Message *m, Header *h, char *p)
634 5cdb1798 2005-10-29 devnull {
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);
638 5cdb1798 2005-10-29 devnull }
639 5cdb1798 2005-10-29 devnull
640 5cdb1798 2005-10-29 devnull static void
641 5cdb1798 2005-10-29 devnull killtrailingwhite(char *p)
642 5cdb1798 2005-10-29 devnull {
643 5cdb1798 2005-10-29 devnull char *e;
644 5cdb1798 2005-10-29 devnull
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;
648 5cdb1798 2005-10-29 devnull }
649 5cdb1798 2005-10-29 devnull
650 5cdb1798 2005-10-29 devnull static void
651 5cdb1798 2005-10-29 devnull date822(Message *m, Header *h, char *p)
652 5cdb1798 2005-10-29 devnull {
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);
659 5cdb1798 2005-10-29 devnull }
660 5cdb1798 2005-10-29 devnull
661 5cdb1798 2005-10-29 devnull static void
662 5cdb1798 2005-10-29 devnull subject822(Message *m, Header *h, char *p)
663 5cdb1798 2005-10-29 devnull {
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);
670 5cdb1798 2005-10-29 devnull }
671 5cdb1798 2005-10-29 devnull
672 5cdb1798 2005-10-29 devnull static void
673 5cdb1798 2005-10-29 devnull inreplyto822(Message *m, Header *h, char *p)
674 5cdb1798 2005-10-29 devnull {
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);
681 5cdb1798 2005-10-29 devnull }
682 5cdb1798 2005-10-29 devnull
683 5cdb1798 2005-10-29 devnull static void
684 5cdb1798 2005-10-29 devnull messageid822(Message *m, Header *h, char *p)
685 5cdb1798 2005-10-29 devnull {
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);
692 5cdb1798 2005-10-29 devnull }
693 5cdb1798 2005-10-29 devnull
694 5cdb1798 2005-10-29 devnull static int
695 5cdb1798 2005-10-29 devnull isattribute(char **pp, char *attr)
696 5cdb1798 2005-10-29 devnull {
697 5cdb1798 2005-10-29 devnull char *p;
698 5cdb1798 2005-10-29 devnull int n;
699 5cdb1798 2005-10-29 devnull
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;
704 5cdb1798 2005-10-29 devnull p += n;
705 5cdb1798 2005-10-29 devnull while(*p == ' ')
706 5cdb1798 2005-10-29 devnull 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 == ' ')
710 5cdb1798 2005-10-29 devnull p++;
711 5cdb1798 2005-10-29 devnull *pp = p;
712 5cdb1798 2005-10-29 devnull return 1;
713 5cdb1798 2005-10-29 devnull }
714 5cdb1798 2005-10-29 devnull
715 5cdb1798 2005-10-29 devnull static void
716 5cdb1798 2005-10-29 devnull ctype(Message *m, Header *h, char *p)
717 5cdb1798 2005-10-29 devnull {
718 5cdb1798 2005-10-29 devnull String *s;
719 5cdb1798 2005-10-29 devnull
720 5cdb1798 2005-10-29 devnull p += h->len;
721 5cdb1798 2005-10-29 devnull p = skipwhite(p);
722 5cdb1798 2005-10-29 devnull
723 5cdb1798 2005-10-29 devnull p = getstring(p, m->type, 1);
724 5cdb1798 2005-10-29 devnull
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){
734 5cdb1798 2005-10-29 devnull /*
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
737 5cdb1798 2005-10-29 devnull */
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);
743 5cdb1798 2005-10-29 devnull }
744 5cdb1798 2005-10-29 devnull
745 5cdb1798 2005-10-29 devnull p = skiptosemi(p);
746 5cdb1798 2005-10-29 devnull }
747 5cdb1798 2005-10-29 devnull }
748 5cdb1798 2005-10-29 devnull
749 5cdb1798 2005-10-29 devnull static void
750 5cdb1798 2005-10-29 devnull cencoding(Message *m, Header *h, char *p)
751 5cdb1798 2005-10-29 devnull {
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;
758 5cdb1798 2005-10-29 devnull }
759 5cdb1798 2005-10-29 devnull
760 5cdb1798 2005-10-29 devnull static void
761 5cdb1798 2005-10-29 devnull cdisposition(Message *m, Header *h, char *p)
762 5cdb1798 2005-10-29 devnull {
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){
771 5cdb1798 2005-10-29 devnull p += 9;
772 5cdb1798 2005-10-29 devnull setfilename(m, p);
773 5cdb1798 2005-10-29 devnull }
774 5cdb1798 2005-10-29 devnull p = skiptosemi(p);
775 5cdb1798 2005-10-29 devnull }
776 5cdb1798 2005-10-29 devnull
777 5cdb1798 2005-10-29 devnull }
778 5cdb1798 2005-10-29 devnull
779 5cdb1798 2005-10-29 devnull ulong msgallocd, msgfreed;
780 5cdb1798 2005-10-29 devnull
781 5cdb1798 2005-10-29 devnull Message*
782 5cdb1798 2005-10-29 devnull newmessage(Message *parent)
783 5cdb1798 2005-10-29 devnull {
784 5cdb1798 2005-10-29 devnull /* static int id; jpc */
785 5cdb1798 2005-10-29 devnull Message *m;
786 5cdb1798 2005-10-29 devnull
787 5cdb1798 2005-10-29 devnull msgallocd++;
788 5cdb1798 2005-10-29 devnull
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;
802 5cdb1798 2005-10-29 devnull }
803 5cdb1798 2005-10-29 devnull
804 cbeb0b26 2006-04-01 devnull /* delete a message from a mailbox */
805 5cdb1798 2005-10-29 devnull void
806 5cdb1798 2005-10-29 devnull delmessage(Mailbox *mb, Message *m)
807 5cdb1798 2005-10-29 devnull {
808 5cdb1798 2005-10-29 devnull Message **l;
809 5cdb1798 2005-10-29 devnull int i;
810 5cdb1798 2005-10-29 devnull
811 5cdb1798 2005-10-29 devnull mb->vers++;
812 5cdb1798 2005-10-29 devnull msgfreed++;
813 5cdb1798 2005-10-29 devnull
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)
817 5cdb1798 2005-10-29 devnull ;
818 5cdb1798 2005-10-29 devnull if(*l != nil)
819 5cdb1798 2005-10-29 devnull *l = m->next;
820 5cdb1798 2005-10-29 devnull
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);
824 5cdb1798 2005-10-29 devnull else
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]);
828 5cdb1798 2005-10-29 devnull }
829 5cdb1798 2005-10-29 devnull
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);
833 5cdb1798 2005-10-29 devnull
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);
861 5cdb1798 2005-10-29 devnull
862 5cdb1798 2005-10-29 devnull free(m);
863 5cdb1798 2005-10-29 devnull }
864 5cdb1798 2005-10-29 devnull
865 cbeb0b26 2006-04-01 devnull /* mark messages (identified by path) for deletion */
866 5cdb1798 2005-10-29 devnull void
867 5cdb1798 2005-10-29 devnull delmessages(int ac, char **av)
868 5cdb1798 2005-10-29 devnull {
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;
872 5cdb1798 2005-10-29 devnull
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);
877 5cdb1798 2005-10-29 devnull break;
878 5cdb1798 2005-10-29 devnull }
879 5cdb1798 2005-10-29 devnull qunlock(&mbllock);
880 5cdb1798 2005-10-29 devnull if(mb == nil)
881 5cdb1798 2005-10-29 devnull return;
882 5cdb1798 2005-10-29 devnull
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);
892 5cdb1798 2005-10-29 devnull }
893 5cdb1798 2005-10-29 devnull break;
894 5cdb1798 2005-10-29 devnull }
895 5cdb1798 2005-10-29 devnull }
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);
899 5cdb1798 2005-10-29 devnull }
900 5cdb1798 2005-10-29 devnull
901 5cdb1798 2005-10-29 devnull /*
902 5cdb1798 2005-10-29 devnull * the following are called with the mailbox qlocked
903 5cdb1798 2005-10-29 devnull */
904 5cdb1798 2005-10-29 devnull void
905 5cdb1798 2005-10-29 devnull msgincref(Message *m)
906 5cdb1798 2005-10-29 devnull {
907 5cdb1798 2005-10-29 devnull m->refs++;
908 5cdb1798 2005-10-29 devnull }
909 5cdb1798 2005-10-29 devnull void
910 5cdb1798 2005-10-29 devnull msgdecref(Mailbox *mb, Message *m)
911 5cdb1798 2005-10-29 devnull {
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);
915 5cdb1798 2005-10-29 devnull }
916 5cdb1798 2005-10-29 devnull
917 5cdb1798 2005-10-29 devnull /*
918 5cdb1798 2005-10-29 devnull * the following are called with mbllock'd
919 5cdb1798 2005-10-29 devnull */
920 5cdb1798 2005-10-29 devnull void
921 5cdb1798 2005-10-29 devnull mboxincref(Mailbox *mb)
922 5cdb1798 2005-10-29 devnull {
923 5cdb1798 2005-10-29 devnull assert(mb->refs > 0);
924 5cdb1798 2005-10-29 devnull mb->refs++;
925 5cdb1798 2005-10-29 devnull }
926 5cdb1798 2005-10-29 devnull void
927 5cdb1798 2005-10-29 devnull mboxdecref(Mailbox *mb)
928 5cdb1798 2005-10-29 devnull {
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);
939 5cdb1798 2005-10-29 devnull } else
940 5cdb1798 2005-10-29 devnull qunlock(&mb->ql);
941 5cdb1798 2005-10-29 devnull }
942 5cdb1798 2005-10-29 devnull
943 5cdb1798 2005-10-29 devnull int
944 5cdb1798 2005-10-29 devnull cistrncmp(char *a, char *b, int n)
945 5cdb1798 2005-10-29 devnull {
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;
949 5cdb1798 2005-10-29 devnull }
950 5cdb1798 2005-10-29 devnull return 0;
951 5cdb1798 2005-10-29 devnull }
952 5cdb1798 2005-10-29 devnull
953 5cdb1798 2005-10-29 devnull int
954 5cdb1798 2005-10-29 devnull cistrcmp(char *a, char *b)
955 5cdb1798 2005-10-29 devnull {
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)
960 5cdb1798 2005-10-29 devnull break;
961 5cdb1798 2005-10-29 devnull }
962 5cdb1798 2005-10-29 devnull return 0;
963 5cdb1798 2005-10-29 devnull }
964 5cdb1798 2005-10-29 devnull
965 5cdb1798 2005-10-29 devnull static char*
966 5cdb1798 2005-10-29 devnull skipwhite(char *p)
967 5cdb1798 2005-10-29 devnull {
968 5cdb1798 2005-10-29 devnull while(isspace(*p))
969 5cdb1798 2005-10-29 devnull p++;
970 5cdb1798 2005-10-29 devnull return p;
971 5cdb1798 2005-10-29 devnull }
972 5cdb1798 2005-10-29 devnull
973 5cdb1798 2005-10-29 devnull static char*
974 5cdb1798 2005-10-29 devnull skiptosemi(char *p)
975 5cdb1798 2005-10-29 devnull {
976 5cdb1798 2005-10-29 devnull while(*p && *p != ';')
977 5cdb1798 2005-10-29 devnull p++;
978 5cdb1798 2005-10-29 devnull while(*p == ';' || isspace(*p))
979 5cdb1798 2005-10-29 devnull p++;
980 5cdb1798 2005-10-29 devnull return p;
981 5cdb1798 2005-10-29 devnull }
982 5cdb1798 2005-10-29 devnull
983 5cdb1798 2005-10-29 devnull static char*
984 5cdb1798 2005-10-29 devnull getstring(char *p, String *s, int dolower)
985 5cdb1798 2005-10-29 devnull {
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 == '"'){
989 5cdb1798 2005-10-29 devnull 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));
993 5cdb1798 2005-10-29 devnull else
994 5cdb1798 2005-10-29 devnull s_putc(s, *p);
995 5cdb1798 2005-10-29 devnull if(*p == '"')
996 5cdb1798 2005-10-29 devnull p++;
997 5cdb1798 2005-10-29 devnull s_terminate(s);
998 5cdb1798 2005-10-29 devnull
999 5cdb1798 2005-10-29 devnull return p;
1000 5cdb1798 2005-10-29 devnull }
1001 5cdb1798 2005-10-29 devnull
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));
1005 5cdb1798 2005-10-29 devnull else
1006 5cdb1798 2005-10-29 devnull s_putc(s, *p);
1007 5cdb1798 2005-10-29 devnull s_terminate(s);
1008 5cdb1798 2005-10-29 devnull
1009 5cdb1798 2005-10-29 devnull return p;
1010 5cdb1798 2005-10-29 devnull }
1011 5cdb1798 2005-10-29 devnull
1012 5cdb1798 2005-10-29 devnull static void
1013 5cdb1798 2005-10-29 devnull setfilename(Message *m, char *p)
1014 5cdb1798 2005-10-29 devnull {
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 = '_';
1020 5cdb1798 2005-10-29 devnull }
1021 5cdb1798 2005-10-29 devnull
1022 cbeb0b26 2006-04-01 devnull /* */
1023 cbeb0b26 2006-04-01 devnull /* undecode message body */
1024 cbeb0b26 2006-04-01 devnull /* */
1025 5cdb1798 2005-10-29 devnull void
1026 5cdb1798 2005-10-29 devnull decode(Message *m)
1027 5cdb1798 2005-10-29 devnull {
1028 5cdb1798 2005-10-29 devnull int i, len;
1029 5cdb1798 2005-10-29 devnull char *x;
1030 5cdb1798 2005-10-29 devnull
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;
1044 5cdb1798 2005-10-29 devnull break;
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;
1054 5cdb1798 2005-10-29 devnull break;
1055 5cdb1798 2005-10-29 devnull default:
1056 5cdb1798 2005-10-29 devnull break;
1057 5cdb1798 2005-10-29 devnull }
1058 5cdb1798 2005-10-29 devnull m->decoded = 1;
1059 5cdb1798 2005-10-29 devnull }
1060 5cdb1798 2005-10-29 devnull
1061 cbeb0b26 2006-04-01 devnull /* convert latin1 to utf */
1062 5cdb1798 2005-10-29 devnull void
1063 5cdb1798 2005-10-29 devnull convert(Message *m)
1064 5cdb1798 2005-10-29 devnull {
1065 5cdb1798 2005-10-29 devnull int len;
1066 5cdb1798 2005-10-29 devnull char *x;
1067 5cdb1798 2005-10-29 devnull
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;
1075 5cdb1798 2005-10-29 devnull
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;
1088 5cdb1798 2005-10-29 devnull }
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;
1097 5cdb1798 2005-10-29 devnull }
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;
1106 5cdb1798 2005-10-29 devnull }
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;
1115 5cdb1798 2005-10-29 devnull }
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;
1124 5cdb1798 2005-10-29 devnull }
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;
1137 5cdb1798 2005-10-29 devnull }
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;
1146 5cdb1798 2005-10-29 devnull }
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;
1155 5cdb1798 2005-10-29 devnull }
1156 5cdb1798 2005-10-29 devnull }
1157 5cdb1798 2005-10-29 devnull
1158 5cdb1798 2005-10-29 devnull m->converted = 1;
1159 5cdb1798 2005-10-29 devnull }
1160 5cdb1798 2005-10-29 devnull
1161 5cdb1798 2005-10-29 devnull enum
1162 5cdb1798 2005-10-29 devnull {
1163 5cdb1798 2005-10-29 devnull Self= 1,
1164 cbeb0b26 2006-04-01 devnull Hex= 2
1165 5cdb1798 2005-10-29 devnull };
1166 5cdb1798 2005-10-29 devnull uchar tableqp[256];
1167 5cdb1798 2005-10-29 devnull
1168 5cdb1798 2005-10-29 devnull static void
1169 5cdb1798 2005-10-29 devnull initquoted(void)
1170 5cdb1798 2005-10-29 devnull {
1171 5cdb1798 2005-10-29 devnull int c;
1172 5cdb1798 2005-10-29 devnull
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;
1180 5cdb1798 2005-10-29 devnull }
1181 5cdb1798 2005-10-29 devnull
1182 5cdb1798 2005-10-29 devnull static int
1183 5cdb1798 2005-10-29 devnull hex2int(int x)
1184 5cdb1798 2005-10-29 devnull {
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;
1192 5cdb1798 2005-10-29 devnull }
1193 5cdb1798 2005-10-29 devnull
1194 5cdb1798 2005-10-29 devnull static char*
1195 5cdb1798 2005-10-29 devnull decquotedline(char *out, char *in, char *e)
1196 5cdb1798 2005-10-29 devnull {
1197 5cdb1798 2005-10-29 devnull int c, soft;
1198 5cdb1798 2005-10-29 devnull
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'))
1201 5cdb1798 2005-10-29 devnull e--;
1202 5cdb1798 2005-10-29 devnull
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;
1206 5cdb1798 2005-10-29 devnull e--;
1207 5cdb1798 2005-10-29 devnull } else
1208 5cdb1798 2005-10-29 devnull soft = 0;
1209 5cdb1798 2005-10-29 devnull
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;
1215 5cdb1798 2005-10-29 devnull break;
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;
1220 5cdb1798 2005-10-29 devnull break;
1221 5cdb1798 2005-10-29 devnull }
1222 5cdb1798 2005-10-29 devnull }
1223 5cdb1798 2005-10-29 devnull if(!soft)
1224 5cdb1798 2005-10-29 devnull *out++ = '\n';
1225 5cdb1798 2005-10-29 devnull *out = 0;
1226 5cdb1798 2005-10-29 devnull
1227 5cdb1798 2005-10-29 devnull return out;
1228 5cdb1798 2005-10-29 devnull }
1229 5cdb1798 2005-10-29 devnull
1230 5cdb1798 2005-10-29 devnull int
1231 5cdb1798 2005-10-29 devnull decquoted(char *out, char *in, char *e)
1232 5cdb1798 2005-10-29 devnull {
1233 5cdb1798 2005-10-29 devnull char *p, *nl;
1234 5cdb1798 2005-10-29 devnull
1235 5cdb1798 2005-10-29 devnull if(tableqp[' '] == 0)
1236 5cdb1798 2005-10-29 devnull initquoted();
1237 5cdb1798 2005-10-29 devnull
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;
1242 5cdb1798 2005-10-29 devnull }
1243 5cdb1798 2005-10-29 devnull if(in < e)
1244 5cdb1798 2005-10-29 devnull p = decquotedline(p, in, e-1);
1245 5cdb1798 2005-10-29 devnull
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;
1250 5cdb1798 2005-10-29 devnull }
1251 5cdb1798 2005-10-29 devnull
1252 5cdb1798 2005-10-29 devnull return p - out;
1253 5cdb1798 2005-10-29 devnull }
1254 5cdb1798 2005-10-29 devnull
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)
1258 5cdb1798 2005-10-29 devnull {
1259 5cdb1798 2005-10-29 devnull char *op;
1260 5cdb1798 2005-10-29 devnull int c;
1261 5cdb1798 2005-10-29 devnull
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;
1266 5cdb1798 2005-10-29 devnull }
1267 5cdb1798 2005-10-29 devnull #endif
1268 5cdb1798 2005-10-29 devnull
1269 5cdb1798 2005-10-29 devnull /*
1270 5cdb1798 2005-10-29 devnull * return number of 8 bit characters
1271 5cdb1798 2005-10-29 devnull */
1272 5cdb1798 2005-10-29 devnull static int
1273 5cdb1798 2005-10-29 devnull is8bit(Message *m)
1274 5cdb1798 2005-10-29 devnull {
1275 5cdb1798 2005-10-29 devnull int count = 0;
1276 5cdb1798 2005-10-29 devnull char *p;
1277 5cdb1798 2005-10-29 devnull
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;
1282 5cdb1798 2005-10-29 devnull }
1283 5cdb1798 2005-10-29 devnull
1284 cbeb0b26 2006-04-01 devnull /* translate latin1 directly since it fits neatly in utf */
1285 5cdb1798 2005-10-29 devnull int
1286 5cdb1798 2005-10-29 devnull latin1toutf(char *out, char *in, char *e)
1287 5cdb1798 2005-10-29 devnull {
1288 5cdb1798 2005-10-29 devnull Rune r;
1289 5cdb1798 2005-10-29 devnull char *p;
1290 5cdb1798 2005-10-29 devnull
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);
1295 5cdb1798 2005-10-29 devnull }
1296 5cdb1798 2005-10-29 devnull *p = 0;
1297 5cdb1798 2005-10-29 devnull return p - out;
1298 5cdb1798 2005-10-29 devnull }
1299 5cdb1798 2005-10-29 devnull
1300 cbeb0b26 2006-04-01 devnull /* translate any thing else using the tcs program */
1301 5cdb1798 2005-10-29 devnull int
1302 5cdb1798 2005-10-29 devnull xtoutf(char *charset, char **out, char *in, char *e)
1303 5cdb1798 2005-10-29 devnull {
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;
1309 5cdb1798 2005-10-29 devnull
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;
1315 5cdb1798 2005-10-29 devnull
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;
1325 5cdb1798 2005-10-29 devnull }
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)
1352 5cdb1798 2005-10-29 devnull break;
1353 5cdb1798 2005-10-29 devnull in += n;
1354 5cdb1798 2005-10-29 devnull }
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)
1363 5cdb1798 2005-10-29 devnull break;
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;
1371 5cdb1798 2005-10-29 devnull }
1372 5cdb1798 2005-10-29 devnull }
1373 5cdb1798 2005-10-29 devnull close(fromtcs[0]);
1374 5cdb1798 2005-10-29 devnull break;
1375 5cdb1798 2005-10-29 devnull }
1376 5cdb1798 2005-10-29 devnull break;
1377 5cdb1798 2005-10-29 devnull }
1378 5cdb1798 2005-10-29 devnull return sofar;
1379 5cdb1798 2005-10-29 devnull }
1380 5cdb1798 2005-10-29 devnull
1381 5cdb1798 2005-10-29 devnull enum {
1382 5cdb1798 2005-10-29 devnull Winstart= 0x7f,
1383 cbeb0b26 2006-04-01 devnull Winend= 0x9f
1384 5cdb1798 2005-10-29 devnull };
1385 5cdb1798 2005-10-29 devnull
1386 5cdb1798 2005-10-29 devnull Rune winchars[] = {
1387 5cdb1798 2005-10-29 devnull L'•',
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'Ÿ'
1392 5cdb1798 2005-10-29 devnull };
1393 5cdb1798 2005-10-29 devnull
1394 5cdb1798 2005-10-29 devnull int
1395 5cdb1798 2005-10-29 devnull windows1257toutf(char *out, char *in, char *e)
1396 5cdb1798 2005-10-29 devnull {
1397 5cdb1798 2005-10-29 devnull Rune r;
1398 5cdb1798 2005-10-29 devnull char *p;
1399 5cdb1798 2005-10-29 devnull
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);
1406 5cdb1798 2005-10-29 devnull }
1407 5cdb1798 2005-10-29 devnull *p = 0;
1408 5cdb1798 2005-10-29 devnull return p - out;
1409 5cdb1798 2005-10-29 devnull }
1410 5cdb1798 2005-10-29 devnull
1411 5cdb1798 2005-10-29 devnull void *
1412 5cdb1798 2005-10-29 devnull emalloc(ulong n)
1413 5cdb1798 2005-10-29 devnull {
1414 5cdb1798 2005-10-29 devnull void *p;
1415 5cdb1798 2005-10-29 devnull
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");
1420 5cdb1798 2005-10-29 devnull }
1421 5cdb1798 2005-10-29 devnull setmalloctag(p, getcallerpc(&n));
1422 5cdb1798 2005-10-29 devnull return p;
1423 5cdb1798 2005-10-29 devnull }
1424 5cdb1798 2005-10-29 devnull
1425 5cdb1798 2005-10-29 devnull void *
1426 5cdb1798 2005-10-29 devnull erealloc(void *p, ulong n)
1427 5cdb1798 2005-10-29 devnull {
1428 5cdb1798 2005-10-29 devnull if(n == 0)
1429 5cdb1798 2005-10-29 devnull n = 1;
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");
1434 5cdb1798 2005-10-29 devnull }
1435 5cdb1798 2005-10-29 devnull setrealloctag(p, getcallerpc(&p));
1436 5cdb1798 2005-10-29 devnull return p;
1437 5cdb1798 2005-10-29 devnull }
1438 5cdb1798 2005-10-29 devnull
1439 5cdb1798 2005-10-29 devnull void
1440 5cdb1798 2005-10-29 devnull mailplumb(Mailbox *mb, Message *m, int delete)
1441 5cdb1798 2005-10-29 devnull {
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;
1448 5cdb1798 2005-10-29 devnull
1449 5cdb1798 2005-10-29 devnull if(m->subject822 == nil)
1450 5cdb1798 2005-10-29 devnull subject = "";
1451 5cdb1798 2005-10-29 devnull else
1452 5cdb1798 2005-10-29 devnull subject = s_to_c(m->subject822);
1453 5cdb1798 2005-10-29 devnull
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);
1458 5cdb1798 2005-10-29 devnull else
1459 5cdb1798 2005-10-29 devnull from = "";
1460 5cdb1798 2005-10-29 devnull
1461 5cdb1798 2005-10-29 devnull if(m->unixdate != nil)
1462 5cdb1798 2005-10-29 devnull date = s_to_c(m->unixdate);
1463 5cdb1798 2005-10-29 devnull else
1464 5cdb1798 2005-10-29 devnull date = "";
1465 5cdb1798 2005-10-29 devnull
1466 5cdb1798 2005-10-29 devnull sprint(lenstr, "%ld", m->end-m->start);
1467 5cdb1798 2005-10-29 devnull
1468 5cdb1798 2005-10-29 devnull if(biffing && !delete)
1469 5cdb1798 2005-10-29 devnull print("[ %s / %s / %s ]\n", from, subject, lenstr);
1470 5cdb1798 2005-10-29 devnull
1471 5cdb1798 2005-10-29 devnull if(!plumbing)
1472 5cdb1798 2005-10-29 devnull return;
1473 5cdb1798 2005-10-29 devnull
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;
1478 5cdb1798 2005-10-29 devnull
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";
1483 5cdb1798 2005-10-29 devnull
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";
1487 5cdb1798 2005-10-29 devnull
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];
1491 5cdb1798 2005-10-29 devnull
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];
1495 5cdb1798 2005-10-29 devnull
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];
1499 5cdb1798 2005-10-29 devnull
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];
1503 5cdb1798 2005-10-29 devnull
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];
1508 5cdb1798 2005-10-29 devnull }
1509 5cdb1798 2005-10-29 devnull
1510 5cdb1798 2005-10-29 devnull a[ai].next = nil;
1511 5cdb1798 2005-10-29 devnull
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;
1517 5cdb1798 2005-10-29 devnull
1518 5cdb1798 2005-10-29 devnull plumbsend(fd, &p);
1519 5cdb1798 2005-10-29 devnull }
1520 5cdb1798 2005-10-29 devnull
1521 cbeb0b26 2006-04-01 devnull /* */
1522 cbeb0b26 2006-04-01 devnull /* count the number of lines in the body (for imap4) */
1523 cbeb0b26 2006-04-01 devnull /* */
1524 5cdb1798 2005-10-29 devnull void
1525 5cdb1798 2005-10-29 devnull countlines(Message *m)
1526 5cdb1798 2005-10-29 devnull {
1527 5cdb1798 2005-10-29 devnull int i;
1528 5cdb1798 2005-10-29 devnull char *p;
1529 5cdb1798 2005-10-29 devnull
1530 5cdb1798 2005-10-29 devnull i = 0;
1531 5cdb1798 2005-10-29 devnull for(p = strchr(m->rbody, '\n'); p != nil && p < m->rbend; p = strchr(p+1, '\n'))
1532 5cdb1798 2005-10-29 devnull i++;
1533 5cdb1798 2005-10-29 devnull sprint(m->lines, "%d", i);
1534 5cdb1798 2005-10-29 devnull }
1535 5cdb1798 2005-10-29 devnull
1536 5cdb1798 2005-10-29 devnull char *LOG = "fs";
1537 5cdb1798 2005-10-29 devnull
1538 5cdb1798 2005-10-29 devnull void
1539 5cdb1798 2005-10-29 devnull logmsg(char *s, Message *m)
1540 5cdb1798 2005-10-29 devnull {
1541 5cdb1798 2005-10-29 devnull int pid;
1542 5cdb1798 2005-10-29 devnull
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);
1548 5cdb1798 2005-10-29 devnull else
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));
1553 5cdb1798 2005-10-29 devnull }
1554 5cdb1798 2005-10-29 devnull
1555 5cdb1798 2005-10-29 devnull /*
1556 5cdb1798 2005-10-29 devnull * squeeze nulls out of the body
1557 5cdb1798 2005-10-29 devnull */
1558 5cdb1798 2005-10-29 devnull static void
1559 5cdb1798 2005-10-29 devnull nullsqueeze(Message *m)
1560 5cdb1798 2005-10-29 devnull {
1561 5cdb1798 2005-10-29 devnull char *p, *q;
1562 5cdb1798 2005-10-29 devnull
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;
1566 5cdb1798 2005-10-29 devnull
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;
1571 5cdb1798 2005-10-29 devnull }
1572 5cdb1798 2005-10-29 devnull m->bend = m->rbend = m->end = p;
1573 5cdb1798 2005-10-29 devnull }
1574 5cdb1798 2005-10-29 devnull
1575 5cdb1798 2005-10-29 devnull
1576 cbeb0b26 2006-04-01 devnull /* */
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. */
1581 cbeb0b26 2006-04-01 devnull /* */
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. */
1584 cbeb0b26 2006-04-01 devnull /* */
1585 5cdb1798 2005-10-29 devnull
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)
1589 5cdb1798 2005-10-29 devnull {
1590 5cdb1798 2005-10-29 devnull char *p, *q;
1591 5cdb1798 2005-10-29 devnull Tm tm;
1592 5cdb1798 2005-10-29 devnull
1593 5cdb1798 2005-10-29 devnull if(strtotm(s, &tm) < 0)
1594 5cdb1798 2005-10-29 devnull return nil;
1595 5cdb1798 2005-10-29 devnull
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);
1600 5cdb1798 2005-10-29 devnull }
1601 5cdb1798 2005-10-29 devnull