Add missing copyrights in tnef_parse plugin
[claws.git] / src / plugins / tnef_parse / tnef_dump.c
1 /*
2  * Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
3  * Copyright (C) 1999-2007 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 <unistd.h>
30 #include <stdio.h>
31 #include <ctype.h>
32
33 #include <glib.h>
34 #include <glib/gi18n.h>
35 #include <gtk/gtk.h>
36 #include "common/claws.h"
37 #include "common/version.h"
38 #include "main.h"
39 #include "plugin.h"
40 #include "procmime.h"
41 #include "utils.h"
42
43 #include <tnef-types.h>
44 #include <ytnef.h>
45 #include <mapi.h>
46 #include <mapidefs.h>
47
48 #include "tnef_dump.h"
49
50 #define PRODID "PRODID:-//The Gauntlet//" PACKAGE " TNEF Parser " VERSION "//EN\n"
51
52 static unsigned char GetRruleCount(unsigned char a, unsigned char b) {
53     return ((a << 8) | b);
54 }
55
56 static unsigned char GetRruleMonthNum(unsigned char a, unsigned char b) {
57     switch (a) {
58         case 0x00:
59             switch (b) {
60                 case 0x00:
61                     // Jan
62                     return(1);
63                 case 0xA3:
64                     // May
65                     return(5);
66                 case 0xAE:
67                     // Nov
68                     return(11);
69             }
70             break;
71         case 0x60:
72             switch (b) {
73                 case 0xAE:
74                     // Feb
75                     return(2);
76                 case 0x51:
77                     // Jun
78                     return(6);
79             }
80             break;
81         case 0xE0:
82             switch (b) {
83                 case 0x4B:
84                     // Mar
85                     return(3);
86                 case 0x56:
87                     // Sep
88                     return(9);
89             }
90             break;
91         case 0x40:
92             switch (b) {
93                 case 0xFA:
94                     // Apr
95                     return(4);
96             }
97             break;
98         case 0x20:
99             if (b == 0xFA) {
100                 // Jul
101                 return(7);
102             }
103             break;
104         case 0x80:
105             if (b == 0xA8) {
106                 // Aug
107                 return(8);
108             }
109             break;
110         case 0xA0:
111             if (b == 0xFF) {
112                 // Oct
113                 return(10);
114             }
115             break;
116         case 0xC0:
117             if (b == 0x56) {
118                 return(12);
119             }
120     }
121
122     // Error
123     return(0);
124 }
125
126 static char * GetRruleDayname(unsigned char a) {
127     static char daystring[25];
128
129     *daystring = 0;
130
131     if (a & 0x01) {
132         strcat(daystring, "SU,");
133     }
134     if (a & 0x02) {
135         strcat(daystring, "MO,");
136     }
137     if (a & 0x04) {
138         strcat(daystring, "TU,");
139     }
140     if (a & 0x08) {
141         strcat(daystring, "WE,");
142     }
143     if (a & 0x10) {
144         strcat(daystring, "TH,");
145     }
146     if (a & 0x20) {
147         strcat(daystring, "FR,");
148     }
149     if (a & 0x40) {
150         strcat(daystring, "SA,");
151     }
152
153     if (strlen(daystring)) {
154         daystring[strlen(daystring) - 1] = 0;
155     }
156
157     return(daystring);
158 }
159
160 static void PrintRrule(FILE *fptr, char *recur_data, int size, TNEFStruct *TNEF) {
161     variableLength *filename;
162
163     if (size < 0x1F) {
164         return;
165     }
166
167     fprintf(fptr, "RRULE:FREQ=");
168
169     if (recur_data[0x04] == 0x0A) {
170         fprintf(fptr, "DAILY");
171
172         if (recur_data[0x16] == 0x23 || recur_data[0x16] == 0x22 ||
173                 recur_data[0x16] == 0x21) {
174             if ((filename=MAPIFindUserProp(&(TNEF->MapiProperties),
175                     PROP_TAG(PT_I2, 0x0011))) != MAPI_UNDEFINED) {
176                 fprintf(fptr, ";INTERVAL=%d", *(filename->data));
177             }
178             if (recur_data[0x16] == 0x22 || recur_data[0x16] == 0x21) {
179                 fprintf(fptr, ";COUNT=%d",
180                     GetRruleCount(recur_data[0x1B], recur_data[0x1A]));
181             }
182         } else if (recur_data[0x16] == 0x3E) {
183             fprintf(fptr, ";BYDAY=MO,TU,WE,TH,FR");
184             if (recur_data[0x1A] == 0x22 || recur_data[0x1A] == 0x21) {
185                 fprintf(fptr, ";COUNT=%d",
186                     GetRruleCount(recur_data[0x1F], recur_data[0x1E]));
187             }
188         }
189     } else if (recur_data[0x04] == 0x0B) {
190         fprintf(fptr, "WEEKLY;INTERVAL=%d;BYDAY=%s",
191             recur_data[0x0E], GetRruleDayname(recur_data[0x16]));
192         if (recur_data[0x1A] == 0x22 || recur_data[0x1A] == 0x21) {
193             fprintf(fptr, ";COUNT=%d",
194                 GetRruleCount(recur_data[0x1F], recur_data[0x1E]));
195         }
196     } else if (recur_data[0x04] == 0x0C) {
197         fprintf(fptr, "MONTHLY");
198         if (recur_data[0x06] == 0x02) {
199             fprintf(fptr, ";INTERVAL=%d;BYMONTHDAY=%d", recur_data[0x0E],
200                 recur_data[0x16]);
201             if (recur_data[0x1A] == 0x22 || recur_data[0x1A] == 0x21) {
202                 fprintf(fptr, ";COUNT=%d", GetRruleCount(recur_data[0x1F],
203                     recur_data[0x1E]));
204             }
205         } else if (recur_data[0x06] == 0x03) {
206             fprintf(fptr, ";BYDAY=%s;BYSETPOS=%d;INTERVAL=%d",
207                 GetRruleDayname(recur_data[0x16]),
208                 recur_data[0x1A] == 0x05 ? -1 : recur_data[0x1A],
209                 recur_data[0x0E]);
210             if (recur_data[0x1E] == 0x22 || recur_data[0x1E] == 0x21) {
211                 fprintf(fptr, ";COUNT=%d", GetRruleCount(recur_data[0x23],
212                     recur_data[0x22]));
213             }
214         }
215     } else if (recur_data[0x04] == 0x0D) {
216         fprintf(fptr, "YEARLY;BYMONTH=%d",
217                 GetRruleMonthNum(recur_data[0x0A], recur_data[0x0B]));
218         if (recur_data[0x06] == 0x02) {
219             fprintf(fptr, ";BYMONTHDAY=%d", recur_data[0x16]);
220         } else if (recur_data[0x06] == 0x03) {
221             fprintf(fptr, ";BYDAY=%s;BYSETPOS=%d",
222                 GetRruleDayname(recur_data[0x16]),
223                 recur_data[0x1A] == 0x05 ? -1 : recur_data[0x1A]);
224         }
225         if (recur_data[0x1E] == 0x22 || recur_data[0x1E] == 0x21) {
226             fprintf(fptr, ";COUNT=%d", GetRruleCount(recur_data[0x23],
227                 recur_data[0x22]));
228         }
229     }
230     fprintf(fptr, "\n");
231 }
232
233 static void fprintProperty(TNEFStruct *TNEF, FILE *FPTR, DWORD PROPTYPE, DWORD PROPID, char TEXT[]) {
234     variableLength *vl;
235     if ((vl=MAPIFindProperty(&(TNEF->MapiProperties), PROP_TAG(PROPTYPE, PROPID))) != MAPI_UNDEFINED) {
236         if (vl->size > 0) {
237             if ((vl->size == 1) && (vl->data[0] == 0)) {
238             } else {
239                 fprintf(FPTR, TEXT, vl->data);
240             }
241         }
242     }
243 }
244
245 static void fprintUserProp(TNEFStruct *TNEF, FILE *FPTR, DWORD PROPTYPE, DWORD PROPID, char TEXT[]) {
246     variableLength *vl;
247     if ((vl=MAPIFindUserProp(&(TNEF->MapiProperties), PROP_TAG(PROPTYPE, PROPID))) != MAPI_UNDEFINED) {
248         if (vl->size > 0) {
249             if ((vl->size == 1) && (vl->data[0] == 0)) {
250             } else {
251                 fprintf(FPTR, TEXT, vl->data);
252             }
253         }
254     }
255 }
256
257 static void quotedfprint(FILE *FPTR, variableLength *VL) {
258     int index;
259
260     for (index=0;index<VL->size-1; index++) {
261         if (VL->data[index] == '\n') {
262             fprintf(FPTR, "=0A");
263         } else if (VL->data[index] == '\r') {
264         } else {
265             fprintf(FPTR, "%c", VL->data[index]);
266         }
267     }
268 }
269
270 static void Cstylefprint(FILE *FPTR, variableLength *VL) {
271     int index;
272
273     for (index=0;index<VL->size-1; index++) {
274         if (VL->data[index] == '\n') {
275             fprintf(FPTR, "\\n");
276         } else if (VL->data[index] == '\r') {
277             // Print nothing.
278         } else if (VL->data[index] == ';') {
279             fprintf(FPTR, "\\;");
280         } else if (VL->data[index] == ',') {
281             fprintf(FPTR, "\\,");
282         } else if (VL->data[index] == '\\') {
283             fprintf(FPTR, "\\");
284         } else {
285             fprintf(FPTR, "%c", VL->data[index]);
286         }
287     }
288 }
289
290 static void PrintRTF(FILE *fptr, variableLength *VL) {
291     int index;
292     char *byte;
293     int brace_ct;
294     int key;
295
296     key = 0;
297     brace_ct = 0;
298
299     for(index = 0, byte=VL->data; index < VL->size; index++, byte++) {
300         if (*byte == '}') {
301             brace_ct--;
302             key = 0;
303             continue;
304         }
305         if (*byte == '{') {
306             brace_ct++;
307             continue;
308         }
309         if (*byte == '\\') {
310             key = 1;
311         }
312         if (isspace(*byte)) {
313             key = 0;
314         }
315         if ((brace_ct == 1) && (key == 0)) {
316             if (*byte == '\n') {
317                 fprintf(fptr, "\\n");
318             } else if (*byte == '\r') {
319                 // Print nothing.
320             } else if (*byte == ';') {
321                 fprintf(fptr, "\\;");
322             } else if (*byte == ',') {
323                 fprintf(fptr, "\\,");
324             } else if (*byte == '\\') {
325                 fprintf(fptr, "\\");
326             } else {
327                 fprintf(fptr, "%c", *byte );
328             }
329         }
330     }
331     fprintf(fptr, "\n");
332 }
333
334 gboolean SaveVCalendar(FILE *fptr, TNEFStruct *TNEF) {
335     variableLength *filename;
336     char *charptr, *charptr2;
337     int index;
338     DDWORD *ddword_ptr;
339     DDWORD ddword_val;
340     dtr thedate;
341
342         fprintf(fptr, "BEGIN:VCALENDAR\n");
343         if (TNEF->messageClass[0] != 0) {
344             charptr2=TNEF->messageClass;
345             charptr=charptr2;
346             while (*charptr != 0) {
347                 if (*charptr == '.') {
348                     charptr2 = charptr;
349                 }
350                 charptr++;
351             }
352             if (strcmp(charptr2, ".MtgCncl") == 0) {
353                 fprintf(fptr, "METHOD:CANCEL\n");
354             } else {
355                 fprintf(fptr, "METHOD:REQUEST\n");
356             }
357         } else {
358             fprintf(fptr, "METHOD:REQUEST\n");
359         }
360         fprintf(fptr, PRODID);
361         fprintf(fptr, "VERSION:2.0\n");
362         fprintf(fptr, "BEGIN:VEVENT\n");
363
364         // UID
365         // After alot of comparisons, I'm reasonably sure this is totally
366         // wrong.  But it's not really necessary.
367         //
368         // I think it only exists to connect future modification entries to
369         // this entry. so as long as it's incorrectly interpreted the same way
370         // every time, it should be ok :)
371         filename = NULL;
372         if ((filename=MAPIFindUserProp(&(TNEF->MapiProperties),
373                         PROP_TAG(PT_BINARY, 0x3))) == MAPI_UNDEFINED) {
374             if ((filename=MAPIFindUserProp(&(TNEF->MapiProperties),
375                             PROP_TAG(PT_BINARY, 0x23))) == MAPI_UNDEFINED) {
376                 filename = NULL;
377             }
378         }
379         if (filename!=NULL) {
380             fprintf(fptr, "UID:");
381             for(index=0;index<filename->size;index++) {
382                 fprintf(fptr,"%02X", (unsigned char)filename->data[index]);
383             }
384             fprintf(fptr,"\n");
385         }
386
387         // Sequence
388         filename = NULL;
389         if ((filename=MAPIFindUserProp(&(TNEF->MapiProperties),
390                         PROP_TAG(PT_LONG, 0x8201))) != MAPI_UNDEFINED) {
391             ddword_ptr = (DDWORD*)filename->data;
392             fprintf(fptr, "SEQUENCE:%i\n", (int) *ddword_ptr);
393         }
394         if ((filename=MAPIFindProperty(&(TNEF->MapiProperties),
395                         PROP_TAG(PT_BINARY, PR_SENDER_SEARCH_KEY)))
396                 != MAPI_UNDEFINED) {
397             charptr = filename->data;
398             charptr2 = strstr(charptr, ":");
399             if (charptr2 == NULL)
400                 charptr2 = charptr;
401             else
402                 charptr2++;
403             fprintf(fptr, "ORGANIZER;CN=\"%s\":MAILTO:%s\n",
404                     charptr2, charptr2);
405         }
406
407         // Required Attendees
408         if ((filename = MAPIFindUserProp(&(TNEF->MapiProperties),
409                         PROP_TAG(PT_STRING8, 0x823b))) != MAPI_UNDEFINED) {
410                 // We have a list of required participants, so
411                 // write them out.
412             if (filename->size > 1) {
413                 charptr = filename->data-1;
414                 charptr2=strstr(charptr+1, ";");
415                 while (charptr != NULL) {
416                     charptr++;
417                     charptr2 = strstr(charptr, ";");
418                     if (charptr2 != NULL) {
419                         *charptr2 = 0;
420                     }
421                     while (*charptr == ' ')
422                         charptr++;
423                     fprintf(fptr, "ATTENDEE;PARTSTAT=NEEDS-ACTION;");
424                     fprintf(fptr, "ROLE=REQ-PARTICIPANT;RSVP=TRUE;");
425                     fprintf(fptr, "CN=\"%s\":MAILTO:%s\n",
426                                 charptr, charptr);
427                     charptr = charptr2;
428                 }
429             }
430             // Optional attendees
431             if ((filename = MAPIFindUserProp(&(TNEF->MapiProperties),
432                             PROP_TAG(PT_STRING8, 0x823c))) != MAPI_UNDEFINED) {
433                     // The list of optional participants
434                 if (filename->size > 1) {
435                     charptr = filename->data-1;
436                     charptr2=strstr(charptr+1, ";");
437                     while (charptr != NULL) {
438                         charptr++;
439                         charptr2 = strstr(charptr, ";");
440                         if (charptr2 != NULL) {
441                             *charptr2 = 0;
442                         }
443                         while (*charptr == ' ')
444                             charptr++;
445                         fprintf(fptr, "ATTENDEE;PARTSTAT=NEEDS-ACTION;");
446                         fprintf(fptr, "ROLE=OPT-PARTICIPANT;RSVP=TRUE;");
447                         fprintf(fptr, "CN=\"%s\":MAILTO:%s\n",
448                                 charptr, charptr);
449                         charptr = charptr2;
450                     }
451                 }
452             }
453         } else if ((filename = MAPIFindUserProp(&(TNEF->MapiProperties),
454                         PROP_TAG(PT_STRING8, 0x8238))) != MAPI_UNDEFINED) {
455             if (filename->size > 1) {
456                 charptr = filename->data-1;
457                 while (charptr != NULL) {
458                     charptr++;
459                     charptr2 = strstr(charptr, ";");
460                     if (charptr2 != NULL) {
461                         *charptr2 = 0;
462                     }
463                     while (*charptr == ' ')
464                         charptr++;
465                     fprintf(fptr, "ATTENDEE;PARTSTAT=NEEDS-ACTION;");
466                     fprintf(fptr, "ROLE=REQ-PARTICIPANT;RSVP=TRUE;");
467                     fprintf(fptr, "CN=\"%s\":MAILTO:%s\n",
468                                 charptr, charptr);
469                     charptr = charptr2;
470                 }
471             }
472
473         }
474         // Summary
475         filename = NULL;
476         if((filename=MAPIFindProperty(&(TNEF->MapiProperties),
477                         PROP_TAG(PT_STRING8, PR_CONVERSATION_TOPIC)))
478                 != MAPI_UNDEFINED) {
479             fprintf(fptr, "SUMMARY:");
480             Cstylefprint(fptr, filename);
481             fprintf(fptr, "\n");
482         }
483
484         // Description
485         if ((filename=MAPIFindProperty(&(TNEF->MapiProperties),
486                                 PROP_TAG(PT_BINARY, PR_RTF_COMPRESSED)))
487                 != MAPI_UNDEFINED) {
488             variableLength buf;
489             if ((buf.data = DecompressRTF(filename, &(buf.size))) != NULL) {
490                 fprintf(fptr, "DESCRIPTION:");
491                 PrintRTF(fptr, &buf);
492                 free(buf.data);
493             }
494
495         }
496
497         // Location
498         filename = NULL;
499         if ((filename=MAPIFindUserProp(&(TNEF->MapiProperties),
500                         PROP_TAG(PT_STRING8, 0x0002))) == MAPI_UNDEFINED) {
501             if ((filename=MAPIFindUserProp(&(TNEF->MapiProperties),
502                             PROP_TAG(PT_STRING8, 0x8208))) == MAPI_UNDEFINED) {
503                 filename = NULL;
504             }
505         }
506         if (filename != NULL) {
507             fprintf(fptr,"LOCATION: %s\n", filename->data);
508         }
509         // Date Start
510         filename = NULL;
511         if ((filename=MAPIFindUserProp(&(TNEF->MapiProperties),
512                         PROP_TAG(PT_SYSTIME, 0x820d))) == MAPI_UNDEFINED) {
513             if ((filename=MAPIFindUserProp(&(TNEF->MapiProperties),
514                             PROP_TAG(PT_SYSTIME, 0x8516))) == MAPI_UNDEFINED) {
515                 filename=NULL;
516             }
517         }
518         if (filename != NULL) {
519             fprintf(fptr, "DTSTART:");
520             MAPISysTimetoDTR(filename->data, &thedate);
521             fprintf(fptr,"%04i%02i%02iT%02i%02i%02iZ\n",
522                     thedate.wYear, thedate.wMonth, thedate.wDay,
523                     thedate.wHour, thedate.wMinute, thedate.wSecond);
524         }
525         // Date End
526         filename = NULL;
527         if ((filename=MAPIFindUserProp(&(TNEF->MapiProperties),
528                         PROP_TAG(PT_SYSTIME, 0x820e))) == MAPI_UNDEFINED) {
529             if ((filename=MAPIFindUserProp(&(TNEF->MapiProperties),
530                             PROP_TAG(PT_SYSTIME, 0x8517))) == MAPI_UNDEFINED) {
531                 filename=NULL;
532             }
533         }
534         if (filename != NULL) {
535             fprintf(fptr, "DTEND:");
536             MAPISysTimetoDTR(filename->data, &thedate);
537             fprintf(fptr,"%04i%02i%02iT%02i%02i%02iZ\n",
538                     thedate.wYear, thedate.wMonth, thedate.wDay,
539                     thedate.wHour, thedate.wMinute, thedate.wSecond);
540         }
541         // Date Stamp
542         filename = NULL;
543         if ((filename=MAPIFindUserProp(&(TNEF->MapiProperties),
544                         PROP_TAG(PT_SYSTIME, 0x8202))) != MAPI_UNDEFINED) {
545             fprintf(fptr, "CREATED:");
546             MAPISysTimetoDTR(filename->data, &thedate);
547             fprintf(fptr,"%04i%02i%02iT%02i%02i%02iZ\n",
548                     thedate.wYear, thedate.wMonth, thedate.wDay,
549                     thedate.wHour, thedate.wMinute, thedate.wSecond);
550         }
551         // Class
552         filename = NULL;
553         if ((filename=MAPIFindUserProp(&(TNEF->MapiProperties),
554                         PROP_TAG(PT_BOOLEAN, 0x8506))) != MAPI_UNDEFINED) {
555             ddword_ptr = (DDWORD*)filename->data;
556             ddword_val = SwapDDWord((BYTE*)ddword_ptr);
557             fprintf(fptr, "CLASS:" );
558             if (ddword_val == 1) {
559                 fprintf(fptr,"PRIVATE\n");
560             } else {
561                 fprintf(fptr,"PUBLIC\n");
562             }
563         }
564         // Recurrence
565         filename = NULL;
566         if ((filename=MAPIFindUserProp(&(TNEF->MapiProperties),
567                         PROP_TAG(PT_BINARY, 0x8216))) != MAPI_UNDEFINED) {
568             PrintRrule(fptr, filename->data, filename->size, TNEF);
569         }
570
571         // Wrap it up
572         fprintf(fptr, "END:VEVENT\n");
573         fprintf(fptr, "END:VCALENDAR\n");
574         return TRUE;
575 }
576
577         
578
579 gboolean SaveVTask(FILE *fptr, TNEFStruct *TNEF) {
580         variableLength *filename;
581         char *charptr, *charptr2;
582         dtr thedate;
583         DDWORD *ddword_ptr;
584         DDWORD ddword_val;
585
586         fprintf(fptr, "BEGIN:VCALENDAR\n");
587         fprintf(fptr, PRODID);
588         fprintf(fptr, "VERSION:2.0\n");
589         fprintf(fptr, "METHOD:PUBLISH\n");
590         filename = NULL;
591
592         fprintf(fptr, "BEGIN:VTODO\n");
593         if (TNEF->messageID[0] != 0) {
594             fprintf(fptr,"UID:%s\n", TNEF->messageID);
595         }
596         filename = MAPIFindUserProp(&(TNEF->MapiProperties), \
597                         PROP_TAG(PT_STRING8, 0x8122));
598         if (filename != MAPI_UNDEFINED) {
599             fprintf(fptr, "ORGANIZER:%s\n", filename->data);
600         }
601
602
603         if ((filename = MAPIFindProperty(&(TNEF->MapiProperties), PROP_TAG(PT_STRING8, PR_DISPLAY_TO))) != MAPI_UNDEFINED) {
604             filename = MAPIFindUserProp(&(TNEF->MapiProperties), PROP_TAG(PT_STRING8, 0x811f));
605         }
606         if ((filename != MAPI_UNDEFINED) && (filename->size > 1)) {
607             charptr = filename->data-1;
608             while (charptr != NULL) {
609                 charptr++;
610                 charptr2 = strstr(charptr, ";");
611                 if (charptr2 != NULL) {
612                     *charptr2 = 0;
613                 }
614                 while (*charptr == ' ')
615                     charptr++;
616                 fprintf(fptr, "ATTENDEE;CN=%s;ROLE=REQ-PARTICIPANT:%s\n", charptr, charptr);
617                 charptr = charptr2;
618             }
619         }
620
621         if (TNEF->subject.size > 0) {
622             fprintf(fptr,"SUMMARY:");
623             Cstylefprint(fptr,&(TNEF->subject));
624             fprintf(fptr,"\n");
625         }
626
627         if (TNEF->body.size > 0) {
628             fprintf(fptr,"DESCRIPTION:");
629             Cstylefprint(fptr,&(TNEF->body));
630             fprintf(fptr,"\n");
631         }
632
633         filename = MAPIFindProperty(&(TNEF->MapiProperties), \
634                     PROP_TAG(PT_SYSTIME, PR_CREATION_TIME));
635         if (filename != MAPI_UNDEFINED) {
636             fprintf(fptr, "DTSTAMP:");
637             MAPISysTimetoDTR(filename->data, &thedate);
638             fprintf(fptr,"%04i%02i%02iT%02i%02i%02iZ\n",
639                     thedate.wYear, thedate.wMonth, thedate.wDay,
640                     thedate.wHour, thedate.wMinute, thedate.wSecond);
641         }
642
643         filename = MAPIFindUserProp(&(TNEF->MapiProperties), \
644                     PROP_TAG(PT_SYSTIME, 0x8517));
645         if (filename != MAPI_UNDEFINED) {
646             fprintf(fptr, "DUE:");
647             MAPISysTimetoDTR(filename->data, &thedate);
648             fprintf(fptr,"%04i%02i%02iT%02i%02i%02iZ\n",
649                     thedate.wYear, thedate.wMonth, thedate.wDay,
650                     thedate.wHour, thedate.wMinute, thedate.wSecond);
651         }
652         filename = MAPIFindProperty(&(TNEF->MapiProperties), \
653                     PROP_TAG(PT_SYSTIME, PR_LAST_MODIFICATION_TIME));
654         if (filename != MAPI_UNDEFINED) {
655             fprintf(fptr, "LAST-MODIFIED:");
656             MAPISysTimetoDTR(filename->data, &thedate);
657             fprintf(fptr,"%04i%02i%02iT%02i%02i%02iZ\n",
658                     thedate.wYear, thedate.wMonth, thedate.wDay,
659                     thedate.wHour, thedate.wMinute, thedate.wSecond);
660         }
661         // Class
662         filename = MAPIFindUserProp(&(TNEF->MapiProperties), \
663                         PROP_TAG(PT_BOOLEAN, 0x8506));
664         if (filename != MAPI_UNDEFINED) {
665             ddword_ptr = (DDWORD*)filename->data;
666             ddword_val = SwapDDWord((BYTE*)ddword_ptr);
667             fprintf(fptr, "CLASS:" );
668             if (ddword_val == 1) {
669                 fprintf(fptr,"PRIVATE\n");
670             } else {
671                 fprintf(fptr,"PUBLIC\n");
672             }
673         }
674         fprintf(fptr, "END:VTODO\n");
675         fprintf(fptr, "END:VCALENDAR\n");
676
677         return TRUE;
678 }
679
680 gboolean SaveVCard(FILE *fptr, TNEFStruct *TNEF) {
681     variableLength *vl;
682     variableLength *pobox, *street, *city, *state, *zip, *country;
683     dtr thedate;
684     int boolean;
685
686     if ((vl = MAPIFindProperty(&(TNEF->MapiProperties), PROP_TAG(PT_STRING8, PR_DISPLAY_NAME))) == MAPI_UNDEFINED) {
687         vl=MAPIFindProperty(&(TNEF->MapiProperties), PROP_TAG(PT_STRING8, PR_COMPANY_NAME));
688     }
689
690         fprintf(fptr, "BEGIN:VCARD\n");
691         fprintf(fptr, "VERSION:2.1\n");
692         if (vl != MAPI_UNDEFINED) {
693             fprintf(fptr, "FN:%s\n", vl->data);
694         }
695         fprintProperty(TNEF, fptr, PT_STRING8, PR_NICKNAME, "NICKNAME:%s\n");
696         fprintUserProp(TNEF, fptr, PT_STRING8, 0x8554, "MAILER:Microsoft Outlook %s\n");
697         fprintProperty(TNEF, fptr, PT_STRING8, PR_SPOUSE_NAME, "X-EVOLUTION-SPOUSE:%s\n");
698         fprintProperty(TNEF, fptr, PT_STRING8, PR_MANAGER_NAME, "X-EVOLUTION-MANAGER:%s\n");
699         fprintProperty(TNEF, fptr, PT_STRING8, PR_ASSISTANT, "X-EVOLUTION-ASSISTANT:%s\n");
700
701         // Organizational
702         if ((vl=MAPIFindProperty(&(TNEF->MapiProperties), PROP_TAG(PT_STRING8, PR_COMPANY_NAME))) != MAPI_UNDEFINED) {
703             if (vl->size > 0) {
704                 if ((vl->size == 1) && (vl->data[0] == 0)) {
705                 } else {
706                     fprintf(fptr,"ORG:%s", vl->data);
707                     if ((vl=MAPIFindProperty(&(TNEF->MapiProperties), PROP_TAG(PT_STRING8, PR_DEPARTMENT_NAME))) != MAPI_UNDEFINED) {
708                         fprintf(fptr,";%s", vl->data);
709                     }
710                     fprintf(fptr, "\n");
711                 }
712             }
713         }
714
715         fprintProperty(TNEF, fptr, PT_STRING8, PR_OFFICE_LOCATION, "X-EVOLUTION-OFFICE:%s\n");
716         fprintProperty(TNEF, fptr, PT_STRING8, PR_TITLE, "TITLE:%s\n");
717         fprintProperty(TNEF, fptr, PT_STRING8, PR_PROFESSION, "ROLE:%s\n");
718         fprintProperty(TNEF, fptr, PT_STRING8, PR_BODY, "NOTE:%s\n");
719         if (TNEF->body.size > 0) {
720             fprintf(fptr, "NOTE;QUOTED-PRINTABLE:");
721             quotedfprint(fptr, &(TNEF->body));
722             fprintf(fptr,"\n");
723         }
724
725
726         // Business Address
727         boolean = 0;
728         if ((pobox = MAPIFindProperty(&(TNEF->MapiProperties), PROP_TAG(PT_STRING8, PR_POST_OFFICE_BOX))) != MAPI_UNDEFINED) {
729             boolean = 1;
730         }
731         if ((street = MAPIFindProperty(&(TNEF->MapiProperties), PROP_TAG(PT_STRING8, PR_STREET_ADDRESS))) != MAPI_UNDEFINED) {
732             boolean = 1;
733         }
734         if ((city = MAPIFindProperty(&(TNEF->MapiProperties), PROP_TAG(PT_STRING8, PR_LOCALITY))) != MAPI_UNDEFINED) {
735             boolean = 1;
736         }
737         if ((state = MAPIFindProperty(&(TNEF->MapiProperties), PROP_TAG(PT_STRING8, PR_STATE_OR_PROVINCE))) != MAPI_UNDEFINED) {
738             boolean = 1;
739         }
740         if ((zip = MAPIFindProperty(&(TNEF->MapiProperties), PROP_TAG(PT_STRING8, PR_POSTAL_CODE))) != MAPI_UNDEFINED) {
741             boolean = 1;
742         }
743         if ((country = MAPIFindProperty(&(TNEF->MapiProperties), PROP_TAG(PT_STRING8, PR_COUNTRY))) != MAPI_UNDEFINED) {
744             boolean = 1;
745         }
746         if (boolean == 1) {
747             fprintf(fptr, "ADR;QUOTED-PRINTABLE;WORK:");
748             if (pobox != MAPI_UNDEFINED) {
749                 quotedfprint(fptr, pobox);
750             }
751             fprintf(fptr, ";;");
752             if (street != MAPI_UNDEFINED) {
753                 quotedfprint(fptr, street);
754             }
755             fprintf(fptr, ";");
756             if (city != MAPI_UNDEFINED) {
757                 quotedfprint(fptr, city);
758             }
759             fprintf(fptr, ";");
760             if (state != MAPI_UNDEFINED) {
761                 quotedfprint(fptr, state);
762             }
763             fprintf(fptr, ";");
764             if (zip != MAPI_UNDEFINED) {
765                 quotedfprint(fptr, zip);
766             }
767             fprintf(fptr, ";");
768             if (country != MAPI_UNDEFINED) {
769                 quotedfprint(fptr, country);
770             }
771             fprintf(fptr,"\n");
772             if ((vl = MAPIFindUserProp(&(TNEF->MapiProperties), PROP_TAG(PT_STRING8, 0x801b))) != MAPI_UNDEFINED) {
773                 fprintf(fptr, "LABEL;QUOTED-PRINTABLE;WORK:");
774                 quotedfprint(fptr, vl);
775                 fprintf(fptr,"\n");
776             }
777         }
778
779         // Home Address
780         boolean = 0;
781         if ((pobox = MAPIFindProperty(&(TNEF->MapiProperties), PROP_TAG(PT_STRING8, PR_HOME_ADDRESS_POST_OFFICE_BOX))) != MAPI_UNDEFINED) {
782             boolean = 1;
783         }
784         if ((street = MAPIFindProperty(&(TNEF->MapiProperties), PROP_TAG(PT_STRING8, PR_HOME_ADDRESS_STREET))) != MAPI_UNDEFINED) {
785             boolean = 1;
786         }
787         if ((city = MAPIFindProperty(&(TNEF->MapiProperties), PROP_TAG(PT_STRING8, PR_HOME_ADDRESS_CITY))) != MAPI_UNDEFINED) {
788             boolean = 1;
789         }
790         if ((state = MAPIFindProperty(&(TNEF->MapiProperties), PROP_TAG(PT_STRING8, PR_HOME_ADDRESS_STATE_OR_PROVINCE))) != MAPI_UNDEFINED) {
791             boolean = 1;
792         }
793         if ((zip = MAPIFindProperty(&(TNEF->MapiProperties), PROP_TAG(PT_STRING8, PR_HOME_ADDRESS_POSTAL_CODE))) != MAPI_UNDEFINED) {
794             boolean = 1;
795         }
796         if ((country = MAPIFindProperty(&(TNEF->MapiProperties), PROP_TAG(PT_STRING8, PR_HOME_ADDRESS_COUNTRY))) != MAPI_UNDEFINED) {
797             boolean = 1;
798         }
799         if (boolean == 1) {
800             fprintf(fptr, "ADR;QUOTED-PRINTABLE;HOME:");
801             if (pobox != MAPI_UNDEFINED) {
802                 quotedfprint(fptr, pobox);
803             }
804             fprintf(fptr, ";;");
805             if (street != MAPI_UNDEFINED) {
806                 quotedfprint(fptr, street);
807             }
808             fprintf(fptr, ";");
809             if (city != MAPI_UNDEFINED) {
810                 quotedfprint(fptr, city);
811             }
812             fprintf(fptr, ";");
813             if (state != MAPI_UNDEFINED) {
814                 quotedfprint(fptr, state);
815             }
816             fprintf(fptr, ";");
817             if (zip != MAPI_UNDEFINED) {
818                 quotedfprint(fptr, zip);
819             }
820             fprintf(fptr, ";");
821             if (country != MAPI_UNDEFINED) {
822                 quotedfprint(fptr, country);
823             }
824             fprintf(fptr,"\n");
825             if ((vl = MAPIFindUserProp(&(TNEF->MapiProperties), PROP_TAG(PT_STRING8, 0x801a))) != MAPI_UNDEFINED) {
826                 fprintf(fptr, "LABEL;QUOTED-PRINTABLE;WORK:");
827                 quotedfprint(fptr, vl);
828                 fprintf(fptr,"\n");
829             }
830         }
831
832         // Other Address
833         boolean = 0;
834         if ((pobox = MAPIFindProperty(&(TNEF->MapiProperties), PROP_TAG(PT_STRING8, PR_OTHER_ADDRESS_POST_OFFICE_BOX))) != MAPI_UNDEFINED) {
835             boolean = 1;
836         }
837         if ((street = MAPIFindProperty(&(TNEF->MapiProperties), PROP_TAG(PT_STRING8, PR_OTHER_ADDRESS_STREET))) != MAPI_UNDEFINED) {
838             boolean = 1;
839         }
840         if ((city = MAPIFindProperty(&(TNEF->MapiProperties), PROP_TAG(PT_STRING8, PR_OTHER_ADDRESS_CITY))) != MAPI_UNDEFINED) {
841             boolean = 1;
842         }
843         if ((state = MAPIFindProperty(&(TNEF->MapiProperties), PROP_TAG(PT_STRING8, PR_OTHER_ADDRESS_STATE_OR_PROVINCE))) != MAPI_UNDEFINED) {
844             boolean = 1;
845         }
846         if ((zip = MAPIFindProperty(&(TNEF->MapiProperties), PROP_TAG(PT_STRING8, PR_OTHER_ADDRESS_POSTAL_CODE))) != MAPI_UNDEFINED) {
847             boolean = 1;
848         }
849         if ((country = MAPIFindProperty(&(TNEF->MapiProperties), PROP_TAG(PT_STRING8, PR_OTHER_ADDRESS_COUNTRY))) != MAPI_UNDEFINED) {
850             boolean = 1;
851         }
852         if (boolean == 1) {
853             fprintf(fptr, "ADR;QUOTED-PRINTABLE;OTHER:");
854             if (pobox != MAPI_UNDEFINED) {
855                 quotedfprint(fptr, pobox);
856             }
857             fprintf(fptr, ";;");
858             if (street != MAPI_UNDEFINED) {
859                 quotedfprint(fptr, street);
860             }
861             fprintf(fptr, ";");
862             if (city != MAPI_UNDEFINED) {
863                 quotedfprint(fptr, city);
864             }
865             fprintf(fptr, ";");
866             if (state != MAPI_UNDEFINED) {
867                 quotedfprint(fptr, state);
868             }
869             fprintf(fptr, ";");
870             if (zip != MAPI_UNDEFINED) {
871                 quotedfprint(fptr, zip);
872             }
873             fprintf(fptr, ";");
874             if (country != MAPI_UNDEFINED) {
875                 quotedfprint(fptr, country);
876             }
877             fprintf(fptr,"\n");
878         }
879
880
881         fprintProperty(TNEF, fptr, PT_STRING8, PR_CALLBACK_TELEPHONE_NUMBER, "TEL;X-EVOLUTION-CALLBACK:%s\n");
882         fprintProperty(TNEF, fptr, PT_STRING8, PR_PRIMARY_TELEPHONE_NUMBER, "TEL;PREF:%s\n");
883         fprintProperty(TNEF, fptr, PT_STRING8, PR_MOBILE_TELEPHONE_NUMBER, "TEL;CELL:%s\n");
884         fprintProperty(TNEF, fptr, PT_STRING8, PR_RADIO_TELEPHONE_NUMBER, "TEL;X-EVOLUTION-RADIO:%s\n");
885         fprintProperty(TNEF, fptr, PT_STRING8, PR_CAR_TELEPHONE_NUMBER, "TEL;CAR:%s\n");
886         fprintProperty(TNEF, fptr, PT_STRING8, PR_OTHER_TELEPHONE_NUMBER, "TEL;VOICE:%s\n");
887         fprintProperty(TNEF, fptr, PT_STRING8, PR_PAGER_TELEPHONE_NUMBER, "TEL;PAGER:%s\n");
888         fprintProperty(TNEF, fptr, PT_STRING8, PR_TELEX_NUMBER, "TEL;X-EVOLUTION-TELEX:%s\n");
889         fprintProperty(TNEF, fptr, PT_STRING8, PR_ISDN_NUMBER, "TEL;ISDN:%s\n");
890         fprintProperty(TNEF, fptr, PT_STRING8, PR_HOME2_TELEPHONE_NUMBER, "TEL;HOME:%s\n");
891         fprintProperty(TNEF, fptr, PT_STRING8, PR_TTYTDD_PHONE_NUMBER, "TEL;X-EVOLUTION-TTYTDD:%s\n");
892         fprintProperty(TNEF, fptr, PT_STRING8, PR_HOME_TELEPHONE_NUMBER, "TEL;HOME;VOICE:%s\n");
893         fprintProperty(TNEF, fptr, PT_STRING8, PR_ASSISTANT_TELEPHONE_NUMBER, "TEL;X-EVOLUTION-ASSISTANT:%s\n");
894         fprintProperty(TNEF, fptr, PT_STRING8, PR_COMPANY_MAIN_PHONE_NUMBER, "TEL;WORK:%s\n");
895         fprintProperty(TNEF, fptr, PT_STRING8, PR_BUSINESS_TELEPHONE_NUMBER, "TEL;WORK:%s\n");
896         fprintProperty(TNEF, fptr, PT_STRING8, PR_BUSINESS2_TELEPHONE_NUMBER, "TEL;WORK;VOICE:%s\n");
897         fprintProperty(TNEF, fptr, PT_STRING8, PR_PRIMARY_FAX_NUMBER, "TEL;PREF;FAX:%s\n");
898         fprintProperty(TNEF, fptr, PT_STRING8, PR_BUSINESS_FAX_NUMBER, "TEL;WORK;FAX:%s\n");
899         fprintProperty(TNEF, fptr, PT_STRING8, PR_HOME_FAX_NUMBER, "TEL;HOME;FAX:%s\n");
900
901
902         // Email addresses
903         if ((vl=MAPIFindUserProp(&(TNEF->MapiProperties), PROP_TAG(PT_STRING8, 0x8083))) == MAPI_UNDEFINED) {
904             vl=MAPIFindUserProp(&(TNEF->MapiProperties), PROP_TAG(PT_STRING8, 0x8084));
905         }
906         if (vl != MAPI_UNDEFINED) {
907             if (vl->size > 0)
908                 fprintf(fptr, "EMAIL:%s\n", vl->data);
909         }
910         if ((vl=MAPIFindUserProp(&(TNEF->MapiProperties), PROP_TAG(PT_STRING8, 0x8093))) == MAPI_UNDEFINED) {
911             vl=MAPIFindUserProp(&(TNEF->MapiProperties), PROP_TAG(PT_STRING8, 0x8094));
912         }
913         if (vl != MAPI_UNDEFINED) {
914             if (vl->size > 0)
915                 fprintf(fptr, "EMAIL:%s\n", vl->data);
916         }
917         if ((vl=MAPIFindUserProp(&(TNEF->MapiProperties), PROP_TAG(PT_STRING8, 0x80a3))) == MAPI_UNDEFINED) {
918             vl=MAPIFindUserProp(&(TNEF->MapiProperties), PROP_TAG(PT_STRING8, 0x80a4));
919         }
920         if (vl != MAPI_UNDEFINED) {
921             if (vl->size > 0)
922                 fprintf(fptr, "EMAIL:%s\n", vl->data);
923         }
924
925         fprintProperty(TNEF, fptr, PT_STRING8, PR_BUSINESS_HOME_PAGE, "URL:%s\n");
926         fprintUserProp(TNEF, fptr, PT_STRING8, 0x80d8, "FBURL:%s\n");
927
928
929
930         //Birthday
931         if ((vl=MAPIFindProperty(&(TNEF->MapiProperties), PROP_TAG(PT_SYSTIME, PR_BIRTHDAY))) != MAPI_UNDEFINED) {
932             fprintf(fptr, "BDAY:");
933             MAPISysTimetoDTR(vl->data, &thedate);
934             fprintf(fptr, "%i-%02i-%02i\n", thedate.wYear, thedate.wMonth, thedate.wDay);
935         }
936
937         //Anniversary
938         if ((vl=MAPIFindProperty(&(TNEF->MapiProperties), PROP_TAG(PT_SYSTIME, PR_WEDDING_ANNIVERSARY))) != MAPI_UNDEFINED) {
939             fprintf(fptr, "X-EVOLUTION-ANNIVERSARY:");
940             MAPISysTimetoDTR(vl->data, &thedate);
941             fprintf(fptr, "%i-%02i-%02i\n", thedate.wYear, thedate.wMonth, thedate.wDay);
942         }
943         fprintf(fptr, "END:VCARD\n");
944         return TRUE;
945 }