git-svn: trunk@3212
Nigel Horne authored on 2007/09/11 19:22:49... | ... |
@@ -653,9 +653,9 @@ fileblobScan(const fileblob *fb) |
653 | 653 |
#ifndef C_WINDOWS |
654 | 654 |
/* |
655 | 655 |
* FIXME: On Windows, cli_readn gives "bad file descriptor" when called |
656 |
- * by cli_check_mydoom_log from a call do cli_magic_scandesc here which |
|
657 |
- * implies that the file descriptor is getting closed somewhere, but I |
|
658 |
- * can't see where. |
|
656 |
+ * by cli_check_mydoom_log from the call to cli_magic_scandesc here |
|
657 |
+ * which implies that the file descriptor is getting closed somewhere, |
|
658 |
+ * but I can't see where. |
|
659 | 659 |
* One possible fix would be to duplicate cli_scanfile here. |
660 | 660 |
*/ |
661 | 661 |
fflush(fb->fp); |
... | ... |
@@ -3255,10 +3255,13 @@ strstrip(char *s) |
3255 | 3255 |
return(strip(s, (int)strlen(s) + 1)); |
3256 | 3256 |
} |
3257 | 3257 |
|
3258 |
+/* |
|
3259 |
+ * Returns 0 for OK, -1 for error |
|
3260 |
+ */ |
|
3258 | 3261 |
static int |
3259 | 3262 |
parseMimeHeader(message *m, const char *cmd, const table_t *rfc821Table, const char *arg) |
3260 | 3263 |
{ |
3261 |
- char *copy, *p; |
|
3264 |
+ char *copy, *p, *buf; |
|
3262 | 3265 |
const char *ptr; |
3263 | 3266 |
int commandNumber; |
3264 | 3267 |
|
... | ... |
@@ -3278,6 +3281,8 @@ parseMimeHeader(message *m, const char *cmd, const table_t *rfc821Table, const c |
3278 | 3278 |
else |
3279 | 3279 |
ptr = arg; |
3280 | 3280 |
|
3281 |
+ buf = NULL; |
|
3282 |
+ |
|
3281 | 3283 |
switch(commandNumber) { |
3282 | 3284 |
case CONTENT_TYPE: |
3283 | 3285 |
/* |
... | ... |
@@ -3309,6 +3314,12 @@ parseMimeHeader(message *m, const char *cmd, const table_t *rfc821Table, const c |
3309 | 3309 |
int i; |
3310 | 3310 |
char *mimeArgs; /* RHS of the ; */ |
3311 | 3311 |
|
3312 |
+ buf = cli_malloc(strlen(ptr) + 1); |
|
3313 |
+ if(buf == NULL) { |
|
3314 |
+ if(copy) |
|
3315 |
+ free(copy); |
|
3316 |
+ return -1; |
|
3317 |
+ } |
|
3312 | 3318 |
/* |
3313 | 3319 |
* Some clients are broken and |
3314 | 3320 |
* put white space after the ; |
... | ... |
@@ -3332,12 +3343,11 @@ parseMimeHeader(message *m, const char *cmd, const table_t *rfc821Table, const c |
3332 | 3332 |
|
3333 | 3333 |
if(ptr[0] != '/') { |
3334 | 3334 |
char *s; |
3335 |
- char *mimeType; /* LHS of the ; */ |
|
3336 | 3335 |
#ifdef CL_THREAD_SAFE |
3337 | 3336 |
char *strptr = NULL; |
3338 | 3337 |
#endif |
3339 | 3338 |
|
3340 |
- s = mimeType = cli_strtok(ptr, 0, ";"); |
|
3339 |
+ s = cli_strtokbuf(ptr, 0, ";", buf); |
|
3341 | 3340 |
/* |
3342 | 3341 |
* Handle |
3343 | 3342 |
* Content-Type: foo/bar multipart/mixed |
... | ... |
@@ -3371,12 +3381,10 @@ parseMimeHeader(message *m, const char *cmd, const table_t *rfc821Table, const c |
3371 | 3371 |
len = strstrip(s); |
3372 | 3372 |
} |
3373 | 3373 |
if(len) { |
3374 |
- if(strchr(s, ' ')) { |
|
3375 |
- char *t = cli_strtok(s, 0, " "); |
|
3376 |
- |
|
3377 |
- messageSetMimeSubtype(m, t); |
|
3378 |
- free(t); |
|
3379 |
- } else |
|
3374 |
+ if(strchr(s, ' ')) |
|
3375 |
+ messageSetMimeSubtype(m, |
|
3376 |
+ cli_strtokbuf(s, 0, " ", buf)); |
|
3377 |
+ else |
|
3380 | 3378 |
messageSetMimeSubtype(m, s); |
3381 | 3379 |
} |
3382 | 3380 |
} |
... | ... |
@@ -3388,8 +3396,6 @@ parseMimeHeader(message *m, const char *cmd, const table_t *rfc821Table, const c |
3388 | 3388 |
if(*s == '\0') |
3389 | 3389 |
break; |
3390 | 3390 |
} |
3391 |
- if(mimeType) |
|
3392 |
- free(mimeType); |
|
3393 | 3391 |
} |
3394 | 3392 |
} |
3395 | 3393 |
|
... | ... |
@@ -3400,11 +3406,10 @@ parseMimeHeader(message *m, const char *cmd, const table_t *rfc821Table, const c |
3400 | 3400 |
* we find the boundary argument set it |
3401 | 3401 |
*/ |
3402 | 3402 |
i = 1; |
3403 |
- while((mimeArgs = cli_strtok(ptr, i++, ";")) != NULL) { |
|
3403 |
+ while((mimeArgs = cli_strtokbuf(ptr, i++, ";", buf)) != NULL) { |
|
3404 | 3404 |
cli_dbgmsg("mimeArgs = '%s'\n", mimeArgs); |
3405 | 3405 |
|
3406 | 3406 |
messageAddArguments(m, mimeArgs); |
3407 |
- free(mimeArgs); |
|
3408 | 3407 |
} |
3409 | 3408 |
} |
3410 | 3409 |
break; |
... | ... |
@@ -3412,15 +3417,18 @@ parseMimeHeader(message *m, const char *cmd, const table_t *rfc821Table, const c |
3412 | 3412 |
messageSetEncoding(m, ptr); |
3413 | 3413 |
break; |
3414 | 3414 |
case CONTENT_DISPOSITION: |
3415 |
- p = cli_strtok(ptr, 0, ";"); |
|
3415 |
+ buf = cli_malloc(strlen(ptr) + 1); |
|
3416 |
+ if(buf == NULL) { |
|
3417 |
+ if(copy) |
|
3418 |
+ free(copy); |
|
3419 |
+ return -1; |
|
3420 |
+ } |
|
3421 |
+ p = cli_strtokbuf(ptr, 0, ";", buf); |
|
3416 | 3422 |
if(p) { |
3417 | 3423 |
if(*p) { |
3418 | 3424 |
messageSetDispositionType(m, p); |
3419 |
- free(p); |
|
3420 |
- p = cli_strtok(ptr, 1, ";"); |
|
3421 |
- messageAddArgument(m, p); |
|
3425 |
+ messageAddArgument(m, cli_strtokbuf(ptr, 1, ";", buf)); |
|
3422 | 3426 |
} |
3423 |
- free(p); |
|
3424 | 3427 |
} |
3425 | 3428 |
if((p = (char *)messageFindArgument(m, "filename")) == NULL) |
3426 | 3429 |
/* |
... | ... |
@@ -3436,6 +3444,8 @@ parseMimeHeader(message *m, const char *cmd, const table_t *rfc821Table, const c |
3436 | 3436 |
} |
3437 | 3437 |
if(copy) |
3438 | 3438 |
free(copy); |
3439 |
+ if(buf) |
|
3440 |
+ free(buf); |
|
3439 | 3441 |
|
3440 | 3442 |
return 0; |
3441 | 3443 |
} |
... | ... |
@@ -5030,7 +5040,8 @@ do_multipart(message *mainMessage, message **messages, int i, mbox_status *rc, m |
5030 | 5030 |
if(*rc != VIRUS) { |
5031 | 5031 |
if(addToText) { |
5032 | 5032 |
cli_dbgmsg("Adding to non mime-part\n"); |
5033 |
- *tptr = textAdd(*tptr, messageGetBody(aMessage)); |
|
5033 |
+ if(messageGetBody(aMessage)) |
|
5034 |
+ *tptr = textMove(*tptr, messageGetBody(aMessage)); |
|
5034 | 5035 |
} else { |
5035 | 5036 |
fileblob *fb = messageToFileblob(aMessage, mctx->dir, 1); |
5036 | 5037 |
|
... | ... |
@@ -1100,8 +1100,6 @@ messageExport(message *m, const char *dir, void *(*create)(void), void (*destroy |
1100 | 1100 |
/* |
1101 | 1101 |
* FIXME: We've probably run out of memory during the |
1102 | 1102 |
* text to blob. |
1103 |
- * TODO: if m->numberOfEncTypes == 1 we could delete |
|
1104 |
- * the text object as we decode it |
|
1105 | 1103 |
*/ |
1106 | 1104 |
cli_warnmsg("Couldn't start binhex parser\n"); |
1107 | 1105 |
(*destroy)(ret); |
... | ... |
@@ -2246,25 +2244,23 @@ decode(message *m, const char *in, unsigned char *out, unsigned char (*decoder)( |
2246 | 2246 |
} |
2247 | 2247 |
|
2248 | 2248 |
switch(nbytes) { |
2249 |
+ case 4: |
|
2250 |
+ *out++ = (b1 << 2) | ((b2 >> 4) & 0x3); |
|
2251 |
+ *out++ = (b2 << 4) | ((b3 >> 2) & 0xF); |
|
2252 |
+ *out++ = (b3 << 6) | (b4 & 0x3F); |
|
2253 |
+ continue; |
|
2249 | 2254 |
case 3: |
2250 | 2255 |
m->base64_3 = b3; |
2251 | 2256 |
case 2: |
2252 | 2257 |
m->base64_2 = b2; |
2253 | 2258 |
case 1: |
2254 | 2259 |
m->base64_1 = b1; |
2255 |
- break; |
|
2256 |
- case 4: |
|
2257 |
- *out++ = (b1 << 2) | ((b2 >> 4) & 0x3); |
|
2258 |
- *out++ = (b2 << 4) | ((b3 >> 2) & 0xF); |
|
2259 |
- *out++ = (b3 << 6) | (b4 & 0x3F); |
|
2260 |
+ m->base64chars = nbytes; |
|
2260 | 2261 |
break; |
2261 | 2262 |
default: |
2262 | 2263 |
assert(0); |
2263 | 2264 |
} |
2264 |
- if(nbytes != 4) { |
|
2265 |
- m->base64chars = nbytes; |
|
2266 |
- break; |
|
2267 |
- } |
|
2265 |
+ break; /* nbytes != 4 => EOL */ |
|
2268 | 2266 |
} |
2269 | 2267 |
return out; |
2270 | 2268 |
} |
... | ... |
@@ -116,6 +116,7 @@ static char const rcsid[] = "$Id: text.c,v 1.25 2007/02/12 20:46:09 njh Exp $"; |
116 | 116 |
#include "mbox.h" |
117 | 117 |
|
118 | 118 |
static text *textCopy(const text *t_head); |
119 |
+static text *textAdd(text *t_head, const text *t); |
|
119 | 120 |
static void addToFileblob(const line_t *line, void *arg); |
120 | 121 |
static void getLength(const line_t *line, void *arg); |
121 | 122 |
static void addToBlob(const line_t *line, void *arg); |
... | ... |
@@ -180,14 +181,19 @@ textCopy(const text *t_head) |
180 | 180 |
} |
181 | 181 |
|
182 | 182 |
/* Add a copy of a text to the end of the current object */ |
183 |
-text * |
|
183 |
+static text * |
|
184 | 184 |
textAdd(text *t_head, const text *t) |
185 | 185 |
{ |
186 | 186 |
text *ret; |
187 | 187 |
int count; |
188 | 188 |
|
189 |
- if(t_head == NULL) |
|
189 |
+ if(t_head == NULL) { |
|
190 |
+ if(t == NULL) { |
|
191 |
+ cli_errmsg("textAdd fails sanity check\n"); |
|
192 |
+ return NULL; |
|
193 |
+ } |
|
190 | 194 |
return textCopy(t); |
195 |
+ } |
|
191 | 196 |
|
192 | 197 |
if(t == NULL) |
193 | 198 |
return t_head; |
... | ... |
@@ -234,16 +240,69 @@ textAddMessage(text *aText, message *aMessage) |
234 | 234 |
else { |
235 | 235 |
text *anotherText = messageToText(aMessage); |
236 | 236 |
|
237 |
- if(aText) { |
|
238 |
- aText = textAdd(aText, anotherText); |
|
239 |
- textDestroy(anotherText); |
|
240 |
- return aText; |
|
241 |
- } |
|
237 |
+ if(aText) |
|
238 |
+ return textMove(aText, anotherText); |
|
242 | 239 |
return anotherText; |
243 | 240 |
} |
244 | 241 |
} |
245 | 242 |
|
246 | 243 |
/* |
244 |
+ * Put the contents of the given text at the end of the current object. |
|
245 |
+ * The given text emptied; it can be used again if needed, though be warned that |
|
246 |
+ * it will have an empty line at the start. |
|
247 |
+ */ |
|
248 |
+text * |
|
249 |
+textMove(text *t_head, text *t) |
|
250 |
+{ |
|
251 |
+ text *ret; |
|
252 |
+ |
|
253 |
+ if(t_head == NULL) { |
|
254 |
+ if(t == NULL) { |
|
255 |
+ cli_errmsg("textMove fails sanity check\n"); |
|
256 |
+ return NULL; |
|
257 |
+ } |
|
258 |
+ t_head = (text *)cli_malloc(sizeof(text)); |
|
259 |
+ if(t_head == NULL) |
|
260 |
+ return NULL; |
|
261 |
+ t_head->t_line = t->t_line; |
|
262 |
+ t_head->t_next = t->t_next; |
|
263 |
+ t->t_line = NULL; |
|
264 |
+ t->t_next = NULL; |
|
265 |
+ return t_head; |
|
266 |
+ } |
|
267 |
+ |
|
268 |
+ if(t == NULL) |
|
269 |
+ return t_head; |
|
270 |
+ |
|
271 |
+ ret = t_head; |
|
272 |
+ |
|
273 |
+ while(t_head->t_next) |
|
274 |
+ t_head = t_head->t_next; |
|
275 |
+ |
|
276 |
+ /* |
|
277 |
+ * Move the first line manually so that the caller is left clean but |
|
278 |
+ * empty, the rest is moved by a simple pointer reassignment |
|
279 |
+ */ |
|
280 |
+ t_head->t_next = (text *)cli_malloc(sizeof(text)); |
|
281 |
+ if(t_head->t_next == NULL) |
|
282 |
+ return NULL; |
|
283 |
+ t_head = t_head->t_next; |
|
284 |
+ |
|
285 |
+ assert(t_head != NULL); |
|
286 |
+ |
|
287 |
+ if(t->t_line) { |
|
288 |
+ t_head->t_line = t->t_line; |
|
289 |
+ t->t_line = NULL; |
|
290 |
+ } else |
|
291 |
+ t_head->t_line = NULL; |
|
292 |
+ |
|
293 |
+ t_head->t_next = t->t_next; |
|
294 |
+ t->t_next = NULL; |
|
295 |
+ |
|
296 |
+ return ret; |
|
297 |
+} |
|
298 |
+ |
|
299 |
+/* |
|
247 | 300 |
* Transfer the contents of the text into a blob |
248 | 301 |
* The caller must free the returned blob if b is NULL |
249 | 302 |
*/ |
... | ... |
@@ -365,7 +424,8 @@ addToFileblob(const line_t *line, void *arg) |
365 | 365 |
if(line) { |
366 | 366 |
const char *l = lineGetData(line); |
367 | 367 |
|
368 |
- fileblobAddData(fb, (const unsigned char *)l, strlen(l)); |
|
368 |
+ if(l) |
|
369 |
+ fileblobAddData(fb, (const unsigned char *)l, strlen(l)); |
|
369 | 370 |
} |
370 | 371 |
fileblobAddData(fb, (const unsigned char *)"\n", 1); |
371 | 372 |
} |
... | ... |
@@ -373,6 +433,11 @@ addToFileblob(const line_t *line, void *arg) |
373 | 373 |
static void * |
374 | 374 |
textIterate(text *t_text, void (*cb)(const line_t *item, void *arg), void *arg, int destroy) |
375 | 375 |
{ |
376 |
+ /* |
|
377 |
+ * Have two loops rather than one, so that we're not checking the |
|
378 |
+ * value of "destroy" lots and lots of times |
|
379 |
+ */ |
|
380 |
+#if 0 |
|
376 | 381 |
while(t_text) { |
377 | 382 |
(*cb)(t_text->t_line, arg); |
378 | 383 |
|
... | ... |
@@ -383,5 +448,24 @@ textIterate(text *t_text, void (*cb)(const line_t *item, void *arg), void *arg, |
383 | 383 |
|
384 | 384 |
t_text = t_text->t_next; |
385 | 385 |
} |
386 |
+#else |
|
387 |
+ if(destroy) |
|
388 |
+ while(t_text) { |
|
389 |
+ (*cb)(t_text->t_line, arg); |
|
390 |
+ |
|
391 |
+ if(t_text->t_line) { |
|
392 |
+ lineUnlink(t_text->t_line); |
|
393 |
+ t_text->t_line = NULL; |
|
394 |
+ } |
|
395 |
+ |
|
396 |
+ t_text = t_text->t_next; |
|
397 |
+ } |
|
398 |
+ else |
|
399 |
+ while(t_text) { |
|
400 |
+ (*cb)(t_text->t_line, arg); |
|
401 |
+ |
|
402 |
+ t_text = t_text->t_next; |
|
403 |
+ } |
|
404 |
+#endif |
|
386 | 405 |
return arg; |
387 | 406 |
} |
... | ... |
@@ -40,6 +40,7 @@ |
40 | 40 |
* |
41 | 41 |
*/ |
42 | 42 |
|
43 |
+/* The contents could change, ONLY access in text.c */ |
|
43 | 44 |
typedef struct text { |
44 | 45 |
line_t *t_line; /* NULL if the line is empty */ |
45 | 46 |
struct text *t_next; |
... | ... |
@@ -49,7 +50,7 @@ typedef struct text { |
49 | 49 |
|
50 | 50 |
void textDestroy(text *t_head); |
51 | 51 |
text *textClean(text *t_head); |
52 |
-text *textAdd(text *t_head, const text *t); |
|
53 | 52 |
text *textAddMessage(text *aText, message *aMessage); |
53 |
+text *textMove(text *t_head, text *t); |
|
54 | 54 |
blob *textToBlob(text *t, blob *b, int destroy); |
55 | 55 |
fileblob *textToFileblob(text *t, fileblob *fb, int destroy); |