aboutsummaryrefslogtreecommitdiffstats
path: root/modules/tnef-attachment
diff options
context:
space:
mode:
authorDan Vrátil <dvratil@redhat.com>2012-06-06 21:29:38 +0800
committerDan Vrátil <dvratil@redhat.com>2012-06-06 21:29:38 +0800
commit931191474643164e96b5778c790e42cca517e729 (patch)
treeaec00f3303dbcd95a8a3f18ee324ac80594ff9b5 /modules/tnef-attachment
parent5b8340563c271fb684a88c6e5bb6dd3bfb629058 (diff)
downloadgsoc2013-evolution-931191474643164e96b5778c790e42cca517e729.tar
gsoc2013-evolution-931191474643164e96b5778c790e42cca517e729.tar.gz
gsoc2013-evolution-931191474643164e96b5778c790e42cca517e729.tar.bz2
gsoc2013-evolution-931191474643164e96b5778c790e42cca517e729.tar.lz
gsoc2013-evolution-931191474643164e96b5778c790e42cca517e729.tar.xz
gsoc2013-evolution-931191474643164e96b5778c790e42cca517e729.tar.zst
gsoc2013-evolution-931191474643164e96b5778c790e42cca517e729.zip
Mail formatter rewrite - convert some plugins to modules
audio-inline, itip-formatter, prefer-plain, tnef-attachments and vcard-inline plugins were converted to modules so that they can fit into concept of the new formatter. Every module still installs .eplug file, because there is no suitable API at the moment to register plugins to the plugins dialog and to extend the Preferences dialog.
Diffstat (limited to 'modules/tnef-attachment')
-rw-r--r--modules/tnef-attachment/Makefile.am34
-rw-r--r--modules/tnef-attachment/e-mail-parser-tnef-attachment.c1446
-rw-r--r--modules/tnef-attachment/e-mail-parser-tnef-attachment.h30
-rw-r--r--modules/tnef-attachment/evolution-module-tnef-attachment.c51
4 files changed, 1561 insertions, 0 deletions
diff --git a/modules/tnef-attachment/Makefile.am b/modules/tnef-attachment/Makefile.am
new file mode 100644
index 0000000000..ff5b412275
--- /dev/null
+++ b/modules/tnef-attachment/Makefile.am
@@ -0,0 +1,34 @@
+if OS_WIN32
+NO_UNDEFINED_REQUIRED_LIBS = \
+ $(top_builddir)/e-util/libeutil.la \
+ $(top_builddir)/mail/libevolution-mail.la
+endif
+
+module_LTLIBRARIES = module-tnef-attachment.la
+
+module_tnef_attachment_la_CPPFLAGS = \
+ $(AM_CPPFLAGS) \
+ -I$(top_srcdir) \
+ -I$(top_srcdir)/widgets \
+ -DEVOLUTION_PRIVDATADIR=\""$(privdatadir)"\" \
+ -DG_LOG_DOMAIN=\"evolution-module-tnef-attachment\" \
+ $(EVOLUTION_DATA_SERVER_CFLAGS) \
+ $(GNOME_PLATFORM_CFLAGS) \
+ $(TNEF_CFLAGS)
+
+module_tnef_attachment_la_SOURCES = \
+ e-mail-parser-tnef-attachment.c \
+ e-mail-parser-tnef-attachment.h \
+ evolution-module-tnef-attachment.c
+
+module_tnef_attachment_la_LIBADD = \
+ $(top_builddir)/e-util/libeutil.la \
+ $(top_builddir)/em-format/libemformat.la \
+ $(EVOLUTION_DATA_SERVER_LIBS) \
+ $(GNOME_PLATFORM_LIBS) \
+ -lytnef
+
+module_tnef_attachment_la_LDFLAGS = \
+ -avoid-version -module $(NO_UNDEFINED)
+
+-include $(top_srcdir)/git.mk
diff --git a/modules/tnef-attachment/e-mail-parser-tnef-attachment.c b/modules/tnef-attachment/e-mail-parser-tnef-attachment.c
new file mode 100644
index 0000000000..854a17765a
--- /dev/null
+++ b/modules/tnef-attachment/e-mail-parser-tnef-attachment.c
@@ -0,0 +1,1446 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+#include <gtk/gtk.h>
+#include <glib/gi18n.h>
+#include <glib/gprintf.h>
+#include <stdio.h>
+
+#include "e-mail-parser-tnef-attachment.h"
+
+#include <em-format/e-mail-extension-registry.h>
+#include <em-format/e-mail-parser-extension.h>
+#include <em-format/e-mail-part.h>
+#include <em-format/e-mail-part-utils.h>
+
+#include <sys/types.h>
+#include <dirent.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <stdlib.h>
+#ifdef HAVE_YTNEF_H
+#include <ytnef.h>
+#elif defined HAVE_LIBYTNEF_YTNEF_H
+#include <libytnef/ytnef.h>
+#endif
+
+#include <mail/em-utils.h>
+#include <e-util/e-mktemp.h>
+
+#include <libebackend/libebackend.h>
+
+#define d(x)
+
+typedef struct _EMailParserTnefAttachment {
+ EExtension parent;
+
+ GSettings *settings;
+ gint mode;
+ gboolean show_suppressed;
+} EMailParserTnefAttachment;
+
+typedef struct _EMailParserTnefAttachmentClass {
+ EExtensionClass parent_class;
+} EMailParserTnefAttachmentClass;
+
+GType e_mail_parser_tnef_attachment_get_type (void);
+static void e_mail_parser_mail_extension_interface_init (EMailExtensionInterface *iface);
+static void e_mail_parser_parser_extension_interface_init (EMailParserExtensionInterface *iface);
+
+G_DEFINE_DYNAMIC_TYPE_EXTENDED (
+ EMailParserTnefAttachment,
+ e_mail_parser_tnef_attachment,
+ E_TYPE_EXTENSION,
+ 0,
+ G_IMPLEMENT_INTERFACE_DYNAMIC (
+ E_TYPE_MAIL_EXTENSION,
+ e_mail_parser_mail_extension_interface_init)
+ G_IMPLEMENT_INTERFACE_DYNAMIC (
+ E_TYPE_MAIL_PARSER_EXTENSION,
+ e_mail_parser_parser_extension_interface_init));
+
+static const gchar* parser_mime_types[] = { "application/vnd.ms-tnef",
+ "application/ms-tnefl",
+ NULL };
+
+gint verbose = 0;
+gint saveRTF = 0;
+gint saveintermediate = 0;
+gboolean loaded = FALSE;
+void processTnef (TNEFStruct *tnef, const gchar *tmpdir);
+void saveVCalendar (TNEFStruct *tnef, const gchar *tmpdir);
+void saveVCard (TNEFStruct *tnef, const gchar *tmpdir);
+void saveVTask (TNEFStruct *tnef, const gchar *tmpdir);
+
+/* Other Prototypes */
+void fprintProperty (TNEFStruct *tnef, FILE *fptr, DWORD proptype, DWORD propid, const gchar text[]);
+void fprintUserProp (TNEFStruct *tnef, FILE *fptr, DWORD proptype, DWORD propid, const gchar text[]);
+void quotedfprint (FILE *fptr, variableLength *vl);
+void cstylefprint (FILE *fptr, variableLength *vl);
+void printRtf (FILE *fptr, variableLength *vl);
+void printRrule (FILE *fptr, gchar *recur_data, gint size, TNEFStruct *tnef);
+guchar getRruleCount (guchar a, guchar b);
+guchar getRruleMonthNum (guchar a, guchar b);
+gchar * getRruleDayname (guchar a);
+
+static gchar *
+sanitize_filename (const gchar *filename)
+{
+ gchar * sanitized_name;
+ sanitized_name = g_path_get_basename (filename);
+ if (sanitized_name == NULL || !g_strcmp0 (sanitized_name, ".")) {
+ g_free (sanitized_name);
+ return NULL;
+ } else {
+ return g_strdelimit (sanitized_name, " ", '_');
+ }
+}
+
+static GSList *
+empe_tnef_attachment_parse (EMailParserExtension *extension,
+ EMailParser *parser,
+ CamelMimePart *part,
+ GString *part_id,
+ GCancellable *cancellable)
+{
+ gchar *tmpdir, *name;
+ CamelStream *out;
+ struct dirent *d;
+ DIR *dir;
+ CamelMultipart *mp;
+ CamelMimePart *mainpart;
+ CamelDataWrapper *content;
+ gint len;
+ TNEFStruct tnef;
+ GSList *parts;
+
+ tmpdir = e_mkdtemp("tnef-attachment-XXXXXX");
+ if (tmpdir == NULL)
+ return NULL;
+
+ name = g_build_filename(tmpdir, ".evo-attachment.tnef", NULL);
+
+ out = camel_stream_fs_new_with_name (name, O_RDWR | O_CREAT, 0666, NULL);
+ if (out == NULL) {
+ g_free (name);
+ return NULL;
+ }
+ content = camel_medium_get_content ((CamelMedium *) part);
+ if (content == NULL) {
+ g_free (name);
+ g_object_unref (out);
+ return NULL;
+ }
+ if (camel_data_wrapper_decode_to_stream_sync (content, out, NULL, NULL) == -1
+ || camel_stream_close (out, NULL, NULL) == -1) {
+ g_object_unref (out);
+ g_free (name);
+ return NULL;
+ }
+ g_object_unref (out);
+
+ /* Extracting the winmail.dat */
+ TNEFInitialize (&tnef);
+ tnef.Debug = verbose;
+ if (TNEFParseFile (name, &tnef) == -1) {
+ printf("ERROR processing file\n");
+ }
+ processTnef (&tnef, tmpdir);
+
+ TNEFFree (&tnef);
+ /* Extraction done */
+
+ dir = opendir (tmpdir);
+ if (dir == NULL) {
+ g_object_unref (out);
+ g_free (name);
+ return NULL;
+ }
+
+ mainpart = camel_mime_part_new ();
+
+ mp = camel_multipart_new ();
+ camel_data_wrapper_set_mime_type((CamelDataWrapper *)mp, "multipart/mixed");
+ camel_multipart_set_boundary (mp, NULL);
+
+ camel_medium_set_content ((CamelMedium *) mainpart, (CamelDataWrapper *) mp);
+
+ while ((d = readdir (dir))) {
+ CamelMimePart *part;
+ CamelDataWrapper *content;
+ CamelStream *stream;
+ gchar *path;
+ const gchar *type;
+
+ if (!strcmp(d->d_name, ".")
+ || !strcmp(d->d_name, "..")
+ || !strcmp(d->d_name, ".evo-attachment.tnef"))
+ continue;
+
+ path = g_build_filename (tmpdir, d->d_name, NULL);
+
+ stream = camel_stream_fs_new_with_name (path, O_RDONLY, 0, NULL);
+ content = camel_data_wrapper_new ();
+ camel_data_wrapper_construct_from_stream_sync (
+ content, stream, NULL, NULL);
+ g_object_unref (stream);
+
+ part = camel_mime_part_new ();
+ camel_mime_part_set_encoding (part, CAMEL_TRANSFER_ENCODING_BINARY);
+
+ camel_medium_set_content ((CamelMedium *) part, content);
+ g_object_unref (content);
+
+ type = e_mail_part_snoop_type (part);
+ if (type)
+ camel_data_wrapper_set_mime_type ((CamelDataWrapper *) part, type);
+
+ camel_mime_part_set_filename (part, d->d_name);
+
+ g_free (path);
+
+ camel_multipart_add_part (mp, part);
+ g_object_unref (part);
+ }
+
+ closedir (dir);
+
+ len = part_id->len;
+ g_string_append_printf(part_id, ".tnef");
+
+ parts = NULL;
+ if (camel_multipart_get_number (mp) > 0) {
+
+ CamelMimePart *part = camel_mime_part_new ();
+
+ camel_medium_set_content ((CamelMedium *) part,
+ CAMEL_DATA_WRAPPER (mp));
+
+ parts = e_mail_parser_parse_part_as (parser, part,
+ part_id, "multipart/mixed", cancellable);
+
+ g_object_unref (part);
+ }
+
+ g_string_truncate (part_id, len);
+
+ if (parts) {
+ parts = e_mail_parser_wrap_as_attachment (parser,
+ part, parts, part_id, cancellable);
+ }
+
+ g_object_unref (mp);
+ g_object_unref (mainpart);
+
+ g_free (name);
+ g_free (tmpdir);
+
+ return parts;
+}
+
+static const gchar **
+empe_mime_types (EMailExtension *extension)
+{
+ return parser_mime_types;
+}
+
+void
+e_mail_parser_tnef_attachment_type_register (GTypeModule *type_module)
+{
+ e_mail_parser_tnef_attachment_register_type (type_module);
+}
+
+static void
+e_mail_parser_mail_extension_interface_init (EMailExtensionInterface *iface)
+{
+ iface->mime_types = empe_mime_types;
+}
+
+static void
+e_mail_parser_parser_extension_interface_init (EMailParserExtensionInterface *iface)
+{
+ iface->parse = empe_tnef_attachment_parse;
+}
+
+static void
+e_mail_parser_tnef_attachment_constructed (GObject *object)
+{
+ EExtensible *extensible;
+ EMailExtensionRegistry *reg;
+
+ extensible = e_extension_get_extensible (E_EXTENSION (object));
+ reg = E_MAIL_EXTENSION_REGISTRY (extensible);
+
+ e_mail_extension_registry_add_extension (reg, E_MAIL_EXTENSION (object));
+}
+
+static void
+e_mail_parser_tnef_attachment_class_init (EMailParserTnefAttachmentClass *klass)
+{
+ GObjectClass *object_class;
+ EExtensionClass *extension_class;
+
+ e_mail_parser_tnef_attachment_parent_class = g_type_class_peek_parent (klass);
+
+ object_class = G_OBJECT_CLASS (klass);
+ object_class->constructed = e_mail_parser_tnef_attachment_constructed;
+
+ extension_class = E_EXTENSION_CLASS (klass);
+ extension_class->extensible_type = E_TYPE_MAIL_PARSER_EXTENSION_REGISTRY;
+}
+
+void
+e_mail_parser_tnef_attachment_class_finalize (EMailParserTnefAttachmentClass *klass)
+{
+}
+
+static void
+e_mail_parser_tnef_attachment_init (EMailParserTnefAttachment *parser)
+{
+}
+
+void
+processTnef (TNEFStruct *tnef,
+ const gchar *tmpdir)
+{
+ variableLength *filename;
+ variableLength *filedata;
+ Attachment *p;
+ gint RealAttachment;
+ gint object;
+ gchar *ifilename = NULL;
+ gchar *absfilename, *file;
+ gint count;
+ gint foundCal = 0;
+
+ FILE *fptr;
+
+ /* First see if this requires special processing. */
+ /* ie: it's a Contact Card, Task, or Meeting request (vCal/vCard) */
+ if (tnef->messageClass[0] != 0) {
+ if (strcmp(tnef->messageClass, "IPM.Contact") == 0) {
+ saveVCard (tnef, tmpdir);
+ }
+ if (strcmp(tnef->messageClass, "IPM.Task") == 0) {
+ saveVTask (tnef, tmpdir);
+ }
+ if (strcmp(tnef->messageClass, "IPM.Appointment") == 0) {
+ saveVCalendar (tnef, tmpdir);
+ foundCal = 1;
+ }
+ }
+
+ if ((filename = MAPIFindUserProp (&(tnef->MapiProperties),
+ PROP_TAG (PT_STRING8,0x24))) != MAPI_UNDEFINED) {
+ if (strcmp(filename->data, "IPM.Appointment") == 0) {
+ /* If it's "indicated" twice, we don't want to save 2 calendar entries. */
+ if (foundCal == 0) {
+ saveVCalendar (tnef, tmpdir);
+ }
+ }
+ }
+
+ if (strcmp(tnef->messageClass, "IPM.Microsoft Mail.Note") == 0) {
+ if ((saveRTF == 1) && (tnef->subject.size > 0)) {
+ /* Description */
+ if ((filename = MAPIFindProperty (&(tnef->MapiProperties),
+ PROP_TAG (PT_BINARY, PR_RTF_COMPRESSED)))
+ != MAPI_UNDEFINED) {
+ variableLength buf;
+ if ((buf.data = (gchar *) DecompressRTF (filename, &buf.size)) != NULL) {
+ file = sanitize_filename (tnef->subject.data);
+ if (!file)
+ return;
+ absfilename = g_strconcat (file, ".rtf", NULL);
+ ifilename = g_build_filename (tmpdir, file, NULL);
+ g_free (absfilename);
+ g_free (file);
+
+ if ((fptr = fopen(ifilename, "wb"))==NULL) {
+ printf("ERROR: Error writing file to disk!");
+ } else {
+ fwrite (buf.data,
+ sizeof (BYTE),
+ buf.size,
+ fptr);
+ fclose (fptr);
+ }
+ free (buf.data);
+ }
+ }
+ }
+ }
+
+ /* Now process each attachment */
+ p = tnef->starting_attach.next;
+ count = 0;
+ while (p != NULL) {
+ count++;
+ /* Make sure it has a size. */
+ if (p->FileData.size > 0) {
+ object = 1;
+
+ /* See if the contents are stored as "attached data" */
+ /* Inside the MAPI blocks. */
+ if ((filedata = MAPIFindProperty (&(p->MAPI),
+ PROP_TAG (PT_OBJECT, PR_ATTACH_DATA_OBJ)))
+ == MAPI_UNDEFINED) {
+ if ((filedata = MAPIFindProperty (&(p->MAPI),
+ PROP_TAG (PT_BINARY, PR_ATTACH_DATA_OBJ)))
+ == MAPI_UNDEFINED) {
+ /* Nope, standard TNEF stuff. */
+ filedata = &(p->FileData);
+ object = 0;
+ }
+ }
+ /* See if this is an embedded TNEF stream. */
+ RealAttachment = 1;
+ if (object == 1) {
+ /* This is an "embedded object", so skip the */
+ /* 16-byte identifier first. */
+ TNEFStruct emb_tnef;
+ DWORD signature;
+ memcpy (&signature, filedata->data + 16, sizeof (DWORD));
+ if (TNEFCheckForSignature (signature) == 0) {
+ /* Has a TNEF signature, so process it. */
+ TNEFInitialize (&emb_tnef);
+ emb_tnef.Debug = tnef->Debug;
+ if (TNEFParseMemory ((guchar *) filedata->data + 16,
+ filedata->size - 16, &emb_tnef) != -1) {
+ processTnef (&emb_tnef, tmpdir);
+ RealAttachment = 0;
+ }
+ TNEFFree (&emb_tnef);
+ }
+ } else {
+ TNEFStruct emb_tnef;
+ DWORD signature;
+ memcpy (&signature, filedata->data, sizeof (DWORD));
+ if (TNEFCheckForSignature (signature) == 0) {
+ /* Has a TNEF signature, so process it. */
+ TNEFInitialize (&emb_tnef);
+ emb_tnef.Debug = tnef->Debug;
+ if (TNEFParseMemory ((guchar *) filedata->data,
+ filedata->size, &emb_tnef) != -1) {
+ processTnef (&emb_tnef, tmpdir);
+ RealAttachment = 0;
+ }
+ TNEFFree (&emb_tnef);
+ }
+ }
+ if ((RealAttachment == 1) || (saveintermediate == 1)) {
+ gchar tmpname[20];
+ /* Ok, it's not an embedded stream, so now we */
+ /* process it. */
+ if ((filename = MAPIFindProperty (&(p->MAPI),
+ PROP_TAG (PT_STRING8, PR_ATTACH_LONG_FILENAME)))
+ == MAPI_UNDEFINED) {
+ if ((filename = MAPIFindProperty (&(p->MAPI),
+ PROP_TAG (PT_STRING8, PR_DISPLAY_NAME)))
+ == MAPI_UNDEFINED) {
+ filename = &(p->Title);
+ }
+ }
+ if (filename->size == 1) {
+ filename->size = 20;
+ g_sprintf(tmpname, "file_%03i.dat", count);
+ filename->data = tmpname;
+ }
+ absfilename = sanitize_filename (filename->data);
+ if (!absfilename)
+ return;
+ ifilename = g_build_filename (tmpdir, absfilename, NULL);
+ g_free (absfilename);
+
+ if ((fptr = fopen(ifilename, "wb"))==NULL) {
+ printf("ERROR: Error writing file to disk!");
+ } else {
+ if (object == 1) {
+ fwrite (filedata->data + 16,
+ sizeof (BYTE),
+ filedata->size - 16,
+ fptr);
+ } else {
+ fwrite (filedata->data,
+ sizeof (BYTE),
+ filedata->size,
+ fptr);
+ }
+ fclose (fptr);
+ }
+ }
+ } /* if size>0 */
+ p = p->next;
+ } /* while p!= null */
+ g_free (ifilename);
+}
+
+void
+saveVCard (TNEFStruct *tnef,
+ const gchar *tmpdir)
+{
+ gchar *ifilename;
+ gchar *absfilename, *file = NULL;
+ FILE *fptr;
+ variableLength *vl;
+ variableLength *pobox, *street, *city, *state, *zip, *country;
+ dtr thedate;
+ gint boolean;
+
+ if ((vl = MAPIFindProperty (&(tnef->MapiProperties), PROP_TAG (PT_STRING8, PR_DISPLAY_NAME))) == MAPI_UNDEFINED) {
+ if ((vl = MAPIFindProperty (&(tnef->MapiProperties), PROP_TAG (PT_STRING8, PR_COMPANY_NAME))) == MAPI_UNDEFINED) {
+ if (tnef->subject.size > 0) {
+ file = sanitize_filename (tnef->subject.data);
+ if (!file)
+ return;
+ absfilename = g_strconcat (file, ".vcard", NULL);
+ } else
+ absfilename = g_strdup ("unknown.vcard");
+ } else {
+ file = sanitize_filename (vl->data);
+ if (!file)
+ return;
+ absfilename = g_strconcat (file, ".vcard", NULL);
+ }
+ } else {
+ file = sanitize_filename (vl->data);
+ if (!file)
+ return;
+ absfilename = g_strconcat (file, ".vcard", NULL);
+ }
+
+ ifilename = g_build_filename (tmpdir, absfilename, NULL);
+ g_free (file);
+ g_free (absfilename);
+
+ if ((fptr = fopen(ifilename, "wb"))==NULL) {
+ printf("Error writing file to disk!");
+ } else {
+ fprintf(fptr, "BEGIN:VCARD\n");
+ fprintf(fptr, "VERSION:2.1\n");
+ if (vl != MAPI_UNDEFINED) {
+ fprintf(fptr, "FN:%s\n", vl->data);
+ }
+ fprintProperty(tnef, fptr, PT_STRING8, PR_NICKNAME, "NICKNAME:%s\n");
+ fprintUserProp(tnef, fptr, PT_STRING8, 0x8554, "MAILER:Microsoft Outlook %s\n");
+ fprintProperty(tnef, fptr, PT_STRING8, PR_SPOUSE_NAME, "X-EVOLUTION-SPOUSE:%s\n");
+ fprintProperty(tnef, fptr, PT_STRING8, PR_MANAGER_NAME, "X-EVOLUTION-MANAGER:%s\n");
+ fprintProperty(tnef, fptr, PT_STRING8, PR_ASSISTANT, "X-EVOLUTION-ASSISTANT:%s\n");
+
+ /* Organizational */
+ if ((vl = MAPIFindProperty (&(tnef->MapiProperties), PROP_TAG (PT_STRING8, PR_COMPANY_NAME))) != MAPI_UNDEFINED) {
+ if (vl->size > 0) {
+ if ((vl->size == 1) && (vl->data[0] == 0)) {
+ } else {
+ fprintf(fptr,"ORG:%s", vl->data);
+ if ((vl = MAPIFindProperty (&(tnef->MapiProperties), PROP_TAG (PT_STRING8, PR_DEPARTMENT_NAME))) != MAPI_UNDEFINED) {
+ fprintf(fptr,";%s", vl->data);
+ }
+ fprintf(fptr, "\n");
+ }
+ }
+ }
+
+ fprintProperty(tnef, fptr, PT_STRING8, PR_OFFICE_LOCATION, "X-EVOLUTION-OFFICE:%s\n");
+ fprintProperty(tnef, fptr, PT_STRING8, PR_TITLE, "TITLE:%s\n");
+ fprintProperty(tnef, fptr, PT_STRING8, PR_PROFESSION, "ROLE:%s\n");
+ fprintProperty(tnef, fptr, PT_STRING8, PR_BODY, "NOTE:%s\n");
+ if (tnef->body.size > 0) {
+ fprintf(fptr, "NOTE;QUOTED-PRINTABLE:");
+ quotedfprint (fptr, &(tnef->body));
+ fprintf(fptr,"\n");
+ }
+
+ /* Business Address */
+ boolean = 0;
+ if ((pobox = MAPIFindProperty (&(tnef->MapiProperties), PROP_TAG (PT_STRING8, PR_POST_OFFICE_BOX))) != MAPI_UNDEFINED) {
+ boolean = 1;
+ }
+ if ((street = MAPIFindProperty (&(tnef->MapiProperties), PROP_TAG (PT_STRING8, PR_STREET_ADDRESS))) != MAPI_UNDEFINED) {
+ boolean = 1;
+ }
+ if ((city = MAPIFindProperty (&(tnef->MapiProperties), PROP_TAG (PT_STRING8, PR_LOCALITY))) != MAPI_UNDEFINED) {
+ boolean = 1;
+ }
+ if ((state = MAPIFindProperty (&(tnef->MapiProperties), PROP_TAG (PT_STRING8, PR_STATE_OR_PROVINCE))) != MAPI_UNDEFINED) {
+ boolean = 1;
+ }
+ if ((zip = MAPIFindProperty (&(tnef->MapiProperties), PROP_TAG (PT_STRING8, PR_POSTAL_CODE))) != MAPI_UNDEFINED) {
+ boolean = 1;
+ }
+ if ((country = MAPIFindProperty (&(tnef->MapiProperties), PROP_TAG (PT_STRING8, PR_COUNTRY))) != MAPI_UNDEFINED) {
+ boolean = 1;
+ }
+ if (boolean == 1) {
+ fprintf(fptr, "ADR;QUOTED-PRINTABLE;WORK:");
+ if (pobox != MAPI_UNDEFINED) {
+ quotedfprint (fptr, pobox);
+ }
+ fprintf(fptr, ";;");
+ if (street != MAPI_UNDEFINED) {
+ quotedfprint (fptr, street);
+ }
+ fprintf(fptr, ";");
+ if (city != MAPI_UNDEFINED) {
+ quotedfprint (fptr, city);
+ }
+ fprintf(fptr, ";");
+ if (state != MAPI_UNDEFINED) {
+ quotedfprint (fptr, state);
+ }
+ fprintf(fptr, ";");
+ if (zip != MAPI_UNDEFINED) {
+ quotedfprint (fptr, zip);
+ }
+ fprintf(fptr, ";");
+ if (country != MAPI_UNDEFINED) {
+ quotedfprint (fptr, country);
+ }
+ fprintf(fptr,"\n");
+ if ((vl = MAPIFindUserProp (&(tnef->MapiProperties), PROP_TAG (PT_STRING8, 0x801b))) != MAPI_UNDEFINED) {
+ fprintf(fptr, "LABEL;QUOTED-PRINTABLE;WORK:");
+ quotedfprint (fptr, vl);
+ fprintf(fptr,"\n");
+ }
+ }
+
+ /* Home Address */
+ boolean = 0;
+ if ((pobox = MAPIFindProperty (&(tnef->MapiProperties), PROP_TAG (PT_STRING8, PR_HOME_ADDRESS_POST_OFFICE_BOX))) != MAPI_UNDEFINED) {
+ boolean = 1;
+ }
+ if ((street = MAPIFindProperty (&(tnef->MapiProperties), PROP_TAG (PT_STRING8, PR_HOME_ADDRESS_STREET))) != MAPI_UNDEFINED) {
+ boolean = 1;
+ }
+ if ((city = MAPIFindProperty (&(tnef->MapiProperties), PROP_TAG (PT_STRING8, PR_HOME_ADDRESS_CITY))) != MAPI_UNDEFINED) {
+ boolean = 1;
+ }
+ if ((state = MAPIFindProperty (&(tnef->MapiProperties), PROP_TAG (PT_STRING8, PR_HOME_ADDRESS_STATE_OR_PROVINCE))) != MAPI_UNDEFINED) {
+ boolean = 1;
+ }
+ if ((zip = MAPIFindProperty (&(tnef->MapiProperties), PROP_TAG (PT_STRING8, PR_HOME_ADDRESS_POSTAL_CODE))) != MAPI_UNDEFINED) {
+ boolean = 1;
+ }
+ if ((country = MAPIFindProperty (&(tnef->MapiProperties), PROP_TAG (PT_STRING8, PR_HOME_ADDRESS_COUNTRY))) != MAPI_UNDEFINED) {
+ boolean = 1;
+ }
+ if (boolean == 1) {
+ fprintf(fptr, "ADR;QUOTED-PRINTABLE;HOME:");
+ if (pobox != MAPI_UNDEFINED) {
+ quotedfprint (fptr, pobox);
+ }
+ fprintf(fptr, ";;");
+ if (street != MAPI_UNDEFINED) {
+ quotedfprint (fptr, street);
+ }
+ fprintf(fptr, ";");
+ if (city != MAPI_UNDEFINED) {
+ quotedfprint (fptr, city);
+ }
+ fprintf(fptr, ";");
+ if (state != MAPI_UNDEFINED) {
+ quotedfprint (fptr, state);
+ }
+ fprintf(fptr, ";");
+ if (zip != MAPI_UNDEFINED) {
+ quotedfprint (fptr, zip);
+ }
+ fprintf(fptr, ";");
+ if (country != MAPI_UNDEFINED) {
+ quotedfprint (fptr, country);
+ }
+ fprintf(fptr,"\n");
+ if ((vl = MAPIFindUserProp (&(tnef->MapiProperties), PROP_TAG (PT_STRING8, 0x801a))) != MAPI_UNDEFINED) {
+ fprintf(fptr, "LABEL;QUOTED-PRINTABLE;WORK:");
+ quotedfprint (fptr, vl);
+ fprintf(fptr,"\n");
+ }
+ }
+
+ /* Other Address */
+ boolean = 0;
+ if ((pobox = MAPIFindProperty (&(tnef->MapiProperties), PROP_TAG (PT_STRING8, PR_OTHER_ADDRESS_POST_OFFICE_BOX))) != MAPI_UNDEFINED) {
+ boolean = 1;
+ }
+ if ((street = MAPIFindProperty (&(tnef->MapiProperties), PROP_TAG (PT_STRING8, PR_OTHER_ADDRESS_STREET))) != MAPI_UNDEFINED) {
+ boolean = 1;
+ }
+ if ((city = MAPIFindProperty (&(tnef->MapiProperties), PROP_TAG (PT_STRING8, PR_OTHER_ADDRESS_CITY))) != MAPI_UNDEFINED) {
+ boolean = 1;
+ }
+ if ((state = MAPIFindProperty (&(tnef->MapiProperties), PROP_TAG (PT_STRING8, PR_OTHER_ADDRESS_STATE_OR_PROVINCE))) != MAPI_UNDEFINED) {
+ boolean = 1;
+ }
+ if ((zip = MAPIFindProperty (&(tnef->MapiProperties), PROP_TAG (PT_STRING8, PR_OTHER_ADDRESS_POSTAL_CODE))) != MAPI_UNDEFINED) {
+ boolean = 1;
+ }
+ if ((country = MAPIFindProperty (&(tnef->MapiProperties), PROP_TAG (PT_STRING8, PR_OTHER_ADDRESS_COUNTRY))) != MAPI_UNDEFINED) {
+ boolean = 1;
+ }
+ if (boolean == 1) {
+ fprintf(fptr, "ADR;QUOTED-PRINTABLE;OTHER:");
+ if (pobox != MAPI_UNDEFINED) {
+ quotedfprint (fptr, pobox);
+ }
+ fprintf(fptr, ";;");
+ if (street != MAPI_UNDEFINED) {
+ quotedfprint (fptr, street);
+ }
+ fprintf(fptr, ";");
+ if (city != MAPI_UNDEFINED) {
+ quotedfprint (fptr, city);
+ }
+ fprintf(fptr, ";");
+ if (state != MAPI_UNDEFINED) {
+ quotedfprint (fptr, state);
+ }
+ fprintf(fptr, ";");
+ if (zip != MAPI_UNDEFINED) {
+ quotedfprint (fptr, zip);
+ }
+ fprintf(fptr, ";");
+ if (country != MAPI_UNDEFINED) {
+ quotedfprint (fptr, country);
+ }
+ fprintf(fptr,"\n");
+ }
+
+ fprintProperty(tnef, fptr, PT_STRING8, PR_CALLBACK_TELEPHONE_NUMBER, "TEL;X-EVOLUTION-CALLBACK:%s\n");
+ fprintProperty(tnef, fptr, PT_STRING8, PR_PRIMARY_TELEPHONE_NUMBER, "TEL;PREF:%s\n");
+ fprintProperty(tnef, fptr, PT_STRING8, PR_MOBILE_TELEPHONE_NUMBER, "TEL;CELL:%s\n");
+ fprintProperty(tnef, fptr, PT_STRING8, PR_RADIO_TELEPHONE_NUMBER, "TEL;X-EVOLUTION-RADIO:%s\n");
+ fprintProperty(tnef, fptr, PT_STRING8, PR_CAR_TELEPHONE_NUMBER, "TEL;CAR:%s\n");
+ fprintProperty(tnef, fptr, PT_STRING8, PR_OTHER_TELEPHONE_NUMBER, "TEL;VOICE:%s\n");
+ fprintProperty(tnef, fptr, PT_STRING8, PR_PAGER_TELEPHONE_NUMBER, "TEL;PAGER:%s\n");
+ fprintProperty(tnef, fptr, PT_STRING8, PR_TELEX_NUMBER, "TEL;X-EVOLUTION-TELEX:%s\n");
+ fprintProperty(tnef, fptr, PT_STRING8, PR_ISDN_NUMBER, "TEL;ISDN:%s\n");
+ fprintProperty(tnef, fptr, PT_STRING8, PR_HOME2_TELEPHONE_NUMBER, "TEL;HOME:%s\n");
+ fprintProperty(tnef, fptr, PT_STRING8, PR_TTYTDD_PHONE_NUMBER, "TEL;X-EVOLUTION-TTYTDD:%s\n");
+ fprintProperty(tnef, fptr, PT_STRING8, PR_HOME_TELEPHONE_NUMBER, "TEL;HOME;VOICE:%s\n");
+ fprintProperty(tnef, fptr, PT_STRING8, PR_ASSISTANT_TELEPHONE_NUMBER, "TEL;X-EVOLUTION-ASSISTANT:%s\n");
+ fprintProperty(tnef, fptr, PT_STRING8, PR_COMPANY_MAIN_PHONE_NUMBER, "TEL;WORK:%s\n");
+ fprintProperty(tnef, fptr, PT_STRING8, PR_BUSINESS_TELEPHONE_NUMBER, "TEL;WORK:%s\n");
+ fprintProperty(tnef, fptr, PT_STRING8, PR_BUSINESS2_TELEPHONE_NUMBER, "TEL;WORK;VOICE:%s\n");
+ fprintProperty(tnef, fptr, PT_STRING8, PR_PRIMARY_FAX_NUMBER, "TEL;PREF;FAX:%s\n");
+ fprintProperty(tnef, fptr, PT_STRING8, PR_BUSINESS_FAX_NUMBER, "TEL;WORK;FAX:%s\n");
+ fprintProperty(tnef, fptr, PT_STRING8, PR_HOME_FAX_NUMBER, "TEL;HOME;FAX:%s\n");
+
+ /* Email addresses */
+ if ((vl = MAPIFindUserProp (&(tnef->MapiProperties), PROP_TAG (PT_STRING8, 0x8083))) == MAPI_UNDEFINED) {
+ vl = MAPIFindUserProp (&(tnef->MapiProperties), PROP_TAG (PT_STRING8, 0x8084));
+ }
+ if (vl != MAPI_UNDEFINED) {
+ if (vl->size > 0)
+ fprintf(fptr, "EMAIL:%s\n", vl->data);
+ }
+ if ((vl = MAPIFindUserProp (&(tnef->MapiProperties), PROP_TAG (PT_STRING8, 0x8093))) == MAPI_UNDEFINED) {
+ vl = MAPIFindUserProp (&(tnef->MapiProperties), PROP_TAG (PT_STRING8, 0x8094));
+ }
+ if (vl != MAPI_UNDEFINED) {
+ if (vl->size > 0)
+ fprintf(fptr, "EMAIL:%s\n", vl->data);
+ }
+ if ((vl = MAPIFindUserProp (&(tnef->MapiProperties), PROP_TAG (PT_STRING8, 0x80a3))) == MAPI_UNDEFINED) {
+ vl = MAPIFindUserProp (&(tnef->MapiProperties), PROP_TAG (PT_STRING8, 0x80a4));
+ }
+ if (vl != MAPI_UNDEFINED) {
+ if (vl->size > 0)
+ fprintf(fptr, "EMAIL:%s\n", vl->data);
+ }
+
+ fprintProperty(tnef, fptr, PT_STRING8, PR_BUSINESS_HOME_PAGE, "URL:%s\n");
+ fprintUserProp(tnef, fptr, PT_STRING8, 0x80d8, "FBURL:%s\n");
+
+ /* Birthday */
+ if ((vl = MAPIFindProperty (&(tnef->MapiProperties), PROP_TAG (PT_SYSTIME, PR_BIRTHDAY))) != MAPI_UNDEFINED) {
+ fprintf(fptr, "BDAY:");
+ MAPISysTimetoDTR ((guchar *) vl->data, &thedate);
+ fprintf(fptr, "%i-%02i-%02i\n", thedate.wYear, thedate.wMonth, thedate.wDay);
+ }
+
+ /* Anniversary */
+ if ((vl = MAPIFindProperty (&(tnef->MapiProperties), PROP_TAG (PT_SYSTIME, PR_WEDDING_ANNIVERSARY))) != MAPI_UNDEFINED) {
+ fprintf(fptr, "X-EVOLUTION-ANNIVERSARY:");
+ MAPISysTimetoDTR ((guchar *) vl->data, &thedate);
+ fprintf(fptr, "%i-%02i-%02i\n", thedate.wYear, thedate.wMonth, thedate.wDay);
+ }
+ fprintf(fptr, "END:VCARD\n");
+ fclose (fptr);
+ }
+ g_free (ifilename);
+}
+
+guchar getRruleCount (guchar a, guchar b) {
+ return ((a << 8) | b);
+}
+
+guchar getRruleMonthNum (guchar a, guchar b) {
+ switch (a) {
+ case 0x00:
+ switch (b) {
+ case 0x00:
+ /* Jan */
+ return (1);
+ case 0xA3:
+ /* May */
+ return (5);
+ case 0xAE:
+ /* Nov */
+ return (11);
+ }
+ break;
+ case 0x60:
+ switch (b) {
+ case 0xAE:
+ /* Feb */
+ return (2);
+ case 0x51:
+ /* Jun */
+ return (6);
+ }
+ break;
+ case 0xE0:
+ switch (b) {
+ case 0x4B:
+ /* Mar */
+ return (3);
+ case 0x56:
+ /* Sep */
+ return (9);
+ }
+ break;
+ case 0x40:
+ switch (b) {
+ case 0xFA:
+ /* Apr */
+ return (4);
+ }
+ break;
+ case 0x20:
+ if (b == 0xFA) {
+ /* Jul */
+ return (7);
+ }
+ break;
+ case 0x80:
+ if (b == 0xA8) {
+ /* Aug */
+ return (8);
+ }
+ break;
+ case 0xA0:
+ if (b == 0xFF) {
+ /* Oct */
+ return (10);
+ }
+ break;
+ case 0xC0:
+ if (b == 0x56) {
+ return (12);
+ }
+ }
+
+ /* Error */
+ return (0);
+}
+
+gchar * getRruleDayname (guchar a) {
+ static gchar daystring[25];
+
+ *daystring = 0;
+
+ if (a & 0x01) {
+ strcat(daystring, "SU,");
+ }
+ if (a & 0x02) {
+ strcat(daystring, "MO,");
+ }
+ if (a & 0x04) {
+ strcat(daystring, "TU,");
+ }
+ if (a & 0x08) {
+ strcat(daystring, "WE,");
+ }
+ if (a & 0x10) {
+ strcat(daystring, "TH,");
+ }
+ if (a & 0x20) {
+ strcat(daystring, "FR,");
+ }
+ if (a & 0x40) {
+ strcat(daystring, "SA,");
+ }
+
+ if (strlen (daystring)) {
+ daystring[strlen (daystring) - 1] = 0;
+ }
+
+ return (daystring);
+}
+
+void printRrule (FILE *fptr, gchar *recur_data, gint size, TNEFStruct *tnef)
+{
+ variableLength *filename;
+
+ if (size < 0x1F) {
+ return;
+ }
+
+ fprintf(fptr, "RRULE:FREQ=");
+
+ if (recur_data[0x04] == 0x0A) {
+ fprintf(fptr, "DAILY");
+
+ if (recur_data[0x16] == 0x23 || recur_data[0x16] == 0x22 ||
+ recur_data[0x16] == 0x21) {
+ if ((filename = MAPIFindUserProp (&(tnef->MapiProperties),
+ PROP_TAG (PT_I2, 0x0011))) != MAPI_UNDEFINED) {
+ fprintf(fptr, ";INTERVAL=%d", *(filename->data));
+ }
+ if (recur_data[0x16] == 0x22 || recur_data[0x16] == 0x21) {
+ fprintf(fptr, ";COUNT=%d",
+ getRruleCount (recur_data[0x1B], recur_data[0x1A]));
+ }
+ } else if (recur_data[0x16] == 0x3E) {
+ fprintf(fptr, ";BYDAY=MO,TU,WE,TH,FR");
+ if (recur_data[0x1A] == 0x22 || recur_data[0x1A] == 0x21) {
+ fprintf(fptr, ";COUNT=%d",
+ getRruleCount (recur_data[0x1F], recur_data[0x1E]));
+ }
+ }
+ } else if (recur_data[0x04] == 0x0B) {
+ fprintf(fptr, "WEEKLY;INTERVAL=%d;BYDAY=%s",
+ recur_data[0x0E], getRruleDayname (recur_data[0x16]));
+ if (recur_data[0x1A] == 0x22 || recur_data[0x1A] == 0x21) {
+ fprintf(fptr, ";COUNT=%d",
+ getRruleCount (recur_data[0x1F], recur_data[0x1E]));
+ }
+ } else if (recur_data[0x04] == 0x0C) {
+ fprintf(fptr, "MONTHLY");
+ if (recur_data[0x06] == 0x02) {
+ fprintf(fptr, ";INTERVAL=%d;BYMONTHDAY=%d", recur_data[0x0E],
+ recur_data[0x16]);
+ if (recur_data[0x1A] == 0x22 || recur_data[0x1A] == 0x21) {
+ fprintf(fptr, ";COUNT=%d", getRruleCount(recur_data[0x1F],
+ recur_data[0x1E]));
+ }
+ } else if (recur_data[0x06] == 0x03) {
+ fprintf(fptr, ";BYDAY=%s;BYSETPOS=%d;INTERVAL=%d",
+ getRruleDayname (recur_data[0x16]),
+ recur_data[0x1A] == 0x05 ? -1 : recur_data[0x1A],
+ recur_data[0x0E]);
+ if (recur_data[0x1E] == 0x22 || recur_data[0x1E] == 0x21) {
+ fprintf(fptr, ";COUNT=%d", getRruleCount(recur_data[0x23],
+ recur_data[0x22]));
+ }
+ }
+ } else if (recur_data[0x04] == 0x0D) {
+ fprintf(fptr, "YEARLY;BYMONTH=%d",
+ getRruleMonthNum (recur_data[0x0A], recur_data[0x0B]));
+ if (recur_data[0x06] == 0x02) {
+ fprintf(fptr, ";BYMONTHDAY=%d", recur_data[0x16]);
+ } else if (recur_data[0x06] == 0x03) {
+ fprintf(fptr, ";BYDAY=%s;BYSETPOS=%d",
+ getRruleDayname (recur_data[0x16]),
+ recur_data[0x1A] == 0x05 ? -1 : recur_data[0x1A]);
+ }
+ if (recur_data[0x1E] == 0x22 || recur_data[0x1E] == 0x21) {
+ fprintf(fptr, ";COUNT=%d", getRruleCount(recur_data[0x23],
+ recur_data[0x22]));
+ }
+ }
+ fprintf(fptr, "\n");
+}
+
+void saveVCalendar (TNEFStruct *tnef, const gchar *tmpdir) {
+ gchar *ifilename;
+ variableLength *filename;
+ gchar *charptr, *charptr2;
+ FILE *fptr;
+ gint index;
+ DWORD *dword_ptr;
+ dtr thedate;
+
+ ifilename = g_build_filename (tmpdir, "calendar.vcf", NULL);
+ printf("%s\n", ifilename);
+
+ if ((fptr = fopen(ifilename, "wb"))==NULL) {
+ printf("Error writing file to disk!");
+ } else {
+ fprintf(fptr, "BEGIN:VCALENDAR\n");
+ if (tnef->messageClass[0] != 0) {
+ charptr2 = tnef->messageClass;
+ charptr = charptr2;
+ while (*charptr != 0) {
+ if (*charptr == '.') {
+ charptr2 = charptr;
+ }
+ charptr++;
+ }
+ if (strcmp(charptr2, ".MtgCncl") == 0) {
+ fprintf(fptr, "METHOD:CANCEL\n");
+ } else {
+ fprintf(fptr, "METHOD:REQUEST\n");
+ }
+ } else {
+ fprintf(fptr, "METHOD:REQUEST\n");
+ }
+ fprintf(fptr, "VERSION:2.0\n");
+ fprintf(fptr, "BEGIN:VEVENT\n");
+
+ /* UID
+ * After alot of comparisons, I'm reasonably sure this is totally
+ * wrong. But it's not really necessary. */
+
+ /* I think it only exists to connect future modification entries to
+ * this entry. so as long as it's incorrectly interpreted the same way
+ * every time, it should be ok :) */
+ filename = NULL;
+ if ((filename = MAPIFindUserProp (&(tnef->MapiProperties),
+ PROP_TAG (PT_BINARY, 0x3))) == MAPI_UNDEFINED) {
+ if ((filename = MAPIFindUserProp (&(tnef->MapiProperties),
+ PROP_TAG (PT_BINARY, 0x23))) == MAPI_UNDEFINED) {
+ filename = NULL;
+ }
+ }
+ if (filename != NULL) {
+ fprintf(fptr, "UID:");
+ for (index = 0; index < filename->size; index++) {
+ fprintf(fptr,"%02X", (guchar)filename->data[index]);
+ }
+ fprintf(fptr,"\n");
+ }
+
+ /* Sequence */
+ filename = NULL;
+ if ((filename = MAPIFindUserProp (&(tnef->MapiProperties),
+ PROP_TAG (PT_LONG, 0x8201))) != MAPI_UNDEFINED) {
+ dword_ptr = (DWORD *) filename->data;
+ fprintf(fptr, "SEQUENCE:%i\n", (gint) *dword_ptr);
+ }
+ if ((filename = MAPIFindProperty (&(tnef->MapiProperties),
+ PROP_TAG (PT_BINARY, PR_SENDER_SEARCH_KEY)))
+ != MAPI_UNDEFINED) {
+ charptr = filename->data;
+ charptr2 = strstr(charptr, ":");
+ if (charptr2 == NULL)
+ charptr2 = charptr;
+ else
+ charptr2++;
+ fprintf(fptr, "ORGANIZER;CN=\"%s\":MAILTO:%s\n",
+ charptr2, charptr2);
+ }
+
+ /* Required Attendees */
+ if ((filename = MAPIFindUserProp (&(tnef->MapiProperties),
+ PROP_TAG (PT_STRING8, 0x823b))) != MAPI_UNDEFINED) {
+ /* We have a list of required participants, so
+ write them out. */
+ if (filename->size > 1) {
+ charptr = filename->data - 1;
+ while (charptr != NULL) {
+ charptr++;
+ charptr2 = strstr(charptr, ";");
+ if (charptr2 != NULL) {
+ *charptr2 = 0;
+ }
+ while (*charptr == ' ')
+ charptr++;
+ fprintf(fptr, "ATTENDEE;PARTSTAT=NEEDS-ACTION;");
+ fprintf(fptr, "ROLE=REQ-PARTICIPANT;RSVP=TRUE;");
+ fprintf(fptr, "CN=\"%s\":MAILTO:%s\n",
+ charptr, charptr);
+ charptr = charptr2;
+ }
+ }
+ /* Optional attendees */
+ if ((filename = MAPIFindUserProp (&(tnef->MapiProperties),
+ PROP_TAG (PT_STRING8, 0x823c))) != MAPI_UNDEFINED) {
+ /* The list of optional participants */
+ if (filename->size > 1) {
+ charptr = filename->data - 1;
+ while (charptr != NULL) {
+ charptr++;
+ charptr2 = strstr(charptr, ";");
+ if (charptr2 != NULL) {
+ *charptr2 = 0;
+ }
+ while (*charptr == ' ')
+ charptr++;
+ fprintf(fptr, "ATTENDEE;PARTSTAT=NEEDS-ACTION;");
+ fprintf(fptr, "ROLE=OPT-PARTICIPANT;RSVP=TRUE;");
+ fprintf(fptr, "CN=\"%s\":MAILTO:%s\n",
+ charptr, charptr);
+ charptr = charptr2;
+ }
+ }
+ }
+ } else if ((filename = MAPIFindUserProp (&(tnef->MapiProperties),
+ PROP_TAG (PT_STRING8, 0x8238))) != MAPI_UNDEFINED) {
+ if (filename->size > 1) {
+ charptr = filename->data - 1;
+ while (charptr != NULL) {
+ charptr++;
+ charptr2 = strstr(charptr, ";");
+ if (charptr2 != NULL) {
+ *charptr2 = 0;
+ }
+ while (*charptr == ' ')
+ charptr++;
+ fprintf(fptr, "ATTENDEE;PARTSTAT=NEEDS-ACTION;");
+ fprintf(fptr, "ROLE=REQ-PARTICIPANT;RSVP=TRUE;");
+ fprintf(fptr, "CN=\"%s\":MAILTO:%s\n",
+ charptr, charptr);
+ charptr = charptr2;
+ }
+ }
+
+ }
+ /* Summary */
+ filename = NULL;
+ if ((filename = MAPIFindProperty (&(tnef->MapiProperties),
+ PROP_TAG (PT_STRING8, PR_CONVERSATION_TOPIC)))
+ != MAPI_UNDEFINED) {
+ fprintf(fptr, "SUMMARY:");
+ cstylefprint (fptr, filename);
+ fprintf(fptr, "\n");
+ }
+
+ /* Description */
+ if ((filename = MAPIFindProperty (&(tnef->MapiProperties),
+ PROP_TAG (PT_BINARY, PR_RTF_COMPRESSED)))
+ != MAPI_UNDEFINED) {
+ variableLength buf;
+ if ((buf.data = (gchar *) DecompressRTF (filename, &buf.size)) != NULL) {
+ fprintf(fptr, "DESCRIPTION:");
+ printRtf (fptr, &buf);
+ free (buf.data);
+ }
+
+ }
+
+ /* Location */
+ filename = NULL;
+ if ((filename = MAPIFindUserProp (&(tnef->MapiProperties),
+ PROP_TAG (PT_STRING8, 0x0002))) == MAPI_UNDEFINED) {
+ if ((filename = MAPIFindUserProp (&(tnef->MapiProperties),
+ PROP_TAG (PT_STRING8, 0x8208))) == MAPI_UNDEFINED) {
+ filename = NULL;
+ }
+ }
+ if (filename != NULL) {
+ fprintf(fptr,"LOCATION: %s\n", filename->data);
+ }
+ /* Date Start */
+ filename = NULL;
+ if ((filename = MAPIFindUserProp (&(tnef->MapiProperties),
+ PROP_TAG (PT_SYSTIME, 0x820d))) == MAPI_UNDEFINED) {
+ if ((filename = MAPIFindUserProp (&(tnef->MapiProperties),
+ PROP_TAG (PT_SYSTIME, 0x8516))) == MAPI_UNDEFINED) {
+ filename = NULL;
+ }
+ }
+ if (filename != NULL) {
+ fprintf(fptr, "DTSTART:");
+ MAPISysTimetoDTR ((guchar *) filename->data, &thedate);
+ fprintf(fptr,"%04i%02i%02iT%02i%02i%02iZ\n",
+ thedate.wYear, thedate.wMonth, thedate.wDay,
+ thedate.wHour, thedate.wMinute, thedate.wSecond);
+ }
+ /* Date End */
+ filename = NULL;
+ if ((filename = MAPIFindUserProp (&(tnef->MapiProperties),
+ PROP_TAG (PT_SYSTIME, 0x820e))) == MAPI_UNDEFINED) {
+ if ((filename = MAPIFindUserProp (&(tnef->MapiProperties),
+ PROP_TAG (PT_SYSTIME, 0x8517))) == MAPI_UNDEFINED) {
+ filename = NULL;
+ }
+ }
+ if (filename != NULL) {
+ fprintf(fptr, "DTEND:");
+ MAPISysTimetoDTR ((guchar *) filename->data, &thedate);
+ fprintf(fptr,"%04i%02i%02iT%02i%02i%02iZ\n",
+ thedate.wYear, thedate.wMonth, thedate.wDay,
+ thedate.wHour, thedate.wMinute, thedate.wSecond);
+ }
+ /* Date Stamp */
+ filename = NULL;
+ if ((filename = MAPIFindUserProp (&(tnef->MapiProperties),
+ PROP_TAG (PT_SYSTIME, 0x8202))) != MAPI_UNDEFINED) {
+ fprintf(fptr, "CREATED:");
+ MAPISysTimetoDTR ((guchar *) filename->data, &thedate);
+ fprintf(fptr,"%04i%02i%02iT%02i%02i%02iZ\n",
+ thedate.wYear, thedate.wMonth, thedate.wDay,
+ thedate.wHour, thedate.wMinute, thedate.wSecond);
+ }
+ /* Class */
+ filename = NULL;
+ if ((filename = MAPIFindUserProp (&(tnef->MapiProperties),
+ PROP_TAG (PT_BOOLEAN, 0x8506))) != MAPI_UNDEFINED) {
+ dword_ptr = (DWORD *) filename->data;
+ fprintf(fptr, "CLASS:" );
+ if (*dword_ptr == 1) {
+ fprintf(fptr,"PRIVATE\n");
+ } else {
+ fprintf(fptr,"PUBLIC\n");
+ }
+ }
+ /* Recurrence */
+ filename = NULL;
+ if ((filename = MAPIFindUserProp (&(tnef->MapiProperties),
+ PROP_TAG (PT_BINARY, 0x8216))) != MAPI_UNDEFINED) {
+ printRrule (fptr, filename->data, filename->size, tnef);
+ }
+
+ /* Wrap it up */
+ fprintf(fptr, "END:VEVENT\n");
+ fprintf(fptr, "END:VCALENDAR\n");
+ fclose (fptr);
+ }
+ g_free (ifilename);
+}
+
+void saveVTask (TNEFStruct *tnef, const gchar *tmpdir) {
+ variableLength *vl;
+ variableLength *filename;
+ gint index;
+ gchar *ifilename;
+ gchar *absfilename, *file;
+ gchar *charptr, *charptr2;
+ dtr thedate;
+ FILE *fptr;
+ DWORD *dword_ptr;
+
+ vl = MAPIFindProperty (&(tnef->MapiProperties), PROP_TAG (PT_STRING8, PR_CONVERSATION_TOPIC));
+
+ if (vl == MAPI_UNDEFINED) {
+ return;
+ }
+
+ index = strlen (vl->data);
+ while (vl->data[index] == ' ')
+ vl->data[index--] = 0;
+
+ file = sanitize_filename (vl->data);
+ if (!file)
+ return;
+ absfilename = g_strconcat (file, ".vcf", NULL);
+ ifilename = g_build_filename (tmpdir, absfilename, NULL);
+ g_free (file);
+ g_free (absfilename);
+
+ printf("%s\n", ifilename);
+
+ if ((fptr = fopen(ifilename, "wb"))==NULL) {
+ printf("Error writing file to disk!");
+ } else {
+ fprintf(fptr, "BEGIN:VCALENDAR\n");
+ fprintf(fptr, "VERSION:2.0\n");
+ fprintf(fptr, "METHOD:PUBLISH\n");
+ filename = NULL;
+
+ fprintf(fptr, "BEGIN:VTODO\n");
+ if (tnef->messageID[0] != 0) {
+ fprintf(fptr,"UID:%s\n", tnef->messageID);
+ }
+ filename = MAPIFindUserProp (&(tnef->MapiProperties), \
+ PROP_TAG (PT_STRING8, 0x8122));
+ if (filename != MAPI_UNDEFINED) {
+ fprintf(fptr, "ORGANIZER:%s\n", filename->data);
+ }
+
+ if ((filename = MAPIFindProperty (&(tnef->MapiProperties), PROP_TAG (PT_STRING8, PR_DISPLAY_TO))) != MAPI_UNDEFINED) {
+ filename = MAPIFindUserProp (&(tnef->MapiProperties), PROP_TAG (PT_STRING8, 0x811f));
+ }
+ if ((filename != MAPI_UNDEFINED) && (filename->size > 1)) {
+ charptr = filename->data - 1;
+ while (charptr != NULL) {
+ charptr++;
+ charptr2 = strstr(charptr, ";");
+ if (charptr2 != NULL) {
+ *charptr2 = 0;
+ }
+ while (*charptr == ' ')
+ charptr++;
+ fprintf(fptr, "ATTENDEE;CN=%s;ROLE=REQ-PARTICIPANT:%s\n", charptr, charptr);
+ charptr = charptr2;
+ }
+ }
+
+ if (tnef->subject.size > 0) {
+ fprintf(fptr,"SUMMARY:");
+ cstylefprint (fptr,&(tnef->subject));
+ fprintf(fptr,"\n");
+ }
+
+ if (tnef->body.size > 0) {
+ fprintf(fptr,"DESCRIPTION:");
+ cstylefprint (fptr,&(tnef->body));
+ fprintf(fptr,"\n");
+ }
+
+ filename = MAPIFindProperty (&(tnef->MapiProperties), \
+ PROP_TAG (PT_SYSTIME, PR_CREATION_TIME));
+ if (filename != MAPI_UNDEFINED) {
+ fprintf(fptr, "DTSTAMP:");
+ MAPISysTimetoDTR ((guchar *) filename->data, &thedate);
+ fprintf(fptr,"%04i%02i%02iT%02i%02i%02iZ\n",
+ thedate.wYear, thedate.wMonth, thedate.wDay,
+ thedate.wHour, thedate.wMinute, thedate.wSecond);
+ }
+
+ filename = MAPIFindUserProp (&(tnef->MapiProperties), \
+ PROP_TAG (PT_SYSTIME, 0x8517));
+ if (filename != MAPI_UNDEFINED) {
+ fprintf(fptr, "DUE:");
+ MAPISysTimetoDTR ((guchar *) filename->data, &thedate);
+ fprintf(fptr,"%04i%02i%02iT%02i%02i%02iZ\n",
+ thedate.wYear, thedate.wMonth, thedate.wDay,
+ thedate.wHour, thedate.wMinute, thedate.wSecond);
+ }
+ filename = MAPIFindProperty (&(tnef->MapiProperties), \
+ PROP_TAG (PT_SYSTIME, PR_LAST_MODIFICATION_TIME));
+ if (filename != MAPI_UNDEFINED) {
+ fprintf(fptr, "LAST-MODIFIED:");
+ MAPISysTimetoDTR ((guchar *) filename->data, &thedate);
+ fprintf(fptr,"%04i%02i%02iT%02i%02i%02iZ\n",
+ thedate.wYear, thedate.wMonth, thedate.wDay,
+ thedate.wHour, thedate.wMinute, thedate.wSecond);
+ }
+ /* Class */
+ filename = MAPIFindUserProp (&(tnef->MapiProperties), \
+ PROP_TAG (PT_BOOLEAN, 0x8506));
+ if (filename != MAPI_UNDEFINED) {
+ dword_ptr = (DWORD *) filename->data;
+ fprintf(fptr, "CLASS:" );
+ if (*dword_ptr == 1) {
+ fprintf(fptr,"PRIVATE\n");
+ } else {
+ fprintf(fptr,"PUBLIC\n");
+ }
+ }
+ fprintf(fptr, "END:VTODO\n");
+ fprintf(fptr, "END:VCALENDAR\n");
+ fclose (fptr);
+ }
+ g_free (ifilename);
+}
+
+void fprintProperty (TNEFStruct *tnef, FILE *fptr, DWORD proptype, DWORD propid, const gchar text[]) {
+ variableLength *vl;
+ if ((vl = MAPIFindProperty (&(tnef->MapiProperties), PROP_TAG (proptype, propid))) != MAPI_UNDEFINED) {
+ if (vl->size > 0) {
+ if ((vl->size == 1) && (vl->data[0] == 0)) {
+ } else {
+ fprintf (fptr, text, vl->data);
+ }
+ }
+ }
+}
+
+void fprintUserProp (TNEFStruct *tnef, FILE *fptr, DWORD proptype, DWORD propid, const gchar text[]) {
+ variableLength *vl;
+ if ((vl = MAPIFindUserProp (&(tnef->MapiProperties), PROP_TAG (proptype, propid))) != MAPI_UNDEFINED) {
+ if (vl->size > 0) {
+ if ((vl->size == 1) && (vl->data[0] == 0)) {
+ } else {
+ fprintf (fptr, text, vl->data);
+ }
+ }
+ }
+}
+
+void quotedfprint (FILE *fptr, variableLength *vl) {
+ gint index;
+
+ for (index = 0; index < vl->size - 1; index++) {
+ if (vl->data[index] == '\n') {
+ fprintf(fptr, "=0A");
+ } else if (vl->data[index] == '\r') {
+ } else {
+ fprintf(fptr, "%c", vl->data[index]);
+ }
+ }
+}
+
+void cstylefprint (FILE *fptr, variableLength *vl) {
+ gint index;
+
+ for (index = 0; index < vl->size - 1; index++) {
+ if (vl->data[index] == '\n') {
+ fprintf(fptr, "\\n");
+ } else if (vl->data[index] == '\r') {
+ /* Print nothing. */
+ } else if (vl->data[index] == ';') {
+ fprintf(fptr, "\\;");
+ } else if (vl->data[index] == ',') {
+ fprintf(fptr, "\\,");
+ } else if (vl->data[index] == '\\') {
+ fprintf(fptr, "\\");
+ } else {
+ fprintf(fptr, "%c", vl->data[index]);
+ }
+ }
+}
+
+void printRtf (FILE *fptr, variableLength *vl) {
+ gint index;
+ gchar *byte;
+ gint brace_ct;
+ gint key;
+
+ key = 0;
+ brace_ct = 0;
+
+ for (index = 0, byte = vl->data; index < vl->size; index++, byte++) {
+ if (*byte == '}') {
+ brace_ct--;
+ key = 0;
+ continue;
+ }
+ if (*byte == '{') {
+ brace_ct++;
+ continue;
+ }
+ if (*byte == '\\') {
+ key = 1;
+ }
+ if (isspace (*byte)) {
+ key = 0;
+ }
+ if ((brace_ct == 1) && (key == 0)) {
+ if (*byte == '\n') {
+ fprintf(fptr, "\\n");
+ } else if (*byte == '\r') {
+ /* Print nothing. */
+ } else if (*byte == ';') {
+ fprintf(fptr, "\\;");
+ } else if (*byte == ',') {
+ fprintf(fptr, "\\,");
+ } else if (*byte == '\\') {
+ fprintf(fptr, "\\");
+ } else {
+ fprintf(fptr, "%c", *byte);
+ }
+ }
+ }
+ fprintf(fptr, "\n");
+}
diff --git a/modules/tnef-attachment/e-mail-parser-tnef-attachment.h b/modules/tnef-attachment/e-mail-parser-tnef-attachment.h
new file mode 100644
index 0000000000..360c66ad9a
--- /dev/null
+++ b/modules/tnef-attachment/e-mail-parser-tnef-attachment.h
@@ -0,0 +1,30 @@
+/*
+ * e-mail-parser-tnef-attachment.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifndef E_MAIL_PARSER_TNEF_ATTACHMENT_H
+#define E_MAIL_PARSER_TNEF_ATTACHMENT_H
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+void e_mail_parser_tnef_attachment_type_register (GTypeModule *type_module);
+
+G_END_DECLS
+
+#endif /* E_MAIL_PARSER_TNEF_ATTACHMENT_H */
diff --git a/modules/tnef-attachment/evolution-module-tnef-attachment.c b/modules/tnef-attachment/evolution-module-tnef-attachment.c
new file mode 100644
index 0000000000..df31b97a13
--- /dev/null
+++ b/modules/tnef-attachment/evolution-module-tnef-attachment.c
@@ -0,0 +1,51 @@
+/*
+ * evolution-module-tnef-attachment.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include "e-mail-parser-tnef-attachment.h"
+
+#include <gmodule.h>
+
+void e_module_load (GTypeModule *type_module);
+void e_module_unload (GTypeModule *type_module);
+const gchar * g_module_check_init (GModule *module);
+
+G_MODULE_EXPORT void
+e_module_load (GTypeModule *type_module)
+{
+ /* Register dynamically loaded types. */
+
+ e_mail_parser_tnef_attachment_type_register (type_module);
+}
+
+G_MODULE_EXPORT void
+e_module_unload (GTypeModule *type_module)
+{
+}
+
+G_MODULE_EXPORT const gchar *
+g_module_check_init (GModule *module)
+{
+ /* FIXME Until mail is split into a module library and a
+ * reusable shared library, prevent the module from
+ * being unloaded. Unloading the module resets all
+ * static variables, which screws up foo_get_type()
+ * functions among other things. */
+ g_module_make_resident (module);
+
+ return NULL;
+}