1 /*
2 * Yerase's TNEF Stream Reader Library
3 * Copyright (C) 2003 Randall E. Hand
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 *
19 * You can contact me at randall.hand@gmail.com for questions or assistance
20 */
21 #include <stdio.h>
22 #include <string.h>
23 #include <stdlib.h>
24 #include <ctype.h>
25 #include <limits.h>
26 #include "ytnef.h"
27 #include "tnef-errors.h"
28 #include "mapi.h"
29 #include "mapidefs.h"
30 #include "mapitags.h"
31 #include "config.h"
32
33 #define RTF_PREBUF "{\\rtf1\\ansi\\mac\\deff0\\deftab720{\\fonttbl;}{\\f0\\fnil \\froman \\fswiss \\fmodern \\fscript \\fdecor MS Sans SerifSymbolArialTimes New RomanCourier{\\colortbl\\red0\\green0\\blue0\n\r\\par \\pard\\plain\\f0\\fs20\\b\\i\\u\\tab\\tx"
34 #define DEBUG(lvl, curlvl, msg) \
35 if ((lvl) >= (curlvl)) \
36 printf("DEBUG(%i/%i): %s\n", curlvl, lvl, msg);
37 #define DEBUG1(lvl, curlvl, msg, var1) \
38 if ((lvl) >= (curlvl)) { \
39 printf("DEBUG(%i/%i):", curlvl, lvl); \
40 printf(msg, var1); \
41 printf("\n"); \
42 }
43 #define DEBUG2(lvl, curlvl, msg, var1, var2) \
44 if ((lvl) >= (curlvl)) { \
45 printf("DEBUG(%i/%i):", curlvl, lvl); \
46 printf(msg, var1, var2); \
47 printf("\n"); \
48 }
49 #define DEBUG3(lvl, curlvl, msg, var1, var2, var3) \
50 if ((lvl) >= (curlvl)) { \
51 printf("DEBUG(%i/%i):", curlvl, lvl); \
52 printf(msg, var1, var2,var3); \
53 printf("\n"); \
54 }
55
56 #define MIN(x,y) (((x)<(y))?(x):(y))
57
58 #define PREALLOCCHECK(sz,max) { if(sz==0||(unsigned)sz>max) { printf("ERROR: invalid alloc size %u at %s : %i, suspected corruption\n", (unsigned)sz, __FILE__, __LINE__); return(-1); } }
59 #define ALLOCCHECK(x) { if(!x) { printf("Out of Memory at %s : %i\n", __FILE__, __LINE__); return(-1); } }
60 #define ALLOCCHECK_CHAR(x) { if(!x) { printf("Out of Memory at %s : %i\n", __FILE__, __LINE__); return(NULL); } }
61 #define SIZECHECK(x) { if ((((char *)d - (char *)data) + x) > size) { printf("Corrupted file detected at %s : %i\n", __FILE__, __LINE__); return(-1); } }
62
63 int TNEFFillMapi(TNEFStruct *TNEF, BYTE *data, DWORD size, MAPIProps *p);
64 void SetFlip(void);
65
66 int TNEFDefaultHandler STD_ARGLIST;
67 int TNEFAttachmentFilename STD_ARGLIST;
68 int TNEFAttachmentSave STD_ARGLIST;
69 int TNEFDetailedPrint STD_ARGLIST;
70 int TNEFHexBreakdown STD_ARGLIST;
71 int TNEFBody STD_ARGLIST;
72 int TNEFRendData STD_ARGLIST;
73 int TNEFDateHandler STD_ARGLIST;
74 int TNEFPriority STD_ARGLIST;
75 int TNEFVersion STD_ARGLIST;
76 int TNEFMapiProperties STD_ARGLIST;
77 int TNEFIcon STD_ARGLIST;
78 int TNEFSubjectHandler STD_ARGLIST;
79 int TNEFFromHandler STD_ARGLIST;
80 int TNEFRecipTable STD_ARGLIST;
81 int TNEFAttachmentMAPI STD_ARGLIST;
82 int TNEFSentFor STD_ARGLIST;
83 int TNEFMessageClass STD_ARGLIST;
84 int TNEFMessageID STD_ARGLIST;
85 int TNEFParentID STD_ARGLIST;
86 int TNEFOriginalMsgClass STD_ARGLIST;
87 int TNEFCodePage STD_ARGLIST;
88
89
90 BYTE *TNEFFileContents = NULL;
91 DWORD TNEFFileContentsSize;
92 BYTE *TNEFFileIcon = NULL;
93 DWORD TNEFFileIconSize;
94
95 int IsCompressedRTF(variableLength *p);
96
97 TNEFHandler TNEFList[] = {
98 {attNull, "Null", TNEFDefaultHandler},
99 {attFrom, "From", TNEFFromHandler},
100 {attSubject, "Subject", TNEFSubjectHandler},
101 {attDateSent, "Date Sent", TNEFDateHandler},
102 {attDateRecd, "Date Received", TNEFDateHandler},
103 {attMessageStatus, "Message Status", TNEFDefaultHandler},
104 {attMessageClass, "Message Class", TNEFMessageClass},
105 {attMessageID, "Message ID", TNEFMessageID},
106 {attParentID, "Parent ID", TNEFParentID},
107 {attConversationID, "Conversation ID", TNEFDefaultHandler},
108 {attBody, "Body", TNEFBody},
109 {attPriority, "Priority", TNEFPriority},
110 {attAttachData, "Attach Data", TNEFAttachmentSave},
111 {attAttachTitle, "Attach Title", TNEFAttachmentFilename},
112 {attAttachMetaFile, "Attach Meta-File", TNEFIcon},
113 {attAttachCreateDate, "Attachment Create Date", TNEFDateHandler},
114 {attAttachModifyDate, "Attachment Modify Date", TNEFDateHandler},
115 {attDateModified, "Date Modified", TNEFDateHandler},
116 {attAttachTransportFilename, "Attachment Transport name", TNEFDefaultHandler},
117 {attAttachRenddata, "Attachment Display info", TNEFRendData},
118 {attMAPIProps, "MAPI Properties", TNEFMapiProperties},
119 {attRecipTable, "Recip Table", TNEFRecipTable},
120 {attAttachment, "Attachment", TNEFAttachmentMAPI},
121 {attTnefVersion, "TNEF Version", TNEFVersion},
122 {attOemCodepage, "OEM CodePage", TNEFCodePage},
123 {attOriginalMessageClass, "Original Message Class", TNEFOriginalMsgClass},
124 {attOwner, "Owner", TNEFDefaultHandler},
125 {attSentFor, "Sent For", TNEFSentFor},
126 {attDelegate, "Delegate", TNEFDefaultHandler},
127 {attDateStart, "Date Start", TNEFDateHandler},
128 {attDateEnd, "Date End", TNEFDateHandler},
129 {attAidOwner, "Aid Owner", TNEFDefaultHandler},
130 {attRequestRes, "Request Response", TNEFDefaultHandler}
131 };
132
133
SwapWord(BYTE * p,int size)134 WORD SwapWord(BYTE *p, int size) {
135 union BYTES2WORD
136 {
137 WORD word;
138 BYTE bytes[sizeof(WORD)];
139 };
140
141 union BYTES2WORD converter;
142 converter.word = 0;
143 int i = 0;
144 int correct = size > sizeof(WORD) ? sizeof(WORD) : size;
145
146 #ifdef WORDS_BIGENDIAN
147 for (i = 0; i < correct; ++i)
148 {
149 converter.bytes[i] = p[correct - i];
150 }
151 #else
152 for (i = 0; i < correct; ++i)
153 {
154 converter.bytes[i] = p[i];
155 }
156 #endif
157
158 return converter.word;
159 }
160
SwapDWord(BYTE * p,int size)161 DWORD SwapDWord(BYTE *p, int size) {
162 union BYTES2DWORD
163 {
164 DWORD dword;
165 BYTE bytes[sizeof(DWORD)];
166 };
167
168 union BYTES2DWORD converter;
169 converter.dword = 0;
170 int i = 0;
171 int correct = size > sizeof(DWORD) ? sizeof(DWORD) : size;
172
173 #ifdef WORDS_BIGENDIAN
174 for (i = 0; i < correct; ++i)
175 {
176 converter.bytes[i] = p[correct - i];
177 }
178 #else
179 for (i = 0; i < correct; ++i)
180 {
181 converter.bytes[i] = p[i];
182 }
183 #endif
184
185 return converter.dword;
186 }
187
188
189
SwapDDWord(BYTE * p,int size)190 DDWORD SwapDDWord(BYTE *p, int size) {
191 union BYTES2DDWORD
192 {
193 DDWORD ddword;
194 BYTE bytes[sizeof(DDWORD)];
195 };
196
197 union BYTES2DDWORD converter;
198 converter.ddword = 0;
199 int i = 0;
200 int correct = size > sizeof(DDWORD) ? sizeof(DDWORD) : size;
201
202 #ifdef WORDS_BIGENDIAN
203 for (i = 0; i < correct; ++i)
204 {
205 converter.bytes[i] = p[correct - i];
206 }
207 #else
208 for (i = 0; i < correct; ++i)
209 {
210 converter.bytes[i] = p[i];
211 }
212 #endif
213
214 return converter.ddword;
215 }
216
217 /* convert 16-bit unicode to UTF8 unicode */
to_utf8(size_t len,char * buf)218 char *to_utf8(size_t len, char *buf) {
219 int i, j = 0;
220 // an arbitrary length limit should be imposed by the caller of this function
221 char *utf8 = malloc(3 * len / 2 + 1);
222
223 for (i = 0; i < len - 1; i += 2) {
224 unsigned int c = SwapWord((BYTE *)buf + i, 2);
225 if (c <= 0x007f) {
226 utf8[j++] = 0x00 | ((c & 0x007f) >> 0);
227 } else if (c < 0x07ff) {
228 utf8[j++] = 0xc0 | ((c & 0x07c0) >> 6);
229 utf8[j++] = 0x80 | ((c & 0x003f) >> 0);
230 } else {
231 utf8[j++] = 0xe0 | ((c & 0xf000) >> 12);
232 utf8[j++] = 0x80 | ((c & 0x0fc0) >> 6);
233 utf8[j++] = 0x80 | ((c & 0x003f) >> 0);
234 }
235 }
236
237 /* just in case the original was not null terminated */
238 utf8[j++] = '\0';
239
240 return utf8;
241 }
242
243
244 // -----------------------------------------------------------------------------
245 int TNEFDefaultHandler STD_ARGLIST {
246 if (TNEF->Debug >= 1)
247 printf("%s: [%i] %.*s\n", TNEFList[id].name, size, size, data);
248 return 0;
249 }
250
251 // -----------------------------------------------------------------------------
252 int TNEFCodePage STD_ARGLIST {
253 TNEF->CodePage.size = size;
254 TNEF->CodePage.data = calloc(size, sizeof(BYTE));
255 ALLOCCHECK(TNEF->CodePage.data);
256 memcpy(TNEF->CodePage.data, data, size);
257 return 0;
258 }
259
260 // -----------------------------------------------------------------------------
261 int TNEFParentID STD_ARGLIST {
262 memcpy(TNEF->parentID, data, MIN(size, sizeof(TNEF->parentID)));
263 return 0;
264 }
265 // -----------------------------------------------------------------------------
266 int TNEFMessageID STD_ARGLIST {
267 memcpy(TNEF->messageID, data, MIN(size, sizeof(TNEF->messageID)));
268 return 0;
269 }
270 // -----------------------------------------------------------------------------
271 int TNEFBody STD_ARGLIST {
272 TNEF->body.size = size;
273 PREALLOCCHECK(size, 100000);
274 TNEF->body.data = calloc(size+1, sizeof(BYTE));
275 ALLOCCHECK(TNEF->body.data);
276 memcpy(TNEF->body.data, data, size);
277 return 0;
278 }
279 // -----------------------------------------------------------------------------
280 int TNEFOriginalMsgClass STD_ARGLIST {
281 TNEF->OriginalMessageClass.size = size;
282 PREALLOCCHECK(size, 100);
283 TNEF->OriginalMessageClass.data = calloc(size+1, sizeof(BYTE));
284 ALLOCCHECK(TNEF->OriginalMessageClass.data);
285 memcpy(TNEF->OriginalMessageClass.data, data, size);
286 return 0;
287 }
288 // -----------------------------------------------------------------------------
289 int TNEFMessageClass STD_ARGLIST {
290 memcpy(TNEF->messageClass, data, MIN(size, sizeof(TNEF->messageClass)-1));
291 return 0;
292 }
293 // -----------------------------------------------------------------------------
294 int TNEFFromHandler STD_ARGLIST {
295 PREALLOCCHECK(size, 100);
296 TNEF->from.data = calloc(size+1, sizeof(BYTE));
297 ALLOCCHECK(TNEF->from.data);
298 TNEF->from.size = size;
299 memcpy(TNEF->from.data, data, size);
300 return 0;
301 }
302 // -----------------------------------------------------------------------------
303 int TNEFSubjectHandler STD_ARGLIST {
304 if (TNEF->subject.data)
305 free(TNEF->subject.data);
306
307 PREALLOCCHECK(size, 100);
308 TNEF->subject.data = calloc(size+1, sizeof(BYTE));
309 ALLOCCHECK(TNEF->subject.data);
310 TNEF->subject.size = size;
311 memcpy(TNEF->subject.data, data, size);
312 return 0;
313 }
314
315 // -----------------------------------------------------------------------------
316 int TNEFRendData STD_ARGLIST {
317 Attachment *p;
318 // Find the last attachment.
319 p = &(TNEF->starting_attach);
320 while (p->next != NULL) p = p->next;
321
322 // Add a new one
323 p->next = calloc(1, sizeof(Attachment));
324 ALLOCCHECK(p->next);
325 p = p->next;
326
327 TNEFInitAttachment(p);
328
329 int correct = (size >= sizeof(renddata)) ? sizeof(renddata) : size;
330 memcpy(&(p->RenderData), data, correct);
331 return 0;
332 }
333
334 // -----------------------------------------------------------------------------
335 int TNEFVersion STD_ARGLIST {
336 WORD major;
337 WORD minor;
338 minor = SwapWord((BYTE*)data, size);
339 major = SwapWord((BYTE*)data + 2, size - 2);
340
341 snprintf(TNEF->version, sizeof(TNEF->version), "TNEF%i.%i", major, minor);
342 return 0;
343 }
344
345 // -----------------------------------------------------------------------------
346 int TNEFIcon STD_ARGLIST {
347 Attachment *p;
348 // Find the last attachment.
349 p = &(TNEF->starting_attach);
350 while (p->next != NULL) p = p->next;
351
352 p->IconData.size = size;
353 PREALLOCCHECK(size, 10000);
354 p->IconData.data = calloc(size, sizeof(BYTE));
355 ALLOCCHECK(p->IconData.data);
356 memcpy(p->IconData.data, data, size);
357 return 0;
358 }
359
360 // -----------------------------------------------------------------------------
361 int TNEFRecipTable STD_ARGLIST {
362 DWORD count;
363 BYTE *d;
364 int current_row;
365 int propcount;
366 int current_prop;
367
368 d = (BYTE*)data;
369 SIZECHECK(sizeof(DWORD));
370 count = SwapDWord((BYTE*)d, sizeof(DWORD));
371 d += sizeof(DWORD);
372 // printf("Recipient Table containing %u rows\n", count);
373
374 return 0;
375
376 for (current_row = 0; current_row < count; current_row++) {
377 propcount = SwapDWord((BYTE*)d, sizeof(DWORD));
378 if (TNEF->Debug >= 1)
379 printf("> Row %i contains %i properties\n", current_row, propcount);
380 d += sizeof(DWORD);
381 for (current_prop = 0; current_prop < propcount; current_prop++) {
382
383
384 }
385 }
386 return 0;
387 }
388 // -----------------------------------------------------------------------------
389 int TNEFAttachmentMAPI STD_ARGLIST {
390 Attachment *p;
391 // Find the last attachment.
392 //
393 p = &(TNEF->starting_attach);
394 while (p->next != NULL) p = p->next;
395 return TNEFFillMapi(TNEF, (BYTE*)data, size, &(p->MAPI));
396 }
397 // -----------------------------------------------------------------------------
398 int TNEFMapiProperties STD_ARGLIST {
399 if (TNEFFillMapi(TNEF, (BYTE*)data, size, &(TNEF->MapiProperties)) < 0) {
400 printf("ERROR Parsing MAPI block\n");
401 return -1;
402 };
403 if (TNEF->Debug >= 3) {
404 MAPIPrint(&(TNEF->MapiProperties));
405 }
406 return 0;
407 }
408
TNEFFillMapi(TNEFStruct * TNEF,BYTE * data,DWORD size,MAPIProps * p)409 int TNEFFillMapi(TNEFStruct *TNEF, BYTE *data, DWORD size, MAPIProps *p) {
410 int i, j;
411 DWORD num;
412 BYTE *d;
413 MAPIProperty *mp;
414 DWORD type;
415 DWORD length;
416 variableLength *vl;
417
418 WORD temp_word;
419 DWORD temp_dword;
420 DDWORD temp_ddword;
421 int mp_count = 0, p_count = 0;
422 int count = -1;
423 int offset;
424
425 d = data;
426 SIZECHECK(sizeof(DWORD));
427 p_count = SwapDWord((BYTE*)data, sizeof(DWORD));
428 d += sizeof(DWORD);
429 // Arbitrary limit on the amount of properties
430 PREALLOCCHECK(p_count, 1000);
431 p->properties = calloc(p_count, sizeof(MAPIProperty));
432 ALLOCCHECK(p->properties);
433 p->count = p_count;
434 mp = p->properties;
435
436 for (i = 0; i < p->count; i++) {
437 if (count == -1) {
438 SIZECHECK(sizeof(DWORD));
439 mp->id = SwapDWord((BYTE*)d, sizeof(DWORD));
440 d += sizeof(DWORD);
441 mp->custom = 0;
442 mp_count = 1;
443 mp->namedproperty = 0;
444 length = -1;
445 if (PROP_ID(mp->id) >= 0x8000) {
446 // Read the GUID
447 SIZECHECK(16);
448 memcpy(&(mp->guid[0]), d, 16);
449 d += 16;
450
451 SIZECHECK(sizeof(DWORD));
452 length = SwapDWord((BYTE*)d, sizeof(DWORD));
453 d += sizeof(DWORD);
454 if (length > 0) {
455 PREALLOCCHECK(length, 1000);
456 mp->propnames = calloc(length, sizeof(variableLength));
457 ALLOCCHECK(mp->propnames);
458 mp->namedproperty = length;
459 while (length > 0) {
460 SIZECHECK(sizeof(DWORD));
461 type = SwapDWord((BYTE*)d, sizeof(DWORD));
462 d += sizeof(DWORD);
463 PREALLOCCHECK(type, 100);
464 mp->propnames[length - 1].data = calloc(type+1, sizeof(BYTE));
465 ALLOCCHECK(mp->propnames[length - 1].data);
466 mp->propnames[length - 1].size = type;
467 SIZECHECK(type);
468 for (j = 0; j < (type >> 1); j++) {
469 mp->propnames[length - 1].data[j] = d[j * 2];
470 }
471 d += type + ((type % 4) ? (4 - type % 4) : 0);
472 length--;
473 }
474 } else {
475 // READ the type
476 SIZECHECK(sizeof(DWORD));
477 type = SwapDWord((BYTE*)d, sizeof(DWORD));
478 d += sizeof(DWORD);
479 mp->id = PROP_TAG(PROP_TYPE(mp->id), type);
480 }
481 mp->custom = 1;
482 }
483
484 DEBUG2(TNEF->Debug, 3, "Type id = %04x, Prop id = %04x", PROP_TYPE(mp->id),
485 PROP_ID(mp->id));
486 if (PROP_TYPE(mp->id) & MV_FLAG) {
487 mp->id = PROP_TAG(PROP_TYPE(mp->id) - MV_FLAG, PROP_ID(mp->id));
488 SIZECHECK(sizeof(DWORD));
489 mp_count = SwapDWord((BYTE*)d, sizeof(DWORD));
490 d += sizeof(DWORD);
491 count = 0;
492 }
493 PREALLOCCHECK(mp_count, 1000);
494 mp->data = calloc(mp_count, sizeof(variableLength));
495 ALLOCCHECK(mp->data);
496 mp->count = mp_count;
497 vl = mp->data;
498 } else {
499 i--;
500 count++;
501 vl = &(mp->data[count]);
502 }
503
504 switch (PROP_TYPE(mp->id)) {
505 case PT_BINARY:
506 case PT_OBJECT:
507 case PT_STRING8:
508 case PT_UNICODE:
509 // First number of objects (assume 1 for now)
510 if (count == -1) {
511 SIZECHECK(sizeof(DWORD));
512 vl->size = SwapDWord((BYTE*)d, sizeof(DWORD));
513 d += sizeof(DWORD);
514 }
515 // now size of object
516 SIZECHECK(sizeof(DWORD));
517 vl->size = SwapDWord((BYTE*)d, sizeof(DWORD));
518 d += sizeof(DWORD);
519
520 // now actual object
521 if (vl->size != 0) {
522 SIZECHECK(vl->size);
523 PREALLOCCHECK(vl->size, 100000);
524 if (PROP_TYPE(mp->id) == PT_UNICODE) {
525 vl->data =(BYTE*) to_utf8(vl->size, (char*)d);
526 if(vl->data == NULL)
527 return -1;
528 } else {
529 vl->data = calloc(vl->size, sizeof(BYTE));
530 ALLOCCHECK(vl->data);
531 memcpy(vl->data, d, vl->size);
532 }
533 } else {
534 vl->data = NULL;
535 }
536
537 // Make sure to read in a multiple of 4
538 num = vl->size;
539 offset = ((num % 4) ? (4 - num % 4) : 0);
540 d += num + ((num % 4) ? (4 - num % 4) : 0);
541 break;
542
543 case PT_I2:
544 // Read in 2 bytes, but proceed by 4 bytes
545 vl->size = 2;
546 PREALLOCCHECK(vl->size, 10000);
547 vl->data = calloc(vl->size, sizeof(WORD));
548 ALLOCCHECK(vl->data);
549 SIZECHECK(sizeof(WORD))
550 temp_word = SwapWord((BYTE*)d, sizeof(WORD));
551 memcpy(vl->data, &temp_word, vl->size);
552 d += 4;
553 break;
554 case PT_BOOLEAN:
555 case PT_LONG:
556 case PT_R4:
557 case PT_CURRENCY:
558 case PT_APPTIME:
559 case PT_ERROR:
560 vl->size = 4;
561 PREALLOCCHECK(vl->size, 10000);
562 vl->data = calloc(vl->size, sizeof(BYTE));
563 ALLOCCHECK(vl->data);
564 SIZECHECK(4);
565 temp_dword = SwapDWord((BYTE*)d, 4);
566 memcpy(vl->data, &temp_dword, vl->size);
567 d += 4;
568 break;
569 case PT_DOUBLE:
570 case PT_I8:
571 case PT_SYSTIME:
572 vl->size = 8;
573 PREALLOCCHECK(vl->size, 10000);
574 vl->data = calloc(vl->size, sizeof(BYTE));
575 ALLOCCHECK(vl->data);
576 SIZECHECK(8);
577 temp_ddword = SwapDDWord(d, 8);
578 memcpy(vl->data, &temp_ddword, vl->size);
579 d += 8;
580 break;
581 case PT_CLSID:
582 vl->size = 16;
583 PREALLOCCHECK(vl->size, 10000);
584 vl->data = calloc(vl->size, sizeof(BYTE));
585 ALLOCCHECK(vl->data);
586 SIZECHECK(vl->size);
587 memcpy(vl->data, d, vl->size);
588 d+=16;
589 break;
590 default:
591 printf("Bad file\n");
592 return -1;
593 }
594
595 switch (PROP_ID(mp->id)) {
596 case PR_SUBJECT:
597 case PR_SUBJECT_IPM:
598 case PR_ORIGINAL_SUBJECT:
599 case PR_NORMALIZED_SUBJECT:
600 case PR_CONVERSATION_TOPIC:
601 DEBUG(TNEF->Debug, 3, "Got a Subject");
602 if (TNEF->subject.size == 0) {
603 int i;
604 DEBUG(TNEF->Debug, 3, "Assigning a Subject");
605 PREALLOCCHECK(vl->size, 100);
606 TNEF->subject.data = calloc(vl->size+1, sizeof(BYTE));
607 ALLOCCHECK(TNEF->subject.data);
608 TNEF->subject.size = vl->size;
609 memcpy(TNEF->subject.data, vl->data, vl->size);
610 // Unfortunately, we have to normalize out some invalid
611 // characters, or else the file won't write
612 for (i = 0; i != TNEF->subject.size; i++) {
613 switch (TNEF->subject.data[i]) {
614 case '\\':
615 case '/':
616 case '\0':
617 TNEF->subject.data[i] = '_';
618 break;
619 }
620 }
621 }
622 break;
623 }
624
625 if (count == (mp->count - 1)) {
626 count = -1;
627 }
628 if (count == -1) {
629 mp++;
630 }
631
632 }
633 if ((d - data) < size) {
634 if (TNEF->Debug >= 1) {
635 printf("ERROR DURING MAPI READ\n");
636 printf("Read %td bytes, Expected %u bytes\n", (d - data), size);
637 printf("%td bytes missing\n", size - (d - data));
638 }
639 return -1;
640 } else if ((d - data) > size) {
641 if (TNEF->Debug >= 1) {
642 printf("ERROR DURING MAPI READ\n");
643 printf("Read %td bytes, Expected %u bytes\n", (d - data), size);
644 printf("%li bytes extra\n", (d - data) - size);
645 }
646 return -1;
647 }
648 return 0;
649 }
650 // -----------------------------------------------------------------------------
651 int TNEFSentFor STD_ARGLIST {
652 WORD name_length, addr_length;
653 BYTE *d;
654
655 d = (BYTE*)data;
656
657 while ((d - (BYTE*)data) < size) {
658 SIZECHECK(sizeof(WORD));
659 name_length = SwapWord((BYTE*)d, sizeof(WORD));
660 d += sizeof(WORD);
661 SIZECHECK(name_length);
662 if (TNEF->Debug >= 1)
663 printf("Sent For : %.*s", name_length, d);
664 d += name_length;
665
666 SIZECHECK(sizeof(WORD));
667 addr_length = SwapWord((BYTE*)d, sizeof(WORD));
668 d += sizeof(WORD);
669 SIZECHECK(addr_length);
670 if (TNEF->Debug >= 1)
671 printf("<%.*s>\n", addr_length, d);
672 d += addr_length;
673 }
674 return 0;
675 }
676 // -----------------------------------------------------------------------------
677 int TNEFDateHandler STD_ARGLIST {
678 dtr *Date;
679 Attachment *p;
680 WORD * tmp_src, *tmp_dst;
681 int i;
682
683 if (size < sizeof(dtr))
684 return -1;
685
686 p = &(TNEF->starting_attach);
687 switch (TNEFList[id].id) {
688 case attDateSent: Date = &(TNEF->dateSent); break;
689 case attDateRecd: Date = &(TNEF->dateReceived); break;
690 case attDateModified: Date = &(TNEF->dateModified); break;
691 case attDateStart: Date = &(TNEF->DateStart); break;
692 case attDateEnd: Date = &(TNEF->DateEnd); break;
693 case attAttachCreateDate:
694 while (p->next != NULL) p = p->next;
695 Date = &(p->CreateDate);
696 break;
697 case attAttachModifyDate:
698 while (p->next != NULL) p = p->next;
699 Date = &(p->ModifyDate);
700 break;
701 default:
702 if (TNEF->Debug >= 1)
703 printf("MISSING CASE\n");
704 return YTNEF_UNKNOWN_PROPERTY;
705 }
706
707 tmp_src = (WORD *)data;
708 tmp_dst = (WORD *)Date;
709 for (i = 0; i < sizeof(dtr) / sizeof(WORD); i++) {
710 *tmp_dst++ = SwapWord((BYTE *)tmp_src++, sizeof(WORD));
711 }
712 return 0;
713 }
714
TNEFPrintDate(dtr Date)715 void TNEFPrintDate(dtr Date) {
716 char days[7][15] = {"Sunday", "Monday", "Tuesday",
717 "Wednesday", "Thursday", "Friday", "Saturday"
718 };
719 char months[12][15] = {"January", "February", "March", "April", "May",
720 "June", "July", "August", "September", "October", "November",
721 "December"
722 };
723
724 if (Date.wDayOfWeek < 7)
725 printf("%s ", days[Date.wDayOfWeek]);
726
727 if ((Date.wMonth < 13) && (Date.wMonth > 0))
728 printf("%s ", months[Date.wMonth - 1]);
729
730 printf("%hu, %hu ", Date.wDay, Date.wYear);
731
732 if (Date.wHour > 12)
733 printf("%i:%02hu:%02hu pm", (Date.wHour - 12),
734 Date.wMinute, Date.wSecond);
735 else if (Date.wHour == 12)
736 printf("%hu:%02hu:%02hu pm", (Date.wHour),
737 Date.wMinute, Date.wSecond);
738 else
739 printf("%hu:%02hu:%02hu am", Date.wHour,
740 Date.wMinute, Date.wSecond);
741 }
742 // -----------------------------------------------------------------------------
743 int TNEFHexBreakdown STD_ARGLIST {
744 int i;
745 if (TNEF->Debug == 0)
746 return 0;
747
748 printf("%s: [%i bytes] \n", TNEFList[id].name, size);
749
750 for (i = 0; i < size; i++) {
751 printf("%02x ", data[i]);
752 if ((i + 1) % 16 == 0) printf("\n");
753 }
754 printf("\n");
755 return 0;
756 }
757
758 // -----------------------------------------------------------------------------
759 int TNEFDetailedPrint STD_ARGLIST {
760 int i;
761 if (TNEF->Debug == 0)
762 return 0;
763
764 printf("%s: [%i bytes] \n", TNEFList[id].name, size);
765
766 for (i = 0; i < size; i++) {
767 printf("%c", data[i]);
768 }
769 printf("\n");
770 return 0;
771 }
772
773 // -----------------------------------------------------------------------------
774 int TNEFAttachmentFilename STD_ARGLIST {
775 Attachment *p;
776 p = &(TNEF->starting_attach);
777 while (p->next != NULL) p = p->next;
778
779 p->Title.size = size;
780 PREALLOCCHECK(size, 100);
781 p->Title.data = calloc(size+1, sizeof(BYTE));
782 ALLOCCHECK(p->Title.data);
783 memcpy(p->Title.data, data, size);
784
785 return 0;
786 }
787
788 // -----------------------------------------------------------------------------
789 int TNEFAttachmentSave STD_ARGLIST {
790 Attachment *p;
791 p = &(TNEF->starting_attach);
792 while (p->next != NULL) p = p->next;
793
794 p->FileData.data = calloc(sizeof(char), size);
795 ALLOCCHECK(p->FileData.data);
796 p->FileData.size = size;
797
798 memcpy(p->FileData.data, data, size);
799
800 return 0;
801 }
802
803 // -----------------------------------------------------------------------------
804 int TNEFPriority STD_ARGLIST {
805 DWORD value;
806
807 value = SwapDWord((BYTE*)data, size);
808 switch (value) {
809 case 3:
810 sprintf((TNEF->priority), "high");
811 break;
812 case 2:
813 sprintf((TNEF->priority), "normal");
814 break;
815 case 1:
816 sprintf((TNEF->priority), "low");
817 break;
818 default:
819 sprintf((TNEF->priority), "N/A");
820 break;
821 }
822 return 0;
823 }
824
825 // -----------------------------------------------------------------------------
TNEFCheckForSignature(DWORD sig)826 int TNEFCheckForSignature(DWORD sig) {
827 DWORD signature = 0x223E9F78;
828
829 sig = SwapDWord((BYTE *)&sig, sizeof(DWORD));
830
831 if (signature == sig) {
832 return 0;
833 } else {
834 return YTNEF_NOT_TNEF_STREAM;
835 }
836 }
837
838 // -----------------------------------------------------------------------------
TNEFGetKey(TNEFStruct * TNEF,WORD * key)839 int TNEFGetKey(TNEFStruct *TNEF, WORD *key) {
840 if (TNEF->IO.ReadProc(&(TNEF->IO), sizeof(WORD), 1, key) < 1) {
841 if (TNEF->Debug >= 1)
842 printf("Error reading Key\n");
843 return YTNEF_ERROR_READING_DATA;
844 }
845 *key = SwapWord((BYTE *)key, sizeof(WORD));
846
847 DEBUG1(TNEF->Debug, 2, "Key = 0x%X", *key);
848 DEBUG1(TNEF->Debug, 2, "Key = %i", *key);
849 return 0;
850 }
851
852 // -----------------------------------------------------------------------------
TNEFGetHeader(TNEFStruct * TNEF,DWORD * type,DWORD * size)853 int TNEFGetHeader(TNEFStruct *TNEF, DWORD *type, DWORD *size) {
854 BYTE component;
855
856 DEBUG(TNEF->Debug, 2, "About to read Component");
857 if (TNEF->IO.ReadProc(&(TNEF->IO), sizeof(BYTE), 1, &component) < 1) {
858 return YTNEF_ERROR_READING_DATA;
859 }
860
861
862 DEBUG(TNEF->Debug, 2, "About to read type");
863 if (TNEF->IO.ReadProc(&(TNEF->IO), sizeof(DWORD), 1, type) < 1) {
864 if (TNEF->Debug >= 1)
865 printf("ERROR: Error reading type\n");
866 return YTNEF_ERROR_READING_DATA;
867 }
868 DEBUG1(TNEF->Debug, 2, "Type = 0x%X", *type);
869 DEBUG1(TNEF->Debug, 2, "Type = %u", *type);
870
871
872 DEBUG(TNEF->Debug, 2, "About to read size");
873 if (TNEF->IO.ReadProc(&(TNEF->IO), sizeof(DWORD), 1, size) < 1) {
874 if (TNEF->Debug >= 1)
875 printf("ERROR: Error reading size\n");
876 return YTNEF_ERROR_READING_DATA;
877 }
878
879
880 DEBUG1(TNEF->Debug, 2, "Size = %u", *size);
881
882 *type = SwapDWord((BYTE *)type, sizeof(DWORD));
883 *size = SwapDWord((BYTE *)size, sizeof(DWORD));
884
885 return 0;
886 }
887
888 // -----------------------------------------------------------------------------
TNEFRawRead(TNEFStruct * TNEF,BYTE * data,DWORD size,WORD * checksum)889 int TNEFRawRead(TNEFStruct *TNEF, BYTE *data, DWORD size, WORD *checksum) {
890 WORD temp;
891 int i;
892
893 if (TNEF->IO.ReadProc(&TNEF->IO, sizeof(BYTE), size, data) < size) {
894 if (TNEF->Debug >= 1)
895 printf("ERROR: Error reading data\n");
896 return YTNEF_ERROR_READING_DATA;
897 }
898
899
900 if (checksum != NULL) {
901 *checksum = 0;
902 for (i = 0; i < size; i++) {
903 temp = data[i];
904 *checksum = (*checksum + temp);
905 }
906 }
907 return 0;
908 }
909
910 #define INITVARLENGTH(x) (x).data = NULL; (x).size = 0;
911 #define INITDTR(x) (x).wYear=0; (x).wMonth=0; (x).wDay=0; \
912 (x).wHour=0; (x).wMinute=0; (x).wSecond=0; \
913 (x).wDayOfWeek=0;
914 #define INITSTR(x) memset((x), 0, sizeof(x));
TNEFInitMapi(MAPIProps * p)915 void TNEFInitMapi(MAPIProps *p) {
916 p->count = 0;
917 p->properties = NULL;
918 }
919
TNEFInitAttachment(Attachment * p)920 void TNEFInitAttachment(Attachment *p) {
921 INITDTR(p->Date);
922 INITVARLENGTH(p->Title);
923 INITVARLENGTH(p->MetaFile);
924 INITDTR(p->CreateDate);
925 INITDTR(p->ModifyDate);
926 INITVARLENGTH(p->TransportFilename);
927 INITVARLENGTH(p->FileData);
928 INITVARLENGTH(p->IconData);
929 memset(&(p->RenderData), 0, sizeof(renddata));
930 TNEFInitMapi(&(p->MAPI));
931 p->next = NULL;
932 }
933
TNEFInitialize(TNEFStruct * TNEF)934 void TNEFInitialize(TNEFStruct *TNEF) {
935 INITSTR(TNEF->version);
936 INITVARLENGTH(TNEF->from);
937 INITVARLENGTH(TNEF->subject);
938 INITDTR(TNEF->dateSent);
939 INITDTR(TNEF->dateReceived);
940
941 INITSTR(TNEF->messageStatus);
942 INITSTR(TNEF->messageClass);
943 INITSTR(TNEF->messageID);
944 INITSTR(TNEF->parentID);
945 INITSTR(TNEF->conversationID);
946 INITVARLENGTH(TNEF->body);
947 INITSTR(TNEF->priority);
948 TNEFInitAttachment(&(TNEF->starting_attach));
949 INITDTR(TNEF->dateModified);
950 TNEFInitMapi(&(TNEF->MapiProperties));
951 INITVARLENGTH(TNEF->CodePage);
952 INITVARLENGTH(TNEF->OriginalMessageClass);
953 INITVARLENGTH(TNEF->Owner);
954 INITVARLENGTH(TNEF->SentFor);
955 INITVARLENGTH(TNEF->Delegate);
956 INITDTR(TNEF->DateStart);
957 INITDTR(TNEF->DateEnd);
958 INITVARLENGTH(TNEF->AidOwner);
959 TNEF->RequestRes = 0;
960 TNEF->IO.data = NULL;
961 TNEF->IO.InitProc = NULL;
962 TNEF->IO.ReadProc = NULL;
963 TNEF->IO.CloseProc = NULL;
964 }
965 #undef INITVARLENGTH
966 #undef INITDTR
967 #undef INITSTR
968
969 #define FREEVARLENGTH(x) if ((x).size > 0) { \
970 free((x).data); (x).size =0; }
TNEFFree(TNEFStruct * TNEF)971 void TNEFFree(TNEFStruct *TNEF) {
972 Attachment *p, *store;
973
974 FREEVARLENGTH(TNEF->from);
975 FREEVARLENGTH(TNEF->subject);
976 FREEVARLENGTH(TNEF->body);
977 FREEVARLENGTH(TNEF->CodePage);
978 FREEVARLENGTH(TNEF->OriginalMessageClass);
979 FREEVARLENGTH(TNEF->Owner);
980 FREEVARLENGTH(TNEF->SentFor);
981 FREEVARLENGTH(TNEF->Delegate);
982 FREEVARLENGTH(TNEF->AidOwner);
983 TNEFFreeMapiProps(&(TNEF->MapiProperties));
984
985 p = TNEF->starting_attach.next;
986 while (p != NULL) {
987 TNEFFreeAttachment(p);
988 store = p->next;
989 free(p);
990 p = store;
991 }
992 }
993
TNEFFreeAttachment(Attachment * p)994 void TNEFFreeAttachment(Attachment *p) {
995 FREEVARLENGTH(p->Title);
996 FREEVARLENGTH(p->MetaFile);
997 FREEVARLENGTH(p->TransportFilename);
998 FREEVARLENGTH(p->FileData);
999 FREEVARLENGTH(p->IconData);
1000 TNEFFreeMapiProps(&(p->MAPI));
1001 }
1002
TNEFFreeMapiProps(MAPIProps * p)1003 void TNEFFreeMapiProps(MAPIProps *p) {
1004 int i, j;
1005 for (i = 0; i < p->count; i++) {
1006 for (j = 0; j < p->properties[i].count; j++) {
1007 FREEVARLENGTH(p->properties[i].data[j]);
1008 }
1009 free(p->properties[i].data);
1010 for (j = 0; j < p->properties[i].namedproperty; j++) {
1011 FREEVARLENGTH(p->properties[i].propnames[j]);
1012 }
1013 free(p->properties[i].propnames);
1014 }
1015 free(p->properties);
1016 p->count = 0;
1017 }
1018 #undef FREEVARLENGTH
1019
1020 // Procedures to handle File IO
TNEFFile_Open(TNEFIOStruct * IO)1021 int TNEFFile_Open(TNEFIOStruct *IO) {
1022 TNEFFileInfo *finfo;
1023 finfo = (TNEFFileInfo *)IO->data;
1024
1025 DEBUG1(finfo->Debug, 3, "Opening %s", finfo->filename);
1026 if ((finfo->fptr = fopen(finfo->filename, "rb")) == NULL) {
1027 return -1;
1028 } else {
1029 return 0;
1030 }
1031 }
1032
TNEFFile_Read(TNEFIOStruct * IO,int size,int count,void * dest)1033 int TNEFFile_Read(TNEFIOStruct *IO, int size, int count, void *dest) {
1034 TNEFFileInfo *finfo;
1035 finfo = (TNEFFileInfo *)IO->data;
1036
1037 DEBUG2(finfo->Debug, 3, "Reading %i blocks of %i size", count, size);
1038 if (finfo->fptr != NULL) {
1039 return fread((BYTE *)dest, size, count, finfo->fptr);
1040 } else {
1041 return -1;
1042 }
1043 }
1044
TNEFFile_Close(TNEFIOStruct * IO)1045 int TNEFFile_Close(TNEFIOStruct *IO) {
1046 TNEFFileInfo *finfo;
1047 finfo = (TNEFFileInfo *)IO->data;
1048
1049 DEBUG1(finfo->Debug, 3, "Closing file %s", finfo->filename);
1050 if (finfo->fptr != NULL) {
1051 fclose(finfo->fptr);
1052 finfo->fptr = NULL;
1053 }
1054 return 0;
1055 }
1056
TNEFParseFile(char * filename,TNEFStruct * TNEF)1057 int TNEFParseFile(char *filename, TNEFStruct *TNEF) {
1058 TNEFFileInfo finfo;
1059
1060 if (TNEF->Debug >= 1)
1061 printf("Attempting to parse %s...\n", filename);
1062
1063
1064 finfo.filename = filename;
1065 finfo.fptr = NULL;
1066 finfo.Debug = TNEF->Debug;
1067 TNEF->IO.data = (void *)&finfo;
1068 TNEF->IO.InitProc = TNEFFile_Open;
1069 TNEF->IO.ReadProc = TNEFFile_Read;
1070 TNEF->IO.CloseProc = TNEFFile_Close;
1071 return TNEFParse(TNEF);
1072 }
1073 //-------------------------------------------------------------
1074 // Procedures to handle Memory IO
TNEFMemory_Open(TNEFIOStruct * IO)1075 int TNEFMemory_Open(TNEFIOStruct *IO) {
1076 TNEFMemInfo *minfo;
1077 minfo = (TNEFMemInfo *)IO->data;
1078
1079 minfo->ptr = minfo->dataStart;
1080 return 0;
1081 }
1082
TNEFMemory_Read(TNEFIOStruct * IO,int size,int count,void * dest)1083 int TNEFMemory_Read(TNEFIOStruct *IO, int size, int count, void *dest) {
1084 TNEFMemInfo *minfo;
1085 int length;
1086 long max;
1087 minfo = (TNEFMemInfo *)IO->data;
1088
1089 length = count * size;
1090 max = (minfo->dataStart + minfo->size) - (minfo->ptr);
1091 if (length > max) {
1092 return -1;
1093 }
1094
1095 DEBUG1(minfo->Debug, 3, "Copying %i bytes", length);
1096
1097 memcpy(dest, minfo->ptr, length);
1098 minfo->ptr += length;
1099 return count;
1100 }
1101
TNEFMemory_Close(TNEFIOStruct * IO)1102 int TNEFMemory_Close(TNEFIOStruct *IO) {
1103 // Do nothing, really...
1104 return 0;
1105 }
1106
TNEFParseMemory(BYTE * memory,long size,TNEFStruct * TNEF)1107 int TNEFParseMemory(BYTE *memory, long size, TNEFStruct *TNEF) {
1108 TNEFMemInfo minfo;
1109
1110 DEBUG(TNEF->Debug, 1, "Attempting to parse memory block...\n");
1111
1112 minfo.dataStart = memory;
1113 minfo.ptr = memory;
1114 minfo.size = size;
1115 minfo.Debug = TNEF->Debug;
1116 TNEF->IO.data = (void *)&minfo;
1117 TNEF->IO.InitProc = TNEFMemory_Open;
1118 TNEF->IO.ReadProc = TNEFMemory_Read;
1119 TNEF->IO.CloseProc = TNEFMemory_Close;
1120 return TNEFParse(TNEF);
1121 }
1122
1123
TNEFParse(TNEFStruct * TNEF)1124 int TNEFParse(TNEFStruct *TNEF) {
1125 WORD key;
1126 DWORD type;
1127 DWORD size;
1128 DWORD signature;
1129 BYTE *data;
1130 WORD checksum, header_checksum;
1131 int i;
1132
1133 if (TNEF->IO.ReadProc == NULL) {
1134 printf("ERROR: Setup incorrectly: No ReadProc\n");
1135 return YTNEF_INCORRECT_SETUP;
1136 }
1137
1138 if (TNEF->IO.InitProc != NULL) {
1139 DEBUG(TNEF->Debug, 2, "About to initialize");
1140 if (TNEF->IO.InitProc(&TNEF->IO) != 0) {
1141 return YTNEF_CANNOT_INIT_DATA;
1142 }
1143 DEBUG(TNEF->Debug, 2, "Initialization finished");
1144 }
1145
1146 DEBUG(TNEF->Debug, 2, "Reading Signature");
1147 if (TNEF->IO.ReadProc(&TNEF->IO, sizeof(DWORD), 1, &signature) < 1) {
1148 printf("ERROR: Error reading signature\n");
1149 if (TNEF->IO.CloseProc != NULL) {
1150 TNEF->IO.CloseProc(&TNEF->IO);
1151 }
1152 return YTNEF_ERROR_READING_DATA;
1153 }
1154
1155 DEBUG(TNEF->Debug, 2, "Checking Signature");
1156 if (TNEFCheckForSignature(signature) < 0) {
1157 printf("ERROR: Signature does not match. Not TNEF.\n");
1158 if (TNEF->IO.CloseProc != NULL) {
1159 TNEF->IO.CloseProc(&TNEF->IO);
1160 }
1161 return YTNEF_NOT_TNEF_STREAM;
1162 }
1163
1164 DEBUG(TNEF->Debug, 2, "Reading Key.");
1165
1166 if (TNEFGetKey(TNEF, &key) < 0) {
1167 printf("ERROR: Unable to retrieve key.\n");
1168 if (TNEF->IO.CloseProc != NULL) {
1169 TNEF->IO.CloseProc(&TNEF->IO);
1170 }
1171 return YTNEF_NO_KEY;
1172 }
1173
1174 DEBUG(TNEF->Debug, 2, "Starting Full Processing.");
1175
1176 while (TNEFGetHeader(TNEF, &type, &size) == 0) {
1177 DEBUG2(TNEF->Debug, 2, "Header says type=0x%X, size=%u", type, size);
1178 DEBUG2(TNEF->Debug, 2, "Header says type=%u, size=%u", type, size);
1179 if(size == 0) {
1180 printf("ERROR: Field with size of 0\n");
1181 return YTNEF_ERROR_READING_DATA;
1182 }
1183 PREALLOCCHECK(size, 100000);
1184 data = calloc(size, sizeof(BYTE));
1185 ALLOCCHECK(data);
1186 if (TNEFRawRead(TNEF, data, size, &header_checksum) < 0) {
1187 printf("ERROR: Unable to read data.\n");
1188 if (TNEF->IO.CloseProc != NULL) {
1189 TNEF->IO.CloseProc(&TNEF->IO);
1190 }
1191 free(data);
1192 return YTNEF_ERROR_READING_DATA;
1193 }
1194 if (TNEFRawRead(TNEF, (BYTE *)&checksum, 2, NULL) < 0) {
1195 printf("ERROR: Unable to read checksum.\n");
1196 if (TNEF->IO.CloseProc != NULL) {
1197 TNEF->IO.CloseProc(&TNEF->IO);
1198 }
1199 free(data);
1200 return YTNEF_ERROR_READING_DATA;
1201 }
1202 checksum = SwapWord((BYTE *)&checksum, sizeof(WORD));
1203 if (checksum != header_checksum) {
1204 printf("ERROR: Checksum mismatch. Data corruption?:\n");
1205 if (TNEF->IO.CloseProc != NULL) {
1206 TNEF->IO.CloseProc(&TNEF->IO);
1207 }
1208 free(data);
1209 return YTNEF_BAD_CHECKSUM;
1210 }
1211 for (i = 0; i < (sizeof(TNEFList) / sizeof(TNEFHandler)); i++) {
1212 if (TNEFList[i].id == type) {
1213 if (TNEFList[i].handler != NULL) {
1214 if (TNEFList[i].handler(TNEF, i, (char*)data, size) < 0) {
1215 free(data);
1216 if (TNEF->IO.CloseProc != NULL) {
1217 TNEF->IO.CloseProc(&TNEF->IO);
1218 }
1219 return YTNEF_ERROR_IN_HANDLER;
1220 } else {
1221 // Found our handler and processed it. now time to get out
1222 break;
1223 }
1224 } else {
1225 DEBUG2(TNEF->Debug, 1, "No handler for %s: %u bytes",
1226 TNEFList[i].name, size);
1227 }
1228 }
1229 }
1230
1231 free(data);
1232 }
1233
1234 if (TNEF->IO.CloseProc != NULL) {
1235 TNEF->IO.CloseProc(&TNEF->IO);
1236 }
1237 return 0;
1238
1239 }
1240
1241 // ----------------------------------------------------------------------------
1242
MAPIFindUserProp(MAPIProps * p,unsigned int ID)1243 variableLength *MAPIFindUserProp(MAPIProps *p, unsigned int ID) {
1244 int i;
1245 if (p != NULL) {
1246 for (i = 0; i < p->count; i++) {
1247 if ((p->properties[i].id == ID) && (p->properties[i].custom == 1)) {
1248 return (p->properties[i].data);
1249 }
1250 }
1251 }
1252 return MAPI_UNDEFINED;
1253 }
1254
MAPIFindProperty(MAPIProps * p,unsigned int ID)1255 variableLength *MAPIFindProperty(MAPIProps *p, unsigned int ID) {
1256 int i;
1257 if (p != NULL) {
1258 for (i = 0; i < p->count; i++) {
1259 if ((p->properties[i].id == ID) && (p->properties[i].custom == 0)) {
1260 return (p->properties[i].data);
1261 }
1262 }
1263 }
1264 return MAPI_UNDEFINED;
1265 }
1266
MAPISysTimetoDTR(BYTE * data,dtr * thedate)1267 int MAPISysTimetoDTR(BYTE *data, dtr *thedate) {
1268 DDWORD ddword_tmp;
1269 int startingdate = 0;
1270 int tmp_date;
1271 int days_in_year = 365;
1272 unsigned int months[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
1273
1274 ddword_tmp = *((DDWORD *)data);
1275 ddword_tmp = ddword_tmp / 10; // micro-s
1276 ddword_tmp /= 1000; // ms
1277 ddword_tmp /= 1000; // s
1278
1279 thedate->wSecond = (ddword_tmp % 60);
1280
1281 ddword_tmp /= 60; // seconds to minutes
1282 thedate->wMinute = (ddword_tmp % 60);
1283
1284 ddword_tmp /= 60; //minutes to hours
1285 thedate->wHour = (ddword_tmp % 24);
1286
1287 ddword_tmp /= 24; // Hours to days
1288
1289 // Now calculate the year based on # of days
1290 thedate->wYear = 1601;
1291 startingdate = 1;
1292 while (ddword_tmp >= days_in_year) {
1293 ddword_tmp -= days_in_year;
1294 thedate->wYear++;
1295 days_in_year = 365;
1296 startingdate++;
1297 if ((thedate->wYear % 4) == 0) {
1298 if ((thedate->wYear % 100) == 0) {
1299 // if the year is 1700,1800,1900, etc, then it is only
1300 // a leap year if exactly divisible by 400, not 4.
1301 if ((thedate->wYear % 400) == 0) {
1302 startingdate++;
1303 days_in_year = 366;
1304 }
1305 } else {
1306 startingdate++;
1307 days_in_year = 366;
1308 }
1309 }
1310 startingdate %= 7;
1311 }
1312
1313 // the remaining number is the day # in this year
1314 // So now calculate the Month, & Day of month
1315 if ((thedate->wYear % 4) == 0) {
1316 // 29 days in february in a leap year
1317 months[1] = 29;
1318 }
1319
1320 tmp_date = (int)ddword_tmp;
1321 thedate->wDayOfWeek = (tmp_date + startingdate) % 7;
1322 thedate->wMonth = 0;
1323
1324 while (tmp_date > months[thedate->wMonth]) {
1325 tmp_date -= months[thedate->wMonth];
1326 thedate->wMonth++;
1327 }
1328 thedate->wMonth++;
1329 thedate->wDay = tmp_date + 1;
1330 return 0;
1331 }
1332
MAPIPrint(MAPIProps * p)1333 void MAPIPrint(MAPIProps *p) {
1334 int j, i, index, h, x;
1335 DDWORD *ddword_ptr;
1336 DDWORD ddword_tmp;
1337 dtr thedate;
1338 MAPIProperty *mapi;
1339 variableLength *mapidata;
1340 variableLength vlTemp;
1341 int found;
1342
1343 for (j = 0; j < p->count; j++) {
1344 mapi = &(p->properties[j]);
1345 printf(" #%i: Type: [", j);
1346 switch (PROP_TYPE(mapi->id)) {
1347 case PT_UNSPECIFIED:
1348 printf(" NONE "); break;
1349 case PT_NULL:
1350 printf(" NULL "); break;
1351 case PT_I2:
1352 printf(" I2 "); break;
1353 case PT_LONG:
1354 printf(" LONG "); break;
1355 case PT_R4:
1356 printf(" R4 "); break;
1357 case PT_DOUBLE:
1358 printf(" DOUBLE "); break;
1359 case PT_CURRENCY:
1360 printf("CURRENCY "); break;
1361 case PT_APPTIME:
1362 printf("APP TIME "); break;
1363 case PT_ERROR:
1364 printf(" ERROR "); break;
1365 case PT_BOOLEAN:
1366 printf(" BOOLEAN "); break;
1367 case PT_OBJECT:
1368 printf(" OBJECT "); break;
1369 case PT_I8:
1370 printf(" I8 "); break;
1371 case PT_STRING8:
1372 printf(" STRING8 "); break;
1373 case PT_UNICODE:
1374 printf(" UNICODE "); break;
1375 case PT_SYSTIME:
1376 printf("SYS TIME "); break;
1377 case PT_CLSID:
1378 printf("OLE GUID "); break;
1379 case PT_BINARY:
1380 printf(" BINARY "); break;
1381 default:
1382 printf("<%x>", PROP_TYPE(mapi->id)); break;
1383 }
1384
1385 printf("] Code: [");
1386 if (mapi->custom == 1) {
1387 printf("UD:x%04x", PROP_ID(mapi->id));
1388 } else {
1389 found = 0;
1390 for (index = 0; index < sizeof(MPList) / sizeof(MAPIPropertyTagList); index++) {
1391 if ((MPList[index].id == PROP_ID(mapi->id)) && (found == 0)) {
1392 printf("%s", MPList[index].name);
1393 found = 1;
1394 }
1395 }
1396 if (found == 0) {
1397 printf("0x%04x", PROP_ID(mapi->id));
1398 }
1399 }
1400 printf("]\n");
1401 if (mapi->namedproperty > 0) {
1402 for (i = 0; i < mapi->namedproperty; i++) {
1403 printf(" Name: %s\n", mapi->propnames[i].data);
1404 }
1405 }
1406 for (i = 0; i < mapi->count; i++) {
1407 mapidata = &(mapi->data[i]);
1408 if (mapi->count > 1) {
1409 printf(" [%i/%u] ", i, mapi->count);
1410 } else {
1411 printf(" ");
1412 }
1413 printf("Size: %i", mapidata->size);
1414 switch (PROP_TYPE(mapi->id)) {
1415 case PT_SYSTIME:
1416 MAPISysTimetoDTR(mapidata->data, &thedate);
1417 printf(" Value: ");
1418 ddword_tmp = *((DDWORD *)mapidata->data);
1419 TNEFPrintDate(thedate);
1420 printf(" [HEX: ");
1421 for (x = 0; x < sizeof(ddword_tmp); x++) {
1422 printf(" %02x", (BYTE)mapidata->data[x]);
1423 }
1424 printf("] (%llu)\n", ddword_tmp);
1425 break;
1426 case PT_LONG:
1427 printf(" Value: %i\n", *((int*)mapidata->data));
1428 break;
1429 case PT_I2:
1430 printf(" Value: %hi\n", *((short int*)mapidata->data));
1431 break;
1432 case PT_BOOLEAN:
1433 if (mapi->data->data[0] != 0) {
1434 printf(" Value: True\n");
1435 } else {
1436 printf(" Value: False\n");
1437 }
1438 break;
1439 case PT_OBJECT:
1440 printf("\n");
1441 break;
1442 case PT_BINARY:
1443 if (IsCompressedRTF(mapidata) == 1) {
1444 printf(" Detected Compressed RTF. ");
1445 printf("Decompressed text follows\n");
1446 printf("-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-\n");
1447 if ((vlTemp.data = (BYTE*)DecompressRTF(mapidata, &(vlTemp.size))) != NULL) {
1448 printf("%s\n", vlTemp.data);
1449 free(vlTemp.data);
1450 }
1451 printf("-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-\n");
1452 } else {
1453 printf(" Value: [");
1454 for (h = 0; h < mapidata->size; h++) {
1455 if (isprint(mapidata->data[h])) {
1456 printf("%c", mapidata->data[h]);
1457 } else {
1458 printf(".");
1459 }
1460
1461 }
1462 printf("]\n");
1463 }
1464 break;
1465 case PT_STRING8:
1466 printf(" Value: [%.*s]\n", mapidata->size, mapidata->data);
1467 if (strlen((char*)mapidata->data) != mapidata->size - 1) {
1468 printf("Detected Hidden data: [");
1469 for (h = 0; h < mapidata->size; h++) {
1470 if (isprint(mapidata->data[h])) {
1471 printf("%c", mapidata->data[h]);
1472 } else {
1473 printf(".");
1474 }
1475
1476 }
1477 printf("]\n");
1478 }
1479 break;
1480 case PT_CLSID:
1481 printf(" Value: ");
1482 printf("[HEX: ");
1483 for(x=0; x< 16; x++) {
1484 printf(" %02x", (BYTE)mapidata->data[x]);
1485 }
1486 printf("]\n");
1487 break;
1488 default:
1489 printf(" Value: [%.*s]\n", mapidata->size, mapidata->data);
1490 }
1491 }
1492 }
1493 }
1494
1495
IsCompressedRTF(variableLength * p)1496 int IsCompressedRTF(variableLength *p) {
1497 BYTE *src;
1498 ULONG magic;
1499
1500 if (p->size < 3*sizeof(DWORD))
1501 return 0;
1502
1503 src = p->data;
1504 magic = SwapDWord((BYTE*)src + 2*sizeof(DWORD), sizeof(DWORD));
1505
1506 if (magic == 0x414c454d || magic == 0x75465a4c) {
1507 return 1;
1508 } else {
1509 return 0;
1510 }
1511 }
1512
DecompressRTF(variableLength * p,int * size)1513 BYTE *DecompressRTF(variableLength *p, int *size) {
1514 BYTE *dst; // destination for uncompressed bytes
1515 BYTE *src;
1516 unsigned int in;
1517 unsigned int out;
1518 variableLength comp_Prebuf;
1519 ULONG compressedSize, uncompressedSize, magic;
1520
1521 comp_Prebuf.size = strlen(RTF_PREBUF);
1522 comp_Prebuf.data = calloc(comp_Prebuf.size+1, 1);
1523 ALLOCCHECK_CHAR(comp_Prebuf.data);
1524 memcpy(comp_Prebuf.data, RTF_PREBUF, comp_Prebuf.size);
1525
1526 src = p->data;
1527 in = 0;
1528
1529 if (p->size < 20) {
1530 printf("File too small\n");
1531 return(NULL);
1532 }
1533 compressedSize = (ULONG)SwapDWord((BYTE*)src + in, sizeof(DWORD));
1534 in += sizeof(DWORD);
1535 uncompressedSize = (ULONG)SwapDWord((BYTE*)src + in, sizeof(DWORD));
1536 in += sizeof(DWORD);
1537 magic = SwapDWord((BYTE*)src + in, sizeof(DWORD));
1538 in += 2*sizeof(DWORD);
1539
1540 // check size excluding the size field itself
1541 if (compressedSize != p->size - 4) {
1542 printf(" Size Mismatch: %u != %i\n", compressedSize, p->size - 4);
1543 free(comp_Prebuf.data);
1544 return NULL;
1545 }
1546
1547 // process the data
1548 if (magic == 0x414c454d) {
1549 // magic number that identifies the stream as a uncompressed stream
1550 dst = calloc(uncompressedSize, 1);
1551 ALLOCCHECK_CHAR(dst);
1552 memcpy(dst, src + 4, uncompressedSize);
1553 } else if (magic == 0x75465a4c) {
1554 // magic number that identifies the stream as a compressed stream
1555 int flagCount = 0;
1556 int flags = 0;
1557 // Prevent overflow on 32 Bit Systems
1558 if (comp_Prebuf.size >= INT_MAX - uncompressedSize) {
1559 printf("Corrupted file\n");
1560 return NULL;
1561 }
1562 dst = calloc(comp_Prebuf.size + uncompressedSize, 1);
1563 ALLOCCHECK_CHAR(dst);
1564 memcpy(dst, comp_Prebuf.data, comp_Prebuf.size);
1565 out = comp_Prebuf.size;
1566 while ((out < (comp_Prebuf.size + uncompressedSize)) && (in < p->size)) {
1567 // each flag byte flags 8 literals/references, 1 per bit
1568 flags = (flagCount++ % 8 == 0) ? src[in++] : flags >> 1;
1569 if ((flags & 1) == 1) { // each flag bit is 1 for reference, 0 for literal
1570 unsigned int offset = src[in++];
1571 unsigned int length = src[in++];
1572 unsigned int end;
1573 offset = (offset << 4) | (length >> 4); // the offset relative to block start
1574 length = (length & 0xF) + 2; // the number of bytes to copy
1575 // the decompression buffer is supposed to wrap around back
1576 // to the beginning when the end is reached. we save the
1577 // need for such a buffer by pointing straight into the data
1578 // buffer, and simulating this behaviour by modifying the
1579 // pointers appropriately.
1580 offset = (out / 4096) * 4096 + offset;
1581 if (offset >= out) // take from previous block
1582 offset -= 4096;
1583 // note: can't use System.arraycopy, because the referenced
1584 // bytes can cross through the current out position.
1585 end = offset + length;
1586 while ((offset < end) && (out < (comp_Prebuf.size + uncompressedSize))
1587 && (offset < (comp_Prebuf.size + uncompressedSize)))
1588 dst[out++] = dst[offset++];
1589 } else { // literal
1590 if ((out >= (comp_Prebuf.size + uncompressedSize)) ||
1591 (in >= p->size)) {
1592 printf("Corrupted stream\n");
1593 return NULL;
1594 }
1595 dst[out++] = src[in++];
1596 }
1597 }
1598 // copy it back without the prebuffered data
1599 src = dst;
1600 dst = calloc(uncompressedSize, 1);
1601 ALLOCCHECK_CHAR(dst);
1602 memcpy(dst, src + comp_Prebuf.size, uncompressedSize);
1603 free(src);
1604 *size = uncompressedSize;
1605 free(comp_Prebuf.data);
1606 return dst;
1607 } else { // unknown magic number
1608 printf("Unknown compression type (magic number %x)\n", magic);
1609 }
1610 free(comp_Prebuf.data);
1611 return NULL;
1612 }
1613