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