evolution-3.6.4/modules/tnef-attachment/e-mail-parser-tnef-attachment.c

No issues found

Incomplete coverage

Tool Failure ID Location Function Message Data
clang-analyzer no-output-found e-mail-parser-tnef-attachment.c Message(text='Unable to locate XML output from invoke-clang-analyzer') None
clang-analyzer no-output-found e-mail-parser-tnef-attachment.c Message(text='Unable to locate XML output from invoke-clang-analyzer') None
Failure running clang-analyzer ('no-output-found')
Message
Unable to locate XML output from invoke-clang-analyzer
Failure running clang-analyzer ('no-output-found')
Message
Unable to locate XML output from invoke-clang-analyzer
   1 /*
   2  * This program is free software; you can redistribute it and/or
   3  * modify it under the terms of the GNU Lesser General Public
   4  * License as published by the Free Software Foundation; either
   5  * version 2 of the License, or (at your option) version 3.
   6  *
   7  * This program is distributed in the hope that it will be useful,
   8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  10  * Lesser General Public License for more details.
  11  *
  12  * You should have received a copy of the GNU Lesser General Public
  13  * License along with the program; if not, see <http://www.gnu.org/licenses/>
  14  */
  15 
  16 #ifdef HAVE_CONFIG_H
  17 #include <config.h>
  18 #endif
  19 
  20 #include <string.h>
  21 #include <gtk/gtk.h>
  22 #include <glib/gi18n.h>
  23 #include <glib/gprintf.h>
  24 #include <stdio.h>
  25 
  26 #include "e-mail-parser-tnef-attachment.h"
  27 
  28 #include <em-format/e-mail-extension-registry.h>
  29 #include <em-format/e-mail-parser-extension.h>
  30 #include <em-format/e-mail-part.h>
  31 #include <em-format/e-mail-part-utils.h>
  32 
  33 #include <sys/types.h>
  34 #include <dirent.h>
  35 #include <sys/stat.h>
  36 #include <fcntl.h>
  37 #include <ctype.h>
  38 #include <stdlib.h>
  39 #ifdef HAVE_YTNEF_H
  40 #include <ytnef.h>
  41 #elif defined HAVE_LIBYTNEF_YTNEF_H
  42 #include <libytnef/ytnef.h>
  43 #endif
  44 
  45 #include <mail/em-utils.h>
  46 #include <e-util/e-mktemp.h>
  47 
  48 #include <libebackend/libebackend.h>
  49 
  50 #define d(x)
  51 
  52 typedef struct _EMailParserTnefAttachment {
  53 	EExtension parent;
  54 
  55 	GSettings *settings;
  56 	gint mode;
  57 	gboolean show_suppressed;
  58 } EMailParserTnefAttachment;
  59 
  60 typedef struct _EMailParserTnefAttachmentClass {
  61 	EExtensionClass parent_class;
  62 } EMailParserTnefAttachmentClass;
  63 
  64 GType e_mail_parser_tnef_attachment_get_type (void);
  65 static void e_mail_parser_mail_extension_interface_init (EMailExtensionInterface *iface);
  66 static void e_mail_parser_parser_extension_interface_init (EMailParserExtensionInterface *iface);
  67 
  68 G_DEFINE_DYNAMIC_TYPE_EXTENDED (
  69 	EMailParserTnefAttachment,
  70 	e_mail_parser_tnef_attachment,
  71 	E_TYPE_EXTENSION,
  72 	0,
  73 	G_IMPLEMENT_INTERFACE_DYNAMIC (
  74 		E_TYPE_MAIL_EXTENSION,
  75 		e_mail_parser_mail_extension_interface_init)
  76 	G_IMPLEMENT_INTERFACE_DYNAMIC (
  77 		E_TYPE_MAIL_PARSER_EXTENSION,
  78 		e_mail_parser_parser_extension_interface_init));
  79 
  80 static const gchar * parser_mime_types[] = { "application/vnd.ms-tnef",
  81 					    "application/ms-tnefl",
  82 					    NULL };
  83 
  84 gint verbose = 0;
  85 gint saveRTF = 0;
  86 gint saveintermediate = 0;
  87 gboolean loaded = FALSE;
  88 void processTnef (TNEFStruct *tnef, const gchar *tmpdir);
  89 void saveVCalendar (TNEFStruct *tnef, const gchar *tmpdir);
  90 void saveVCard (TNEFStruct *tnef, const gchar *tmpdir);
  91 void saveVTask (TNEFStruct *tnef, const gchar *tmpdir);
  92 
  93 /* Other Prototypes */
  94 void fprintProperty (TNEFStruct *tnef, FILE *fptr, DWORD proptype, DWORD propid, const gchar text[]);
  95 void fprintUserProp (TNEFStruct *tnef, FILE *fptr, DWORD proptype, DWORD propid, const gchar text[]);
  96 void quotedfprint (FILE *fptr, variableLength *vl);
  97 void cstylefprint (FILE *fptr, variableLength *vl);
  98 void printRtf (FILE *fptr, variableLength *vl);
  99 void printRrule (FILE *fptr, gchar *recur_data, gint size, TNEFStruct *tnef);
 100 guchar getRruleCount (guchar a, guchar b);
 101 guchar getRruleMonthNum (guchar a, guchar b);
 102 gchar * getRruleDayname (guchar a);
 103 
 104 static gchar *
 105 sanitize_filename (const gchar *filename)
 106 {
 107 	gchar * sanitized_name;
 108 	sanitized_name = g_path_get_basename (filename);
 109 	if (sanitized_name == NULL || !g_strcmp0 (sanitized_name, ".")) {
 110 		g_free (sanitized_name);
 111 		return NULL;
 112 	} else {
 113 		return g_strdelimit (sanitized_name, " ", '_');
 114 	}
 115 }
 116 
 117 static GSList *
 118 empe_tnef_attachment_parse (EMailParserExtension *extension,
 119                             EMailParser *parser,
 120                             CamelMimePart *part,
 121                             GString *part_id,
 122                             GCancellable *cancellable)
 123 {
 124 	gchar *tmpdir, *name;
 125 	CamelStream *out;
 126 	struct dirent *d;
 127 	DIR *dir;
 128 	CamelMultipart *mp;
 129 	CamelMimePart *mainpart;
 130 	CamelDataWrapper *content;
 131 	gint len;
 132 	TNEFStruct tnef;
 133 	GSList *parts;
 134 
 135 	tmpdir = e_mkdtemp ("tnef-attachment-XXXXXX");
 136 	if (tmpdir == NULL)
 137 		return NULL;
 138 
 139 	name = g_build_filename (tmpdir, ".evo-attachment.tnef", NULL);
 140 
 141 	out = camel_stream_fs_new_with_name (name, O_RDWR | O_CREAT, 0666, NULL);
 142 	if (out == NULL) {
 143 	    g_free (name);
 144 	    return NULL;
 145 	}
 146 	content = camel_medium_get_content ((CamelMedium *) part);
 147 	if (content == NULL) {
 148 		g_free (name);
 149 		g_object_unref (out);
 150 		return NULL;
 151 	}
 152 	if (camel_data_wrapper_decode_to_stream_sync (content, out, NULL, NULL) == -1
 153 	    || camel_stream_close (out, NULL, NULL) == -1) {
 154 		g_object_unref (out);
 155 		g_free (name);
 156 		return NULL;
 157 	}
 158 	g_object_unref (out);
 159 
 160 	/* Extracting the winmail.dat */
 161 	TNEFInitialize (&tnef);
 162 	tnef.Debug = verbose;
 163 	if (TNEFParseFile (name, &tnef) == -1) {
 164 	    printf ("ERROR processing file\n");
 165 	}
 166 	processTnef (&tnef, tmpdir);
 167 
 168 	TNEFFree (&tnef);
 169 	/* Extraction done */
 170 
 171 	dir = opendir (tmpdir);
 172 	if (dir == NULL) {
 173 	    g_object_unref (out);
 174 	    g_free (name);
 175 	    return NULL;
 176 	}
 177 
 178 	mainpart = camel_mime_part_new ();
 179 
 180 	mp = camel_multipart_new ();
 181 	camel_data_wrapper_set_mime_type ((CamelDataWrapper *) mp, "multipart/mixed");
 182 	camel_multipart_set_boundary (mp, NULL);
 183 
 184 	camel_medium_set_content ((CamelMedium *) mainpart, (CamelDataWrapper *) mp);
 185 
 186 	while ((d = readdir (dir))) {
 187 		CamelMimePart *part;
 188 		CamelDataWrapper *content;
 189 		CamelStream *stream;
 190 		gchar *path;
 191 		const gchar *type;
 192 
 193 		if (!strcmp (d->d_name, ".")
 194 		    || !strcmp (d->d_name, "..")
 195 		    || !strcmp (d->d_name, ".evo-attachment.tnef"))
 196 		    continue;
 197 
 198 		path = g_build_filename (tmpdir, d->d_name, NULL);
 199 
 200 		stream = camel_stream_fs_new_with_name (path, O_RDONLY, 0, NULL);
 201 		content = camel_data_wrapper_new ();
 202 		camel_data_wrapper_construct_from_stream_sync (
 203 			content, stream, NULL, NULL);
 204 		g_object_unref (stream);
 205 
 206 		part = camel_mime_part_new ();
 207 		camel_mime_part_set_encoding (part, CAMEL_TRANSFER_ENCODING_BINARY);
 208 
 209 		camel_medium_set_content ((CamelMedium *) part, content);
 210 		g_object_unref (content);
 211 
 212 		type = e_mail_part_snoop_type (part);
 213 		if (type)
 214 		    camel_data_wrapper_set_mime_type ((CamelDataWrapper *) part, type);
 215 
 216 		camel_mime_part_set_filename (part, d->d_name);
 217 
 218 		g_free (path);
 219 
 220 		camel_multipart_add_part (mp, part);
 221 		g_object_unref (part);
 222 	}
 223 
 224 	closedir (dir);
 225 
 226 	len = part_id->len;
 227 	g_string_append_printf (part_id, ".tnef");
 228 
 229 	parts = NULL;
 230 	if (camel_multipart_get_number (mp) > 0) {
 231 
 232 		CamelMimePart *part = camel_mime_part_new ();
 233 
 234 		camel_medium_set_content (
 235 			(CamelMedium *) part,
 236 			CAMEL_DATA_WRAPPER (mp));
 237 
 238 		parts = e_mail_parser_parse_part_as (
 239 			parser, part, part_id,
 240 			"multipart/mixed", cancellable);
 241 
 242 		g_object_unref (part);
 243 	}
 244 
 245 	g_string_truncate (part_id, len);
 246 
 247 	if (parts)
 248 		parts = e_mail_parser_wrap_as_attachment (
 249 			parser, part, parts, part_id, cancellable);
 250 
 251 	g_object_unref (mp);
 252 	g_object_unref (mainpart);
 253 
 254 	g_free (name);
 255 	g_free (tmpdir);
 256 
 257 	return parts;
 258 }
 259 
 260 static const gchar **
 261 empe_mime_types (EMailExtension *extension)
 262 {
 263 	return parser_mime_types;
 264 }
 265 
 266 void
 267 e_mail_parser_tnef_attachment_type_register (GTypeModule *type_module)
 268 {
 269 	e_mail_parser_tnef_attachment_register_type (type_module);
 270 }
 271 
 272 static void
 273 e_mail_parser_mail_extension_interface_init (EMailExtensionInterface *iface)
 274 {
 275 	iface->mime_types = empe_mime_types;
 276 }
 277 
 278 static void
 279 e_mail_parser_parser_extension_interface_init (EMailParserExtensionInterface *iface)
 280 {
 281 	iface->parse = empe_tnef_attachment_parse;
 282 }
 283 
 284 static void
 285 e_mail_parser_tnef_attachment_constructed (GObject *object)
 286 {
 287 	EExtensible *extensible;
 288 	EMailExtensionRegistry *reg;
 289 
 290 	extensible = e_extension_get_extensible (E_EXTENSION (object));
 291 	reg = E_MAIL_EXTENSION_REGISTRY (extensible);
 292 
 293 	e_mail_extension_registry_add_extension (reg, E_MAIL_EXTENSION (object));
 294 }
 295 
 296 static void
 297 e_mail_parser_tnef_attachment_class_init (EMailParserTnefAttachmentClass *class)
 298 {
 299 	GObjectClass *object_class;
 300 	EExtensionClass *extension_class;
 301 
 302 	object_class = G_OBJECT_CLASS (class);
 303 	object_class->constructed = e_mail_parser_tnef_attachment_constructed;
 304 
 305 	extension_class = E_EXTENSION_CLASS (class);
 306 	extension_class->extensible_type = E_TYPE_MAIL_PARSER_EXTENSION_REGISTRY;
 307 }
 308 
 309 void
 310 e_mail_parser_tnef_attachment_class_finalize (EMailParserTnefAttachmentClass *class)
 311 {
 312 }
 313 
 314 static void
 315 e_mail_parser_tnef_attachment_init (EMailParserTnefAttachment *parser)
 316 {
 317 }
 318 
 319 void
 320 processTnef (TNEFStruct *tnef,
 321              const gchar *tmpdir)
 322 {
 323     variableLength *filename;
 324     variableLength *filedata;
 325     Attachment *p;
 326     gint RealAttachment;
 327     gint object;
 328     gchar *ifilename = NULL;
 329     gchar *absfilename, *file;
 330     gint count;
 331     gint foundCal = 0;
 332 
 333     FILE *fptr;
 334 
 335     /* First see if this requires special processing. */
 336     /* ie: it's a Contact Card, Task, or Meeting request (vCal/vCard) */
 337     if (tnef->messageClass[0] != 0)  {
 338 	if (strcmp (tnef->messageClass, "IPM.Contact") == 0) {
 339 	    saveVCard (tnef, tmpdir);
 340 	}
 341 	if (strcmp (tnef->messageClass, "IPM.Task") == 0) {
 342 	    saveVTask (tnef, tmpdir);
 343 	}
 344 	if (strcmp (tnef->messageClass, "IPM.Appointment") == 0) {
 345 	    saveVCalendar (tnef, tmpdir);
 346 	    foundCal = 1;
 347 	}
 348     }
 349 
 350     if ((filename = MAPIFindUserProp (&(tnef->MapiProperties),
 351 			PROP_TAG (PT_STRING8,0x24))) != MAPI_UNDEFINED) {
 352 	if (strcmp (filename->data, "IPM.Appointment") == 0) {
 353              /* If it's "indicated" twice, we don't want to save 2 calendar entries. */
 354 	    if (foundCal == 0) {
 355 		saveVCalendar (tnef, tmpdir);
 356 	    }
 357 	}
 358     }
 359 
 360     if (strcmp (tnef->messageClass, "IPM.Microsoft Mail.Note") == 0) {
 361 	if ((saveRTF == 1) && (tnef->subject.size > 0)) {
 362             /*  Description */
 363 	    if ((filename = MAPIFindProperty (&(tnef->MapiProperties),
 364 					   PROP_TAG (PT_BINARY, PR_RTF_COMPRESSED)))
 365 		    != MAPI_UNDEFINED) {
 366 		variableLength buf;
 367 		if ((buf.data = (gchar *) DecompressRTF (filename, &buf.size)) != NULL) {
 368 		    file = sanitize_filename (tnef->subject.data);
 369 		    if (!file)
 370 			    return;
 371 		    absfilename = g_strconcat (file, ".rtf", NULL);
 372 		    ifilename = g_build_filename (tmpdir, file, NULL);
 373 		    g_free (absfilename);
 374 		    g_free (file);
 375 
 376 		    if ((fptr = fopen (ifilename, "wb")) == NULL) {
 377 			printf ("ERROR: Error writing file to disk!");
 378 		    } else {
 379 			fwrite (
 380 				buf.data,
 381 				sizeof (BYTE),
 382 				buf.size,
 383 				fptr);
 384 			fclose (fptr);
 385 		    }
 386 		    free (buf.data);
 387 		}
 388 	    }
 389 	}
 390     }
 391 
 392     /* Now process each attachment */
 393     p = tnef->starting_attach.next;
 394     count = 0;
 395     while (p != NULL) {
 396 	count++;
 397         /* Make sure it has a size. */
 398 	if (p->FileData.size > 0) {
 399 	    object = 1;
 400 
 401             /* See if the contents are stored as "attached data" */
 402 	    /* Inside the MAPI blocks. */
 403 	    if ((filedata = MAPIFindProperty (&(p->MAPI),
 404 				    PROP_TAG (PT_OBJECT, PR_ATTACH_DATA_OBJ)))
 405 		    == MAPI_UNDEFINED) {
 406 		if ((filedata = MAPIFindProperty (&(p->MAPI),
 407 				    PROP_TAG (PT_BINARY, PR_ATTACH_DATA_OBJ)))
 408 		   == MAPI_UNDEFINED) {
 409                     /* Nope, standard TNEF stuff. */
 410 		    filedata = &(p->FileData);
 411 		    object = 0;
 412 		}
 413 	    }
 414             /* See if this is an embedded TNEF stream. */
 415 	    RealAttachment = 1;
 416 	    if (object == 1) {
 417                 /*  This is an "embedded object", so skip the */
 418                 /* 16-byte identifier first. */
 419 		TNEFStruct emb_tnef;
 420 		DWORD signature;
 421 		memcpy (&signature, filedata->data + 16, sizeof (DWORD));
 422 		if (TNEFCheckForSignature (signature) == 0) {
 423                     /* Has a TNEF signature, so process it. */
 424 		    TNEFInitialize (&emb_tnef);
 425 		    emb_tnef.Debug = tnef->Debug;
 426 		    if (TNEFParseMemory ((guchar *) filedata->data + 16,
 427 			     filedata->size - 16, &emb_tnef) != -1) {
 428 			processTnef (&emb_tnef, tmpdir);
 429 			RealAttachment = 0;
 430 		    }
 431 		    TNEFFree (&emb_tnef);
 432 		}
 433 	    } else {
 434 		TNEFStruct emb_tnef;
 435 		DWORD signature;
 436 		memcpy (&signature, filedata->data, sizeof (DWORD));
 437 		if (TNEFCheckForSignature (signature) == 0) {
 438                     /* Has a TNEF signature, so process it. */
 439 		    TNEFInitialize (&emb_tnef);
 440 		    emb_tnef.Debug = tnef->Debug;
 441 		    if (TNEFParseMemory ((guchar *) filedata->data,
 442 			    filedata->size, &emb_tnef) != -1) {
 443 			processTnef (&emb_tnef, tmpdir);
 444 			RealAttachment = 0;
 445 		    }
 446 		    TNEFFree (&emb_tnef);
 447 		}
 448 	    }
 449 	    if ((RealAttachment == 1) || (saveintermediate == 1)) {
 450 		gchar tmpname[20];
 451                 /* Ok, it's not an embedded stream, so now we */
 452 		/* process it. */
 453 		if ((filename = MAPIFindProperty (&(p->MAPI),
 454 					PROP_TAG (PT_STRING8, PR_ATTACH_LONG_FILENAME)))
 455 			== MAPI_UNDEFINED) {
 456 		    if ((filename = MAPIFindProperty (&(p->MAPI),
 457 					PROP_TAG (PT_STRING8, PR_DISPLAY_NAME)))
 458 			    == MAPI_UNDEFINED) {
 459 			filename = &(p->Title);
 460 		    }
 461 		}
 462 		if (filename->size == 1) {
 463 		    filename->size = 20;
 464 		    g_sprintf (tmpname, "file_%03i.dat", count);
 465 		    filename->data = tmpname;
 466 		}
 467 		absfilename = sanitize_filename (filename->data);
 468 		if (!absfilename)
 469 		    return;
 470 		ifilename = g_build_filename (tmpdir, absfilename, NULL);
 471 		g_free (absfilename);
 472 
 473 		if ((fptr = fopen (ifilename, "wb")) == NULL) {
 474 		    printf ("ERROR: Error writing file to disk!");
 475 		} else {
 476 		    if (object == 1) {
 477 			fwrite (
 478 				filedata->data + 16,
 479 				sizeof (BYTE),
 480 				filedata->size - 16,
 481 				fptr);
 482 		    } else {
 483 			fwrite (
 484 				filedata->data,
 485 				sizeof (BYTE),
 486 				filedata->size,
 487 				fptr);
 488 		    }
 489 		    fclose (fptr);
 490 		}
 491 	    }
 492 	} /* if size>0 */
 493 	p = p->next;
 494     } /* while p!= null */
 495     g_free (ifilename);
 496 }
 497 
 498 void
 499 saveVCard (TNEFStruct *tnef,
 500            const gchar *tmpdir)
 501 {
 502     gchar *ifilename;
 503     gchar *absfilename, *file = NULL;
 504     FILE *fptr;
 505     variableLength *vl;
 506     variableLength *pobox, *street, *city, *state, *zip, *country;
 507     dtr thedate;
 508     gint boolean;
 509 
 510     if ((vl = MAPIFindProperty (&(tnef->MapiProperties), PROP_TAG (PT_STRING8, PR_DISPLAY_NAME))) == MAPI_UNDEFINED) {
 511 	if ((vl = MAPIFindProperty (&(tnef->MapiProperties), PROP_TAG (PT_STRING8, PR_COMPANY_NAME))) == MAPI_UNDEFINED) {
 512 	    if (tnef->subject.size > 0) {
 513 	       file = sanitize_filename (tnef->subject.data);
 514 		if (!file)
 515 		    return;
 516 		absfilename = g_strconcat (file, ".vcard", NULL);
 517 	    } else
 518 		absfilename = g_strdup ("unknown.vcard");
 519      } else {
 520 	    file = sanitize_filename (vl->data);
 521 	    if (!file)
 522 		return;
 523 	    absfilename = g_strconcat (file, ".vcard", NULL);
 524 	}
 525     } else {
 526 	file = sanitize_filename (vl->data);
 527 	if (!file)
 528 	    return;
 529 	absfilename = g_strconcat (file, ".vcard", NULL);
 530     }
 531 
 532     ifilename = g_build_filename (tmpdir, absfilename, NULL);
 533     g_free (file);
 534     g_free (absfilename);
 535 
 536     if ((fptr = fopen (ifilename, "wb")) == NULL) {
 537 	    printf ("Error writing file to disk!");
 538     } else {
 539 	fprintf (fptr, "BEGIN:VCARD\n");
 540 	fprintf (fptr, "VERSION:2.1\n");
 541 	if (vl != MAPI_UNDEFINED) {
 542 	    fprintf (fptr, "FN:%s\n", vl->data);
 543 	}
 544 	fprintProperty (tnef, fptr, PT_STRING8, PR_NICKNAME, "NICKNAME:%s\n");
 545 	fprintUserProp (tnef, fptr, PT_STRING8, 0x8554, "MAILER:Microsoft Outlook %s\n");
 546 	fprintProperty (tnef, fptr, PT_STRING8, PR_SPOUSE_NAME, "X-EVOLUTION-SPOUSE:%s\n");
 547 	fprintProperty (tnef, fptr, PT_STRING8, PR_MANAGER_NAME, "X-EVOLUTION-MANAGER:%s\n");
 548 	fprintProperty (tnef, fptr, PT_STRING8, PR_ASSISTANT, "X-EVOLUTION-ASSISTANT:%s\n");
 549 
 550         /* Organizational */
 551 	if ((vl = MAPIFindProperty (&(tnef->MapiProperties), PROP_TAG (PT_STRING8, PR_COMPANY_NAME))) != MAPI_UNDEFINED) {
 552 	    if (vl->size > 0) {
 553 		if ((vl->size == 1) && (vl->data[0] == 0)) {
 554 		} else {
 555 		    fprintf (fptr,"ORG:%s", vl->data);
 556 		    if ((vl = MAPIFindProperty (&(tnef->MapiProperties), PROP_TAG (PT_STRING8, PR_DEPARTMENT_NAME))) != MAPI_UNDEFINED) {
 557 			fprintf (fptr,";%s", vl->data);
 558 		    }
 559 		    fprintf (fptr, "\n");
 560 		}
 561 	    }
 562 	}
 563 
 564 	fprintProperty (tnef, fptr, PT_STRING8, PR_OFFICE_LOCATION, "X-EVOLUTION-OFFICE:%s\n");
 565 	fprintProperty (tnef, fptr, PT_STRING8, PR_TITLE, "TITLE:%s\n");
 566 	fprintProperty (tnef, fptr, PT_STRING8, PR_PROFESSION, "ROLE:%s\n");
 567 	fprintProperty (tnef, fptr, PT_STRING8, PR_BODY, "NOTE:%s\n");
 568 	if (tnef->body.size > 0) {
 569 	    fprintf (fptr, "NOTE;QUOTED-PRINTABLE:");
 570 	    quotedfprint (fptr, &(tnef->body));
 571 	    fprintf (fptr,"\n");
 572 	}
 573 
 574         /* Business Address */
 575 	boolean = 0;
 576 	if ((pobox = MAPIFindProperty (&(tnef->MapiProperties), PROP_TAG (PT_STRING8, PR_POST_OFFICE_BOX))) != MAPI_UNDEFINED) {
 577 	    boolean = 1;
 578 	}
 579 	if ((street = MAPIFindProperty (&(tnef->MapiProperties), PROP_TAG (PT_STRING8, PR_STREET_ADDRESS))) != MAPI_UNDEFINED) {
 580 	    boolean = 1;
 581 	}
 582 	if ((city = MAPIFindProperty (&(tnef->MapiProperties), PROP_TAG (PT_STRING8, PR_LOCALITY))) != MAPI_UNDEFINED) {
 583 	    boolean = 1;
 584 	}
 585 	if ((state = MAPIFindProperty (&(tnef->MapiProperties), PROP_TAG (PT_STRING8, PR_STATE_OR_PROVINCE))) != MAPI_UNDEFINED) {
 586 	    boolean = 1;
 587 	}
 588 	if ((zip = MAPIFindProperty (&(tnef->MapiProperties), PROP_TAG (PT_STRING8, PR_POSTAL_CODE))) != MAPI_UNDEFINED) {
 589 	    boolean = 1;
 590 	}
 591 	if ((country = MAPIFindProperty (&(tnef->MapiProperties), PROP_TAG (PT_STRING8, PR_COUNTRY))) != MAPI_UNDEFINED) {
 592 	    boolean = 1;
 593 	}
 594 	if (boolean == 1) {
 595 	    fprintf (fptr, "ADR;QUOTED-PRINTABLE;WORK:");
 596 	    if (pobox != MAPI_UNDEFINED) {
 597 		quotedfprint (fptr, pobox);
 598 	    }
 599 	    fprintf (fptr, ";;");
 600 	    if (street != MAPI_UNDEFINED) {
 601 		quotedfprint (fptr, street);
 602 	    }
 603 	    fprintf (fptr, ";");
 604 	    if (city != MAPI_UNDEFINED) {
 605 		quotedfprint (fptr, city);
 606 	    }
 607 	    fprintf (fptr, ";");
 608 	    if (state != MAPI_UNDEFINED) {
 609 		quotedfprint (fptr, state);
 610 	    }
 611 	    fprintf (fptr, ";");
 612 	    if (zip != MAPI_UNDEFINED) {
 613 		quotedfprint (fptr, zip);
 614 	    }
 615 	    fprintf (fptr, ";");
 616 	    if (country != MAPI_UNDEFINED) {
 617 		quotedfprint (fptr, country);
 618 	    }
 619 	    fprintf (fptr,"\n");
 620 	    if ((vl = MAPIFindUserProp (&(tnef->MapiProperties), PROP_TAG (PT_STRING8, 0x801b))) != MAPI_UNDEFINED) {
 621 		fprintf (fptr, "LABEL;QUOTED-PRINTABLE;WORK:");
 622 		quotedfprint (fptr, vl);
 623 		fprintf (fptr,"\n");
 624 	    }
 625 	}
 626 
 627         /* Home Address */
 628 	boolean = 0;
 629 	if ((pobox = MAPIFindProperty (&(tnef->MapiProperties), PROP_TAG (PT_STRING8, PR_HOME_ADDRESS_POST_OFFICE_BOX))) != MAPI_UNDEFINED) {
 630 	    boolean = 1;
 631 	}
 632 	if ((street = MAPIFindProperty (&(tnef->MapiProperties), PROP_TAG (PT_STRING8, PR_HOME_ADDRESS_STREET))) != MAPI_UNDEFINED) {
 633 	    boolean = 1;
 634 	}
 635 	if ((city = MAPIFindProperty (&(tnef->MapiProperties), PROP_TAG (PT_STRING8, PR_HOME_ADDRESS_CITY))) != MAPI_UNDEFINED) {
 636 	    boolean = 1;
 637 	}
 638 	if ((state = MAPIFindProperty (&(tnef->MapiProperties), PROP_TAG (PT_STRING8, PR_HOME_ADDRESS_STATE_OR_PROVINCE))) != MAPI_UNDEFINED) {
 639 	    boolean = 1;
 640 	}
 641 	if ((zip = MAPIFindProperty (&(tnef->MapiProperties), PROP_TAG (PT_STRING8, PR_HOME_ADDRESS_POSTAL_CODE))) != MAPI_UNDEFINED) {
 642 	    boolean = 1;
 643 	}
 644 	if ((country = MAPIFindProperty (&(tnef->MapiProperties), PROP_TAG (PT_STRING8, PR_HOME_ADDRESS_COUNTRY))) != MAPI_UNDEFINED) {
 645 	    boolean = 1;
 646 	}
 647 	if (boolean == 1) {
 648 	    fprintf (fptr, "ADR;QUOTED-PRINTABLE;HOME:");
 649 	    if (pobox != MAPI_UNDEFINED) {
 650 		quotedfprint (fptr, pobox);
 651 	    }
 652 	    fprintf (fptr, ";;");
 653 	    if (street != MAPI_UNDEFINED) {
 654 		quotedfprint (fptr, street);
 655 	    }
 656 	    fprintf (fptr, ";");
 657 	    if (city != MAPI_UNDEFINED) {
 658 		quotedfprint (fptr, city);
 659 	    }
 660 	    fprintf (fptr, ";");
 661 	    if (state != MAPI_UNDEFINED) {
 662 		quotedfprint (fptr, state);
 663 	    }
 664 	    fprintf (fptr, ";");
 665 	    if (zip != MAPI_UNDEFINED) {
 666 		quotedfprint (fptr, zip);
 667 	    }
 668 	    fprintf (fptr, ";");
 669 	    if (country != MAPI_UNDEFINED) {
 670 		quotedfprint (fptr, country);
 671 	    }
 672 	    fprintf (fptr,"\n");
 673 	    if ((vl = MAPIFindUserProp (&(tnef->MapiProperties), PROP_TAG (PT_STRING8, 0x801a))) != MAPI_UNDEFINED) {
 674 		fprintf (fptr, "LABEL;QUOTED-PRINTABLE;WORK:");
 675 		quotedfprint (fptr, vl);
 676 		fprintf (fptr,"\n");
 677 	    }
 678 	}
 679 
 680         /* Other Address */
 681 	boolean = 0;
 682 	if ((pobox = MAPIFindProperty (&(tnef->MapiProperties), PROP_TAG (PT_STRING8, PR_OTHER_ADDRESS_POST_OFFICE_BOX))) != MAPI_UNDEFINED) {
 683 	    boolean = 1;
 684 	}
 685 	if ((street = MAPIFindProperty (&(tnef->MapiProperties), PROP_TAG (PT_STRING8, PR_OTHER_ADDRESS_STREET))) != MAPI_UNDEFINED) {
 686 	    boolean = 1;
 687 	}
 688 	if ((city = MAPIFindProperty (&(tnef->MapiProperties), PROP_TAG (PT_STRING8, PR_OTHER_ADDRESS_CITY))) != MAPI_UNDEFINED) {
 689 	    boolean = 1;
 690 	}
 691 	if ((state = MAPIFindProperty (&(tnef->MapiProperties), PROP_TAG (PT_STRING8, PR_OTHER_ADDRESS_STATE_OR_PROVINCE))) != MAPI_UNDEFINED) {
 692 	    boolean = 1;
 693 	}
 694 	if ((zip = MAPIFindProperty (&(tnef->MapiProperties), PROP_TAG (PT_STRING8, PR_OTHER_ADDRESS_POSTAL_CODE))) != MAPI_UNDEFINED) {
 695 	    boolean = 1;
 696 	}
 697 	if ((country = MAPIFindProperty (&(tnef->MapiProperties), PROP_TAG (PT_STRING8, PR_OTHER_ADDRESS_COUNTRY))) != MAPI_UNDEFINED) {
 698 	    boolean = 1;
 699 	}
 700 	if (boolean == 1) {
 701 	    fprintf (fptr, "ADR;QUOTED-PRINTABLE;OTHER:");
 702 	    if (pobox != MAPI_UNDEFINED) {
 703 		quotedfprint (fptr, pobox);
 704 	    }
 705 	    fprintf (fptr, ";;");
 706 	    if (street != MAPI_UNDEFINED) {
 707 		quotedfprint (fptr, street);
 708 	    }
 709 	    fprintf (fptr, ";");
 710 	    if (city != MAPI_UNDEFINED) {
 711 		quotedfprint (fptr, city);
 712 	    }
 713 	    fprintf (fptr, ";");
 714 	    if (state != MAPI_UNDEFINED) {
 715 		quotedfprint (fptr, state);
 716 	    }
 717 	    fprintf (fptr, ";");
 718 	    if (zip != MAPI_UNDEFINED) {
 719 		quotedfprint (fptr, zip);
 720 	    }
 721 	    fprintf (fptr, ";");
 722 	    if (country != MAPI_UNDEFINED) {
 723 		quotedfprint (fptr, country);
 724 	    }
 725 	    fprintf (fptr,"\n");
 726 	}
 727 
 728 	fprintProperty (tnef, fptr, PT_STRING8, PR_CALLBACK_TELEPHONE_NUMBER, "TEL;X-EVOLUTION-CALLBACK:%s\n");
 729 	fprintProperty (tnef, fptr, PT_STRING8, PR_PRIMARY_TELEPHONE_NUMBER, "TEL;PREF:%s\n");
 730 	fprintProperty (tnef, fptr, PT_STRING8, PR_MOBILE_TELEPHONE_NUMBER, "TEL;CELL:%s\n");
 731 	fprintProperty (tnef, fptr, PT_STRING8, PR_RADIO_TELEPHONE_NUMBER, "TEL;X-EVOLUTION-RADIO:%s\n");
 732 	fprintProperty (tnef, fptr, PT_STRING8, PR_CAR_TELEPHONE_NUMBER, "TEL;CAR:%s\n");
 733 	fprintProperty (tnef, fptr, PT_STRING8, PR_OTHER_TELEPHONE_NUMBER, "TEL;VOICE:%s\n");
 734 	fprintProperty (tnef, fptr, PT_STRING8, PR_PAGER_TELEPHONE_NUMBER, "TEL;PAGER:%s\n");
 735 	fprintProperty (tnef, fptr, PT_STRING8, PR_TELEX_NUMBER, "TEL;X-EVOLUTION-TELEX:%s\n");
 736 	fprintProperty (tnef, fptr, PT_STRING8, PR_ISDN_NUMBER, "TEL;ISDN:%s\n");
 737 	fprintProperty (tnef, fptr, PT_STRING8, PR_HOME2_TELEPHONE_NUMBER, "TEL;HOME:%s\n");
 738 	fprintProperty (tnef, fptr, PT_STRING8, PR_TTYTDD_PHONE_NUMBER, "TEL;X-EVOLUTION-TTYTDD:%s\n");
 739 	fprintProperty (tnef, fptr, PT_STRING8, PR_HOME_TELEPHONE_NUMBER, "TEL;HOME;VOICE:%s\n");
 740 	fprintProperty (tnef, fptr, PT_STRING8, PR_ASSISTANT_TELEPHONE_NUMBER, "TEL;X-EVOLUTION-ASSISTANT:%s\n");
 741 	fprintProperty (tnef, fptr, PT_STRING8, PR_COMPANY_MAIN_PHONE_NUMBER, "TEL;WORK:%s\n");
 742 	fprintProperty (tnef, fptr, PT_STRING8, PR_BUSINESS_TELEPHONE_NUMBER, "TEL;WORK:%s\n");
 743 	fprintProperty (tnef, fptr, PT_STRING8, PR_BUSINESS2_TELEPHONE_NUMBER, "TEL;WORK;VOICE:%s\n");
 744 	fprintProperty (tnef, fptr, PT_STRING8, PR_PRIMARY_FAX_NUMBER, "TEL;PREF;FAX:%s\n");
 745 	fprintProperty (tnef, fptr, PT_STRING8, PR_BUSINESS_FAX_NUMBER, "TEL;WORK;FAX:%s\n");
 746 	fprintProperty (tnef, fptr, PT_STRING8, PR_HOME_FAX_NUMBER, "TEL;HOME;FAX:%s\n");
 747 
 748         /* Email addresses */
 749 	if ((vl = MAPIFindUserProp (&(tnef->MapiProperties), PROP_TAG (PT_STRING8, 0x8083))) == MAPI_UNDEFINED) {
 750 	    vl = MAPIFindUserProp (&(tnef->MapiProperties), PROP_TAG (PT_STRING8, 0x8084));
 751 	}
 752 	if (vl != MAPI_UNDEFINED) {
 753 	    if (vl->size > 0)
 754 		fprintf (fptr, "EMAIL:%s\n", vl->data);
 755 	}
 756 	if ((vl = MAPIFindUserProp (&(tnef->MapiProperties), PROP_TAG (PT_STRING8, 0x8093))) == MAPI_UNDEFINED) {
 757 	    vl = MAPIFindUserProp (&(tnef->MapiProperties), PROP_TAG (PT_STRING8, 0x8094));
 758 	}
 759 	if (vl != MAPI_UNDEFINED) {
 760 	    if (vl->size > 0)
 761 		fprintf (fptr, "EMAIL:%s\n", vl->data);
 762 	}
 763 	if ((vl = MAPIFindUserProp (&(tnef->MapiProperties), PROP_TAG (PT_STRING8, 0x80a3))) == MAPI_UNDEFINED) {
 764 	    vl = MAPIFindUserProp (&(tnef->MapiProperties), PROP_TAG (PT_STRING8, 0x80a4));
 765 	}
 766 	if (vl != MAPI_UNDEFINED) {
 767 	    if (vl->size > 0)
 768 		fprintf (fptr, "EMAIL:%s\n", vl->data);
 769 	}
 770 
 771 	fprintProperty (tnef, fptr, PT_STRING8, PR_BUSINESS_HOME_PAGE, "URL:%s\n");
 772 	fprintUserProp (tnef, fptr, PT_STRING8, 0x80d8, "FBURL:%s\n");
 773 
 774         /* Birthday */
 775 	if ((vl = MAPIFindProperty (&(tnef->MapiProperties), PROP_TAG (PT_SYSTIME, PR_BIRTHDAY))) != MAPI_UNDEFINED) {
 776 	    fprintf (fptr, "BDAY:");
 777 	    MAPISysTimetoDTR ((guchar *) vl->data, &thedate);
 778 	    fprintf (fptr, "%i-%02i-%02i\n", thedate.wYear, thedate.wMonth, thedate.wDay);
 779 	}
 780 
 781         /* Anniversary */
 782 	if ((vl = MAPIFindProperty (&(tnef->MapiProperties), PROP_TAG (PT_SYSTIME, PR_WEDDING_ANNIVERSARY))) != MAPI_UNDEFINED) {
 783 	    fprintf (fptr, "X-EVOLUTION-ANNIVERSARY:");
 784 	    MAPISysTimetoDTR ((guchar *) vl->data, &thedate);
 785 	    fprintf (fptr, "%i-%02i-%02i\n", thedate.wYear, thedate.wMonth, thedate.wDay);
 786 	}
 787 	fprintf (fptr, "END:VCARD\n");
 788 	fclose (fptr);
 789     }
 790     g_free (ifilename);
 791 }
 792 
 793 guchar getRruleCount (guchar a, guchar b) {
 794     return ((a << 8) | b);
 795 }
 796 
 797 guchar getRruleMonthNum (guchar a, guchar b) {
 798     switch (a) {
 799         case 0x00:
 800             switch (b) {
 801                 case 0x00:
 802                     /* Jan */
 803                     return (1);
 804                 case 0xA3:
 805                     /* May */
 806                     return (5);
 807                 case 0xAE:
 808                     /* Nov */
 809                     return (11);
 810             }
 811             break;
 812         case 0x60:
 813             switch (b) {
 814                 case 0xAE:
 815                     /* Feb */
 816                     return (2);
 817                 case 0x51:
 818                     /* Jun */
 819                     return (6);
 820             }
 821             break;
 822         case 0xE0:
 823             switch (b) {
 824                 case 0x4B:
 825                     /* Mar */
 826                     return (3);
 827                 case 0x56:
 828                     /* Sep */
 829                     return (9);
 830             }
 831             break;
 832         case 0x40:
 833             switch (b) {
 834                 case 0xFA:
 835                     /* Apr */
 836                     return (4);
 837             }
 838             break;
 839         case 0x20:
 840             if (b == 0xFA) {
 841                 /* Jul */
 842                 return (7);
 843             }
 844             break;
 845         case 0x80:
 846             if (b == 0xA8) {
 847                 /* Aug */
 848                 return (8);
 849             }
 850             break;
 851         case 0xA0:
 852             if (b == 0xFF) {
 853                 /* Oct */
 854                 return (10);
 855             }
 856             break;
 857         case 0xC0:
 858             if (b == 0x56) {
 859                 return (12);
 860             }
 861     }
 862 
 863     /*  Error */
 864     return (0);
 865 }
 866 
 867 gchar * getRruleDayname (guchar a) {
 868     static gchar daystring[25];
 869 
 870     *daystring = 0;
 871 
 872     if (a & 0x01) {
 873         strcat (daystring, "SU,");
 874     }
 875     if (a & 0x02) {
 876         strcat (daystring, "MO,");
 877     }
 878     if (a & 0x04) {
 879         strcat (daystring, "TU,");
 880     }
 881     if (a & 0x08) {
 882         strcat (daystring, "WE,");
 883     }
 884     if (a & 0x10) {
 885         strcat (daystring, "TH,");
 886     }
 887     if (a & 0x20) {
 888         strcat (daystring, "FR,");
 889     }
 890     if (a & 0x40) {
 891         strcat (daystring, "SA,");
 892     }
 893 
 894     if (strlen (daystring)) {
 895         daystring[strlen (daystring) - 1] = 0;
 896     }
 897 
 898     return (daystring);
 899 }
 900 
 901 void printRrule (FILE *fptr, gchar *recur_data, gint size, TNEFStruct *tnef)
 902 {
 903     variableLength *filename;
 904 
 905     if (size < 0x1F) {
 906 	return;
 907     }
 908 
 909     fprintf (fptr, "RRULE:FREQ=");
 910 
 911     if (recur_data[0x04] == 0x0A) {
 912 	fprintf (fptr, "DAILY");
 913 
 914 	if (recur_data[0x16] == 0x23 || recur_data[0x16] == 0x22 ||
 915 		recur_data[0x16] == 0x21) {
 916 	    if ((filename = MAPIFindUserProp (&(tnef->MapiProperties),
 917 		    PROP_TAG (PT_I2, 0x0011))) != MAPI_UNDEFINED) {
 918 		fprintf (fptr, ";INTERVAL=%d", *(filename->data));
 919 	    }
 920 	    if (recur_data[0x16] == 0x22 || recur_data[0x16] == 0x21) {
 921 		fprintf (
 922 			fptr, ";COUNT=%d",
 923 			getRruleCount (recur_data[0x1B], recur_data[0x1A]));
 924 	    }
 925 	} else if (recur_data[0x16] == 0x3E) {
 926 	    fprintf (fptr, ";BYDAY=MO,TU,WE,TH,FR");
 927 	    if (recur_data[0x1A] == 0x22 || recur_data[0x1A] == 0x21) {
 928 		fprintf (
 929 			fptr, ";COUNT=%d",
 930 			getRruleCount (recur_data[0x1F], recur_data[0x1E]));
 931 	    }
 932 	}
 933     } else if (recur_data[0x04] == 0x0B) {
 934 	fprintf (
 935 		fptr, "WEEKLY;INTERVAL=%d;BYDAY=%s",
 936 		recur_data[0x0E], getRruleDayname (recur_data[0x16]));
 937 	if (recur_data[0x1A] == 0x22 || recur_data[0x1A] == 0x21) {
 938 	    fprintf (fptr, ";COUNT=%d",
 939 		getRruleCount (recur_data[0x1F], recur_data[0x1E]));
 940 	}
 941     } else if (recur_data[0x04] == 0x0C) {
 942 	fprintf (fptr, "MONTHLY");
 943 	if (recur_data[0x06] == 0x02) {
 944 	    fprintf (fptr, ";INTERVAL=%d;BYMONTHDAY=%d", recur_data[0x0E],
 945 		recur_data[0x16]);
 946 	    if (recur_data[0x1A] == 0x22 || recur_data[0x1A] == 0x21) {
 947 		fprintf (
 948 			fptr, ";COUNT=%d", getRruleCount (recur_data[0x1F],
 949 			recur_data[0x1E]));
 950 	    }
 951 	} else if (recur_data[0x06] == 0x03) {
 952 	    fprintf (fptr, ";BYDAY=%s;BYSETPOS=%d;INTERVAL=%d",
 953 		getRruleDayname (recur_data[0x16]),
 954 		recur_data[0x1A] == 0x05 ? -1 : recur_data[0x1A],
 955 		recur_data[0x0E]);
 956 	    if (recur_data[0x1E] == 0x22 || recur_data[0x1E] == 0x21) {
 957 		fprintf (
 958 			fptr, ";COUNT=%d", getRruleCount (recur_data[0x23],
 959 			recur_data[0x22]));
 960 	    }
 961 	}
 962     } else if (recur_data[0x04] == 0x0D) {
 963 	fprintf (
 964 		fptr, "YEARLY;BYMONTH=%d",
 965 		getRruleMonthNum (recur_data[0x0A], recur_data[0x0B]));
 966 	if (recur_data[0x06] == 0x02) {
 967 	    fprintf (fptr, ";BYMONTHDAY=%d", recur_data[0x16]);
 968 	} else if (recur_data[0x06] == 0x03) {
 969 	    fprintf (fptr, ";BYDAY=%s;BYSETPOS=%d",
 970 		getRruleDayname (recur_data[0x16]),
 971 		recur_data[0x1A] == 0x05 ? -1 : recur_data[0x1A]);
 972 	}
 973 	if (recur_data[0x1E] == 0x22 || recur_data[0x1E] == 0x21) {
 974 	    fprintf (fptr, ";COUNT=%d", getRruleCount (recur_data[0x23],
 975 		recur_data[0x22]));
 976 	}
 977     }
 978     fprintf (fptr, "\n");
 979 }
 980 
 981 void saveVCalendar (TNEFStruct *tnef, const gchar *tmpdir) {
 982     gchar *ifilename;
 983     variableLength *filename;
 984     gchar *charptr, *charptr2;
 985     FILE *fptr;
 986     gint index;
 987     DWORD *dword_ptr;
 988     dtr thedate;
 989 
 990     ifilename = g_build_filename (tmpdir, "calendar.vcf", NULL);
 991     printf ("%s\n", ifilename);
 992 
 993     if ((fptr = fopen (ifilename, "wb")) == NULL) {
 994             printf ("Error writing file to disk!");
 995     } else {
 996         fprintf (fptr, "BEGIN:VCALENDAR\n");
 997         if (tnef->messageClass[0] != 0) {
 998             charptr2 = tnef->messageClass;
 999             charptr = charptr2;
1000             while (*charptr != 0) {
1001                 if (*charptr == '.') {
1002                     charptr2 = charptr;
1003                 }
1004                 charptr++;
1005             }
1006             if (strcmp (charptr2, ".MtgCncl") == 0) {
1007                 fprintf (fptr, "METHOD:CANCEL\n");
1008             } else {
1009                 fprintf (fptr, "METHOD:REQUEST\n");
1010             }
1011         } else {
1012             fprintf (fptr, "METHOD:REQUEST\n");
1013         }
1014         fprintf (fptr, "VERSION:2.0\n");
1015         fprintf (fptr, "BEGIN:VEVENT\n");
1016 
1017 	/* UID
1018 	 * After alot of comparisons, I'm reasonably sure this is totally
1019 	 * wrong.  But it's not really necessary. */
1020 
1021 	/* I think it only exists to connect future modification entries to
1022 	 * this entry. so as long as it's incorrectly interpreted the same way
1023 	 * every time, it should be ok :) */
1024         filename = NULL;
1025         if ((filename = MAPIFindUserProp (&(tnef->MapiProperties),
1026                         PROP_TAG (PT_BINARY, 0x3))) == MAPI_UNDEFINED) {
1027             if ((filename = MAPIFindUserProp (&(tnef->MapiProperties),
1028                             PROP_TAG (PT_BINARY, 0x23))) == MAPI_UNDEFINED) {
1029                 filename = NULL;
1030             }
1031         }
1032         if (filename != NULL) {
1033             fprintf (fptr, "UID:");
1034             for (index = 0; index < filename->size; index++) {
1035                 fprintf (fptr,"%02X", (guchar) filename->data[index]);
1036             }
1037             fprintf (fptr,"\n");
1038         }
1039 
1040         /* Sequence */
1041         filename = NULL;
1042         if ((filename = MAPIFindUserProp (&(tnef->MapiProperties),
1043                         PROP_TAG (PT_LONG, 0x8201))) != MAPI_UNDEFINED) {
1044             dword_ptr = (DWORD *) filename->data;
1045             fprintf (fptr, "SEQUENCE:%i\n", (gint) *dword_ptr);
1046         }
1047         if ((filename = MAPIFindProperty (&(tnef->MapiProperties),
1048                         PROP_TAG (PT_BINARY, PR_SENDER_SEARCH_KEY)))
1049                 != MAPI_UNDEFINED) {
1050             charptr = filename->data;
1051             charptr2 = strstr (charptr, ":");
1052             if (charptr2 == NULL)
1053                 charptr2 = charptr;
1054             else
1055                 charptr2++;
1056             fprintf (fptr, "ORGANIZER;CN=\"%s\":MAILTO:%s\n",
1057                     charptr2, charptr2);
1058         }
1059 
1060         /* Required Attendees */
1061         if ((filename = MAPIFindUserProp (&(tnef->MapiProperties),
1062                         PROP_TAG (PT_STRING8, 0x823b))) != MAPI_UNDEFINED) {
1063 	    /* We have a list of required participants, so
1064 	       write them out. */
1065             if (filename->size > 1) {
1066                 charptr = filename->data - 1;
1067                 while (charptr != NULL) {
1068                     charptr++;
1069                     charptr2 = strstr (charptr, ";");
1070                     if (charptr2 != NULL) {
1071                         *charptr2 = 0;
1072                     }
1073                     while (*charptr == ' ')
1074                         charptr++;
1075                     fprintf (fptr, "ATTENDEE;PARTSTAT=NEEDS-ACTION;");
1076                     fprintf (fptr, "ROLE=REQ-PARTICIPANT;RSVP=TRUE;");
1077                     fprintf (fptr, "CN=\"%s\":MAILTO:%s\n",
1078                                 charptr, charptr);
1079                     charptr = charptr2;
1080                 }
1081             }
1082             /* Optional attendees */
1083             if ((filename = MAPIFindUserProp (&(tnef->MapiProperties),
1084                             PROP_TAG (PT_STRING8, 0x823c))) != MAPI_UNDEFINED) {
1085                     /* The list of optional participants */
1086                 if (filename->size > 1) {
1087                     charptr = filename->data - 1;
1088                     while (charptr != NULL) {
1089                         charptr++;
1090                         charptr2 = strstr (charptr, ";");
1091                         if (charptr2 != NULL) {
1092                             *charptr2 = 0;
1093                         }
1094                         while (*charptr == ' ')
1095                             charptr++;
1096                         fprintf (fptr, "ATTENDEE;PARTSTAT=NEEDS-ACTION;");
1097                         fprintf (fptr, "ROLE=OPT-PARTICIPANT;RSVP=TRUE;");
1098                         fprintf (fptr, "CN=\"%s\":MAILTO:%s\n",
1099                                 charptr, charptr);
1100                         charptr = charptr2;
1101                     }
1102                 }
1103             }
1104         } else if ((filename = MAPIFindUserProp (&(tnef->MapiProperties),
1105                         PROP_TAG (PT_STRING8, 0x8238))) != MAPI_UNDEFINED) {
1106             if (filename->size > 1) {
1107                 charptr = filename->data - 1;
1108                 while (charptr != NULL) {
1109                     charptr++;
1110                     charptr2 = strstr (charptr, ";");
1111                     if (charptr2 != NULL) {
1112                         *charptr2 = 0;
1113                     }
1114                     while (*charptr == ' ')
1115                         charptr++;
1116                     fprintf (fptr, "ATTENDEE;PARTSTAT=NEEDS-ACTION;");
1117                     fprintf (fptr, "ROLE=REQ-PARTICIPANT;RSVP=TRUE;");
1118                     fprintf (fptr, "CN=\"%s\":MAILTO:%s\n",
1119                                 charptr, charptr);
1120                     charptr = charptr2;
1121                 }
1122             }
1123 
1124         }
1125         /* Summary */
1126         filename = NULL;
1127         if ((filename = MAPIFindProperty (&(tnef->MapiProperties),
1128                         PROP_TAG (PT_STRING8, PR_CONVERSATION_TOPIC)))
1129                 != MAPI_UNDEFINED) {
1130             fprintf (fptr, "SUMMARY:");
1131             cstylefprint (fptr, filename);
1132             fprintf (fptr, "\n");
1133         }
1134 
1135         /* Description */
1136         if ((filename = MAPIFindProperty (&(tnef->MapiProperties),
1137                                 PROP_TAG (PT_BINARY, PR_RTF_COMPRESSED)))
1138                 != MAPI_UNDEFINED) {
1139             variableLength buf;
1140             if ((buf.data = (gchar *) DecompressRTF (filename, &buf.size)) != NULL) {
1141                 fprintf (fptr, "DESCRIPTION:");
1142                 printRtf (fptr, &buf);
1143                 free (buf.data);
1144             }
1145 
1146         }
1147 
1148         /* Location */
1149         filename = NULL;
1150         if ((filename = MAPIFindUserProp (&(tnef->MapiProperties),
1151                         PROP_TAG (PT_STRING8, 0x0002))) == MAPI_UNDEFINED) {
1152             if ((filename = MAPIFindUserProp (&(tnef->MapiProperties),
1153                             PROP_TAG (PT_STRING8, 0x8208))) == MAPI_UNDEFINED) {
1154                 filename = NULL;
1155             }
1156         }
1157         if (filename != NULL) {
1158             fprintf (fptr,"LOCATION: %s\n", filename->data);
1159         }
1160         /* Date Start */
1161         filename = NULL;
1162         if ((filename = MAPIFindUserProp (&(tnef->MapiProperties),
1163                         PROP_TAG (PT_SYSTIME, 0x820d))) == MAPI_UNDEFINED) {
1164             if ((filename = MAPIFindUserProp (&(tnef->MapiProperties),
1165                             PROP_TAG (PT_SYSTIME, 0x8516))) == MAPI_UNDEFINED) {
1166                 filename = NULL;
1167             }
1168         }
1169         if (filename != NULL) {
1170             fprintf (fptr, "DTSTART:");
1171             MAPISysTimetoDTR ((guchar *) filename->data, &thedate);
1172             fprintf (fptr,"%04i%02i%02iT%02i%02i%02iZ\n",
1173                     thedate.wYear, thedate.wMonth, thedate.wDay,
1174                     thedate.wHour, thedate.wMinute, thedate.wSecond);
1175         }
1176         /* Date End */
1177         filename = NULL;
1178         if ((filename = MAPIFindUserProp (&(tnef->MapiProperties),
1179                         PROP_TAG (PT_SYSTIME, 0x820e))) == MAPI_UNDEFINED) {
1180             if ((filename = MAPIFindUserProp (&(tnef->MapiProperties),
1181                             PROP_TAG (PT_SYSTIME, 0x8517))) == MAPI_UNDEFINED) {
1182                 filename = NULL;
1183             }
1184         }
1185         if (filename != NULL) {
1186             fprintf (fptr, "DTEND:");
1187             MAPISysTimetoDTR ((guchar *) filename->data, &thedate);
1188             fprintf (fptr,"%04i%02i%02iT%02i%02i%02iZ\n",
1189                     thedate.wYear, thedate.wMonth, thedate.wDay,
1190                     thedate.wHour, thedate.wMinute, thedate.wSecond);
1191         }
1192         /* Date Stamp */
1193         filename = NULL;
1194         if ((filename = MAPIFindUserProp (&(tnef->MapiProperties),
1195                         PROP_TAG (PT_SYSTIME, 0x8202))) != MAPI_UNDEFINED) {
1196             fprintf (fptr, "CREATED:");
1197             MAPISysTimetoDTR ((guchar *) filename->data, &thedate);
1198             fprintf (fptr,"%04i%02i%02iT%02i%02i%02iZ\n",
1199                     thedate.wYear, thedate.wMonth, thedate.wDay,
1200                     thedate.wHour, thedate.wMinute, thedate.wSecond);
1201         }
1202         /* Class */
1203         filename = NULL;
1204         if ((filename = MAPIFindUserProp (&(tnef->MapiProperties),
1205                         PROP_TAG (PT_BOOLEAN, 0x8506))) != MAPI_UNDEFINED) {
1206             dword_ptr = (DWORD *) filename->data;
1207             fprintf (fptr, "CLASS:");
1208             if (*dword_ptr == 1) {
1209                 fprintf (fptr,"PRIVATE\n");
1210             } else {
1211                 fprintf (fptr,"PUBLIC\n");
1212             }
1213         }
1214         /* Recurrence */
1215         filename = NULL;
1216         if ((filename = MAPIFindUserProp (&(tnef->MapiProperties),
1217                         PROP_TAG (PT_BINARY, 0x8216))) != MAPI_UNDEFINED) {
1218             printRrule (fptr, filename->data, filename->size, tnef);
1219         }
1220 
1221         /* Wrap it up */
1222         fprintf (fptr, "END:VEVENT\n");
1223         fprintf (fptr, "END:VCALENDAR\n");
1224         fclose (fptr);
1225     }
1226     g_free (ifilename);
1227 }
1228 
1229 void saveVTask (TNEFStruct *tnef, const gchar *tmpdir) {
1230     variableLength *vl;
1231     variableLength *filename;
1232     gint index;
1233     gchar *ifilename;
1234     gchar *absfilename, *file;
1235     gchar *charptr, *charptr2;
1236     dtr thedate;
1237     FILE *fptr;
1238     DWORD *dword_ptr;
1239 
1240     vl = MAPIFindProperty (&(tnef->MapiProperties), PROP_TAG (PT_STRING8, PR_CONVERSATION_TOPIC));
1241 
1242     if (vl == MAPI_UNDEFINED) {
1243         return;
1244     }
1245 
1246     index = strlen (vl->data);
1247     while (vl->data[index] == ' ')
1248             vl->data[index--] = 0;
1249 
1250     file = sanitize_filename (vl->data);
1251     if (!file)
1252 	return;
1253     absfilename = g_strconcat (file, ".vcf", NULL);
1254     ifilename = g_build_filename (tmpdir, absfilename, NULL);
1255     g_free (file);
1256     g_free (absfilename);
1257 
1258     printf ("%s\n", ifilename);
1259 
1260     if ((fptr = fopen (ifilename, "wb")) == NULL) {
1261             printf ("Error writing file to disk!");
1262     } else {
1263         fprintf (fptr, "BEGIN:VCALENDAR\n");
1264         fprintf (fptr, "VERSION:2.0\n");
1265         fprintf (fptr, "METHOD:PUBLISH\n");
1266         filename = NULL;
1267 
1268         fprintf (fptr, "BEGIN:VTODO\n");
1269         if (tnef->messageID[0] != 0) {
1270             fprintf (fptr,"UID:%s\n", tnef->messageID);
1271         }
1272         filename = MAPIFindUserProp (&(tnef->MapiProperties), \
1273                         PROP_TAG (PT_STRING8, 0x8122));
1274         if (filename != MAPI_UNDEFINED) {
1275             fprintf (fptr, "ORGANIZER:%s\n", filename->data);
1276         }
1277 
1278         if ((filename = MAPIFindProperty (&(tnef->MapiProperties), PROP_TAG (PT_STRING8, PR_DISPLAY_TO))) != MAPI_UNDEFINED) {
1279             filename = MAPIFindUserProp (&(tnef->MapiProperties), PROP_TAG (PT_STRING8, 0x811f));
1280         }
1281         if ((filename != MAPI_UNDEFINED) && (filename->size > 1)) {
1282             charptr = filename->data - 1;
1283             while (charptr != NULL) {
1284                 charptr++;
1285                 charptr2 = strstr (charptr, ";");
1286                 if (charptr2 != NULL) {
1287                     *charptr2 = 0;
1288                 }
1289                 while (*charptr == ' ')
1290                     charptr++;
1291                 fprintf (fptr, "ATTENDEE;CN=%s;ROLE=REQ-PARTICIPANT:%s\n", charptr, charptr);
1292                 charptr = charptr2;
1293             }
1294         }
1295 
1296         if (tnef->subject.size > 0) {
1297             fprintf (fptr,"SUMMARY:");
1298             cstylefprint (fptr,&(tnef->subject));
1299             fprintf (fptr,"\n");
1300         }
1301 
1302         if (tnef->body.size > 0) {
1303             fprintf (fptr,"DESCRIPTION:");
1304             cstylefprint (fptr,&(tnef->body));
1305             fprintf (fptr,"\n");
1306         }
1307 
1308         filename = MAPIFindProperty (&(tnef->MapiProperties), \
1309                     PROP_TAG (PT_SYSTIME, PR_CREATION_TIME));
1310         if (filename != MAPI_UNDEFINED) {
1311             fprintf (fptr, "DTSTAMP:");
1312             MAPISysTimetoDTR ((guchar *) filename->data, &thedate);
1313             fprintf (fptr,"%04i%02i%02iT%02i%02i%02iZ\n",
1314                     thedate.wYear, thedate.wMonth, thedate.wDay,
1315                     thedate.wHour, thedate.wMinute, thedate.wSecond);
1316         }
1317 
1318         filename = MAPIFindUserProp (&(tnef->MapiProperties), \
1319                     PROP_TAG (PT_SYSTIME, 0x8517));
1320         if (filename != MAPI_UNDEFINED) {
1321             fprintf (fptr, "DUE:");
1322             MAPISysTimetoDTR ((guchar *) filename->data, &thedate);
1323             fprintf (fptr,"%04i%02i%02iT%02i%02i%02iZ\n",
1324                     thedate.wYear, thedate.wMonth, thedate.wDay,
1325                     thedate.wHour, thedate.wMinute, thedate.wSecond);
1326         }
1327         filename = MAPIFindProperty (&(tnef->MapiProperties), \
1328                     PROP_TAG (PT_SYSTIME, PR_LAST_MODIFICATION_TIME));
1329         if (filename != MAPI_UNDEFINED) {
1330             fprintf (fptr, "LAST-MODIFIED:");
1331             MAPISysTimetoDTR ((guchar *) filename->data, &thedate);
1332             fprintf (fptr,"%04i%02i%02iT%02i%02i%02iZ\n",
1333                     thedate.wYear, thedate.wMonth, thedate.wDay,
1334                     thedate.wHour, thedate.wMinute, thedate.wSecond);
1335         }
1336         /* Class */
1337         filename = MAPIFindUserProp (&(tnef->MapiProperties), \
1338                         PROP_TAG (PT_BOOLEAN, 0x8506));
1339         if (filename != MAPI_UNDEFINED) {
1340             dword_ptr = (DWORD *) filename->data;
1341             fprintf (fptr, "CLASS:");
1342             if (*dword_ptr == 1) {
1343                 fprintf (fptr,"PRIVATE\n");
1344             } else {
1345                 fprintf (fptr,"PUBLIC\n");
1346             }
1347         }
1348         fprintf (fptr, "END:VTODO\n");
1349         fprintf (fptr, "END:VCALENDAR\n");
1350         fclose (fptr);
1351     }
1352     g_free (ifilename);
1353 }
1354 
1355 void fprintProperty (TNEFStruct *tnef, FILE *fptr, DWORD proptype, DWORD propid, const gchar text[]) {
1356     variableLength *vl;
1357     if ((vl = MAPIFindProperty (&(tnef->MapiProperties), PROP_TAG (proptype, propid))) != MAPI_UNDEFINED) {
1358         if (vl->size > 0) {
1359             if ((vl->size == 1) && (vl->data[0] == 0)) {
1360             } else {
1361                 fprintf (fptr, text, vl->data);
1362             }
1363 	}
1364     }
1365 }
1366 
1367 void fprintUserProp (TNEFStruct *tnef, FILE *fptr, DWORD proptype, DWORD propid, const gchar text[]) {
1368     variableLength *vl;
1369     if ((vl = MAPIFindUserProp (&(tnef->MapiProperties), PROP_TAG (proptype, propid))) != MAPI_UNDEFINED) {
1370         if (vl->size > 0) {
1371             if ((vl->size == 1) && (vl->data[0] == 0)) {
1372             } else {
1373                 fprintf (fptr, text, vl->data);
1374             }
1375 	}
1376     }
1377 }
1378 
1379 void quotedfprint (FILE *fptr, variableLength *vl) {
1380     gint index;
1381 
1382     for (index = 0; index < vl->size - 1; index++) {
1383         if (vl->data[index] == '\n') {
1384             fprintf (fptr, "=0A");
1385         } else if (vl->data[index] == '\r') {
1386         } else {
1387             fprintf (fptr, "%c", vl->data[index]);
1388         }
1389     }
1390 }
1391 
1392 void cstylefprint (FILE *fptr, variableLength *vl) {
1393     gint index;
1394 
1395     for (index = 0; index < vl->size - 1; index++) {
1396         if (vl->data[index] == '\n') {
1397             fprintf (fptr, "\\n");
1398         } else if (vl->data[index] == '\r') {
1399             /* Print nothing. */
1400         } else if (vl->data[index] == ';') {
1401             fprintf (fptr, "\\;");
1402         } else if (vl->data[index] == ',') {
1403             fprintf (fptr, "\\,");
1404         } else if (vl->data[index] == '\\') {
1405             fprintf (fptr, "\\");
1406         } else {
1407             fprintf (fptr, "%c", vl->data[index]);
1408         }
1409     }
1410 }
1411 
1412 void printRtf (FILE *fptr, variableLength *vl) {
1413     gint index;
1414     gchar *byte;
1415     gint brace_ct;
1416     gint key;
1417 
1418     key = 0;
1419     brace_ct = 0;
1420 
1421     for (index = 0, byte = vl->data; index < vl->size; index++, byte++) {
1422         if (*byte == '}') {
1423             brace_ct--;
1424             key = 0;
1425             continue;
1426         }
1427         if (*byte == '{') {
1428             brace_ct++;
1429             continue;
1430         }
1431         if (*byte == '\\') {
1432             key = 1;
1433         }
1434         if (isspace (*byte)) {
1435             key = 0;
1436         }
1437         if ((brace_ct == 1) && (key == 0)) {
1438             if (*byte == '\n') {
1439                 fprintf (fptr, "\\n");
1440             } else if (*byte == '\r') {
1441 		/* Print nothing. */
1442             } else if (*byte == ';') {
1443                 fprintf (fptr, "\\;");
1444             } else if (*byte == ',') {
1445                 fprintf (fptr, "\\,");
1446             } else if (*byte == '\\') {
1447                 fprintf (fptr, "\\");
1448             } else {
1449                 fprintf (fptr, "%c", *byte);
1450             }
1451         }
1452     }
1453     fprintf (fptr, "\n");
1454 }