+2013-02-20 [colin] 3.9.0cvs83
+
+ * configure.ac
+ * src/plugins/Makefile.am
+ * src/plugins/spam_report/.cvsignore
+ * src/plugins/spam_report/Makefile.am
+ * src/plugins/spam_report/placeholder.txt
+ * src/plugins/spam_report/spam_report.c
+ * src/plugins/spam_report/spam_report_prefs.c
+ * src/plugins/spam_report/spam_report_prefs.h
+ * src/plugins/tnef_parse/.cvsignore
+ * src/plugins/tnef_parse/Makefile.am
+ * src/plugins/tnef_parse/claws.def
+ * src/plugins/tnef_parse/mapi.h
+ * src/plugins/tnef_parse/mapidefs.h
+ * src/plugins/tnef_parse/mapitags.h
+ * src/plugins/tnef_parse/placeholder.txt
+ * src/plugins/tnef_parse/plugin.def
+ * src/plugins/tnef_parse/tnef-errors.h
+ * src/plugins/tnef_parse/tnef-types.h
+ * src/plugins/tnef_parse/tnef_dump.c
+ * src/plugins/tnef_parse/tnef_dump.h
+ * src/plugins/tnef_parse/tnef_parse.c
+ * src/plugins/tnef_parse/version.rc
+ * src/plugins/tnef_parse/ytnef.c
+ * src/plugins/tnef_parse/ytnef.h
+ Add tnef_parse and spam_report
+
2013-02-20 [colin] 3.9.0cvs82
* src/plugins/bogofilter/Makefile.am
( cvs diff -u -r 1.1.2.2 -r 1.1.2.3 src/plugins/notification/Makefile.am; cvs diff -u -r 1.1.2.1 -r 1.1.2.2 src/plugins/pdf_viewer/Makefile.am; cvs diff -u -r 1.1.2.1 -r 1.1.2.2 src/plugins/python/Makefile.am; ) > 3.9.0cvs80.patchset
( cvs diff -u -r 1.654.2.4657 -r 1.654.2.4658 configure.ac; ) > 3.9.0cvs81.patchset
( cvs diff -u -r 1.1.2.7 -r 1.1.2.8 src/plugins/bogofilter/Makefile.am; cvs diff -u -r 1.1.2.1 -r 1.1.2.2 src/plugins/clamd/Makefile.am; cvs diff -u -r 1.3.2.4 -r 1.3.2.5 src/plugins/demo/Makefile.am; cvs diff -u -r 1.4.2.9 -r 1.4.2.10 src/plugins/dillo_viewer/Makefile.am; cvs diff -u -r 1.1.2.2 -r 1.1.2.3 src/plugins/fancy/Makefile.am; cvs diff -u -r 1.1.2.1 -r 1.1.2.2 src/plugins/fetchinfo/Makefile.am; cvs diff -u -r 1.1.2.1 -r 1.1.2.2 src/plugins/gdata/Makefile.am; cvs diff -u -r 1.1.2.1 -r 1.1.2.2 src/plugins/mailmbox/Makefile.am; cvs diff -u -r 1.1.2.1 -r 1.1.2.2 src/plugins/newmail/Makefile.am; cvs diff -u -r 1.1.2.3 -r 1.1.2.4 src/plugins/notification/Makefile.am; cvs diff -u -r 1.1.2.2 -r 1.1.2.3 src/plugins/pdf_viewer/Makefile.am; cvs diff -u -r 1.1.2.1 -r 1.1.2.2 src/plugins/perl/Makefile.am; cvs diff -u -r 1.1.2.2 -r 1.1.2.3 src/plugins/python/Makefile.am; cvs diff -u -r 1.5.2.10 -r 1.5.2.11 src/plugins/spamassassin/Makefile.am; cvs diff -u -r 1.4.2.14 -r 1.4.2.15 src/plugins/trayicon/Makefile.am; cvs diff -u -r 1.1.2.1 -r 1.1.2.2 src/plugins/vcalendar/libical/libical/Makefile.am; ) > 3.9.0cvs82.patchset
+( cvs diff -u -r 1.654.2.4659 -r 1.654.2.4660 configure.ac; cvs diff -u -r 1.8.2.14 -r 1.8.2.15 src/plugins/Makefile.am; diff -u /dev/null src/plugins/spam_report/.cvsignore; diff -u /dev/null src/plugins/spam_report/Makefile.am; cvs diff -u -r -1.1.2.1 -r -1.1.2.2 src/plugins/spam_report/placeholder.txt; diff -u /dev/null src/plugins/spam_report/spam_report.c; diff -u /dev/null src/plugins/spam_report/spam_report_prefs.c; diff -u /dev/null src/plugins/spam_report/spam_report_prefs.h; diff -u /dev/null src/plugins/tnef_parse/.cvsignore; diff -u /dev/null src/plugins/tnef_parse/Makefile.am; diff -u /dev/null src/plugins/tnef_parse/claws.def; diff -u /dev/null src/plugins/tnef_parse/mapi.h; diff -u /dev/null src/plugins/tnef_parse/mapidefs.h; diff -u /dev/null src/plugins/tnef_parse/mapitags.h; cvs diff -u -r -1.1.2.1 -r -1.1.2.2 src/plugins/tnef_parse/placeholder.txt; diff -u /dev/null src/plugins/tnef_parse/plugin.def; diff -u /dev/null src/plugins/tnef_parse/tnef-errors.h; diff -u /dev/null src/plugins/tnef_parse/tnef-types.h; diff -u /dev/null src/plugins/tnef_parse/tnef_dump.c; diff -u /dev/null src/plugins/tnef_parse/tnef_dump.h; diff -u /dev/null src/plugins/tnef_parse/tnef_parse.c; diff -u /dev/null src/plugins/tnef_parse/version.rc; diff -u /dev/null src/plugins/tnef_parse/ytnef.c; diff -u /dev/null src/plugins/tnef_parse/ytnef.h; ) > 3.9.0cvs83.patchset
MICRO_VERSION=0
INTERFACE_AGE=0
BINARY_AGE=0
-EXTRA_VERSION=82
+EXTRA_VERSION=83
EXTRA_RELEASE=
EXTRA_GTK2_VERSION=
PLUGINS=""
dnl Find curl-config, used by fancy, vcalendar
-PKG_CHECK_MODULES(CURL, libcurl)
+PKG_CHECK_MODULES(CURL, libcurl, [have_curl=yes], [have_curl=no])
AC_SUBST(CURL_LIBS)
AC_SUBST(CURL_CFLAGS)
AC_MSG_RESULT(no)
fi
AM_CONDITIONAL(BUILD_SMIME_PLUGIN, test x"$ac_cv_enable_smime_plugin" = xyes)
+
dnl --- SpamAssassin ---
AC_MSG_CHECKING([whether to build SpamAssassin plugin])
AC_ARG_ENABLE(spamassassin-plugin,
fi
AM_CONDITIONAL(BUILD_SPAMASSASSIN_PLUGIN, test x"$ac_cv_enable_spamassassin_plugin" = xyes)
+dnl --- spam_report ---
+AC_MSG_CHECKING([whether to build spam_report plugin])
+AC_ARG_ENABLE(spam_report-plugin,
+ [ --disable-spam_report-plugin do not build spam_report plugin],
+ [ac_cv_enable_spam_report_plugin=$enableval], [ac_cv_enable_spam_report_plugin=yes])
+if test x"$ac_cv_enable_spam_report_plugin" = xyes; then
+ if test x"$have_curl" = xyes; then
+ AC_MSG_RESULT(yes)
+ PLUGINS="spam_report $PLUGINS"
+ else
+ AC_MSG_ERROR(spam_report needs libcurl)
+ fi
+else
+ AC_MSG_RESULT(no)
+fi
+AM_CONDITIONAL(BUILD_SPAM_REPORT_PLUGIN, test x"$ac_cv_enable_spam_report_plugin" = xyes)
+
+dnl --- tnef_parse ---
+AC_MSG_CHECKING([whether to build tnef_parse plugin])
+AC_ARG_ENABLE(tnef_parse-plugin,
+ [ --disable-tnef_parse-plugin do not build tnef_parse plugin],
+ [ac_cv_enable_tnef_parse_plugin=$enableval], [ac_cv_enable_tnef_parse_plugin=yes])
+if test x"$ac_cv_enable_tnef_parse_plugin" = xyes; then
+ AC_MSG_RESULT(yes)
+ PLUGINS="tnef_parse $PLUGINS"
+else
+ AC_MSG_RESULT(no)
+fi
+AM_CONDITIONAL(BUILD_TNEF_PARSE_PLUGIN, test x"$ac_cv_enable_tnef_parse_plugin" = xyes)
+
dnl --- Trayicon ---
AC_MSG_CHECKING([whether to build Trayicon plugin])
AC_ARG_ENABLE(trayicon-plugin,
src/plugins/rssyl/Makefile
src/plugins/smime/Makefile
src/plugins/spamassassin/Makefile
+src/plugins/spam_report/Makefile
+src/plugins/tnef_parse/Makefile
src/plugins/trayicon/Makefile
src/plugins/vcalendar/Makefile
src/plugins/vcalendar/libical/Makefile
endif
if BUILD_SPAMASSASSIN_PLUGIN
-spamassasssin_dir = spamassassin
+spamassassin_dir = spamassassin
+endif
+
+if BUILD_SPAM_REPORT_PLUGIN
+spam_report_dir = spam_report
+endif
+
+if BUILD_TNEF_PARSE_PLUGIN
+tnef_parse_dir = tnef_parse
endif
if BUILD_TRAYICON_PLUGIN
$(pgpmime_dir) \
$(pgpinline_dir) \
$(rssyl_dir) \
- $(spamassasssin_dir) \
$(smime_dir) \
+ $(spamassassin_dir) \
+ $(spam_report_dir) \
+ $(tnef_parse_dir) \
$(trayicon_dir) \
$(vcalendar_dir)
--- /dev/null
+.deps
+.libs
+Makefile
+Makefile.in
+*.la
+*.lo
+*.o
--- /dev/null
+plugindir = $(pkglibdir)/plugins
+
+plugin_LTLIBRARIES = spamreport.la
+
+spamreport_la_SOURCES = \
+ spam_report.c \
+ spam_report_prefs.c \
+ spam_report_prefs.h \
+ gettext.h
+
+spamreport_la_LDFLAGS = \
+ -avoid-version -module \
+ $(GTK_LIBS)
+
+spamreport_la_LIBADD = \
+ $(CURL_LIBS) \
+ $(GTK_LIBS)
+
+INCLUDES = \
+ -I$(top_srcdir)/src \
+ -I$(top_srcdir)/src/common \
+ -I$(top_builddir)/src/common \
+ -I$(top_srcdir)/src/gtk
+
+AM_CPPFLAGS = \
+ -Wall \
+ $(CLAWS_MAIL_CFLAGS) \
+ $(GLIB_CFLAGS) \
+ $(CURL_CFLAGS) \
+ $(GTK_CFLAGS) \
+ -DLOCALEDIR=\""$(localedir)"\"
+++ /dev/null
-Placeholder
--- /dev/null
+/*
+ * Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
+ * Copyright (C) 1999-2007 Colin Leroy <colin@colino.net>
+ * and the Claws Mail Team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#include "claws-features.h"
+#endif
+
+#include <unistd.h>
+#include <stdio.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+#include <gdk/gdkx.h>
+#include "common/claws.h"
+#include "common/version.h"
+#include "main.h"
+#include "plugin.h"
+#include "prefs_common.h"
+#include "utils.h"
+#include "spam_report_prefs.h"
+#include "statusbar.h"
+#include "procmsg.h"
+#include "log.h"
+#include "inc.h"
+#include "plugin.h"
+#include "menu.h"
+#include "defs.h"
+#include "base64.h"
+#include "procheader.h"
+
+#ifdef USE_PTHREAD
+#include <pthread.h>
+#endif
+
+#include <curl/curl.h>
+#include <curl/curlver.h>
+
+struct CurlReadWrite {
+ char *data;
+ size_t size;
+};
+
+static gboolean check_debian_listid(MsgInfo *msginfo);
+
+/* this interface struct is probably not enough for the various available
+ * reporting places/methods. It'll be extended as necessary. */
+
+ReportInterface spam_interfaces[] = {
+ { "Signal-Spam.fr", INTF_HTTP_AUTH, "https://www.signal-spam.fr/api/signaler",
+ "message=%claws_mail_body_b64%", NULL},
+ { "Spamcop.net", INTF_MAIL, NULL, NULL, NULL},
+ { "Debian Lists", INTF_HTTP_GET,
+ "http://lists.debian.org/cgi-bin/nominate-for-review.pl?Quiet=on&msgid=%claws_mail_msgid%",
+ NULL, check_debian_listid},
+ { NULL, INTF_NULL, NULL, NULL, NULL}
+};
+
+/* From RSSyl. This should be factorized to the core... */
+static gchar *spamreport_strreplace(gchar *source, gchar *pattern,
+ gchar *replacement)
+{
+ gchar *new, *w_new, *c;
+ guint count = 0, final_length;
+ size_t len_pattern, len_replacement;
+
+ if( source == NULL || pattern == NULL ) {
+ debug_print("source or pattern is NULL!!!\n");
+ return NULL;
+ }
+
+ if( !g_utf8_validate(source, -1, NULL) ) {
+ debug_print("source is not an UTF-8 encoded text\n");
+ return NULL;
+ }
+
+ if( !g_utf8_validate(pattern, -1, NULL) ) {
+ debug_print("pattern is not an UTF-8 encoded text\n");
+ return NULL;
+ }
+
+ len_pattern = strlen(pattern);
+ len_replacement = replacement ? strlen(replacement) : 0;
+
+ c = source;
+ while( ( c = g_strstr_len(c, strlen(c), pattern) ) ) {
+ count++;
+ c += len_pattern;
+ }
+
+ final_length = strlen(source)
+ - ( count * len_pattern )
+ + ( count * len_replacement );
+
+ new = malloc(final_length + 1);
+ w_new = new;
+ memset(new, '\0', final_length + 1);
+
+ c = source;
+
+ while( *c != '\0' ) {
+ if( !memcmp(c, pattern, len_pattern) ) {
+ gboolean break_after_rep = FALSE;
+ size_t i;
+ if (*(c + len_pattern) == '\0')
+ break_after_rep = TRUE;
+ for (i = 0; i < len_replacement; i++) {
+ *w_new = replacement[i];
+ w_new++;
+ }
+ if (break_after_rep)
+ break;
+ c = c + len_pattern;
+ } else {
+ *w_new = *c;
+ w_new++;
+ c++;
+ }
+ }
+ return new;
+}
+
+static gboolean check_debian_listid(MsgInfo *msginfo)
+{
+ gchar buf[1024];
+ if (!procheader_get_header_from_msginfo(msginfo, buf, sizeof(buf), "List-Id:")) {
+ if (strstr(buf, "lists.debian.org")) {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+static void spamreport_http_response_log(gchar *url, long response)
+{
+ switch (response) {
+ case 400: /* Bad Request */
+ log_error(LOG_PROTOCOL, "%s: Bad Request\n", url);
+ break;
+ case 401: /* Not Authorized */
+ log_error(LOG_PROTOCOL, "%s: Wrong login or password\n", url);
+ break;
+ case 404: /* Not Authorized */
+ log_error(LOG_PROTOCOL, "%s: Not found\n", url);
+ break;
+ }
+}
+
+static void *myrealloc(void *pointer, size_t size) {
+ /*
+ * There might be a realloc() out there that doesn't like reallocing
+ * NULL pointers, so we take care of it here.
+ */
+ if (pointer) {
+ return realloc(pointer, size);
+ } else {
+ return malloc(size);
+ }
+}
+
+static size_t curl_writefunction_cb(void *pointer, size_t size, size_t nmemb, void *data) {
+ size_t realsize = size * nmemb;
+ struct CurlReadWrite *mem = (struct CurlReadWrite *)data;
+
+ mem->data = myrealloc(mem->data, mem->size + realsize + 1);
+ if (mem->data) {
+ memcpy(&(mem->data[mem->size]), pointer, realsize);
+ mem->size += realsize;
+ mem->data[mem->size] = 0;
+ }
+ return realsize;
+}
+
+static void report_spam(gint id, ReportInterface *intf, MsgInfo *msginfo, gchar *contents)
+{
+ gchar *reqbody = NULL, *tmp = NULL, *auth = NULL, *b64 = NULL, *geturl = NULL;
+ size_t len_contents;
+ CURL *curl;
+ CURLcode res;
+ long response;
+ struct CurlReadWrite chunk;
+
+ chunk.data = NULL;
+ chunk.size = 0;
+
+ if (spamreport_prefs.enabled[id] == FALSE) {
+ debug_print("not reporting via %s (disabled)\n", intf->name);
+ return;
+ }
+ if (intf->should_report != NULL && (intf->should_report)(msginfo) == FALSE) {
+ debug_print("not reporting via %s (unsuitable)\n", intf->name);
+ return;
+ }
+
+ debug_print("reporting via %s\n", intf->name);
+ tmp = spamreport_strreplace(intf->body, "%claws_mail_body%", contents);
+ len_contents = strlen(contents);
+ b64 = g_malloc0(B64LEN(len_contents) + 1);
+ base64_encode(b64, contents, len_contents);
+ reqbody = spamreport_strreplace(tmp, "%claws_mail_body_b64%", b64);
+ geturl = spamreport_strreplace(intf->url, "%claws_mail_msgid%", msginfo->msgid);
+ g_free(b64);
+ g_free(tmp);
+
+ switch(intf->type) {
+ case INTF_HTTP_AUTH:
+ if (spamreport_prefs.user[id] && *(spamreport_prefs.user[id])) {
+ auth = g_strdup_printf("%s:%s", spamreport_prefs.user[id], spamreport_prefs.pass[id]);
+
+ curl = curl_easy_init();
+ curl_easy_setopt(curl, CURLOPT_URL, intf->url);
+ curl_easy_setopt(curl, CURLOPT_POSTFIELDS, reqbody);
+ curl_easy_setopt(curl, CURLOPT_USERPWD, auth);
+ curl_easy_setopt(curl, CURLOPT_TIMEOUT, prefs_common_get_prefs()->io_timeout_secs);
+ curl_easy_setopt(curl, CURLOPT_USERAGENT,
+ SPAM_REPORT_USERAGENT "(" PLUGINS_URI ")");
+ res = curl_easy_perform(curl);
+ curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response);
+ curl_easy_cleanup(curl);
+ spamreport_http_response_log(intf->url, response);
+ g_free(auth);
+ }
+ break;
+ case INTF_MAIL:
+ if (spamreport_prefs.user[id] && *(spamreport_prefs.user[id])) {
+ Compose *compose = compose_forward(NULL, msginfo, TRUE, NULL, TRUE, TRUE);
+ compose->use_signing = FALSE;
+ compose_entry_append(compose, spamreport_prefs.user[id], COMPOSE_TO, PREF_NONE);
+ compose_send(compose);
+ }
+ break;
+ case INTF_HTTP_GET:
+ curl = curl_easy_init();
+ curl_easy_setopt(curl, CURLOPT_URL, geturl);
+ curl_easy_setopt(curl, CURLOPT_USERAGENT,
+ SPAM_REPORT_USERAGENT "(" PLUGINS_URI ")");
+ curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_writefunction_cb);
+ curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunk);
+ res = curl_easy_perform(curl);
+ curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response);
+ curl_easy_cleanup(curl);
+ spamreport_http_response_log(geturl, response);
+ /* On success the page should return "OK: nominated <msgid>" */
+ if (chunk.size < 13 || strstr(chunk.data, "OK: nominated") == NULL) {
+ if (chunk.size > 0) {
+ log_error(LOG_PROTOCOL, "%s: response was %s\n", geturl, chunk.data);
+ }
+ else {
+ log_error(LOG_PROTOCOL, "%s: response was empty\n", geturl);
+ }
+ }
+ break;
+ default:
+ g_warning("Unknown method\n");
+ }
+ g_free(reqbody);
+ g_free(geturl);
+}
+
+static void report_spam_cb_ui(GtkAction *action, gpointer data)
+{
+ MainWindow *mainwin = mainwindow_get_mainwindow();
+ SummaryView *summaryview = mainwin->summaryview;
+ GSList *msglist = summary_get_selected_msg_list(summaryview);
+ GSList *cur;
+ gint curnum=0, total=0;
+ if (summary_is_locked(summaryview) || !msglist) {
+ if (msglist)
+ g_slist_free(msglist);
+ return;
+ }
+ main_window_cursor_wait(summaryview->mainwin);
+ gtk_cmclist_freeze(GTK_CMCLIST(summaryview->ctree));
+ folder_item_update_freeze();
+ inc_lock();
+
+ STATUSBAR_PUSH(mainwin, _("Reporting spam..."));
+ total = g_slist_length(msglist);
+
+ for (cur = msglist; cur; cur = cur->next) {
+ MsgInfo *msginfo = (MsgInfo *)cur->data;
+ gchar *file = procmsg_get_message_file(msginfo);
+ gchar *contents = NULL;
+ int i = 0;
+ if (!file)
+ continue;
+ debug_print("reporting message %d (%s)\n", msginfo->msgnum, file);
+ statusbar_progress_all(curnum, total, 1);
+ GTK_EVENTS_FLUSH();
+ curnum++;
+
+ contents = file_read_to_str(file);
+
+ for (i = 0; i < INTF_LAST; i++)
+ report_spam(i, &(spam_interfaces[i]), msginfo, contents);
+
+ g_free(contents);
+ g_free(file);
+ }
+
+ statusbar_progress_all(0,0,0);
+ STATUSBAR_POP(mainwin);
+ inc_unlock();
+ folder_item_update_thaw();
+ gtk_cmclist_thaw(GTK_CMCLIST(summaryview->ctree));
+ main_window_cursor_normal(summaryview->mainwin);
+ g_slist_free(msglist);
+}
+
+static GtkActionEntry spamreport_main_menu[] = {{
+ "Message/ReportSpam",
+ NULL, N_("Report spam online..."), NULL, NULL, G_CALLBACK(report_spam_cb_ui)
+}};
+
+static guint context_menu_id = 0;
+static guint main_menu_id = 0;
+
+gint plugin_init(gchar **error)
+{
+ MainWindow *mainwin = mainwindow_get_mainwindow();
+
+ if (!check_plugin_version(MAKE_NUMERIC_VERSION(3,7,3,13),
+ VERSION_NUMERIC, _("SpamReport"), error))
+ return -1;
+
+ spamreport_prefs_init();
+#ifdef HAVE_LIBCURL
+ curl_global_init(CURL_GLOBAL_DEFAULT);
+#endif
+
+ gtk_action_group_add_actions(mainwin->action_group, spamreport_main_menu,
+ 1, (gpointer)mainwin);
+ MENUITEM_ADDUI_ID_MANAGER(mainwin->ui_manager, "/Menu/Message", "ReportSpam",
+ "Message/ReportSpam", GTK_UI_MANAGER_MENUITEM,
+ main_menu_id)
+ MENUITEM_ADDUI_ID_MANAGER(mainwin->ui_manager, "/Menus/SummaryViewPopup", "ReportSpam",
+ "Message/ReportSpam", GTK_UI_MANAGER_MENUITEM,
+ context_menu_id)
+ return 0;
+}
+
+gboolean plugin_done(void)
+{
+ MainWindow *mainwin = mainwindow_get_mainwindow();
+ SummaryView *summaryview = NULL;
+
+ if (mainwin == NULL)
+ return TRUE;
+
+ summaryview = mainwin->summaryview;
+ MENUITEM_REMUI_MANAGER(mainwin->ui_manager,mainwin->action_group, "Message/ReportSpam", main_menu_id);
+ main_menu_id = 0;
+
+ MENUITEM_REMUI_MANAGER(mainwin->ui_manager,mainwin->action_group, "Message/ReportSpam", context_menu_id);
+ context_menu_id = 0;
+#ifdef HAVE_LIBCURL
+ spamreport_prefs_done();
+#endif
+ return TRUE;
+}
+
+const gchar *plugin_name(void)
+{
+ return _("SpamReport");
+}
+
+const gchar *plugin_desc(void)
+{
+ return _("This plugin reports spam to various places.\n"
+ "Currently the following sites or methods are supported:\n\n"
+ " * spam-signal.fr\n"
+ " * spamcop.net\n"
+ " * lists.debian.org nomination system");
+}
+
+const gchar *plugin_type(void)
+{
+ return "GTK2";
+}
+
+const gchar *plugin_licence(void)
+{
+ return "GPL3+";
+}
+
+const gchar *plugin_version(void)
+{
+ return VERSION;
+}
+
+struct PluginFeature *plugin_provides(void)
+{
+ static struct PluginFeature features[] =
+ { {PLUGIN_UTILITY, N_("Spam reporting")},
+ {PLUGIN_NOTHING, NULL}};
+ return features;
+}
--- /dev/null
+/*
+ * Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
+ * Copyright (C) 1999-2007 Colin Leroy <colin@colino.net>
+ * and the Claws Mail Team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#include "claws-features.h"
+#endif
+
+#include "defs.h"
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+
+#include "gtkutils.h"
+#include "prefs.h"
+#include "prefs_gtk.h"
+#include "prefswindow.h"
+#include "alertpanel.h"
+#include "utils.h"
+
+#include "spam_report_prefs.h"
+
+#define PREFS_BLOCK_NAME "SpamReport"
+
+SpamReportPrefs spamreport_prefs;
+void spamreport_clear_cache(void);
+
+typedef struct _SpamReportPage SpamReportPage;
+
+struct _SpamReportPage {
+ PrefsPage page;
+ GtkWidget *frame[INTF_LAST];
+ GtkWidget *enabled_chkbtn[INTF_LAST];
+ GtkWidget *user_entry[INTF_LAST];
+ GtkWidget *pass_entry[INTF_LAST];
+};
+
+static PrefParam param[] = {
+ {"signalspam_enabled", "FALSE", &spamreport_prefs.enabled[INTF_SIGNALSPAM], P_BOOL, NULL, NULL, NULL},
+ {"signalspam_user", "", &spamreport_prefs.user[INTF_SIGNALSPAM], P_STRING, NULL, NULL, NULL},
+ {"signalspam_pass", "", &spamreport_prefs.pass[INTF_SIGNALSPAM], P_PASSWORD, NULL, NULL, NULL},
+ {"spamcop_enabled", "FALSE", &spamreport_prefs.enabled[INTF_SPAMCOP], P_BOOL, NULL, NULL, NULL},
+ {"spamcop_user", "", &spamreport_prefs.user[INTF_SPAMCOP], P_STRING, NULL, NULL, NULL},
+ {"debianspam_enabled", "FALSE", &spamreport_prefs.enabled[INTF_DEBIANSPAM], P_BOOL, NULL, NULL, NULL},
+ {0,0,0,0,0,0,0}
+};
+
+static SpamReportPage spamreport_prefs_page;
+
+static void create_spamreport_prefs_page (PrefsPage *page,
+ GtkWindow *window,
+ gpointer data);
+static void destroy_spamreport_prefs_page (PrefsPage *page);
+static void save_spamreport_prefs (PrefsPage *page);
+
+void spamreport_prefs_init(void)
+{
+ static gchar *path[3];
+ gchar *rcpath;
+
+ path[0] = _("Plugins");
+ path[1] = _("SpamReport");
+ path[2] = NULL;
+
+ prefs_set_default(param);
+ rcpath = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, COMMON_RC, NULL);
+ prefs_read_config(param, PREFS_BLOCK_NAME, rcpath, NULL);
+ g_free(rcpath);
+
+ spamreport_prefs_page.page.path = path;
+ spamreport_prefs_page.page.create_widget = create_spamreport_prefs_page;
+ spamreport_prefs_page.page.destroy_widget = destroy_spamreport_prefs_page;
+ spamreport_prefs_page.page.save_page = save_spamreport_prefs;
+ spamreport_prefs_page.page.weight = 30.0;
+
+ prefs_gtk_register_page((PrefsPage *) &spamreport_prefs_page);
+}
+
+void spamreport_prefs_done(void)
+{
+ prefs_gtk_unregister_page((PrefsPage *) &spamreport_prefs_page);
+}
+
+static void create_spamreport_prefs_page(PrefsPage *page,
+ GtkWindow *window,
+ gpointer data)
+{
+ SpamReportPage *prefs_page = (SpamReportPage *) page;
+
+ GtkWidget *vbox, *table;
+ GtkWidget *tmp;
+ int i = 0;
+
+ vbox = gtk_vbox_new(FALSE, VSPACING_NARROW);
+ gtk_container_set_border_width(GTK_CONTAINER(vbox), VBOX_BORDER);
+ gtk_widget_show(vbox);
+
+ for (i = 0; i < INTF_LAST; i++) {
+ prefs_page->frame[i] = gtk_frame_new(spam_interfaces[i].name);
+ gtk_box_pack_start(GTK_BOX(vbox), prefs_page->frame[i], FALSE, FALSE, 6);
+
+ prefs_page->user_entry[i] = gtk_entry_new();
+ prefs_page->pass_entry[i] = gtk_entry_new();
+ prefs_page->enabled_chkbtn[i] = gtk_check_button_new_with_label(_("Enabled"));
+
+ gtk_entry_set_visibility(GTK_ENTRY(prefs_page->pass_entry[i]), FALSE);
+
+ gtk_entry_set_text(GTK_ENTRY(prefs_page->user_entry[i]),
+ spamreport_prefs.user[i] ? spamreport_prefs.user[i]:"");
+ gtk_entry_set_text(GTK_ENTRY(prefs_page->pass_entry[i]),
+ spamreport_prefs.pass[i] ? spamreport_prefs.pass[i]:"");
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(prefs_page->enabled_chkbtn[i]),
+ spamreport_prefs.enabled[i]);
+
+ table = gtk_table_new(3, 2, FALSE);
+ gtk_container_set_border_width(GTK_CONTAINER(table), 8);
+ gtk_table_set_row_spacings(GTK_TABLE(table), 4);
+ gtk_table_set_col_spacings(GTK_TABLE(table), 8);
+
+ gtk_container_add(GTK_CONTAINER(prefs_page->frame[i]), table);
+ gtk_widget_show(prefs_page->frame[i]);
+ gtk_widget_show(table);
+
+ gtk_table_attach(GTK_TABLE(table), prefs_page->enabled_chkbtn[i], 0, 2, 0, 1,
+ GTK_EXPAND|GTK_FILL, GTK_EXPAND|GTK_FILL,
+ 0, 0);
+ gtk_widget_show(prefs_page->enabled_chkbtn[i]);
+
+ switch(spam_interfaces[i].type) {
+ case INTF_MAIL:
+ tmp = gtk_label_new(_("Forward to:"));
+ break;
+ default:
+ tmp = gtk_label_new(_("Username:"));
+ }
+ gtk_table_attach(GTK_TABLE(table), tmp, 0, 1, 1, 2,
+ 0, 0,
+ 0, 0);
+ gtk_table_attach(GTK_TABLE(table), prefs_page->user_entry[i], 1, 2, 1, 2,
+ GTK_EXPAND|GTK_FILL, GTK_EXPAND|GTK_FILL,
+ 0, 0);
+ if (spam_interfaces[i].type != INTF_HTTP_GET) {
+ gtk_widget_show(tmp);
+ gtk_widget_show(prefs_page->user_entry[i]);
+ }
+
+ tmp = gtk_label_new(_("Password:"));
+ gtk_table_attach(GTK_TABLE(table), tmp, 0, 1, 2, 3,
+ 0, 0,
+ 0, 0);
+ gtk_table_attach(GTK_TABLE(table), prefs_page->pass_entry[i], 1, 2, 2, 3,
+ GTK_EXPAND|GTK_FILL, GTK_EXPAND|GTK_FILL,
+ 0, 0);
+ if (spam_interfaces[i].type != INTF_MAIL && spam_interfaces[i].type != INTF_HTTP_GET) {
+ gtk_widget_show(tmp);
+ gtk_widget_show(prefs_page->pass_entry[i]);
+ }
+ }
+ prefs_page->page.widget = vbox;
+}
+
+static void destroy_spamreport_prefs_page(PrefsPage *page)
+{
+ /* Do nothing! */
+}
+
+static void save_spamreport_prefs(PrefsPage *page)
+{
+ SpamReportPage *prefs_page = (SpamReportPage *) page;
+ PrefFile *pref_file;
+ gchar *rc_file_path = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S,
+ COMMON_RC, NULL);
+ int i = 0;
+
+ for (i = 0; i < INTF_LAST; i++) {
+
+ g_free(spamreport_prefs.user[i]);
+ g_free(spamreport_prefs.pass[i]);
+
+ spamreport_prefs.enabled[i] = gtk_toggle_button_get_active(
+ GTK_TOGGLE_BUTTON(prefs_page->enabled_chkbtn[i]));
+ spamreport_prefs.user[i] = gtk_editable_get_chars(
+ GTK_EDITABLE(prefs_page->user_entry[i]), 0, -1);
+ spamreport_prefs.pass[i] = gtk_editable_get_chars(
+ GTK_EDITABLE(prefs_page->pass_entry[i]), 0, -1);
+ }
+
+ pref_file = prefs_write_open(rc_file_path);
+ g_free(rc_file_path);
+
+ if (!(pref_file) ||
+ (prefs_set_block_label(pref_file, PREFS_BLOCK_NAME) < 0))
+ return;
+
+ if (prefs_write_param(param, pref_file->fp) < 0) {
+ g_warning("failed to write SpamReport Plugin configuration\n");
+ prefs_file_close_revert(pref_file);
+ return;
+ }
+ if (fprintf(pref_file->fp, "\n") < 0) {
+ FILE_OP_ERROR(rc_file_path, "fprintf");
+ prefs_file_close_revert(pref_file);
+ } else
+ prefs_file_close(pref_file);
+}
--- /dev/null
+/*
+ * Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
+ * Copyright (C) 1999-2007 Colin Leroy <colin@colino.net>
+ * and the Claws Mail Team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef SPAMREPORTPREFS_H
+#define SPAMREPORTPREFS_H
+
+#include <glib.h>
+
+#include "procmsg.h"
+
+#define SPAM_REPORT_USERAGENT "Claws Mail SpamReport plugin "
+
+typedef struct _SpamReportPrefs SpamReportPrefs;
+
+typedef enum {
+ INTF_SIGNALSPAM,
+ INTF_SPAMCOP,
+ INTF_DEBIANSPAM,
+ INTF_LAST
+} InterfaceId;
+
+typedef enum {
+ INTF_HTTP,
+ INTF_HTTP_AUTH,
+ INTF_MAIL,
+ INTF_HTTP_GET,
+ INTF_NULL
+} InterfaceType;
+
+typedef struct _ReportInterface {
+ gchar *name;
+ InterfaceType type;
+ gchar *url;
+ gchar *body;
+ gboolean (*should_report)(MsgInfo *info);
+} ReportInterface;
+
+extern ReportInterface spam_interfaces[];
+
+struct _SpamReportPrefs
+{
+ gboolean enabled[INTF_LAST];
+ gchar *user[INTF_LAST];
+ gchar *pass[INTF_LAST];
+};
+
+extern SpamReportPrefs spamreport_prefs;
+
+void spamreport_prefs_init(void);
+void spamreport_prefs_done(void);
+
+#endif
--- /dev/null
+.deps
+.libs
+Makefile
+Makefile.in
+*.la
+*.lo
+*.o
--- /dev/null
+EXTRA_DIST = claws.def plugin.def version.rc
+
+if OS_WIN32
+
+LTRCCOMPILE = $(LIBTOOL) --mode=compile --tag=RC $(RC) \
+ `echo $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) | \
+ sed -e 's/-I/--include-dir /g;s/-D/--define /g'`
+
+%.lo : %.rc
+ $(LTRCCOMPILE) -i $< -o $@
+
+plugin_res = version.lo
+plugin_res_ldflag = -Wl,.libs/version.o
+
+export_symbols = -export-symbols $(srcdir)/plugin.def
+
+plugin_deps = libclaws.a $(plugin_res) plugin.def
+
+libclaws.a: claws.def
+ $(DLLTOOL) --output-lib $@ --def $<
+
+plugin_ldadd = -L. -lclaws
+
+else
+plugin_res =
+plugin_res_ldflag =
+export_symbols =
+plugin_deps =
+plugin_ldadd =
+endif
+
+if PLATFORM_WIN32
+no_undefined = -no-undefined
+else
+no_undefined =
+endif
+
+if CYGWIN
+cygwin_export_lib = -L$(top_builddir)/src -lclaws-mail
+else
+cygwin_export_lib =
+endif
+
+plugindir = $(pkglibdir)/plugins
+
+plugin_LTLIBRARIES = tnef_parse.la
+
+tnef_parse_la_SOURCES = \
+ tnef_parse.c \
+ tnef_dump.c \
+ tnef_dump.h \
+ ytnef.c \
+ gettext.h
+
+tnef_parse_la_LDFLAGS = \
+ $(plugin_res_ldflag) $(no_undefined) $(export_symbols) \
+ -avoid-version -module \
+ $(GTK_LIBS)
+
+tnef_parse_la_DEPENDENCIES = $(plugin_deps)
+
+tnef_parse_la_LIBADD = $(plugin_ldadd) $(cygwin_export_lib) \
+ $(GTK_LIBS)
+
+noinst_HEADERS = \
+ mapidefs.h \
+ mapi.h \
+ mapitags.h \
+ tnef_dump.h \
+ tnef-errors.h \
+ tnef-types.h \
+ ytnef.h
+
+INCLUDES = \
+ -I$(top_srcdir)/src \
+ -I$(top_srcdir)/src/common \
+ -I$(top_builddir)/src/common \
+ -I$(top_srcdir)/src/gtk
+
+AM_CPPFLAGS = \
+ -Wall \
+ $(CLAWS_MAIL_CFLAGS) \
+ $(GLIB_CFLAGS) \
+ $(GTK_CFLAGS) \
+ -DLOCALEDIR=\""$(localedir)"\"
--- /dev/null
+LIBRARY CLAWS-MAIL.EXE
+EXPORTS
+get_locale_dir
+check_plugin_version
+claws_unlink
+debug_get_mode
+debug_print_real
+debug_srcname
+get_mime_tmp_dir
+get_tmpfile_in_dir
+procmime_decode_content
+procmime_get_media_type
+procmime_get_mime_type
+procmime_mimeinfo_free_all
+procmime_mimeinfo_new
+procmime_mimeparser_register
+procmime_mimeparser_unregister
--- /dev/null
+#define MV_FLAG 0x1000 /* Multi-value flag */
+
+#define PT_UNSPECIFIED ((ULONG) 0) /* (Reserved for interface use) type doesn't matter to caller */
+#define PT_NULL ((ULONG) 1) /* NULL property value */
+#define PT_I2 ((ULONG) 2) /* Signed 16-bit value */
+#define PT_LONG ((ULONG) 3) /* Signed 32-bit value */
+#define PT_R4 ((ULONG) 4) /* 4-byte floating point */
+#define PT_DOUBLE ((ULONG) 5) /* Floating point double */
+#define PT_CURRENCY ((ULONG) 6) /* Signed 64-bit int (decimal w/ 4 digits right of decimal pt) */
+#define PT_APPTIME ((ULONG) 7) /* Application time */
+#define PT_ERROR ((ULONG) 10) /* 32-bit error value */
+#define PT_BOOLEAN ((ULONG) 11) /* 16-bit boolean (non-zero true) */
+#define PT_OBJECT ((ULONG) 13) /* Embedded object in a property */
+#define PT_I8 ((ULONG) 20) /* 8-byte signed integer */
+#define PT_STRING8 ((ULONG) 30) /* Null terminated 8-bit character string */
+#define PT_UNICODE ((ULONG) 31) /* Null terminated Unicode string */
+#define PT_SYSTIME ((ULONG) 64) /* FILETIME 64-bit int w/ number of 100ns periods since Jan 1,1601 */
+#define PT_CLSID ((ULONG) 72) /* OLE GUID */
+#define PT_BINARY ((ULONG) 258) /* Uninterpreted (counted byte array) */
+
+#define PROP_TYPE_MASK ((ULONG)0x0000FFFF) /* Mask for Property type */
+#define PROP_TYPE(ulPropTag) (((ULONG)(ulPropTag))&PROP_TYPE_MASK)
+#define PROP_ID(ulPropTag) (((ULONG)(ulPropTag))>>16)
+#define PROP_TAG(ulPropType,ulPropID) ((((ULONG)(ulPropID))<<16)|((ULONG)(ulPropType)))
+#define PROP_ID_NULL 0
+#define PROP_ID_INVALID 0xFFFF
+#define PR_NULL PROP_TAG( PT_NULL, PROP_ID_NULL)
+
+#define MAPI_UNDEFINED ((variableLength*)-1)
--- /dev/null
+#ifndef MAPIDEFS_H
+#define MAPIDEFS_H
+
+#define PR_ACKNOWLEDGEMENT_MODE 0x0001
+#define PR_ALTERNATE_RECIPIENT_ALLOWED 0x0002
+#define PR_AUTHORIZING_USERS 0x0003
+#define PR_AUTO_FORWARD_COMMENT 0x0004
+#define PR_AUTO_FORWARDED 0x0005
+#define PR_CONTENT_CONFIDENTIALITY_ALGORITHM_ID 0x0006
+#define PR_CONTENT_CORRELATOR 0x0007
+#define PR_CONTENT_IDENTIFIER 0x0008
+#define PR_CONTENT_LENGTH 0x0009
+#define PR_CONTENT_RETURN_REQUESTED 0x000A
+#define PR_CONVERSATION_KEY 0x000B
+#define PR_CONVERSION_EITS 0x000C
+#define PR_CONVERSION_WITH_LOSS_PROHIBITED 0x000D
+#define PR_CONVERTED_EITS 0x000E
+#define PR_DEFERRED_DELIVERY_TIME 0x000F
+#define PR_DELIVER_TIME 0x0010
+#define PR_DISCARD_REASON 0x0011
+#define PR_DISCLOSURE_OF_RECIPIENTS 0x0012
+#define PR_DL_EXPANSION_HISTORY 0x0013
+#define PR_DL_EXPANSION_PROHIBITED 0x0014
+#define PR_EXPIRY_TIME 0x0015
+#define PR_IMPLICIT_CONVERSION_PROHIBITED 0x0016
+#define PR_IMPORTANCE 0x0017
+#define PR_IPM_ID 0x0018
+#define PR_LATEST_DELIVERY_TIME 0x0019
+#define PR_MESSAGE_CLASS 0x001A
+#define PR_MESSAGE_DELIVERY_ID 0x001B
+#define PR_MESSAGE_SECURITY_LABEL 0x001E
+#define PR_OBSOLETED_IPMS 0x001F
+#define PR_ORIGINALLY_INTENDED_RECIPIENT_NAME 0x0020
+#define PR_ORIGINAL_EITS 0x0021
+#define PR_ORIGINATOR_CERTIFICATE 0x0022
+#define PR_ORIGINATOR_DELIVERY_REPORT_REQUESTED 0x0023
+#define PR_ORIGINATOR_RETURN_ADDRESS 0x0024
+#define PR_PARENT_KEY 0x0025
+#define PR_PRIORITY 0x0026
+#define PR_ORIGIN_CHECK 0x0027
+#define PR_PROOF_OF_SUBMISSION_REQUESTED 0x0028
+#define PR_READ_RECEIPT_REQUESTED 0x0029
+#define PR_RECEIPT_TIME 0x002A
+#define PR_RECIPIENT_REASSIGNMENT_PROHIBITED 0x002B
+#define PR_REDIRECTION_HISTORY 0x002C
+#define PR_RELATED_IPMS 0x002D
+#define PR_ORIGINAL_SENSITIVITY 0x002E
+#define PR_LANGUAGES 0x002F
+#define PR_REPLY_TIME 0x0030
+#define PR_REPORT_TAG 0x0031
+#define PR_REPORT_TIME 0x0032
+#define PR_RETURNED_IPM 0x0033
+#define PR_SECURITY 0x0034
+#define PR_INCOMPLETE_COPY 0x0035
+#define PR_SENSITIVITY 0x0036
+#define PR_SUBJECT 0x0037
+#define PR_SUBJECT_IPM 0x0038
+#define PR_CLIENT_SUBMIT_TIME 0x0039
+#define PR_REPORT_NAME 0x003A
+#define PR_SENT_REPRESENTING_SEARCH_KEY 0x003B
+#define PR_X400_CONTENT_TYPE 0x003C
+#define PR_SUBJECT_PREFIX 0x003D
+#define PR_NON_RECEIPT_REASON 0x003E
+#define PR_RECEIVED_BY_ENTRYID 0x003F
+#define PR_RECEIVED_BY_NAME 0x0040
+#define PR_SENT_REPRESENTING_ENTRYID 0x0041
+#define PR_SENT_REPRESENTING_NAME 0x0042
+#define PR_RCVD_REPRESENTING_ENTRYID 0x0043
+#define PR_RCVD_REPRESENTING_NAME 0x0044
+#define PR_REPORT_ENTRYID 0x0045
+#define PR_READ_RECEIPT_ENTRYID 0x0046
+#define PR_MESSAGE_SUBMISSION_ID 0x0047
+#define PR_PROVIDER_SUBMIT_TIME 0x0048
+#define PR_ORIGINAL_SUBJECT 0x0049
+#define PR_DISC_VAL 0x004A
+#define PR_ORIG_MESSAGE_CLASS 0x004B
+#define PR_ORIGINAL_AUTHOR_ENTRYID 0x004C
+#define PR_ORIGINAL_AUTHOR_NAME 0x004D
+#define PR_ORIGINAL_SUBMIT_TIME 0x004E
+#define PR_REPLY_RECIPIENT_ENTRIES 0x004F
+#define PR_REPLY_RECIPIENT_NAMES 0x0050
+#define PR_RECEIVED_BY_SEARCH_KEY 0x0051
+#define PR_RCVD_REPRESENTING_SEARCH_KEY 0x0052
+#define PR_READ_RECEIPT_SEARCH_KEY 0x0053
+#define PR_REPORT_SEARCH_KEY 0x0054
+#define PR_ORIGINAL_DELIVERY_TIME 0x0055
+#define PR_ORIGINAL_AUTHOR_SEARCH_KEY 0x0056
+#define PR_MESSAGE_TO_ME 0x0057
+#define PR_MESSAGE_CC_ME 0x0058
+#define PR_MESSAGE_RECIP_ME 0x0059
+#define PR_ORIGINAL_SENDER_NAME 0x005A
+#define PR_ORIGINAL_SENDER_ENTRYID 0x005B
+#define PR_ORIGINAL_SENDER_SEARCH_KEY 0x005C
+#define PR_ORIGINAL_SENT_REPRESENTING_NAME 0x005D
+#define PR_ORIGINAL_SENT_REPRESENTING_ENTRYID 0x005E
+#define PR_ORIGINAL_SENT_REPRESENTING_SEARCH_KEY 0x005F
+#define PR_START_DATE 0x0060
+#define PR_END_DATE 0x0061
+#define PR_OWNER_APPT_ID 0x0062
+#define PR_RESPONSE_REQUESTED 0x0063
+#define PR_SENT_REPRESENTING_ADDRTYPE 0x0064
+#define PR_SENT_REPRESENTING_EMAIL_ADDRESS 0x0065
+#define PR_ORIGINAL_SENDER_ADDRTYPE 0x0066
+#define PR_ORIGINAL_SENDER_EMAIL_ADDRESS 0x0067
+#define PR_ORIGINAL_SENT_REPRESENTING_ADDRTYPE 0x0068
+#define PR_ORIGINAL_SENT_REPRESENTING_EMAIL_ADDRESS 0x0069
+#define PR_CONVERSATION_TOPIC 0x0070
+#define PR_CONVERSATION_INDEX 0x0071
+#define PR_ORIGINAL_DISPLAY_BCC 0x0072
+#define PR_ORIGINAL_DISPLAY_CC 0x0073
+#define PR_ORIGINAL_DISPLAY_TO 0x0074
+#define PR_RECEIVED_BY_ADDRTYPE 0x0075
+#define PR_RECEIVED_BY_EMAIL_ADDRESS 0x0076
+#define PR_RCVD_REPRESENTING_ADDRTYPE 0x0077
+#define PR_RCVD_REPRESENTING_EMAIL_ADDRESS 0x0078
+#define PR_ORIGINAL_AUTHOR_ADDRTYPE 0x0079
+#define PR_ORIGINAL_AUTHOR_EMAIL_ADDRESS 0x007A
+#define PR_ORIGINALLY_INTENDED_RECIP_ADDRTYPE 0x007B
+#define PR_ORIGINALLY_INTENDED_RECIP_EMAIL_ADDRESS 0x007C
+#define PR_TRANSPORT_MESSAGE_HEADERS 0x007D
+#define PR_DELEGATION 0x007E
+#define PR_TNEF_CORRELATION_KEY 0x007F
+#define PR_BODY 0x1000
+#define PR_REPORT_TEXT 0x1001
+#define PR_ORIGINATOR_AND_DL_EXPANSION_HISTORY 0x1002
+#define PR_REPORTING_DL_NAME 0x1003
+#define PR_REPORTING_MTA_CERTIFICATE 0x1004
+#define PR_RTF_SYNC_BODY_CRC 0x1006
+#define PR_RTF_SYNC_BODY_COUNT 0x1007
+#define PR_RTF_SYNC_BODY_TAG 0x1008
+#define PR_RTF_COMPRESSED 0x1009
+#define PR_RTF_SYNC_PREFIX_COUNT 0x1010
+#define PR_RTF_SYNC_TRAILING_COUNT 0x1011
+#define PR_ORIGINALLY_INTENDED_RECIP_ENTRYID 0x1012
+#define PR_CONTENT_INTEGRITY_CHECK 0x0C00
+#define PR_EXPLICIT_CONVERSION 0x0C01
+#define PR_IPM_RETURN_REQUESTED 0x0C02
+#define PR_MESSAGE_TOKEN 0x0C03
+#define PR_NDR_REASON_CODE 0x0C04
+#define PR_NDR_DIAG_CODE 0x0C05
+#define PR_NON_RECEIPT_NOTIFICATION_REQUESTED 0x0C06
+#define PR_DELIVERY_POINT 0x0C07
+
+#define PR_ORIGINATOR_NON_DELIVERY_REPORT_REQUESTED 0x0C08
+#define PR_ORIGINATOR_REQUESTED_ALTERNATE_RECIPIENT 0x0C09
+#define PR_PHYSICAL_DELIVERY_BUREAU_FAX_DELIVERY 0x0C0A
+#define PR_PHYSICAL_DELIVERY_MODE 0x0C0B
+#define PR_PHYSICAL_DELIVERY_REPORT_REQUEST 0x0C0C
+#define PR_PHYSICAL_FORWARDING_ADDRESS 0x0C0D
+#define PR_PHYSICAL_FORWARDING_ADDRESS_REQUESTED 0x0C0E
+#define PR_PHYSICAL_FORWARDING_PROHIBITED 0x0C0F
+#define PR_PHYSICAL_RENDITION_ATTRIBUTES 0x0C10
+#define PR_PROOF_OF_DELIVERY 0x0C11
+#define PR_PROOF_OF_DELIVERY_REQUESTED 0x0C12
+#define PR_RECIPIENT_CERTIFICATE 0x0C13
+#define PR_RECIPIENT_NUMBER_FOR_ADVICE 0x0C14
+#define PR_RECIPIENT_TYPE 0x0C15
+#define PR_REGISTERED_MAIL_TYPE 0x0C16
+#define PR_REPLY_REQUESTED 0x0C17
+#define PR_REQUESTED_DELIVERY_METHOD 0x0C18
+#define PR_SENDER_ENTRYID 0x0C19
+#define PR_SENDER_NAME 0x0C1A
+#define PR_SUPPLEMENTARY_INFO 0x0C1B
+#define PR_TYPE_OF_MTS_USER 0x0C1C
+#define PR_SENDER_SEARCH_KEY 0x0C1D
+#define PR_SENDER_ADDRTYPE 0x0C1E
+#define PR_SENDER_EMAIL_ADDRESS 0x0C1F
+#define PR_CURRENT_VERSION 0x0E00
+#define PR_DELETE_AFTER_SUBMIT 0x0E01
+#define PR_DISPLAY_BCC 0x0E02
+#define PR_DISPLAY_CC 0x0E03
+#define PR_DISPLAY_TO 0x0E04
+#define PR_PARENT_DISPLAY 0x0E05
+#define PR_MESSAGE_DELIVERY_TIME 0x0E06
+#define PR_MESSAGE_FLAGS 0x0E07
+#define PR_MESSAGE_SIZE 0x0E08
+#define PR_PARENT_ENTRYID 0x0E09
+#define PR_SENTMAIL_ENTRYID 0x0E0A
+#define PR_CORRELATE 0x0E0C
+#define PR_CORRELATE_MTSID 0x0E0D
+#define PR_DISCRETE_VALUES 0x0E0E
+#define PR_RESPONSIBILITY 0x0E0F
+#define PR_SPOOLER_STATUS 0x0E10
+#define PR_TRANSPORT_STATUS 0x0E11
+#define PR_MESSAGE_RECIPIENTS 0x0E12
+#define PR_MESSAGE_ATTACHMENTS 0x0E13
+#define PR_SUBMIT_FLAGS 0x0E14
+#define PR_RECIPIENT_STATUS 0x0E15
+#define PR_TRANSPORT_KEY 0x0E16
+#define PR_MSG_STATUS 0x0E17
+#define PR_MESSAGE_DOWNLOAD_TIME 0x0E18
+#define PR_CREATION_VERSION 0x0E19
+#define PR_MODIFY_VERSION 0x0E1A
+#define PR_HASATTACH 0x0E1B
+#define PR_BODY_CRC 0x0E1C
+#define PR_NORMALIZED_SUBJECT 0x0E1D
+#define PR_RTF_IN_SYNC 0x0E1F
+#define PR_ATTACH_SIZE 0x0E20
+#define PR_ATTACH_NUM 0x0E21
+#define PR_PREPROCESS 0x0E22
+#define PR_ORIGINATING_MTA_CERTIFICATE 0x0E25
+#define PR_PROOF_OF_SUBMISSION 0x0E26
+#define PR_ENTRYID 0x0FFF
+#define PR_OBJECT_TYPE 0x0FFE
+#define PR_ICON 0x0FFD
+#define PR_MINI_ICON 0x0FFC
+#define PR_STORE_ENTRYID 0x0FFB
+#define PR_STORE_RECORD_KEY 0x0FFA
+#define PR_RECORD_KEY 0x0FF9
+#define PR_MAPPING_SIGNATURE 0x0FF8
+#define PR_ACCESS_LEVEL 0x0FF7
+#define PR_INSTANCE_KEY 0x0FF6
+#define PR_ROW_TYPE 0x0FF5
+#define PR_ACCESS 0x0FF4
+#define PR_ROWID 0x3000
+#define PR_DISPLAY_NAME 0x3001
+#define PR_ADDRTYPE 0x3002
+#define PR_EMAIL_ADDRESS 0x3003
+#define PR_COMMENT 0x3004
+#define PR_DEPTH 0x3005
+#define PR_PROVIDER_DISPLAY 0x3006
+#define PR_CREATION_TIME 0x3007
+#define PR_LAST_MODIFICATION_TIME 0x3008
+#define PR_RESOURCE_FLAGS 0x3009
+#define PR_PROVIDER_DLL_NAME 0x300A
+#define PR_SEARCH_KEY 0x300B
+#define PR_PROVIDER_UID 0x300C
+#define PR_PROVIDER_ORDINAL 0x300D
+#define PR_FORM_VERSION 0x3301
+#define PR_FORM_CLSID 0x3302
+#define PR_FORM_CONTACT_NAME 0x3303
+#define PR_FORM_CATEGORY 0x3304
+#define PR_FORM_CATEGORY_SUB 0x3305
+#define PR_FORM_HOST_MAP 0x3306
+#define PR_FORM_HIDDEN 0x3307
+#define PR_FORM_DESIGNER_NAME 0x3308
+#define PR_FORM_DESIGNER_GUID 0x3309
+#define PR_FORM_MESSAGE_BEHAVIOR 0x330A
+#define PR_DEFAULT_STORE 0x3400
+#define PR_STORE_SUPPORT_MASK 0x340D
+#define PR_STORE_STATE 0x340E
+#define PR_IPM_SUBTREE_SEARCH_KEY 0x3410
+#define PR_IPM_OUTBOX_SEARCH_KEY 0x3411
+#define PR_IPM_WASTEBASKET_SEARCH_KEY 0x3412
+#define PR_IPM_SENTMAIL_SEARCH_KEY 0x3413
+#define PR_MDB_PROVIDER 0x3414
+#define PR_RECEIVE_FOLDER_SETTINGS 0x3415
+#define PR_VALID_FOLDER_MASK 0x35DF
+#define PR_IPM_SUBTREE_ENTRYID 0x35E0
+#define PR_IPM_OUTBOX_ENTRYID 0x35E2
+#define PR_IPM_WASTEBASKET_ENTRYID 0x35E3
+#define PR_IPM_SENTMAIL_ENTRYID 0x35E4
+#define PR_VIEWS_ENTRYID 0x35E5
+#define PR_COMMON_VIEWS_ENTRYID 0x35E6
+#define PR_FINDER_ENTRYID 0x35E7
+#define PR_CONTAINER_FLAGS 0x3600
+#define PR_FOLDER_TYPE 0x3601
+#define PR_CONTENT_COUNT 0x3602
+#define PR_CONTENT_UNREAD 0x3603
+#define PR_CREATE_TEMPLATES 0x3604
+#define PR_DETAILS_TABLE 0x3605
+#define PR_SEARCH 0x3607
+#define PR_SELECTABLE 0x3609
+#define PR_SUBFOLDERS 0x360A
+#define PR_STATUS 0x360B
+#define PR_ANR 0x360C
+#define PR_CONTENTS_SORT_ORDER 0x360D
+#define PR_CONTAINER_HIERARCHY 0x360E
+#define PR_CONTAINER_CONTENTS 0x360F
+#define PR_FOLDER_ASSOCIATED_CONTENTS 0x3610
+#define PR_DEF_CREATE_DL 0x3611
+#define PR_DEF_CREATE_MAILUSER 0x3612
+#define PR_CONTAINER_CLASS 0x3613
+#define PR_CONTAINER_MODIFY_VERSION 0x3614
+#define PR_AB_PROVIDER_ID 0x3615
+#define PR_DEFAULT_VIEW_ENTRYID 0x3616
+#define PR_ASSOC_CONTENT_COUNT 0x3617
+#define PR_ATTACHMENT_X400_PARAMETERS 0x3700
+#define PR_ATTACH_DATA_OBJ 0x3701
+#define PR_ATTACH_ENCODING 0x3702
+#define PR_ATTACH_EXTENSION 0x3703
+#define PR_ATTACH_FILENAME 0x3704
+#define PR_ATTACH_METHOD 0x3705
+#define PR_ATTACH_LONG_FILENAME 0x3707
+#define PR_ATTACH_PATHNAME 0x3708
+#define PR_ATTACH_RENDERING 0x3709
+#define PR_ATTACH_TAG 0x370A
+#define PR_RENDERING_POSITION 0x370B
+#define PR_ATTACH_TRANSPORT_NAME 0x370C
+#define PR_ATTACH_LONG_PATHNAME 0x370D
+#define PR_ATTACH_MIME_TAG 0x370E
+#define PR_ATTACH_ADDITIONAL_INFO 0x370F
+#define PR_DISPLAY_TYPE 0x3900
+#define PR_TEMPLATEID 0x3902
+#define PR_PRIMARY_CAPABILITY 0x3904
+#define PR_7BIT_DISPLAY_NAME 0x39FF
+#define PR_ACCOUNT 0x3A00
+#define PR_ALTERNATE_RECIPIENT 0x3A01
+#define PR_CALLBACK_TELEPHONE_NUMBER 0x3A02
+#define PR_CONVERSION_PROHIBITED 0x3A03
+#define PR_DISCLOSE_RECIPIENTS 0x3A04
+#define PR_GENERATION 0x3A05
+#define PR_GIVEN_NAME 0x3A06
+#define PR_GOVERNMENT_ID_NUMBER 0x3A07
+#define PR_BUSINESS_TELEPHONE_NUMBER 0x3A08
+#define PR_HOME_TELEPHONE_NUMBER 0x3A09
+#define PR_INITIALS 0x3A0A
+#define PR_KEYWORD 0x3A0B
+#define PR_LANGUAGE 0x3A0C
+#define PR_LOCATION 0x3A0D
+#define PR_MAIL_PERMISSION 0x3A0E
+#define PR_MHS_COMMON_NAME 0x3A0F
+#define PR_ORGANIZATIONAL_ID_NUMBER 0x3A10
+#define PR_SURNAME 0x3A11
+#define PR_ORIGINAL_ENTRYID 0x3A12
+#define PR_ORIGINAL_DISPLAY_NAME 0x3A13
+#define PR_ORIGINAL_SEARCH_KEY 0x3A14
+#define PR_POSTAL_ADDRESS 0x3A15
+#define PR_COMPANY_NAME 0x3A16
+#define PR_TITLE 0x3A17
+#define PR_DEPARTMENT_NAME 0x3A18
+#define PR_OFFICE_LOCATION 0x3A19
+#define PR_PRIMARY_TELEPHONE_NUMBER 0x3A1A
+#define PR_BUSINESS2_TELEPHONE_NUMBER 0x3A1B
+#define PR_MOBILE_TELEPHONE_NUMBER 0x3A1C
+#define PR_RADIO_TELEPHONE_NUMBER 0x3A1D
+#define PR_CAR_TELEPHONE_NUMBER 0x3A1E
+#define PR_OTHER_TELEPHONE_NUMBER 0x3A1F
+#define PR_TRANSMITABLE_DISPLAY_NAME 0x3A20
+#define PR_PAGER_TELEPHONE_NUMBER 0x3A21
+#define PR_USER_CERTIFICATE 0x3A22
+#define PR_PRIMARY_FAX_NUMBER 0x3A23
+#define PR_BUSINESS_FAX_NUMBER 0x3A24
+#define PR_HOME_FAX_NUMBER 0x3A25
+#define PR_COUNTRY 0x3A26
+#define PR_LOCALITY 0x3A27
+#define PR_STATE_OR_PROVINCE 0x3A28
+#define PR_STREET_ADDRESS 0x3A29
+#define PR_POSTAL_CODE 0x3A2A
+#define PR_POST_OFFICE_BOX 0x3A2B
+#define PR_TELEX_NUMBER 0x3A2C
+#define PR_ISDN_NUMBER 0x3A2D
+#define PR_ASSISTANT_TELEPHONE_NUMBER 0x3A2E
+#define PR_HOME2_TELEPHONE_NUMBER 0x3A2F
+#define PR_ASSISTANT 0x3A30
+#define PR_SEND_RICH_INFO 0x3A40
+#define PR_WEDDING_ANNIVERSARY 0x3A41
+#define PR_BIRTHDAY 0x3A42
+#define PR_HOBBIES 0x3A43
+#define PR_MIDDLE_NAME 0x3A44
+#define PR_DISPLAY_NAME_PREFIX 0x3A45
+#define PR_PROFESSION 0x3A46
+#define PR_PREFERRED_BY_NAME 0x3A47
+#define PR_SPOUSE_NAME 0x3A48
+#define PR_COMPUTER_NETWORK_NAME 0x3A49
+#define PR_CUSTOMER_ID 0x3A4A
+#define PR_TTYTDD_PHONE_NUMBER 0x3A4B
+#define PR_FTP_SITE 0x3A4C
+#define PR_GENDER 0x3A4D
+#define PR_MANAGER_NAME 0x3A4E
+#define PR_NICKNAME 0x3A4F
+#define PR_PERSONAL_HOME_PAGE 0x3A50
+#define PR_BUSINESS_HOME_PAGE 0x3A51
+#define PR_CONTACT_VERSION 0x3A52
+#define PR_CONTACT_ENTRYIDS 0x3A53
+#define PR_CONTACT_ADDRTYPES 0x3A54
+#define PR_CONTACT_DEFAULT_ADDRESS_INDEX 0x3A55
+#define PR_CONTACT_EMAIL_ADDRESSES 0x3A56
+#define PR_COMPANY_MAIN_PHONE_NUMBER 0x3A57
+#define PR_CHILDRENS_NAMES 0x3A58
+#define PR_HOME_ADDRESS_CITY 0x3A59
+#define PR_HOME_ADDRESS_COUNTRY 0x3A5A
+#define PR_HOME_ADDRESS_POSTAL_CODE 0x3A5B
+#define PR_HOME_ADDRESS_STATE_OR_PROVINCE 0x3A5C
+#define PR_HOME_ADDRESS_STREET 0x3A5D
+#define PR_HOME_ADDRESS_POST_OFFICE_BOX 0x3A5E
+#define PR_OTHER_ADDRESS_CITY 0x3A5F
+#define PR_OTHER_ADDRESS_COUNTRY 0x3A60
+#define PR_OTHER_ADDRESS_POSTAL_CODE 0x3A61
+#define PR_OTHER_ADDRESS_STATE_OR_PROVINCE 0x3A62
+#define PR_OTHER_ADDRESS_STREET 0x3A63
+#define PR_OTHER_ADDRESS_POST_OFFICE_BOX 0x3A64
+#define PR_STORE_PROVIDERS 0x3D00
+#define PR_AB_PROVIDERS 0x3D01
+#define PR_TRANSPORT_PROVIDERS 0x3D02
+#define PR_DEFAULT_PROFILE 0x3D04
+#define PR_AB_SEARCH_PATH 0x3D05
+#define PR_AB_DEFAULT_DIR 0x3D06
+#define PR_AB_DEFAULT_PAB 0x3D07
+#define PR_FILTERING_HOOKS 0x3D08
+#define PR_SERVICE_NAME 0x3D09
+#define PR_SERVICE_DLL_NAME 0x3D0A
+#define PR_SERVICE_ENTRY_NAME 0x3D0B
+#define PR_SERVICE_UID 0x3D0C
+#define PR_SERVICE_EXTRA_UIDS 0x3D0D
+#define PR_SERVICES 0x3D0E
+#define PR_SERVICE_SUPPORT_FILES 0x3D0F
+#define PR_SERVICE_DELETE_FILES 0x3D10
+#define PR_AB_SEARCH_PATH_UPDATE 0x3D11
+#define PR_PROFILE_NAME 0x3D12
+#define PR_IDENTITY_DISPLAY 0x3E00
+#define PR_IDENTITY_ENTRYID 0x3E01
+#define PR_RESOURCE_METHODS 0x3E02
+#define PR_RESOURCE_TYPE 0x3E03
+#define PR_STATUS_CODE 0x3E04
+#define PR_IDENTITY_SEARCH_KEY 0x3E05
+#define PR_OWN_STORE_ENTRYID 0x3E06
+#define PR_RESOURCE_PATH 0x3E07
+#define PR_STATUS_STRING 0x3E08
+#define PR_X400_DEFERRED_DELIVERY_CANCEL 0x3E09
+#define PR_HEADER_FOLDER_ENTRYID 0x3E0A
+#define PR_REMOTE_PROGRESS 0x3E0B
+#define PR_REMOTE_PROGRESS_TEXT 0x3E0C
+#define PR_REMOTE_VALIDATE_OK 0x3E0D
+#define PR_CONTROL_FLAGS 0x3F00
+#define PR_CONTROL_STRUCTURE 0x3F01
+#define PR_CONTROL_TYPE 0x3F02
+#define PR_DELTAX 0x3F03
+#define PR_DELTAY 0x3F04
+#define PR_XPOS 0x3F05
+#define PR_YPOS 0x3F06
+#define PR_CONTROL_ID 0x3F07
+#define PR_INITIAL_DETAILS_PANE 0x3F08
+
+/*
+ * Secure property id range
+ */
+
+#define PROP_ID_SECURE_MIN 0x67F0
+#define PROP_ID_SECURE_MAX 0x67FF
+
+
+#endif /* MAPIDEFS_H */
--- /dev/null
+#ifndef MAPITAGS_H
+#define MAPITAGS_H
+
+#define MAPIMACRO(x) {x, #x}
+typedef struct {
+ unsigned int id;
+ char name[128];
+} MAPIPropertyTagList;
+
+
+MAPIPropertyTagList MPList[] = {
+ MAPIMACRO(PR_ACKNOWLEDGEMENT_MODE ),
+ MAPIMACRO(PR_ALTERNATE_RECIPIENT_ALLOWED ),
+ MAPIMACRO(PR_AUTHORIZING_USERS ),
+ MAPIMACRO(PR_AUTO_FORWARD_COMMENT ),
+ MAPIMACRO(PR_AUTO_FORWARDED ),
+ MAPIMACRO(PR_CONTENT_CONFIDENTIALITY_ALGORITHM_ID ),
+ MAPIMACRO(PR_CONTENT_CORRELATOR ),
+ MAPIMACRO(PR_CONTENT_IDENTIFIER ),
+ MAPIMACRO(PR_CONTENT_LENGTH ),
+ MAPIMACRO(PR_CONTENT_RETURN_REQUESTED ),
+ MAPIMACRO(PR_CONVERSATION_KEY ),
+ MAPIMACRO(PR_CONVERSION_EITS ),
+ MAPIMACRO(PR_CONVERSION_WITH_LOSS_PROHIBITED ),
+ MAPIMACRO(PR_CONVERTED_EITS ),
+ MAPIMACRO(PR_DEFERRED_DELIVERY_TIME ),
+ MAPIMACRO(PR_DELIVER_TIME ),
+ MAPIMACRO(PR_DISCARD_REASON ),
+ MAPIMACRO(PR_DISCLOSURE_OF_RECIPIENTS ),
+ MAPIMACRO(PR_DL_EXPANSION_HISTORY ),
+ MAPIMACRO(PR_DL_EXPANSION_PROHIBITED ),
+ MAPIMACRO(PR_EXPIRY_TIME ),
+ MAPIMACRO(PR_IMPLICIT_CONVERSION_PROHIBITED ),
+ MAPIMACRO(PR_IMPORTANCE ),
+ MAPIMACRO(PR_IPM_ID ),
+ MAPIMACRO(PR_LATEST_DELIVERY_TIME ),
+ MAPIMACRO(PR_MESSAGE_CLASS ),
+ MAPIMACRO(PR_MESSAGE_DELIVERY_ID ),
+ MAPIMACRO(PR_MESSAGE_SECURITY_LABEL ),
+ MAPIMACRO(PR_OBSOLETED_IPMS ),
+ MAPIMACRO(PR_ORIGINALLY_INTENDED_RECIPIENT_NAME ),
+ MAPIMACRO(PR_ORIGINAL_EITS ),
+ MAPIMACRO(PR_ORIGINATOR_CERTIFICATE ),
+ MAPIMACRO(PR_ORIGINATOR_DELIVERY_REPORT_REQUESTED ),
+ MAPIMACRO(PR_ORIGINATOR_RETURN_ADDRESS ),
+ MAPIMACRO(PR_PARENT_KEY ),
+ MAPIMACRO(PR_PRIORITY ),
+ MAPIMACRO(PR_ORIGIN_CHECK ),
+ MAPIMACRO(PR_PROOF_OF_SUBMISSION_REQUESTED ),
+ MAPIMACRO(PR_READ_RECEIPT_REQUESTED ),
+ MAPIMACRO(PR_RECEIPT_TIME ),
+ MAPIMACRO(PR_RECIPIENT_REASSIGNMENT_PROHIBITED ),
+ MAPIMACRO(PR_REDIRECTION_HISTORY ),
+ MAPIMACRO(PR_RELATED_IPMS ),
+ MAPIMACRO(PR_ORIGINAL_SENSITIVITY ),
+ MAPIMACRO(PR_LANGUAGES ),
+ MAPIMACRO(PR_REPLY_TIME ),
+ MAPIMACRO(PR_REPORT_TAG ),
+ MAPIMACRO(PR_REPORT_TIME ),
+ MAPIMACRO(PR_RETURNED_IPM ),
+ MAPIMACRO(PR_SECURITY ),
+ MAPIMACRO(PR_INCOMPLETE_COPY ),
+ MAPIMACRO(PR_SENSITIVITY ),
+ MAPIMACRO(PR_SUBJECT ),
+ MAPIMACRO(PR_SUBJECT_IPM ),
+ MAPIMACRO(PR_CLIENT_SUBMIT_TIME ),
+ MAPIMACRO(PR_REPORT_NAME ),
+ MAPIMACRO(PR_SENT_REPRESENTING_SEARCH_KEY ),
+ MAPIMACRO(PR_X400_CONTENT_TYPE ),
+ MAPIMACRO(PR_SUBJECT_PREFIX ),
+ MAPIMACRO(PR_NON_RECEIPT_REASON ),
+ MAPIMACRO(PR_RECEIVED_BY_ENTRYID ),
+ MAPIMACRO(PR_RECEIVED_BY_NAME ),
+ MAPIMACRO(PR_SENT_REPRESENTING_ENTRYID ),
+ MAPIMACRO(PR_SENT_REPRESENTING_NAME ),
+ MAPIMACRO(PR_RCVD_REPRESENTING_ENTRYID ),
+ MAPIMACRO(PR_RCVD_REPRESENTING_NAME ),
+ MAPIMACRO(PR_REPORT_ENTRYID ),
+ MAPIMACRO(PR_READ_RECEIPT_ENTRYID ),
+ MAPIMACRO(PR_MESSAGE_SUBMISSION_ID ),
+ MAPIMACRO(PR_PROVIDER_SUBMIT_TIME ),
+ MAPIMACRO(PR_ORIGINAL_SUBJECT ),
+ MAPIMACRO(PR_DISC_VAL ),
+ MAPIMACRO(PR_ORIG_MESSAGE_CLASS ),
+ MAPIMACRO(PR_ORIGINAL_AUTHOR_ENTRYID ),
+ MAPIMACRO(PR_ORIGINAL_AUTHOR_NAME ),
+ MAPIMACRO(PR_ORIGINAL_SUBMIT_TIME ),
+ MAPIMACRO(PR_REPLY_RECIPIENT_ENTRIES ),
+ MAPIMACRO(PR_REPLY_RECIPIENT_NAMES ),
+ MAPIMACRO(PR_RECEIVED_BY_SEARCH_KEY ),
+ MAPIMACRO(PR_RCVD_REPRESENTING_SEARCH_KEY ),
+ MAPIMACRO(PR_READ_RECEIPT_SEARCH_KEY ),
+ MAPIMACRO(PR_REPORT_SEARCH_KEY ),
+ MAPIMACRO(PR_ORIGINAL_DELIVERY_TIME ),
+ MAPIMACRO(PR_ORIGINAL_AUTHOR_SEARCH_KEY ),
+ MAPIMACRO(PR_MESSAGE_TO_ME ),
+ MAPIMACRO(PR_MESSAGE_CC_ME ),
+ MAPIMACRO(PR_MESSAGE_RECIP_ME ),
+ MAPIMACRO(PR_ORIGINAL_SENDER_NAME ),
+ MAPIMACRO(PR_ORIGINAL_SENDER_ENTRYID ),
+ MAPIMACRO(PR_ORIGINAL_SENDER_SEARCH_KEY ),
+ MAPIMACRO(PR_ORIGINAL_SENT_REPRESENTING_NAME ),
+ MAPIMACRO(PR_ORIGINAL_SENT_REPRESENTING_ENTRYID ),
+ MAPIMACRO(PR_ORIGINAL_SENT_REPRESENTING_SEARCH_KEY ),
+ MAPIMACRO(PR_START_DATE ),
+ MAPIMACRO(PR_END_DATE ),
+ MAPIMACRO(PR_OWNER_APPT_ID ),
+ MAPIMACRO(PR_RESPONSE_REQUESTED ),
+ MAPIMACRO(PR_SENT_REPRESENTING_ADDRTYPE ),
+ MAPIMACRO(PR_SENT_REPRESENTING_EMAIL_ADDRESS ),
+ MAPIMACRO(PR_ORIGINAL_SENDER_ADDRTYPE ),
+ MAPIMACRO(PR_ORIGINAL_SENDER_EMAIL_ADDRESS ),
+ MAPIMACRO(PR_ORIGINAL_SENT_REPRESENTING_ADDRTYPE ),
+ MAPIMACRO(PR_ORIGINAL_SENT_REPRESENTING_EMAIL_ADDRESS ),
+ MAPIMACRO(PR_CONVERSATION_TOPIC ),
+ MAPIMACRO(PR_CONVERSATION_INDEX ),
+ MAPIMACRO(PR_ORIGINAL_DISPLAY_BCC ),
+ MAPIMACRO(PR_ORIGINAL_DISPLAY_CC ),
+ MAPIMACRO(PR_ORIGINAL_DISPLAY_TO ),
+ MAPIMACRO(PR_RECEIVED_BY_ADDRTYPE ),
+ MAPIMACRO(PR_RECEIVED_BY_EMAIL_ADDRESS ),
+ MAPIMACRO(PR_RCVD_REPRESENTING_ADDRTYPE ),
+ MAPIMACRO(PR_RCVD_REPRESENTING_EMAIL_ADDRESS ),
+ MAPIMACRO(PR_ORIGINAL_AUTHOR_ADDRTYPE ),
+ MAPIMACRO(PR_ORIGINAL_AUTHOR_EMAIL_ADDRESS ),
+ MAPIMACRO(PR_ORIGINALLY_INTENDED_RECIP_ADDRTYPE ),
+ MAPIMACRO(PR_ORIGINALLY_INTENDED_RECIP_EMAIL_ADDRESS ),
+ MAPIMACRO(PR_TRANSPORT_MESSAGE_HEADERS ),
+ MAPIMACRO(PR_DELEGATION ),
+ MAPIMACRO(PR_TNEF_CORRELATION_KEY ),
+ MAPIMACRO(PR_BODY ),
+ MAPIMACRO(PR_REPORT_TEXT ),
+ MAPIMACRO(PR_ORIGINATOR_AND_DL_EXPANSION_HISTORY ),
+ MAPIMACRO(PR_REPORTING_DL_NAME ),
+ MAPIMACRO(PR_REPORTING_MTA_CERTIFICATE ),
+ MAPIMACRO(PR_RTF_SYNC_BODY_CRC ),
+ MAPIMACRO(PR_RTF_SYNC_BODY_COUNT ),
+ MAPIMACRO(PR_RTF_SYNC_BODY_TAG ),
+ MAPIMACRO(PR_RTF_COMPRESSED ),
+ MAPIMACRO(PR_RTF_SYNC_PREFIX_COUNT ),
+ MAPIMACRO(PR_RTF_SYNC_TRAILING_COUNT ),
+ MAPIMACRO(PR_ORIGINALLY_INTENDED_RECIP_ENTRYID ),
+ MAPIMACRO(PR_CONTENT_INTEGRITY_CHECK ),
+ MAPIMACRO(PR_EXPLICIT_CONVERSION ),
+ MAPIMACRO(PR_IPM_RETURN_REQUESTED ),
+ MAPIMACRO(PR_MESSAGE_TOKEN ),
+ MAPIMACRO(PR_NDR_REASON_CODE ),
+ MAPIMACRO(PR_NDR_DIAG_CODE ),
+ MAPIMACRO(PR_NON_RECEIPT_NOTIFICATION_REQUESTED ),
+ MAPIMACRO(PR_DELIVERY_POINT ),
+ MAPIMACRO(PR_ORIGINATOR_NON_DELIVERY_REPORT_REQUESTED ),
+ MAPIMACRO(PR_ORIGINATOR_REQUESTED_ALTERNATE_RECIPIENT ),
+ MAPIMACRO(PR_PHYSICAL_DELIVERY_BUREAU_FAX_DELIVERY ),
+ MAPIMACRO(PR_PHYSICAL_DELIVERY_MODE ),
+ MAPIMACRO(PR_PHYSICAL_DELIVERY_REPORT_REQUEST ),
+ MAPIMACRO(PR_PHYSICAL_FORWARDING_ADDRESS ),
+ MAPIMACRO(PR_PHYSICAL_FORWARDING_ADDRESS_REQUESTED ),
+ MAPIMACRO(PR_PHYSICAL_FORWARDING_PROHIBITED ),
+ MAPIMACRO(PR_PHYSICAL_RENDITION_ATTRIBUTES ),
+ MAPIMACRO(PR_PROOF_OF_DELIVERY ),
+ MAPIMACRO(PR_PROOF_OF_DELIVERY_REQUESTED ),
+ MAPIMACRO(PR_RECIPIENT_CERTIFICATE ),
+ MAPIMACRO(PR_RECIPIENT_NUMBER_FOR_ADVICE ),
+ MAPIMACRO(PR_RECIPIENT_TYPE ),
+ MAPIMACRO(PR_REGISTERED_MAIL_TYPE ),
+ MAPIMACRO(PR_REPLY_REQUESTED ),
+ MAPIMACRO(PR_REQUESTED_DELIVERY_METHOD ),
+ MAPIMACRO(PR_SENDER_ENTRYID ),
+ MAPIMACRO(PR_SENDER_NAME ),
+ MAPIMACRO(PR_SUPPLEMENTARY_INFO ),
+ MAPIMACRO(PR_TYPE_OF_MTS_USER ),
+ MAPIMACRO(PR_SENDER_SEARCH_KEY ),
+ MAPIMACRO(PR_SENDER_ADDRTYPE ),
+ MAPIMACRO(PR_SENDER_EMAIL_ADDRESS ),
+ MAPIMACRO(PR_CURRENT_VERSION ),
+ MAPIMACRO(PR_DELETE_AFTER_SUBMIT ),
+ MAPIMACRO(PR_DISPLAY_BCC ),
+ MAPIMACRO(PR_DISPLAY_CC ),
+ MAPIMACRO(PR_DISPLAY_TO ),
+ MAPIMACRO(PR_PARENT_DISPLAY ),
+ MAPIMACRO(PR_MESSAGE_DELIVERY_TIME ),
+ MAPIMACRO(PR_MESSAGE_FLAGS ),
+ MAPIMACRO(PR_MESSAGE_SIZE ),
+ MAPIMACRO(PR_PARENT_ENTRYID ),
+ MAPIMACRO(PR_SENTMAIL_ENTRYID ),
+ MAPIMACRO(PR_CORRELATE ),
+ MAPIMACRO(PR_CORRELATE_MTSID ),
+ MAPIMACRO(PR_DISCRETE_VALUES ),
+ MAPIMACRO(PR_RESPONSIBILITY ),
+ MAPIMACRO(PR_SPOOLER_STATUS ),
+ MAPIMACRO(PR_TRANSPORT_STATUS ),
+ MAPIMACRO(PR_MESSAGE_RECIPIENTS ),
+ MAPIMACRO(PR_MESSAGE_ATTACHMENTS ),
+ MAPIMACRO(PR_SUBMIT_FLAGS ),
+ MAPIMACRO(PR_RECIPIENT_STATUS ),
+ MAPIMACRO(PR_TRANSPORT_KEY ),
+ MAPIMACRO(PR_MSG_STATUS ),
+ MAPIMACRO(PR_MESSAGE_DOWNLOAD_TIME ),
+ MAPIMACRO(PR_CREATION_VERSION ),
+ MAPIMACRO(PR_MODIFY_VERSION ),
+ MAPIMACRO(PR_HASATTACH ),
+ MAPIMACRO(PR_BODY_CRC ),
+ MAPIMACRO(PR_NORMALIZED_SUBJECT ),
+ MAPIMACRO(PR_RTF_IN_SYNC ),
+ MAPIMACRO(PR_ATTACH_SIZE ),
+ MAPIMACRO(PR_ATTACH_NUM ),
+ MAPIMACRO(PR_PREPROCESS ),
+ MAPIMACRO(PR_ORIGINATING_MTA_CERTIFICATE ),
+ MAPIMACRO(PR_PROOF_OF_SUBMISSION ),
+ MAPIMACRO(PR_ENTRYID ),
+ MAPIMACRO(PR_OBJECT_TYPE ),
+ MAPIMACRO(PR_ICON ),
+ MAPIMACRO(PR_MINI_ICON ),
+ MAPIMACRO(PR_STORE_ENTRYID ),
+ MAPIMACRO(PR_STORE_RECORD_KEY ),
+ MAPIMACRO(PR_RECORD_KEY ),
+ MAPIMACRO(PR_MAPPING_SIGNATURE ),
+ MAPIMACRO(PR_ACCESS_LEVEL ),
+ MAPIMACRO(PR_INSTANCE_KEY ),
+ MAPIMACRO(PR_ROW_TYPE ),
+ MAPIMACRO(PR_ACCESS ),
+ MAPIMACRO(PR_ROWID ),
+ MAPIMACRO(PR_DISPLAY_NAME ),
+ MAPIMACRO(PR_ADDRTYPE ),
+ MAPIMACRO(PR_EMAIL_ADDRESS ),
+ MAPIMACRO(PR_COMMENT ),
+ MAPIMACRO(PR_DEPTH ),
+ MAPIMACRO(PR_PROVIDER_DISPLAY ),
+ MAPIMACRO(PR_CREATION_TIME ),
+ MAPIMACRO(PR_LAST_MODIFICATION_TIME ),
+ MAPIMACRO(PR_RESOURCE_FLAGS ),
+ MAPIMACRO(PR_PROVIDER_DLL_NAME ),
+ MAPIMACRO(PR_SEARCH_KEY ),
+ MAPIMACRO(PR_PROVIDER_UID ),
+ MAPIMACRO(PR_PROVIDER_ORDINAL ),
+ MAPIMACRO(PR_FORM_VERSION ),
+ MAPIMACRO(PR_FORM_CLSID ),
+ MAPIMACRO(PR_FORM_CONTACT_NAME ),
+ MAPIMACRO(PR_FORM_CATEGORY ),
+ MAPIMACRO(PR_FORM_CATEGORY_SUB ),
+ MAPIMACRO(PR_FORM_HOST_MAP ),
+ MAPIMACRO(PR_FORM_HIDDEN ),
+ MAPIMACRO(PR_FORM_DESIGNER_NAME ),
+ MAPIMACRO(PR_FORM_DESIGNER_GUID ),
+ MAPIMACRO(PR_FORM_MESSAGE_BEHAVIOR ),
+ MAPIMACRO(PR_DEFAULT_STORE ),
+ MAPIMACRO(PR_STORE_SUPPORT_MASK ),
+ MAPIMACRO(PR_STORE_STATE ),
+ MAPIMACRO(PR_IPM_SUBTREE_SEARCH_KEY ),
+ MAPIMACRO(PR_IPM_OUTBOX_SEARCH_KEY ),
+ MAPIMACRO(PR_IPM_WASTEBASKET_SEARCH_KEY ),
+ MAPIMACRO(PR_IPM_SENTMAIL_SEARCH_KEY ),
+ MAPIMACRO(PR_MDB_PROVIDER ),
+ MAPIMACRO(PR_RECEIVE_FOLDER_SETTINGS ),
+ MAPIMACRO(PR_VALID_FOLDER_MASK ),
+ MAPIMACRO(PR_IPM_SUBTREE_ENTRYID ),
+ MAPIMACRO(PR_IPM_OUTBOX_ENTRYID ),
+ MAPIMACRO(PR_IPM_WASTEBASKET_ENTRYID ),
+ MAPIMACRO(PR_IPM_SENTMAIL_ENTRYID ),
+ MAPIMACRO(PR_VIEWS_ENTRYID ),
+ MAPIMACRO(PR_COMMON_VIEWS_ENTRYID ),
+ MAPIMACRO(PR_FINDER_ENTRYID ),
+ MAPIMACRO(PR_CONTAINER_FLAGS ),
+ MAPIMACRO(PR_FOLDER_TYPE ),
+ MAPIMACRO(PR_CONTENT_COUNT ),
+ MAPIMACRO(PR_CONTENT_UNREAD ),
+ MAPIMACRO(PR_CREATE_TEMPLATES ),
+ MAPIMACRO(PR_DETAILS_TABLE ),
+ MAPIMACRO(PR_SEARCH ),
+ MAPIMACRO(PR_SELECTABLE ),
+ MAPIMACRO(PR_SUBFOLDERS ),
+ MAPIMACRO(PR_STATUS ),
+ MAPIMACRO(PR_ANR ),
+ MAPIMACRO(PR_CONTENTS_SORT_ORDER ),
+ MAPIMACRO(PR_CONTAINER_HIERARCHY ),
+ MAPIMACRO(PR_CONTAINER_CONTENTS ),
+ MAPIMACRO(PR_FOLDER_ASSOCIATED_CONTENTS ),
+ MAPIMACRO(PR_DEF_CREATE_DL ),
+ MAPIMACRO(PR_DEF_CREATE_MAILUSER ),
+ MAPIMACRO(PR_CONTAINER_CLASS ),
+ MAPIMACRO(PR_CONTAINER_MODIFY_VERSION ),
+ MAPIMACRO(PR_AB_PROVIDER_ID ),
+ MAPIMACRO(PR_DEFAULT_VIEW_ENTRYID ),
+ MAPIMACRO(PR_ASSOC_CONTENT_COUNT ),
+ MAPIMACRO(PR_ATTACHMENT_X400_PARAMETERS ),
+ MAPIMACRO(PR_ATTACH_DATA_OBJ ),
+ MAPIMACRO(PR_ATTACH_ENCODING ),
+ MAPIMACRO(PR_ATTACH_EXTENSION ),
+ MAPIMACRO(PR_ATTACH_FILENAME ),
+ MAPIMACRO(PR_ATTACH_METHOD ),
+ MAPIMACRO(PR_ATTACH_LONG_FILENAME ),
+ MAPIMACRO(PR_ATTACH_PATHNAME ),
+ MAPIMACRO(PR_ATTACH_RENDERING ),
+ MAPIMACRO(PR_ATTACH_TAG ),
+ MAPIMACRO(PR_RENDERING_POSITION ),
+ MAPIMACRO(PR_ATTACH_TRANSPORT_NAME ),
+ MAPIMACRO(PR_ATTACH_LONG_PATHNAME ),
+ MAPIMACRO(PR_ATTACH_MIME_TAG ),
+ MAPIMACRO(PR_ATTACH_ADDITIONAL_INFO ),
+ MAPIMACRO(PR_DISPLAY_TYPE ),
+ MAPIMACRO(PR_TEMPLATEID ),
+ MAPIMACRO(PR_PRIMARY_CAPABILITY ),
+ MAPIMACRO(PR_7BIT_DISPLAY_NAME ),
+ MAPIMACRO(PR_ACCOUNT ),
+ MAPIMACRO(PR_ALTERNATE_RECIPIENT ),
+ MAPIMACRO(PR_CALLBACK_TELEPHONE_NUMBER ),
+ MAPIMACRO(PR_CONVERSION_PROHIBITED ),
+ MAPIMACRO(PR_DISCLOSE_RECIPIENTS ),
+ MAPIMACRO(PR_GENERATION ),
+ MAPIMACRO(PR_GIVEN_NAME ),
+ MAPIMACRO(PR_GOVERNMENT_ID_NUMBER ),
+ MAPIMACRO(PR_BUSINESS_TELEPHONE_NUMBER ),
+ MAPIMACRO(PR_HOME_TELEPHONE_NUMBER ),
+ MAPIMACRO(PR_INITIALS ),
+ MAPIMACRO(PR_KEYWORD ),
+ MAPIMACRO(PR_LANGUAGE ),
+ MAPIMACRO(PR_LOCATION ),
+ MAPIMACRO(PR_MAIL_PERMISSION ),
+ MAPIMACRO(PR_MHS_COMMON_NAME ),
+ MAPIMACRO(PR_ORGANIZATIONAL_ID_NUMBER ),
+ MAPIMACRO(PR_SURNAME ),
+ MAPIMACRO(PR_ORIGINAL_ENTRYID ),
+ MAPIMACRO(PR_ORIGINAL_DISPLAY_NAME ),
+ MAPIMACRO(PR_ORIGINAL_SEARCH_KEY ),
+ MAPIMACRO(PR_POSTAL_ADDRESS ),
+ MAPIMACRO(PR_COMPANY_NAME ),
+ MAPIMACRO(PR_TITLE ),
+ MAPIMACRO(PR_DEPARTMENT_NAME ),
+ MAPIMACRO(PR_OFFICE_LOCATION ),
+ MAPIMACRO(PR_PRIMARY_TELEPHONE_NUMBER ),
+ MAPIMACRO(PR_BUSINESS2_TELEPHONE_NUMBER ),
+ MAPIMACRO(PR_MOBILE_TELEPHONE_NUMBER ),
+ MAPIMACRO(PR_RADIO_TELEPHONE_NUMBER ),
+ MAPIMACRO(PR_CAR_TELEPHONE_NUMBER ),
+ MAPIMACRO(PR_OTHER_TELEPHONE_NUMBER ),
+ MAPIMACRO(PR_TRANSMITABLE_DISPLAY_NAME ),
+ MAPIMACRO(PR_PAGER_TELEPHONE_NUMBER ),
+ MAPIMACRO(PR_USER_CERTIFICATE ),
+ MAPIMACRO(PR_PRIMARY_FAX_NUMBER ),
+ MAPIMACRO(PR_BUSINESS_FAX_NUMBER ),
+ MAPIMACRO(PR_HOME_FAX_NUMBER ),
+ MAPIMACRO(PR_COUNTRY ),
+ MAPIMACRO(PR_LOCALITY ),
+ MAPIMACRO(PR_STATE_OR_PROVINCE ),
+ MAPIMACRO(PR_STREET_ADDRESS ),
+ MAPIMACRO(PR_POSTAL_CODE ),
+ MAPIMACRO(PR_POST_OFFICE_BOX ),
+ MAPIMACRO(PR_TELEX_NUMBER ),
+ MAPIMACRO(PR_ISDN_NUMBER ),
+ MAPIMACRO(PR_ASSISTANT_TELEPHONE_NUMBER ),
+ MAPIMACRO(PR_HOME2_TELEPHONE_NUMBER ),
+ MAPIMACRO(PR_ASSISTANT ),
+ MAPIMACRO(PR_SEND_RICH_INFO ),
+ MAPIMACRO(PR_WEDDING_ANNIVERSARY ),
+ MAPIMACRO(PR_BIRTHDAY ),
+ MAPIMACRO(PR_HOBBIES ),
+ MAPIMACRO(PR_MIDDLE_NAME ),
+ MAPIMACRO(PR_DISPLAY_NAME_PREFIX ),
+ MAPIMACRO(PR_PROFESSION ),
+ MAPIMACRO(PR_PREFERRED_BY_NAME ),
+ MAPIMACRO(PR_SPOUSE_NAME ),
+ MAPIMACRO(PR_COMPUTER_NETWORK_NAME ),
+ MAPIMACRO(PR_CUSTOMER_ID ),
+ MAPIMACRO(PR_TTYTDD_PHONE_NUMBER ),
+ MAPIMACRO(PR_FTP_SITE ),
+ MAPIMACRO(PR_GENDER ),
+ MAPIMACRO(PR_MANAGER_NAME ),
+ MAPIMACRO(PR_NICKNAME ),
+ MAPIMACRO(PR_PERSONAL_HOME_PAGE ),
+ MAPIMACRO(PR_BUSINESS_HOME_PAGE ),
+ MAPIMACRO(PR_CONTACT_VERSION ),
+ MAPIMACRO(PR_CONTACT_ENTRYIDS ),
+ MAPIMACRO(PR_CONTACT_ADDRTYPES ),
+ MAPIMACRO(PR_CONTACT_DEFAULT_ADDRESS_INDEX ),
+ MAPIMACRO(PR_CONTACT_EMAIL_ADDRESSES ),
+ MAPIMACRO(PR_COMPANY_MAIN_PHONE_NUMBER ),
+ MAPIMACRO(PR_CHILDRENS_NAMES ),
+ MAPIMACRO(PR_HOME_ADDRESS_CITY ),
+ MAPIMACRO(PR_HOME_ADDRESS_COUNTRY ),
+ MAPIMACRO(PR_HOME_ADDRESS_POSTAL_CODE ),
+ MAPIMACRO(PR_HOME_ADDRESS_STATE_OR_PROVINCE ),
+ MAPIMACRO(PR_HOME_ADDRESS_STREET ),
+ MAPIMACRO(PR_HOME_ADDRESS_POST_OFFICE_BOX ),
+ MAPIMACRO(PR_OTHER_ADDRESS_CITY ),
+ MAPIMACRO(PR_OTHER_ADDRESS_COUNTRY ),
+ MAPIMACRO(PR_OTHER_ADDRESS_POSTAL_CODE ),
+ MAPIMACRO(PR_OTHER_ADDRESS_STATE_OR_PROVINCE ),
+ MAPIMACRO(PR_OTHER_ADDRESS_STREET ),
+ MAPIMACRO(PR_OTHER_ADDRESS_POST_OFFICE_BOX ),
+ MAPIMACRO(PR_STORE_PROVIDERS ),
+ MAPIMACRO(PR_AB_PROVIDERS ),
+ MAPIMACRO(PR_TRANSPORT_PROVIDERS ),
+ MAPIMACRO(PR_DEFAULT_PROFILE ),
+ MAPIMACRO(PR_AB_SEARCH_PATH ),
+ MAPIMACRO(PR_AB_DEFAULT_DIR ),
+ MAPIMACRO(PR_AB_DEFAULT_PAB ),
+ MAPIMACRO(PR_FILTERING_HOOKS ),
+ MAPIMACRO(PR_SERVICE_NAME ),
+ MAPIMACRO(PR_SERVICE_DLL_NAME ),
+ MAPIMACRO(PR_SERVICE_ENTRY_NAME ),
+ MAPIMACRO(PR_SERVICE_UID ),
+ MAPIMACRO(PR_SERVICE_EXTRA_UIDS ),
+ MAPIMACRO(PR_SERVICES ),
+ MAPIMACRO(PR_SERVICE_SUPPORT_FILES ),
+ MAPIMACRO(PR_SERVICE_DELETE_FILES ),
+ MAPIMACRO(PR_AB_SEARCH_PATH_UPDATE ),
+ MAPIMACRO(PR_PROFILE_NAME ),
+ MAPIMACRO(PR_IDENTITY_DISPLAY ),
+ MAPIMACRO(PR_IDENTITY_ENTRYID ),
+ MAPIMACRO(PR_RESOURCE_METHODS ),
+ MAPIMACRO(PR_RESOURCE_TYPE ),
+ MAPIMACRO(PR_STATUS_CODE ),
+ MAPIMACRO(PR_IDENTITY_SEARCH_KEY ),
+ MAPIMACRO(PR_OWN_STORE_ENTRYID ),
+ MAPIMACRO(PR_RESOURCE_PATH ),
+ MAPIMACRO(PR_STATUS_STRING ),
+ MAPIMACRO(PR_X400_DEFERRED_DELIVERY_CANCEL ),
+ MAPIMACRO(PR_HEADER_FOLDER_ENTRYID ),
+ MAPIMACRO(PR_REMOTE_PROGRESS ),
+ MAPIMACRO(PR_REMOTE_PROGRESS_TEXT ),
+ MAPIMACRO(PR_REMOTE_VALIDATE_OK ),
+ MAPIMACRO(PR_CONTROL_FLAGS ),
+ MAPIMACRO(PR_CONTROL_STRUCTURE ),
+ MAPIMACRO(PR_CONTROL_TYPE ),
+ MAPIMACRO(PR_DELTAX ),
+ MAPIMACRO(PR_DELTAY ),
+ MAPIMACRO(PR_XPOS ),
+ MAPIMACRO(PR_YPOS ),
+ MAPIMACRO(PR_CONTROL_ID ),
+ MAPIMACRO(PR_INITIAL_DETAILS_PANE )};
+
+#endif /* MAPITAGS_H */
+++ /dev/null
-Placeholder
--- /dev/null
+EXPORTS
+ plugin_desc
+ plugin_done
+ plugin_init
+ plugin_licence
+ plugin_name
+ plugin_type
+ plugin_provides
+ plugin_version
+
--- /dev/null
+#ifndef _TNEF_ERRORS_
+#define _TNEF_ERRORS_
+
+
+#define YTNEF_CANNOT_INIT_DATA -1
+#define YTNEF_NOT_TNEF_STREAM -2
+#define YTNEF_ERROR_READING_DATA -3
+#define YTNEF_NO_KEY -4
+#define YTNEF_BAD_CHECKSUM -5
+#define YTNEF_ERROR_IN_HANDLER -6
+#define YTNEF_UNKNOWN_PROPERTY -7
+#define YTNEF_INCORRECT_SETUP -8
+
+
+#endif
+
--- /dev/null
+#ifndef _TNEF_TYPES_H_
+#define _TNEF_TYPES_H_
+
+#define BYTE unsigned char
+#define WORD unsigned short int
+#define DWORD unsigned int
+#define ULONG unsigned int
+#define DDWORD unsigned long long
+typedef struct
+{
+ WORD atyp;
+ ULONG ulPosition;
+ WORD dxWidth;
+ WORD dyHeight;
+ DWORD dwFlags;
+} renddata;
+
+/* ----------------------------------- */
+/* TNEF Down-level Date/Time Structure */
+/* ----------------------------------- */
+
+typedef struct
+{
+ WORD wYear;
+ WORD wMonth;
+ WORD wDay;
+ WORD wHour;
+ WORD wMinute;
+ WORD wSecond;
+ WORD wDayOfWeek;
+} dtr;
+
+typedef struct
+{
+ char *data;
+ int size;
+} variableLength;
+
+typedef struct {
+ DWORD custom;
+ BYTE guid[16];
+ DWORD id;
+ ULONG count;
+ int namedproperty;
+ variableLength *propnames;
+ variableLength *data;
+} MAPIProperty;
+
+typedef struct MAPIProps {
+ DWORD count;
+ MAPIProperty *properties;
+} MAPIProps;
+
+typedef struct Attachment
+{
+ dtr Date;
+ variableLength Title;
+ variableLength MetaFile;
+ dtr CreateDate;
+ dtr ModifyDate;
+ variableLength TransportFilename;
+ renddata RenderData;
+ MAPIProps MAPI;
+ struct Attachment *next;
+ variableLength FileData;
+ variableLength IconData;
+} Attachment;
+
+typedef struct _TNEFIOStruct
+{
+ int (*InitProc) (struct _TNEFIOStruct *IO);
+ int (*ReadProc) (struct _TNEFIOStruct *IO, int size, int count, void *dest);
+ int (*CloseProc) (struct _TNEFIOStruct *IO);
+ void *data;
+} TNEFIOStruct;
+
+typedef struct
+{
+ char *filename;
+ FILE *fptr;
+ int Debug;
+} TNEFFileInfo;
+
+typedef struct
+{
+ BYTE *dataStart;
+ BYTE *ptr;
+ long size;
+ int Debug;
+} TNEFMemInfo;
+
+typedef struct
+{
+ char version[10];
+ variableLength from;
+ variableLength subject;
+ dtr dateSent;
+ dtr dateReceived;
+ char messageStatus[10];
+ char messageClass[50];
+ char messageID[50];
+ char parentID[50];
+ char conversationID[50];
+ variableLength body;
+ char priority[10];
+ Attachment starting_attach;
+ dtr dateModified;
+ MAPIProps MapiProperties;
+ variableLength CodePage;
+ variableLength OriginalMessageClass;
+ variableLength Owner;
+ variableLength SentFor;
+ variableLength Delegate;
+ dtr DateStart;
+ dtr DateEnd;
+ variableLength AidOwner;
+ int RequestRes;
+ int Debug;
+ TNEFIOStruct IO;
+} TNEFStruct;
+
+#endif
--- /dev/null
+/*
+ * Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
+ * Copyright (C) 1999-2007 Colin Leroy <colin@colino.net>
+ * and the Claws Mail Team
+ *
+ * This file Copyright (C) 2002-2007 Randall Hand <yerase@yerot.com>
+ * Thanks to him for allowing redistribution of this code as GPLv3.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#include "claws-features.h"
+#endif
+
+#include <unistd.h>
+#include <stdio.h>
+#include <ctype.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+#include "common/claws.h"
+#include "common/version.h"
+#include "main.h"
+#include "plugin.h"
+#include "procmime.h"
+#include "utils.h"
+
+#include <tnef-types.h>
+#include <ytnef.h>
+#include <mapi.h>
+#include <mapidefs.h>
+
+#include "tnef_dump.h"
+
+#define PRODID "PRODID:-//The Gauntlet//" PACKAGE " TNEF Parser " VERSION "//EN\n"
+
+static unsigned char GetRruleCount(unsigned char a, unsigned char b) {
+ return ((a << 8) | b);
+}
+
+static unsigned char GetRruleMonthNum(unsigned char a, unsigned char 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);
+}
+
+static char * GetRruleDayname(unsigned char a) {
+ static char 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);
+}
+
+static void PrintRrule(FILE *fptr, char *recur_data, int 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");
+}
+
+static void fprintProperty(TNEFStruct TNEF, FILE *FPTR, DWORD PROPTYPE, DWORD PROPID, char 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);
+ }
+ }
+ }
+}
+
+static void fprintUserProp(TNEFStruct TNEF, FILE *FPTR, DWORD PROPTYPE, DWORD PROPID, char 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);
+ }
+ }
+ }
+}
+
+static void quotedfprint(FILE *FPTR, variableLength *VL) {
+ int 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]);
+ }
+ }
+}
+
+static void Cstylefprint(FILE *FPTR, variableLength *VL) {
+ int 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]);
+ }
+ }
+}
+
+static void PrintRTF(FILE *fptr, variableLength *VL) {
+ int index;
+ char *byte;
+ int brace_ct;
+ int 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");
+}
+
+gboolean SaveVCalendar(FILE *fptr, TNEFStruct TNEF) {
+ variableLength *filename;
+ char *charptr, *charptr2;
+ int index;
+ DDWORD *ddword_ptr;
+ DDWORD ddword_val;
+ dtr thedate;
+
+ 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, PRODID);
+ 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", (unsigned char)filename->data[index]);
+ }
+ fprintf(fptr,"\n");
+ }
+
+ // Sequence
+ filename = NULL;
+ if ((filename=MAPIFindUserProp(&(TNEF.MapiProperties),
+ PROP_TAG(PT_LONG, 0x8201))) != MAPI_UNDEFINED) {
+ ddword_ptr = (DDWORD*)filename->data;
+ fprintf(fptr, "SEQUENCE:%i\n", (int) *ddword_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;
+ charptr2=strstr(charptr+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;
+ charptr2=strstr(charptr+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;
+ charptr2=strstr(charptr+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 = 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(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(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(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) {
+ ddword_ptr = (DDWORD*)filename->data;
+ ddword_val = SwapDDWord((BYTE*)ddword_ptr);
+ fprintf(fptr, "CLASS:" );
+ if (*ddword_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");
+ return TRUE;
+}
+
+
+
+gboolean SaveVTask(FILE *fptr, TNEFStruct TNEF) {
+ variableLength *filename;
+ char *charptr, *charptr2;
+ dtr thedate;
+ DDWORD *ddword_ptr;
+ DDWORD ddword_val;
+
+ fprintf(fptr, "BEGIN:VCALENDAR\n");
+ fprintf(fptr, PRODID);
+ 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;
+ charptr2=strstr(charptr+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(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(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(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) {
+ ddword_ptr = (DDWORD*)filename->data;
+ ddword_val = SwapDDWord((BYTE*)ddword_ptr);
+ fprintf(fptr, "CLASS:" );
+ if (*ddword_ptr == 1) {
+ fprintf(fptr,"PRIVATE\n");
+ } else {
+ fprintf(fptr,"PUBLIC\n");
+ }
+ }
+ fprintf(fptr, "END:VTODO\n");
+ fprintf(fptr, "END:VCALENDAR\n");
+ fclose(fptr);
+ return TRUE;
+}
+
+gboolean SaveVCard(FILE *fptr, TNEFStruct TNEF) {
+ variableLength *vl;
+ variableLength *pobox, *street, *city, *state, *zip, *country;
+ dtr thedate;
+ int boolean;
+
+ if ((vl = MAPIFindProperty(&(TNEF.MapiProperties), PROP_TAG(PT_STRING8, PR_DISPLAY_NAME))) == MAPI_UNDEFINED) {
+ vl=MAPIFindProperty(&(TNEF.MapiProperties), PROP_TAG(PT_STRING8, PR_COMPANY_NAME));
+ }
+
+ 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(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(vl->data, &thedate);
+ fprintf(fptr, "%i-%02i-%02i\n", thedate.wYear, thedate.wMonth, thedate.wDay);
+ }
+ fprintf(fptr, "END:VCARD\n");
+ return TRUE;
+}
--- /dev/null
+/*
+ * Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
+ * Copyright (C) 1999-2007 Colin Leroy <colin@colino.net>
+ * and the Claws Mail Team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __TNEF_DUMP__
+#define __TNEF_DUMP__
+
+gboolean SaveVCalendar(FILE *fptr, TNEFStruct TNEF);
+gboolean SaveVCard(FILE *fptr, TNEFStruct TNEF);
+gboolean SaveVTask(FILE *fptr, TNEFStruct TNEF);
+
+#endif
--- /dev/null
+/*
+ * Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
+ * Copyright (C) 1999-2007 Colin Leroy <colin@colino.net>
+ * and the Claws Mail Team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#include "claws-features.h"
+#endif
+
+#include <unistd.h>
+#include <stdio.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+#include "common/claws.h"
+#include "common/version.h"
+#include "main.h"
+#include "plugin.h"
+#include "procmime.h"
+#include "utils.h"
+
+#include <tnef-types.h>
+#include <ytnef.h>
+#include <mapi.h>
+#include <mapidefs.h>
+
+#include "tnef_dump.h"
+
+static MimeParser *tnef_parser = NULL;
+
+static MimeInfo *tnef_broken_mimeinfo(const gchar *reason)
+{
+ MimeInfo *sub_info = NULL;
+ gchar *tmpfilename = NULL;
+ FILE *fp = get_tmpfile_in_dir(get_mime_tmp_dir(), &tmpfilename);
+ struct stat statbuf;
+
+ if (!fp) {
+ g_free(tmpfilename);
+ return NULL;
+ }
+ sub_info = procmime_mimeinfo_new();
+ sub_info->content = MIMECONTENT_FILE;
+ sub_info->data.filename = tmpfilename;
+ sub_info->type = MIMETYPE_TEXT;
+ sub_info->subtype = g_strdup("plain");
+
+ fprintf(fp, _("\n"
+ "Claws Mail TNEF parser:\n\n"
+ "%s\n"), reason?reason:_("Unknown error"));
+
+ fclose(fp);
+ g_stat(tmpfilename, &statbuf);
+ sub_info->tmp = TRUE;
+ sub_info->length = statbuf.st_size;
+ sub_info->encoding_type = ENC_BINARY;
+
+ return sub_info;
+
+}
+
+static MimeInfo *tnef_dump_file(const gchar *filename, char *data, size_t size)
+{
+ MimeInfo *sub_info = NULL;
+ gchar *tmpfilename = NULL;
+ FILE *fp = get_tmpfile_in_dir(get_mime_tmp_dir(), &tmpfilename);
+ struct stat statbuf;
+ gchar *content_type = NULL;
+ if (!fp) {
+ g_free(tmpfilename);
+ return NULL;
+ }
+ sub_info = procmime_mimeinfo_new();
+ sub_info->content = MIMECONTENT_FILE;
+ sub_info->data.filename = tmpfilename;
+ sub_info->type = MIMETYPE_APPLICATION;
+ sub_info->subtype = g_strdup("octet-stream");
+
+ if (filename) {
+ g_hash_table_insert(sub_info->typeparameters,
+ g_strdup("filename"),
+ g_strdup(filename));
+
+ content_type = procmime_get_mime_type(filename);
+ if (content_type && strchr(content_type, '/')) {
+ g_free(sub_info->subtype);
+ sub_info->subtype = g_strdup(strchr(content_type, '/')+1);
+ *(strchr(content_type, '/')) = '\0';
+ sub_info->type = procmime_get_media_type(content_type);
+ g_free(content_type);
+ }
+ }
+
+ if (fwrite(data, 1, size, fp) < size) {
+ FILE_OP_ERROR(tmpfilename, "fwrite");
+ fclose(fp);
+ claws_unlink(tmpfilename);
+ procmime_mimeinfo_free_all(sub_info);
+ return tnef_broken_mimeinfo(_("Failed to write the part data."));
+ }
+ fclose(fp);
+ g_stat(tmpfilename, &statbuf);
+ sub_info->tmp = TRUE;
+ sub_info->length = statbuf.st_size;
+ sub_info->encoding_type = ENC_BINARY;
+
+ return sub_info;
+}
+
+MimeInfo *tnef_parse_vcal(TNEFStruct tnef)
+{
+ MimeInfo *sub_info = NULL;
+ gchar *tmpfilename = NULL;
+ FILE *fp = get_tmpfile_in_dir(get_mime_tmp_dir(), &tmpfilename);
+ struct stat statbuf;
+ gboolean result = FALSE;
+ if (!fp) {
+ g_free(tmpfilename);
+ return NULL;
+ }
+ sub_info = procmime_mimeinfo_new();
+ sub_info->content = MIMECONTENT_FILE;
+ sub_info->data.filename = tmpfilename;
+ sub_info->type = MIMETYPE_TEXT;
+ sub_info->subtype = g_strdup("calendar");
+ g_hash_table_insert(sub_info->typeparameters,
+ g_strdup("filename"),
+ g_strdup("calendar.ics"));
+
+ result = SaveVCalendar(fp, tnef);
+
+ fclose(fp);
+ g_stat(tmpfilename, &statbuf);
+ sub_info->tmp = TRUE;
+ sub_info->length = statbuf.st_size;
+ sub_info->encoding_type = ENC_BINARY;
+
+ if (!result) {
+ claws_unlink(tmpfilename);
+ procmime_mimeinfo_free_all(sub_info);
+ return tnef_broken_mimeinfo(_("Failed to parse VCalendar data."));
+ }
+ return sub_info;
+}
+
+MimeInfo *tnef_parse_vtask(TNEFStruct tnef)
+{
+ MimeInfo *sub_info = NULL;
+ gchar *tmpfilename = NULL;
+ FILE *fp = get_tmpfile_in_dir(get_mime_tmp_dir(), &tmpfilename);
+ struct stat statbuf;
+ gboolean result = FALSE;
+ if (!fp) {
+ g_free(tmpfilename);
+ return NULL;
+ }
+ sub_info = procmime_mimeinfo_new();
+ sub_info->content = MIMECONTENT_FILE;
+ sub_info->data.filename = tmpfilename;
+ sub_info->type = MIMETYPE_TEXT;
+ sub_info->subtype = g_strdup("calendar");
+ g_hash_table_insert(sub_info->typeparameters,
+ g_strdup("filename"),
+ g_strdup("task.ics"));
+
+ result = SaveVTask(fp, tnef);
+
+ fclose(fp);
+ g_stat(tmpfilename, &statbuf);
+ sub_info->tmp = TRUE;
+ sub_info->length = statbuf.st_size;
+ sub_info->encoding_type = ENC_BINARY;
+
+ if (!result) {
+ claws_unlink(tmpfilename);
+ procmime_mimeinfo_free_all(sub_info);
+ return tnef_broken_mimeinfo(_("Failed to parse VTask data."));
+ }
+ return sub_info;
+}
+
+MimeInfo *tnef_parse_rtf(TNEFStruct tnef, variableLength *tmp_var)
+{
+ variableLength buf;
+ MimeInfo *info = NULL;
+ buf.data = DecompressRTF(tmp_var, &(buf.size));
+ if (buf.data) {
+ info = tnef_dump_file("message.rtf", buf.data, buf.size);
+ free(buf.data);
+ return info;
+ } else {
+ return NULL;
+ }
+}
+
+MimeInfo *tnef_parse_vcard(TNEFStruct tnef)
+{
+ MimeInfo *sub_info = NULL;
+ gchar *tmpfilename = NULL;
+ FILE *fp = get_tmpfile_in_dir(get_mime_tmp_dir(), &tmpfilename);
+ struct stat statbuf;
+ gboolean result = FALSE;
+ if (!fp) {
+ g_free(tmpfilename);
+ return NULL;
+ }
+ sub_info = procmime_mimeinfo_new();
+ sub_info->content = MIMECONTENT_FILE;
+ sub_info->data.filename = tmpfilename;
+ sub_info->type = MIMETYPE_TEXT;
+ sub_info->subtype = g_strdup("x-vcard");
+ g_hash_table_insert(sub_info->typeparameters,
+ g_strdup("filename"),
+ g_strdup("contact.vcf"));
+
+ result = SaveVCard(fp, tnef);
+
+ fclose(fp);
+ g_stat(tmpfilename, &statbuf);
+ sub_info->tmp = TRUE;
+ sub_info->length = statbuf.st_size;
+ sub_info->encoding_type = ENC_BINARY;
+
+ if (!result) {
+ claws_unlink(tmpfilename);
+ procmime_mimeinfo_free_all(sub_info);
+ return tnef_broken_mimeinfo(_("Failed to parse VCard data."));
+ }
+ return sub_info;
+}
+
+static gboolean tnef_parse (MimeParser *parser, MimeInfo *mimeinfo)
+{
+ TNEFStruct tnef;
+ MimeInfo *sub_info = NULL;
+ variableLength *tmp_var;
+ Attachment *att;
+ int parse_result = 0;
+ gboolean cal_done = FALSE;
+
+ if (!procmime_decode_content(mimeinfo)) {
+ debug_print("error decoding\n");
+ return FALSE;
+ }
+ debug_print("Tnef parser parsing part (%d).\n", mimeinfo->length);
+ if (mimeinfo->content == MIMECONTENT_FILE)
+ debug_print("content: %s\n", mimeinfo->data.filename);
+ else
+ debug_print("contents in memory (len %zd)\n",
+ strlen(mimeinfo->data.mem));
+
+ TNEFInitialize(&tnef);
+
+ if (!debug_get_mode())
+ tnef.Debug = 0;
+
+ if (mimeinfo->content == MIMECONTENT_MEM)
+ parse_result = TNEFParseMemory(mimeinfo->data.mem, mimeinfo->length, &tnef);
+ else
+ parse_result = TNEFParseFile(mimeinfo->data.filename, &tnef);
+
+ mimeinfo->type = MIMETYPE_MULTIPART;
+ mimeinfo->subtype = g_strdup("mixed");
+ g_hash_table_insert(mimeinfo->typeparameters,
+ g_strdup("description"),
+ g_strdup("Parsed from MS-TNEF"));
+
+ if (parse_result != 0) {
+ g_warning("Failed to parse TNEF data.");
+ TNEFFree(&tnef);
+ return FALSE;
+ }
+
+ sub_info = NULL;
+ if (tnef.messageClass != NULL && tnef.messageClass[0] != '\0') {
+ if (strcmp(tnef.messageClass, "IPM.Contact") == 0)
+ sub_info = tnef_parse_vcard(tnef);
+ else if (strcmp(tnef.messageClass, "IPM.Task") == 0)
+ sub_info = tnef_parse_vtask(tnef);
+ else if (strcmp(tnef.messageClass, "IPM.Appointment") == 0) {
+ sub_info = tnef_parse_vcal(tnef);
+ cal_done = TRUE;
+ }
+ }
+
+ if (sub_info)
+ g_node_append(mimeinfo->node, sub_info->node);
+ sub_info = NULL;
+
+ if (tnef.MapiProperties.count > 0) {
+ tmp_var = MAPIFindProperty (&(tnef.MapiProperties), PROP_TAG(PT_BINARY,PR_RTF_COMPRESSED));
+ if (tmp_var != MAPI_UNDEFINED) {
+ sub_info = tnef_parse_rtf(tnef, tmp_var);
+ }
+ }
+
+ if (sub_info)
+ g_node_append(mimeinfo->node, sub_info->node);
+ sub_info = NULL;
+
+ tmp_var = MAPIFindUserProp(&(tnef.MapiProperties), PROP_TAG(PT_STRING8,0x24));
+ if (tmp_var != MAPI_UNDEFINED) {
+ if (!cal_done && strcmp(tmp_var->data, "IPM.Appointment") == 0) {
+ sub_info = tnef_parse_vcal(tnef);
+ }
+ }
+
+ if (sub_info)
+ g_node_append(mimeinfo->node, sub_info->node);
+ sub_info = NULL;
+
+ att = tnef.starting_attach.next;
+ while (att) {
+ gchar *filename = NULL;
+ gboolean is_object = TRUE;
+ DWORD signature;
+
+ tmp_var = MAPIFindProperty(&(att->MAPI), PROP_TAG(30,0x3707));
+ if (tmp_var == MAPI_UNDEFINED)
+ tmp_var = MAPIFindProperty(&(att->MAPI), PROP_TAG(30,0x3001));
+ if (tmp_var == MAPI_UNDEFINED)
+ tmp_var = &(att->Title);
+
+ if (tmp_var->data)
+ filename = g_strdup(tmp_var->data);
+
+ tmp_var = MAPIFindProperty(&(att->MAPI), PROP_TAG(PT_OBJECT, PR_ATTACH_DATA_OBJ));
+ if (tmp_var == MAPI_UNDEFINED)
+ tmp_var = MAPIFindProperty(&(att->MAPI), PROP_TAG(PT_BINARY, PR_ATTACH_DATA_OBJ));
+ if (tmp_var == MAPI_UNDEFINED) {
+ tmp_var = &(att->FileData);
+ is_object = FALSE;
+ }
+
+ sub_info = tnef_dump_file(filename,
+ tmp_var->data + (is_object ? 16:0),
+ tmp_var->size - (is_object ? 16:0));
+
+ if (sub_info)
+ g_node_append(mimeinfo->node, sub_info->node);
+
+ memcpy(&signature, tmp_var->data+(is_object ? 16:0), sizeof(DWORD));
+
+ if (TNEFCheckForSignature(signature) == 0) {
+ debug_print("that's TNEF stuff, process it\n");
+ tnef_parse(parser, sub_info);
+ }
+
+ sub_info = NULL;
+
+ att = att->next;
+
+ g_free(filename);
+ }
+
+ TNEFFree(&tnef);
+ return TRUE;
+}
+
+gint plugin_init(gchar **error)
+{
+ if (!check_plugin_version(MAKE_NUMERIC_VERSION(2,9,2,72),
+ VERSION_NUMERIC, _("TNEF Parser"), error))
+ return -1;
+
+ tnef_parser = g_new0(MimeParser, 1);
+ tnef_parser->type = MIMETYPE_APPLICATION;
+ tnef_parser->sub_type = "ms-tnef";
+ tnef_parser->parse = tnef_parse;
+
+ procmime_mimeparser_register(tnef_parser);
+
+ return 0;
+}
+
+gboolean plugin_done(void)
+{
+ procmime_mimeparser_unregister(tnef_parser);
+ g_free(tnef_parser);
+ tnef_parser = NULL;
+
+ return TRUE;
+}
+
+const gchar *plugin_name(void)
+{
+ return _("TNEF Parser");
+}
+
+const gchar *plugin_desc(void)
+{
+ return _("This Claws Mail plugin allows you to read application/ms-tnef attachments.\n\n"
+ "The plugin uses the Ytnef library, which is copyright 2002-2007 by "
+ "Randall Hand <yerase@yerot.com>");
+}
+
+const gchar *plugin_type(void)
+{
+ return "GTK2";
+}
+
+const gchar *plugin_licence(void)
+{
+ return "GPL3+";
+}
+
+const gchar *plugin_version(void)
+{
+ return VERSION;
+}
+
+struct PluginFeature *plugin_provides(void)
+{
+ static struct PluginFeature features[] =
+ { {PLUGIN_MIMEPARSER, "application/ms-tnef"},
+ {PLUGIN_NOTHING, NULL}};
+ return features;
+}
--- /dev/null
+1 VERSIONINFO
+ FILEVERSION 0, 0, 0, 0
+ PRODUCTVERSION 0, 0, 0, 0
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x40004L
+ FILETYPE 0x2L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "000004b0"
+ BEGIN
+ VALUE "FileDescription", "TNEF Parser Plugin\0"
+ VALUE "FileVersion", "0.0.0.0\0"
+ VALUE "ProductVersion", "0.0.0.0 Win32\0"
+ VALUE "LegalCopyright", "GPL / © 1999-2008 Hiroyuki Yamamoto & The Claws Mail Team\0"
+ VALUE "CompanyName", "GNU / Free Software Foundation\0"
+ VALUE "ProductName", "Claws Mail\0"
+// VALUE "Comments", "\0"
+// VALUE "InternalName", "\0"
+// VALUE "LegalTrademarks", "\0"
+// VALUE "OriginalFilename", "\0"
+// VALUE "PrivateBuild", "\0"
+// VALUE "SpecialBuild", "\0"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x0, 1200
+ END
+END
--- /dev/null
+/*
+ * Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
+ * Copyright (C) 2008 Colin Leroy <colin@colino.net>
+ * and the Claws Mail Team
+ *
+ * This file Copyright (C) 2002-2007 Randall Hand <yerase@yerot.com>
+ * Thanks to him for allowing redistribution of this code as GPLv3.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#include "claws-features.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include "ytnef.h"
+#include "tnef-errors.h"
+#include "mapi.h"
+#include "mapidefs.h"
+#include "mapitags.h"
+#include "config.h"
+
+#include <glib.h>
+#include <glib/gstdio.h>
+
+#define RTF_PREBUF "{\\rtf1\\ansi\\mac\\deff0\\deftab720{\\fonttbl;}{\\f0\\fnil \\froman \\fswiss \\fmodern \\fscript \\fdecor MS Sans SerifSymbolArialTimes New RomanCourier{\\colortbl\\red0\\green0\\blue0\n\r\\par \\pard\\plain\\f0\\fs20\\b\\i\\u\\tab\\tx"
+#define DEBUG(lvl, curlvl, msg) \
+ if ((lvl) >= (curlvl)) \
+ printf("DEBUG(%i/%i): %s\n", curlvl, lvl, msg);
+#define DEBUG1(lvl, curlvl, msg, var1) \
+ if ((lvl) >= (curlvl)) { \
+ printf("DEBUG(%i/%i):", curlvl, lvl); \
+ printf(msg, var1); \
+ printf("\n"); \
+ }
+#define DEBUG2(lvl, curlvl, msg, var1, var2) \
+ if ((lvl) >= (curlvl)) { \
+ printf("DEBUG(%i/%i):", curlvl, lvl); \
+ printf(msg, var1, var2); \
+ printf("\n"); \
+ }
+#define DEBUG3(lvl, curlvl, msg, var1, var2, var3) \
+ if ((lvl) >= (curlvl)) { \
+ printf("DEBUG(%i/%i):", curlvl, lvl); \
+ printf(msg, var1, var2,var3); \
+ printf("\n"); \
+ }
+
+#ifndef MIN
+#define MIN(x,y) (((x)<(y))?(x):(y))
+#endif
+
+void TNEFFillMapi(TNEFStruct *TNEF, BYTE *data, DWORD size, MAPIProps *p);
+void SetFlip(void);
+
+int TNEFDefaultHandler STD_ARGLIST;
+int TNEFAttachmentFilename STD_ARGLIST;
+int TNEFAttachmentSave STD_ARGLIST;
+int TNEFDetailedPrint STD_ARGLIST;
+int TNEFHexBreakdown STD_ARGLIST;
+int TNEFBody STD_ARGLIST;
+int TNEFRendData STD_ARGLIST;
+int TNEFDateHandler STD_ARGLIST;
+int TNEFPriority STD_ARGLIST;
+int TNEFVersion STD_ARGLIST;
+int TNEFMapiProperties STD_ARGLIST;
+int TNEFIcon STD_ARGLIST;
+int TNEFSubjectHandler STD_ARGLIST;
+int TNEFFromHandler STD_ARGLIST;
+int TNEFRecipTable STD_ARGLIST;
+int TNEFAttachmentMAPI STD_ARGLIST;
+int TNEFSentFor STD_ARGLIST;
+int TNEFMessageClass STD_ARGLIST;
+int TNEFMessageID STD_ARGLIST;
+int TNEFParentID STD_ARGLIST;
+int TNEFOriginalMsgClass STD_ARGLIST;
+int TNEFCodePage STD_ARGLIST;
+
+
+BYTE *TNEFFileContents=NULL;
+DWORD TNEFFileContentsSize;
+BYTE *TNEFFileIcon=NULL;
+DWORD TNEFFileIconSize;
+
+TNEFHandler TNEFList[] = {
+ {attNull, "Null", TNEFDefaultHandler},
+ {attFrom, "From", TNEFFromHandler},
+ {attSubject, "Subject", TNEFSubjectHandler},
+ {attDateSent, "Date Sent", TNEFDateHandler},
+ {attDateRecd, "Date Received", TNEFDateHandler},
+ {attMessageStatus, "Message Status", TNEFDefaultHandler},
+ {attMessageClass, "Message Class", TNEFMessageClass},
+ {attMessageID, "Message ID", TNEFMessageID},
+ {attParentID, "Parent ID", TNEFParentID},
+ {attConversationID, "Conversation ID", TNEFDefaultHandler},
+ {attBody, "Body", TNEFBody},
+ {attPriority, "Priority", TNEFPriority},
+ {attAttachData, "Attach Data", TNEFAttachmentSave},
+ {attAttachTitle, "Attach Title", TNEFAttachmentFilename},
+ {attAttachMetaFile, "Attach Meta-File", TNEFIcon},
+ {attAttachCreateDate, "Attachment Create Date", TNEFDateHandler},
+ {attAttachModifyDate, "Attachment Modify Date", TNEFDateHandler},
+ {attDateModified, "Date Modified", TNEFDateHandler},
+ {attAttachTransportFilename, "Attachment Transport name", TNEFDefaultHandler},
+ {attAttachRenddata, "Attachment Display info", TNEFRendData},
+ {attMAPIProps, "MAPI Properties", TNEFMapiProperties},
+ {attRecipTable, "Recip Table", TNEFRecipTable},
+ {attAttachment, "Attachment", TNEFAttachmentMAPI},
+ {attTnefVersion, "TNEF Version", TNEFVersion},
+ {attOemCodepage, "OEM CodePage", TNEFCodePage},
+ {attOriginalMessageClass, "Original Message Class", TNEFOriginalMsgClass},
+ {attOwner, "Owner", TNEFDefaultHandler},
+ {attSentFor, "Sent For", TNEFSentFor},
+ {attDelegate, "Delegate", TNEFDefaultHandler},
+ {attDateStart, "Date Start", TNEFDateHandler},
+ {attDateEnd, "Date End", TNEFDateHandler},
+ {attAidOwner, "Aid Owner", TNEFDefaultHandler},
+ {attRequestRes, "Request Response", TNEFDefaultHandler} };
+
+
+WORD SwapWord(BYTE *p)
+{
+ WORD *word_ptr;
+#ifdef WORDS_BIGENDIAN
+ BYTE bytes[2];
+ bytes[0] = p[1];
+ bytes[1] = p[0];
+ word_ptr = (WORD*)&(bytes[0]);
+#else
+ word_ptr = (WORD*)p;
+#endif
+ return *word_ptr;
+}
+
+DWORD SwapDWord(BYTE *p)
+{
+ DWORD *dword_ptr;
+#ifdef WORDS_BIGENDIAN
+ BYTE bytes[4];
+ bytes[0] = p[3];
+ bytes[1] = p[2];
+ bytes[2] = p[1];
+ bytes[3] = p[0];
+ dword_ptr = (DWORD*)&(bytes[0]);
+#else
+ dword_ptr = (DWORD*)p;
+#endif
+ return *dword_ptr;
+}
+
+DDWORD SwapDDWord(BYTE *p)
+{
+ DDWORD *ddword_ptr;
+#ifdef WORDS_BIGENDIAN
+ BYTE bytes[8];
+ bytes[0] = p[7];
+ bytes[1] = p[6];
+ bytes[2] = p[5];
+ bytes[3] = p[4];
+ bytes[4] = p[3];
+ bytes[5] = p[2];
+ bytes[6] = p[1];
+ bytes[7] = p[0];
+ ddword_ptr = (DDWORD*)&(bytes[0]);
+#else
+ ddword_ptr = (DDWORD*)p;
+#endif
+ return *ddword_ptr;
+}
+
+/* convert 16-bit unicode to UTF8 unicode */
+char* to_utf8(int len, char* buf)
+{
+ int i, j = 0;
+ /* worst case length */
+ char *utf8 = malloc(3 * len/2 + 1);
+
+ for (i=0; i<len-1; i+=2) {
+ unsigned int c = SwapWord(buf+i);
+ if (c <= 0x007f) {
+ utf8[j++] = 0x00 | ((c & 0x007f) >> 0);
+ }
+ else if (c < 0x07ff) {
+ utf8[j++] = 0xc0 | ((c & 0x07c0) >> 6);
+ utf8[j++] = 0x80 | ((c & 0x003f) >> 0);
+ }
+ else {
+ utf8[j++] = 0xe0 | ((c & 0xf000) >> 12);
+ utf8[j++] = 0x80 | ((c & 0x0fc0) >> 6);
+ utf8[j++] = 0x80 | ((c & 0x003f) >> 0);
+ }
+ }
+
+ /* just in case the original was not null terminated */
+ utf8[j++] = '\0';
+
+ return utf8;
+}
+
+
+// -----------------------------------------------------------------------------
+int TNEFDefaultHandler STD_ARGLIST {
+ if (TNEF->Debug >= 1)
+ printf("%s: [%i] %s\n", TNEFList[id].name, size, data);
+ return 0;
+}
+
+// -----------------------------------------------------------------------------
+int TNEFCodePage STD_ARGLIST {
+ TNEF->CodePage.size = size;
+ TNEF->CodePage.data = calloc(size, sizeof(BYTE));
+ memcpy(TNEF->CodePage.data, data, size);
+ return 0;
+}
+
+// -----------------------------------------------------------------------------
+int TNEFParentID STD_ARGLIST {
+ memcpy(TNEF->parentID, data, MIN(size,sizeof(TNEF->parentID)));
+ return 0;
+}
+// -----------------------------------------------------------------------------
+int TNEFMessageID STD_ARGLIST {
+ memcpy(TNEF->messageID, data, MIN(size,sizeof(TNEF->messageID)));
+ return 0;
+}
+// -----------------------------------------------------------------------------
+int TNEFBody STD_ARGLIST {
+ TNEF->body.size = size;
+ TNEF->body.data = calloc(size, sizeof(BYTE));
+ memcpy(TNEF->body.data, data, size);
+ return 0;
+}
+// -----------------------------------------------------------------------------
+int TNEFOriginalMsgClass STD_ARGLIST {
+ TNEF->OriginalMessageClass.size = size;
+ TNEF->OriginalMessageClass.data = calloc(size, sizeof(BYTE));
+ memcpy(TNEF->OriginalMessageClass.data, data, size);
+ return 0;
+}
+// -----------------------------------------------------------------------------
+int TNEFMessageClass STD_ARGLIST {
+ memcpy(TNEF->messageClass, data, MIN(size,sizeof(TNEF->messageClass)));
+ return 0;
+}
+// -----------------------------------------------------------------------------
+int TNEFFromHandler STD_ARGLIST {
+ TNEF->from.data = calloc(size, sizeof(BYTE));
+ TNEF->from.size = size;
+ memcpy(TNEF->from.data, data,size);
+ return 0;
+}
+// -----------------------------------------------------------------------------
+int TNEFSubjectHandler STD_ARGLIST {
+ TNEF->subject.data = calloc(size, sizeof(BYTE));
+ TNEF->subject.size = size;
+ memcpy(TNEF->subject.data, data,size);
+ return 0;
+}
+
+// -----------------------------------------------------------------------------
+int TNEFRendData STD_ARGLIST {
+ Attachment *p;
+ // Find the last attachment.
+ p = &(TNEF->starting_attach);
+ while (p->next!=NULL) p=p->next;
+
+ // Add a new one
+ p->next = calloc(1,sizeof(Attachment));
+ p=p->next;
+
+ TNEFInitAttachment(p);
+
+ memcpy(&(p->RenderData), data, sizeof(renddata));
+ return 0;
+}
+
+// -----------------------------------------------------------------------------
+int TNEFVersion STD_ARGLIST {
+ WORD major;
+ WORD minor;
+ major = SwapWord(data+2);
+ minor = SwapWord(data);
+
+ sprintf(TNEF->version, "TNEF%i.%i", major, minor);
+ return 0;
+}
+
+// -----------------------------------------------------------------------------
+int TNEFIcon STD_ARGLIST {
+ Attachment *p;
+ // Find the last attachment.
+ p = &(TNEF->starting_attach);
+ while (p->next!=NULL) p=p->next;
+
+ p->IconData.size = size;
+ p->IconData.data = calloc(size, sizeof(BYTE));
+ memcpy(p->IconData.data, data, size);
+ return 0;
+}
+
+// -----------------------------------------------------------------------------
+int TNEFRecipTable STD_ARGLIST {
+ DWORD count;
+ BYTE *d;
+ int current_row;
+ int propcount;
+ int current_prop;
+
+ d = data;
+ count = SwapDWord(d);
+ d += 4;
+// printf("Recipient Table containing %u rows\n", count);
+
+ return 0;
+
+ for(current_row=0; current_row<count; current_row++) {
+ propcount = SwapDWord(d);
+ if (TNEF->Debug >= 1)
+ printf("> Row %i contains %i properties\n", current_row, propcount);
+ d+=4;
+ for(current_prop=0; current_prop<propcount; current_prop++) {
+
+
+ }
+ }
+ return 0;
+}
+// -----------------------------------------------------------------------------
+int TNEFAttachmentMAPI STD_ARGLIST {
+ Attachment *p;
+ // Find the last attachment.
+ //
+ p = &(TNEF->starting_attach);
+ while (p->next!=NULL) p=p->next;
+ TNEFFillMapi(TNEF, data, size, &(p->MAPI));
+
+ return 0;
+}
+// -----------------------------------------------------------------------------
+int TNEFMapiProperties STD_ARGLIST {
+ TNEFFillMapi(TNEF, data, size, &(TNEF->MapiProperties));
+ return 0;
+}
+
+void TNEFFillMapi(TNEFStruct *TNEF, BYTE *data, DWORD size, MAPIProps *p) {
+ int i,j;
+ DWORD num;
+ BYTE *d;
+ MAPIProperty *mp;
+ DWORD type;
+ DWORD length;
+ variableLength *vl;
+
+ WORD temp_word;
+ DWORD temp_dword;
+ DDWORD temp_ddword;
+ int count=-1;
+ int offset;
+
+ d = data;
+ p->count = SwapDWord(data);
+ d += 4;
+ p->properties = calloc(p->count, sizeof(MAPIProperty));
+ mp = p->properties;
+
+ for(i=0; i<p->count; i++) {
+ if (count == -1) {
+ mp->id = SwapDWord(d);
+ d+=4;
+ mp->custom = 0;
+ mp->count = 1;
+ mp->namedproperty = 0;
+ length = -1;
+ if (PROP_ID(mp->id) >= 0x8000) {
+ // Read the GUID
+ memcpy(&(mp->guid[0]), d, 16);
+ d+=16;
+
+ length = SwapDWord(d);
+ d+=sizeof(DWORD);
+ if (length > 0) {
+ mp->namedproperty = length;
+ mp->propnames = calloc(length, sizeof(variableLength));
+ while (length > 0) {
+ type = SwapDWord(d);
+ mp->propnames[length-1].data = calloc(type, sizeof(BYTE));
+ mp->propnames[length-1].size = type;
+ d+=4;
+ for(j=0; j<(type>>1); j++) {
+ mp->propnames[length-1].data[j] = d[j*2];
+ }
+ d += type + ((type % 4) ? (4 - type%4) : 0);
+ length--;
+ }
+ } else {
+ // READ the type
+ type = SwapDWord(d);
+ d+=sizeof(DWORD);
+ mp->id = PROP_TAG(PROP_TYPE(mp->id), type);
+ }
+ mp->custom = 1;
+ }
+
+ //printf("Type id = %04x\n", PROP_TYPE(mp->id));
+ if (PROP_TYPE(mp->id) & MV_FLAG) {
+ mp->id = PROP_TAG(PROP_TYPE(mp->id) - MV_FLAG, PROP_ID(mp->id));
+ mp->count = SwapDWord(d);
+ d+=4;
+ count = 0;
+ }
+ mp->data = calloc(mp->count, sizeof(variableLength));
+ vl = mp->data;
+ } else {
+ i--;
+ count++;
+ vl = &(mp->data[count]);
+ }
+
+ switch (PROP_TYPE(mp->id)) {
+ case PT_BINARY:
+ case PT_OBJECT:
+ case PT_STRING8:
+ case PT_UNICODE:
+ // First number of objects (assume 1 for now)
+ if (count == -1) {
+ vl->size = SwapDWord(d);
+ d+=4;
+ }
+ // now size of object
+ vl->size = SwapDWord(d);
+ d+=4;
+
+ // now actual object
+ if (PROP_TYPE(mp->id) == PT_UNICODE) {
+ vl->data = to_utf8(vl->size, d);
+ }
+ else {
+ vl->data = calloc(vl->size, sizeof(BYTE));
+ memcpy(vl->data, d, vl->size);
+ }
+
+ // Make sure to read in a multiple of 4
+ num = vl->size;
+ offset = ((num % 4) ? (4 - num%4) : 0);
+ d += num + ((num % 4) ? (4 - num%4) : 0);
+ break;
+
+ case PT_I2:
+ // Read in 2 bytes, but proceed by 4 bytes
+ vl->size = 2;
+ vl->data = calloc(vl->size, sizeof(WORD));
+ temp_word = SwapWord(d);
+ memcpy(vl->data, &temp_word, vl->size);
+ d += 4;
+ break;
+ case PT_BOOLEAN:
+ case PT_LONG:
+ case PT_R4:
+ case PT_CURRENCY:
+ case PT_APPTIME:
+ case PT_ERROR:
+ vl->size = 4;
+ vl->data = calloc(vl->size, sizeof(BYTE));
+ temp_dword = SwapDWord(d);
+ memcpy(vl->data, &temp_dword, vl->size);
+ d += 4;
+ break;
+ case PT_DOUBLE:
+ case PT_I8:
+ case PT_SYSTIME:
+ vl->size = 8;
+ vl->data = calloc(vl->size, sizeof(BYTE));
+ temp_ddword = SwapDDWord(d);
+ memcpy(vl->data, &temp_ddword, vl->size);
+ d+=8;
+ break;
+ }
+ if (count == (mp->count-1)) {
+ count = -1;
+ }
+ if (count == -1) {
+ mp++;
+ }
+ }
+ if ((d-data) < size) {
+ if (TNEF->Debug >= 1) {
+ printf("ERROR DURING MAPI READ\n");
+ printf("Read %i bytes, Expected %i bytes\n", (d-data), size);
+ printf("%i bytes missing\n", size - (d-data));
+ }
+ } else if ((d-data) > size){
+ if (TNEF->Debug >= 1) {
+ printf("ERROR DURING MAPI READ\n");
+ printf("Read %i bytes, Expected %i bytes\n", (d-data), size);
+ printf("%i bytes extra\n", (d-data)-size);
+ }
+ }
+ return;
+}
+// -----------------------------------------------------------------------------
+int TNEFSentFor STD_ARGLIST {
+ WORD name_length, addr_length;
+ BYTE *d;
+
+ d=data;
+
+ while ((d-data)<size) {
+ name_length = SwapWord(d);
+ d+=sizeof(WORD);
+ if (TNEF->Debug >= 1)
+ printf("Sent For : %s", d);
+ d+=name_length;
+
+ addr_length = SwapWord(d);
+ d+=sizeof(WORD);
+ if (TNEF->Debug >= 1)
+ printf("<%s>\n", d);
+ d+=addr_length;
+ }
+ return 0;
+}
+// -----------------------------------------------------------------------------
+int TNEFDateHandler STD_ARGLIST {
+ dtr *Date;
+ Attachment *p;
+ WORD *tmp_src, *tmp_dst;
+ int i;
+
+ p = &(TNEF->starting_attach);
+ switch (TNEFList[id].id) {
+ case attDateSent: Date = &(TNEF->dateSent); break;
+ case attDateRecd: Date = &(TNEF->dateReceived); break;
+ case attDateModified: Date = &(TNEF->dateModified); break;
+ case attDateStart: Date = &(TNEF->DateStart); break;
+ case attDateEnd: Date = &(TNEF->DateEnd); break;
+ case attAttachCreateDate:
+ while (p->next!=NULL) p=p->next;
+ Date = &(p->CreateDate);
+ break;
+ case attAttachModifyDate:
+ while (p->next!=NULL) p=p->next;
+ Date = &(p->ModifyDate);
+ break;
+ default:
+ if (TNEF->Debug >= 1)
+ printf("MISSING CASE\n");
+ return YTNEF_UNKNOWN_PROPERTY;
+ }
+
+ tmp_src = (WORD*)data;
+ tmp_dst = (WORD*)Date;
+ for(i=0;i<sizeof(dtr)/sizeof(WORD);i++) {
+ *tmp_dst++ = SwapWord((BYTE*)tmp_src++);
+ }
+ return 0;
+}
+
+void TNEFPrintDate(dtr Date) {
+ char days[7][15] = {"Sunday", "Monday", "Tuesday",
+ "Wednesday", "Thursday", "Friday", "Saturday"};
+ char months[12][15] = {"January", "February", "March", "April", "May",
+ "June", "July", "August", "September", "October", "November",
+ "December"};
+
+ if (Date.wDayOfWeek < 7)
+ printf("%s ", days[Date.wDayOfWeek]);
+
+ if ((Date.wMonth < 13) && (Date.wMonth>0))
+ printf("%s ", months[Date.wMonth-1]);
+
+ printf("%hu, %hu ", Date.wDay, Date.wYear);
+
+ if (Date.wHour>12)
+ printf("%hu:%02hu:%02hu pm", (Date.wHour-12),
+ Date.wMinute, Date.wSecond);
+ else if (Date.wHour == 12)
+ printf("%hu:%02hu:%02hu pm", (Date.wHour),
+ Date.wMinute, Date.wSecond);
+ else
+ printf("%hu:%02hu:%02hu am", Date.wHour,
+ Date.wMinute, Date.wSecond);
+}
+// -----------------------------------------------------------------------------
+int TNEFHexBreakdown STD_ARGLIST {
+ int i;
+ if (TNEF->Debug == 0)
+ return 0;
+
+ printf("%s: [%i bytes] \n", TNEFList[id].name, size);
+
+ for(i=0; i<size; i++) {
+ printf("%02x ", data[i]);
+ if ((i+1)%16 == 0) printf("\n");
+ }
+ printf("\n");
+ return 0;
+}
+
+// -----------------------------------------------------------------------------
+int TNEFDetailedPrint STD_ARGLIST {
+ int i;
+ if (TNEF->Debug == 0)
+ return 0;
+
+ printf("%s: [%i bytes] \n", TNEFList[id].name, size);
+
+ for(i=0; i<size; i++) {
+ printf("%c", data[i]);
+ }
+ printf("\n");
+ return 0;
+}
+
+// -----------------------------------------------------------------------------
+int TNEFAttachmentFilename STD_ARGLIST {
+ Attachment *p;
+ p = &(TNEF->starting_attach);
+ while (p->next!=NULL) p=p->next;
+
+ p->Title.size = size;
+ p->Title.data = calloc(size, sizeof(BYTE));
+ memcpy(p->Title.data, data, size);
+
+ return 0;
+}
+
+// -----------------------------------------------------------------------------
+int TNEFAttachmentSave STD_ARGLIST {
+ Attachment *p;
+ p = &(TNEF->starting_attach);
+ while (p->next!=NULL) p=p->next;
+
+ p->FileData.data = calloc(sizeof(unsigned char), size);
+ p->FileData.size = size;
+
+ memcpy(p->FileData.data, data, size);
+
+ return 0;
+}
+
+// -----------------------------------------------------------------------------
+int TNEFPriority STD_ARGLIST {
+ DWORD value;
+
+ value = SwapDWord(data);
+ switch (value) {
+ case 3:
+ sprintf((TNEF->priority), "high");
+ break;
+ case 2:
+ sprintf((TNEF->priority), "normal");
+ break;
+ case 1:
+ sprintf((TNEF->priority), "low");
+ break;
+ default:
+ sprintf((TNEF->priority), "N/A");
+ break;
+ }
+ return 0;
+}
+
+// -----------------------------------------------------------------------------
+int TNEFCheckForSignature(DWORD sig) {
+ DWORD signature = 0x223E9F78;
+
+ sig = SwapDWord((BYTE*)&sig);
+
+ if (signature == sig) {
+ return 0;
+ } else {
+ return YTNEF_NOT_TNEF_STREAM;
+ }
+}
+
+// -----------------------------------------------------------------------------
+int TNEFGetKey(TNEFStruct *TNEF, WORD *key) {
+ if (TNEF->IO.ReadProc (&(TNEF->IO), sizeof(WORD),1, key) < 1) {
+ if (TNEF->Debug >= 1)
+ printf("Error reading Key\n");
+ return YTNEF_ERROR_READING_DATA;
+ }
+ *key = SwapWord((BYTE*)key);
+
+ DEBUG1(TNEF->Debug, 2, "Key = %i", *key);
+ return 0;
+}
+
+// -----------------------------------------------------------------------------
+int TNEFGetHeader(TNEFStruct *TNEF, DWORD *type, DWORD *size) {
+ BYTE component;
+
+ DEBUG(TNEF->Debug, 2, "About to read Component");
+ if (TNEF->IO.ReadProc(&(TNEF->IO), sizeof(BYTE),1, &component) < 1) {
+ return YTNEF_ERROR_READING_DATA;
+ }
+
+
+ DEBUG(TNEF->Debug, 2, "About to read type");
+ if (TNEF->IO.ReadProc(&(TNEF->IO), sizeof(DWORD), 1, type) < 1) {
+ if (TNEF->Debug >= 1)
+ printf("ERROR: Error reading type\n");
+ return YTNEF_ERROR_READING_DATA;
+ }
+ DEBUG1(TNEF->Debug, 2, "Type = %i", *type);
+
+
+ DEBUG(TNEF->Debug, 2, "About to read size");
+ if (TNEF->IO.ReadProc(&(TNEF->IO), sizeof(DWORD), 1, size) < 1) {
+ if (TNEF->Debug >= 1)
+ printf("ERROR: Error reading size\n");
+ return YTNEF_ERROR_READING_DATA;
+ }
+
+
+ DEBUG1(TNEF->Debug, 2, "Size = %i", *size);
+
+ *type = SwapDWord((BYTE*)type);
+ *size = SwapDWord((BYTE*)size);
+
+ return 0;
+}
+
+// -----------------------------------------------------------------------------
+int TNEFRawRead(TNEFStruct *TNEF, BYTE *data, DWORD size, WORD *checksum) {
+ WORD temp;
+ int i;
+
+ if (TNEF->IO.ReadProc(&TNEF->IO, sizeof(BYTE), size, data) < size) {
+ if (TNEF->Debug >= 1)
+ printf("ERROR: Error reading data\n");
+ return YTNEF_ERROR_READING_DATA;
+ }
+
+
+ if (checksum != NULL) {
+ *checksum = 0;
+ for(i=0; i<size; i++) {
+ temp = data[i];
+ *checksum = (*checksum + temp);
+ }
+ }
+ return 0;
+}
+
+#define INITVARLENGTH(x) (x).data = NULL; (x).size = 0;
+#define INITDTR(x) (x).wYear=0; (x).wMonth=0; (x).wDay=0; \
+ (x).wHour=0; (x).wMinute=0; (x).wSecond=0; \
+ (x).wDayOfWeek=0;
+#define INITSTR(x) memset((x), 0, sizeof(x));
+void TNEFInitMapi(MAPIProps *p)
+{
+ p->count = 0;
+ p->properties = NULL;
+}
+
+void TNEFInitAttachment(Attachment *p)
+{
+ INITDTR(p->Date);
+ INITVARLENGTH(p->Title);
+ INITVARLENGTH(p->MetaFile);
+ INITDTR(p->CreateDate);
+ INITDTR(p->ModifyDate);
+ INITVARLENGTH(p->TransportFilename);
+ INITVARLENGTH(p->FileData);
+ INITVARLENGTH(p->IconData);
+ memset(&(p->RenderData), 0, sizeof(renddata));
+ TNEFInitMapi(&(p->MAPI));
+ p->next = NULL;
+}
+
+void TNEFInitialize(TNEFStruct *TNEF)
+{
+ INITSTR(TNEF->version);
+ INITVARLENGTH(TNEF->from);
+ INITVARLENGTH(TNEF->subject);
+ INITDTR(TNEF->dateSent);
+ INITDTR(TNEF->dateReceived);
+
+ INITSTR(TNEF->messageStatus);
+ INITSTR(TNEF->messageClass);
+ INITSTR(TNEF->messageID);
+ INITSTR(TNEF->parentID);
+ INITSTR(TNEF->conversationID);
+ INITVARLENGTH(TNEF->body);
+ INITSTR(TNEF->priority);
+ TNEFInitAttachment(&(TNEF->starting_attach));
+ INITDTR(TNEF->dateModified);
+ TNEFInitMapi(&(TNEF->MapiProperties));
+ INITVARLENGTH(TNEF->CodePage);
+ INITVARLENGTH(TNEF->OriginalMessageClass);
+ INITVARLENGTH(TNEF->Owner);
+ INITVARLENGTH(TNEF->SentFor);
+ INITVARLENGTH(TNEF->Delegate);
+ INITDTR(TNEF->DateStart);
+ INITDTR(TNEF->DateEnd);
+ INITVARLENGTH(TNEF->AidOwner);
+ TNEF->RequestRes=0;
+ TNEF->IO.data = NULL;
+ TNEF->IO.InitProc = NULL;
+ TNEF->IO.ReadProc = NULL;
+ TNEF->IO.CloseProc = NULL;
+}
+#undef INITVARLENGTH
+#undef INITDTR
+#undef INITSTR
+
+#define FREEVARLENGTH(x) if ((x).size > 0) { \
+ free((x).data); (x).size =0; }
+void TNEFFree(TNEFStruct *TNEF) {
+ Attachment *p, *store;
+
+ FREEVARLENGTH(TNEF->from);
+ FREEVARLENGTH(TNEF->subject);
+ FREEVARLENGTH(TNEF->body);
+ FREEVARLENGTH(TNEF->CodePage);
+ FREEVARLENGTH(TNEF->OriginalMessageClass);
+ FREEVARLENGTH(TNEF->Owner);
+ FREEVARLENGTH(TNEF->SentFor);
+ FREEVARLENGTH(TNEF->Delegate);
+ FREEVARLENGTH(TNEF->AidOwner);
+ TNEFFreeMapiProps(&(TNEF->MapiProperties));
+
+ p = TNEF->starting_attach.next;
+ while (p != NULL) {
+ TNEFFreeAttachment(p);
+ store = p->next;
+ free(p);
+ p=store;
+ }
+}
+
+void TNEFFreeAttachment(Attachment *p)
+{
+ FREEVARLENGTH(p->Title);
+ FREEVARLENGTH(p->MetaFile);
+ FREEVARLENGTH(p->TransportFilename);
+ FREEVARLENGTH(p->FileData);
+ FREEVARLENGTH(p->IconData);
+ TNEFFreeMapiProps(&(p->MAPI));
+}
+
+void TNEFFreeMapiProps(MAPIProps *p)
+{
+ int i,j;
+ for(i=0; i<p->count; i++) {
+ for(j=0; j<p->properties[i].count; j++) {
+ FREEVARLENGTH(p->properties[i].data[j]);
+ }
+ free(p->properties[i].data);
+ }
+ free(p->properties);
+ p->count = 0;
+}
+#undef FREEVARLENGTH
+
+// Procedures to handle File IO
+int TNEFFile_Open (TNEFIOStruct *IO) {
+ TNEFFileInfo *finfo;
+ finfo = (TNEFFileInfo*)IO->data;
+
+ DEBUG1(finfo->Debug, 3, "Opening %s", finfo->filename);
+ if ((finfo->fptr = g_fopen(finfo->filename, "rb")) == NULL) {
+ return -1;
+ } else {
+ return 0;
+ }
+}
+
+int TNEFFile_Read (TNEFIOStruct *IO, int size, int count, void *dest) {
+ TNEFFileInfo *finfo;
+ finfo = (TNEFFileInfo*)IO->data;
+
+ DEBUG2(finfo->Debug, 3, "Reading %i blocks of %i size", count, size);
+ if (finfo->fptr != NULL) {
+ return fread((BYTE*)dest, size, count, finfo->fptr);
+ } else {
+ return -1;
+ }
+}
+
+int TNEFFile_Close (TNEFIOStruct *IO) {
+ TNEFFileInfo *finfo;
+ finfo = (TNEFFileInfo*)IO->data;
+
+ DEBUG1(finfo->Debug, 3, "Closing file %s", finfo->filename);
+ if (finfo->fptr != NULL) {
+ fclose(finfo->fptr);
+ finfo->fptr = NULL;
+ }
+ return 0;
+}
+
+int TNEFParseFile(char *filename, TNEFStruct *TNEF) {
+ TNEFFileInfo finfo;
+
+ if (TNEF->Debug >= 1)
+ printf("Attempting to parse %s...\n", filename);
+
+
+ finfo.filename = filename;
+ finfo.fptr = NULL;
+ finfo.Debug = TNEF->Debug;
+ TNEF->IO.data = (void*)&finfo;
+ TNEF->IO.InitProc = TNEFFile_Open;
+ TNEF->IO.ReadProc = TNEFFile_Read;
+ TNEF->IO.CloseProc = TNEFFile_Close;
+ return TNEFParse(TNEF);
+}
+//-------------------------------------------------------------
+// Procedures to handle Memory IO
+int TNEFMemory_Open (TNEFIOStruct *IO) {
+ TNEFMemInfo *minfo;
+ minfo = (TNEFMemInfo*)IO->data;
+
+ minfo->ptr = minfo->dataStart;
+ return 0;
+}
+
+int TNEFMemory_Read (TNEFIOStruct *IO, int size, int count, void *dest) {
+ TNEFMemInfo *minfo;
+ int length;
+ long max;
+ minfo = (TNEFMemInfo*)IO->data;
+
+ length = count*size;
+ max = (minfo->dataStart + minfo->size) - (minfo->ptr);
+ if (length > max) {
+ return -1;
+ }
+
+ DEBUG1(minfo->Debug, 3, "Copying %i bytes", length);
+
+ memcpy(dest, minfo->ptr, length);
+ minfo->ptr+=length;
+ return count;
+}
+
+int TNEFMemory_Close (TNEFIOStruct *IO) {
+ // Do nothing, really...
+ return 0;
+}
+
+int TNEFParseMemory(BYTE *memory, long size, TNEFStruct *TNEF) {
+ TNEFMemInfo minfo;
+
+ DEBUG(TNEF->Debug, 1, "Attempting to parse memory block...\n");
+
+ minfo.dataStart = memory;
+ minfo.ptr = memory;
+ minfo.size = size;
+ minfo.Debug = TNEF->Debug;
+ TNEF->IO.data = (void*)&minfo;
+ TNEF->IO.InitProc = TNEFMemory_Open;
+ TNEF->IO.ReadProc = TNEFMemory_Read;
+ TNEF->IO.CloseProc = TNEFMemory_Close;
+ return TNEFParse(TNEF);
+}
+
+
+int TNEFParse(TNEFStruct *TNEF) {
+ WORD key;
+ DWORD type;
+ DWORD size;
+ DWORD signature;
+ BYTE *data;
+ WORD checksum, header_checksum;
+ int i;
+
+ if (TNEF->IO.ReadProc == NULL) {
+ printf("ERROR: Setup incorrectly: No ReadProc\n");
+ return YTNEF_INCORRECT_SETUP;
+ }
+
+ if (TNEF->IO.InitProc != NULL) {
+ DEBUG(TNEF->Debug, 2, "About to initialize");
+ if (TNEF->IO.InitProc (&TNEF->IO) != 0) {
+ return YTNEF_CANNOT_INIT_DATA;
+ }
+ DEBUG(TNEF->Debug, 2, "Initialization finished");
+ }
+
+ DEBUG(TNEF->Debug, 2, "Reading Signature");
+ if (TNEF->IO.ReadProc (&TNEF->IO, sizeof(DWORD), 1, &signature) < 1) {
+ printf("ERROR: Error reading signature\n");
+ if (TNEF->IO.CloseProc != NULL) {
+ TNEF->IO.CloseProc (&TNEF->IO);
+ }
+ return YTNEF_ERROR_READING_DATA;
+ }
+
+ DEBUG(TNEF->Debug, 2, "Checking Signature");
+ if (TNEFCheckForSignature(signature) < 0) {
+ printf("ERROR: Signature does not match. Not TNEF.\n");
+ if (TNEF->IO.CloseProc != NULL) {
+ TNEF->IO.CloseProc (&TNEF->IO);
+ }
+ return YTNEF_NOT_TNEF_STREAM;
+ }
+
+ DEBUG(TNEF->Debug, 2, "Reading Key.");
+
+ if (TNEFGetKey(TNEF, &key) < 0) {
+ printf("ERROR: Unable to retrieve key.\n");
+ if (TNEF->IO.CloseProc != NULL) {
+ TNEF->IO.CloseProc (&TNEF->IO);
+ }
+ return YTNEF_NO_KEY;
+ }
+
+ DEBUG(TNEF->Debug, 2, "Starting Full Processing.");
+
+ while (TNEFGetHeader(TNEF, &type, &size) == 0) {
+ DEBUG2(TNEF->Debug, 2, "Header says type=%i, size=%i", type, size);
+ if (size > 0) {
+ data = calloc(size, sizeof(BYTE));
+ if (TNEFRawRead(TNEF, data, size, &header_checksum)< 0) {
+ printf("ERROR: Unable to read data.\n");
+ if (TNEF->IO.CloseProc != NULL) {
+ TNEF->IO.CloseProc (&TNEF->IO);
+ }
+ free(data);
+ return YTNEF_ERROR_READING_DATA;
+ }
+ if (TNEFRawRead(TNEF, (BYTE *)&checksum, 2, NULL) < 0) {
+ printf("ERROR: Unable to read checksum.\n");
+ if (TNEF->IO.CloseProc != NULL) {
+ TNEF->IO.CloseProc (&TNEF->IO);
+ }
+ free(data);
+ return YTNEF_ERROR_READING_DATA;
+ }
+ checksum = SwapWord((BYTE*)&checksum);
+ if (checksum != header_checksum) {
+ printf("ERROR: Checksum mismatch. Data corruption?:\n");
+ if (TNEF->IO.CloseProc != NULL) {
+ TNEF->IO.CloseProc (&TNEF->IO);
+ }
+ free(data);
+ return YTNEF_BAD_CHECKSUM;
+ }
+ for(i=0; i<(sizeof(TNEFList)/sizeof(TNEFHandler));i++) {
+ if (TNEFList[i].id == type) {
+ if (TNEFList[i].handler != NULL) {
+ if (TNEFList[i].handler(TNEF, i, data, size) < 0) {
+ free(data);
+ if (TNEF->IO.CloseProc != NULL) {
+ TNEF->IO.CloseProc (&TNEF->IO);
+ }
+ return YTNEF_ERROR_IN_HANDLER;
+ }
+ } else {
+ DEBUG2(TNEF->Debug, 1, "No handler for %s: %i bytes",
+ TNEFList[i].name, size);
+ }
+ }
+ }
+
+ free(data);
+ }
+ }
+
+ if (TNEF->IO.CloseProc != NULL) {
+ TNEF->IO.CloseProc (&TNEF->IO);
+ }
+ return 0;
+
+}
+
+// ----------------------------------------------------------------------------
+
+variableLength *MAPIFindUserProp(MAPIProps *p, unsigned int ID)
+{
+ int i;
+ if (p != NULL) {
+ for(i=0;i<p->count; i++) {
+ if ((p->properties[i].id == ID) && (p->properties[i].custom == 1)) {
+ return (p->properties[i].data);
+ }
+ }
+ }
+ return MAPI_UNDEFINED;
+}
+
+variableLength *MAPIFindProperty(MAPIProps *p, unsigned int ID)
+{
+ int i;
+ if (p != NULL) {
+ for(i=0;i<p->count; i++) {
+ if ((p->properties[i].id == ID) && (p->properties[i].custom == 0)) {
+ return (p->properties[i].data);
+ }
+ }
+ }
+ return MAPI_UNDEFINED;
+}
+
+int MAPISysTimetoDTR(BYTE *data, dtr *thedate)
+{
+ DDWORD ddword_tmp;
+ int startingdate = 0;
+ int tmp_date;
+ int days_in_year = 365;
+ unsigned int months[] = {31,28,31,30,31,30,31,31,30,31,30,31};
+
+ ddword_tmp = *((DDWORD*)data);
+ ddword_tmp = ddword_tmp /10; // micro-s
+ ddword_tmp /= 1000; // ms
+ ddword_tmp /= 1000; // s
+
+ thedate->wSecond = (ddword_tmp % 60);
+
+ ddword_tmp /= 60; // seconds to minutes
+ thedate->wMinute = (ddword_tmp % 60);
+
+ ddword_tmp /= 60; //minutes to hours
+ thedate->wHour = (ddword_tmp % 24);
+
+ ddword_tmp /= 24; // Hours to days
+
+ // Now calculate the year based on # of days
+ thedate->wYear = 1601;
+ startingdate = 1;
+ while(ddword_tmp >= days_in_year) {
+ ddword_tmp-=days_in_year;
+ thedate->wYear++;
+ days_in_year = 365;
+ startingdate++;
+ if ((thedate->wYear % 4) == 0) {
+ if ((thedate->wYear % 100) == 0) {
+ // if the year is 1700,1800,1900, etc, then it is only
+ // a leap year if exactly divisible by 400, not 4.
+ if ((thedate->wYear % 400) == 0) {
+ startingdate++;
+ days_in_year = 366;
+ }
+ } else {
+ startingdate++;
+ days_in_year = 366;
+ }
+ }
+ startingdate %= 7;
+ }
+
+ // the remaining number is the day # in this year
+ // So now calculate the Month, & Day of month
+ if ((thedate->wYear % 4) == 0) {
+ // 29 days in february in a leap year
+ months[1] = 29;
+ }
+
+ tmp_date = (int)ddword_tmp;
+ thedate->wDayOfWeek = (tmp_date + startingdate) % 7;
+ thedate->wMonth = 0;
+
+ while (tmp_date > months[thedate->wMonth]) {
+ tmp_date -= months[thedate->wMonth];
+ thedate->wMonth++;
+ }
+ thedate->wMonth++;
+ thedate->wDay = tmp_date+1;
+ return 0;
+}
+
+int IsCompressedRTF(variableLength *p) {
+ unsigned int in;
+ unsigned char *src;
+ ULONG compressedSize, uncompressedSize, magic, crc32;
+
+ src = p->data;
+ in = 0;
+
+ compressedSize = (ULONG)SwapDWord(src+in);
+ in += 4;
+ uncompressedSize = (ULONG)SwapDWord(src+in);
+ in += 4;
+ magic = SwapDWord(src+in);
+ in += 4;
+ crc32 = SwapDWord(src+in);
+ in += 4;
+
+ if (magic == 0x414c454d) {
+ return 1;
+ } else if (magic == 0x75465a4c) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+void MAPIPrint(MAPIProps *p)
+{
+ int j, i,index, h;
+ dtr thedate;
+ MAPIProperty *mapi;
+ variableLength *mapidata;
+ variableLength vlTemp;
+ int found;
+
+ for(j=0; j<p->count; j++) {
+ mapi = &(p->properties[j]);
+ printf(" #%i: Type: [", j);
+ switch (PROP_TYPE(mapi->id)) {
+ case PT_UNSPECIFIED:
+ printf(" NONE "); break;
+ case PT_NULL:
+ printf(" NULL "); break;
+ case PT_I2:
+ printf(" I2 "); break;
+ case PT_LONG:
+ printf(" LONG "); break;
+ case PT_R4:
+ printf(" R4 "); break;
+ case PT_DOUBLE:
+ printf(" DOUBLE "); break;
+ case PT_CURRENCY:
+ printf("CURRENCY "); break;
+ case PT_APPTIME:
+ printf("APP TIME "); break;
+ case PT_ERROR:
+ printf(" ERROR "); break;
+ case PT_BOOLEAN:
+ printf(" BOOLEAN "); break;
+ case PT_OBJECT:
+ printf(" OBJECT "); break;
+ case PT_I8:
+ printf(" I8 "); break;
+ case PT_STRING8:
+ printf(" STRING8 "); break;
+ case PT_UNICODE:
+ printf(" UNICODE "); break;
+ case PT_SYSTIME:
+ printf("SYS TIME "); break;
+ case PT_CLSID:
+ printf("OLE GUID "); break;
+ case PT_BINARY:
+ printf(" BINARY "); break;
+ default:
+ printf("<%x>", PROP_TYPE(mapi->id)); break;
+ }
+
+ printf("] Code: [");
+ if (mapi->custom == 1) {
+ printf("UD:x%04x", PROP_ID(mapi->id));
+ } else {
+ found = 0;
+ for(index=0; index<sizeof(MPList)/sizeof(MAPIPropertyTagList); index++) {
+ if ((MPList[index].id == PROP_ID(mapi->id)) && (found == 0)) {
+ printf("%s", MPList[index].name);
+ found = 1;
+ }
+ }
+ if (found == 0) {
+ printf("0x%04x", PROP_ID(mapi->id));
+ }
+ }
+ printf("]\n");
+ if (mapi->namedproperty > 0) {
+ for(i=0; i<mapi->namedproperty; i++) {
+ printf(" Name: %s\n", mapi->propnames[i].data);
+ }
+ }
+ for (i=0;i<mapi->count;i++) {
+ mapidata = &(mapi->data[i]);
+ if (mapi->count > 1) {
+ printf(" [%i/%i] ", i, mapi->count);
+ } else {
+ printf(" ");
+ }
+ printf("Size: %i", mapidata->size);
+ switch (PROP_TYPE(mapi->id)) {
+ case PT_SYSTIME:
+ MAPISysTimetoDTR(mapidata->data, &thedate);
+ printf(" Value: ");
+ TNEFPrintDate(thedate);
+ printf("\n");
+ break;
+ case PT_LONG:
+ printf(" Value: %li\n", (long int) *(mapidata->data));
+ break;
+ case PT_I2:
+ printf(" Value: %hi\n", *(mapidata->data));
+ break;
+ case PT_BOOLEAN:
+ if (mapi->data->data[0]!=0) {
+ printf(" Value: True\n");
+ } else {
+ printf(" Value: False\n");
+ }
+ break;
+ case PT_OBJECT:
+ printf("\n");
+ break;
+ case PT_BINARY:
+ if(IsCompressedRTF(mapidata)==1) {
+ printf(" Detected Compressed RTF.");
+ printf("Decompressed text follows\n");
+ printf("-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-\n");
+ if((vlTemp.data = DecompressRTF(mapidata, &(vlTemp.size))) != NULL) {
+ printf("%s\n", vlTemp.data);
+ free(vlTemp.data);
+ }
+ printf("-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-\n");
+ } else {
+ printf(" Value: [");
+ for(h=0; h< mapidata->size; h++) {
+ if (isprint(mapidata->data[h]))
+ printf("%c", mapidata->data[h]);
+ else
+ printf(".");
+
+ }
+ printf("]\n");
+ }
+ break;
+ case PT_STRING8:
+ printf(" Value: [%s]\n", mapidata->data);
+ if (strlen(mapidata->data) != mapidata->size-1) {
+ printf("Detected Hidden data: [");
+ for(h=0; h< mapidata->size; h++) {
+ if (isprint(mapidata->data[h]))
+ printf("%c", mapidata->data[h]);
+ else
+ printf(".");
+
+ }
+ printf("]\n");
+ }
+ break;
+ default:
+ printf(" Value: [%s]\n", mapidata->data);
+ }
+ }
+ }
+}
+
+unsigned char *DecompressRTF(variableLength *p, int *size) {
+ unsigned char *dst; // destination for uncompressed bytes
+ unsigned char *src;
+ unsigned int in;
+ unsigned int out;
+ variableLength comp_Prebuf;
+ ULONG compressedSize, uncompressedSize, magic, crc32;
+
+ comp_Prebuf.size = strlen(RTF_PREBUF);
+ comp_Prebuf.data = calloc(comp_Prebuf.size + 1, 1);
+ strcpy(comp_Prebuf.data, RTF_PREBUF);
+
+ src = p->data;
+ in = 0;
+
+ compressedSize = (ULONG)SwapDWord(src+in);
+ in += 4;
+ uncompressedSize = (ULONG)SwapDWord(src+in);
+ in += 4;
+ magic = SwapDWord(src+in);
+ in += 4;
+ crc32 = SwapDWord(src+in);
+ in += 4;
+
+ // check size excluding the size field itself
+ if (compressedSize != p->size - 4) {
+ printf(" Size Mismatch: %i != %i\n", compressedSize, p->size-4);
+ return NULL;
+ }
+
+ // process the data
+ if (magic == 0x414c454d) {
+ // magic number that identifies the stream as a uncompressed stream
+ dst = calloc(uncompressedSize,1);
+ memcpy(dst, src+4, uncompressedSize);
+ return dst;
+ } else if (magic == 0x75465a4c) {
+ // magic number that identifies the stream as a compressed stream
+ int flagCount = 0;
+ int flags = 0;
+ dst = calloc(comp_Prebuf.size + uncompressedSize,1);
+ memcpy(dst, comp_Prebuf.data, comp_Prebuf.size);
+ out = comp_Prebuf.size;
+ while (out < (comp_Prebuf.size+uncompressedSize)) {
+ // each flag byte flags 8 literals/references, 1 per bit
+ flags = (flagCount++ % 8 == 0) ? src[in++] : flags >> 1;
+ if ((flags & 1) == 1) { // each flag bit is 1 for reference, 0 for literal
+ int offset = src[in++];
+ int length = src[in++];
+ int end;
+ offset = (offset << 4) | (length >> 4); // the offset relative to block start
+ length = (length & 0xF) + 2; // the number of bytes to copy
+ // the decompression buffer is supposed to wrap around back
+ // to the beginning when the end is reached. we save the
+ // need for such a buffer by pointing straight into the data
+ // buffer, and simulating this behaviour by modifying the
+ // pointers appropriately.
+ offset = (out / 4096) * 4096 + offset;
+ if (offset >= out) // take from previous block
+ offset -= 4096;
+ // note: can't use System.arraycopy, because the referenced
+ // bytes can cross through the current out position.
+ end = offset + length;
+ while (offset < end)
+ dst[out++] = dst[offset++];
+ } else { // literal
+ dst[out++] = src[in++];
+ }
+ }
+ // copy it back without the prebuffered data
+ src = dst;
+ dst = calloc(uncompressedSize,1);
+ memcpy(dst, src + comp_Prebuf.size, uncompressedSize);
+ free(src);
+ *size = uncompressedSize;
+ return dst;
+ } else { // unknown magic number
+ printf("Unknown compression type (magic number %x)\n", magic );
+ return NULL;
+ }
+}
--- /dev/null
+#ifndef _TNEF_PROCS_H_
+#define _TNEF_PROCS_H_
+
+#include "tnef-types.h"
+#include "mapi.h"
+#include "mapidefs.h"
+#define STD_ARGLIST (TNEFStruct *TNEF, int id, unsigned char *data, int size)
+DWORD SwapDWord(BYTE *p);
+WORD SwapWord(BYTE *p);
+
+
+void TNEFInitMapi(MAPIProps *p);
+void TNEFInitAttachment(Attachment *p);
+void TNEFInitialize(TNEFStruct *TNEF);
+void TNEFFree(TNEFStruct *TNEF);
+void TNEFFreeAttachment(Attachment *p);
+void TNEFFreeMapiProps(MAPIProps *p);
+int TNEFCheckForSignature(DWORD sig);
+int TNEFParseMemory(BYTE *memory, long size, TNEFStruct *TNEF);
+int TNEFParseFile(char *filename, TNEFStruct *TNEF);
+int TNEFParse(TNEFStruct *TNEF);
+variableLength *MAPIFindUserProp(MAPIProps *p, unsigned int ID);
+variableLength *MAPIFindProperty(MAPIProps *p, unsigned int ID);
+int MAPISysTimetoDTR(BYTE *data, dtr *thedate);
+void MAPIPrint(MAPIProps *p);
+char* to_utf8(int len, char* buf);
+WORD SwapWord(BYTE *p);
+DWORD SwapDWord(BYTE *p);
+DDWORD SwapDDWord(BYTE *p);
+variableLength *MAPIFindUserProp(MAPIProps *p, unsigned int ID);
+variableLength *MAPIFindProperty(MAPIProps *p, unsigned int ID);
+unsigned char * DecompressRTF(variableLength *p, int *size);
+
+/* ------------------------------------- */
+/* TNEF Down-level Attributes/Properties */
+/* ------------------------------------- */
+
+#define atpTriples ((WORD) 0x0000)
+#define atpString ((WORD) 0x0001)
+#define atpText ((WORD) 0x0002)
+#define atpDate ((WORD) 0x0003)
+#define atpShort ((WORD) 0x0004)
+#define atpLong ((WORD) 0x0005)
+#define atpByte ((WORD) 0x0006)
+#define atpWord ((WORD) 0x0007)
+#define atpDword ((WORD) 0x0008)
+#define atpMax ((WORD) 0x0009)
+
+#define LVL_MESSAGE ((BYTE) 0x01)
+#define LVL_ATTACHMENT ((BYTE) 0x02)
+
+#define ATT_ID(_att) ((WORD) ((_att) & 0x0000FFFF))
+#define ATT_TYPE(_att) ((WORD) (((_att) >> 16) & 0x0000FFFF))
+#define ATT(_atp, _id) ((((DWORD) (_atp)) << 16) | ((WORD) (_id)))
+
+#define attNull ATT( 0, 0x0000)
+#define attFrom ATT( atpTriples, 0x8000) /* PR_ORIGINATOR_RETURN_ADDRESS */
+#define attSubject ATT( atpString, 0x8004) /* PR_SUBJECT */
+#define attDateSent ATT( atpDate, 0x8005) /* PR_CLIENT_SUBMIT_TIME */
+#define attDateRecd ATT( atpDate, 0x8006) /* PR_MESSAGE_DELIVERY_TIME */
+#define attMessageStatus ATT( atpByte, 0x8007) /* PR_MESSAGE_FLAGS */
+#define attMessageClass ATT( atpWord, 0x8008) /* PR_MESSAGE_CLASS */
+#define attMessageID ATT( atpString, 0x8009) /* PR_MESSAGE_ID */
+#define attParentID ATT( atpString, 0x800A) /* PR_PARENT_ID */
+#define attConversationID ATT( atpString, 0x800B) /* PR_CONVERSATION_ID */
+#define attBody ATT( atpText, 0x800C) /* PR_BODY */
+#define attPriority ATT( atpShort, 0x800D) /* PR_IMPORTANCE */
+#define attAttachData ATT( atpByte, 0x800F) /* PR_ATTACH_DATA_xxx */
+#define attAttachTitle ATT( atpString, 0x8010) /* PR_ATTACH_FILENAME */
+#define attAttachMetaFile ATT( atpByte, 0x8011) /* PR_ATTACH_RENDERING */
+#define attAttachCreateDate ATT( atpDate, 0x8012) /* PR_CREATION_TIME */
+#define attAttachModifyDate ATT( atpDate, 0x8013) /* PR_LAST_MODIFICATION_TIME */
+#define attDateModified ATT( atpDate, 0x8020) /* PR_LAST_MODIFICATION_TIME */
+#define attAttachTransportFilename ATT( atpByte, 0x9001) /* PR_ATTACH_TRANSPORT_NAME */
+#define attAttachRenddata ATT( atpByte, 0x9002)
+#define attMAPIProps ATT( atpByte, 0x9003)
+#define attRecipTable ATT( atpByte, 0x9004) /* PR_MESSAGE_RECIPIENTS */
+#define attAttachment ATT( atpByte, 0x9005)
+#define attTnefVersion ATT( atpDword, 0x9006)
+#define attOemCodepage ATT( atpByte, 0x9007)
+#define attOriginalMessageClass ATT( atpWord, 0x0006) /* PR_ORIG_MESSAGE_CLASS */
+
+#define attOwner ATT( atpByte, 0x0000) /* PR_RCVD_REPRESENTING_xxx or
+ PR_SENT_REPRESENTING_xxx */
+#define attSentFor ATT( atpByte, 0x0001) /* PR_SENT_REPRESENTING_xxx */
+#define attDelegate ATT( atpByte, 0x0002) /* PR_RCVD_REPRESENTING_xxx */
+#define attDateStart ATT( atpDate, 0x0006) /* PR_DATE_START */
+#define attDateEnd ATT( atpDate, 0x0007) /* PR_DATE_END */
+#define attAidOwner ATT( atpLong, 0x0008) /* PR_OWNER_APPT_ID */
+#define attRequestRes ATT( atpShort, 0x0009) /* PR_RESPONSE_REQUESTED */
+
+typedef struct {
+ DWORD id;
+ char name[40];
+ int (*handler) STD_ARGLIST;
+} TNEFHandler;
+
+
+#endif