~ubuntu-branches/debian/sid/claws-mail/sid

« back to all changes in this revision

Viewing changes to .pc/14CVE_2010_5109.patch/src/plugins/tnef_parse/ytnef.c

  • Committer: Package Import Robot
  • Author(s): Ricardo Mones
  • Date: 2014-11-29 23:03:27 UTC
  • Revision ID: package-import@ubuntu.com-20141129230327-uk8b0jq77upt3tih
Tags: 3.11.1-2
* patches/14CVE_2010_5109.patch, patches/series
- Fix possible buffer overflow CVE-2010-5109 (Closes: #771360)
- Raised urgency because of RC security bug

Show diffs side-by-side

added added

removed removed

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