~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: 2015-08-18 16:37:25 UTC
  • mfrom: (1.3.7)
  • Revision ID: package-import@ubuntu.com-20150818163725-1it32n9mzqkwy2ef
Tags: 3.12.0-1
* New upstream release:
- 'cannot reorganize mailboxes' (Closes: #777208)
- 'dropdown menu bar has disappeared…'(Closes: #778886)
- 'depends on plugins libraries'  (Closes: #779824)
- 'new upstream version (3.12.0)…' (Closes: #793665)
* 14CVE_2010_5109.patch, 15fix_crash_open_folder.patch,
  13desktop_file_categories.patch
- Remove patches applied upstream
* debian/control, debian/copyright, debian/claws-mail-managesieve*
- Add managesieve plugin (new in this release)
* debian/rules
- Set perl-plugin manpage release version automatically
* 12fix_manpage_header.patch
- Update patch to cope with upstream changes
* debian/control, debian/watch
- Update VCS-* and watch URLs (thanks Julian Wollrath)

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
 
}