[evolution-mapi] Drop unused code and parameters
- From: Milan Crha <mcrha src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-mapi] Drop unused code and parameters
- Date: Wed, 14 Dec 2011 09:11:28 +0000 (UTC)
commit 6702fb2b57f2b193f9634a57c42c4de0239bc63a
Author: Milan Crha <mcrha redhat com>
Date: Wed Dec 14 10:10:35 2011 +0100
Drop unused code and parameters
src/addressbook/e-book-backend-mapi-contacts.c | 12 +-
src/calendar/e-cal-backend-mapi.c | 22 +-
src/camel/camel-mapi-folder.c | 1 -
src/libexchangemapi/e-mapi-cal-utils.c | 1764 +------
src/libexchangemapi/e-mapi-cal-utils.h | 55 +-
src/libexchangemapi/e-mapi-connection.c | 6999 +++++++++---------------
src/libexchangemapi/e-mapi-connection.h | 154 +-
src/libexchangemapi/e-mapi-fast-transfer.c | 146 -
src/libexchangemapi/e-mapi-mail-utils.c | 3453 ++++---------
src/libexchangemapi/e-mapi-mail-utils.h | 80 -
src/libexchangemapi/e-mapi-utils.c | 207 -
src/libexchangemapi/e-mapi-utils.h | 14 -
12 files changed, 3655 insertions(+), 9252 deletions(-)
---
diff --git a/src/addressbook/e-book-backend-mapi-contacts.c b/src/addressbook/e-book-backend-mapi-contacts.c
index a757a32..5ecb253 100644
--- a/src/addressbook/e-book-backend-mapi-contacts.c
+++ b/src/addressbook/e-book-backend-mapi-contacts.c
@@ -58,7 +58,6 @@ struct _EBookBackendMAPIContactsPrivate
static gboolean
build_restriction_from_sexp_query (EMapiConnection *conn,
- mapi_id_t fid,
TALLOC_CTX *mem_ctx,
struct mapi_SRestriction **restrictions,
gpointer user_data,
@@ -431,7 +430,6 @@ transfer_contact_cb (EMapiConnection *conn,
static gboolean
gather_contact_mids_cb (EMapiConnection *conn,
- mapi_id_t fid,
TALLOC_CTX *mem_ctx,
const ListObjectsData *object_data,
guint32 obj_index,
@@ -511,7 +509,6 @@ transfer_contacts_cb (EMapiConnection *conn,
static gboolean
gather_known_uids_cb (EMapiConnection *conn,
- mapi_id_t fid,
TALLOC_CTX *mem_ctx,
const ListObjectsData *object_data,
guint32 obj_index,
@@ -832,17 +829,16 @@ ebbm_contacts_remove_contacts (EBookBackendMAPI *ebma, GCancellable *cancellable
to_remove = NULL;
for (l = id_list; l; l = l->next) {
- mapi_id_t mid;
const gchar *uid = l->data;
- struct id_list *idl = g_new0 (struct id_list, 1);
+ mapi_id_t *pmid = g_new0 (mapi_id_t, 1);
- if (e_mapi_util_mapi_id_from_string (uid, &mid)) {
- idl->id = mid;
- to_remove = g_slist_prepend (to_remove, idl);
+ if (e_mapi_util_mapi_id_from_string (uid, pmid)) {
+ to_remove = g_slist_prepend (to_remove, pmid);
*removed_ids = g_slist_prepend (*removed_ids, g_strdup (uid));
} else {
g_debug ("%s: Failed to decode MID from '%s'", G_STRFUNC, uid);
+ g_free (pmid);
}
}
diff --git a/src/calendar/e-cal-backend-mapi.c b/src/calendar/e-cal-backend-mapi.c
index 36ec3a3..b8356fa 100644
--- a/src/calendar/e-cal-backend-mapi.c
+++ b/src/calendar/e-cal-backend-mapi.c
@@ -512,7 +512,6 @@ struct ListCalendarObjectsData
static gboolean
list_calendar_objects_cb (EMapiConnection *conn,
- mapi_id_t fid,
TALLOC_CTX *mem_ctx,
const ListObjectsData *object_data,
guint32 obj_index,
@@ -1349,7 +1348,6 @@ ecbm_capture_req_props (EMapiConnection *conn,
static gboolean
ecbm_list_for_one_mid_cb (EMapiConnection *conn,
- mapi_id_t fid,
TALLOC_CTX *mem_ctx,
const ListObjectsData *object_data,
guint32 obj_index,
@@ -1370,7 +1368,6 @@ ecbm_list_for_one_mid_cb (EMapiConnection *conn,
static gboolean
ecbm_build_global_id_restriction (EMapiConnection *conn,
- mapi_id_t fid,
TALLOC_CTX *mem_ctx,
struct mapi_SRestriction **restrictions,
gpointer user_data,
@@ -1382,21 +1379,16 @@ ecbm_build_global_id_restriction (EMapiConnection *conn,
struct SPropValue sprop;
struct mapi_SRestriction *restriction;
gchar *propval;
- uint32_t proptag;
g_return_val_if_fail (restrictions != NULL, FALSE);
g_return_val_if_fail (comp != NULL, FALSE);
- proptag = e_mapi_connection_resolve_named_prop (conn, fid, PidLidCleanGlobalObjectId, cancellable, perror);
- if (proptag == MAPI_E_RESERVED)
- proptag = PidLidCleanGlobalObjectId;
-
restriction = talloc_zero (mem_ctx, struct mapi_SRestriction);
g_return_val_if_fail (restriction != NULL, FALSE);
restriction->rt = RES_PROPERTY;
restriction->res.resProperty.relop = RELOP_EQ;
- restriction->res.resProperty.ulPropTag = proptag;
+ restriction->res.resProperty.ulPropTag = PidLidGlobalObjectId;
propval = e_mapi_cal_utils_get_icomp_x_prop (e_cal_component_get_icalcomponent (comp), "X-EVOLUTION-MAPI-GLOBALID");
if (propval && *propval) {
@@ -1414,11 +1406,11 @@ ecbm_build_global_id_restriction (EMapiConnection *conn,
e_cal_component_get_dtstamp (comp, &ical_creation_time);
e_mapi_util_time_t_to_filetime (icaltime_as_timet (ical_creation_time), &creation_time);
- e_mapi_cal_util_generate_globalobjectid (TRUE, uid, NULL, ical_creation_time.year ? &creation_time : NULL, &sb);
+ e_mapi_cal_util_generate_globalobjectid (FALSE, uid, NULL, ical_creation_time.year ? &creation_time : NULL, &sb);
}
g_free (propval);
- set_SPropValue_proptag (&sprop, proptag, &sb);
+ set_SPropValue_proptag (&sprop, PidLidGlobalObjectId, &sb);
cast_mapi_SPropValue (mem_ctx, &(restriction->res.resProperty.lpProp), &sprop);
*restrictions = restriction;
@@ -1874,9 +1866,9 @@ ecbm_remove_object (ECalBackend *backend, EDataCal *cal, GCancellable *cancellab
/*if (e_cal_component_has_attendees (E_CAL_COMPONENT (comp_list->data))) {
} else {*/
- struct id_list *data = g_new (struct id_list, 1);
- data->id = mid;
- list = g_slist_prepend (list, (gpointer) data);
+ mapi_id_t *pmid = g_new (mapi_id_t, 1);
+ *pmid = mid;
+ list = g_slist_prepend (list, pmid);
/* } */
if (e_mapi_connection_remove_items (priv->conn, priv->olFolder, priv->fid, 0, list, cancellable, &ri_error)) {
@@ -1898,7 +1890,7 @@ ecbm_remove_object (ECalBackend *backend, EDataCal *cal, GCancellable *cancellab
} else
mapi_error_to_edc_error (&err, ri_error, OtherError, "Cannot remove items from a server");
- g_slist_free (list);
+ g_slist_free_full (list, g_free);
g_slist_free (comp_list);
}
g_free (calobj);
diff --git a/src/camel/camel-mapi-folder.c b/src/camel/camel-mapi-folder.c
index 003367a..31dccf4 100644
--- a/src/camel/camel-mapi-folder.c
+++ b/src/camel/camel-mapi-folder.c
@@ -240,7 +240,6 @@ struct GatherChangedObjectsData
static gboolean
gather_changed_objects_to_slist (EMapiConnection *conn,
- mapi_id_t fid,
TALLOC_CTX *mem_ctx,
const ListObjectsData *object_data,
guint32 obj_index,
diff --git a/src/libexchangemapi/e-mapi-cal-utils.c b/src/libexchangemapi/e-mapi-cal-utils.c
index ddaba75..690ea2c 100644
--- a/src/libexchangemapi/e-mapi-cal-utils.c
+++ b/src/libexchangemapi/e-mapi-cal-utils.c
@@ -45,9 +45,9 @@
#define d(x)
-static gboolean appt_build_name_id (EMapiConnection *conn, mapi_id_t fid, TALLOC_CTX *mem_ctx, struct SPropTagArray *props, GCancellable *cancellable, GError **perror);
-static gboolean task_build_name_id (EMapiConnection *conn, mapi_id_t fid, TALLOC_CTX *mem_ctx, struct SPropTagArray *props, GCancellable *cancellable, GError **perror);
-static gboolean note_build_name_id (EMapiConnection *conn, mapi_id_t fid, TALLOC_CTX *mem_ctx, struct SPropTagArray *props, GCancellable *cancellable, GError **perror);
+#define DEFAULT_APPT_REMINDER_MINS 15
+#define DEFAULT_TASK_REMINDER_MINS 1080
+
static icalparameter_role
get_role_from_type (OlMailRecipientType type)
@@ -151,1893 +151,190 @@ get_prop_from_taskstatus (icalproperty_status status)
static icalproperty_class
get_class_from_prop (uint32_t prop)
{
- /* FIXME: is this mapping correct ? */
- switch (prop) {
- case olPersonal :
- case olPrivate : return ICAL_CLASS_PRIVATE;
- case olConfidential : return ICAL_CLASS_CONFIDENTIAL;
- case olNormal :
- default : return ICAL_CLASS_PUBLIC;
- }
-}
-
-static uint32_t
-get_prop_from_class (icalproperty_class class)
-{
- /* FIXME: is this mapping correct ? */
- switch (class) {
- case ICAL_CLASS_PRIVATE : return olPrivate;
- case ICAL_CLASS_CONFIDENTIAL : return olConfidential;
- default : return olNormal;
- }
-}
-
-static gint
-get_priority_from_prop (uint32_t prop)
-{
- switch (prop) {
- case PRIORITY_LOW : return 7;
- case PRIORITY_HIGH : return 1;
- case PRIORITY_NORMAL :
- default : return 5;
- }
-}
-
-static uint32_t
-get_prio_prop_from_priority (gint priority)
-{
- if (priority > 0 && priority <= 4)
- return PRIORITY_HIGH;
- else if (priority > 5 && priority <= 9)
- return PRIORITY_LOW;
- else
- return PRIORITY_NORMAL;
-}
-
-static uint32_t
-get_imp_prop_from_priority (gint priority)
-{
- if (priority > 0 && priority <= 4)
- return IMPORTANCE_HIGH;
- else if (priority > 5 && priority <= 9)
- return IMPORTANCE_LOW;
- else
- return IMPORTANCE_NORMAL;
-}
-
-void
-e_mapi_cal_util_fetch_attachments (ECalComponent *comp, GSList **attach_list, const gchar *local_store_uri)
-{
- GSList *comp_attach_list = NULL, *new_attach_list = NULL;
- GSList *l;
- const gchar *uid;
- gchar *safeuid;
-
- e_cal_component_get_attachment_list (comp, &comp_attach_list);
- e_cal_component_get_uid (comp, &uid);
-
- safeuid = g_strdup (uid);
- e_filename_make_safe (safeuid);
- g_return_if_fail (safeuid != NULL);
-
- for (l = comp_attach_list; l; l = l->next) {
- gchar *sfname_uri = (gchar *) l->data;
- gchar *sfname = NULL, *filename = NULL;
- GMappedFile *mapped_file;
- GError *error = NULL;
-
- sfname = g_filename_from_uri (sfname_uri, NULL, NULL);
- mapped_file = g_mapped_file_new (sfname, FALSE, &error);
- filename = g_path_get_basename (sfname);
-
- if (mapped_file) {
- ExchangeMAPIAttachment *attach_item;
- ExchangeMAPIStream *stream;
- guint8 *attach = (guint8 *) g_mapped_file_get_contents (mapped_file);
- guint filelength = g_mapped_file_get_length (mapped_file);
- const gchar *split_name;
- uint32_t flag;
-
- if (g_str_has_prefix (filename, safeuid)) {
- split_name = (filename + strlen (safeuid) + strlen ("-"));
- } else {
- split_name = filename;
- }
-
- new_attach_list = g_slist_append (new_attach_list, g_strdup (sfname_uri));
-
- attach_item = g_new0 (ExchangeMAPIAttachment, 1);
-
- attach_item->cValues = 4;
- attach_item->lpProps = g_new0 (struct SPropValue, attach_item->cValues + 1);
-
- flag = ATTACH_BY_VALUE;
- set_SPropValue_proptag(&(attach_item->lpProps[0]), PR_ATTACH_METHOD, (gconstpointer ) (&flag));
-
- /* MSDN Documentation: When the supplied offset is -1 (0xFFFFFFFF), the
- * attachment is not rendered using the PR_RENDERING_POSITION property.
- * All values other than -1 indicate the position within PR_BODY at which
- * the attachment is to be rendered.
- */
- flag = 0xFFFFFFFF;
- set_SPropValue_proptag(&(attach_item->lpProps[1]), PR_RENDERING_POSITION, (gconstpointer ) (&flag));
-
- set_SPropValue_proptag(&(attach_item->lpProps[2]), PR_ATTACH_FILENAME_UNICODE, (gconstpointer ) g_strdup(split_name));
- set_SPropValue_proptag(&(attach_item->lpProps[3]), PR_ATTACH_LONG_FILENAME_UNICODE, (gconstpointer ) g_strdup(split_name));
-
- stream = g_new0 (ExchangeMAPIStream, 1);
- stream->proptag = PR_ATTACH_DATA_BIN;
- stream->value = g_byte_array_sized_new (filelength);
- stream->value = g_byte_array_append (stream->value, attach, filelength);
- attach_item->streams = g_slist_append (attach_item->streams, stream);
-
- *attach_list = g_slist_append (*attach_list, attach_item);
-
-#if GLIB_CHECK_VERSION(2,21,3)
- g_mapped_file_unref (mapped_file);
-#else
- g_mapped_file_free (mapped_file);
-#endif
- } else if (error) {
- e_mapi_debug_print ("Could not map %s: %s \n", sfname_uri, error->message);
- g_error_free (error);
- }
-
- g_free (filename);
- }
-
- e_cal_component_set_attachment_list (comp, new_attach_list);
-
- g_slist_foreach (new_attach_list, (GFunc) g_free, NULL);
- g_slist_free (new_attach_list);
- g_free (safeuid);
-}
-
-#define RECIP_SENDABLE 0x1
-#define RECIP_ORGANIZER 0x2
-
-void
-e_mapi_cal_util_fetch_organizer (ECalComponent *comp, GSList **recip_list)
-{
- icalcomponent *icalcomp = e_cal_component_get_icalcomponent (comp);
- icalproperty *org_prop = NULL;
- const gchar *org = NULL;
-
- org_prop = icalcomponent_get_first_property (icalcomp, ICAL_ORGANIZER_PROPERTY);
- org = icalproperty_get_organizer (org_prop);
- if (org && *org) {
- ExchangeMAPIRecipient *recipient;
- uint32_t val = 0;
- const gchar *str = NULL;
- icalparameter *param;
-
- recipient = g_new0 (ExchangeMAPIRecipient, 1);
-
- if (!g_ascii_strncasecmp (org, "mailto:", 7))
- recipient->email_id = (org) + 7;
- else
- recipient->email_id = (org);
-
- /* Required properties - set them always */
- recipient->in.req_cValues = 5;
- recipient->in.req_lpProps = g_new0 (struct SPropValue, recipient->in.req_cValues + 1);
-
- val = 0;
- set_SPropValue_proptag (&(recipient->in.req_lpProps[0]), PR_SEND_INTERNET_ENCODING, (gconstpointer )&val);
-
- val = RECIP_SENDABLE | RECIP_ORGANIZER;
- set_SPropValue_proptag (&(recipient->in.req_lpProps[1]), PR_RECIPIENT_FLAGS, (gconstpointer )&val);
-
- val = olResponseNone;
- set_SPropValue_proptag (&(recipient->in.req_lpProps[2]), PR_RECIPIENT_TRACKSTATUS, (gconstpointer )&val);
-
- val = olTo;
- set_SPropValue_proptag (&(recipient->in.req_lpProps[3]), PR_RECIPIENT_TYPE, (gconstpointer ) &val);
-
- param = icalproperty_get_first_parameter (org_prop, ICAL_CN_PARAMETER);
- str = icalparameter_get_cn (param);
- if (!(str && *str))
- str = "";
- set_SPropValue_proptag (&(recipient->in.req_lpProps[4]), PR_RECIPIENT_DISPLAY_NAME_UNICODE, (gconstpointer )(str));
-
- /* External recipient properties - set them only when the recipient is unresolved */
- recipient->in.ext_cValues = 5;
- recipient->in.ext_lpProps = g_new0 (struct SPropValue, recipient->in.ext_cValues + 1);
-
- val = DT_MAILUSER;
- set_SPropValue_proptag (&(recipient->in.ext_lpProps[0]), PR_DISPLAY_TYPE, (gconstpointer )&val);
- val = MAPI_MAILUSER;
- set_SPropValue_proptag (&(recipient->in.ext_lpProps[1]), PR_OBJECT_TYPE, (gconstpointer )&val);
- str = "SMTP";
- set_SPropValue_proptag (&(recipient->in.ext_lpProps[2]), PR_ADDRTYPE_UNICODE, (gconstpointer )(str));
- str = recipient->email_id;
- set_SPropValue_proptag (&(recipient->in.ext_lpProps[3]), PR_SMTP_ADDRESS_UNICODE, (gconstpointer )(str));
-
- param = icalproperty_get_first_parameter (org_prop, ICAL_CN_PARAMETER);
- str = icalparameter_get_cn (param);
- if (!(str && *str))
- str = "";
- set_SPropValue_proptag (&(recipient->in.ext_lpProps[4]), PR_DISPLAY_NAME_UNICODE, (gconstpointer )(str));
-
- *recip_list = g_slist_append (*recip_list, recipient);
- }
-}
-
-void
-e_mapi_cal_util_fetch_recipients (ECalComponent *comp, GSList **recip_list)
-{
- icalcomponent *icalcomp = e_cal_component_get_icalcomponent (comp);
- icalproperty *org_prop = NULL, *att_prop = NULL;
- const gchar *org = NULL;
-
- org_prop = icalcomponent_get_first_property (icalcomp, ICAL_ORGANIZER_PROPERTY);
- org = icalproperty_get_organizer (org_prop);
- if (!org)
- org = "";
-
- att_prop = icalcomponent_get_first_property (icalcomp, ICAL_ATTENDEE_PROPERTY);
- while (att_prop) {
- ExchangeMAPIRecipient *recipient;
- uint32_t val = 0;
- const gchar *str = NULL;
- icalparameter *param;
-
- str = icalproperty_get_attendee (att_prop);
- if (!str || g_ascii_strcasecmp (str, org) == 0) {
- att_prop = icalcomponent_get_next_property (icalcomp, ICAL_ATTENDEE_PROPERTY);
- continue;
- }
-
- recipient = g_new0 (ExchangeMAPIRecipient, 1);
-
- if (!g_ascii_strncasecmp (str, "mailto:", 7))
- recipient->email_id = (str) + 7;
- else
- recipient->email_id = (str);
-
- /* Required properties - set them always */
- recipient->in.req_cValues = 5;
- recipient->in.req_lpProps = g_new0 (struct SPropValue, recipient->in.req_cValues + 1);
-
- val = 0;
- set_SPropValue_proptag (&(recipient->in.req_lpProps[0]), PR_SEND_INTERNET_ENCODING, (gconstpointer )&val);
-
- val = RECIP_SENDABLE | (!g_ascii_strcasecmp(str, org) ? RECIP_ORGANIZER : 0);
- set_SPropValue_proptag (&(recipient->in.req_lpProps[1]), PR_RECIPIENT_FLAGS, (gconstpointer )&val);
-
- param = icalproperty_get_first_parameter (att_prop, ICAL_PARTSTAT_PARAMETER);
- val = get_trackstatus_from_partstat (icalparameter_get_partstat(param));
- set_SPropValue_proptag (&(recipient->in.req_lpProps[2]), PR_RECIPIENT_TRACKSTATUS, (gconstpointer )&val);
-
- param = icalproperty_get_first_parameter (att_prop, ICAL_ROLE_PARAMETER);
- val = get_type_from_role (icalparameter_get_role(param));
- set_SPropValue_proptag (&(recipient->in.req_lpProps[3]), PR_RECIPIENT_TYPE, (gconstpointer ) &val);
-
- param = icalproperty_get_first_parameter (att_prop, ICAL_CN_PARAMETER);
- str = icalparameter_get_cn (param);
- str = (str) ? str : recipient->email_id;
- set_SPropValue_proptag (&(recipient->in.req_lpProps[4]), PR_RECIPIENT_DISPLAY_NAME_UNICODE, (gconstpointer )(str));
-
- /* External recipient properties - set them only when the recipient is unresolved */
- recipient->in.ext_cValues = 7;
- recipient->in.ext_lpProps = g_new0 (struct SPropValue, recipient->in.ext_cValues + 1);
-
- val = DT_MAILUSER;
- set_SPropValue_proptag (&(recipient->in.ext_lpProps[0]), PR_DISPLAY_TYPE, (gconstpointer )&val);
- val = MAPI_MAILUSER;
- set_SPropValue_proptag (&(recipient->in.ext_lpProps[1]), PR_OBJECT_TYPE, (gconstpointer )&val);
- str = "SMTP";
- set_SPropValue_proptag (&(recipient->in.ext_lpProps[2]), PR_ADDRTYPE_UNICODE, (gconstpointer )(str));
- str = recipient->email_id;
- set_SPropValue_proptag (&(recipient->in.ext_lpProps[3]), PR_SMTP_ADDRESS_UNICODE, (gconstpointer )(str));
-
- param = icalproperty_get_first_parameter (att_prop, ICAL_CN_PARAMETER);
- str = icalparameter_get_cn (param);
- str = (str) ? str : recipient->email_id;
- set_SPropValue_proptag (&(recipient->in.ext_lpProps[4]), PR_GIVEN_NAME_UNICODE, (gconstpointer )(str));
- set_SPropValue_proptag (&(recipient->in.ext_lpProps[5]), PR_DISPLAY_NAME_UNICODE, (gconstpointer )(str));
- set_SPropValue_proptag (&(recipient->in.ext_lpProps[6]), PR_7BIT_DISPLAY_NAME_UNICODE, (gconstpointer )(str));
-
- *recip_list = g_slist_append (*recip_list, recipient);
-
- att_prop = icalcomponent_get_next_property (icalcomp, ICAL_ATTENDEE_PROPERTY);
- }
-}
-
-static void
-set_attachments_to_cal_component (ECalComponent *comp, GSList *attach_list, const gchar *local_store_uri)
-{
- GSList *comp_attach_list = NULL, *l;
- const gchar *uid;
- gchar *safeuid;
-
- g_return_if_fail (comp != NULL);
-
- e_cal_component_get_uid (comp, &uid);
-
- safeuid = g_strdup (uid);
- e_filename_make_safe (safeuid);
- g_return_if_fail (safeuid != NULL);
-
- for (l = attach_list; l; l = l->next) {
- ExchangeMAPIAttachment *attach_item = (ExchangeMAPIAttachment *) (l->data);
- ExchangeMAPIStream *stream;
- gchar *attach_file_url, *filename;
- const gchar *str, *attach;
- GError *error = NULL;
- guint len;
- gint fd = -1;
-
- stream = e_mapi_util_find_stream (attach_item->streams, PR_ATTACH_DATA_BIN);
- if (!stream)
- continue;
-
- attach = (const gchar *)stream->value->data;
- len = stream->value->len;
-
- str = (const gchar *) e_mapi_util_find_SPropVal_array_propval(attach_item->lpProps, PR_ATTACH_LONG_FILENAME_UNICODE);
- if (!(str && *str))
- str = (const gchar *) e_mapi_util_find_SPropVal_array_propval(attach_item->lpProps, PR_ATTACH_FILENAME_UNICODE);
- filename = g_strconcat (local_store_uri, G_DIR_SEPARATOR_S, safeuid, "-", str, NULL);
- attach_file_url = g_filename_to_uri (filename, NULL, &error);
-
- if (!attach_file_url) {
- g_message ("Could not get attach_file_url %s \n", error->message);
- g_clear_error (&error);
- g_free (filename);
- return;
- }
-
- fd = g_open (filename, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, 0600);
- if (fd == -1) {
- /* skip gracefully */
- e_mapi_debug_print ("Could not open %s for writing \n", filename);
- } else if (len && write (fd, attach, len) == -1) {
- /* skip gracefully */
- e_mapi_debug_print ("Attachment write failed \n");
- }
- if (fd != -1) {
- close (fd);
- comp_attach_list = g_slist_append (comp_attach_list, g_strdup (attach_file_url));
- }
-
- g_free (filename);
- g_free (attach_file_url);
- }
-
- e_cal_component_set_attachment_list (comp, comp_attach_list);
- g_free (safeuid);
-}
-
-static void
-ical_attendees_from_props (icalcomponent *ical_comp, GSList *recipients, gboolean rsvp)
-{
- GSList *l;
- for (l=recipients; l; l=l->next) {
- ExchangeMAPIRecipient *recip = (ExchangeMAPIRecipient *)(l->data);
- icalproperty *prop = NULL;
- icalparameter *param;
- gchar *val;
- const uint32_t *ui32;
- const gchar *str;
- const uint32_t *flags;
-
- if (recip->email_id)
- val = g_strdup_printf ("MAILTO:%s", recip->email_id);
- else
- continue;
-
- flags = (const uint32_t *) get_SPropValue_SRow_data (&recip->out_SRow, PR_RECIPIENT_FLAGS);
-
- if (flags && (*flags & RECIP_ORGANIZER)) {
- prop = icalproperty_new_organizer (val);
-
- /* CN */
- str = recip->display_name;
- if (!str || !*str)
- str = (const gchar *) e_mapi_util_find_row_propval (&recip->out_SRow, PR_RECIPIENT_DISPLAY_NAME_UNICODE);
- if (!str)
- str = (const gchar *) e_mapi_util_find_row_propval (&recip->out_SRow, PR_DISPLAY_NAME_UNICODE);
- if (str) {
- param = icalparameter_new_cn (str);
- icalproperty_add_parameter (prop, param);
- }
- } else {
- prop = icalproperty_new_attendee (val);
-
- /* CN */
- str = recip->display_name;
- if (!str || !*str)
- str = (const gchar *) e_mapi_util_find_row_propval (&recip->out_SRow, PR_RECIPIENT_DISPLAY_NAME_UNICODE);
- if (!str)
- str = (const gchar *) e_mapi_util_find_row_propval (&recip->out_SRow, PR_DISPLAY_NAME_UNICODE);
- if (str) {
- param = icalparameter_new_cn (str);
- icalproperty_add_parameter (prop, param);
- }
- /* RSVP */
- param = icalparameter_new_rsvp (rsvp ? ICAL_RSVP_TRUE : ICAL_RSVP_FALSE);
- icalproperty_add_parameter (prop, param);
- /* PARTSTAT */
- ui32 = (const uint32_t *) get_SPropValue_SRow_data (&recip->out_SRow, PR_RECIPIENT_TRACKSTATUS);
- param = icalparameter_new_partstat (get_partstat_from_trackstatus (ui32 ? *ui32 : olResponseNone));
- icalproperty_add_parameter (prop, param);
- /* ROLE */
- ui32 = (const uint32_t *) get_SPropValue_SRow_data (&recip->out_SRow, PR_RECIPIENT_TYPE);
- param = icalparameter_new_role (get_role_from_type (ui32 ? *ui32 : olTo));
- icalproperty_add_parameter (prop, param);
-
- /* CALENDAR USER TYPE */
- param = NULL;
- if (ui32 && *ui32 == 0x03)
- param = icalparameter_new_cutype (ICAL_CUTYPE_RESOURCE);
- if (!param)
- param = icalparameter_new_cutype (ICAL_CUTYPE_INDIVIDUAL);
- icalproperty_add_parameter (prop, param);
- }
-
- if (prop)
- icalcomponent_add_property (ical_comp, prop);
-
- g_free (val);
- }
-}
-
-static const uint8_t GID_START_SEQ[] = {
- 0x04, 0x00, 0x00, 0x00, 0x82, 0x00, 0xe0, 0x00,
- 0x74, 0xc5, 0xb7, 0x10, 0x1a, 0x82, 0xe0, 0x08
-};
-
-/* exception_replace_time is a value of PidLidExceptionReplaceTime; this is not used for 'clean' object ids.
- creation_time is a value of PR_CREATION_TIME
-*/
-void
-e_mapi_cal_util_generate_globalobjectid (gboolean is_clean, const gchar *uid, const struct timeval *exception_replace_time, const struct FILETIME *creation_time, struct Binary_r *sb)
-{
- GByteArray *ba;
- guint32 val32;
- guchar *buf = NULL;
- gsize len;
- d(guint32 i);
-
- ba = g_byte_array_new ();
-
- ba = g_byte_array_append (ba, GID_START_SEQ, (sizeof (GID_START_SEQ) / sizeof (GID_START_SEQ[0])));
-
- val32 = 0;
- if (!is_clean && exception_replace_time) {
- struct icaltimetype icaltm = icaltime_from_timet_with_zone (exception_replace_time->tv_sec, 0, icaltimezone_get_utc_timezone ());
-
- val32 |= (icaltm.year & 0xFF00) << 16;
- val32 |= (icaltm.year & 0xFF) << 16;
- val32 |= (icaltm.month & 0xFF) << 8;
- val32 |= (icaltm.day & 0xFF);
- }
-
- ba = g_byte_array_append (ba, (const guint8 *) &val32, sizeof (guint32));
-
- /* creation time */
- val32 = creation_time ? creation_time->dwLowDateTime : 0;
- ba = g_byte_array_append (ba, (const guint8 *) &val32, sizeof (guint32));
- val32 = creation_time ? creation_time->dwHighDateTime : 0;
- ba = g_byte_array_append (ba, (const guint8 *) &val32, sizeof (guint32));
-
- /* RESERVED - should be all 0's */
- val32 = 0;
- ba = g_byte_array_append (ba, (const guint8 *) &val32, sizeof (guint32));
- val32 = 0;
- ba = g_byte_array_append (ba, (const guint8 *) &val32, sizeof (guint32));
-
- /* We put Evolution's UID in base64 here */
- buf = g_base64_decode (uid, &len);
- if (len % 2 != 0)
- --len;
- val32 = len;
-
- /* Size in bytes of the following data */
- ba = g_byte_array_append (ba, (const guint8 *) &val32, sizeof (guint32));
- /* Data */
- ba = g_byte_array_append (ba, (const guint8 *)buf, val32);
- g_free (buf);
-
- sb->lpb = ba->data;
- sb->cb = ba->len;
-
- d(g_message ("New GlobalObjectId.. Length: %d bytes.. Hex-data follows:", ba->len));
- d(for (i = 0; i < ba->len; i++)
- g_print("0x%02X ", ba->data[i]));
-
- g_byte_array_free (ba, FALSE);
-}
-
-/* returns complete globalid as base64 encoded string */
-static gchar *
-globalid_to_string (const guint8 *lpb, guint32 cb)
-{
- const guint8 *ptr;
- guint32 i, j;
-
- g_return_val_if_fail (lpb != NULL, NULL);
-
- /* MSDN docs: the globalID must have an even number of bytes */
- if ((cb) % 2 != 0)
- return NULL;
-
- ptr = lpb;
-
- /* starting seq - len = 16 bytes */
- for (i = 0, j = 0; i < cb && j < sizeof (GID_START_SEQ); i++, ptr++, j++) {
- if (*ptr != GID_START_SEQ[j])
- return NULL;
- }
-
- /* take complete global id */
- return g_base64_encode (lpb, cb);
-}
-
-ECalComponent *
-e_mapi_cal_util_mapi_props_to_comp (EMapiConnection *conn, mapi_id_t fid, icalcomponent_kind kind, const gchar *mid, struct mapi_SPropValue_array *properties,
- GSList *streams, GSList *recipients, GSList *attachments,
- const gchar *local_store_uri, const icaltimezone *default_zone, gboolean is_reply, GSList **detached_components)
-{
- ECalComponent *comp = NULL;
- struct timeval t;
- ExchangeMAPIStream *body_stream;
- const gchar *subject = NULL, *body = NULL;
- const struct StringArrayW_r *categories_array;
- const uint32_t *ui32;
- const bool *b;
- icalcomponent *ical_comp;
- icalproperty *prop = NULL;
- icalparameter *param = NULL;
- const icaltimezone *utc_zone;
-
- switch (kind) {
- case ICAL_VEVENT_COMPONENT:
- case ICAL_VTODO_COMPONENT:
- case ICAL_VJOURNAL_COMPONENT:
- comp = e_cal_component_new ();
- ical_comp = icalcomponent_new (kind);
- e_cal_component_set_icalcomponent (comp, ical_comp);
- icalcomponent_set_uid (ical_comp, mid);
- e_cal_component_set_uid (comp, mid);
- break;
- default:
- return NULL;
- }
-
- utc_zone = icaltimezone_get_utc_timezone ();
-
- subject = (const gchar *)e_mapi_util_find_array_propval(properties, PR_SUBJECT_UNICODE);
- if (!subject)
- subject = (const gchar *)e_mapi_util_find_array_propval(properties, PR_NORMALIZED_SUBJECT_UNICODE);
- if (!subject)
- subject = (const gchar *)e_mapi_util_find_array_propval(properties, PR_CONVERSATION_TOPIC_UNICODE);
- if (!subject)
- subject = "";
-
- body = (const gchar *)e_mapi_util_find_array_propval(properties, PR_BODY_UNICODE);
- if (!body) {
- body_stream = e_mapi_util_find_stream (streams, PR_HTML);
- body = body_stream ? (const gchar *) body_stream->value->data : "";
- }
-
- /* set dtstamp - in UTC */
- if (get_mapi_SPropValue_array_date_timeval (&t, properties, PR_CREATION_TIME) == MAPI_E_SUCCESS)
- icalcomponent_set_dtstamp (ical_comp, icaltime_from_timet_with_zone (t.tv_sec, 0, utc_zone));
-
- /* created - in UTC */
- prop = icalproperty_new_created (icaltime_current_time_with_zone (icaltimezone_get_utc_timezone ()));
- icalcomponent_add_property (ical_comp, prop);
-
- /* last modified - in UTC */
- if (get_mapi_SPropValue_array_date_timeval (&t, properties, PR_LAST_MODIFICATION_TIME) == MAPI_E_SUCCESS) {
- prop = icalproperty_new_lastmodified (icaltime_from_timet_with_zone (t.tv_sec, 0, utc_zone));
- icalcomponent_add_property (ical_comp, prop);
- }
-
- icalcomponent_set_summary (ical_comp, subject);
- icalcomponent_set_description (ical_comp, body);
-
- categories_array = e_mapi_util_find_array_namedid (properties, conn, fid, PidNameKeywords);
- if (categories_array) {
- GSList *categories = NULL;
- gint ii;
-
- for (ii = 0; ii < categories_array->cValues; ii++) {
- const gchar *category = categories_array->lppszW[ii];
-
- if (!category || !*category)
- continue;
-
- categories = g_slist_append (categories, (gpointer) category);
- }
-
- e_cal_component_set_categories_list (comp, categories);
-
- g_slist_free (categories);
- }
-
- if (icalcomponent_isa (ical_comp) == ICAL_VEVENT_COMPONENT) {
- const gchar *location = NULL;
- const gchar *dtstart_tz_location = NULL, *dtend_tz_location = NULL;
- gboolean all_day;
- ExchangeMAPIStream *stream;
-
- /* GlobalObjectId */
- stream = e_mapi_util_find_stream_namedid (streams, conn, fid, PidLidGlobalObjectId);
- if (stream && stream->value) {
- gchar *value = globalid_to_string (stream->value->data, stream->value->len);
- prop = icalproperty_new_x (value);
- icalproperty_set_x_name (prop, "X-EVOLUTION-MAPI-GLOBALID");
- icalcomponent_add_property (ical_comp, prop);
- if (value && *value) {
- e_cal_component_set_uid (comp, value);
-
- if (!g_str_equal (value, mid)) {
- prop = icalproperty_new_x (mid);
- icalproperty_set_x_name (prop, "X-EVOLUTION-MAPI-MID");
- icalcomponent_add_property (ical_comp, prop);
- }
- }
-
- g_free (value);
- }
-
- ui32 = find_mapi_SPropValue_data(properties, PR_OWNER_APPT_ID);
- if (ui32) {
- gchar *value = e_mapi_util_mapi_id_to_string ((mapi_id_t) (*ui32));
-
- prop = icalproperty_new_x (value);
- icalproperty_set_x_name (prop, "X-EVOLUTION-MAPI-OWNER-APPT-ID");
- icalcomponent_add_property (ical_comp, prop);
- g_free (value);
- }
-
- /* AppointmentSequence */
- ui32 = e_mapi_util_find_array_namedid (properties, conn, fid, PidLidAppointmentSequence);
- if (ui32) {
- gchar *value = g_strdup_printf ("%d", *ui32);
- prop = icalproperty_new_x (value);
- icalproperty_set_x_name (prop, "X-EVOLUTION-MAPI-APPTSEQ");
- icalcomponent_add_property (ical_comp, prop);
- g_free (value);
- }
-
- location = e_mapi_util_find_array_namedid (properties, conn, fid, PidLidLocation);
- if (location && *location)
- icalcomponent_set_location (ical_comp, location);
-
- b = e_mapi_util_find_array_namedid (properties, conn, fid, PidLidAppointmentSubType);;
- all_day = b && *b;
-
- stream = e_mapi_util_find_stream_namedid (streams, conn, fid, PidLidAppointmentTimeZoneDefinitionStartDisplay);
- if (stream && stream->value) {
- gchar *buf = e_mapi_cal_util_bin_to_mapi_tz (stream->value->data, stream->value->len);
- dtstart_tz_location = e_mapi_cal_tz_util_get_ical_equivalent (buf);
- g_free (buf);
- }
-
- if (e_mapi_util_find_array_datetime_namedid (&t, properties, conn, fid, PidLidAppointmentStartWhole) == MAPI_E_SUCCESS) {
- icaltimezone *zone = dtstart_tz_location ? icaltimezone_get_builtin_timezone (dtstart_tz_location) : (icaltimezone *)default_zone;
- prop = icalproperty_new_dtstart (icaltime_from_timet_with_zone (t.tv_sec, all_day, zone));
- if (!all_day && zone && icaltimezone_get_tzid (zone)) {
- icalproperty_add_parameter (prop, icalparameter_new_tzid (icaltimezone_get_tzid (zone)));
- }
-
- icalcomponent_add_property (ical_comp, prop);
- }
-
- stream = e_mapi_util_find_stream_namedid (streams, conn, fid, PidLidAppointmentTimeZoneDefinitionEndDisplay);
- if (stream && stream->value) {
- gchar *buf = e_mapi_cal_util_bin_to_mapi_tz (stream->value->data, stream->value->len);
- dtend_tz_location = e_mapi_cal_tz_util_get_ical_equivalent (buf);
- g_free (buf);
- }
-
- if (e_mapi_util_find_array_datetime_namedid (&t, properties, conn, fid, PidLidAppointmentEndWhole) == MAPI_E_SUCCESS) {
- icaltimezone *zone;
-
- if (!dtend_tz_location)
- dtend_tz_location = dtstart_tz_location;
-
- zone = dtend_tz_location ? icaltimezone_get_builtin_timezone (dtend_tz_location) : (icaltimezone *) default_zone;
- prop = icalproperty_new_dtend (icaltime_from_timet_with_zone (t.tv_sec, all_day, zone));
- if (!all_day && zone && icaltimezone_get_tzid (zone)) {
- icalproperty_add_parameter (prop, icalparameter_new_tzid (icaltimezone_get_tzid (zone)));
- }
-
- icalcomponent_add_property (ical_comp, prop);
- }
-
- ui32 = e_mapi_util_find_array_namedid (properties, conn, fid, PidLidBusyStatus);
- if (ui32) {
- prop = icalproperty_new_transp (get_transp_from_prop (*ui32));
- icalcomponent_add_property (ical_comp, prop);
- }
-
- if (recipients) {
- b = (const bool *)find_mapi_SPropValue_data(properties, PR_RESPONSE_REQUESTED);
- ical_attendees_from_props (ical_comp, recipients, (b && *b));
- if (is_reply) {
- if (icalcomponent_get_first_property (ical_comp, ICAL_ORGANIZER_PROPERTY) == NULL) {
- gchar *val, *to_free = NULL;
- const gchar *name = e_mapi_util_find_array_propval (properties, PR_RCVD_REPRESENTING_NAME_UNICODE);
- const gchar *email_type = e_mapi_util_find_array_propval (properties, PR_RCVD_REPRESENTING_ADDRTYPE_UNICODE);
- const gchar *email = e_mapi_util_find_array_propval (properties, PR_RCVD_REPRESENTING_EMAIL_ADDRESS_UNICODE);
-
- if (!name)
- name = "";
- if (!email_type)
- email_type = "";
- if (!email)
- email = "";
-
- if (g_str_equal (email_type, "EX")) {
- to_free = e_mapi_connection_ex_to_smtp (conn, email, NULL, NULL, NULL);
- email = to_free;
- }
-
- val = g_strdup_printf ("MAILTO:%s", email);
- prop = icalproperty_new_organizer (val);
- g_free (val);
-
- /* CN */
- param = icalparameter_new_cn (name);
- icalproperty_add_parameter (prop, param);
-
- icalcomponent_add_property (ical_comp, prop);
-
- g_free (to_free);
- }
-
- if (icalcomponent_get_first_property (ical_comp, ICAL_ATTENDEE_PROPERTY) == NULL) {
- const uint32_t *ui32;
- gchar *val, *to_free = NULL;
- const gchar *name = e_mapi_util_find_array_propval (properties, PR_SENT_REPRESENTING_NAME_UNICODE);
- const gchar *email_type = e_mapi_util_find_array_propval (properties, PR_SENT_REPRESENTING_ADDRTYPE_UNICODE);
- const gchar *email = e_mapi_util_find_array_propval (properties, PR_SENT_REPRESENTING_EMAIL_ADDRESS_UNICODE);
-
- if (!name)
- name = "";
- if (!email_type)
- email_type = "";
- if (!email)
- email = "";
-
- if (g_str_equal (email_type, "EX")) {
- to_free = e_mapi_connection_ex_to_smtp (conn, email, NULL, NULL, NULL);
- email = to_free;
- }
-
- val = g_strdup_printf ("MAILTO:%s", email);
- prop = icalproperty_new_attendee (val);
- g_free (val);
-
- /* CN */
- param = icalparameter_new_cn (name);
- icalproperty_add_parameter (prop, param);
-
- ui32 = e_mapi_util_find_array_namedid (properties, conn, fid, PidLidResponseStatus);
- param = icalparameter_new_partstat (get_partstat_from_trackstatus (ui32 ? *ui32 : olResponseNone));
- icalproperty_add_parameter (prop, param);
-
- icalcomponent_add_property (ical_comp, prop);
-
- g_free (to_free);
- }
- } else if (icalcomponent_get_first_property (ical_comp, ICAL_ORGANIZER_PROPERTY) == NULL) {
- gchar *val, *sender_free = NULL, *sent_free = NULL;
- const gchar *sender_email_type = (const gchar *) e_mapi_util_find_array_propval (properties, PR_SENDER_ADDRTYPE_UNICODE);
- const gchar *sender_email = (const gchar *) e_mapi_util_find_array_propval (properties, PR_SENDER_EMAIL_ADDRESS_UNICODE);
- const gchar *sent_name = (const gchar *) e_mapi_util_find_array_propval (properties, PR_SENT_REPRESENTING_NAME_UNICODE);
- const gchar *sent_email_type = (const gchar *) e_mapi_util_find_array_propval (properties, PR_SENT_REPRESENTING_ADDRTYPE_UNICODE);
- const gchar *sent_email = (const gchar *) e_mapi_util_find_array_propval (properties, PR_SENT_REPRESENTING_EMAIL_ADDRESS_UNICODE);
-
- if (!g_utf8_collate (sender_email_type, "EX")) {
- sender_free = e_mapi_connection_ex_to_smtp (conn, sender_email, NULL, NULL, NULL);
- sender_email = sender_free;
- }
- if (!g_utf8_collate (sent_email_type, "EX")) {
- sent_free = e_mapi_connection_ex_to_smtp (conn, sent_email, NULL, NULL, NULL);
- sent_email = sent_free;
- }
-
- val = g_strdup_printf ("MAILTO:%s", sent_email);
- prop = icalproperty_new_organizer (val);
- g_free (val);
- /* CN */
- param = icalparameter_new_cn (sent_name);
- icalproperty_add_parameter (prop, param);
- /* SENTBY */
- if (g_utf8_collate (sent_email, sender_email)) {
- val = g_strdup_printf ("MAILTO:%s", sender_email);
- param = icalparameter_new_sentby (val);
- icalproperty_add_parameter (prop, param);
- g_free (val);
- }
-
- icalcomponent_add_property (ical_comp, prop);
-
- g_free (sender_free);
- g_free (sent_free);
- }
- }
-
- b = e_mapi_util_find_array_namedid (properties, conn, fid, PidLidRecurring);
- if (b && *b) {
- stream = e_mapi_util_find_stream_namedid (streams, conn, fid, PidLidAppointmentRecur);
- if (stream && stream->value) {
- icaltimezone *recur_zone;
- const gchar *recur_tz_location;
-
- recur_tz_location = e_mapi_util_find_array_namedid (properties, conn, fid, PidLidTimeZoneDescription);
- if (recur_tz_location)
- recur_tz_location = e_mapi_cal_tz_util_get_ical_equivalent (recur_tz_location);
- recur_zone = recur_tz_location ? icaltimezone_get_builtin_timezone (recur_tz_location) : (icaltimezone *) default_zone;
-
- e_mapi_cal_util_bin_to_rrule (stream->value->data, stream->value->len, comp, detached_components, recur_zone);
- }
- }
-
- b = e_mapi_util_find_array_namedid (properties, conn, fid, PidLidReminderSet);
- if (b && *b) {
- struct timeval start, displaytime;
-
- if ((e_mapi_util_find_array_datetime_namedid (&start, properties, conn, fid, PidLidReminderTime) == MAPI_E_SUCCESS)
- && (e_mapi_util_find_array_datetime_namedid (&displaytime, properties, conn, fid, PidLidReminderSignalTime) == MAPI_E_SUCCESS)) {
- ECalComponentAlarm *e_alarm = e_cal_component_alarm_new ();
- ECalComponentAlarmTrigger trigger;
-
- trigger.type = E_CAL_COMPONENT_ALARM_TRIGGER_RELATIVE_START;
- trigger.u.rel_duration = icaltime_subtract (icaltime_from_timet_with_zone (displaytime.tv_sec, 0, 0),
- icaltime_from_timet_with_zone (start.tv_sec, 0, 0));
-
- e_cal_component_alarm_set_action (e_alarm, E_CAL_COMPONENT_ALARM_DISPLAY);
- e_cal_component_alarm_set_trigger (e_alarm, trigger);
-
- e_cal_component_add_alarm (comp, e_alarm);
- }
- } else
- e_cal_component_remove_all_alarms (comp);
-
- } else if (icalcomponent_isa (ical_comp) == ICAL_VTODO_COMPONENT) {
- const double *complete = NULL;
- const uint64_t *status = NULL;
-
- /* NOTE: Exchange tasks are DATE values, not DATE-TIME values, but maybe someday, we could expect Exchange to support it;) */
- if (e_mapi_util_find_array_datetime_namedid (&t, properties, conn, fid, PidLidTaskStartDate) == MAPI_E_SUCCESS)
- icalcomponent_set_dtstart (ical_comp, icaltime_from_timet_with_zone (t.tv_sec, 1, default_zone));
- if (e_mapi_util_find_array_datetime_namedid (&t, properties, conn, fid, PidLidTaskDueDate) == MAPI_E_SUCCESS)
- icalcomponent_set_due (ical_comp, icaltime_from_timet_with_zone (t.tv_sec, 1, default_zone));
-
- status = e_mapi_util_find_array_namedid (properties, conn, fid, PidLidTaskStatus);
- if (status) {
- icalcomponent_set_status (ical_comp, get_taskstatus_from_prop(*status));
- if (*status == olTaskComplete
- && e_mapi_util_find_array_datetime_namedid (&t, properties, conn, fid, PidLidTaskDateCompleted) == MAPI_E_SUCCESS) {
- prop = icalproperty_new_completed (icaltime_from_timet_with_zone (t.tv_sec, 1, default_zone));
- icalcomponent_add_property (ical_comp, prop);
- }
- }
-
- complete = e_mapi_util_find_array_namedid (properties, conn, fid, PidLidPercentComplete);
- if (complete) {
- prop = icalproperty_new_percentcomplete ((gint)(*complete * 100 + 1e-9));
- icalcomponent_add_property (ical_comp, prop);
- }
-
- b = e_mapi_util_find_array_namedid (properties, conn, fid, PidLidTaskFRecurring);
- if (b && *b) {
- /* FIXME: Evolution does not support recurring tasks */
- g_warning ("Encountered a recurring task.");
- }
-
- b = e_mapi_util_find_array_namedid (properties, conn, fid, PidLidReminderSet);
- if (b && *b) {
- struct timeval abs;
-
- if (e_mapi_util_find_array_datetime_namedid (&abs, properties, conn, fid, PidLidReminderTime) == MAPI_E_SUCCESS) {
- ECalComponentAlarm *e_alarm = e_cal_component_alarm_new ();
- ECalComponentAlarmTrigger trigger;
-
- trigger.type = E_CAL_COMPONENT_ALARM_TRIGGER_ABSOLUTE;
- trigger.u.abs_time = icaltime_from_timet_with_zone (abs.tv_sec, 0, default_zone);
-
- e_cal_component_alarm_set_action (e_alarm, E_CAL_COMPONENT_ALARM_DISPLAY);
- e_cal_component_alarm_set_trigger (e_alarm, trigger);
-
- e_cal_component_add_alarm (comp, e_alarm);
- }
- } else
- e_cal_component_remove_all_alarms (comp);
-
- } else if (icalcomponent_isa (ical_comp) == ICAL_VJOURNAL_COMPONENT) {
- if (get_mapi_SPropValue_array_date_timeval (&t, properties, PR_LAST_MODIFICATION_TIME) == MAPI_E_SUCCESS)
- icalcomponent_set_dtstart (ical_comp, icaltime_from_timet_with_zone (t.tv_sec, 1, default_zone));
- }
-
- if (icalcomponent_isa (ical_comp) == ICAL_VEVENT_COMPONENT || icalcomponent_isa (ical_comp) == ICAL_VTODO_COMPONENT) {
- /* priority */
- ui32 = (const uint32_t *)find_mapi_SPropValue_data(properties, PR_PRIORITY);
- if (ui32) {
- prop = icalproperty_new_priority (get_priority_from_prop (*ui32));
- icalcomponent_add_property (ical_comp, prop);
- }
- }
-
- /* classification */
- ui32 = (const uint32_t *)find_mapi_SPropValue_data(properties, PR_SENSITIVITY);
- if (ui32) {
- prop = icalproperty_new_class (get_class_from_prop (*ui32));
- icalcomponent_add_property (ical_comp, prop);
- }
-
- set_attachments_to_cal_component (comp, attachments, local_store_uri);
-
- e_cal_component_rescan (comp);
-
- return comp;
-}
-
-struct fetch_camel_cal_data {
- icalcomponent_kind kind;
- icalproperty_method method;
- gchar *result_data;
-};
-
-static gboolean
-fetch_camel_cal_comp_cb (FetchItemsCallbackData *item_data,
- gpointer data,
- GCancellable *cancellable,
- GError **perror)
-{
- struct fetch_camel_cal_data *fccd = data;
- ECalComponent *comp = NULL;
- GSList *detached_recurrences = NULL, *d_i = NULL;
- mapi_id_t mid = 0;
- icalcomponent *icalcomp = NULL;
- gchar *str = NULL, *smid = NULL, *filepath;
-
- g_return_val_if_fail (item_data != NULL, FALSE);
- g_return_val_if_fail (fccd != NULL, FALSE);
-
- filepath = g_strdup (g_get_tmp_dir ());
-
- if (!comp) {
- /* read component from a mail, if not found in the calendar */
- if (mid)
- smid = e_mapi_util_mapi_id_to_string (mid);
- else if (item_data->mid)
- smid = e_mapi_util_mapi_id_to_string (item_data->mid);
- else
- smid = e_cal_component_gen_uid();
- comp = e_mapi_cal_util_mapi_props_to_comp (item_data->conn, item_data->fid, fccd->kind, smid,
- item_data->properties, item_data->streams, item_data->recipients,
- item_data->attachments, filepath, NULL, fccd->method == ICAL_METHOD_REPLY,
- &detached_recurrences);
-
- g_free (smid);
- }
-
- g_free (filepath);
-
- icalcomp = e_cal_util_new_top_level ();
- icalcomponent_set_method (icalcomp, fccd->method);
- if (comp)
- icalcomponent_add_component (icalcomp,
- icalcomponent_new_clone(e_cal_component_get_icalcomponent(comp)));
- for (d_i = detached_recurrences; d_i; d_i = g_slist_next (d_i)) {
- icalcomponent_add_component (icalcomp,
- icalcomponent_new_clone (e_cal_component_get_icalcomponent (d_i->data)));
- g_object_unref (d_i->data);
- }
- str = icalcomponent_as_ical_string_r (icalcomp);
- icalcomponent_free (icalcomp);
- if (comp)
- g_object_unref (comp);
- g_slist_free (detached_recurrences);
-
- e_mapi_util_free_stream_list (&item_data->streams);
- e_mapi_util_free_recipient_list (&item_data->recipients);
- e_mapi_util_free_attachment_list (&item_data->attachments);
-
- fccd->result_data = str;
-
- return TRUE;
-}
-
-gchar *
-e_mapi_cal_util_camel_helper (EMapiConnection *conn, mapi_id_t orig_fid, mapi_id_t orig_mid, mapi_object_t *obj_message, const gchar *msg_class,
- GSList *streams, GSList *recipients, GSList *attachments)
-{
- struct fetch_camel_cal_data fccd = { 0 };
-
- fccd.kind = ICAL_NO_COMPONENT;
- fccd.method = ICAL_METHOD_NONE;
-
- g_return_val_if_fail (msg_class && *msg_class, NULL);
- g_return_val_if_fail (conn != NULL, NULL);
-
- if (!g_ascii_strcasecmp (msg_class, IPM_SCHEDULE_MEETING_REQUEST)) {
- fccd.method = ICAL_METHOD_REQUEST;
- fccd.kind = ICAL_VEVENT_COMPONENT;
- } else if (!g_ascii_strcasecmp (msg_class, IPM_SCHEDULE_MEETING_CANCELED)) {
- fccd.method = ICAL_METHOD_CANCEL;
- fccd.kind = ICAL_VEVENT_COMPONENT;
- } else if (g_str_has_prefix (msg_class, IPM_SCHEDULE_MEETING_RESP_PREFIX)) {
- fccd.method = ICAL_METHOD_REPLY;
- fccd.kind = ICAL_VEVENT_COMPONENT;
- } else
- return NULL;
-
- if (obj_message)
- e_mapi_connection_fetch_object_props (conn, NULL, orig_fid, orig_mid, obj_message,
- e_mapi_cal_utils_get_props_cb, GINT_TO_POINTER (fccd.kind),
- fetch_camel_cal_comp_cb, &fccd,
- MAPI_OPTIONS_FETCH_ALL, NULL, NULL);
- else
- e_mapi_connection_fetch_item (conn, orig_fid, orig_mid,
- e_mapi_cal_utils_get_props_cb, GINT_TO_POINTER (fccd.kind),
- fetch_camel_cal_comp_cb, &fccd,
- MAPI_OPTIONS_FETCH_ALL, NULL, NULL);
-
- return fccd.result_data;
-}
-
-/* call with props = NULL to fetch named ids into the connection cache */
-gboolean
-e_mapi_cal_utils_add_named_ids (EMapiConnection *conn,
- mapi_id_t fid,
- TALLOC_CTX *mem_ctx,
- struct SPropTagArray *props,
- gint pkind,
- GCancellable *cancellable,
- GError **perror)
-{
- /* do not make this array static, the function modifies it on run */
- ResolveNamedIDsData common_nids[] = {
- { PidLidReminderDelta, 0 },
- { PidLidReminderTime, 0 },
- { PidLidReminderSet, 0 },
- { PidLidPrivate, 0 },
- { PidLidSideEffects, 0 },
- { PidLidCommonStart, 0 },
- { PidLidCommonEnd, 0 },
- { PidLidTaskMode, 0 },
- { PidLidReminderSignalTime, 0 },
- { PidLidTimeZoneStruct, 0 },
- { PidLidTimeZoneDescription, 0 },
- { PidLidExceptionReplaceTime, 0 },
- { PidNameKeywords, 0 }
- };
- icalcomponent_kind kind = pkind;
-
- if (!props) {
- if (!e_mapi_connection_resolve_named_props (conn, fid, common_nids, G_N_ELEMENTS (common_nids), cancellable, perror))
- return FALSE;
- } else if (!e_mapi_utils_add_named_ids_to_props_array (conn, fid, mem_ctx, props, common_nids, G_N_ELEMENTS (common_nids), cancellable, perror))
- return FALSE;
-
- if (kind == ICAL_VEVENT_COMPONENT)
- return appt_build_name_id (conn, fid, mem_ctx, props, cancellable, perror);
- else if (kind == ICAL_VTODO_COMPONENT)
- return task_build_name_id (conn, fid, mem_ctx, props, cancellable, perror);
- else if (kind == ICAL_VJOURNAL_COMPONENT)
- return note_build_name_id (conn, fid, mem_ctx, props, cancellable, perror);
-
- return TRUE;
-}
-
-#define DEFAULT_APPT_REMINDER_MINS 15
-
-static gboolean
-appt_build_name_id (EMapiConnection *conn,
- mapi_id_t fid,
- TALLOC_CTX *mem_ctx,
- struct SPropTagArray *props,
- GCancellable *cancellable,
- GError **perror)
-{
- /* do not make this array static, the function modifies it on run */
- ResolveNamedIDsData nids[] = {
- { PidLidAppointmentSequence, 0 },
- { PidLidBusyStatus, 0 },
- { PidLidLocation, 0 },
- { PidLidAppointmentStartWhole, 0 },
- { PidLidAppointmentEndWhole, 0 },
- { PidLidAppointmentDuration, 0 },
- { PidLidAppointmentSubType, 0 },
- { PidLidAppointmentRecur, 0 },
- { PidLidAppointmentStateFlags, 0 },
- { PidLidResponseStatus, 0 },
- { PidLidRecurring, 0 },
- { PidLidIntendedBusyStatus, 0 },
- { PidLidExceptionReplaceTime, 0 },
- { PidLidFInvited, 0 },
- { PidLidRecurrenceType, 0 },
- { PidLidClipStart, 0 },
- { PidLidClipEnd, 0 },
- { PidLidAutoFillLocation, 0 },
- { PidLidAppointmentCounterProposal, 0 },
- { PidLidAppointmentNotAllowPropose, 0 },
- { PidLidAppointmentTimeZoneDefinitionStartDisplay, 0 },
- { PidLidAppointmentTimeZoneDefinitionEndDisplay, 0 },
- { PidLidWhere, 0 },
- { PidLidGlobalObjectId, 0 },
- { PidLidIsRecurring, 0 },
- { PidLidIsException, 0 },
- { PidLidCleanGlobalObjectId, 0 },
- { PidLidAppointmentMessageClass, 0 },
- { PidLidMeetingType, 0 },
- { PidLidTimeZone, 0 }
- };
-
- if (!props)
- return e_mapi_connection_resolve_named_props (conn, fid, nids, G_N_ELEMENTS (nids), cancellable, perror);
-
- return e_mapi_utils_add_named_ids_to_props_array (conn, fid, mem_ctx, props, nids, G_N_ELEMENTS (nids), cancellable, perror);
-}
-
-#define DEFAULT_TASK_REMINDER_MINS 1080
-
-static gboolean
-task_build_name_id (EMapiConnection *conn,
- mapi_id_t fid,
- TALLOC_CTX *mem_ctx,
- struct SPropTagArray *props,
- GCancellable *cancellable,
- GError **perror)
-{
- /* do not make this array static, the function modifies it on run */
- ResolveNamedIDsData nids[] = {
- { PidLidTaskStatus, 0 },
- { PidLidPercentComplete, 0 },
- { PidLidTeamTask, 0 },
- { PidLidTaskStartDate, 0 },
- { PidLidTaskDueDate, 0 },
- { PidLidTaskDateCompleted, 0 },
- /*{ PidLidTaskRecurrence, 0 },*/
- { PidLidTaskComplete, 0 },
- { PidLidTaskOwner, 0 },
- { PidLidTaskAssigner, 0 },
- { PidLidTaskFRecurring, 0 },
- { PidLidTaskOwnership, 0 },
- { PidLidTaskAcceptanceState, 0 },
- { PidLidTaskRole, 0 }
- };
-
- if (!props)
- return e_mapi_connection_resolve_named_props (conn, fid, nids, G_N_ELEMENTS (nids), cancellable, perror);
-
- return e_mapi_utils_add_named_ids_to_props_array (conn, fid, mem_ctx, props, nids, G_N_ELEMENTS (nids), cancellable, perror);
-}
-
-static gboolean
-note_build_name_id (EMapiConnection *conn,
- mapi_id_t fid,
- TALLOC_CTX *mem_ctx,
- struct SPropTagArray *props,
- GCancellable *cancellable,
- GError **perror)
-{
- /* do not make this array static, the function modifies it on run */
- ResolveNamedIDsData nids[] = {
- { PidLidNoteColor, 0 },
- { PidLidNoteWidth, 0 },
- { PidLidNoteHeight, 0 }
- };
-
- if (!props)
- return e_mapi_connection_resolve_named_props (conn, fid, nids, G_N_ELEMENTS (nids), cancellable, perror);
-
- return e_mapi_utils_add_named_ids_to_props_array (conn, fid, mem_ctx, props, nids, G_N_ELEMENTS (nids), cancellable, perror);
-}
-
-/* retrieves timezone location from a timezone ID */
-static const gchar *
-get_tzid_location (const gchar *tzid, struct cal_cbdata *cbdata)
-{
- icaltimezone *zone = NULL;
-
- if (!tzid || !*tzid || g_str_equal (tzid, "UTC"))
- return NULL;
-
- /* ask backend first, if any */
- if (cbdata && cbdata->get_timezone)
- zone = cbdata->get_timezone (cbdata->get_tz_data, tzid);
-
- if (!zone)
- zone = icaltimezone_get_builtin_timezone_from_tzid (tzid);
-
- /* the old TZID prefix used in previous versions of evolution-mapi */
- #define OLD_TZID_PREFIX "/softwarestudio.org/Tzfile/"
-
- if (!zone && g_str_has_prefix (tzid, OLD_TZID_PREFIX))
- zone = icaltimezone_get_builtin_timezone (tzid + strlen (OLD_TZID_PREFIX));
-
- #undef OLD_TZID_PREFIX
-
- if (!zone)
- return NULL;
-
- return icaltimezone_get_location (zone);
-}
-
-#define MINUTES_IN_HOUR 60
-#define SECS_IN_MINUTE 60
-
-gboolean
-e_mapi_cal_utils_write_props_cb (EMapiConnection *conn,
- mapi_id_t fid,
- TALLOC_CTX *mem_ctx,
- struct SPropValue **values,
- uint32_t *n_values,
- gpointer data,
- GCancellable *cancellable,
- GError **perror)
-{
- struct cal_cbdata *cbdata = (struct cal_cbdata *) data;
- ECalComponent *comp;
- icalcomponent *ical_comp;
- icalcomponent_kind kind;
- uint32_t flag32;
- bool b;
- icalproperty *prop;
- struct icaltimetype dtstart, dtend, utc_dtstart, utc_dtend, all_day_dtstart = {0}, all_day_dtend = {0};
- const icaltimezone *utc_zone;
- const gchar *dtstart_tz_location, *dtend_tz_location, *text = NULL;
- time_t tt;
- gboolean is_all_day;
- GSList *categories = NULL;
-
- g_return_val_if_fail (conn != NULL, FALSE);
- g_return_val_if_fail (mem_ctx != NULL, FALSE);
- g_return_val_if_fail (values != NULL, FALSE);
- g_return_val_if_fail (n_values != NULL, FALSE);
- g_return_val_if_fail (cbdata != NULL, FALSE);
-
- switch (cbdata->kind) {
- case ICAL_VEVENT_COMPONENT:
- case ICAL_VTODO_COMPONENT:
- case ICAL_VJOURNAL_COMPONENT:
- if (!e_mapi_cal_utils_add_named_ids (conn, fid, mem_ctx, NULL, cbdata->kind, cancellable, perror))
- return FALSE;
- break;
- default:
- return FALSE;
- }
-
- comp = cbdata->comp;
- ical_comp = e_cal_component_get_icalcomponent (comp);
- kind = icalcomponent_isa (ical_comp);
- g_return_val_if_fail (kind == cbdata->kind, FALSE);
-
- #define set_value(hex, val) G_STMT_START { \
- if (!e_mapi_utils_add_spropvalue (mem_ctx, values, n_values, hex, val)) \
- return FALSE; \
- } G_STMT_END
-
- #define set_named_value(named_id, val) G_STMT_START { \
- if (!e_mapi_utils_add_spropvalue_namedid (conn, fid, mem_ctx, values, n_values, named_id, val, cancellable, perror)) \
- return FALSE; \
- } G_STMT_END
-
- #define set_datetime_value(hex, dtval) G_STMT_START { \
- struct FILETIME filetime; \
- \
- e_mapi_util_time_t_to_filetime (dtval, &filetime); \
- \
- if (!e_mapi_utils_add_spropvalue (mem_ctx, values, n_values, hex, &filetime)) \
- return FALSE; \
- } G_STMT_END
-
- #define set_named_datetime_value(named_id, dtval) G_STMT_START { \
- struct FILETIME filetime; \
- \
- e_mapi_util_time_t_to_filetime (dtval, &filetime); \
- \
- if (!e_mapi_utils_add_spropvalue_namedid (conn, fid, mem_ctx, values, n_values, named_id, &filetime, cancellable, perror)) \
- return FALSE; \
- } G_STMT_END
-
- utc_zone = icaltimezone_get_utc_timezone ();
-
- dtstart = icalcomponent_get_dtstart (ical_comp);
-
- /* For VEVENTs */
- if (icalcomponent_get_first_property (ical_comp, ICAL_DTEND_PROPERTY) != 0)
- dtend = icalcomponent_get_dtend (ical_comp);
- /* For VTODOs */
- else if (icalcomponent_get_first_property (ical_comp, ICAL_DUE_PROPERTY) != 0)
- dtend = icalcomponent_get_due (ical_comp);
- else
- dtend = icalcomponent_get_dtstart (ical_comp);
-
- dtstart_tz_location = get_tzid_location (icaltime_get_tzid (dtstart), cbdata);
- dtend_tz_location = get_tzid_location (icaltime_get_tzid (dtend), cbdata);
-
- is_all_day = kind == ICAL_VEVENT_COMPONENT && icaltime_is_date (dtstart) && icaltime_is_date (dtend);
- if (is_all_day) {
- const gchar *def_location;
- icaltimezone *use_zone = NULL;
-
- /* all-day events expect times not in UTC but in local time;
- if this differs from the server timezone, then the event
- is shown spread among (two) days */
- def_location = get_tzid_location ("*default-zone*", cbdata);
- if (def_location && *def_location)
- use_zone = icaltimezone_get_builtin_timezone (def_location);
-
- if (!use_zone)
- use_zone = (icaltimezone *) utc_zone;
-
- dtstart.is_date = 0;
- dtstart.hour = 0;
- dtstart.minute = 0;
- dtstart.second = 0;
- all_day_dtstart = icaltime_convert_to_zone (dtstart, use_zone);
- dtstart.is_date = 1;
- all_day_dtstart = icaltime_convert_to_zone (all_day_dtstart, (icaltimezone *) utc_zone);
-
- dtend.is_date = 0;
- dtend.hour = 0;
- dtend.minute = 0;
- dtend.second = 0;
- all_day_dtend = icaltime_convert_to_zone (dtend, use_zone);
- dtend.is_date = 1;
- all_day_dtend = icaltime_convert_to_zone (all_day_dtend, (icaltimezone *) utc_zone);
- }
-
- utc_dtstart = icaltime_convert_to_zone (dtstart, (icaltimezone *)utc_zone);
- utc_dtend = icaltime_convert_to_zone (dtend, (icaltimezone *)utc_zone);
-
- text = icalcomponent_get_summary (ical_comp);
- if (!(text && *text))
- text = "";
- set_value (PR_SUBJECT_UNICODE, text);
- set_value (PR_NORMALIZED_SUBJECT_UNICODE, text);
- if (cbdata->appt_seq == 0)
- set_value (PR_CONVERSATION_TOPIC_UNICODE, text);
- text = NULL;
-
- /* we don't support HTML event/task/memo editor */
- flag32 = olEditorText;
- set_value (PR_MSG_EDITOR_FORMAT, &flag32);
-
- /* it'd be better to convert, then set it in unicode */
- text = icalcomponent_get_description (ical_comp);
- if (!(text && *text) || !g_utf8_validate (text, -1, NULL))
- text = "";
- set_value (PR_BODY_UNICODE, text);
- text = NULL;
-
- e_cal_component_get_categories_list (comp, &categories);
- if (categories) {
- gint ii;
- GSList *c;
- struct StringArrayW_r *categories_array;
-
- categories_array = talloc_zero (mem_ctx, struct StringArrayW_r);
- categories_array->cValues = g_slist_length (categories);
- categories_array->lppszW = (const char **) talloc_zero_array (mem_ctx, gchar *, categories_array->cValues);
-
- for (c = categories, ii = 0; c; c = c->next, ii++) {
- const gchar *category = c->data;
-
- if (!category || !*category) {
- ii--;
- categories_array->cValues--;
- continue;
- }
-
- categories_array->lppszW[ii] = talloc_strdup (mem_ctx, category);
- }
-
- set_named_value (PidNameKeywords, categories_array);
-
- e_cal_component_free_categories_list (categories);
- }
-
- /* Priority and Importance */
- prop = icalcomponent_get_first_property (ical_comp, ICAL_PRIORITY_PROPERTY);
- flag32 = prop ? get_prio_prop_from_priority (icalproperty_get_priority (prop)) : PRIORITY_NORMAL;
- set_value (PR_PRIORITY, &flag32);
- flag32 = prop ? get_imp_prop_from_priority (icalproperty_get_priority (prop)) : IMPORTANCE_NORMAL;
- set_value (PR_IMPORTANCE, &flag32);
-
- if (cbdata->ownername && cbdata->owneridtype && cbdata->ownerid) {
- set_value (PR_SENT_REPRESENTING_NAME_UNICODE, cbdata->ownername);
- set_value (PR_SENT_REPRESENTING_ADDRTYPE_UNICODE, cbdata->owneridtype);
- set_value (PR_SENT_REPRESENTING_EMAIL_ADDRESS_UNICODE, cbdata->ownerid);
- }
-
- if (cbdata->username && cbdata->useridtype && cbdata->userid) {
- set_value (PR_SENDER_NAME_UNICODE, cbdata->username);
- set_value (PR_SENDER_ADDRTYPE_UNICODE, cbdata->useridtype);
- set_value (PR_SENDER_EMAIL_ADDRESS_UNICODE, cbdata->userid);
- }
-
- flag32 = cbdata->msgflags;
- set_value (PR_MESSAGE_FLAGS, &flag32);
-
- flag32 = 0x0;
- b = e_cal_component_has_alarms (comp);
- if (b) {
- /* We know there would be only a single alarm of type:DISPLAY [static properties of the backend] */
- GList *alarm_uids = e_cal_component_get_alarm_uids (comp);
- ECalComponentAlarm *alarm = e_cal_component_get_alarm (comp, (const gchar *)(alarm_uids->data));
- ECalComponentAlarmAction action;
- e_cal_component_alarm_get_action (alarm, &action);
- if (action == E_CAL_COMPONENT_ALARM_DISPLAY) {
- ECalComponentAlarmTrigger trigger;
- gint dur_int = 0;
- e_cal_component_alarm_get_trigger (alarm, &trigger);
- switch (trigger.type) {
- case E_CAL_COMPONENT_ALARM_TRIGGER_RELATIVE_START :
- dur_int = (icaldurationtype_as_int (trigger.u.rel_duration)) / SECS_IN_MINUTE;
- /* we cannot set an alarm to popup after the start of an appointment on Exchange */
- flag32 = (dur_int < 0) ? -(dur_int) : 0;
- break;
- default :
- break;
- }
- }
- e_cal_component_alarm_free (alarm);
- cal_obj_uid_list_free (alarm_uids);
- }
- if (!flag32)
- switch (kind) {
- case ICAL_VEVENT_COMPONENT:
- flag32 = DEFAULT_APPT_REMINDER_MINS;
- break;
- case ICAL_VTODO_COMPONENT:
- flag32 = DEFAULT_TASK_REMINDER_MINS;
- break;
- default:
- break;
- }
- set_named_value (PidLidReminderSet, &b);
- set_named_value (PidLidReminderDelta, &flag32);
- tt = icaltime_as_timet (utc_dtstart);
- set_named_datetime_value (PidLidReminderTime, tt);
- tt = icaltime_as_timet (utc_dtstart) - (flag32 * SECS_IN_MINUTE);
- /* ReminderNextTime: FIXME for recurrence */
- set_named_datetime_value (PidLidReminderSignalTime, tt);
-
- /* Sensitivity, Private */
- flag32 = olNormal; /* default */
- b = 0; /* default */
- prop = icalcomponent_get_first_property (ical_comp, ICAL_CLASS_PROPERTY);
- if (prop)
- flag32 = get_prop_from_class (icalproperty_get_class (prop));
- if (flag32 == olPrivate || flag32 == olConfidential)
- b = 1;
- set_value (PR_SENSITIVITY, &flag32);
- set_named_value (PidLidPrivate, &b);
-
- tt = icaltime_as_timet (is_all_day ? all_day_dtstart : utc_dtstart);
- set_named_datetime_value (PidLidCommonStart, tt);
- set_datetime_value (PR_START_DATE, tt);
-
- tt = icaltime_as_timet (is_all_day ? all_day_dtend : utc_dtend);
- set_named_datetime_value (PidLidCommonEnd, tt);
- set_datetime_value (PR_END_DATE, tt);
-
- b = 1;
- set_value (PR_RESPONSE_REQUESTED, &b);
-
- /* PR_OWNER_APPT_ID needs to be set in certain cases only */
- /* PR_ICON_INDEX needs to be set appropriately */
-
- b = 0;
- set_value (PR_RTF_IN_SYNC, &b);
-
- if (kind == ICAL_VEVENT_COMPONENT) {
- const gchar *mapi_tzid;
- struct SBinary_short start_tz, end_tz;
-
- set_named_value (PidLidAppointmentMessageClass, IPM_APPOINTMENT);
-
- /* Busy Status */
- flag32 = olBusy; /* default */
- prop = icalcomponent_get_first_property (ical_comp, ICAL_TRANSP_PROPERTY);
- if (prop)
- flag32 = get_prop_from_transp (icalproperty_get_transp (prop));
- if (cbdata->meeting_type == MEETING_CANCEL)
- flag32 = olFree;
- set_named_value (PidLidIntendedBusyStatus, &flag32);
-
- if (cbdata->meeting_type == MEETING_REQUEST || cbdata->meeting_type == MEETING_REQUEST_RCVD) {
- flag32 = olTentative;
- set_named_value (PidLidBusyStatus, &flag32);
- } else if (cbdata->meeting_type == MEETING_CANCEL) {
- flag32 = olFree;
- set_named_value (PidLidBusyStatus, &flag32);
- } else
- set_named_value (PidLidBusyStatus, &flag32);
-
- /* Location */
- text = icalcomponent_get_location (ical_comp);
- if (!(text && *text))
- text = "";
- set_named_value (PidLidLocation, text);
- set_named_value (PidLidWhere, text);
- text = NULL;
- /* Auto-Location is always FALSE - Evolution doesn't work that way */
- b = 0;
- set_named_value (PidLidAutoFillLocation, &b);
-
- /* All-day event */
- b = is_all_day ? 1 : 0;
- set_named_value (PidLidAppointmentSubType, &b);
-
- /* Start */
- tt = icaltime_as_timet (is_all_day ? all_day_dtstart : utc_dtstart);
- set_named_datetime_value (PidLidAppointmentStartWhole, tt);
- /* FIXME: for recurrence */
- set_named_datetime_value (PidLidClipStart, tt);
-
- /* Start TZ */
- mapi_tzid = e_mapi_cal_tz_util_get_mapi_equivalent ((dtstart_tz_location && *dtstart_tz_location) ? dtstart_tz_location : "UTC");
- if (mapi_tzid && *mapi_tzid) {
- e_mapi_cal_util_mapi_tz_to_bin (mapi_tzid, &start_tz, mem_ctx);
- set_named_value (PidLidAppointmentTimeZoneDefinitionStartDisplay, &start_tz);
- }
- set_named_value (PidLidTimeZoneDescription, mapi_tzid ? mapi_tzid : "");
-
- /* End */
- tt = icaltime_as_timet (is_all_day ? all_day_dtend : utc_dtend);
- set_named_datetime_value (PidLidAppointmentEndWhole, tt);
- /* FIXME: for recurrence */
- set_named_datetime_value (PidLidClipEnd, tt);
-
- /* End TZ */
- mapi_tzid = e_mapi_cal_tz_util_get_mapi_equivalent ((dtend_tz_location && *dtend_tz_location) ? dtend_tz_location : "UTC");
- if (mapi_tzid && *mapi_tzid) {
- e_mapi_cal_util_mapi_tz_to_bin (mapi_tzid, &end_tz, mem_ctx);
- set_named_value (PidLidAppointmentTimeZoneDefinitionEndDisplay, &end_tz);
- }
-
- /* Recurrences also need to have this rather arbitrary index set
- to properly determine SDT/DST and appear in OWA (Bug #629057). */
- if (e_cal_component_has_recurrences (comp)) {
- uint64_t pltz;
- icaltimezone *ictz;
- const gchar *zone_location = dtstart_tz_location;
-
- if (!zone_location)
- zone_location = get_tzid_location ("*default-zone*", cbdata);
-
- ictz = icaltimezone_get_builtin_timezone (zone_location);
- pltz = e_mapi_cal_util_mapi_tz_pidlidtimezone (ictz);
- set_named_value (PidLidTimeZone, &pltz);
- }
-
- /* Duration */
- flag32 = icaldurationtype_as_int (icaltime_subtract (dtend, dtstart));
- flag32 /= MINUTES_IN_HOUR;
- set_named_value (PidLidAppointmentDuration, &flag32);
-
- if (e_cal_component_has_recurrences (comp)) {
- GSList *rrule_list = NULL;
- struct icalrecurrencetype *rt = NULL;
-
- e_cal_component_get_rrule_list (comp, &rrule_list);
- rt = (struct icalrecurrencetype *)(rrule_list->data);
-
- if (rt->freq == ICAL_DAILY_RECURRENCE)
- flag32 = rectypeDaily;
- else if (rt->freq == ICAL_WEEKLY_RECURRENCE)
- flag32 = rectypeWeekly;
- else if (rt->freq == ICAL_MONTHLY_RECURRENCE)
- flag32 = rectypeMonthly;
- else if (rt->freq == ICAL_YEARLY_RECURRENCE)
- flag32 = rectypeYearly;
- else
- flag32 = rectypeNone;
-
- e_cal_component_free_recur_list (rrule_list);
- } else
- flag32 = rectypeNone;
- set_named_value (PidLidRecurrenceType, &flag32);
-
- flag32 = cbdata->appt_id;
- if (!flag32) {
- gchar *propval;
-
- propval = e_mapi_cal_utils_get_icomp_x_prop (e_cal_component_get_icalcomponent (comp), "X-EVOLUTION-MAPI-OWNER-APPT-ID");
- if (propval && *propval) {
- mapi_id_t as_id = 0;
-
- if (e_mapi_util_mapi_id_from_string (propval, &as_id))
- flag32 = (uint32_t) as_id;
- }
-
- g_free (propval);
- }
- set_value (PR_OWNER_APPT_ID, &flag32);
-
- flag32 = cbdata->appt_seq;
- set_named_value (PidLidAppointmentSequence, &flag32);
-
- if (cbdata->cleanglobalid) {
- set_named_value (PidLidCleanGlobalObjectId, cbdata->cleanglobalid);
- }
-
- if (cbdata->globalid) {
- set_named_value (PidLidGlobalObjectId, cbdata->globalid);
- }
-
- flag32 = cbdata->resp;
- set_named_value (PidLidResponseStatus, &flag32);
-
- switch (cbdata->meeting_type) {
- case MEETING_OBJECT :
- set_value (PR_MESSAGE_CLASS, IPM_APPOINTMENT);
-
- flag32 = e_cal_component_has_recurrences (comp) ? RecurMeet : SingleMeet;
- set_value (PR_ICON_INDEX, &flag32);
-
- flag32 = 0x0171;
- set_named_value (PidLidSideEffects, &flag32);
-
- flag32 = asfMeeting;
- set_named_value (PidLidAppointmentStateFlags, &flag32);
-
- flag32 = mtgRequest;
- set_named_value (PidLidMeetingType, &flag32);
-
- b = 1;
- set_named_value (PidLidFInvited, &b);
-
- break;
- case MEETING_OBJECT_RCVD :
- set_value (PR_MESSAGE_CLASS, IPM_APPOINTMENT);
-
- flag32 = e_cal_component_has_recurrences (comp) ? RecurMeet : SingleMeet;
- set_value (PR_ICON_INDEX, (gconstpointer ) &flag32);
-
- flag32 = 0x0171;
- set_named_value (PidLidSideEffects, &flag32);
-
- flag32 = asfMeeting | asfReceived;
- set_named_value (PidLidAppointmentStateFlags, &flag32);
-
- flag32 = mtgRequest;
- set_named_value (PidLidMeetingType, &flag32);
-
- b = 1;
- set_named_value (PidLidFInvited, &b);
-
- break;
- case MEETING_REQUEST :
- set_value (PR_MESSAGE_CLASS, IPM_SCHEDULE_MEETING_REQUEST);
-
- flag32 = 0xFFFFFFFF; /* no idea why this has to be -1, but that's what the docs say */
- set_value (PR_ICON_INDEX, &flag32);
-
- flag32 = 0x1C61;
- set_named_value (PidLidSideEffects, &flag32);
-
- flag32 = asfMeeting | asfReceived;
- set_named_value (PidLidAppointmentStateFlags, &flag32);
-
- flag32 = (cbdata->appt_seq == 0) ? mtgRequest : mtgFull;
- set_named_value (PidLidMeetingType, &flag32);
-
- b = 1;
- set_named_value (PidLidFInvited, &b);
-
- break;
- case MEETING_REQUEST_RCVD :
- set_value (PR_MESSAGE_CLASS, IPM_APPOINTMENT);
-
- flag32 = e_cal_component_has_recurrences (comp) ? RecurMeet : SingleMeet;
- set_value (PR_ICON_INDEX, &flag32);
-
- flag32 = 0x0171;
- set_named_value (PidLidSideEffects, &flag32);
-
- flag32 = asfMeeting | asfReceived;
- set_named_value (PidLidAppointmentStateFlags, &flag32);
-
- flag32 = mtgRequest;
- set_named_value (PidLidMeetingType, &flag32);
-
- b = 1;
- set_named_value (PidLidFInvited, &b);
-
- break;
- case MEETING_CANCEL :
- set_value (PR_MESSAGE_CLASS, IPM_SCHEDULE_MEETING_CANCELED);
-
- flag32 = 0xFFFFFFFF; /* no idea why this has to be -1, but that's what the docs say */
- set_value (PR_ICON_INDEX, &flag32);
-
- flag32 = 0x1C61;
- set_named_value (PidLidSideEffects, &flag32);
-
- flag32 = asfMeeting | asfReceived | asfCanceled;
- set_named_value (PidLidAppointmentStateFlags, &flag32);
-
- flag32 = mtgEmpty;
- set_named_value (PidLidMeetingType, &flag32);
+ /* FIXME: is this mapping correct ? */
+ switch (prop) {
+ case olPersonal :
+ case olPrivate : return ICAL_CLASS_PRIVATE;
+ case olConfidential : return ICAL_CLASS_CONFIDENTIAL;
+ case olNormal :
+ default : return ICAL_CLASS_PUBLIC;
+ }
+}
- b = 1;
- set_named_value (PidLidFInvited, &b);
+static uint32_t
+get_prop_from_class (icalproperty_class class)
+{
+ /* FIXME: is this mapping correct ? */
+ switch (class) {
+ case ICAL_CLASS_PRIVATE : return olPrivate;
+ case ICAL_CLASS_CONFIDENTIAL : return olConfidential;
+ default : return olNormal;
+ }
+}
- break;
- case MEETING_RESPONSE :
- #define prefix_subject(prefix) { \
- const gchar *summary; \
- \
- summary = icalcomponent_get_summary (ical_comp); \
- if (!(summary && *summary)) \
- summary = ""; \
- \
- summary = talloc_asprintf (mem_ctx, "%s %s", prefix, summary); \
- \
- set_value (PR_SUBJECT_UNICODE, summary); \
- set_value (PR_NORMALIZED_SUBJECT_UNICODE, summary); \
- if (cbdata->appt_seq == 0) \
- set_value (PR_CONVERSATION_TOPIC_UNICODE, summary); \
- }
- if (cbdata->resp == olResponseAccepted) {
- /* Translators: This is a meeting response prefix which will be shown in a message Subject */
- prefix_subject (C_("MeetingResp", "Accepted:"));
- text = IPM_SCHEDULE_MEETING_RESP_POS;
- } else if (cbdata->resp == olResponseTentative) {
- /* Translators: This is a meeting response prefix which will be shown in a message Subject */
- prefix_subject (C_("MeetingResp", "Tentative:"));
- text = IPM_SCHEDULE_MEETING_RESP_TENT;
- } else if (cbdata->resp == olResponseDeclined) {
- /* Translators: This is a meeting response prefix which will be shown in a message Subject */
- prefix_subject (C_("MeetingResp", "Declined:"));
- text = IPM_SCHEDULE_MEETING_RESP_NEG;
- } else {
- text = "";
- }
- #undef prefix_subject
- set_value (PR_MESSAGE_CLASS, text);
- text = NULL;
+static gint
+get_priority_from_prop (uint32_t prop)
+{
+ switch (prop) {
+ case PRIORITY_LOW : return 7;
+ case PRIORITY_HIGH : return 1;
+ case PRIORITY_NORMAL :
+ default : return 5;
+ }
+}
- flag32 = 0xFFFFFFFF; /* no idea why this has to be -1, but that's what the docs say */
- set_value (PR_ICON_INDEX, &flag32);
+static uint32_t
+get_prio_prop_from_priority (gint priority)
+{
+ if (priority > 0 && priority <= 4)
+ return PRIORITY_HIGH;
+ else if (priority > 5 && priority <= 9)
+ return PRIORITY_LOW;
+ else
+ return PRIORITY_NORMAL;
+}
- flag32 = 0x1C61;
- set_named_value (PidLidSideEffects, &flag32);
+static uint32_t
+get_imp_prop_from_priority (gint priority)
+{
+ if (priority > 0 && priority <= 4)
+ return IMPORTANCE_HIGH;
+ else if (priority > 5 && priority <= 9)
+ return IMPORTANCE_LOW;
+ else
+ return IMPORTANCE_NORMAL;
+}
- flag32 = asfNone;
- set_named_value (PidLidAppointmentStateFlags, &flag32);
+#define RECIP_SENDABLE 0x1
+#define RECIP_ORGANIZER 0x2
- flag32 = mtgEmpty;
- set_named_value (PidLidMeetingType, &flag32);
+static const uint8_t GID_START_SEQ[] = {
+ 0x04, 0x00, 0x00, 0x00, 0x82, 0x00, 0xe0, 0x00,
+ 0x74, 0xc5, 0xb7, 0x10, 0x1a, 0x82, 0xe0, 0x08
+};
- break;
- case NOT_A_MEETING :
- default :
- set_value (PR_MESSAGE_CLASS, IPM_APPOINTMENT);
+/* exception_replace_time is a value of PidLidExceptionReplaceTime; this is not used for 'clean' object ids.
+ creation_time is a value of PR_CREATION_TIME
+*/
+void
+e_mapi_cal_util_generate_globalobjectid (gboolean is_clean, const gchar *uid, const struct timeval *exception_replace_time, const struct FILETIME *creation_time, struct Binary_r *sb)
+{
+ GByteArray *ba;
+ guint32 val32;
+ guchar *buf = NULL;
+ gsize len;
+ d(guint32 i);
- flag32 = e_cal_component_has_recurrences (comp) ? RecurAppt : SingleAppt;
- set_value (PR_ICON_INDEX, &flag32);
+ ba = g_byte_array_new ();
- flag32 = 0x0171;
- set_named_value (PidLidSideEffects, &flag32);
+ ba = g_byte_array_append (ba, GID_START_SEQ, (sizeof (GID_START_SEQ) / sizeof (GID_START_SEQ[0])));
- flag32 = 0;
- set_named_value (PidLidAppointmentStateFlags, &flag32);
+ val32 = 0;
+ if (!is_clean && exception_replace_time) {
+ struct icaltimetype icaltm = icaltime_from_timet_with_zone (exception_replace_time->tv_sec, 0, icaltimezone_get_utc_timezone ());
- b = 0;
- set_named_value (PidLidFInvited, &b);
+ val32 |= (icaltm.year & 0xFF00) << 16;
+ val32 |= (icaltm.year & 0xFF) << 16;
+ val32 |= (icaltm.month & 0xFF) << 8;
+ val32 |= (icaltm.day & 0xFF);
+ }
- break;
- }
+ ba = g_byte_array_append (ba, (const guint8 *) &val32, sizeof (guint32));
- b = e_cal_component_has_recurrences (comp);
- set_named_value (PidLidRecurring, &b);
- set_named_value (PidLidIsRecurring, &b);
- /* FIXME: Modified exceptions */
- b = e_cal_component_has_exceptions (comp) && FALSE; b = 0;
- set_named_value (PidLidIsException, &b);
+ /* creation time */
+ val32 = creation_time ? creation_time->dwLowDateTime : 0;
+ ba = g_byte_array_append (ba, (const guint8 *) &val32, sizeof (guint32));
+ val32 = creation_time ? creation_time->dwHighDateTime : 0;
+ ba = g_byte_array_append (ba, (const guint8 *) &val32, sizeof (guint32));
- /* Counter Proposal for appointments : not supported */
- b = 1;
- set_named_value (PidLidAppointmentNotAllowPropose, &b);
- b = 0;
- set_named_value (PidLidAppointmentCounterProposal, &b);
+ /* RESERVED - should be all 0's */
+ val32 = 0;
+ ba = g_byte_array_append (ba, (const guint8 *) &val32, sizeof (guint32));
+ val32 = 0;
+ ba = g_byte_array_append (ba, (const guint8 *) &val32, sizeof (guint32));
- } else if (kind == ICAL_VTODO_COMPONENT) {
- gdouble d;
+ /* We put Evolution's UID in base64 here */
+ buf = g_base64_decode (uid, &len);
+ if (len % 2 != 0)
+ --len;
+ val32 = len;
- set_value (PR_MESSAGE_CLASS, IPM_TASK);
+ /* Size in bytes of the following data */
+ ba = g_byte_array_append (ba, (const guint8 *) &val32, sizeof (guint32));
+ /* Data */
+ ba = g_byte_array_append (ba, (const guint8 *)buf, val32);
+ g_free (buf);
- /* Context menu flags */ /* FIXME: for assigned tasks */
- flag32 = 0x0110;
- set_named_value (PidLidSideEffects, &flag32);
+ sb->lpb = ba->data;
+ sb->cb = ba->len;
- /* Status, Percent complete, IsComplete */
- flag32 = olTaskNotStarted; /* default */
- b = 0; /* default */
- d = 0.0;
- prop = icalcomponent_get_first_property (ical_comp, ICAL_PERCENTCOMPLETE_PROPERTY);
- if (prop)
- d = 0.01 * icalproperty_get_percentcomplete (prop);
+ d(g_message ("New GlobalObjectId.. Length: %d bytes.. Hex-data follows:", ba->len));
+ d(for (i = 0; i < ba->len; i++)
+ g_print("0x%02X ", ba->data[i]));
- flag32 = get_prop_from_taskstatus (icalcomponent_get_status (ical_comp));
- if (flag32 == olTaskComplete) {
- b = 1;
- d = 1.0;
- }
+ g_byte_array_free (ba, FALSE);
+}
- set_named_value (PidLidTaskStatus, &flag32);
- set_named_value (PidLidPercentComplete, &d);
- set_named_value (PidLidTaskComplete, &b);
+/* returns complete globalid as base64 encoded string */
+static gchar *
+globalid_to_string (const guint8 *lpb, guint32 cb)
+{
+ const guint8 *ptr;
+ guint32 i, j;
- /* Date completed */
- if (b) {
- struct icaltimetype completed;
- prop = icalcomponent_get_first_property (ical_comp, ICAL_COMPLETED_PROPERTY);
- completed = icalproperty_get_completed (prop);
+ g_return_val_if_fail (lpb != NULL, NULL);
- completed.hour = completed.minute = completed.second = 0; completed.is_date = completed.is_utc = 1;
- tt = icaltime_as_timet (completed);
- set_named_datetime_value (PidLidTaskDateCompleted, tt);
- }
+ /* MSDN docs: the globalID must have an even number of bytes */
+ if ((cb) % 2 != 0)
+ return NULL;
- /* Start */
- dtstart.hour = dtstart.minute = dtstart.second = 0; dtstart.is_date = dtstart.is_utc = 1;
- tt = icaltime_as_timet (dtstart);
- if (!icaltime_is_null_time (dtstart)) {
- set_named_datetime_value (PidLidTaskStartDate, tt);
- }
+ ptr = lpb;
- /* Due */
- dtend.hour = dtend.minute = dtend.second = 0; dtend.is_date = dtend.is_utc = 1;
- tt = icaltime_as_timet (dtend);
- if (!icaltime_is_null_time (dtend)) {
- set_named_datetime_value (PidLidTaskDueDate, tt);
- }
+ /* starting seq - len = 16 bytes */
+ for (i = 0, j = 0; i < cb && j < sizeof (GID_START_SEQ); i++, ptr++, j++) {
+ if (*ptr != GID_START_SEQ[j])
+ return NULL;
+ }
- /* FIXME: Evolution does not support recurring tasks */
- b = 0;
- set_named_value (PidLidTaskFRecurring, &b);
+ /* take complete global id */
+ return g_base64_encode (lpb, cb);
+}
- } else if (kind == ICAL_VJOURNAL_COMPONENT) {
- uint32_t color = olYellow;
+/* retrieves timezone location from a timezone ID */
+static const gchar *
+get_tzid_location (const gchar *tzid, struct cal_cbdata *cbdata)
+{
+ icaltimezone *zone = NULL;
- set_value (PR_MESSAGE_CLASS, IPM_STICKYNOTE);
+ if (!tzid || !*tzid || g_str_equal (tzid, "UTC"))
+ return NULL;
- /* Context menu flags */
- flag32 = 0x0110;
- set_named_value (PidLidSideEffects, &flag32);
+ /* ask backend first, if any */
+ if (cbdata && cbdata->get_timezone)
+ zone = cbdata->get_timezone (cbdata->get_tz_data, tzid);
- flag32 = 0x0300 + color;
- set_value (PR_ICON_INDEX, &flag32);
+ if (!zone)
+ zone = icaltimezone_get_builtin_timezone_from_tzid (tzid);
- flag32 = color;
- set_named_value (PidLidNoteColor, &flag32);
+ /* the old TZID prefix used in previous versions of evolution-mapi */
+ #define OLD_TZID_PREFIX "/softwarestudio.org/Tzfile/"
- /* some random value */
- flag32 = 0x00FF;
- set_named_value (PidLidNoteWidth, &flag32);
+ if (!zone && g_str_has_prefix (tzid, OLD_TZID_PREFIX))
+ zone = icaltimezone_get_builtin_timezone (tzid + strlen (OLD_TZID_PREFIX));
- /* some random value */
- flag32 = 0x00FF;
- set_named_value (PidLidNoteHeight, &flag32);
- }
+ #undef OLD_TZID_PREFIX
- #undef set_value
- #undef set_named_value
- #undef set_datetime_value
- #undef set_named_datetime_value
+ if (!zone)
+ return NULL;
- return TRUE;
+ return icaltimezone_get_location (zone);
}
+#define MINUTES_IN_HOUR 60
+#define SECS_IN_MINUTE 60
+
static gboolean
emcu_build_restriction (EMapiConnection *conn,
- mapi_id_t fid,
TALLOC_CTX *mem_ctx,
struct mapi_SRestriction **restrictions,
gpointer user_data,
@@ -2070,7 +367,6 @@ emcu_build_restriction (EMapiConnection *conn,
static gboolean
emcu_check_id_exists_cb (EMapiConnection *conn,
- mapi_id_t fid,
TALLOC_CTX *mem_ctx,
const ListObjectsData *object_data,
guint32 obj_index,
@@ -2350,60 +646,6 @@ e_mapi_cal_utils_get_free_busy_data (EMapiConnection *conn, const GSList *users,
return TRUE;
}
-/* beware, the 'data' pointer is an integer of the event kind */
-gboolean
-e_mapi_cal_utils_get_props_cb (EMapiConnection *conn,
- mapi_id_t fid,
- TALLOC_CTX *mem_ctx,
- struct SPropTagArray *props,
- gpointer data,
- GCancellable *cancellable,
- GError **perror)
-{
- static const uint32_t cal_GetPropsList[] = {
- PR_FID,
- PR_MID,
-
- PR_SUBJECT_UNICODE,
- PR_NORMALIZED_SUBJECT_UNICODE,
- PR_CONVERSATION_TOPIC_UNICODE,
- PR_BODY,
- PR_BODY_UNICODE,
-
- PR_CREATION_TIME,
- PR_LAST_MODIFICATION_TIME,
- PR_PRIORITY,
- PR_SENSITIVITY,
- PR_START_DATE,
- PR_END_DATE,
- PR_RESPONSE_REQUESTED,
- PR_OWNER_APPT_ID,
- PR_PROCESSED,
- PR_MSG_EDITOR_FORMAT,
-
- PR_SENT_REPRESENTING_NAME_UNICODE,
- PR_SENT_REPRESENTING_ADDRTYPE_UNICODE,
- PR_SENT_REPRESENTING_EMAIL_ADDRESS_UNICODE,
-
- PR_SENDER_NAME_UNICODE,
- PR_SENDER_ADDRTYPE_UNICODE,
- PR_SENDER_EMAIL_ADDRESS_UNICODE,
-
- PR_RCVD_REPRESENTING_NAME_UNICODE,
- PR_RCVD_REPRESENTING_ADDRTYPE_UNICODE,
- PR_RCVD_REPRESENTING_EMAIL_ADDRESS_UNICODE
- };
-
- g_return_val_if_fail (conn != NULL, FALSE);
- g_return_val_if_fail (mem_ctx != NULL, FALSE);
- g_return_val_if_fail (props != NULL, FALSE);
-
- if (!e_mapi_utils_add_props_to_props_array (mem_ctx, props, cal_GetPropsList, G_N_ELEMENTS (cal_GetPropsList)))
- return FALSE;
-
- return e_mapi_cal_utils_add_named_ids (conn, fid, mem_ctx, props, GPOINTER_TO_INT (data), cancellable, perror);
-}
-
gchar *
e_mapi_cal_utils_get_icomp_x_prop (icalcomponent *comp, const gchar *key)
{
diff --git a/src/libexchangemapi/e-mapi-cal-utils.h b/src/libexchangemapi/e-mapi-cal-utils.h
index 38a5142..d4f056f 100644
--- a/src/libexchangemapi/e-mapi-cal-utils.h
+++ b/src/libexchangemapi/e-mapi-cal-utils.h
@@ -74,50 +74,14 @@ struct cal_cbdata {
icaltimezone * (*get_timezone)(gpointer get_tz_data, const gchar *tzid);
};
-void
-e_mapi_cal_util_fetch_organizer (ECalComponent *comp, GSList **recip_list);
-void
-e_mapi_cal_util_fetch_recipients (ECalComponent *comp, GSList **recip_list);
-void
-e_mapi_cal_util_fetch_attachments (ECalComponent *comp, GSList **attach_list, const gchar *local_store_uri);
-
-ECalComponent *
-e_mapi_cal_util_mapi_props_to_comp (EMapiConnection *conn, mapi_id_t fid, icalcomponent_kind kind, const gchar *mid, struct mapi_SPropValue_array *properties,
- GSList *streams, GSList *recipients, GSList *attachments,
- const gchar *local_store_uri, const icaltimezone *default_zone, gboolean is_reply, GSList **detached_components);
-
-void
-e_mapi_cal_util_generate_globalobjectid (gboolean is_clean, const gchar *uid, const struct timeval *exception_replace_time, const struct FILETIME *creation_time, struct Binary_r *sb);
-
-gchar *
-e_mapi_cal_util_camel_helper (EMapiConnection *conn, mapi_id_t fid, mapi_id_t mid, mapi_object_t *obj_message, const gchar *msg_class,
- GSList *streams, GSList *recipients, GSList *attachments);
-
-uint32_t
-e_mapi_cal_util_get_new_appt_id (EMapiConnection *conn, mapi_id_t fid);
-
-gboolean e_mapi_cal_utils_add_named_ids (EMapiConnection *conn,
- mapi_id_t fid,
- TALLOC_CTX *mem_ctx,
- struct SPropTagArray *props,
- gint pkind,
- GCancellable *cancellable,
- GError **perror);
-gboolean e_mapi_cal_utils_get_props_cb (EMapiConnection *conn,
- mapi_id_t fid,
- TALLOC_CTX *mem_ctx,
- struct SPropTagArray *props,
- gpointer data,
- GCancellable *cancellable,
- GError **perror);
-gboolean e_mapi_cal_utils_write_props_cb (EMapiConnection *conn,
- mapi_id_t fid,
- TALLOC_CTX *mem_ctx,
- struct SPropValue **values,
- uint32_t *n_values,
- gpointer data,
- GCancellable *cancellable,
- GError **perror);
+void e_mapi_cal_util_generate_globalobjectid (gboolean is_clean,
+ const gchar *uid,
+ const struct timeval *exception_replace_time,
+ const struct FILETIME *creation_time,
+ struct Binary_r *sb);
+
+uint32_t e_mapi_cal_util_get_new_appt_id (EMapiConnection *conn,
+ mapi_id_t fid);
gboolean e_mapi_cal_utils_get_free_busy_data (EMapiConnection *conn,
const GSList *users,
@@ -142,7 +106,8 @@ gboolean e_mapi_cal_utils_comp_to_object (EMapiConnection *conn,
GCancellable *cancellable,
GError **perror);
-gchar * e_mapi_cal_utils_get_icomp_x_prop (icalcomponent *comp, const gchar *key);
+gchar * e_mapi_cal_utils_get_icomp_x_prop (icalcomponent *comp,
+ const gchar *key);
G_END_DECLS
diff --git a/src/libexchangemapi/e-mapi-connection.c b/src/libexchangemapi/e-mapi-connection.c
index ae94799..b1d2f54 100644
--- a/src/libexchangemapi/e-mapi-connection.c
+++ b/src/libexchangemapi/e-mapi-connection.c
@@ -616,4491 +616,2636 @@ e_mapi_connection_connected (EMapiConnection *conn)
return priv->session != NULL;
}
-/* proptag should be already set for this stream */
-static void
-set_stream_value (ExchangeMAPIStream *stream, const uint32_t *cpid, const guint8 *buf_data, guint32 buf_len, gboolean converted)
+static gboolean
+may_skip_property (uint32_t proptag)
{
- g_return_if_fail (stream != NULL);
-
- stream->value = NULL;
-
- if (!converted && (stream->proptag == PR_HTML || (stream->proptag & 0xFFFF) == PT_UNICODE) && ((cpid && (*cpid == 1200 || *cpid == 1201)) || (buf_len > 5 && buf_data[3] == '\0'))) {
- /* this is special, get the CPID and transform to utf8 when it's utf16 */
- gsize written = 0;
- gchar *in_utf8;
-
- /* skip Unicode marker, if there */
- if (buf_len >= 2 && buf_data[0] == 0xFF && buf_data[1] == 0xFE)
- in_utf8 = g_convert ((const gchar *) buf_data + 2, buf_len - 2, "UTF-8", "UTF-16", NULL, &written, NULL);
- else
- in_utf8 = g_convert ((const gchar *) buf_data, buf_len, "UTF-8", "UTF-16", NULL, &written, NULL);
-
- if (in_utf8 && written > 0) {
- stream->value = g_byte_array_sized_new (written + 1);
- g_byte_array_append (stream->value, (const guint8 *) in_utf8, written);
+ /* skip all "strange" properties */
+ gboolean skip = TRUE;
- if (in_utf8[written] != '\0')
- g_byte_array_append (stream->value, (const guint8 *) "", 1);
- }
+ switch (proptag & 0xFFFF) {
+ case PT_BOOLEAN:
+ case PT_I2:
+ case PT_LONG:
+ case PT_DOUBLE:
+ case PT_I8:
+ case PT_STRING8:
+ case PT_UNICODE:
+ case PT_SYSTIME:
+ case PT_BINARY:
+ case PT_ERROR:
+ case PT_CLSID:
+ case PT_SVREID:
+ case PT_MV_STRING8:
+ case PT_MV_UNICODE:
+ case PT_MV_BINARY:
+ case PT_MV_LONG:
+ skip = FALSE;
+ break;
+ default:
+ break;
}
- if (!stream->value) {
- stream->value = g_byte_array_sized_new (buf_len);
- g_byte_array_append (stream->value, buf_data, buf_len);
- }
+ return skip;
}
-/* returns whether found that property */
-static gboolean
-add_stream_from_properties (GSList **stream_list, struct mapi_SPropValue_array *properties, uint32_t proptag, const uint32_t *cpid)
+gboolean
+e_mapi_connection_fetch_gal (EMapiConnection *conn,
+ BuildRestrictionsCB build_rs_cb,
+ gpointer build_rs_cb_data,
+ BuildReadPropsCB build_props,
+ gpointer brp_data,
+ FetchGALCallback cb,
+ gpointer data,
+ GCancellable *cancellable,
+ GError **perror)
{
- if (e_mapi_util_find_stream (*stream_list, proptag)) {
- return TRUE;
- } else if (properties) {
- gconstpointer data;
-
- data = e_mapi_util_find_array_propval (properties, proptag);
- if (data) {
- const struct SBinary_short *bin;
- const gchar *str;
- ExchangeMAPIStream *stream;
-
- switch (proptag & 0xFFFF) {
- case PT_BINARY:
- bin = data;
- if (bin->cb) {
- stream = g_new0 (ExchangeMAPIStream, 1);
+ struct SPropTagArray *propsTagArray;
+ struct SRowSet *aRowSet;
+ enum MAPISTATUS ms;
+ uint32_t i, count, n_rows = 0;
+ uint8_t ulFlags;
+ TALLOC_CTX *mem_ctx;
- stream->proptag = proptag;
- set_stream_value (stream, cpid, bin->lpb, bin->cb, FALSE);
+ CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
+ e_return_val_mapi_error_if_fail (build_props != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+ e_return_val_mapi_error_if_fail (cb != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
- *stream_list = g_slist_append (*stream_list, stream);
- }
+ mem_ctx = talloc_new (priv->session);
- return TRUE;
- case PT_STRING8:
- case PT_UNICODE:
- str = data;
- stream = g_new0 (ExchangeMAPIStream, 1);
+ LOCK ();
- stream->proptag = proptag;
- set_stream_value (stream, cpid, (const guint8 *) str, strlen (str) + 1, FALSE);
+ ms = GetGALTableCount (priv->session, &n_rows);
+ if (ms != MAPI_E_SUCCESS) {
+ make_mapi_error (perror, "GetGALTableCount", ms);
+ n_rows = 0;
+ }
- *stream_list = g_slist_append (*stream_list, stream);
+ propsTagArray = set_SPropTagArray (mem_ctx, 0x1, PR_MESSAGE_CLASS);
+ if (!build_props (conn, 0, mem_ctx, propsTagArray, brp_data, cancellable, perror)) {
+ make_mapi_error (perror, "build_props", MAPI_E_CALL_FAILED);
+ UNLOCK();
+ talloc_free (mem_ctx);
+ return FALSE;
+ }
- return TRUE;
+ ms = MAPI_E_SUCCESS;
+ count = 0;
+ ulFlags = TABLE_START;
+ while (ms == MAPI_E_SUCCESS) {
+ aRowSet = NULL;
+ /* fetch per 100 items */
+ ms = GetGALTable (priv->session, propsTagArray, &aRowSet, 100, ulFlags);
+ if ((!aRowSet) || (!(aRowSet->aRow)) || ms != MAPI_E_SUCCESS) {
+ break;
+ }
+ if (aRowSet->cRows) {
+ global_unlock ();
+ for (i = 0; i < aRowSet->cRows; i++, count++) {
+ if (!cb (conn, count, n_rows, &aRowSet->aRow[i], data, cancellable, perror)) {
+ ms = MAPI_E_RESERVED;
+ break;
+ }
}
+ global_lock ();
+ } else {
+ talloc_free (aRowSet);
+ break;
}
+
+ ulFlags = TABLE_CUR;
+ talloc_free (aRowSet);
}
- return FALSE;
+ talloc_free (mem_ctx);
+
+ UNLOCK ();
+
+ if (ms != MAPI_E_SUCCESS && ms != MAPI_E_RESERVED)
+ make_mapi_error (perror, "GetGALTable", ms);
+
+ return ms == MAPI_E_SUCCESS;
}
-static gboolean
-e_mapi_util_read_generic_stream (TALLOC_CTX *mem_ctx, mapi_object_t *obj_message, const uint32_t *cpid, uint32_t proptag, GSList **stream_list, struct mapi_SPropValue_array *properties, GError **perror)
+gboolean
+e_mapi_connection_get_public_folder (EMapiConnection *conn,
+ mapi_object_t *obj_store,
+ GCancellable *cancellable,
+ GError **perror)
{
- enum MAPISTATUS ms;
- mapi_object_t obj_stream;
- uint16_t cn_read = 0, max_read;
- uint32_t off_data = 0;
- uint8_t *buf_data = NULL;
- uint32_t buf_size = 0;
- gboolean done = FALSE;
-
- /* sanity */
- e_return_val_mapi_error_if_fail (obj_message, MAPI_E_INVALID_PARAMETER, FALSE);
- e_return_val_mapi_error_if_fail (((proptag & 0xFFFF) == PT_BINARY) || ((proptag & 0xFFFF) == PT_STRING8 || ((proptag & 0xFFFF) == PT_UNICODE)), MAPI_E_INVALID_PARAMETER, FALSE);
-
- /* if compressed RTF stream, then return */
- if (proptag == PR_RTF_COMPRESSED)
- return FALSE;
+ enum MAPISTATUS ms;
- if (add_stream_from_properties (stream_list, properties, proptag, cpid))
- return TRUE;
+ CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
+ e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
- e_mapi_debug_print("%s: Entering %s ", G_STRLOC, G_STRFUNC);
- e_mapi_debug_print("Attempt to read stream for proptag 0x%08X ", proptag);
+ LOCK ();
- mapi_object_init(&obj_stream);
+ mapi_object_init (&priv->public_store);
- /* get a stream on specified proptag */
- ms = OpenStream(obj_message, proptag, STREAM_ACCESS_READ, &obj_stream);
- if (ms != MAPI_E_SUCCESS) {
- /* If OpenStream failed, should we attempt any other call(s) to fetch the blob? */
- make_mapi_error (perror, "OpenStream", ms);
- goto cleanup;
- }
+ ms = OpenPublicFolder (priv->session, &priv->public_store);
- /* NOTE: This may prove unreliable for streams larger than 4GB length */
- ms = GetStreamSize(&obj_stream, &buf_size);
if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "GetStreamSize", ms);
- goto cleanup;
+ make_mapi_error (perror, "OpenPublicFolder", ms);
}
- buf_data = talloc_size (mem_ctx, buf_size);
- if (!buf_data)
- goto cleanup;
+ *obj_store = priv->public_store;
+ UNLOCK ();
- /* determine max_read first, to read by chunks as long as possible */
- max_read = buf_size > STREAM_MAX_READ_SIZE ? STREAM_MAX_READ_SIZE : buf_size;
- do {
- ms = ReadStream (&obj_stream, (buf_data) + off_data, max_read, &cn_read);
- if (ms == MAPI_E_SUCCESS) {
- if (cn_read == 0) {
- done = TRUE;
- } else {
- off_data += cn_read;
- if (off_data >= buf_size)
- done = TRUE;
- }
- break;
- }
+ return ms == MAPI_E_SUCCESS;
+}
- if (ms == 0x2c80)
- max_read = max_read >> 1;
- else
- max_read = STREAM_MAX_READ_SIZE_DF;
+static enum MAPISTATUS
+open_folder (EMapiConnection *conn, uint32_t olFolder, mapi_id_t *fid, guint32 fid_options, mapi_object_t *obj_folder, GError **perror)
+{
+ enum MAPISTATUS ms;
- if (max_read < STREAM_MAX_READ_SIZE_DF)
- max_read = STREAM_MAX_READ_SIZE_DF;
- } while (ms == 0x2c80); /* an error when max_read is too large? */
+ CHECK_CORRECT_CONN_AND_GET_PRIV (conn, MAPI_E_INVALID_PARAMETER);
+ e_return_val_mapi_error_if_fail (obj_folder != NULL, MAPI_E_INVALID_PARAMETER, MAPI_E_INVALID_PARAMETER);
+ e_return_val_mapi_error_if_fail (fid != NULL, MAPI_E_INVALID_PARAMETER, MAPI_E_INVALID_PARAMETER);
- /* Read from the stream */
- while (!done) {
- ms = ReadStream (&obj_stream, (buf_data) + off_data, max_read, &cn_read);
+ if (*fid == 0) {
+ ms = GetDefaultFolder (&priv->msg_store, fid, olFolder);
if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "ReadStream", ms);
- done = TRUE;
- } else if (cn_read == 0) {
- done = TRUE;
- } else {
- off_data += cn_read;
- if (off_data >= buf_size)
- done = TRUE;
+ make_mapi_error (perror, "GetDefaultFolder", ms);
+ return ms;
}
- }
-
- if (ms == MAPI_E_SUCCESS) {
- ExchangeMAPIStream *stream = g_new0 (ExchangeMAPIStream, 1);
- stream->proptag = proptag;
- set_stream_value (stream, cpid, buf_data, off_data, FALSE);
-
- e_mapi_debug_print("Attempt succeeded for proptag 0x%08X (after name conversion) ", stream->proptag);
-
- *stream_list = g_slist_append (*stream_list, stream);
+ fid_options = 0;
}
-cleanup:
- mapi_object_release(&obj_stream);
+ if ((fid_options & MAPI_OPTIONS_USE_PFSTORE) != 0) {
+ if (!ensure_public_store (priv, perror)) {
+ return MAPI_E_CALL_FAILED;
+ }
+ }
- e_mapi_debug_print("%s: Leaving %s ", G_STRLOC, G_STRFUNC);
+ ms = OpenFolder (((fid_options & MAPI_OPTIONS_USE_PFSTORE) != 0 ? &priv->public_store : &priv->msg_store), *fid, obj_folder);
+ if (ms != MAPI_E_SUCCESS)
+ make_mapi_error (perror, "OpenFolder", ms);
- return (ms == MAPI_E_SUCCESS);
+ return ms;
}
-static void
-e_mapi_util_read_body_stream (TALLOC_CTX *mem_ctx, mapi_object_t *obj_message, GSList **stream_list, struct mapi_SPropValue_array *properties, gboolean by_best_body)
+gboolean
+e_mapi_connection_open_default_folder (EMapiConnection *conn,
+ uint32_t olFolderIdentifier,
+ mapi_object_t *obj_folder,
+ GCancellable *cancellable,
+ GError **perror)
{
- const uint32_t *cpid = e_mapi_util_find_array_propval (properties, PR_INTERNET_CPID);
- gboolean can_html = FALSE, has_body = FALSE, has_body_unicode;
+ enum MAPISTATUS ms;
+ mapi_id_t fid = 0;
+ gboolean res;
+
+ CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
+ e_return_val_mapi_error_if_fail (obj_folder != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
- has_body_unicode = add_stream_from_properties (stream_list, properties, PR_BODY_UNICODE, cpid);
- if (!has_body_unicode)
- has_body = add_stream_from_properties (stream_list, properties, PR_BODY, cpid);
+ LOCK ();
- if (by_best_body) {
- uint8_t best_body = 0;
+ mapi_object_init (obj_folder);
- can_html = GetBestBody (obj_message, &best_body) == MAPI_E_SUCCESS && best_body == olEditorHTML;
- } else {
- const uint32_t *ui32 = e_mapi_util_find_array_propval (properties, PR_MSG_EDITOR_FORMAT);
- can_html = ui32 && *ui32 == olEditorHTML;
+ ms = GetDefaultFolder (&priv->msg_store, &fid, olFolderIdentifier);
+ if (ms != MAPI_E_SUCCESS) {
+ make_mapi_error (perror, "GetDefaultFolder", ms);
+ UNLOCK ();
+ return FALSE;
+ }
+
+ if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
+ UNLOCK ();
+ return FALSE;
}
- if (can_html)
- e_mapi_util_read_generic_stream (mem_ctx, obj_message, cpid, PR_HTML, stream_list, properties, NULL);
+ res = e_mapi_connection_open_personal_folder (conn, fid, obj_folder, cancellable, perror);
- if (!has_body_unicode)
- has_body_unicode = e_mapi_util_read_generic_stream (mem_ctx, obj_message, cpid, PR_BODY_UNICODE, stream_list, properties, NULL);
+ UNLOCK ();
- if (!has_body && !has_body_unicode)
- e_mapi_util_read_generic_stream (mem_ctx, obj_message, cpid, PR_BODY, stream_list, properties, NULL);
+ return res;
}
-/* Returns TRUE if all streams were written succcesfully, else returns FALSE */
-static gboolean
-e_mapi_util_write_generic_streams (mapi_object_t *obj_message, GSList *stream_list, GError **perror)
+gboolean
+e_mapi_connection_open_personal_folder (EMapiConnection *conn,
+ mapi_id_t fid,
+ mapi_object_t *obj_folder,
+ GCancellable *cancellable,
+ GError **perror)
{
- GSList *l;
- enum MAPISTATUS ms;
- gboolean status = TRUE;
-
- e_mapi_debug_print("%s: Entering %s ", G_STRLOC, G_STRFUNC);
-
- for (l = stream_list; l; l = l->next) {
- ExchangeMAPIStream *stream = (ExchangeMAPIStream *) (l->data);
- uint32_t total_written;
- gboolean done = FALSE;
- mapi_object_t obj_stream;
+ enum MAPISTATUS ms;
- mapi_object_init(&obj_stream);
+ CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
+ e_return_val_mapi_error_if_fail (obj_folder != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
- /* OpenStream on required proptag */
- ms = OpenStream (obj_message, stream->proptag, STREAM_ACCESS_READWRITE, &obj_stream);
- if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "OpenStream", ms);
- goto cleanup;
- }
+ LOCK ();
- /* Set the stream size */
- ms = SetStreamSize (&obj_stream, stream->value->len);
- if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "SetStreamSize", ms);
- goto cleanup;
- }
+ mapi_object_init (obj_folder);
- total_written = 0;
- /* Write attachment */
- while (!done) {
- uint16_t cn_written = 0;
- DATA_BLOB blob;
+ ms = OpenFolder (&priv->msg_store, fid, obj_folder);
+ if (ms != MAPI_E_SUCCESS)
+ make_mapi_error (perror, "OpenFolder", ms);
- blob.length = (stream->value->len - total_written) < STREAM_MAX_WRITE_SIZE ?
- (stream->value->len - total_written) : STREAM_MAX_WRITE_SIZE;
- blob.data = (stream->value->data) + total_written;
+ UNLOCK ();
- ms = WriteStream (&obj_stream, &blob, &cn_written);
+ return ms == MAPI_E_SUCCESS;
+}
- if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "WriteStream", ms);
- done = TRUE;
- } else if (cn_written == 0) {
- done = TRUE;
- } else {
- total_written += cn_written;
- if (total_written >= stream->value->len)
- done = TRUE;
- }
- }
-
- /* Commit the stream */
- ms = CommitStream (&obj_stream);
- if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "CommitStream", ms);
- goto cleanup;
- }
-
- cleanup:
- if (ms != MAPI_E_SUCCESS)
- status = FALSE;
- mapi_object_release(&obj_stream);
- }
-
- e_mapi_debug_print("%s: Leaving %s ", G_STRLOC, G_STRFUNC);
-
- return status;
-}
-
-static void
-set_recipient_properties (TALLOC_CTX *mem_ctx, struct SRow *aRow, ExchangeMAPIRecipient *recipient, gboolean is_external)
-{
- uint32_t i;
-
- if (is_external && recipient->in.ext_lpProps) {
- /* FIXME: Setting PR_ENTRYID property seems to create problems for now. We should take
- * another look at this after the CreateOneoffEntryId API is provided by LibMAPI. */
-#if 0
- struct Binary_r oneoff_eid;
- struct SPropValue sprop;
- const gchar *dn = NULL, *email = NULL;
-
- dn = (const gchar *) e_mapi_util_find_SPropVal_array_propval (recipient->in.ext_lpProps, PR_DISPLAY_NAME_UNICODE);
- dn = (dn) ? dn : "";
- email = (const gchar *) e_mapi_util_find_SPropVal_array_propval (recipient->in.ext_lpProps, PR_SMTP_ADDRESS_UNICODE);
- email = (email) ? email : "";
- e_mapi_util_recip_entryid_generate_smtp (mem_ctx, &oneoff_eid, dn, email);
- set_SPropValue_proptag (&sprop, PR_ENTRYID, (gconstpointer )(oneoff_eid));
- SRow_addprop (aRow, sprop);
-#endif
-
- /* Now, add the properties which are specified for unresolved recipients alone. */
- for (i = 0; i < recipient->in.ext_cValues; ++i)
- SRow_addprop (aRow, recipient->in.ext_lpProps[i]);
- }
-
- /* Now, add the properties which are specified for each recipient
- * irrespective of whether it was resolved or not. */
- for (i = 0; i < recipient->in.req_cValues; ++i)
- SRow_addprop (aRow, recipient->in.req_lpProps[i]);
-}
-
-static gboolean
-e_mapi_util_modify_recipients (EMapiConnection *conn, TALLOC_CTX *mem_ctx, mapi_object_t *obj_message , GSList *recipients, gboolean remove_existing, GError **perror)
+gboolean
+e_mapi_connection_open_public_folder (EMapiConnection *conn,
+ mapi_id_t fid,
+ mapi_object_t *obj_folder,
+ GCancellable *cancellable,
+ GError **perror)
{
- enum MAPISTATUS ms;
- struct SPropTagArray *SPropTagArray = NULL;
- struct SRowSet *SRowSet = NULL;
- struct PropertyTagArray_r *FlagList = NULL;
- GSList *l;
- const gchar **users = NULL;
- uint32_t i, j, count = 0;
+ enum MAPISTATUS ms;
CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
- e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
-
- e_mapi_debug_print("%s: Entering %s ", G_STRLOC, G_STRFUNC);
-
- SPropTagArray = set_SPropTagArray(mem_ctx, 0xA,
- PR_ENTRYID,
- PR_DISPLAY_NAME_UNICODE,
- PR_OBJECT_TYPE,
- PR_DISPLAY_TYPE,
- PR_TRANSMITTABLE_DISPLAY_NAME_UNICODE,
- PR_EMAIL_ADDRESS_UNICODE,
- PR_ADDRTYPE_UNICODE,
- PR_SEND_RICH_INFO,
- PR_7BIT_DISPLAY_NAME_UNICODE,
- PR_SMTP_ADDRESS_UNICODE);
-
- count = g_slist_length (recipients);
- users = g_new0 (const gchar *, count + 1);
-
- for (i = 0, l = recipients; (i < count && l != NULL); ++i, l = l->next) {
- ExchangeMAPIRecipient *recipient = (ExchangeMAPIRecipient *)(l->data);
- users[i] = recipient->email_id;
- }
+ e_return_val_mapi_error_if_fail (obj_folder != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
- /* Attempt to resolve names from the server */
LOCK ();
- ms = ResolveNames (priv->session, users, SPropTagArray, &SRowSet, &FlagList, MAPI_UNICODE);
- UNLOCK ();
- if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "ResolveNames", ms);
- goto cleanup;
- }
-
- g_assert (count == FlagList->cValues);
-
- if (!SRowSet) /* This happens when there are ZERO RESOLVED recipients */
- SRowSet = talloc_zero(mem_ctx, struct SRowSet);
-
- for (i = 0, l = recipients, j = 0; (i < count && l != NULL); ++i, l = l->next) {
- ExchangeMAPIRecipient *recipient = (ExchangeMAPIRecipient *)(l->data);
- uint32_t last;
- if (FlagList->aulPropTag[i] == MAPI_AMBIGUOUS) {
- /* We should never get an ambiguous resolution as we use the email-id for resolving.
- * However, if we do still get an ambiguous entry, we can't handle it :-( */
- e_mapi_debug_print ("%s: %s() - '%s' is ambiguous ", G_STRLOC, G_STRFUNC, recipient->email_id);
- ms = MAPI_E_AMBIGUOUS_RECIP;
- /* Translators: %s is replaced with an email address which was found ambiguous on a remote server */
- g_set_error (perror, E_MAPI_ERROR, ms, _("Recipient '%s' is ambiguous"), recipient->email_id);
- goto cleanup;
- } else if (FlagList->aulPropTag[i] == MAPI_UNRESOLVED) {
- /* If the recipient is unresolved, consider it is a SMTP one */
- SRowSet->aRow = talloc_realloc(mem_ctx, SRowSet->aRow, struct SRow, SRowSet->cRows + 1);
- last = SRowSet->cRows;
- SRowSet->aRow[last].cValues = 0;
- SRowSet->aRow[last].lpProps = talloc_zero(mem_ctx, struct SPropValue);
- set_recipient_properties(mem_ctx, &SRowSet->aRow[last], recipient, TRUE);
- SRowSet->cRows += 1;
- } else if (FlagList->aulPropTag[i] == MAPI_RESOLVED) {
- set_recipient_properties (mem_ctx, &SRowSet->aRow[j], recipient, FALSE);
- j += 1;
- }
+ if (!ensure_public_store (priv, perror)) {
+ UNLOCK ();
+ return FALSE;
}
- if (remove_existing) {
- ms = RemoveAllRecipients (obj_message);
- if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "RemoveAllRecipients", ms);
- goto cleanup;
- }
+ if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
+ UNLOCK ();
+ return FALSE;
}
- /* Modify the recipient table */
- ms = ModifyRecipients (obj_message, SRowSet);
- if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "ModifyRecipients", ms);
- goto cleanup;
- }
+ mapi_object_init (obj_folder);
-cleanup:
- g_free (users);
+ ms = OpenFolder (&priv->public_store, fid, obj_folder);
+ if (ms != MAPI_E_SUCCESS)
+ make_mapi_error (perror, "OpenFolder", ms);
- e_mapi_debug_print("%s: Leaving %s ", G_STRLOC, G_STRFUNC);
+ UNLOCK ();
return ms == MAPI_E_SUCCESS;
}
-static gboolean
-e_mapi_util_delete_attachments (TALLOC_CTX *mem_ctx, mapi_object_t *obj_message, GError **perror)
+gboolean
+e_mapi_connection_close_folder (EMapiConnection *conn,
+ mapi_object_t *obj_folder,
+ GCancellable *cancellable,
+ GError **perror)
{
- enum MAPISTATUS ms;
- mapi_object_t obj_tb_attach;
- struct SPropTagArray *proptags;
- struct SRowSet rows_attach;
- uint32_t attach_count;
- uint32_t i_row_attach;
- gboolean status = TRUE;
-
- e_mapi_debug_print("%s: Entering %s ", G_STRLOC, G_STRFUNC);
-
- proptags = set_SPropTagArray(mem_ctx, 0x4,
- PR_ATTACH_NUM,
- PR_INSTANCE_KEY,
- PR_RECORD_KEY,
- PR_RENDERING_POSITION);
-
- mapi_object_init(&obj_tb_attach);
-
- /* open attachment table */
- ms = GetAttachmentTable (obj_message, &obj_tb_attach);
- if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "GetAttachmentTable", ms);
- goto cleanup;
- }
-
- ms = SetColumns (&obj_tb_attach, proptags);
- if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "SetColumns", ms);
- goto cleanup;
- }
-
- ms = QueryPosition (&obj_tb_attach, NULL, &attach_count);
- if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "QueryPosition", ms);
- goto cleanup;
- }
-
- if (!attach_count)
- goto cleanup;
-
- ms = QueryRows (&obj_tb_attach, attach_count, TBL_ADVANCE, &rows_attach);
- if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "QueryRows", ms);
- goto cleanup;
- }
-
- /* foreach attachment, delete by PR_ATTACH_NUM */
- for (i_row_attach = 0; i_row_attach < rows_attach.cRows; i_row_attach++) {
- const uint32_t *num_attach;
-
- num_attach = (const uint32_t *) get_SPropValue_SRow_data(&rows_attach.aRow[i_row_attach], PR_ATTACH_NUM);
+ CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
+ e_return_val_mapi_error_if_fail (obj_folder != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
- ms = DeleteAttach (obj_message, *num_attach);
- if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "DeleteAttach", ms);
- status = FALSE;
- }
- }
+ LOCK ();
-cleanup:
- if (ms != MAPI_E_SUCCESS)
- status = FALSE;
- mapi_object_release(&obj_tb_attach);
+ mapi_object_release (obj_folder);
- e_mapi_debug_print("%s: Leaving %s ", G_STRLOC, G_STRFUNC);
+ UNLOCK ();
- return status;
+ return TRUE;
}
-/* Returns TRUE if all attachments were written succcesfully, else returns FALSE */
-static gboolean
-e_mapi_util_set_attachments (EMapiConnection *conn, mapi_id_t fid, TALLOC_CTX *mem_ctx, mapi_object_t *obj_message, GSList *attach_list, gboolean remove_existing, GError **perror)
+/* deals with named IDs transparently, if not using NULL bpr_cb, thus it's OK to check with PidLid and PidName constants only */
+gboolean
+e_mapi_connection_get_folder_properties (EMapiConnection *conn,
+ mapi_object_t *obj_folder,
+ BuildReadPropsCB brp_cb,
+ gpointer brp_cb_user_data,
+ GetFolderPropertiesCB cb,
+ gpointer cb_user_data,
+ GCancellable *cancellable,
+ GError **perror)
{
- GSList *l;
- enum MAPISTATUS ms;
- gboolean status = FALSE;
-
- e_mapi_debug_print("%s: Entering %s ", G_STRLOC, G_STRFUNC);
+ enum MAPISTATUS ms;
+ TALLOC_CTX *mem_ctx;
+ struct SPropTagArray *spropTagArray = NULL;
+ struct mapi_SPropValue_array *properties = NULL;
+ gboolean res = FALSE;
- if (remove_existing)
- e_mapi_util_delete_attachments (mem_ctx, obj_message, NULL);
+ CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
+ e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+ e_return_val_mapi_error_if_fail (obj_folder != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
- for (l = attach_list; l; l = l->next) {
- ExchangeMAPIAttachment *attachment = (ExchangeMAPIAttachment *) (l->data);
- mapi_object_t obj_attach;
+ LOCK ();
+ mem_ctx = talloc_new (priv->session);
- mapi_object_init(&obj_attach);
+ if (g_cancellable_set_error_if_cancelled (cancellable, perror))
+ goto cleanup;
- /* CreateAttach */
- ms = CreateAttach (obj_message, &obj_attach);
- if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "CreateAttach", ms);
+ spropTagArray = set_SPropTagArray (mem_ctx, 3, PidTagFolderId, PidTagLastModificationTime, PidTagContentCount);
+ if (brp_cb) {
+ if (!brp_cb (conn, mapi_object_get_id (obj_folder), mem_ctx, spropTagArray, brp_cb_user_data, cancellable, perror)) {
goto cleanup;
}
+ } else {
+ talloc_free (spropTagArray);
+ spropTagArray = NULL;
+ }
- if (attachment->mail) {
- struct SPropValue *props = NULL;
- uint32_t propslen = 0, ui32;
- MailItem *item = attachment->mail;
- mapi_object_t obj_emb_msg;
-
- ui32 = ATTACH_EMBEDDED_MSG;
- e_mapi_utils_add_spropvalue (mem_ctx, &props, &propslen, PR_ATTACH_METHOD, &ui32);
- ui32 = 0;
- e_mapi_utils_add_spropvalue (mem_ctx, &props, &propslen, PR_RENDERING_POSITION, &ui32);
- e_mapi_utils_add_spropvalue (mem_ctx, &props, &propslen, PR_ATTACH_MIME_TAG, "message/rfc822");
- if (item->header.subject)
- e_mapi_utils_add_spropvalue (mem_ctx, &props, &propslen, PR_ATTACH_FILENAME_UNICODE, item->header.subject);
+ properties = talloc_zero (mem_ctx, struct mapi_SPropValue_array);
+ if (spropTagArray && spropTagArray->cValues) {
+ struct SPropValue *lpProps;
+ uint32_t prop_count = 0, k, ll;
+ ResolveNamedIDsData *named_ids_list = NULL;
+ guint named_ids_len = 0;
- /* set properties for the item */
- ms = SetProps (&obj_attach, MAPI_PROPS_SKIP_NAMEDID_CHECK, props, propslen);
- if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "SetProps", ms);
- goto cleanup;
- }
+ lpProps = talloc_zero (mem_ctx, struct SPropValue);
- props = NULL;
- propslen = 0;
+ for (k = 0; k < spropTagArray->cValues; k++) {
+ uint32_t proptag = spropTagArray->aulPropTag[k];
- mapi_object_init (&obj_emb_msg);
+ if (may_skip_property (proptag)) {
+ const gchar *name = get_proptag_name (proptag);
+ if (!name)
+ name = "";
- ms = OpenEmbeddedMessage (&obj_attach, &obj_emb_msg, MAPI_CREATE);
- if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "OpenEmbeddedMessage", ms);
- goto cleanup;
+ g_debug ("%s: Cannot fetch property 0x%08x %s", G_STRFUNC, proptag, name);
+ } else if (((proptag >> 16) & 0xFFFF) >= 0x8000) {
+ if (!named_ids_list)
+ named_ids_list = g_new0 (ResolveNamedIDsData, spropTagArray->cValues - k + 1);
+ named_ids_list[named_ids_len].pidlid_propid = proptag;
+ named_ids_list[named_ids_len].propid = MAPI_E_RESERVED;
+ named_ids_len++;
}
+ }
- if (!mapi_mail_utils_create_item_build_props (conn, fid, mem_ctx, &props, &propslen, item, NULL, perror)) {
- make_mapi_error (perror, "build_props", MAPI_E_CALL_FAILED);
+ if (named_ids_list) {
+ if (!e_mapi_connection_resolve_named_props (conn, mapi_object_get_id (obj_folder), named_ids_list, named_ids_len, cancellable, perror)) {
+ g_free (named_ids_list);
goto cleanup;
}
- /* set properties for the item */
- ms = SetProps (&obj_emb_msg, MAPI_PROPS_SKIP_NAMEDID_CHECK, props, propslen);
- if (ms != MAPI_E_SUCCESS) {
- mapi_object_release (&obj_emb_msg);
- make_mapi_error (perror, "SetProps", ms);
+ if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
+ g_free (named_ids_list);
goto cleanup;
}
- if (item->generic_streams) {
- if (!e_mapi_util_write_generic_streams (&obj_emb_msg, item->generic_streams, perror)) {
- mapi_object_release (&obj_emb_msg);
- goto cleanup;
- }
- }
-
- /* Set attachments if any */
- if (item->attachments) {
- if (!e_mapi_util_set_attachments (conn, fid, mem_ctx, &obj_emb_msg, item->attachments, FALSE, perror)) {
- mapi_object_release (&obj_emb_msg);
- goto cleanup;
- }
- }
-
- /* Set recipients if any */
- if (item->recipients) {
- if (!e_mapi_util_modify_recipients (conn, mem_ctx, &obj_emb_msg, item->recipients, FALSE, perror)) {
- mapi_object_release (&obj_emb_msg);
- goto cleanup;
+ for (k = 0, ll = 0; k < named_ids_len; k++) {
+ if (named_ids_list[k].propid != MAPI_E_RESERVED) {
+ while (ll < spropTagArray->cValues) {
+ if (spropTagArray->aulPropTag[k] == named_ids_list[k].pidlid_propid) {
+ spropTagArray->aulPropTag[k] = named_ids_list[k].propid;
+ break;
+ }
+ ll++;
+ }
}
}
-
- ms = SaveChangesMessage (&obj_attach, &obj_emb_msg, KeepOpenReadOnly);
- if (ms != MAPI_E_SUCCESS) {
- mapi_object_release (&obj_emb_msg);
- make_mapi_error (perror, "SaveChangesMessage", ms);
- goto cleanup;
- }
-
- mapi_object_release (&obj_emb_msg);
- } else {
- /* SetProps */
- ms = SetProps (&obj_attach, MAPI_PROPS_SKIP_NAMEDID_CHECK, attachment->lpProps, attachment->cValues);
- if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "SetProps", ms);
- goto cleanup;
- }
-
- /* If there are any streams to be set, write them. */
- if (!e_mapi_util_write_generic_streams (&obj_attach, attachment->streams, perror))
- goto cleanup;
}
- /* message->SaveChangesAttachment() */
- ms = SaveChangesAttachment (obj_message, &obj_attach, KeepOpenReadWrite);
+ ms = GetProps (obj_folder, MAPI_PROPS_SKIP_NAMEDID_CHECK | MAPI_UNICODE, spropTagArray, &lpProps, &prop_count);
if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "SaveChangesAttachment", ms);
+ make_mapi_error (perror, "GetProps", ms);
+ g_free (named_ids_list);
goto cleanup;
}
- status = TRUE;
-
- cleanup:
- mapi_object_release(&obj_attach);
- }
-
- e_mapi_debug_print("%s: Leaving %s ", G_STRLOC, G_STRFUNC);
-
- return status;
-}
+ if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
+ g_free (named_ids_list);
+ goto cleanup;
+ }
-static GByteArray *
-obj_message_to_camel_mime (EMapiConnection *conn, mapi_id_t fid, mapi_object_t *obj_msg)
-{
- GByteArray *res = NULL;
- MailItem *item = NULL;
- CamelMimeMessage *msg;
-
- g_return_val_if_fail (conn != NULL, NULL);
- g_return_val_if_fail (obj_msg != NULL, NULL);
+ /* Conversion from SPropValue to mapi_SPropValue. (no padding here) */
+ properties->cValues = prop_count;
+ properties->lpProps = talloc_zero_array (mem_ctx, struct mapi_SPropValue, prop_count + 1);
+ for (k = 0, ll = 0; k < prop_count; k++, ll++) {
+ if (may_skip_property (lpProps[k].ulPropTag)) {
+ ll--;
+ properties->cValues--;
+ } else {
+ if (named_ids_list) {
+ guint m;
- if (!e_mapi_connection_fetch_object_props (conn, NULL, fid, 0, obj_msg, mapi_mail_get_item_prop_list, NULL,
- fetch_props_to_mail_item_cb, &item,
- MAPI_OPTIONS_FETCH_ALL | MAPI_OPTIONS_GETBESTBODY, NULL, NULL)
- || item == NULL) {
- if (item)
- mail_item_free (item);
+ for (m = 0; m < named_ids_len; m++) {
+ if (lpProps[k].ulPropTag == named_ids_list[named_ids_len - m - 1].propid ||
+ (((lpProps[k].ulPropTag & 0xFFFF) == PT_ERROR) &&
+ (lpProps[k].ulPropTag & ~0xFFFF) == (named_ids_list[named_ids_len - m - 1].propid & ~0xFFFF))) {
+ lpProps[k].ulPropTag = (lpProps[k].ulPropTag & 0xFFFF) | (named_ids_list[named_ids_len - m - 1].pidlid_propid & ~0xFFFF);
+ break;
+ }
+ }
+ }
- return NULL;
+ cast_mapi_SPropValue (mem_ctx, &properties->lpProps[ll], &lpProps[k]);
+ }
+ }
+ } else {
+ ms = GetPropsAll (obj_folder, MAPI_UNICODE, properties);
+ if (ms != MAPI_E_SUCCESS) {
+ make_mapi_error (perror, "GetPropsAll", ms);
+ goto cleanup;
+ }
}
- msg = mapi_mail_item_to_mime_message (conn, item);
- mail_item_free (item);
-
- if (msg) {
- CamelStream *mem = camel_stream_mem_new ();
-
- res = g_byte_array_new ();
+ if (g_cancellable_set_error_if_cancelled (cancellable, perror))
+ goto cleanup;
- mem = camel_stream_mem_new ();
- camel_stream_mem_set_byte_array (CAMEL_STREAM_MEM (mem), res);
- camel_data_wrapper_write_to_stream_sync (
- CAMEL_DATA_WRAPPER (msg), mem, NULL, NULL);
+ res = cb (conn, mem_ctx, properties, cb_user_data, cancellable, perror);
- g_object_unref (mem);
- g_object_unref (msg);
- }
+ cleanup:
+ talloc_free (spropTagArray);
+ talloc_free (properties);
+ talloc_free (mem_ctx);
+ UNLOCK();
return res;
}
-static gboolean
-may_skip_property (uint32_t proptag)
-{
- /* skip all "strange" properties */
- gboolean skip = TRUE;
-
- switch (proptag & 0xFFFF) {
- case PT_BOOLEAN:
- case PT_I2:
- case PT_LONG:
- case PT_DOUBLE:
- case PT_I8:
- case PT_STRING8:
- case PT_UNICODE:
- case PT_SYSTIME:
- case PT_BINARY:
- case PT_ERROR:
- case PT_CLSID:
- case PT_SVREID:
- case PT_MV_STRING8:
- case PT_MV_UNICODE:
- case PT_MV_BINARY:
- case PT_MV_LONG:
- skip = FALSE;
- break;
- default:
- break;
- }
-
- return skip;
-}
+typedef gboolean (*ForeachTableRowCB) (EMapiConnection *conn,
+ TALLOC_CTX *mem_ctx,
+ struct SRow *srow,
+ guint32 row_index,
+ guint32 rows_total,
+ gpointer user_data,
+ GCancellable *cancellable,
+ GError **perror);
-/* Returns TRUE if all attachments were read succcesfully, else returns FALSE */
-static gboolean
-e_mapi_util_get_attachments (EMapiConnection *conn,
- mapi_id_t fid,
- TALLOC_CTX *mem_ctx,
- mapi_object_t *obj_message,
- GSList **attach_list,
- GError **perror)
+static enum MAPISTATUS
+foreach_tablerow (EMapiConnection *conn,
+ TALLOC_CTX *mem_ctx,
+ mapi_object_t *obj_table,
+ ForeachTableRowCB cb,
+ gpointer user_data,
+ GCancellable *cancellable,
+ GError **perror)
{
- enum MAPISTATUS ms;
- mapi_object_t obj_tb_attach;
- struct SPropTagArray *proptags;
- struct SRowSet rows_attach;
- uint32_t attach_count;
- uint32_t i_row_attach;
- gboolean status = TRUE;
-
- e_mapi_debug_print("%s: Entering %s ", G_STRLOC, G_STRFUNC);
-
- proptags = set_SPropTagArray(mem_ctx, 0x5,
- PR_ATTACH_NUM,
- PR_INSTANCE_KEY,
- PR_RECORD_KEY,
- PR_RENDERING_POSITION,
- PR_ATTACH_METHOD);
-
- mapi_object_init(&obj_tb_attach);
-
- /* open attachment table */
- ms = GetAttachmentTable (obj_message, &obj_tb_attach);
- if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "GetAttachmentTable", ms);
- goto cleanup;
- }
-
- ms = SetColumns (&obj_tb_attach, proptags);
- if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "SetColumns", ms);
- goto cleanup;
- }
-
- ms = QueryPosition (&obj_tb_attach, NULL, &attach_count);
- if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "QueryPosition", ms);
- goto cleanup;
- }
-
- if (!attach_count)
- goto cleanup;
-
- ms = QueryRows (&obj_tb_attach, attach_count, TBL_ADVANCE, &rows_attach);
- if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "QueryRows", ms);
- goto cleanup;
- }
-
- /* foreach attachment, open by PR_ATTACH_NUM */
- for (i_row_attach = 0; i_row_attach < rows_attach.cRows; i_row_attach++) {
- ExchangeMAPIAttachment *attachment;
- struct mapi_SPropValue_array properties;
- const uint32_t *ui32;
- mapi_object_t obj_attach;
- uint32_t z, az;
-
- mapi_object_init(&obj_attach);
+ enum MAPISTATUS ms;
+ struct SRowSet SRowSet;
+ uint32_t count, i, cursor_pos = 0;
- ui32 = (const uint32_t *) get_SPropValue_SRow_data(&rows_attach.aRow[i_row_attach], PR_ATTACH_NUM);
+ CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
+ e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+ e_return_val_mapi_error_if_fail (mem_ctx != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+ e_return_val_mapi_error_if_fail (obj_table != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+ e_return_val_mapi_error_if_fail (cb != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
- ms = OpenAttach (obj_message, *ui32, &obj_attach);
+ do {
+ /* Number of items in the container */
+ ms = QueryPosition (obj_table, &cursor_pos, &count);
if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "OpenAttach", ms);
- goto loop_cleanup;
+ make_mapi_error (perror, "QueryPosition", ms);
+ break;
}
- ms = GetPropsAll (&obj_attach, MAPI_UNICODE, &properties);
- if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "GetPropsAll", ms);
- goto loop_cleanup;
+ if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
+ ms = MAPI_E_USER_CANCEL;
+ break;
}
- az = 0;
- attachment = g_new0 (ExchangeMAPIAttachment, 1);
- attachment->cValues = properties.cValues;
- attachment->lpProps = g_new0 (struct SPropValue, attachment->cValues + 1);
- for (z=0; z < properties.cValues; z++) {
- if (may_skip_property (properties.lpProps[z].ulPropTag)) {
- attachment->cValues--;
- continue;
- }
-
- cast_SPropValue (mem_ctx, &properties.lpProps[z],
- &(attachment->lpProps[az]));
-
- if ((attachment->lpProps[az].ulPropTag & 0xFFFF) == PT_STRING8) {
- struct SPropValue *lpProps;
- struct SPropTagArray *tags;
- uint32_t prop_count = 0;
-
- /* prefer unicode strings, if available */
- tags = set_SPropTagArray (mem_ctx, 0x1, (attachment->lpProps[az].ulPropTag & 0xFFFF0000) | PT_UNICODE);
- if (MAPI_E_SUCCESS == GetProps (&obj_attach, MAPI_PROPS_SKIP_NAMEDID_CHECK | MAPI_UNICODE, tags, &lpProps, &prop_count) && prop_count == 1 && lpProps) {
- if ((lpProps->ulPropTag & 0xFFFF) == PT_UNICODE)
- attachment->lpProps[az] = *lpProps;
- }
- talloc_free (tags);
- }
+ if (!count)
+ break;
- az++;
+ /* Fill the table columns with data from the rows */
+ ms = QueryRows (obj_table, count, TBL_ADVANCE, &SRowSet);
+ if (ms != MAPI_E_SUCCESS) {
+ make_mapi_error (perror, "QueryRows", ms);
+ break;
}
- /* just to get all the other streams */
- for (z = 0; z < properties.cValues; z++) {
- if ((properties.lpProps[z].ulPropTag & 0xFFFF) == PT_BINARY) {
- e_mapi_util_read_generic_stream (mem_ctx, &obj_attach, e_mapi_util_find_array_propval (&properties, PR_INTERNET_CPID), properties.lpProps[z].ulPropTag, &(attachment->streams), &properties, NULL);
- }
+ if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
+ ms = MAPI_E_USER_CANCEL;
+ break;
}
- ui32 = (const uint32_t *) get_SPropValue_SRow_data(&rows_attach.aRow[i_row_attach], PR_ATTACH_METHOD);
- if (ui32 && *ui32 == ATTACH_BY_VALUE) {
- e_mapi_util_read_generic_stream (mem_ctx, &obj_attach, e_mapi_util_find_array_propval (&properties, PR_INTERNET_CPID), PR_ATTACH_DATA_BIN, &(attachment->streams), &properties, NULL);
- } else if (ui32 && *ui32 == ATTACH_EMBEDDED_MSG) {
- mapi_object_t obj_emb_msg;
-
- mapi_object_init (&obj_emb_msg);
-
- if (OpenEmbeddedMessage (&obj_attach, &obj_emb_msg, MAPI_READONLY) == MAPI_E_SUCCESS) {
- /* very the same is in camel-mapi-folder.c, how I hate diplicating the code */
- GByteArray *bytes;
-
- bytes = obj_message_to_camel_mime (conn, fid, &obj_emb_msg);
- if (bytes) {
- ExchangeMAPIStream *stream = g_new0 (ExchangeMAPIStream, 1);
-
- stream->value = bytes;
- stream->proptag = PR_ATTACH_DATA_BIN;
+ for (i = 0; i < SRowSet.cRows && ms == MAPI_E_SUCCESS; i++) {
+ if (!cb (conn, mem_ctx, &SRowSet.aRow[i], cursor_pos + i + 1, count, user_data, cancellable, perror))
+ ms = MAPI_E_RESERVED;
+ else if (g_cancellable_set_error_if_cancelled (cancellable, perror))
+ ms = MAPI_E_USER_CANCEL;
+ }
+ } while (cursor_pos < count && ms == MAPI_E_SUCCESS);
- attachment->streams = g_slist_append (attachment->streams, stream);
- }
- }
+ return ms;
+}
- mapi_object_release (&obj_emb_msg);
- }
+struct ListObjectsInternalData
+{
+ ListObjectsCB cb;
+ gpointer user_data;
+};
- *attach_list = g_slist_append (*attach_list, attachment);
+static gboolean
+list_objects_internal_cb (EMapiConnection *conn,
+ TALLOC_CTX *mem_ctx,
+ struct SRow *srow,
+ guint32 row_index,
+ guint32 rows_total,
+ gpointer user_data,
+ GCancellable *cancellable,
+ GError **perror)
+{
+ struct ListObjectsInternalData *loi_data = user_data;
+ ListObjectsData lod;
+ const mapi_id_t *pmid;
+ const gchar *msg_class;
+ const uint32_t *pmsg_flags;
+ const struct FILETIME *last_modified;
- loop_cleanup:
- if (ms != MAPI_E_SUCCESS)
- status = FALSE;
- mapi_object_release(&obj_attach);
- }
+ CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
+ e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+ e_return_val_mapi_error_if_fail (mem_ctx != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+ e_return_val_mapi_error_if_fail (srow != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
- cleanup:
- if (ms != MAPI_E_SUCCESS)
- status = FALSE;
- mapi_object_release(&obj_tb_attach);
+ pmid = get_SPropValue_SRow_data (srow, PidTagMid);
+ msg_class = get_SPropValue_SRow_data (srow, PidTagMessageClass);
+ pmsg_flags = get_SPropValue_SRow_data (srow, PidTagMessageFlags);
+ last_modified = get_SPropValue_SRow_data (srow, PidTagLastModificationTime);
- e_mapi_debug_print("%s: Leaving %s ", G_STRLOC, G_STRFUNC);
+ lod.mid = pmid ? *pmid : 0;
+ lod.msg_class = msg_class;
+ lod.msg_flags = pmsg_flags ? *pmsg_flags : 0;
+ lod.last_modified = last_modified ? e_mapi_util_filetime_to_time_t (last_modified) : 0;
- return status;
+ return loi_data->cb (conn, mem_ctx, &lod, row_index, rows_total, loi_data->user_data, cancellable, perror);
}
-gboolean
-e_mapi_connection_fetch_gal (EMapiConnection *conn,
- BuildRestrictionsCB build_rs_cb,
- gpointer build_rs_cb_data,
- BuildReadPropsCB build_props,
- gpointer brp_data,
- FetchGALCallback cb,
- gpointer data,
- GCancellable *cancellable,
- GError **perror)
+static void
+maybe_add_named_id_tag (uint32_t proptag,
+ ResolveNamedIDsData **named_ids_list,
+ guint *named_ids_len)
{
- struct SPropTagArray *propsTagArray;
- struct SRowSet *aRowSet;
- enum MAPISTATUS ms;
- uint32_t i, count, n_rows = 0;
- uint8_t ulFlags;
- TALLOC_CTX *mem_ctx;
+ g_return_if_fail (named_ids_list != NULL);
+ g_return_if_fail (named_ids_len != NULL);
- CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
- e_return_val_mapi_error_if_fail (build_props != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
- e_return_val_mapi_error_if_fail (cb != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+ if (((proptag >> 16) & 0xFFFF) >= 0x8000) {
+ if (!*named_ids_list) {
+ *named_ids_list = g_new0 (ResolveNamedIDsData, 1);
+ *named_ids_len = 0;
+ } else {
+ *named_ids_list = g_renew (ResolveNamedIDsData, *named_ids_list, *named_ids_len + 1);
+ }
- mem_ctx = talloc_new (priv->session);
+ (*named_ids_list)[*named_ids_len].pidlid_propid = proptag;
+ (*named_ids_list)[*named_ids_len].propid = MAPI_E_RESERVED;
+ (*named_ids_len) += 1;
+ }
+}
- LOCK ();
+static void
+gather_mapi_SRestriction_named_ids (struct mapi_SRestriction *restriction,
+ ResolveNamedIDsData **named_ids_list,
+ guint *named_ids_len)
+{
+ guint i;
- ms = GetGALTableCount (priv->session, &n_rows);
- if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "GetGALTableCount", ms);
- n_rows = 0;
- }
+ g_return_if_fail (restriction != NULL);
+ g_return_if_fail (named_ids_list != NULL);
+ g_return_if_fail (named_ids_len != NULL);
- propsTagArray = set_SPropTagArray (mem_ctx, 0x1, PR_MESSAGE_CLASS);
- if (!build_props (conn, 0, mem_ctx, propsTagArray, brp_data, cancellable, perror)) {
- make_mapi_error (perror, "build_props", MAPI_E_CALL_FAILED);
- UNLOCK();
- talloc_free (mem_ctx);
- return FALSE;
+ switch (restriction->rt) {
+ case RES_AND:
+ for (i = 0; i < restriction->res.resAnd.cRes; i++) {
+ gather_mapi_SRestriction_named_ids ((struct mapi_SRestriction *) &(restriction->res.resAnd.res[i]), named_ids_list, named_ids_len);
+ }
+ break;
+ case RES_OR:
+ for (i = 0; i < restriction->res.resOr.cRes; i++) {
+ gather_mapi_SRestriction_named_ids ((struct mapi_SRestriction *) &(restriction->res.resOr.res[i]), named_ids_list, named_ids_len);
+ }
+ break;
+ #ifdef HAVE_RES_NOT_SUPPORTED
+ case RES_NOT:
+ gather_mapi_SRestriction_named_ids ((struct mapi_SRestriction *) restriction->res.resNot.res, named_ids_list, named_ids_len);
+ break;
+ #endif
+ case RES_CONTENT:
+ maybe_add_named_id_tag (restriction->res.resContent.ulPropTag, named_ids_list, named_ids_len);
+ maybe_add_named_id_tag (restriction->res.resContent.lpProp.ulPropTag, named_ids_list, named_ids_len);
+ break;
+ case RES_PROPERTY:
+ maybe_add_named_id_tag (restriction->res.resProperty.ulPropTag, named_ids_list, named_ids_len);
+ maybe_add_named_id_tag (restriction->res.resProperty.lpProp.ulPropTag, named_ids_list, named_ids_len);
+ break;
+ case RES_COMPAREPROPS:
+ maybe_add_named_id_tag (restriction->res.resCompareProps.ulPropTag1, named_ids_list, named_ids_len);
+ maybe_add_named_id_tag (restriction->res.resCompareProps.ulPropTag2, named_ids_list, named_ids_len);
+ break;
+ case RES_BITMASK:
+ maybe_add_named_id_tag (restriction->res.resBitmask.ulPropTag, named_ids_list, named_ids_len);
+ break;
+ case RES_SIZE:
+ maybe_add_named_id_tag (restriction->res.resSize.ulPropTag, named_ids_list, named_ids_len);
+ break;
+ case RES_EXIST:
+ maybe_add_named_id_tag (restriction->res.resExist.ulPropTag, named_ids_list, named_ids_len);
+ break;
}
+}
- ms = MAPI_E_SUCCESS;
- count = 0;
- ulFlags = TABLE_START;
- while (ms == MAPI_E_SUCCESS) {
- aRowSet = NULL;
- /* fetch per 100 items */
- ms = GetGALTable (priv->session, propsTagArray, &aRowSet, 100, ulFlags);
- if ((!aRowSet) || (!(aRowSet->aRow)) || ms != MAPI_E_SUCCESS) {
+static void
+maybe_replace_named_id_tag (uint32_t *pproptag,
+ const ResolveNamedIDsData *named_ids_list,
+ guint named_ids_len)
+{
+ gint i;
+
+ g_return_if_fail (pproptag != NULL);
+ g_return_if_fail (named_ids_list != NULL);
+
+ if ((((*pproptag) >> 16) & 0xFFFF) < 0x8000)
+ return;
+
+ for (i = 0; i < named_ids_len; i++) {
+ if ((*pproptag) == named_ids_list[i].pidlid_propid ||
+ ((((*pproptag) & 0xFFFF) == PT_ERROR) &&
+ ((*pproptag) & ~0xFFFF) == (named_ids_list[i].pidlid_propid & ~0xFFFF))) {
+ (*pproptag) = ((*pproptag) & 0xFFFF) | (named_ids_list[i].propid & ~0xFFFF);
break;
}
- if (aRowSet->cRows) {
- global_unlock ();
- for (i = 0; i < aRowSet->cRows; i++, count++) {
- if (!cb (conn, count, n_rows, &aRowSet->aRow[i], data, cancellable, perror)) {
- ms = MAPI_E_RESERVED;
- break;
- }
- }
- global_lock ();
- } else {
- talloc_free (aRowSet);
- break;
+ }
+}
+
+static void
+replace_mapi_SRestriction_named_ids (struct mapi_SRestriction *restriction,
+ const ResolveNamedIDsData *named_ids_list,
+ guint named_ids_len)
+{
+ guint i;
+ uint32_t proptag;
+
+ g_return_if_fail (restriction != NULL);
+ g_return_if_fail (named_ids_list != NULL);
+
+ #define check_proptag(x) { \
+ proptag = x; \
+ maybe_replace_named_id_tag (&proptag, named_ids_list, named_ids_len); \
+ x = proptag; \
}
- ulFlags = TABLE_CUR;
- talloc_free (aRowSet);
+ switch (restriction->rt) {
+ case RES_AND:
+ for (i = 0; i < restriction->res.resAnd.cRes; i++) {
+ replace_mapi_SRestriction_named_ids ((struct mapi_SRestriction *) &(restriction->res.resAnd.res[i]), named_ids_list, named_ids_len);
+ }
+ break;
+ case RES_OR:
+ for (i = 0; i < restriction->res.resOr.cRes; i++) {
+ replace_mapi_SRestriction_named_ids ((struct mapi_SRestriction *) &(restriction->res.resOr.res[i]), named_ids_list, named_ids_len);
+ }
+ break;
+ #ifdef HAVE_RES_NOT_SUPPORTED
+ case RES_NOT:
+ replace_mapi_SRestriction_named_ids (restriction->res.resNot.res, named_ids_list, named_ids_len);
+ break;
+ #endif
+ case RES_CONTENT:
+ check_proptag (restriction->res.resContent.ulPropTag);
+ check_proptag (restriction->res.resContent.lpProp.ulPropTag);
+ break;
+ case RES_PROPERTY:
+ check_proptag (restriction->res.resProperty.ulPropTag);
+ check_proptag (restriction->res.resProperty.lpProp.ulPropTag);
+ break;
+ case RES_COMPAREPROPS:
+ check_proptag (restriction->res.resCompareProps.ulPropTag1);
+ check_proptag (restriction->res.resCompareProps.ulPropTag2);
+ break;
+ case RES_BITMASK:
+ check_proptag (restriction->res.resBitmask.ulPropTag);
+ break;
+ case RES_SIZE:
+ check_proptag (restriction->res.resSize.ulPropTag);
+ break;
+ case RES_EXIST:
+ check_proptag (restriction->res.resExist.ulPropTag);
+ break;
}
- talloc_free (mem_ctx);
+ #undef check_proptag
+}
- UNLOCK ();
+static gboolean
+change_mapi_SRestriction_named_ids (EMapiConnection *conn,
+ mapi_object_t *obj_folder,
+ struct mapi_SRestriction *restrictions,
+ GCancellable *cancellable,
+ GError **perror)
+{
+ ResolveNamedIDsData *named_ids_list = NULL;
+ guint named_ids_len = 0;
+ gboolean res = FALSE;
- if (ms != MAPI_E_SUCCESS && ms != MAPI_E_RESERVED)
- make_mapi_error (perror, "GetGALTable", ms);
+ CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
+ e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+ e_return_val_mapi_error_if_fail (obj_folder != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+ e_return_val_mapi_error_if_fail (restrictions != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
- return ms == MAPI_E_SUCCESS;
+ gather_mapi_SRestriction_named_ids (restrictions, &named_ids_list, &named_ids_len);
+
+ if (!named_ids_list)
+ return TRUE;
+
+ res = e_mapi_connection_resolve_named_props (conn, mapi_object_get_id (obj_folder), named_ids_list, named_ids_len, cancellable, perror);
+
+ if (res)
+ replace_mapi_SRestriction_named_ids (restrictions, named_ids_list, named_ids_len);
+
+ g_free (named_ids_list);
+
+ return res;
}
+/* deals with named IDs transparently, thus it's OK to pass Restrictions with PidLid and PidName constants */
gboolean
-e_mapi_connection_get_public_folder (EMapiConnection *conn,
- mapi_object_t *obj_store,
- GCancellable *cancellable,
- GError **perror)
+e_mapi_connection_list_objects (EMapiConnection *conn,
+ mapi_object_t *obj_folder,
+ BuildRestrictionsCB build_rs_cb,
+ gpointer build_rs_cb_data,
+ ListObjectsCB cb,
+ gpointer user_data,
+ GCancellable *cancellable,
+ GError **perror)
{
enum MAPISTATUS ms;
+ TALLOC_CTX *mem_ctx;
+ mapi_object_t obj_table;
+ struct SPropTagArray *propTagArray;
+ struct ListObjectsInternalData loi_data;
CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+ e_return_val_mapi_error_if_fail (cb != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+ e_return_val_mapi_error_if_fail (obj_folder != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
LOCK ();
+ mem_ctx = talloc_new (priv->session);
+ mapi_object_init (&obj_table);
- mapi_object_init (&priv->public_store);
-
- ms = OpenPublicFolder (priv->session, &priv->public_store);
+ if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
+ ms = MAPI_E_USER_CANCEL;
+ goto cleanup;
+ }
+ /* Get a handle on the container */
+ ms = GetContentsTable (obj_folder, &obj_table, TableFlags_UseUnicode, NULL);
if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "OpenPublicFolder", ms);
+ make_mapi_error (perror, "GetContentsTable", ms);
+ goto cleanup;
}
- *obj_store = priv->public_store;
- UNLOCK ();
-
- return ms == MAPI_E_SUCCESS;
-}
-
-/* Returns TRUE if all recipients were read succcesfully, else returns FALSE */
-static gboolean
-e_mapi_util_get_recipients (EMapiConnection *conn, TALLOC_CTX *mem_ctx, mapi_object_t *obj_message, GSList **recip_list, GError **perror)
-{
- enum MAPISTATUS ms;
- struct SPropTagArray proptags;
- struct SRowSet rows_recip;
- uint32_t i_row_recip;
- gboolean status = TRUE;
-
- e_mapi_debug_print("%s: Entering %s ", G_STRLOC, G_STRFUNC);
+ propTagArray = set_SPropTagArray (mem_ctx, 0x4,
+ PidTagMid,
+ PidTagMessageClass,
+ PidTagMessageFlags,
+ PidTagLastModificationTime);
- /* fetch recipient table */
- ms = GetRecipientTable (obj_message, &rows_recip, &proptags);
+ /* Set primary columns to be fetched */
+ ms = SetColumns (&obj_table, propTagArray);
if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "GetRecipientTable", ms);
+ make_mapi_error (perror, "SetColumns", ms);
goto cleanup;
}
- for (i_row_recip = 0; i_row_recip < rows_recip.cRows; i_row_recip++) {
- ExchangeMAPIRecipient *recipient = g_new0 (ExchangeMAPIRecipient, 1);
- gchar *display_name = NULL, *email = NULL;
- const struct Binary_r *entryid;
+ if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
+ ms = MAPI_E_USER_CANCEL;
+ goto cleanup;
+ }
- recipient->mem_ctx = talloc_new (conn->priv->session);
+ if (build_rs_cb) {
+ struct mapi_SRestriction *restrictions = NULL;
- entryid = e_mapi_util_find_row_propval (&(rows_recip.aRow[i_row_recip]), PR_RECIPIENT_ENTRYID);
- if (entryid && e_mapi_util_recip_entryid_decode (conn, entryid, &display_name, &email) && email) {
- recipient->email_id = talloc_strdup (recipient->mem_ctx, email);
- if (display_name)
- recipient->display_name = talloc_strdup (recipient->mem_ctx, display_name);
- } else {
- recipient->email_id = talloc_steal (recipient->mem_ctx, (const gchar *) e_mapi_util_find_row_propval (&(rows_recip.aRow[i_row_recip]), PR_SMTP_ADDRESS_UNICODE));
- /* fallback */
- if (!recipient->email_id) {
- uint32_t fallback_props[] = {
- PROP_TAG (PT_UNICODE, 0x6001), /* PidTagNickname for Recipients table */
- PR_RECIPIENT_DISPLAY_NAME_UNICODE
- };
- gint ii;
- const gchar *addrtype = e_mapi_util_find_row_propval (&(rows_recip.aRow[i_row_recip]), PR_ADDRTYPE_UNICODE);
-
- if (addrtype && !g_ascii_strcasecmp (addrtype, "SMTP"))
- recipient->email_id = talloc_steal (recipient->mem_ctx, (const gchar *) e_mapi_util_find_row_propval (&(rows_recip.aRow[i_row_recip]), PR_EMAIL_ADDRESS_UNICODE));
-
- for (ii = 0; !recipient->email_id && ii < G_N_ELEMENTS (fallback_props); ii++) {
- recipient->email_id = talloc_steal (recipient->mem_ctx, (const gchar *) e_mapi_util_find_row_propval (&(rows_recip.aRow[i_row_recip]), fallback_props[ii]));
- }
+ if (!build_rs_cb (conn, mem_ctx, &restrictions, build_rs_cb_data, cancellable, perror)) {
+ ms = MAPI_E_CALL_FAILED;
+ make_mapi_error (perror, "build_restrictions", ms);
+ goto cleanup;
+ }
+
+ if (restrictions) {
+ change_mapi_SRestriction_named_ids (conn, obj_folder, restrictions, cancellable, perror);
+
+ if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
+ ms = MAPI_E_USER_CANCEL;
+ goto cleanup;
}
- if (recipient->email_id) {
- const gchar *addrtype = e_mapi_util_find_row_propval (&(rows_recip.aRow[i_row_recip]), PR_ADDRTYPE_UNICODE);
+ /* Applying any restriction that are set. */
+ ms = Restrict (&obj_table, restrictions, NULL);
+ if (ms != MAPI_E_SUCCESS) {
+ make_mapi_error (perror, "Restrict", ms);
+ goto cleanup;
+ }
- if (addrtype && g_ascii_strcasecmp (addrtype, "EX") == 0)
- recipient->email_id = talloc_strdup (recipient->mem_ctx, e_mapi_connection_ex_to_smtp (conn, recipient->email_id, NULL, NULL, NULL));
+ if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
+ ms = MAPI_E_USER_CANCEL;
+ goto cleanup;
}
}
+ }
- recipient->out_SRow.ulAdrEntryPad = rows_recip.aRow[i_row_recip].ulAdrEntryPad;
- recipient->out_SRow.cValues = rows_recip.aRow[i_row_recip].cValues;
- recipient->out_SRow.lpProps = talloc_steal ((TALLOC_CTX *)recipient->mem_ctx, rows_recip.aRow[i_row_recip].lpProps);
+ loi_data.cb = cb;
+ loi_data.user_data = user_data;
- *recip_list = g_slist_append (*recip_list, recipient);
+ ms = foreach_tablerow (conn, mem_ctx, &obj_table, list_objects_internal_cb, &loi_data, cancellable, perror);
- g_free (display_name);
- g_free (email);
- }
-
-cleanup:
- if (ms != MAPI_E_SUCCESS)
- status = FALSE;
-
- e_mapi_debug_print("%s: Leaving %s ", G_STRLOC, G_STRFUNC);
+ cleanup:
+ mapi_object_release (&obj_table);
+ talloc_free (mem_ctx);
+ UNLOCK ();
- return status;
+ return ms == MAPI_E_SUCCESS;
}
-static enum MAPISTATUS
-open_folder (EMapiConnection *conn, uint32_t olFolder, mapi_id_t *fid, guint32 fid_options, mapi_object_t *obj_folder, GError **perror)
+static gboolean
+has_embedded_message_with_html (EMapiObject *object)
{
- enum MAPISTATUS ms;
+ EMapiAttachment *attach;
- CHECK_CORRECT_CONN_AND_GET_PRIV (conn, MAPI_E_INVALID_PARAMETER);
- e_return_val_mapi_error_if_fail (obj_folder != NULL, MAPI_E_INVALID_PARAMETER, MAPI_E_INVALID_PARAMETER);
- e_return_val_mapi_error_if_fail (fid != NULL, MAPI_E_INVALID_PARAMETER, MAPI_E_INVALID_PARAMETER);
+ if (!object)
+ return FALSE;
- if (*fid == 0) {
- ms = GetDefaultFolder (&priv->msg_store, fid, olFolder);
- if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "GetDefaultFolder", ms);
- return ms;
- }
+ for (attach = object->attachments; attach; attach = attach->next) {
+ if (!attach->embedded_object)
+ continue;
- fid_options = 0;
- }
+ if (e_mapi_util_find_array_propval (&attach->embedded_object->properties, PidTagHtml) &&
+ !e_mapi_util_find_array_propval (&attach->embedded_object->properties, PidTagBody))
+ return TRUE;
- if ((fid_options & MAPI_OPTIONS_USE_PFSTORE) != 0) {
- if (!ensure_public_store (priv, perror)) {
- return MAPI_E_CALL_FAILED;
- }
+ if (has_embedded_message_with_html (attach->embedded_object))
+ return TRUE;
}
- ms = OpenFolder (((fid_options & MAPI_OPTIONS_USE_PFSTORE) != 0 ? &priv->public_store : &priv->msg_store), *fid, obj_folder);
- if (ms != MAPI_E_SUCCESS)
- make_mapi_error (perror, "OpenFolder", ms);
-
- return ms;
+ return FALSE;
}
-gboolean
-e_mapi_connection_open_default_folder (EMapiConnection *conn,
- uint32_t olFolderIdentifier,
- mapi_object_t *obj_folder,
- GCancellable *cancellable,
- GError **perror)
+static gboolean
+get_additional_properties_cb (EMapiConnection *conn,
+ TALLOC_CTX *mem_ctx,
+ /* const */ EMapiObject *object,
+ guint32 obj_index,
+ guint32 obj_total,
+ gpointer user_data,
+ GCancellable *cancellable,
+ GError **perror)
{
- enum MAPISTATUS ms;
- mapi_id_t fid = 0;
- gboolean res;
-
- CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
- e_return_val_mapi_error_if_fail (obj_folder != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+ uint32_t ii;
+ EMapiObject *dest_object = user_data;
- LOCK ();
+ g_return_val_if_fail (object != NULL, FALSE);
+ g_return_val_if_fail (dest_object != NULL, FALSE);
- mapi_object_init (obj_folder);
+ for (ii = 0; ii < object->properties.cValues; ii++) {
+ uint32_t proptag = object->properties.lpProps[ii].ulPropTag;
- ms = GetDefaultFolder (&priv->msg_store, &fid, olFolderIdentifier);
- if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "GetDefaultFolder", ms);
- UNLOCK ();
- return FALSE;
- }
+ if ((proptag & 0xFFFF) == PT_ERROR
+ || e_mapi_util_find_array_propval (&dest_object->properties, proptag))
+ continue;
- if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
- UNLOCK ();
- return FALSE;
- }
+ dest_object->properties.cValues++;
+ dest_object->properties.lpProps = talloc_realloc (mem_ctx,
+ dest_object->properties.lpProps,
+ struct mapi_SPropValue,
+ dest_object->properties.cValues + 1);
+ dest_object->properties.lpProps[dest_object->properties.cValues - 1] = object->properties.lpProps[ii];
- res = e_mapi_connection_open_personal_folder (conn, fid, obj_folder, cancellable, perror);
+ #define steal_ptr(x) (x) = talloc_steal (dest_object, (x))
+ switch (proptag & 0xFFFF) {
+ case PT_BOOLEAN:
+ case PT_I2:
+ case PT_LONG:
+ case PT_DOUBLE:
+ case PT_I8:
+ case PT_SYSTIME:
+ break;
+ case PT_STRING8:
+ steal_ptr (dest_object->properties.lpProps[dest_object->properties.cValues - 1].value.lpszA);
+ break;
+ case PT_UNICODE:
+ steal_ptr (dest_object->properties.lpProps[dest_object->properties.cValues - 1].value.lpszW);
+ break;
+ default:
+ g_debug ("%s: Do not know how to steal property type 0x%x, skipping it", G_STRFUNC, proptag & 0xFFFF);
+ dest_object->properties.cValues--;
+ break;
+ }
+ #undef steal_ptr
- UNLOCK ();
+ dest_object->properties.lpProps[dest_object->properties.cValues].ulPropTag = 0;
+ }
- return res;
+ return TRUE;
}
-gboolean
-e_mapi_connection_open_personal_folder (EMapiConnection *conn,
- mapi_id_t fid,
- mapi_object_t *obj_folder,
- GCancellable *cancellable,
- GError **perror)
+static void
+traverse_attachments_for_body (EMapiConnection *conn,
+ TALLOC_CTX *mem_ctx,
+ EMapiObject *object,
+ mapi_object_t *obj_message,
+ GCancellable *cancellable,
+ GError **perror)
{
- enum MAPISTATUS ms;
-
- CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
- e_return_val_mapi_error_if_fail (obj_folder != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
-
- LOCK ();
-
- mapi_object_init (obj_folder);
+ EMapiAttachment *attach;
- ms = OpenFolder (&priv->msg_store, fid, obj_folder);
- if (ms != MAPI_E_SUCCESS)
- make_mapi_error (perror, "OpenFolder", ms);
+ g_return_if_fail (conn != NULL);
+ g_return_if_fail (mem_ctx != NULL);
+ g_return_if_fail (obj_message != NULL);
- UNLOCK ();
+ if (!has_embedded_message_with_html (object))
+ return;
- return ms == MAPI_E_SUCCESS;
-}
+ for (attach = object->attachments; attach && !g_cancellable_is_cancelled (cancellable); attach = attach->next) {
+ if (attach->embedded_object) {
+ const uint32_t *pattach_num;
+ mapi_object_t obj_attach;
+ mapi_object_t obj_embedded;
+ gboolean have_embedded = FALSE;
-gboolean
-e_mapi_connection_open_public_folder (EMapiConnection *conn,
- mapi_id_t fid,
- mapi_object_t *obj_folder,
- GCancellable *cancellable,
- GError **perror)
-{
- enum MAPISTATUS ms;
+ pattach_num = e_mapi_util_find_array_propval (&attach->properties, PidTagAttachNumber);
+ if (!pattach_num)
+ continue;
- CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
- e_return_val_mapi_error_if_fail (obj_folder != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+ mapi_object_init (&obj_attach);
+ mapi_object_init (&obj_embedded);
- LOCK ();
+ if (e_mapi_util_find_array_propval (&attach->embedded_object->properties, PidTagHtml) &&
+ !e_mapi_util_find_array_propval (&attach->embedded_object->properties, PidTagBody)) {
+ struct SPropTagArray *tags;
- if (!ensure_public_store (priv, perror)) {
- UNLOCK ();
- return FALSE;
- }
+ if (OpenAttach (obj_message, *pattach_num, &obj_attach) != MAPI_E_SUCCESS)
+ continue;
- if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
- UNLOCK ();
- return FALSE;
- }
+ if (OpenEmbeddedMessage (&obj_attach, &obj_embedded, MAPI_READONLY) != MAPI_E_SUCCESS) {
+ mapi_object_release (&obj_attach);
+ continue;
+ }
- mapi_object_init (obj_folder);
+ have_embedded = TRUE;
- ms = OpenFolder (&priv->public_store, fid, obj_folder);
- if (ms != MAPI_E_SUCCESS)
- make_mapi_error (perror, "OpenFolder", ms);
+ tags = set_SPropTagArray (mem_ctx, 1, PidTagBody);
- UNLOCK ();
+ e_mapi_fast_transfer_properties (conn, mem_ctx, &obj_embedded, tags, get_additional_properties_cb, attach->embedded_object, cancellable, perror);
- return ms == MAPI_E_SUCCESS;
-}
+ talloc_free (tags);
+ }
-gboolean
-e_mapi_connection_close_folder (EMapiConnection *conn,
- mapi_object_t *obj_folder,
- GCancellable *cancellable,
- GError **perror)
-{
- CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
- e_return_val_mapi_error_if_fail (obj_folder != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+ if (has_embedded_message_with_html (attach->embedded_object)) {
+ if (!have_embedded) {
+ if (OpenAttach (obj_message, *pattach_num, &obj_attach) != MAPI_E_SUCCESS)
+ continue;
- LOCK ();
+ if (OpenEmbeddedMessage (&obj_attach, &obj_embedded, MAPI_READONLY) != MAPI_E_SUCCESS) {
+ mapi_object_release (&obj_attach);
+ continue;
+ }
- mapi_object_release (obj_folder);
+ have_embedded = TRUE;
+ }
- UNLOCK ();
+ traverse_attachments_for_body (conn, mem_ctx, attach->embedded_object, &obj_embedded, cancellable, perror);
+ }
- return TRUE;
+ mapi_object_release (&obj_embedded);
+ mapi_object_release (&obj_attach);
+ }
+ }
}
-/* deals with named IDs transparently, if not using NULL bpr_cb, thus it's OK to check with PidLid and PidName constants only */
-gboolean
-e_mapi_connection_get_folder_properties (EMapiConnection *conn,
- mapi_object_t *obj_folder,
- BuildReadPropsCB brp_cb,
- gpointer brp_cb_user_data,
- GetFolderPropertiesCB cb,
- gpointer cb_user_data,
- GCancellable *cancellable,
- GError **perror)
+struct EnsureAdditionalPropertiesData
{
- enum MAPISTATUS ms;
- TALLOC_CTX *mem_ctx;
- struct SPropTagArray *spropTagArray = NULL;
- struct mapi_SPropValue_array *properties = NULL;
- gboolean res = FALSE;
+ TransferObjectCB cb;
+ gpointer cb_user_data;
+ mapi_object_t *obj_folder;
+ guint32 downloaded;
+};
- CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
- e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
- e_return_val_mapi_error_if_fail (obj_folder != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+static gboolean
+ensure_additional_properties_cb (EMapiConnection *conn,
+ TALLOC_CTX *mem_ctx,
+ /* const */ EMapiObject *object,
+ guint32 obj_index,
+ guint32 obj_total,
+ gpointer user_data,
+ GCancellable *cancellable,
+ GError **perror)
+{
+ struct ap_data {
+ uint32_t orig_proptag, use_proptag;
+ } additional_properties[] = {
+ { PidTagBody, MAPI_E_RESERVED },
+ { PidNameContentClass, MAPI_E_RESERVED }
+ };
+ struct EnsureAdditionalPropertiesData *eap = user_data;
+ gboolean need_any = FALSE, need_attachments;
+ uint32_t ii;
- LOCK ();
- mem_ctx = talloc_new (priv->session);
+ g_return_val_if_fail (eap != NULL, FALSE);
+ g_return_val_if_fail (eap->cb != NULL, FALSE);
+ g_return_val_if_fail (object != NULL, FALSE);
- if (g_cancellable_set_error_if_cancelled (cancellable, perror))
- goto cleanup;
+ for (ii = 0; ii < G_N_ELEMENTS (additional_properties); ii++) {
+ uint32_t prop = additional_properties[ii].orig_proptag;
- spropTagArray = set_SPropTagArray (mem_ctx, 3, PidTagFolderId, PidTagLastModificationTime, PidTagContentCount);
- if (brp_cb) {
- if (!brp_cb (conn, mapi_object_get_id (obj_folder), mem_ctx, spropTagArray, brp_cb_user_data, cancellable, perror)) {
- goto cleanup;
+ if (!e_mapi_util_find_array_propval (&object->properties, prop)) {
+ if (((prop >> 16) & 0xFFFF) >= 0x8000) {
+ prop = e_mapi_connection_resolve_named_prop (conn, mapi_object_get_id (eap->obj_folder), prop, cancellable, NULL);
+ }
+ } else {
+ prop = MAPI_E_RESERVED;
}
- } else {
- talloc_free (spropTagArray);
- spropTagArray = NULL;
- }
- properties = talloc_zero (mem_ctx, struct mapi_SPropValue_array);
- if (spropTagArray && spropTagArray->cValues) {
- struct SPropValue *lpProps;
- uint32_t prop_count = 0, k, ll;
- ResolveNamedIDsData *named_ids_list = NULL;
- guint named_ids_len = 0;
+ additional_properties[ii].use_proptag = prop;
+ need_any = need_any || prop != MAPI_E_RESERVED;
+ }
- lpProps = talloc_zero (mem_ctx, struct SPropValue);
+ need_attachments = has_embedded_message_with_html (object);
- for (k = 0; k < spropTagArray->cValues; k++) {
- uint32_t proptag = spropTagArray->aulPropTag[k];
+ /* Fast-transfer transfers only Html or Body, never both */
+ if (need_any || need_attachments) {
+ const mapi_id_t *mid;
- if (may_skip_property (proptag)) {
- const gchar *name = get_proptag_name (proptag);
- if (!name)
- name = "";
+ mid = e_mapi_util_find_array_propval (&object->properties, PidTagMid);
+ if (mid && *mid) {
+ mapi_object_t obj_message;
+
+ mapi_object_init (&obj_message);
- g_debug ("%s: Cannot fetch property 0x%08x %s", G_STRFUNC, proptag, name);
- } else if (((proptag >> 16) & 0xFFFF) >= 0x8000) {
- if (!named_ids_list)
- named_ids_list = g_new0 (ResolveNamedIDsData, spropTagArray->cValues - k + 1);
- named_ids_list[named_ids_len].pidlid_propid = proptag;
- named_ids_list[named_ids_len].propid = MAPI_E_RESERVED;
- named_ids_len++;
- }
- }
+ if (OpenMessage (eap->obj_folder, mapi_object_get_id (eap->obj_folder), *mid, &obj_message, 0) == MAPI_E_SUCCESS) {
+ struct SPropTagArray *tags = NULL;
- if (named_ids_list) {
- if (!e_mapi_connection_resolve_named_props (conn, mapi_object_get_id (obj_folder), named_ids_list, named_ids_len, cancellable, perror)) {
- g_free (named_ids_list);
- goto cleanup;
- }
+ for (ii = 0; ii < G_N_ELEMENTS (additional_properties); ii++) {
+ uint32_t prop = additional_properties[ii].use_proptag;
- if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
- g_free (named_ids_list);
- goto cleanup;
- }
+ if (prop == MAPI_E_RESERVED)
+ continue;
- for (k = 0, ll = 0; k < named_ids_len; k++) {
- if (named_ids_list[k].propid != MAPI_E_RESERVED) {
- while (ll < spropTagArray->cValues) {
- if (spropTagArray->aulPropTag[k] == named_ids_list[k].pidlid_propid) {
- spropTagArray->aulPropTag[k] = named_ids_list[k].propid;
- break;
- }
- ll++;
- }
+ if (!tags)
+ tags = set_SPropTagArray (mem_ctx, 1, prop);
+ else
+ SPropTagArray_add (mem_ctx, tags, prop);
}
- }
- }
- ms = GetProps (obj_folder, MAPI_PROPS_SKIP_NAMEDID_CHECK | MAPI_UNICODE, spropTagArray, &lpProps, &prop_count);
- if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "GetProps", ms);
- g_free (named_ids_list);
- goto cleanup;
- }
+ if (tags) {
+ uint32_t jj = object->properties.cValues;
- if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
- g_free (named_ids_list);
- goto cleanup;
- }
+ e_mapi_fast_transfer_properties (conn, mem_ctx, &obj_message, tags, get_additional_properties_cb, object, cancellable, perror);
- /* Conversion from SPropValue to mapi_SPropValue. (no padding here) */
- properties->cValues = prop_count;
- properties->lpProps = talloc_zero_array (mem_ctx, struct mapi_SPropValue, prop_count + 1);
- for (k = 0, ll = 0; k < prop_count; k++, ll++) {
- if (may_skip_property (lpProps[k].ulPropTag)) {
- ll--;
- properties->cValues--;
- } else {
- if (named_ids_list) {
- guint m;
+ while (jj < object->properties.cValues) {
+ for (ii = 0; ii < G_N_ELEMENTS (additional_properties); ii++) {
+ uint32_t proptag = object->properties.lpProps[jj].ulPropTag;
- for (m = 0; m < named_ids_len; m++) {
- if (lpProps[k].ulPropTag == named_ids_list[named_ids_len - m - 1].propid ||
- (((lpProps[k].ulPropTag & 0xFFFF) == PT_ERROR) &&
- (lpProps[k].ulPropTag & ~0xFFFF) == (named_ids_list[named_ids_len - m - 1].propid & ~0xFFFF))) {
- lpProps[k].ulPropTag = (lpProps[k].ulPropTag & 0xFFFF) | (named_ids_list[named_ids_len - m - 1].pidlid_propid & ~0xFFFF);
- break;
+ if (additional_properties[ii].use_proptag == proptag ||
+ (((proptag & 0xFFFF) == PT_STRING8 || (proptag & 0xFFFF) == PT_UNICODE) &&
+ (proptag & ~0xFFFF) == (additional_properties[ii].use_proptag & ~0xFFFF))) {
+ /* string8 and unicode properties are interchangeable in the union, luckily */
+ object->properties.lpProps[jj].ulPropTag = additional_properties[ii].orig_proptag;
+ break;
+ }
}
+
+ jj++;
}
+
+ talloc_free (tags);
}
- cast_mapi_SPropValue (mem_ctx, &properties->lpProps[ll], &lpProps[k]);
+ if (need_attachments)
+ traverse_attachments_for_body (conn, mem_ctx, object, &obj_message, cancellable, perror);
}
- }
- } else {
- ms = GetPropsAll (obj_folder, MAPI_UNICODE, properties);
- if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "GetPropsAll", ms);
- goto cleanup;
+
+ mapi_object_release (&obj_message);
}
}
- if (g_cancellable_set_error_if_cancelled (cancellable, perror))
- goto cleanup;
-
- res = cb (conn, mapi_object_get_id (obj_folder), mem_ctx, properties, cb_user_data, cancellable, perror);
-
- cleanup:
- talloc_free (spropTagArray);
- talloc_free (properties);
- talloc_free (mem_ctx);
- UNLOCK();
+ eap->downloaded++;
- return res;
+ return eap->cb (conn, mem_ctx, object, obj_index, obj_total, eap->cb_user_data, cancellable, perror);
}
-typedef gboolean (*ForeachTableRowCB) (EMapiConnection *conn, mapi_id_t fid, TALLOC_CTX *mem_ctx, struct SRow *srow, guint32 row_index, guint32 rows_total, gpointer user_data, GCancellable *cancellable, GError **perror);
-
static enum MAPISTATUS
-foreach_tablerow (EMapiConnection *conn, mapi_id_t fid, TALLOC_CTX *mem_ctx, mapi_object_t *obj_table, ForeachTableRowCB cb, gpointer user_data, GCancellable *cancellable, GError **perror)
+fetch_object_property_as_stream (EMapiConnection *conn,
+ TALLOC_CTX *mem_ctx,
+ mapi_object_t *obj_message,
+ uint32_t proptag,
+ struct SBinary_short *bin,
+ GCancellable *cancellable,
+ GError **perror)
{
enum MAPISTATUS ms;
- struct SRowSet SRowSet;
- uint32_t count, i, cursor_pos = 0;
+ mapi_object_t obj_stream;
+ uint32_t buf_size, max_read;
+ uint16_t off_data, cn_read;
+ gboolean done = FALSE;
- CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
- e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
- e_return_val_mapi_error_if_fail (mem_ctx != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
- e_return_val_mapi_error_if_fail (obj_table != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
- e_return_val_mapi_error_if_fail (cb != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+ g_return_val_if_fail (conn != NULL, MAPI_E_INVALID_PARAMETER);
+ g_return_val_if_fail (mem_ctx != NULL, MAPI_E_INVALID_PARAMETER);
+ g_return_val_if_fail (obj_message != NULL, MAPI_E_INVALID_PARAMETER);
+ g_return_val_if_fail (bin != NULL, MAPI_E_INVALID_PARAMETER);
- do {
- /* Number of items in the container */
- ms = QueryPosition (obj_table, &cursor_pos, &count);
- if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "QueryPosition", ms);
- break;
- }
+ mapi_object_init (&obj_stream);
- if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
- ms = MAPI_E_USER_CANCEL;
- break;
- }
+ ms = OpenStream (obj_message, proptag, STREAM_ACCESS_READ, &obj_stream);
+ if (ms != MAPI_E_SUCCESS) {
+ make_mapi_error (perror, "OpenStream", ms);
+ goto cleanup;
+ }
- if (!count)
- break;
+ bin->cb = 0;
- /* Fill the table columns with data from the rows */
- ms = QueryRows (obj_table, count, TBL_ADVANCE, &SRowSet);
- if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "QueryRows", ms);
- break;
- }
+ ms = GetStreamSize (&obj_stream, &buf_size);
+ if (ms != MAPI_E_SUCCESS) {
+ make_mapi_error (perror, "GetStreamSize", ms);
+ goto cleanup;
+ }
- if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
- ms = MAPI_E_USER_CANCEL;
- break;
- }
+ bin->cb = buf_size;
+ bin->lpb = talloc_size (mem_ctx, bin->cb + 1);
+ if (!bin->lpb || !bin->cb)
+ goto cleanup;
- for (i = 0; i < SRowSet.cRows && ms == MAPI_E_SUCCESS; i++) {
- if (!cb (conn, fid, mem_ctx, &SRowSet.aRow[i], cursor_pos + i + 1, count, user_data, cancellable, perror))
- ms = MAPI_E_RESERVED;
- else if (g_cancellable_set_error_if_cancelled (cancellable, perror))
- ms = MAPI_E_USER_CANCEL;
+ /* determine max_read first, to read by chunks as long as possible */
+ off_data = 0;
+ max_read = buf_size > STREAM_MAX_READ_SIZE ? STREAM_MAX_READ_SIZE : buf_size;
+ do {
+ ms = ReadStream (&obj_stream, (bin->lpb) + off_data, max_read, &cn_read);
+ if (ms == MAPI_E_SUCCESS) {
+ if (cn_read == 0) {
+ done = TRUE;
+ } else {
+ off_data += cn_read;
+ if (off_data >= buf_size)
+ done = TRUE;
+ }
+ break;
}
- } while (cursor_pos < count && ms == MAPI_E_SUCCESS);
- return ms;
-}
-
-struct ListObjectsInternalData
-{
- ListObjectsCB cb;
- gpointer user_data;
-};
-
-static gboolean
-list_objects_internal_cb (EMapiConnection *conn,
- mapi_id_t fid,
- TALLOC_CTX *mem_ctx,
- struct SRow *srow,
- guint32 row_index,
- guint32 rows_total,
- gpointer user_data,
- GCancellable *cancellable,
- GError **perror)
-{
- struct ListObjectsInternalData *loi_data = user_data;
- ListObjectsData lod;
- const mapi_id_t *pmid;
- const gchar *msg_class;
- const uint32_t *pmsg_flags;
- const struct FILETIME *last_modified;
-
- CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
- e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
- e_return_val_mapi_error_if_fail (mem_ctx != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
- e_return_val_mapi_error_if_fail (srow != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
-
- pmid = get_SPropValue_SRow_data (srow, PidTagMid);
- msg_class = get_SPropValue_SRow_data (srow, PidTagMessageClass);
- pmsg_flags = get_SPropValue_SRow_data (srow, PidTagMessageFlags);
- last_modified = get_SPropValue_SRow_data (srow, PidTagLastModificationTime);
-
- lod.mid = pmid ? *pmid : 0;
- lod.msg_class = msg_class;
- lod.msg_flags = pmsg_flags ? *pmsg_flags : 0;
- lod.last_modified = last_modified ? e_mapi_util_filetime_to_time_t (last_modified) : 0;
-
- return loi_data->cb (conn, fid, mem_ctx, &lod, row_index, rows_total, loi_data->user_data, cancellable, perror);
-}
-
-static void
-maybe_add_named_id_tag (uint32_t proptag,
- ResolveNamedIDsData **named_ids_list,
- guint *named_ids_len)
-{
- g_return_if_fail (named_ids_list != NULL);
- g_return_if_fail (named_ids_len != NULL);
-
- if (((proptag >> 16) & 0xFFFF) >= 0x8000) {
- if (!*named_ids_list) {
- *named_ids_list = g_new0 (ResolveNamedIDsData, 1);
- *named_ids_len = 0;
- } else {
- *named_ids_list = g_renew (ResolveNamedIDsData, *named_ids_list, *named_ids_len + 1);
- }
-
- (*named_ids_list)[*named_ids_len].pidlid_propid = proptag;
- (*named_ids_list)[*named_ids_len].propid = MAPI_E_RESERVED;
- (*named_ids_len) += 1;
- }
-}
-
-static void
-gather_mapi_SRestriction_named_ids (struct mapi_SRestriction *restriction,
- ResolveNamedIDsData **named_ids_list,
- guint *named_ids_len)
-{
- guint i;
-
- g_return_if_fail (restriction != NULL);
- g_return_if_fail (named_ids_list != NULL);
- g_return_if_fail (named_ids_len != NULL);
-
- switch (restriction->rt) {
- case RES_AND:
- for (i = 0; i < restriction->res.resAnd.cRes; i++) {
- gather_mapi_SRestriction_named_ids ((struct mapi_SRestriction *) &(restriction->res.resAnd.res[i]), named_ids_list, named_ids_len);
- }
- break;
- case RES_OR:
- for (i = 0; i < restriction->res.resOr.cRes; i++) {
- gather_mapi_SRestriction_named_ids ((struct mapi_SRestriction *) &(restriction->res.resOr.res[i]), named_ids_list, named_ids_len);
- }
- break;
- #ifdef HAVE_RES_NOT_SUPPORTED
- case RES_NOT:
- gather_mapi_SRestriction_named_ids ((struct mapi_SRestriction *) restriction->res.resNot.res, named_ids_list, named_ids_len);
- break;
- #endif
- case RES_CONTENT:
- maybe_add_named_id_tag (restriction->res.resContent.ulPropTag, named_ids_list, named_ids_len);
- maybe_add_named_id_tag (restriction->res.resContent.lpProp.ulPropTag, named_ids_list, named_ids_len);
- break;
- case RES_PROPERTY:
- maybe_add_named_id_tag (restriction->res.resProperty.ulPropTag, named_ids_list, named_ids_len);
- maybe_add_named_id_tag (restriction->res.resProperty.lpProp.ulPropTag, named_ids_list, named_ids_len);
- break;
- case RES_COMPAREPROPS:
- maybe_add_named_id_tag (restriction->res.resCompareProps.ulPropTag1, named_ids_list, named_ids_len);
- maybe_add_named_id_tag (restriction->res.resCompareProps.ulPropTag2, named_ids_list, named_ids_len);
- break;
- case RES_BITMASK:
- maybe_add_named_id_tag (restriction->res.resBitmask.ulPropTag, named_ids_list, named_ids_len);
- break;
- case RES_SIZE:
- maybe_add_named_id_tag (restriction->res.resSize.ulPropTag, named_ids_list, named_ids_len);
- break;
- case RES_EXIST:
- maybe_add_named_id_tag (restriction->res.resExist.ulPropTag, named_ids_list, named_ids_len);
- break;
- }
-}
-
-static void
-maybe_replace_named_id_tag (uint32_t *pproptag,
- const ResolveNamedIDsData *named_ids_list,
- guint named_ids_len)
-{
- gint i;
-
- g_return_if_fail (pproptag != NULL);
- g_return_if_fail (named_ids_list != NULL);
-
- if ((((*pproptag) >> 16) & 0xFFFF) < 0x8000)
- return;
-
- for (i = 0; i < named_ids_len; i++) {
- if ((*pproptag) == named_ids_list[i].pidlid_propid ||
- ((((*pproptag) & 0xFFFF) == PT_ERROR) &&
- ((*pproptag) & ~0xFFFF) == (named_ids_list[i].pidlid_propid & ~0xFFFF))) {
- (*pproptag) = ((*pproptag) & 0xFFFF) | (named_ids_list[i].propid & ~0xFFFF);
- break;
- }
- }
-}
-
-static void
-replace_mapi_SRestriction_named_ids (struct mapi_SRestriction *restriction,
- const ResolveNamedIDsData *named_ids_list,
- guint named_ids_len)
-{
- guint i;
- uint32_t proptag;
-
- g_return_if_fail (restriction != NULL);
- g_return_if_fail (named_ids_list != NULL);
-
- #define check_proptag(x) { \
- proptag = x; \
- maybe_replace_named_id_tag (&proptag, named_ids_list, named_ids_len); \
- x = proptag; \
- }
-
- switch (restriction->rt) {
- case RES_AND:
- for (i = 0; i < restriction->res.resAnd.cRes; i++) {
- replace_mapi_SRestriction_named_ids ((struct mapi_SRestriction *) &(restriction->res.resAnd.res[i]), named_ids_list, named_ids_len);
- }
- break;
- case RES_OR:
- for (i = 0; i < restriction->res.resOr.cRes; i++) {
- replace_mapi_SRestriction_named_ids ((struct mapi_SRestriction *) &(restriction->res.resOr.res[i]), named_ids_list, named_ids_len);
- }
- break;
- #ifdef HAVE_RES_NOT_SUPPORTED
- case RES_NOT:
- replace_mapi_SRestriction_named_ids (restriction->res.resNot.res, named_ids_list, named_ids_len);
- break;
- #endif
- case RES_CONTENT:
- check_proptag (restriction->res.resContent.ulPropTag);
- check_proptag (restriction->res.resContent.lpProp.ulPropTag);
- break;
- case RES_PROPERTY:
- check_proptag (restriction->res.resProperty.ulPropTag);
- check_proptag (restriction->res.resProperty.lpProp.ulPropTag);
- break;
- case RES_COMPAREPROPS:
- check_proptag (restriction->res.resCompareProps.ulPropTag1);
- check_proptag (restriction->res.resCompareProps.ulPropTag2);
- break;
- case RES_BITMASK:
- check_proptag (restriction->res.resBitmask.ulPropTag);
- break;
- case RES_SIZE:
- check_proptag (restriction->res.resSize.ulPropTag);
- break;
- case RES_EXIST:
- check_proptag (restriction->res.resExist.ulPropTag);
- break;
- }
-
- #undef check_proptag
-}
-
-static gboolean
-change_mapi_SRestriction_named_ids (EMapiConnection *conn,
- mapi_object_t *obj_folder,
- struct mapi_SRestriction *restrictions,
- GCancellable *cancellable,
- GError **perror)
-{
- ResolveNamedIDsData *named_ids_list = NULL;
- guint named_ids_len = 0;
- gboolean res = FALSE;
-
- CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
- e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
- e_return_val_mapi_error_if_fail (obj_folder != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
- e_return_val_mapi_error_if_fail (restrictions != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
-
- gather_mapi_SRestriction_named_ids (restrictions, &named_ids_list, &named_ids_len);
-
- if (!named_ids_list)
- return TRUE;
-
- res = e_mapi_connection_resolve_named_props (conn, mapi_object_get_id (obj_folder), named_ids_list, named_ids_len, cancellable, perror);
-
- if (res)
- replace_mapi_SRestriction_named_ids (restrictions, named_ids_list, named_ids_len);
-
- g_free (named_ids_list);
-
- return res;
-}
-
-/* deals with named IDs transparently, thus it's OK to pass Restrictions with PidLid and PidName constants */
-gboolean
-e_mapi_connection_list_objects (EMapiConnection *conn,
- mapi_object_t *obj_folder,
- BuildRestrictionsCB build_rs_cb,
- gpointer build_rs_cb_data,
- ListObjectsCB cb,
- gpointer user_data,
- GCancellable *cancellable,
- GError **perror)
-{
- enum MAPISTATUS ms;
- TALLOC_CTX *mem_ctx;
- mapi_object_t obj_table;
- struct SPropTagArray *propTagArray;
- struct ListObjectsInternalData loi_data;
-
- CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
- e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
- e_return_val_mapi_error_if_fail (cb != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
- e_return_val_mapi_error_if_fail (obj_folder != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
-
- LOCK ();
- mem_ctx = talloc_new (priv->session);
- mapi_object_init (&obj_table);
-
- if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
- ms = MAPI_E_USER_CANCEL;
- goto cleanup;
- }
-
- /* Get a handle on the container */
- ms = GetContentsTable (obj_folder, &obj_table, TableFlags_UseUnicode, NULL);
- if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "GetContentsTable", ms);
- goto cleanup;
- }
-
- propTagArray = set_SPropTagArray (mem_ctx, 0x4,
- PidTagMid,
- PidTagMessageClass,
- PidTagMessageFlags,
- PidTagLastModificationTime);
-
- /* Set primary columns to be fetched */
- ms = SetColumns (&obj_table, propTagArray);
- if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "SetColumns", ms);
- goto cleanup;
- }
-
- if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
- ms = MAPI_E_USER_CANCEL;
- goto cleanup;
- }
-
- if (build_rs_cb) {
- struct mapi_SRestriction *restrictions = NULL;
-
- if (!build_rs_cb (conn, mapi_object_get_id (obj_folder), mem_ctx, &restrictions, build_rs_cb_data, cancellable, perror)) {
- ms = MAPI_E_CALL_FAILED;
- make_mapi_error (perror, "build_restrictions", ms);
- goto cleanup;
- }
-
- if (restrictions) {
- change_mapi_SRestriction_named_ids (conn, obj_folder, restrictions, cancellable, perror);
-
- if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
- ms = MAPI_E_USER_CANCEL;
- goto cleanup;
- }
-
- /* Applying any restriction that are set. */
- ms = Restrict (&obj_table, restrictions, NULL);
- if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "Restrict", ms);
- goto cleanup;
- }
-
- if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
- ms = MAPI_E_USER_CANCEL;
- goto cleanup;
- }
- }
- }
-
- loi_data.cb = cb;
- loi_data.user_data = user_data;
-
- ms = foreach_tablerow (conn, mapi_object_get_id (obj_folder), mem_ctx, &obj_table, list_objects_internal_cb, &loi_data, cancellable, perror);
-
- cleanup:
- mapi_object_release (&obj_table);
- talloc_free (mem_ctx);
- UNLOCK ();
-
- return ms == MAPI_E_SUCCESS;
-}
-
-static gboolean
-has_embedded_message_with_html (EMapiObject *object)
-{
- EMapiAttachment *attach;
-
- if (!object)
- return FALSE;
-
- for (attach = object->attachments; attach; attach = attach->next) {
- if (!attach->embedded_object)
- continue;
-
- if (e_mapi_util_find_array_propval (&attach->embedded_object->properties, PidTagHtml) &&
- !e_mapi_util_find_array_propval (&attach->embedded_object->properties, PidTagBody))
- return TRUE;
-
- if (has_embedded_message_with_html (attach->embedded_object))
- return TRUE;
- }
-
- return FALSE;
-}
-
-static gboolean
-get_additional_properties_cb (EMapiConnection *conn,
- TALLOC_CTX *mem_ctx,
- /* const */ EMapiObject *object,
- guint32 obj_index,
- guint32 obj_total,
- gpointer user_data,
- GCancellable *cancellable,
- GError **perror)
-{
- uint32_t ii;
- EMapiObject *dest_object = user_data;
-
- g_return_val_if_fail (object != NULL, FALSE);
- g_return_val_if_fail (dest_object != NULL, FALSE);
-
- for (ii = 0; ii < object->properties.cValues; ii++) {
- uint32_t proptag = object->properties.lpProps[ii].ulPropTag;
-
- if ((proptag & 0xFFFF) == PT_ERROR
- || e_mapi_util_find_array_propval (&dest_object->properties, proptag))
- continue;
-
- dest_object->properties.cValues++;
- dest_object->properties.lpProps = talloc_realloc (mem_ctx,
- dest_object->properties.lpProps,
- struct mapi_SPropValue,
- dest_object->properties.cValues + 1);
- dest_object->properties.lpProps[dest_object->properties.cValues - 1] = object->properties.lpProps[ii];
-
- #define steal_ptr(x) (x) = talloc_steal (dest_object, (x))
- switch (proptag & 0xFFFF) {
- case PT_BOOLEAN:
- case PT_I2:
- case PT_LONG:
- case PT_DOUBLE:
- case PT_I8:
- case PT_SYSTIME:
- break;
- case PT_STRING8:
- steal_ptr (dest_object->properties.lpProps[dest_object->properties.cValues - 1].value.lpszA);
- break;
- case PT_UNICODE:
- steal_ptr (dest_object->properties.lpProps[dest_object->properties.cValues - 1].value.lpszW);
- break;
- default:
- g_debug ("%s: Do not know how to steal property type 0x%x, skipping it", G_STRFUNC, proptag & 0xFFFF);
- dest_object->properties.cValues--;
- break;
- }
- #undef steal_ptr
-
- dest_object->properties.lpProps[dest_object->properties.cValues].ulPropTag = 0;
- }
-
- return TRUE;
-}
-
-static void
-traverse_attachments_for_body (EMapiConnection *conn,
- TALLOC_CTX *mem_ctx,
- EMapiObject *object,
- mapi_object_t *obj_message,
- GCancellable *cancellable,
- GError **perror)
-{
- EMapiAttachment *attach;
-
- g_return_if_fail (conn != NULL);
- g_return_if_fail (mem_ctx != NULL);
- g_return_if_fail (obj_message != NULL);
-
- if (!has_embedded_message_with_html (object))
- return;
-
- for (attach = object->attachments; attach && !g_cancellable_is_cancelled (cancellable); attach = attach->next) {
- if (attach->embedded_object) {
- const uint32_t *pattach_num;
- mapi_object_t obj_attach;
- mapi_object_t obj_embedded;
- gboolean have_embedded = FALSE;
-
- pattach_num = e_mapi_util_find_array_propval (&attach->properties, PidTagAttachNumber);
- if (!pattach_num)
- continue;
-
- mapi_object_init (&obj_attach);
- mapi_object_init (&obj_embedded);
-
- if (e_mapi_util_find_array_propval (&attach->embedded_object->properties, PidTagHtml) &&
- !e_mapi_util_find_array_propval (&attach->embedded_object->properties, PidTagBody)) {
- struct SPropTagArray *tags;
-
- if (OpenAttach (obj_message, *pattach_num, &obj_attach) != MAPI_E_SUCCESS)
- continue;
-
- if (OpenEmbeddedMessage (&obj_attach, &obj_embedded, MAPI_READONLY) != MAPI_E_SUCCESS) {
- mapi_object_release (&obj_attach);
- continue;
- }
-
- have_embedded = TRUE;
-
- tags = set_SPropTagArray (mem_ctx, 1, PidTagBody);
-
- e_mapi_fast_transfer_properties (conn, mem_ctx, &obj_embedded, tags, get_additional_properties_cb, attach->embedded_object, cancellable, perror);
-
- talloc_free (tags);
- }
-
- if (has_embedded_message_with_html (attach->embedded_object)) {
- if (!have_embedded) {
- if (OpenAttach (obj_message, *pattach_num, &obj_attach) != MAPI_E_SUCCESS)
- continue;
-
- if (OpenEmbeddedMessage (&obj_attach, &obj_embedded, MAPI_READONLY) != MAPI_E_SUCCESS) {
- mapi_object_release (&obj_attach);
- continue;
- }
-
- have_embedded = TRUE;
- }
-
- traverse_attachments_for_body (conn, mem_ctx, attach->embedded_object, &obj_embedded, cancellable, perror);
- }
-
- mapi_object_release (&obj_embedded);
- mapi_object_release (&obj_attach);
- }
- }
-}
-
-struct EnsureAdditionalPropertiesData
-{
- TransferObjectCB cb;
- gpointer cb_user_data;
- mapi_object_t *obj_folder;
- guint32 downloaded;
-};
-
-static gboolean
-ensure_additional_properties_cb (EMapiConnection *conn,
- TALLOC_CTX *mem_ctx,
- /* const */ EMapiObject *object,
- guint32 obj_index,
- guint32 obj_total,
- gpointer user_data,
- GCancellable *cancellable,
- GError **perror)
-{
- struct ap_data {
- uint32_t orig_proptag, use_proptag;
- } additional_properties[] = {
- { PidTagBody, MAPI_E_RESERVED },
- { PidNameContentClass, MAPI_E_RESERVED }
- };
- struct EnsureAdditionalPropertiesData *eap = user_data;
- gboolean need_any = FALSE, need_attachments;
- uint32_t ii;
-
- g_return_val_if_fail (eap != NULL, FALSE);
- g_return_val_if_fail (eap->cb != NULL, FALSE);
- g_return_val_if_fail (object != NULL, FALSE);
-
- for (ii = 0; ii < G_N_ELEMENTS (additional_properties); ii++) {
- uint32_t prop = additional_properties[ii].orig_proptag;
-
- if (!e_mapi_util_find_array_propval (&object->properties, prop)) {
- if (((prop >> 16) & 0xFFFF) >= 0x8000) {
- prop = e_mapi_connection_resolve_named_prop (conn, mapi_object_get_id (eap->obj_folder), prop, cancellable, NULL);
- }
- } else {
- prop = MAPI_E_RESERVED;
- }
-
- additional_properties[ii].use_proptag = prop;
- need_any = need_any || prop != MAPI_E_RESERVED;
- }
-
- need_attachments = has_embedded_message_with_html (object);
-
- /* Fast-transfer transfers only Html or Body, never both */
- if (need_any || need_attachments) {
- const mapi_id_t *mid;
-
- mid = e_mapi_util_find_array_propval (&object->properties, PidTagMid);
- if (mid && *mid) {
- mapi_object_t obj_message;
-
- mapi_object_init (&obj_message);
-
- if (OpenMessage (eap->obj_folder, mapi_object_get_id (eap->obj_folder), *mid, &obj_message, 0) == MAPI_E_SUCCESS) {
- struct SPropTagArray *tags = NULL;
-
- for (ii = 0; ii < G_N_ELEMENTS (additional_properties); ii++) {
- uint32_t prop = additional_properties[ii].use_proptag;
-
- if (prop == MAPI_E_RESERVED)
- continue;
-
- if (!tags)
- tags = set_SPropTagArray (mem_ctx, 1, prop);
- else
- SPropTagArray_add (mem_ctx, tags, prop);
- }
-
- if (tags) {
- uint32_t jj = object->properties.cValues;
-
- e_mapi_fast_transfer_properties (conn, mem_ctx, &obj_message, tags, get_additional_properties_cb, object, cancellable, perror);
-
- while (jj < object->properties.cValues) {
- for (ii = 0; ii < G_N_ELEMENTS (additional_properties); ii++) {
- uint32_t proptag = object->properties.lpProps[jj].ulPropTag;
-
- if (additional_properties[ii].use_proptag == proptag ||
- (((proptag & 0xFFFF) == PT_STRING8 || (proptag & 0xFFFF) == PT_UNICODE) &&
- (proptag & ~0xFFFF) == (additional_properties[ii].use_proptag & ~0xFFFF))) {
- /* string8 and unicode properties are interchangeable in the union, luckily */
- object->properties.lpProps[jj].ulPropTag = additional_properties[ii].orig_proptag;
- break;
- }
- }
-
- jj++;
- }
-
- talloc_free (tags);
- }
-
- if (need_attachments)
- traverse_attachments_for_body (conn, mem_ctx, object, &obj_message, cancellable, perror);
- }
-
- mapi_object_release (&obj_message);
- }
- }
-
- eap->downloaded++;
-
- return eap->cb (conn, mem_ctx, object, obj_index, obj_total, eap->cb_user_data, cancellable, perror);
-}
-
-static enum MAPISTATUS
-fetch_object_property_as_stream (EMapiConnection *conn,
- TALLOC_CTX *mem_ctx,
- mapi_object_t *obj_message,
- uint32_t proptag,
- struct SBinary_short *bin,
- GCancellable *cancellable,
- GError **perror)
-{
- enum MAPISTATUS ms;
- mapi_object_t obj_stream;
- uint32_t buf_size, max_read;
- uint16_t off_data, cn_read;
- gboolean done = FALSE;
-
- g_return_val_if_fail (conn != NULL, MAPI_E_INVALID_PARAMETER);
- g_return_val_if_fail (mem_ctx != NULL, MAPI_E_INVALID_PARAMETER);
- g_return_val_if_fail (obj_message != NULL, MAPI_E_INVALID_PARAMETER);
- g_return_val_if_fail (bin != NULL, MAPI_E_INVALID_PARAMETER);
-
- mapi_object_init (&obj_stream);
-
- ms = OpenStream (obj_message, proptag, STREAM_ACCESS_READ, &obj_stream);
- if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "OpenStream", ms);
- goto cleanup;
- }
-
- bin->cb = 0;
-
- ms = GetStreamSize (&obj_stream, &buf_size);
- if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "GetStreamSize", ms);
- goto cleanup;
- }
-
- bin->cb = buf_size;
- bin->lpb = talloc_size (mem_ctx, bin->cb + 1);
- if (!bin->lpb || !bin->cb)
- goto cleanup;
-
- /* determine max_read first, to read by chunks as long as possible */
- off_data = 0;
- max_read = buf_size > STREAM_MAX_READ_SIZE ? STREAM_MAX_READ_SIZE : buf_size;
- do {
- ms = ReadStream (&obj_stream, (bin->lpb) + off_data, max_read, &cn_read);
- if (ms == MAPI_E_SUCCESS) {
- if (cn_read == 0) {
- done = TRUE;
- } else {
- off_data += cn_read;
- if (off_data >= buf_size)
- done = TRUE;
- }
- break;
- }
-
- if (ms == 0x2c80)
- max_read = max_read >> 1;
- else
- max_read = STREAM_MAX_READ_SIZE_DF;
-
- if (max_read < STREAM_MAX_READ_SIZE_DF)
- max_read = STREAM_MAX_READ_SIZE_DF;
- } while (ms == 0x2c80); /* an error when max_read is too large? */
-
- while (!done) {
- ms = ReadStream (&obj_stream, bin->lpb + off_data, max_read, &cn_read);
- if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "ReadStream", ms);
- done = TRUE;
- } else if (cn_read == 0) {
- done = TRUE;
- } else {
- off_data += cn_read;
- if (off_data >= buf_size)
- done = TRUE;
- }
- }
-
- cleanup:
- mapi_object_release (&obj_stream);
-
- return ms;
-}
-
-static enum MAPISTATUS
-e_mapi_connection_fetch_object_internal (EMapiConnection *conn,
- TALLOC_CTX *mem_ctx,
- mapi_object_t *obj_message,
- struct EnsureAdditionalPropertiesData *eap,
- EMapiObject **out_object,
- GCancellable *cancellable,
- GError **perror);
-
-struct FetchObjectAttachmentData
-{
- mapi_object_t *obj_message;
- struct EnsureAdditionalPropertiesData *eap;
- EMapiObject *object; /* to add attachments to */
-};
-
-static gboolean
-fetch_object_attachment_cb (EMapiConnection *conn,
- mapi_id_t fid,
- TALLOC_CTX *mem_ctx,
- struct SRow *srow,
- guint32 row_index,
- guint32 rows_total,
- gpointer user_data,
- GCancellable *cancellable,
- GError **perror)
-{
- enum MAPISTATUS ms;
- struct FetchObjectAttachmentData *foa = user_data;
- EMapiAttachment *attachment = NULL;
- mapi_object_t obj_attach;
- const uint32_t *attach_num, *attach_method;
-
- g_return_val_if_fail (conn != NULL, FALSE);
- g_return_val_if_fail (mem_ctx != NULL, FALSE);
- g_return_val_if_fail (srow != NULL, FALSE);
- g_return_val_if_fail (user_data != NULL, FALSE);
- g_return_val_if_fail (foa->obj_message != NULL, FALSE);
- g_return_val_if_fail (foa->object != NULL, FALSE);
-
- mapi_object_init (&obj_attach);
-
- attach_num = e_mapi_util_find_row_propval (srow, PidTagAttachNumber);
- if (!attach_num)
- return FALSE;
-
- ms = OpenAttach (foa->obj_message, *attach_num, &obj_attach);
- if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "OpenAttach", ms);
- goto cleanup;
- }
-
- attachment = e_mapi_attachment_new (foa->object);
-
- ms = GetPropsAll (&obj_attach, MAPI_UNICODE, &attachment->properties);
- if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "Attachment::GetPropsAll", ms);
- goto cleanup;
- }
-
- attach_method = e_mapi_util_find_row_propval (srow, PidTagAttachMethod);
- if (attach_method && *attach_method == ATTACH_BY_VALUE) {
- if (!e_mapi_util_find_array_propval (&attachment->properties, PidTagAttachDataBinary)) {
- struct SBinary_short bin;
-
- ms = fetch_object_property_as_stream (conn, mem_ctx, &obj_attach, PidTagAttachDataBinary, &bin, cancellable, perror);
- if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "Attachment::fetch PidTagAttachDataBinary", ms);
- goto cleanup;
- }
-
- attachment->properties.cValues++;
- attachment->properties.lpProps = talloc_realloc (mem_ctx,
- attachment->properties.lpProps,
- struct mapi_SPropValue,
- attachment->properties.cValues + 1);
- attachment->properties.lpProps[attachment->properties.cValues - 1].ulPropTag = PidTagAttachDataBinary;
- attachment->properties.lpProps[attachment->properties.cValues - 1].value.bin = bin;
- attachment->properties.lpProps[attachment->properties.cValues].ulPropTag = 0;
- }
- } else if (attach_method && *attach_method == ATTACH_EMBEDDED_MSG) {
- mapi_object_t obj_emb_msg;
-
- mapi_object_init (&obj_emb_msg);
-
- if (OpenEmbeddedMessage (&obj_attach, &obj_emb_msg, MAPI_READONLY) == MAPI_E_SUCCESS) {
- e_mapi_connection_fetch_object_internal (conn, mem_ctx, &obj_emb_msg, foa->eap, &attachment->embedded_object, cancellable, perror);
- }
-
- mapi_object_release (&obj_emb_msg);
- }
-
- cleanup:
- mapi_object_release (&obj_attach);
-
- if (ms == MAPI_E_SUCCESS) {
- if (!foa->object->attachments) {
- foa->object->attachments = attachment;
- } else {
- EMapiAttachment *attach = foa->object->attachments;
- while (attach->next)
- attach = attach->next;
- attach->next = attachment;
- }
- } else {
- e_mapi_attachment_free (attachment);
- }
-
- return ms == MAPI_E_SUCCESS;
-}
-
-static enum MAPISTATUS
-e_mapi_connection_fetch_object_internal (EMapiConnection *conn,
- TALLOC_CTX *mem_ctx,
- mapi_object_t *obj_message,
- struct EnsureAdditionalPropertiesData *eap,
- EMapiObject **out_object,
- GCancellable *cancellable,
- GError **perror)
-{
- enum MAPISTATUS ms;
- EMapiObject *object;
- uint16_t ui16, uj16, np_count = 0, *np_propID = NULL;
- uint32_t ui32;
- struct MAPINAMEID *np_nameid = NULL;
- const bool *has_attachments;
- struct SPropTagArray recipient_proptags;
- struct SRowSet recipient_rows;
- mapi_object_t attach_table;
-
- g_return_val_if_fail (conn != NULL, MAPI_E_INVALID_PARAMETER);
- g_return_val_if_fail (mem_ctx != NULL, MAPI_E_INVALID_PARAMETER);
- g_return_val_if_fail (obj_message != NULL, MAPI_E_INVALID_PARAMETER);
- g_return_val_if_fail (eap != NULL, MAPI_E_INVALID_PARAMETER);
- g_return_val_if_fail (out_object != NULL, MAPI_E_INVALID_PARAMETER);
-
- mapi_object_init (&attach_table);
-
- object = e_mapi_object_new (mem_ctx);
-
- ms = GetPropsAll (obj_message, MAPI_UNICODE, &object->properties);
- if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "GetPropsAll", ms);
- goto cleanup;
- }
-
- /* to transform named ids to their PidLid or PidName tags, like the fast-transfer does */
- ms = QueryNamedProperties (obj_message, 0, NULL, &np_count, &np_propID, &np_nameid);
- if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "QueryNamedProperties", ms);
- goto cleanup;
- }
-
- if (np_count && np_propID && np_nameid) {
- for (ui16 = 0; ui16 < np_count; ui16++) {
- uint32_t proptag = np_propID[ui16];
-
- for (uj16 = 0; uj16 < object->properties.cValues; uj16++) {
- if (object->properties.lpProps[uj16].ulPropTag == proptag) {
- uint32_t lid = MAPI_E_RESERVED;
- char *guid;
-
- guid = GUID_string (mem_ctx, &(np_nameid[ui16].lpguid));
-
- if (np_nameid[ui16].ulKind == MNID_ID) {
- if (e_mapi_nameid_lid_lookup_canonical (np_nameid[ui16].kind.lid, guid, &lid) != MAPI_E_SUCCESS)
- lid = MAPI_E_RESERVED;
- } else if (np_nameid[ui16].ulKind == MNID_STRING) {
- if (e_mapi_nameid_string_lookup_canonical (np_nameid[ui16].kind.lpwstr.Name, guid, &lid) != MAPI_E_SUCCESS)
- lid = MAPI_E_RESERVED;
- }
-
- talloc_free (guid);
-
- if (lid != MAPI_E_RESERVED && (lid & 0xFFFF) == (proptag & 0xFFFF)) {
- object->properties.lpProps[uj16].ulPropTag = lid;
- }
-
- break;
- }
- }
- }
- }
-
- talloc_free (np_propID);
- talloc_free (np_nameid);
-
- /* ensure certain properties */
- if (!e_mapi_util_find_array_propval (&object->properties, PidTagHtml)) {
- uint8_t best_body = 0;
-
- if (GetBestBody (obj_message, &best_body) == MAPI_E_SUCCESS && best_body == olEditorHTML) {
- struct SBinary_short bin;
-
- ms = fetch_object_property_as_stream (conn, mem_ctx, obj_message, PidTagHtml, &bin, cancellable, perror);
- if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "Object::fetch PidTagHtml", ms);
- goto cleanup;
- }
-
- object->properties.cValues++;
- object->properties.lpProps = talloc_realloc (mem_ctx,
- object->properties.lpProps,
- struct mapi_SPropValue,
- object->properties.cValues + 1);
- object->properties.lpProps[object->properties.cValues - 1].ulPropTag = PidTagHtml;
- object->properties.lpProps[object->properties.cValues - 1].value.bin = bin;
- object->properties.lpProps[object->properties.cValues].ulPropTag = 0;
- }
- }
-
- if (!e_mapi_util_find_array_propval (&object->properties, PidTagBody)) {
- struct SBinary_short bin;
-
- if (fetch_object_property_as_stream (conn, mem_ctx, obj_message, PidTagBody, &bin, cancellable, NULL) == MAPI_E_SUCCESS) {
- object->properties.cValues++;
- object->properties.lpProps = talloc_realloc (mem_ctx,
- object->properties.lpProps,
- struct mapi_SPropValue,
- object->properties.cValues + 1);
- object->properties.lpProps[object->properties.cValues - 1].ulPropTag = PidTagBody;
- if (bin.cb > 0 && bin.lpb[bin.cb - 1] == 0)
- object->properties.lpProps[object->properties.cValues - 1].value.lpszW = (const char *) talloc_steal (object, bin.lpb);
- else
- object->properties.lpProps[object->properties.cValues - 1].value.lpszW = talloc_strndup (object, (char *) bin.lpb, bin.cb);
- object->properties.lpProps[object->properties.cValues].ulPropTag = 0;
- }
- }
-
- if (!e_mapi_util_find_array_propval (&object->properties, PidNameContentClass)) {
- uint32_t prop = PidNameContentClass;
-
- prop = e_mapi_connection_resolve_named_prop (conn, mapi_object_get_id (eap->obj_folder), prop, cancellable, NULL);
- if (prop != MAPI_E_RESERVED) {
- struct SPropTagArray *tags;
- struct SPropValue *lpProps = NULL;
- uint32_t prop_count = 0;
-
- tags = set_SPropTagArray (mem_ctx, 1, prop);
-
- if (GetProps (obj_message, MAPI_PROPS_SKIP_NAMEDID_CHECK | MAPI_UNICODE, tags, &lpProps, &prop_count) == MAPI_E_SUCCESS && lpProps) {
- if (lpProps[0].ulPropTag == prop) {
- object->properties.cValues++;
- object->properties.lpProps = talloc_realloc (mem_ctx,
- object->properties.lpProps,
- struct mapi_SPropValue,
- object->properties.cValues + 1);
- object->properties.lpProps[object->properties.cValues - 1].ulPropTag = PidNameContentClass;
- object->properties.lpProps[object->properties.cValues - 1].value.lpszW = talloc_strdup (object, lpProps[0].value.lpszW);
- object->properties.lpProps[object->properties.cValues].ulPropTag = 0;
- }
- }
-
- talloc_free (tags);
- talloc_free (lpProps);
- }
- }
-
- /* fetch attachments */
- has_attachments = e_mapi_util_find_array_propval (&object->properties, PidTagHasAttachments);
- if (has_attachments && *has_attachments) {
- struct SPropTagArray *attach_columns;
- struct FetchObjectAttachmentData foa;
-
- ms = GetAttachmentTable (obj_message, &attach_table);
- if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "GetAttachmentTable", ms);
- goto cleanup;
- }
-
- attach_columns = set_SPropTagArray (mem_ctx, 1, PidTagAttachNumber);
- ms = SetColumns (&attach_table, attach_columns);
- if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "AttachTable::SetColumns", ms);
- talloc_free (attach_columns);
- goto cleanup;
- }
- talloc_free (attach_columns);
-
- foa.obj_message = obj_message;
- foa.eap = eap;
- foa.object = object;
-
- ms = foreach_tablerow (conn, mapi_object_get_id (eap->obj_folder), mem_ctx, &attach_table, fetch_object_attachment_cb, &foa, cancellable, perror);
- if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "AttachTable::foreach_tablerow", ms);
- goto cleanup;
- }
- }
-
- /* get recipients */
- ms = GetRecipientTable (obj_message, &recipient_rows, &recipient_proptags);
- if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "GetRecipientTable", ms);
- goto cleanup;
- }
-
- if (recipient_rows.cRows > 0) {
- uint32_t uj32, uk32;
- EMapiRecipient *first_recipient = NULL;
-
- for (ui32 = 0; ui32 < recipient_rows.cRows; ui32++) {
- struct SRow *row = &recipient_rows.aRow[ui32];
- EMapiRecipient *recipient;
-
- recipient = e_mapi_recipient_new (object);
- recipient->properties.cValues = row->cValues;
- recipient->properties.lpProps = talloc_zero_array (recipient, struct mapi_SPropValue, recipient->properties.cValues + 1);
-
- for (uj32 = 0, uk32 = 0; uj32 < row->cValues; uj32++, uk32++) {
- if (may_skip_property (row->lpProps[uj32].ulPropTag) ||
- !e_mapi_utils_copy_to_mapi_SPropValue (recipient, &recipient->properties.lpProps[uk32], &row->lpProps[uj32])) {
- uk32--;
- recipient->properties.cValues--;
- recipient->properties.lpProps[recipient->properties.cValues].ulPropTag = 0;
- }
- }
-
- recipient->properties.lpProps[recipient->properties.cValues].ulPropTag = 0;
- }
-
- object->recipients = first_recipient;
- }
-
- cleanup:
- mapi_object_release (&attach_table);
-
- if (ms == MAPI_E_SUCCESS) {
- *out_object = object;
- } else {
- *out_object = NULL;
- e_mapi_object_free (object);
- }
-
- return ms;
-}
-
-static enum MAPISTATUS
-e_mapi_connection_fetch_objects_internal (EMapiConnection *conn,
- TALLOC_CTX *mem_ctx,
- mapi_id_array_t *ids,
- struct EnsureAdditionalPropertiesData *eap,
- GCancellable *cancellable,
- GError **perror)
-{
- enum MAPISTATUS ms;
- guint32 idx;
- mapi_container_list_t *element;
-
- g_return_val_if_fail (conn != NULL, MAPI_E_INVALID_PARAMETER);
- g_return_val_if_fail (mem_ctx != NULL, MAPI_E_INVALID_PARAMETER);
- g_return_val_if_fail (ids != NULL, MAPI_E_INVALID_PARAMETER);
- g_return_val_if_fail (eap != NULL, MAPI_E_INVALID_PARAMETER);
- g_return_val_if_fail (eap->obj_folder != NULL, MAPI_E_INVALID_PARAMETER);
- g_return_val_if_fail (eap->downloaded < ids->count, MAPI_E_INVALID_PARAMETER);
-
- for (idx = 0, element = ids->lpContainerList; idx < ids->count && idx < eap->downloaded && element; idx++) {
- element = element->next;
- }
-
- g_return_val_if_fail (idx < ids->count, MAPI_E_INVALID_PARAMETER);
-
- ms = MAPI_E_SUCCESS;
- while (element && ms == MAPI_E_SUCCESS) {
- mapi_object_t obj_message;
- EMapiObject *object = NULL;
- GError *local_error = NULL;
-
- if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
- ms = MAPI_E_USER_CANCEL;
- break;
- }
-
- mapi_object_init (&obj_message);
-
- ms = OpenMessage (eap->obj_folder, mapi_object_get_id (eap->obj_folder), element->id, &obj_message, 0 /* read-only */);
- if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "OpenMessage", ms);
- mapi_object_release (&obj_message);
- break;
- }
-
- /* silently skip broken objects */
- ms = e_mapi_connection_fetch_object_internal (conn, mem_ctx, &obj_message, eap, &object, cancellable, &local_error);
- if (ms == MAPI_E_SUCCESS) {
- if (!eap->cb (conn, mem_ctx, object, eap->downloaded, ids->count, eap->cb_user_data, cancellable, perror)) {
- ms = MAPI_E_USER_CANCEL;
- make_mapi_error (perror, "Object processing", ms);
- }
- } else {
- e_mapi_debug_print ("%s: Skipping object %016" G_GINT64_MODIFIER "X because its fetch failed: %s",
- G_STRFUNC, element->id, local_error ? local_error->message : mapi_get_errstr (ms));
- ms = MAPI_E_SUCCESS;
- }
-
- e_mapi_object_free (object);
- mapi_object_release (&obj_message);
-
- eap->downloaded++;
-
- element = element->next;
- }
-
- return ms;
-}
-
-/* deals with named IDs transparently, thus it's OK to check with PidLid and PidName constants only */
-gboolean
-e_mapi_connection_transfer_objects (EMapiConnection *conn,
- mapi_object_t *obj_folder,
- const GSList *mids,
- TransferObjectCB cb,
- gpointer cb_user_data,
- GCancellable *cancellable,
- GError **perror)
-{
- enum MAPISTATUS ms;
- TALLOC_CTX *mem_ctx;
- mapi_id_array_t ids;
- const GSList *iter;
- struct EnsureAdditionalPropertiesData eap;
-
- CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
- e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
- e_return_val_mapi_error_if_fail (cb != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
- e_return_val_mapi_error_if_fail (obj_folder != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
-
- LOCK ();
- mem_ctx = talloc_new (priv->session);
-
- ms = mapi_id_array_init (priv->mapi_ctx, &ids);
- if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "mapi_id_array_init", ms);
- goto cleanup;
- }
-
- for (iter = mids; iter; iter = iter->next) {
- mapi_id_t *pmid = iter->data;
-
- if (pmid)
- mapi_id_array_add_id (&ids, *pmid);
- }
-
- if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
- ms = MAPI_E_USER_CANCEL;
- mapi_id_array_release (&ids);
- goto cleanup;
- }
-
- eap.cb = cb;
- eap.cb_user_data = cb_user_data;
- eap.obj_folder = obj_folder;
- eap.downloaded = 0;
-
- ms = e_mapi_fast_transfer_objects (conn, mem_ctx, obj_folder, &ids, ensure_additional_properties_cb, &eap, cancellable, perror);
- if (ms == MAPI_E_CALL_FAILED) {
- /* err, fallback to slow transfer, probably FXGetBuffer failed;
- see http://tracker.openchange.org/issues/378
- */
-
- g_clear_error (perror);
-
- e_mapi_debug_print ("%s: Failed to fast-transfer, fallback to slow fetch from %d of %d objects\n", G_STRFUNC, eap.downloaded, ids.count);
-
- ms = e_mapi_connection_fetch_objects_internal (conn, mem_ctx, &ids, &eap, cancellable, perror);
- }
-
- mapi_id_array_release (&ids);
-
- cleanup:
- talloc_free (mem_ctx);
- UNLOCK ();
-
- return ms == MAPI_E_SUCCESS;
-}
-
-gboolean
-e_mapi_connection_transfer_object (EMapiConnection *conn,
- mapi_object_t *obj_folder,
- mapi_id_t message_id,
- TransferObjectCB cb,
- gpointer cb_user_data,
- GCancellable *cancellable,
- GError **perror)
-{
- GSList *mids;
- gboolean res;
-
- mids = g_slist_append (NULL, &message_id);
- res = e_mapi_connection_transfer_objects (conn, obj_folder, mids, cb, cb_user_data, cancellable, perror);
- g_slist_free (mids);
-
- return res;
-}
-
-struct GetSummaryData {
- guint32 obj_index;
- guint32 obj_total;
- struct SPropValue *lpProps;
- uint32_t prop_count;
- TransferObjectCB cb;
- gpointer cb_user_data;
-};
-
-static gboolean
-internal_get_summary_cb (EMapiConnection *conn,
- TALLOC_CTX *mem_ctx,
- /* const */ EMapiObject *object,
- guint32 obj_index,
- guint32 obj_total,
- gpointer user_data,
- GCancellable *cancellable,
- GError **perror)
-{
- struct GetSummaryData *gsd = user_data;
-
- g_return_val_if_fail (gsd != NULL, FALSE);
- g_return_val_if_fail (gsd->cb != NULL, FALSE);
- g_return_val_if_fail (object != NULL, FALSE);
-
- /* also include properties received from GetProps,
- as those like PR_MID are not included by default */
- if (gsd->lpProps && gsd->prop_count > 0) {
- uint32_t ii;
-
- for (ii = 0; ii < gsd->prop_count; ii++) {
- /* skip errors and already included properties */
- if ((gsd->lpProps[ii].ulPropTag & 0xFFFF) == PT_ERROR
- || e_mapi_util_find_array_propval (&object->properties, gsd->lpProps[ii].ulPropTag))
- continue;
-
- object->properties.cValues++;
- object->properties.lpProps = talloc_realloc (mem_ctx,
- object->properties.lpProps,
- struct mapi_SPropValue,
- object->properties.cValues + 1);
- cast_mapi_SPropValue (mem_ctx, &object->properties.lpProps[object->properties.cValues - 1], &gsd->lpProps[ii]);
- object->properties.lpProps[object->properties.cValues].ulPropTag = 0;
- }
- }
-
- return gsd->cb (conn, mem_ctx, object, gsd->obj_index, gsd->obj_total, gsd->cb_user_data, cancellable, perror);
-}
-
-/* transfers items summary, which is either PR_TRANSPORT_MESSAGE_HEADERS_UNICODE or
- the object without attachment */
-gboolean
-e_mapi_connection_transfer_summary (EMapiConnection *conn,
- mapi_object_t *obj_folder,
- const GSList *mids,
- TransferObjectCB cb,
- gpointer cb_user_data,
- GCancellable *cancellable,
- GError **perror)
-{
- enum MAPISTATUS ms;
- TALLOC_CTX *mem_ctx;
- const GSList *iter;
- guint32 index, total;
-
- CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
- e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
- e_return_val_mapi_error_if_fail (cb != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
- e_return_val_mapi_error_if_fail (obj_folder != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
-
- LOCK ();
- mem_ctx = talloc_new (priv->session);
-
- ms = MAPI_E_SUCCESS;
- total = g_slist_length ((GSList *) mids);
- for (iter = mids, index = 0; iter && ms == MAPI_E_SUCCESS; iter = iter->next, index++) {
- mapi_id_t *pmid = iter->data;
-
- if (pmid) {
- mapi_object_t obj_message;
- struct SPropTagArray *tags;
- struct SPropValue *lpProps = NULL;
- uint32_t prop_count = 0, ii;
-
- mapi_object_init (&obj_message);
-
- ms = OpenMessage (obj_folder, mapi_object_get_id (obj_folder), *pmid, &obj_message, 0);
- if (ms != MAPI_E_SUCCESS && ms != MAPI_E_NOT_FOUND) {
- make_mapi_error (perror, "OpenMessage", ms);
- goto cleanup;
- }
-
- tags = set_SPropTagArray (mem_ctx, 6,
- PR_FID,
- PR_MID,
- PR_MESSAGE_FLAGS,
- PR_LAST_MODIFICATION_TIME,
- PR_MESSAGE_CLASS,
- PR_TRANSPORT_MESSAGE_HEADERS_UNICODE);
-
- ms = GetProps (&obj_message, MAPI_PROPS_SKIP_NAMEDID_CHECK | MAPI_UNICODE, tags, &lpProps, &prop_count);
- if (ms == MAPI_E_SUCCESS) {
- ms = MAPI_E_NOT_FOUND;
- if (lpProps && prop_count > 0) {
- const gchar *headers = e_mapi_util_find_SPropVal_array_propval (lpProps, PR_TRANSPORT_MESSAGE_HEADERS_UNICODE);
-
- if (headers && *headers) {
- EMapiObject *object;
-
- ms = MAPI_E_SUCCESS;
-
- object = e_mapi_object_new (mem_ctx);
- for (ii = 0; ii < prop_count; ii++) {
- object->properties.cValues++;
- object->properties.lpProps = talloc_realloc (mem_ctx,
- object->properties.lpProps,
- struct mapi_SPropValue,
- object->properties.cValues + 1);
- cast_mapi_SPropValue (mem_ctx, &object->properties.lpProps[object->properties.cValues - 1], &lpProps[ii]);
- object->properties.lpProps[object->properties.cValues].ulPropTag = 0;
- }
-
- if (!cb (conn, mem_ctx, object, index, total, cb_user_data, cancellable, perror)) {
- ms = MAPI_E_USER_CANCEL;
- e_mapi_object_free (object);
- mapi_object_release (&obj_message);
- goto cleanup;
- }
-
- e_mapi_object_free (object);
- }
- }
- }
-
- if (ms == MAPI_E_NOT_FOUND) {
- struct GetSummaryData gsd;
-
- gsd.obj_index = index;
- gsd.obj_total = total;
- gsd.lpProps = lpProps;
- gsd.prop_count = prop_count;
- gsd.cb = cb;
- gsd.cb_user_data = cb_user_data;
-
- ms = e_mapi_fast_transfer_object (conn, mem_ctx, &obj_message, E_MAPI_FAST_TRANSFER_FLAG_RECIPIENTS, internal_get_summary_cb, &gsd, cancellable, perror);
- if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "transfer_object", ms);
- mapi_object_release (&obj_message);
- goto cleanup;
- }
- }
-
- mapi_object_release (&obj_message);
- talloc_free (tags);
- }
-
- if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
- ms = MAPI_E_USER_CANCEL;
- goto cleanup;
- }
- }
-
- cleanup:
- talloc_free (mem_ctx);
- UNLOCK ();
-
- return ms == MAPI_E_SUCCESS;
-}
-
-typedef struct {
- uint32_t proptag;
- uint32_t cb;
- const uint8_t *lpb; /* taken from the original mapi prop, no need to copy the memory */
-} EMapiStreamedProp;
-
-static gboolean
-convert_mapi_props_to_props (EMapiConnection *conn,
- mapi_object_t *obj_folder,
- const struct mapi_SPropValue_array *mapi_props,
- struct SPropValue **props,
- uint32_t *propslen,
- EMapiStreamedProp **streams, /* can be NULL for no streaming */
- guint *streamslen, /* can be NULL only if streams is NULL; is ignored if streams is NULL */
- TALLOC_CTX *mem_ctx,
- GCancellable *cancellable,
- GError **perror)
-{
- uint16_t ii;
- ResolveNamedIDsData *named_ids_list = NULL;
- guint named_ids_len = 0;
- gboolean res = TRUE;
-
- e_return_val_mapi_error_if_fail (conn != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
- e_return_val_mapi_error_if_fail (mapi_props != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
- e_return_val_mapi_error_if_fail (props != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
- e_return_val_mapi_error_if_fail (propslen != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
- e_return_val_mapi_error_if_fail (mem_ctx != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
- if (streams) {
- e_return_val_mapi_error_if_fail (streamslen != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
- }
-
- for (ii = 0; ii < mapi_props->cValues; ii++) {
- gboolean processed = FALSE;
- uint32_t proptag = mapi_props->lpProps[ii].ulPropTag;
- gconstpointer propdata = get_mapi_SPropValue_data (&mapi_props->lpProps[ii]);
-
- maybe_add_named_id_tag (proptag, &named_ids_list, &named_ids_len);
-
- if (streams && propdata) {
- /* copy anything longer than 1KB as streams; this doesn't count total packet size needed,
- but because this is usually useful only for PidTagBody, PidTagHtml, which are there
- only once, then no big deal
- */
-
- uint32_t sz;
- const gchar *str;
- const struct SBinary_short *bin;
-
- #define addstream() { \
- if (!*streams) { \
- *streams = g_new0 (EMapiStreamedProp, 1); \
- *streamslen = 0; \
- } else { \
- *streams = g_renew (EMapiStreamedProp, *streams, *streamslen + 1); \
- } \
- \
- (*streams)[*streamslen].proptag = proptag; \
- (*streams)[*streamslen].cb = 0; \
- (*streams)[*streamslen].lpb = NULL; \
- (*streamslen) += 1; \
- }
-
- switch (proptag & 0xFFFF) {
- case PT_BINARY:
- bin = propdata;
- if (bin->cb > MAX_PROPERTY_WRITE_SIZE) {
- addstream ();
- (*streams)[(*streamslen) - 1].cb = bin->cb;
- (*streams)[(*streamslen) - 1].lpb = bin->lpb;
- processed = TRUE;
- }
- break;
- case PT_STRING8:
- str = propdata;
- sz = get_mapi_property_size (&mapi_props->lpProps[ii]);
- if (sz > MAX_PROPERTY_WRITE_SIZE) {
- addstream ();
- (*streams)[(*streamslen) - 1].cb = sz;
- (*streams)[(*streamslen) - 1].lpb = (uint8_t *) str;
- processed = TRUE;
- }
- break;
- case PT_UNICODE:
- str = propdata;
- sz = get_mapi_property_size (&mapi_props->lpProps[ii]);
- if (sz > MAX_PROPERTY_WRITE_SIZE) {
- gchar *in_unicode;
- gsize written = 0;
-
- addstream ();
-
- in_unicode = g_convert (str, strlen (str), "UTF-16", "UTF-8", NULL, &written, NULL);
- if (in_unicode && written > 0) {
- uint8_t *bytes = talloc_zero_size (mem_ctx, written + 2);
-
- /* skip Unicode marker, if there */
- if (written >= 2 && (const guchar) in_unicode[0] == 0xFF && (const guchar) in_unicode[1] == 0xFE) {
- memcpy (bytes, in_unicode + 2, written - 2);
- written -= 2;
- } else
- memcpy (bytes, in_unicode, written);
-
- /* null-terminated unicode string */
- (*streams)[(*streamslen) - 1].lpb = bytes;
- (*streams)[(*streamslen) - 1].cb = written + 2;
- }
- g_free (in_unicode);
- processed = TRUE;
- }
- break;
- }
-
- #undef addstream
- }
-
- if (!processed)
- e_mapi_utils_add_spropvalue (mem_ctx, props, propslen, proptag, propdata);
- }
-
- if (named_ids_list) {
- res = e_mapi_connection_resolve_named_props (conn, mapi_object_get_id (obj_folder), named_ids_list, named_ids_len, cancellable, perror);
-
- if (res && *props) {
- for (ii = 0; ii < *propslen; ii++) {
- uint32_t proptag = (*props)[ii].ulPropTag;
-
- maybe_replace_named_id_tag (&proptag, named_ids_list, named_ids_len);
-
- (*props)[ii].ulPropTag = proptag;
- }
- }
-
- if (res && streams) {
- for (ii = 0; ii < *streamslen; ii++) {
- maybe_replace_named_id_tag (&((*streams)[ii].proptag), named_ids_list, named_ids_len);
- }
- }
- }
-
- g_free (named_ids_list);
-
- return res;
-}
-
-static gboolean
-write_streamed_prop (EMapiConnection *conn,
- mapi_object_t *obj_object,
- const EMapiStreamedProp *stream,
- GCancellable *cancellable,
- GError **perror)
-{
- enum MAPISTATUS ms;
- uint32_t total_written;
- gboolean done = FALSE;
- mapi_object_t obj_stream;
-
- CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
- e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
- e_return_val_mapi_error_if_fail (obj_object != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
- e_return_val_mapi_error_if_fail (stream != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
-
- LOCK ();
-
- mapi_object_init (&obj_stream);
-
- if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
- ms = MAPI_E_USER_CANCEL;
- goto cleanup;
- }
-
- /* OpenStream on required proptag */
- ms = OpenStream (obj_object, stream->proptag, STREAM_ACCESS_READWRITE, &obj_stream);
- if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "OpenStream", ms);
- goto cleanup;
- }
+ if (ms == 0x2c80)
+ max_read = max_read >> 1;
+ else
+ max_read = STREAM_MAX_READ_SIZE_DF;
- /* Set the stream size */
- ms = SetStreamSize (&obj_stream, stream->cb);
- if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "SetStreamSize", ms);
- goto cleanup;
- }
+ if (max_read < STREAM_MAX_READ_SIZE_DF)
+ max_read = STREAM_MAX_READ_SIZE_DF;
+ } while (ms == 0x2c80); /* an error when max_read is too large? */
- total_written = 0;
- /* Write stream */
while (!done) {
- uint16_t cn_written = 0;
- DATA_BLOB blob;
-
- if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
- ms = MAPI_E_USER_CANCEL;
- goto cleanup;
- }
-
- blob.length = (stream->cb - total_written) < STREAM_MAX_WRITE_SIZE ?
- (stream->cb - total_written) : STREAM_MAX_WRITE_SIZE;
- blob.data = (uint8_t *) (stream->lpb + total_written);
-
- ms = WriteStream (&obj_stream, &blob, &cn_written);
+ ms = ReadStream (&obj_stream, bin->lpb + off_data, max_read, &cn_read);
if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "WriteStream", ms);
+ make_mapi_error (perror, "ReadStream", ms);
done = TRUE;
- } else if (cn_written == 0) {
+ } else if (cn_read == 0) {
done = TRUE;
} else {
- total_written += cn_written;
- if (total_written >= stream->cb)
+ off_data += cn_read;
+ if (off_data >= buf_size)
done = TRUE;
}
}
- if (ms == MAPI_E_SUCCESS) {
- /* Commit the stream */
- ms = CommitStream (&obj_stream);
- if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "CommitStream", ms);
- goto cleanup;
- }
- }
-
cleanup:
mapi_object_release (&obj_stream);
- UNLOCK ();
-
- return ms == MAPI_E_SUCCESS;
+ return ms;
}
+static enum MAPISTATUS
+e_mapi_connection_fetch_object_internal (EMapiConnection *conn,
+ TALLOC_CTX *mem_ctx,
+ mapi_object_t *obj_message,
+ struct EnsureAdditionalPropertiesData *eap,
+ EMapiObject **out_object,
+ GCancellable *cancellable,
+ GError **perror);
+
+struct FetchObjectAttachmentData
+{
+ mapi_object_t *obj_message;
+ struct EnsureAdditionalPropertiesData *eap;
+ EMapiObject *object; /* to add attachments to */
+};
+
static gboolean
-update_props_on_object (EMapiConnection *conn,
- mapi_object_t *obj_folder,
- mapi_object_t *obj_object,
- const struct mapi_SPropValue_array *properties,
- TALLOC_CTX *mem_ctx,
- GCancellable *cancellable,
- GError **perror)
+fetch_object_attachment_cb (EMapiConnection *conn,
+ TALLOC_CTX *mem_ctx,
+ struct SRow *srow,
+ guint32 row_index,
+ guint32 rows_total,
+ gpointer user_data,
+ GCancellable *cancellable,
+ GError **perror)
{
- enum MAPISTATUS ms;
- struct SPropValue *props = NULL;
- uint32_t propslen = 0;
- EMapiStreamedProp *streams = NULL;
- guint streamslen = 0;
+ enum MAPISTATUS ms;
+ struct FetchObjectAttachmentData *foa = user_data;
+ EMapiAttachment *attachment = NULL;
+ mapi_object_t obj_attach;
+ const uint32_t *attach_num, *attach_method;
- CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
- e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+ g_return_val_if_fail (conn != NULL, FALSE);
+ g_return_val_if_fail (mem_ctx != NULL, FALSE);
+ g_return_val_if_fail (srow != NULL, FALSE);
+ g_return_val_if_fail (user_data != NULL, FALSE);
+ g_return_val_if_fail (foa->obj_message != NULL, FALSE);
+ g_return_val_if_fail (foa->object != NULL, FALSE);
- LOCK ();
+ mapi_object_init (&obj_attach);
- if (!convert_mapi_props_to_props (conn, obj_folder, properties, &props, &propslen, &streams, &streamslen, mem_ctx, cancellable, perror)) {
- ms = MAPI_E_CALL_FAILED;
- make_mapi_error (perror, "convert_mapi_props_to_props", ms);
- goto cleanup;
- }
+ attach_num = e_mapi_util_find_row_propval (srow, PidTagAttachNumber);
+ if (!attach_num)
+ return FALSE;
- if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
- ms = MAPI_E_USER_CANCEL;
+ ms = OpenAttach (foa->obj_message, *attach_num, &obj_attach);
+ if (ms != MAPI_E_SUCCESS) {
+ make_mapi_error (perror, "OpenAttach", ms);
goto cleanup;
}
- if (props) {
- /* set properties for the item */
- ms = SetProps (obj_object, MAPI_PROPS_SKIP_NAMEDID_CHECK, props, propslen);
-
- talloc_free (props);
-
- if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "SetProps", ms);
- goto cleanup;
- }
- }
+ attachment = e_mapi_attachment_new (foa->object);
- if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
- ms = MAPI_E_USER_CANCEL;
+ ms = GetPropsAll (&obj_attach, MAPI_UNICODE, &attachment->properties);
+ if (ms != MAPI_E_SUCCESS) {
+ make_mapi_error (perror, "Attachment::GetPropsAll", ms);
goto cleanup;
}
- if (streams) {
- guint ii;
+ attach_method = e_mapi_util_find_row_propval (srow, PidTagAttachMethod);
+ if (attach_method && *attach_method == ATTACH_BY_VALUE) {
+ if (!e_mapi_util_find_array_propval (&attachment->properties, PidTagAttachDataBinary)) {
+ struct SBinary_short bin;
- for (ii = 0; ii < streamslen; ii++) {
- if (!write_streamed_prop (conn, obj_object, &streams[ii], cancellable, perror)) {
- ms = MAPI_E_CALL_FAILED;
- make_mapi_error (perror, "write_streamed_prop", ms);
- break;
+ ms = fetch_object_property_as_stream (conn, mem_ctx, &obj_attach, PidTagAttachDataBinary, &bin, cancellable, perror);
+ if (ms != MAPI_E_SUCCESS) {
+ make_mapi_error (perror, "Attachment::fetch PidTagAttachDataBinary", ms);
+ goto cleanup;
}
- if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
- ms = MAPI_E_USER_CANCEL;
- break;
- }
+ attachment->properties.cValues++;
+ attachment->properties.lpProps = talloc_realloc (mem_ctx,
+ attachment->properties.lpProps,
+ struct mapi_SPropValue,
+ attachment->properties.cValues + 1);
+ attachment->properties.lpProps[attachment->properties.cValues - 1].ulPropTag = PidTagAttachDataBinary;
+ attachment->properties.lpProps[attachment->properties.cValues - 1].value.bin = bin;
+ attachment->properties.lpProps[attachment->properties.cValues].ulPropTag = 0;
}
+ } else if (attach_method && *attach_method == ATTACH_EMBEDDED_MSG) {
+ mapi_object_t obj_emb_msg;
- g_free (streams);
- }
- cleanup:
- UNLOCK ();
-
- return ms == MAPI_E_SUCCESS;
-}
-
-static gboolean
-update_recipient_properties (EMapiConnection *conn,
- mapi_object_t *obj_folder,
- struct SRow *aRow,
- EMapiRecipient *recipient,
- gboolean is_resolved,
- TALLOC_CTX *mem_ctx,
- GCancellable *cancellable,
- GError **perror)
-{
- struct SPropValue *props = NULL;
- uint32_t propslen = 0, ii;
-
- g_return_val_if_fail (recipient != NULL, FALSE);
+ mapi_object_init (&obj_emb_msg);
- if (!convert_mapi_props_to_props (conn, obj_folder, &recipient->properties, &props, &propslen, NULL, NULL, mem_ctx, cancellable, perror))
- return FALSE;
+ if (OpenEmbeddedMessage (&obj_attach, &obj_emb_msg, MAPI_READONLY) == MAPI_E_SUCCESS) {
+ e_mapi_connection_fetch_object_internal (conn, mem_ctx, &obj_emb_msg, foa->eap, &attachment->embedded_object, cancellable, perror);
+ }
- for (ii = 0; ii < propslen; ii++) {
- /* do not overwrite all properties, if recipient was resolved properly */
- if (!is_resolved
- || props[ii].ulPropTag == PidTagRecipientType
- || props[ii].ulPropTag == PidTagSendInternetEncoding
- || props[ii].ulPropTag == PidTagRecipientFlags
- || props[ii].ulPropTag == PidTagRecipientTrackStatus)
- SRow_addprop (aRow, props[ii]);
+ mapi_object_release (&obj_emb_msg);
}
- return TRUE;
-}
-
-static gboolean
-delete_object_recipients (EMapiConnection *conn,
- mapi_object_t *obj_folder,
- mapi_object_t *obj_object,
- TALLOC_CTX *mem_ctx,
- GCancellable *cancellable,
- GError **perror)
-{
- enum MAPISTATUS ms;
-
- CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
- e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
-
- LOCK ();
-
- ms = RemoveAllRecipients (obj_object);
- if (ms != MAPI_E_SUCCESS)
- make_mapi_error (perror, "RemoveAllRecipients", ms);
+ cleanup:
+ mapi_object_release (&obj_attach);
- UNLOCK ();
+ if (ms == MAPI_E_SUCCESS) {
+ if (!foa->object->attachments) {
+ foa->object->attachments = attachment;
+ } else {
+ EMapiAttachment *attach = foa->object->attachments;
+ while (attach->next)
+ attach = attach->next;
+ attach->next = attachment;
+ }
+ } else {
+ e_mapi_attachment_free (attachment);
+ }
return ms == MAPI_E_SUCCESS;
}
-static gboolean
-add_object_recipients (EMapiConnection *conn,
- mapi_object_t *obj_folder,
- mapi_object_t *obj_message,
- EMapiRecipient *recipients,
- TALLOC_CTX *mem_ctx,
- GCancellable *cancellable,
- GError **perror)
+static enum MAPISTATUS
+e_mapi_connection_fetch_object_internal (EMapiConnection *conn,
+ TALLOC_CTX *mem_ctx,
+ mapi_object_t *obj_message,
+ struct EnsureAdditionalPropertiesData *eap,
+ EMapiObject **out_object,
+ GCancellable *cancellable,
+ GError **perror)
{
- const uint32_t required_tags[] = {PidTagEntryId,
- PidTagDisplayName,
- PidTagObjectType,
- PidTagDisplayType,
- PidTagTransmittableDisplayName,
- PidTagEmailAddress,
- PidTagAddressType,
- PidTagSendRichInfo,
- PidTag7BitDisplayName};
- enum MAPISTATUS ms;
- struct SPropTagArray *tags;
- struct SRowSet *rows = NULL;
- struct PropertyTagArray_r *flagList = NULL;
- ResolveNamedIDsData *named_ids_list = NULL;
- guint named_ids_len = 0;
- const gchar **users = NULL;
- EMapiRecipient *recipient;
- EMapiRecipient **recips;
- uint32_t ii, jj, count = 0;
- GHashTable *all_proptags;
- GHashTableIter iter;
- gpointer key, value;
-
- CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
- e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
-
- count = 0;
- for (recipient = recipients, ii = 0; recipient; recipient = recipient->next, ii++) {
- if (!e_mapi_util_find_array_propval (&recipient->properties, PidTagPrimarySmtpAddress)
- && !e_mapi_util_find_array_propval (&recipient->properties, PidTagDisplayName))
- g_debug ("%s: Cannot get email or display name for a recipient %d, skipping it", G_STRFUNC, ii);
- else
- count++;
- }
+ enum MAPISTATUS ms;
+ EMapiObject *object;
+ uint16_t ui16, uj16, np_count = 0, *np_propID = NULL;
+ uint32_t ui32;
+ struct MAPINAMEID *np_nameid = NULL;
+ const bool *has_attachments;
+ struct SPropTagArray recipient_proptags;
+ struct SRowSet recipient_rows;
+ mapi_object_t attach_table;
- if (!count)
- return TRUE;
+ g_return_val_if_fail (conn != NULL, MAPI_E_INVALID_PARAMETER);
+ g_return_val_if_fail (mem_ctx != NULL, MAPI_E_INVALID_PARAMETER);
+ g_return_val_if_fail (obj_message != NULL, MAPI_E_INVALID_PARAMETER);
+ g_return_val_if_fail (eap != NULL, MAPI_E_INVALID_PARAMETER);
+ g_return_val_if_fail (out_object != NULL, MAPI_E_INVALID_PARAMETER);
- LOCK ();
+ mapi_object_init (&attach_table);
- all_proptags = g_hash_table_new (g_direct_hash, g_direct_equal);
- users = g_new0 (const gchar *, count + 1);
- recips = g_new0 (EMapiRecipient *, count + 1);
+ object = e_mapi_object_new (mem_ctx);
- for (ii = 0; ii < G_N_ELEMENTS (required_tags); ii++) {
- g_hash_table_insert (all_proptags, GUINT_TO_POINTER (required_tags[ii]), GUINT_TO_POINTER (1));
+ ms = GetPropsAll (obj_message, MAPI_UNICODE, &object->properties);
+ if (ms != MAPI_E_SUCCESS) {
+ make_mapi_error (perror, "GetPropsAll", ms);
+ goto cleanup;
}
- for (ii = 0, jj = 0, recipient = recipients; ii < count && recipient != NULL; ii++, recipient = recipient->next) {
- users[ii] = e_mapi_util_find_array_propval (&recipient->properties, PidTagPrimarySmtpAddress);
- if (!users[ii])
- users[ii] = e_mapi_util_find_array_propval (&recipient->properties, PidTagDisplayName);
- if (!users[ii]) {
- ii--;
- } else {
- uint32_t kk;
-
- recips[jj] = recipient;
- jj++;
-
- for (kk = 0; kk < recipient->properties.cValues; kk++) {
- g_hash_table_insert (all_proptags, GUINT_TO_POINTER (recipient->properties.lpProps[kk].ulPropTag), GUINT_TO_POINTER (1));
- }
- }
+ /* to transform named ids to their PidLid or PidName tags, like the fast-transfer does */
+ ms = QueryNamedProperties (obj_message, 0, NULL, &np_count, &np_propID, &np_nameid);
+ if (ms != MAPI_E_SUCCESS) {
+ make_mapi_error (perror, "QueryNamedProperties", ms);
+ goto cleanup;
}
- /* Attempt to resolve names from the server */
- tags = NULL;
- g_hash_table_iter_init (&iter, all_proptags);
- while (g_hash_table_iter_next (&iter, &key, &value)) {
- uint32_t proptag = GPOINTER_TO_UINT (key);
+ if (np_count && np_propID && np_nameid) {
+ for (ui16 = 0; ui16 < np_count; ui16++) {
+ uint32_t proptag = np_propID[ui16];
- maybe_add_named_id_tag (proptag, &named_ids_list, &named_ids_len);
+ for (uj16 = 0; uj16 < object->properties.cValues; uj16++) {
+ if (object->properties.lpProps[uj16].ulPropTag == proptag) {
+ uint32_t lid = MAPI_E_RESERVED;
+ char *guid;
- if (!tags)
- tags = set_SPropTagArray (mem_ctx, 1, proptag);
- else
- SPropTagArray_add (mem_ctx, tags, proptag);
- }
+ guid = GUID_string (mem_ctx, &(np_nameid[ui16].lpguid));
- if (named_ids_list) {
- if (!e_mapi_connection_resolve_named_props (conn, mapi_object_get_id (obj_folder), named_ids_list, named_ids_len, cancellable, perror)) {
- ms = MAPI_E_CALL_FAILED;
- make_mapi_error (perror, "e_mapi_connection_resolve_named_props", ms);
- goto cleanup;
- }
+ if (np_nameid[ui16].ulKind == MNID_ID) {
+ if (e_mapi_nameid_lid_lookup_canonical (np_nameid[ui16].kind.lid, guid, &lid) != MAPI_E_SUCCESS)
+ lid = MAPI_E_RESERVED;
+ } else if (np_nameid[ui16].ulKind == MNID_STRING) {
+ if (e_mapi_nameid_string_lookup_canonical (np_nameid[ui16].kind.lpwstr.Name, guid, &lid) != MAPI_E_SUCCESS)
+ lid = MAPI_E_RESERVED;
+ }
- for (ii = 0; ii < tags->cValues; ii++) {
- uint32_t proptag = tags->aulPropTag[ii];
+ talloc_free (guid);
- maybe_replace_named_id_tag (&proptag, named_ids_list, named_ids_len);
+ if (lid != MAPI_E_RESERVED && (lid & 0xFFFF) == (proptag & 0xFFFF)) {
+ object->properties.lpProps[uj16].ulPropTag = lid;
+ }
- tags->aulPropTag[ii] = proptag;
+ break;
+ }
+ }
}
}
- ms = ResolveNames (priv->session, users, tags, &rows, &flagList, MAPI_UNICODE);
- if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "ResolveNames", ms);
- goto cleanup;
- }
-
- g_assert (count == flagList->cValues);
-
- if (!rows) /* This happens when there are ZERO RESOLVED recipients */
- rows = talloc_zero (mem_ctx, struct SRowSet);
+ talloc_free (np_propID);
+ talloc_free (np_nameid);
- for (ii = 0, jj = 0; ii < count; ii++) {
- recipient = recips[ii];
+ /* ensure certain properties */
+ if (!e_mapi_util_find_array_propval (&object->properties, PidTagHtml)) {
+ uint8_t best_body = 0;
- if (flagList->aulPropTag[ii] == MAPI_AMBIGUOUS) {
- /* We should never get an ambiguous resolution as we use the email-id for resolving.
- * However, if we do still get an ambiguous entry, we can't handle it :-( */
- ms = MAPI_E_AMBIGUOUS_RECIP;
- /* Translators: %s is replaced with an email address which was found ambiguous on a remote server */
- g_set_error (perror, E_MAPI_ERROR, ms, _("Recipient '%s' is ambiguous"), users[ii]);
- goto cleanup;
- } else if (flagList->aulPropTag[ii] == MAPI_UNRESOLVED) {
- uint32_t last;
+ if (GetBestBody (obj_message, &best_body) == MAPI_E_SUCCESS && best_body == olEditorHTML) {
+ struct SBinary_short bin;
- /* If the recipient is unresolved, consider it is a SMTP one */
- rows->aRow = talloc_realloc (mem_ctx, rows->aRow, struct SRow, rows->cRows + 1);
- last = rows->cRows;
- rows->aRow[last].cValues = 0;
- rows->aRow[last].lpProps = talloc_zero (mem_ctx, struct SPropValue);
- if (!update_recipient_properties (conn, obj_folder, &rows->aRow[last], recipient, FALSE, mem_ctx, cancellable, perror)) {
- ms = MAPI_E_CALL_FAILED;
- goto cleanup;
- }
- rows->cRows += 1;
- } else if (flagList->aulPropTag[ii] == MAPI_RESOLVED) {
- if (!update_recipient_properties (conn, obj_folder, &rows->aRow[jj], recipient, TRUE, mem_ctx, cancellable, perror)) {
- ms = MAPI_E_CALL_FAILED;
+ ms = fetch_object_property_as_stream (conn, mem_ctx, obj_message, PidTagHtml, &bin, cancellable, perror);
+ if (ms != MAPI_E_SUCCESS) {
+ make_mapi_error (perror, "Object::fetch PidTagHtml", ms);
goto cleanup;
}
- jj += 1;
- }
- }
- /* Modify the recipient table */
- ms = ModifyRecipients (obj_message, rows);
- if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "ModifyRecipients", ms);
- goto cleanup;
+ object->properties.cValues++;
+ object->properties.lpProps = talloc_realloc (mem_ctx,
+ object->properties.lpProps,
+ struct mapi_SPropValue,
+ object->properties.cValues + 1);
+ object->properties.lpProps[object->properties.cValues - 1].ulPropTag = PidTagHtml;
+ object->properties.lpProps[object->properties.cValues - 1].value.bin = bin;
+ object->properties.lpProps[object->properties.cValues].ulPropTag = 0;
+ }
}
- cleanup:
- UNLOCK ();
+ if (!e_mapi_util_find_array_propval (&object->properties, PidTagBody)) {
+ struct SBinary_short bin;
- g_free (users);
- g_free (recips);
- g_free (named_ids_list);
- g_hash_table_destroy (all_proptags);
+ if (fetch_object_property_as_stream (conn, mem_ctx, obj_message, PidTagBody, &bin, cancellable, NULL) == MAPI_E_SUCCESS) {
+ object->properties.cValues++;
+ object->properties.lpProps = talloc_realloc (mem_ctx,
+ object->properties.lpProps,
+ struct mapi_SPropValue,
+ object->properties.cValues + 1);
+ object->properties.lpProps[object->properties.cValues - 1].ulPropTag = PidTagBody;
+ if (bin.cb > 0 && bin.lpb[bin.cb - 1] == 0)
+ object->properties.lpProps[object->properties.cValues - 1].value.lpszW = (const char *) talloc_steal (object, bin.lpb);
+ else
+ object->properties.lpProps[object->properties.cValues - 1].value.lpszW = talloc_strndup (object, (char *) bin.lpb, bin.cb);
+ object->properties.lpProps[object->properties.cValues].ulPropTag = 0;
+ }
+ }
- return ms == MAPI_E_SUCCESS;
-}
+ if (!e_mapi_util_find_array_propval (&object->properties, PidNameContentClass)) {
+ uint32_t prop = PidNameContentClass;
-static gboolean
-delete_attachment_cb (EMapiConnection *conn,
- mapi_id_t fid,
- TALLOC_CTX *mem_ctx,
- struct SRow *srow,
- guint32 row_index,
- guint32 rows_total,
- gpointer user_data,
- GCancellable *cancellable,
- GError **perror)
-{
- const uint32_t *attach_num;
- mapi_object_t *obj_object = user_data;
- enum MAPISTATUS ms;
+ prop = e_mapi_connection_resolve_named_prop (conn, mapi_object_get_id (eap->obj_folder), prop, cancellable, NULL);
+ if (prop != MAPI_E_RESERVED) {
+ struct SPropTagArray *tags;
+ struct SPropValue *lpProps = NULL;
+ uint32_t prop_count = 0;
- g_return_val_if_fail (obj_object != NULL, FALSE);
+ tags = set_SPropTagArray (mem_ctx, 1, prop);
- attach_num = e_mapi_util_find_row_propval (srow, PidTagAttachNumber);
- g_return_val_if_fail (attach_num != NULL, FALSE);
+ if (GetProps (obj_message, MAPI_PROPS_SKIP_NAMEDID_CHECK | MAPI_UNICODE, tags, &lpProps, &prop_count) == MAPI_E_SUCCESS && lpProps) {
+ if (lpProps[0].ulPropTag == prop) {
+ object->properties.cValues++;
+ object->properties.lpProps = talloc_realloc (mem_ctx,
+ object->properties.lpProps,
+ struct mapi_SPropValue,
+ object->properties.cValues + 1);
+ object->properties.lpProps[object->properties.cValues - 1].ulPropTag = PidNameContentClass;
+ object->properties.lpProps[object->properties.cValues - 1].value.lpszW = talloc_strdup (object, lpProps[0].value.lpszW);
+ object->properties.lpProps[object->properties.cValues].ulPropTag = 0;
+ }
+ }
- ms = DeleteAttach (obj_object, *attach_num);
- if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "DeleteAttach", ms);
+ talloc_free (tags);
+ talloc_free (lpProps);
+ }
}
- return ms == MAPI_E_SUCCESS;
-}
+ /* fetch attachments */
+ has_attachments = e_mapi_util_find_array_propval (&object->properties, PidTagHasAttachments);
+ if (has_attachments && *has_attachments) {
+ struct SPropTagArray *attach_columns;
+ struct FetchObjectAttachmentData foa;
-static gboolean
-delete_object_attachments (EMapiConnection *conn,
- mapi_object_t *obj_folder,
- mapi_object_t *obj_object,
- TALLOC_CTX *mem_ctx,
- GCancellable *cancellable,
- GError **perror)
-{
- enum MAPISTATUS ms;
- mapi_object_t obj_table;
- struct SPropTagArray *proptags;
+ ms = GetAttachmentTable (obj_message, &attach_table);
+ if (ms != MAPI_E_SUCCESS) {
+ make_mapi_error (perror, "GetAttachmentTable", ms);
+ goto cleanup;
+ }
- CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
+ attach_columns = set_SPropTagArray (mem_ctx, 1, PidTagAttachNumber);
+ ms = SetColumns (&attach_table, attach_columns);
+ if (ms != MAPI_E_SUCCESS) {
+ make_mapi_error (perror, "AttachTable::SetColumns", ms);
+ talloc_free (attach_columns);
+ goto cleanup;
+ }
+ talloc_free (attach_columns);
- LOCK ();
+ foa.obj_message = obj_message;
+ foa.eap = eap;
+ foa.object = object;
- mapi_object_init (&obj_table);
+ ms = foreach_tablerow (conn, mem_ctx, &attach_table, fetch_object_attachment_cb, &foa, cancellable, perror);
+ if (ms != MAPI_E_SUCCESS) {
+ make_mapi_error (perror, "AttachTable::foreach_tablerow", ms);
+ goto cleanup;
+ }
+ }
- /* open attachment table */
- ms = GetAttachmentTable (obj_object, &obj_table);
+ /* get recipients */
+ ms = GetRecipientTable (obj_message, &recipient_rows, &recipient_proptags);
if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "GetAttachmentTable", ms);
+ make_mapi_error (perror, "GetRecipientTable", ms);
goto cleanup;
}
- proptags = set_SPropTagArray (mem_ctx, 1, PidTagAttachNumber);
+ if (recipient_rows.cRows > 0) {
+ uint32_t uj32, uk32;
+ EMapiRecipient *first_recipient = NULL;
- ms = SetColumns (&obj_table, proptags);
- if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "SetColumns", ms);
- goto cleanup;
- }
+ for (ui32 = 0; ui32 < recipient_rows.cRows; ui32++) {
+ struct SRow *row = &recipient_rows.aRow[ui32];
+ EMapiRecipient *recipient;
- ms = foreach_tablerow (conn, mapi_object_get_id (obj_folder), mem_ctx, &obj_table, delete_attachment_cb, obj_object, cancellable, perror);
- if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "foreach_tablerow", ms);
+ recipient = e_mapi_recipient_new (object);
+ recipient->properties.cValues = row->cValues;
+ recipient->properties.lpProps = talloc_zero_array (recipient, struct mapi_SPropValue, recipient->properties.cValues + 1);
+
+ for (uj32 = 0, uk32 = 0; uj32 < row->cValues; uj32++, uk32++) {
+ if (may_skip_property (row->lpProps[uj32].ulPropTag) ||
+ !e_mapi_utils_copy_to_mapi_SPropValue (recipient, &recipient->properties.lpProps[uk32], &row->lpProps[uj32])) {
+ uk32--;
+ recipient->properties.cValues--;
+ recipient->properties.lpProps[recipient->properties.cValues].ulPropTag = 0;
+ }
+ }
+
+ recipient->properties.lpProps[recipient->properties.cValues].ulPropTag = 0;
+ }
+
+ object->recipients = first_recipient;
}
cleanup:
- mapi_object_release (&obj_table);
+ mapi_object_release (&attach_table);
- UNLOCK ();
+ if (ms == MAPI_E_SUCCESS) {
+ *out_object = object;
+ } else {
+ *out_object = NULL;
+ e_mapi_object_free (object);
+ }
- return ms == MAPI_E_SUCCESS;
+ return ms;
}
-static gboolean update_message_with_object (EMapiConnection *conn,
- mapi_object_t *obj_folder,
- mapi_object_t *obj_message,
- EMapiObject *object,
- TALLOC_CTX *mem_ctx,
- GCancellable *cancellable,
- GError **perror);
-
-static gboolean
-add_object_attachments (EMapiConnection *conn,
- mapi_object_t *obj_folder,
- mapi_object_t *obj_message,
- EMapiAttachment *attachments,
- TALLOC_CTX *mem_ctx,
- GCancellable *cancellable,
- GError **perror)
+static enum MAPISTATUS
+e_mapi_connection_fetch_objects_internal (EMapiConnection *conn,
+ TALLOC_CTX *mem_ctx,
+ mapi_id_array_t *ids,
+ struct EnsureAdditionalPropertiesData *eap,
+ GCancellable *cancellable,
+ GError **perror)
{
- enum MAPISTATUS ms = MAPI_E_SUCCESS;
- EMapiAttachment *attachment;
+ enum MAPISTATUS ms;
+ guint32 idx;
+ mapi_container_list_t *element;
- CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
- e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
- e_return_val_mapi_error_if_fail (obj_folder != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
- e_return_val_mapi_error_if_fail (obj_message != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
- e_return_val_mapi_error_if_fail (mem_ctx != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+ g_return_val_if_fail (conn != NULL, MAPI_E_INVALID_PARAMETER);
+ g_return_val_if_fail (mem_ctx != NULL, MAPI_E_INVALID_PARAMETER);
+ g_return_val_if_fail (ids != NULL, MAPI_E_INVALID_PARAMETER);
+ g_return_val_if_fail (eap != NULL, MAPI_E_INVALID_PARAMETER);
+ g_return_val_if_fail (eap->obj_folder != NULL, MAPI_E_INVALID_PARAMETER);
+ g_return_val_if_fail (eap->downloaded < ids->count, MAPI_E_INVALID_PARAMETER);
- LOCK ();
+ for (idx = 0, element = ids->lpContainerList; idx < ids->count && idx < eap->downloaded && element; idx++) {
+ element = element->next;
+ }
- for (attachment = attachments; attachment && ms == MAPI_E_SUCCESS; attachment = attachment->next) {
- mapi_object_t obj_attach;
+ g_return_val_if_fail (idx < ids->count, MAPI_E_INVALID_PARAMETER);
+
+ ms = MAPI_E_SUCCESS;
+ while (element && ms == MAPI_E_SUCCESS) {
+ mapi_object_t obj_message;
+ EMapiObject *object = NULL;
+ GError *local_error = NULL;
if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
ms = MAPI_E_USER_CANCEL;
break;
}
- mapi_object_init (&obj_attach);
+ mapi_object_init (&obj_message);
- ms = CreateAttach (obj_message, &obj_attach);
+ ms = OpenMessage (eap->obj_folder, mapi_object_get_id (eap->obj_folder), element->id, &obj_message, 0 /* read-only */);
if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "CreateAttach", ms);
- goto cleanup;
+ make_mapi_error (perror, "OpenMessage", ms);
+ mapi_object_release (&obj_message);
+ break;
}
- if (!update_props_on_object (conn, obj_folder, &obj_attach, &attachment->properties, mem_ctx, cancellable, perror)) {
- ms = MAPI_E_CALL_FAILED;
- make_mapi_error (perror, "update_props_on_object", ms);
- goto cleanup;
+ /* silently skip broken objects */
+ ms = e_mapi_connection_fetch_object_internal (conn, mem_ctx, &obj_message, eap, &object, cancellable, &local_error);
+ if (ms == MAPI_E_SUCCESS) {
+ if (!eap->cb (conn, mem_ctx, object, eap->downloaded, ids->count, eap->cb_user_data, cancellable, perror)) {
+ ms = MAPI_E_USER_CANCEL;
+ make_mapi_error (perror, "Object processing", ms);
+ }
+ } else {
+ e_mapi_debug_print ("%s: Skipping object %016" G_GINT64_MODIFIER "X because its fetch failed: %s",
+ G_STRFUNC, element->id, local_error ? local_error->message : mapi_get_errstr (ms));
+ ms = MAPI_E_SUCCESS;
}
- if (attachment->embedded_object) {
- mapi_object_t obj_emb_msg;
+ e_mapi_object_free (object);
+ mapi_object_release (&obj_message);
- mapi_object_init (&obj_emb_msg);
+ eap->downloaded++;
- ms = OpenEmbeddedMessage (&obj_attach, &obj_emb_msg, MAPI_CREATE);
- if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "OpenEmbeddedMessage", ms);
- goto cleanup;
- }
+ element = element->next;
+ }
- if (!update_message_with_object (conn, obj_folder, &obj_emb_msg, attachment->embedded_object, mem_ctx, cancellable, perror)) {
- ms = MAPI_E_CALL_FAILED;
- make_mapi_error (perror, "SaveChangesMessage", ms);
- mapi_object_release (&obj_emb_msg);
- goto cleanup;
- }
+ return ms;
+}
- ms = SaveChangesMessage (&obj_attach, &obj_emb_msg, KeepOpenReadOnly);
- if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "SaveChangesMessage", ms);
- mapi_object_release (&obj_emb_msg);
- goto cleanup;
- }
+/* deals with named IDs transparently, thus it's OK to check with PidLid and PidName constants only */
+gboolean
+e_mapi_connection_transfer_objects (EMapiConnection *conn,
+ mapi_object_t *obj_folder,
+ const GSList *mids,
+ TransferObjectCB cb,
+ gpointer cb_user_data,
+ GCancellable *cancellable,
+ GError **perror)
+{
+ enum MAPISTATUS ms;
+ TALLOC_CTX *mem_ctx;
+ mapi_id_array_t ids;
+ const GSList *iter;
+ struct EnsureAdditionalPropertiesData eap;
- mapi_object_release (&obj_emb_msg);
- }
+ CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
+ e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+ e_return_val_mapi_error_if_fail (cb != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+ e_return_val_mapi_error_if_fail (obj_folder != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
- ms = SaveChangesAttachment (obj_message, &obj_attach, KeepOpenReadWrite);
- if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "SaveChangesAttachment", ms);
- goto cleanup;
- }
+ LOCK ();
+ mem_ctx = talloc_new (priv->session);
- cleanup:
- mapi_object_release (&obj_attach);
+ ms = mapi_id_array_init (priv->mapi_ctx, &ids);
+ if (ms != MAPI_E_SUCCESS) {
+ make_mapi_error (perror, "mapi_id_array_init", ms);
+ goto cleanup;
+ }
+
+ for (iter = mids; iter; iter = iter->next) {
+ mapi_id_t *pmid = iter->data;
+
+ if (pmid)
+ mapi_id_array_add_id (&ids, *pmid);
}
+ if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
+ ms = MAPI_E_USER_CANCEL;
+ mapi_id_array_release (&ids);
+ goto cleanup;
+ }
+
+ eap.cb = cb;
+ eap.cb_user_data = cb_user_data;
+ eap.obj_folder = obj_folder;
+ eap.downloaded = 0;
+
+ ms = e_mapi_fast_transfer_objects (conn, mem_ctx, obj_folder, &ids, ensure_additional_properties_cb, &eap, cancellable, perror);
+ if (ms == MAPI_E_CALL_FAILED) {
+ /* err, fallback to slow transfer, probably FXGetBuffer failed;
+ see http://tracker.openchange.org/issues/378
+ */
+
+ g_clear_error (perror);
+
+ e_mapi_debug_print ("%s: Failed to fast-transfer, fallback to slow fetch from %d of %d objects\n", G_STRFUNC, eap.downloaded, ids.count);
+
+ ms = e_mapi_connection_fetch_objects_internal (conn, mem_ctx, &ids, &eap, cancellable, perror);
+ }
+
+ mapi_id_array_release (&ids);
+
+ cleanup:
+ talloc_free (mem_ctx);
UNLOCK ();
return ms == MAPI_E_SUCCESS;
}
-static gboolean
-update_message_with_object (EMapiConnection *conn,
- mapi_object_t *obj_folder,
- mapi_object_t *obj_message,
- EMapiObject *object,
- TALLOC_CTX *mem_ctx,
- GCancellable *cancellable,
- GError **perror)
+gboolean
+e_mapi_connection_transfer_object (EMapiConnection *conn,
+ mapi_object_t *obj_folder,
+ mapi_id_t message_id,
+ TransferObjectCB cb,
+ gpointer cb_user_data,
+ GCancellable *cancellable,
+ GError **perror)
{
- CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
- e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
- e_return_val_mapi_error_if_fail (obj_folder != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
- e_return_val_mapi_error_if_fail (obj_message != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
- e_return_val_mapi_error_if_fail (object != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
-
- if (!update_props_on_object (conn, obj_folder, obj_message, &object->properties, mem_ctx, cancellable, perror))
- return FALSE;
-
- if (g_cancellable_set_error_if_cancelled (cancellable, perror))
- return FALSE;
+ GSList *mids;
+ gboolean res;
- /* do not touch recipients if not set */
- if (object->recipients) {
- /* remove current recipients... */
- if (!delete_object_recipients (conn, obj_folder, obj_message, mem_ctx, cancellable, perror))
- return FALSE;
+ mids = g_slist_append (NULL, &message_id);
+ res = e_mapi_connection_transfer_objects (conn, obj_folder, mids, cb, cb_user_data, cancellable, perror);
+ g_slist_free (mids);
- if (g_cancellable_set_error_if_cancelled (cancellable, perror))
- return FALSE;
+ return res;
+}
- /* ... and add new */
- if (!add_object_recipients (conn, obj_folder, obj_message, object->recipients, mem_ctx, cancellable, perror))
- return FALSE;
- }
+struct GetSummaryData {
+ guint32 obj_index;
+ guint32 obj_total;
+ struct SPropValue *lpProps;
+ uint32_t prop_count;
+ TransferObjectCB cb;
+ gpointer cb_user_data;
+};
- if (g_cancellable_set_error_if_cancelled (cancellable, perror))
- return FALSE;
+static gboolean
+internal_get_summary_cb (EMapiConnection *conn,
+ TALLOC_CTX *mem_ctx,
+ /* const */ EMapiObject *object,
+ guint32 obj_index,
+ guint32 obj_total,
+ gpointer user_data,
+ GCancellable *cancellable,
+ GError **perror)
+{
+ struct GetSummaryData *gsd = user_data;
- /* remove current attachments... */
- if (!delete_object_attachments (conn, obj_folder, obj_message, mem_ctx, cancellable, perror))
- return FALSE;
+ g_return_val_if_fail (gsd != NULL, FALSE);
+ g_return_val_if_fail (gsd->cb != NULL, FALSE);
+ g_return_val_if_fail (object != NULL, FALSE);
- if (g_cancellable_set_error_if_cancelled (cancellable, perror))
- return FALSE;
+ /* also include properties received from GetProps,
+ as those like PR_MID are not included by default */
+ if (gsd->lpProps && gsd->prop_count > 0) {
+ uint32_t ii;
- /* ... and add new */
- if (object->attachments && !add_object_attachments (conn, obj_folder, obj_message, object->attachments, mem_ctx, cancellable, perror))
- return FALSE;
+ for (ii = 0; ii < gsd->prop_count; ii++) {
+ /* skip errors and already included properties */
+ if ((gsd->lpProps[ii].ulPropTag & 0xFFFF) == PT_ERROR
+ || e_mapi_util_find_array_propval (&object->properties, gsd->lpProps[ii].ulPropTag))
+ continue;
- if (g_cancellable_set_error_if_cancelled (cancellable, perror))
- return FALSE;
+ object->properties.cValues++;
+ object->properties.lpProps = talloc_realloc (mem_ctx,
+ object->properties.lpProps,
+ struct mapi_SPropValue,
+ object->properties.cValues + 1);
+ cast_mapi_SPropValue (mem_ctx, &object->properties.lpProps[object->properties.cValues - 1], &gsd->lpProps[ii]);
+ object->properties.lpProps[object->properties.cValues].ulPropTag = 0;
+ }
+ }
- return TRUE;
+ return gsd->cb (conn, mem_ctx, object, gsd->obj_index, gsd->obj_total, gsd->cb_user_data, cancellable, perror);
}
+/* transfers items summary, which is either PR_TRANSPORT_MESSAGE_HEADERS_UNICODE or
+ the object without attachment */
gboolean
-e_mapi_connection_create_object (EMapiConnection *conn,
- mapi_object_t *obj_folder,
- uint32_t flags, /* bit-or of EMapiCreateFlags */
- WriteObjectCB write_object_cb,
- gpointer woc_data,
- mapi_id_t *out_mid,
- GCancellable *cancellable,
- GError **perror)
+e_mapi_connection_transfer_summary (EMapiConnection *conn,
+ mapi_object_t *obj_folder,
+ const GSList *mids,
+ TransferObjectCB cb,
+ gpointer cb_user_data,
+ GCancellable *cancellable,
+ GError **perror)
{
enum MAPISTATUS ms;
TALLOC_CTX *mem_ctx;
- EMapiObject *object = NULL;
- mapi_object_t obj_message;
+ const GSList *iter;
+ guint32 index, total;
CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+ e_return_val_mapi_error_if_fail (cb != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
e_return_val_mapi_error_if_fail (obj_folder != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
- e_return_val_mapi_error_if_fail (write_object_cb != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
- e_return_val_mapi_error_if_fail (out_mid != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
LOCK ();
-
- *out_mid = 0;
-
mem_ctx = talloc_new (priv->session);
- mapi_object_init (&obj_message);
- if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
- ms = MAPI_E_USER_CANCEL;
- goto cleanup;
- }
+ ms = MAPI_E_SUCCESS;
+ total = g_slist_length ((GSList *) mids);
+ for (iter = mids, index = 0; iter && ms == MAPI_E_SUCCESS; iter = iter->next, index++) {
+ mapi_id_t *pmid = iter->data;
- if (!write_object_cb (conn, mem_ctx, &object, woc_data, cancellable, perror) || !object) {
- ms = MAPI_E_CALL_FAILED;
- make_mapi_error (perror, "write_object_cb", ms);
- goto cleanup;
- }
+ if (pmid) {
+ mapi_object_t obj_message;
+ struct SPropTagArray *tags;
+ struct SPropValue *lpProps = NULL;
+ uint32_t prop_count = 0, ii;
- if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
- ms = MAPI_E_USER_CANCEL;
- goto cleanup;
- }
+ mapi_object_init (&obj_message);
- ms = CreateMessage (obj_folder, &obj_message);
- if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "CreateMessage", ms);
- goto cleanup;
- }
+ ms = OpenMessage (obj_folder, mapi_object_get_id (obj_folder), *pmid, &obj_message, 0);
+ if (ms != MAPI_E_SUCCESS && ms != MAPI_E_NOT_FOUND) {
+ make_mapi_error (perror, "OpenMessage", ms);
+ goto cleanup;
+ }
- if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
- ms = MAPI_E_USER_CANCEL;
- goto cleanup;
- }
+ tags = set_SPropTagArray (mem_ctx, 6,
+ PR_FID,
+ PR_MID,
+ PR_MESSAGE_FLAGS,
+ PR_LAST_MODIFICATION_TIME,
+ PR_MESSAGE_CLASS,
+ PR_TRANSPORT_MESSAGE_HEADERS_UNICODE);
- if (!update_message_with_object (conn, obj_folder, &obj_message, object, mem_ctx, cancellable, perror)) {
- ms = MAPI_E_CALL_FAILED;
- make_mapi_error (perror, "update_message_with_object", ms);
- goto cleanup;
- }
+ ms = GetProps (&obj_message, MAPI_PROPS_SKIP_NAMEDID_CHECK | MAPI_UNICODE, tags, &lpProps, &prop_count);
+ if (ms == MAPI_E_SUCCESS) {
+ ms = MAPI_E_NOT_FOUND;
+ if (lpProps && prop_count > 0) {
+ const gchar *headers = e_mapi_util_find_SPropVal_array_propval (lpProps, PR_TRANSPORT_MESSAGE_HEADERS_UNICODE);
- if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
- ms = MAPI_E_USER_CANCEL;
- goto cleanup;
- }
+ if (headers && *headers) {
+ EMapiObject *object;
- ms = SaveChangesMessage (obj_folder, &obj_message, KeepOpenReadWrite);
- if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "SaveChangesMessage", ms);
- goto cleanup;
- }
+ ms = MAPI_E_SUCCESS;
- if ((flags & E_MAPI_CREATE_FLAG_SUBMIT) != 0) {
- /* Mark message as ready to be sent */
- ms = SubmitMessage (&obj_message);
- if (ms != MAPI_E_SUCCESS) {
- mapi_id_t mid;
- make_mapi_error (perror, "SubmitMessage", ms);
+ object = e_mapi_object_new (mem_ctx);
+ for (ii = 0; ii < prop_count; ii++) {
+ object->properties.cValues++;
+ object->properties.lpProps = talloc_realloc (mem_ctx,
+ object->properties.lpProps,
+ struct mapi_SPropValue,
+ object->properties.cValues + 1);
+ cast_mapi_SPropValue (mem_ctx, &object->properties.lpProps[object->properties.cValues - 1], &lpProps[ii]);
+ object->properties.lpProps[object->properties.cValues].ulPropTag = 0;
+ }
- /*
- The code is storing message right to Sent items instead of Outbox,
- because fetching PR_ENTRYID or PR_IPM_SENTMAIL_ENTRYID didn't seem
- to work in time of doing this change.
+ if (!cb (conn, mem_ctx, object, index, total, cb_user_data, cancellable, perror)) {
+ ms = MAPI_E_USER_CANCEL;
+ e_mapi_object_free (object);
+ mapi_object_release (&obj_message);
+ goto cleanup;
+ }
- For more information and other possible (correct) approaches see:
- https://bugzilla.gnome.org/show_bug.cgi?id=561794
- */
- mid = mapi_object_get_id (&obj_message);
+ e_mapi_object_free (object);
+ }
+ }
+ }
- mapi_object_release (&obj_message);
- /* to not release a message object twice */
- mapi_object_init (&obj_message);
+ if (ms == MAPI_E_NOT_FOUND) {
+ struct GetSummaryData gsd;
- ms = DeleteMessage (obj_folder, &mid, 1);
- if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "DeleteMessage", ms);
+ gsd.obj_index = index;
+ gsd.obj_total = total;
+ gsd.lpProps = lpProps;
+ gsd.prop_count = prop_count;
+ gsd.cb = cb;
+ gsd.cb_user_data = cb_user_data;
+
+ ms = e_mapi_fast_transfer_object (conn, mem_ctx, &obj_message, E_MAPI_FAST_TRANSFER_FLAG_RECIPIENTS, internal_get_summary_cb, &gsd, cancellable, perror);
+ if (ms != MAPI_E_SUCCESS) {
+ make_mapi_error (perror, "transfer_object", ms);
+ mapi_object_release (&obj_message);
+ goto cleanup;
+ }
}
+ mapi_object_release (&obj_message);
+ talloc_free (tags);
+ }
+
+ if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
+ ms = MAPI_E_USER_CANCEL;
goto cleanup;
}
}
- *out_mid = mapi_object_get_id (&obj_message);
+ cleanup:
+ talloc_free (mem_ctx);
+ UNLOCK ();
+
+ return ms == MAPI_E_SUCCESS;
+}
+
+typedef struct {
+ uint32_t proptag;
+ uint32_t cb;
+ const uint8_t *lpb; /* taken from the original mapi prop, no need to copy the memory */
+} EMapiStreamedProp;
+
+static gboolean
+convert_mapi_props_to_props (EMapiConnection *conn,
+ mapi_object_t *obj_folder,
+ const struct mapi_SPropValue_array *mapi_props,
+ struct SPropValue **props,
+ uint32_t *propslen,
+ EMapiStreamedProp **streams, /* can be NULL for no streaming */
+ guint *streamslen, /* can be NULL only if streams is NULL; is ignored if streams is NULL */
+ TALLOC_CTX *mem_ctx,
+ GCancellable *cancellable,
+ GError **perror)
+{
+ uint16_t ii;
+ ResolveNamedIDsData *named_ids_list = NULL;
+ guint named_ids_len = 0;
+ gboolean res = TRUE;
+
+ e_return_val_mapi_error_if_fail (conn != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+ e_return_val_mapi_error_if_fail (mapi_props != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+ e_return_val_mapi_error_if_fail (props != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+ e_return_val_mapi_error_if_fail (propslen != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+ e_return_val_mapi_error_if_fail (mem_ctx != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+ if (streams) {
+ e_return_val_mapi_error_if_fail (streamslen != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+ }
+
+ for (ii = 0; ii < mapi_props->cValues; ii++) {
+ gboolean processed = FALSE;
+ uint32_t proptag = mapi_props->lpProps[ii].ulPropTag;
+ gconstpointer propdata = get_mapi_SPropValue_data (&mapi_props->lpProps[ii]);
- cleanup:
- e_mapi_object_free (object);
- mapi_object_release (&obj_message);
- talloc_free (mem_ctx);
+ maybe_add_named_id_tag (proptag, &named_ids_list, &named_ids_len);
- UNLOCK ();
+ if (streams && propdata) {
+ /* copy anything longer than 1KB as streams; this doesn't count total packet size needed,
+ but because this is usually useful only for PidTagBody, PidTagHtml, which are there
+ only once, then no big deal
+ */
- return ms == MAPI_E_SUCCESS;
-}
+ uint32_t sz;
+ const gchar *str;
+ const struct SBinary_short *bin;
-gboolean
-e_mapi_connection_modify_object (EMapiConnection *conn,
- mapi_object_t *obj_folder,
- mapi_id_t mid,
- WriteObjectCB write_object_cb,
- gpointer woc_data,
- GCancellable *cancellable,
- GError **perror)
-{
- enum MAPISTATUS ms;
- TALLOC_CTX *mem_ctx;
- EMapiObject *object = NULL;
- mapi_object_t obj_message;
+ #define addstream() { \
+ if (!*streams) { \
+ *streams = g_new0 (EMapiStreamedProp, 1); \
+ *streamslen = 0; \
+ } else { \
+ *streams = g_renew (EMapiStreamedProp, *streams, *streamslen + 1); \
+ } \
+ \
+ (*streams)[*streamslen].proptag = proptag; \
+ (*streams)[*streamslen].cb = 0; \
+ (*streams)[*streamslen].lpb = NULL; \
+ (*streamslen) += 1; \
+ }
- CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
- e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
- e_return_val_mapi_error_if_fail (obj_folder != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
- e_return_val_mapi_error_if_fail (write_object_cb != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
- e_return_val_mapi_error_if_fail (mid != 0, MAPI_E_INVALID_PARAMETER, FALSE);
+ switch (proptag & 0xFFFF) {
+ case PT_BINARY:
+ bin = propdata;
+ if (bin->cb > MAX_PROPERTY_WRITE_SIZE) {
+ addstream ();
+ (*streams)[(*streamslen) - 1].cb = bin->cb;
+ (*streams)[(*streamslen) - 1].lpb = bin->lpb;
+ processed = TRUE;
+ }
+ break;
+ case PT_STRING8:
+ str = propdata;
+ sz = get_mapi_property_size (&mapi_props->lpProps[ii]);
+ if (sz > MAX_PROPERTY_WRITE_SIZE) {
+ addstream ();
+ (*streams)[(*streamslen) - 1].cb = sz;
+ (*streams)[(*streamslen) - 1].lpb = (uint8_t *) str;
+ processed = TRUE;
+ }
+ break;
+ case PT_UNICODE:
+ str = propdata;
+ sz = get_mapi_property_size (&mapi_props->lpProps[ii]);
+ if (sz > MAX_PROPERTY_WRITE_SIZE) {
+ gchar *in_unicode;
+ gsize written = 0;
- LOCK ();
+ addstream ();
- mem_ctx = talloc_new (priv->session);
- mapi_object_init (&obj_message);
+ in_unicode = g_convert (str, strlen (str), "UTF-16", "UTF-8", NULL, &written, NULL);
+ if (in_unicode && written > 0) {
+ uint8_t *bytes = talloc_zero_size (mem_ctx, written + 2);
- if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
- ms = MAPI_E_USER_CANCEL;
- goto cleanup;
- }
+ /* skip Unicode marker, if there */
+ if (written >= 2 && (const guchar) in_unicode[0] == 0xFF && (const guchar) in_unicode[1] == 0xFE) {
+ memcpy (bytes, in_unicode + 2, written - 2);
+ written -= 2;
+ } else
+ memcpy (bytes, in_unicode, written);
- if (!write_object_cb (conn, mem_ctx, &object, woc_data, cancellable, perror)) {
- ms = MAPI_E_CALL_FAILED;
- make_mapi_error (perror, "write_object_cb", ms);
- goto cleanup;
- }
+ /* null-terminated unicode string */
+ (*streams)[(*streamslen) - 1].lpb = bytes;
+ (*streams)[(*streamslen) - 1].cb = written + 2;
+ }
+ g_free (in_unicode);
+ processed = TRUE;
+ }
+ break;
+ }
- if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
- ms = MAPI_E_USER_CANCEL;
- goto cleanup;
- }
+ #undef addstream
+ }
- ms = OpenMessage (obj_folder, mapi_object_get_id (obj_folder), mid, &obj_message, MAPI_MODIFY);
- if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "OpenMessage", ms);
- goto cleanup;
+ if (!processed)
+ e_mapi_utils_add_spropvalue (mem_ctx, props, propslen, proptag, propdata);
}
- if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
- ms = MAPI_E_USER_CANCEL;
- goto cleanup;
- }
+ if (named_ids_list) {
+ res = e_mapi_connection_resolve_named_props (conn, mapi_object_get_id (obj_folder), named_ids_list, named_ids_len, cancellable, perror);
- if (!update_message_with_object (conn, obj_folder, &obj_message, object, mem_ctx, cancellable, perror)) {
- ms = MAPI_E_CALL_FAILED;
- make_mapi_error (perror, "update_message_with_object", ms);
- goto cleanup;
- }
+ if (res && *props) {
+ for (ii = 0; ii < *propslen; ii++) {
+ uint32_t proptag = (*props)[ii].ulPropTag;
- ms = SaveChangesMessage (obj_folder, &obj_message, KeepOpenReadOnly);
- if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "SaveChangesMessage", ms);
- goto cleanup;
- }
+ maybe_replace_named_id_tag (&proptag, named_ids_list, named_ids_len);
- cleanup:
- e_mapi_object_free (object);
- mapi_object_release (&obj_message);
- talloc_free (mem_ctx);
+ (*props)[ii].ulPropTag = proptag;
+ }
+ }
- UNLOCK ();
+ if (res && streams) {
+ for (ii = 0; ii < *streamslen; ii++) {
+ maybe_replace_named_id_tag (&((*streams)[ii].proptag), named_ids_list, named_ids_len);
+ }
+ }
+ }
- return ms == MAPI_E_SUCCESS;
+ g_free (named_ids_list);
+
+ return res;
}
-gboolean
-e_mapi_connection_fetch_items (EMapiConnection *conn,
- mapi_id_t fid,
- BuildRestrictionsCB build_rs_cb,
- gpointer build_rs_cb_data,
- struct SSortOrderSet *sort_order,
- BuildReadPropsCB build_props,
- gpointer brp_data,
- FetchCallback cb,
- gpointer data,
- guint32 options,
- GCancellable *cancellable,
- GError **perror)
+static gboolean
+write_streamed_prop (EMapiConnection *conn,
+ mapi_object_t *obj_object,
+ const EMapiStreamedProp *stream,
+ GCancellable *cancellable,
+ GError **perror)
{
- enum MAPISTATUS ms;
- TALLOC_CTX *mem_ctx;
- mapi_object_t obj_folder;
- mapi_object_t obj_table;
- struct SPropTagArray *SPropTagArray, *propsTagArray = NULL;
- struct SRowSet SRowSet;
- uint32_t count, i, cursor_pos = 0;
- gboolean result = FALSE;
+ enum MAPISTATUS ms;
+ uint32_t total_written;
+ gboolean done = FALSE;
+ mapi_object_t obj_stream;
CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
-
- e_mapi_debug_print("%s: Entering %s: folder-id %016" G_GINT64_MODIFIER "X ", G_STRLOC, G_STRFUNC, fid);
+ e_return_val_mapi_error_if_fail (obj_object != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+ e_return_val_mapi_error_if_fail (stream != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
LOCK ();
- mem_ctx = talloc_new (priv->session);
- mapi_object_init(&obj_folder);
- mapi_object_init(&obj_table);
- /* Attempt to open the folder */
- ms = open_folder (conn, 0, &fid, options, &obj_folder, perror);
- if (ms != MAPI_E_SUCCESS) {
- goto cleanup;
- }
+ mapi_object_init (&obj_stream);
if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
ms = MAPI_E_USER_CANCEL;
goto cleanup;
}
- /* Get a handle on the container */
- ms = GetContentsTable (&obj_folder, &obj_table, TableFlags_UseUnicode, NULL);
+ /* OpenStream on required proptag */
+ ms = OpenStream (obj_object, stream->proptag, STREAM_ACCESS_READWRITE, &obj_stream);
if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "GetContentsTable", ms);
- goto cleanup;
- }
-
- if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
- ms = MAPI_E_USER_CANCEL;
+ make_mapi_error (perror, "OpenStream", ms);
goto cleanup;
}
- SPropTagArray = set_SPropTagArray(mem_ctx, 0x5,
- PR_FID,
- PR_MID,
- PR_LAST_MODIFICATION_TIME,
- PR_HASATTACH,
- PR_MESSAGE_FLAGS);
-
- /* Set primary columns to be fetched */
- ms = SetColumns (&obj_table, SPropTagArray);
+ /* Set the stream size */
+ ms = SetStreamSize (&obj_stream, stream->cb);
if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "SetColumns", ms);
- goto cleanup;
- }
-
- if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
- ms = MAPI_E_USER_CANCEL;
+ make_mapi_error (perror, "SetStreamSize", ms);
goto cleanup;
}
- if (build_rs_cb) {
- struct mapi_SRestriction *restrictions = NULL;
-
- if (!build_rs_cb (conn, fid, mem_ctx, &restrictions, build_rs_cb_data, cancellable, perror)) {
- ms = MAPI_E_CALL_FAILED;
- make_mapi_error (perror, "build_restrictions", ms);
- goto cleanup;
- }
-
- if (restrictions) {
- /* Applying any restriction that are set. */
- ms = Restrict (&obj_table, restrictions, NULL);
- if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "Restrict", ms);
- goto cleanup;
- }
-
- if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
- ms = MAPI_E_USER_CANCEL;
- goto cleanup;
- }
- }
- }
-
- if (sort_order) {
- ms = SortTable (&obj_table, sort_order);
- if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "SortTable", ms);
- goto cleanup;
- }
- }
-
- if (build_props) {
- propsTagArray = set_SPropTagArray (mem_ctx, 0x1, PR_MESSAGE_CLASS);
- if (!build_props (conn, fid, mem_ctx, propsTagArray, brp_data, cancellable, perror)) {
- make_mapi_error (perror, "build_props", MAPI_E_CALL_FAILED);
- goto cleanup;
- }
+ total_written = 0;
+ /* Write stream */
+ while (!done) {
+ uint16_t cn_written = 0;
+ DATA_BLOB blob;
if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
ms = MAPI_E_USER_CANCEL;
goto cleanup;
}
- }
- /* Note : We maintain a cursor position. count parameter in QueryRows */
- /* is more of a request and not gauranteed */
- do {
- /* Number of items in the container */
- ms = QueryPosition (&obj_table, &cursor_pos, &count);
+ blob.length = (stream->cb - total_written) < STREAM_MAX_WRITE_SIZE ?
+ (stream->cb - total_written) : STREAM_MAX_WRITE_SIZE;
+ blob.data = (uint8_t *) (stream->lpb + total_written);
+
+ ms = WriteStream (&obj_stream, &blob, &cn_written);
if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "QueryPosition", ms);
- goto cleanup;
+ make_mapi_error (perror, "WriteStream", ms);
+ done = TRUE;
+ } else if (cn_written == 0) {
+ done = TRUE;
+ } else {
+ total_written += cn_written;
+ if (total_written >= stream->cb)
+ done = TRUE;
}
+ }
- if (!count)
- break;
-
- /* Fill the table columns with data from the rows */
- ms = QueryRows (&obj_table, count, TBL_ADVANCE, &SRowSet);
+ if (ms == MAPI_E_SUCCESS) {
+ /* Commit the stream */
+ ms = CommitStream (&obj_stream);
if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "QueryRows", ms);
+ make_mapi_error (perror, "CommitStream", ms);
goto cleanup;
}
+ }
- for (i = 0; i < SRowSet.cRows; i++) {
- mapi_object_t obj_message;
- struct mapi_SPropValue_array properties_array = {0};
- const mapi_id_t *pfid;
- const mapi_id_t *pmid;
- const bool *has_attach = NULL;
- const uint32_t *msg_flags;
- GSList *attach_list = NULL;
- GSList *recip_list = NULL;
- GSList *stream_list = NULL;
- gboolean cb_retval = false;
+ cleanup:
+ mapi_object_release (&obj_stream);
- mapi_object_init(&obj_message);
+ UNLOCK ();
- pfid = (const uint64_t *) get_SPropValue_SRow_data(&SRowSet.aRow[i], PR_FID);
- pmid = (const uint64_t *) get_SPropValue_SRow_data(&SRowSet.aRow[i], PR_MID);
+ return ms == MAPI_E_SUCCESS;
+}
- has_attach = (const bool *) get_SPropValue_SRow_data(&SRowSet.aRow[i], PR_HASATTACH);
- msg_flags = get_SPropValue_SRow_data (&SRowSet.aRow[i], PR_MESSAGE_FLAGS);
+static gboolean
+update_props_on_object (EMapiConnection *conn,
+ mapi_object_t *obj_folder,
+ mapi_object_t *obj_object,
+ const struct mapi_SPropValue_array *properties,
+ TALLOC_CTX *mem_ctx,
+ GCancellable *cancellable,
+ GError **perror)
+{
+ enum MAPISTATUS ms;
+ struct SPropValue *props = NULL;
+ uint32_t propslen = 0;
+ EMapiStreamedProp *streams = NULL;
+ guint streamslen = 0;
- if (options & MAPI_OPTIONS_DONT_OPEN_MESSAGE)
- goto relax;
+ CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
+ e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
- ms = OpenMessage (&obj_folder, *pfid, *pmid, &obj_message, 0);
- if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "OpenMessage", ms);
- goto loop_cleanup;
- }
+ LOCK ();
- if (propsTagArray && propsTagArray->cValues) {
- struct SPropValue *lpProps = NULL;
- struct SPropTagArray *tags;
- uint32_t prop_count = 0, k, ll;
- /* we need to make a local copy of the tag array
- * since GetProps will modify the array on any
- * errors */
- tags = set_SPropTagArray (mem_ctx, 0x1, PR_MSG_EDITOR_FORMAT);
- for (k = 0; k < propsTagArray->cValues; k++)
- SPropTagArray_add (mem_ctx, tags, propsTagArray->aulPropTag[k]);
-
- ms = GetProps (&obj_message, MAPI_PROPS_SKIP_NAMEDID_CHECK | MAPI_UNICODE, tags, &lpProps, &prop_count);
- if (ms != MAPI_E_SUCCESS)
- make_mapi_error (perror, "GetProps", ms);
-
- properties_array.lpProps = talloc_zero_array (mem_ctx, struct mapi_SPropValue,
- prop_count + 1);
- properties_array.cValues = prop_count;
- for (k = 0, ll = 0; k < prop_count; k++, ll++) {
- if ((lpProps[k].ulPropTag & 0xFFFF) == PT_MV_BINARY) {
- uint32_t ci;
-
- properties_array.lpProps[ll].ulPropTag = lpProps[k].ulPropTag;
- properties_array.lpProps[ll].value.MVbin.cValues = lpProps[k].value.MVbin.cValues;
- properties_array.lpProps[ll].value.MVbin.bin = (struct SBinary_short *) talloc_array (mem_ctx, struct Binary_r, properties_array.lpProps[ll].value.MVbin.cValues);
- for (ci = 0; ci < properties_array.lpProps[ll].value.MVbin.cValues; ci++) {
- properties_array.lpProps[ll].value.MVbin.bin[ci].cb = lpProps[k].value.MVbin.lpbin[ci].cb;
- properties_array.lpProps[ll].value.MVbin.bin[ci].lpb = lpProps[k].value.MVbin.lpbin[ci].lpb;
- }
- } else if (may_skip_property (lpProps[k].ulPropTag)) {
- ll--;
- properties_array.cValues--;
- } else {
- cast_mapi_SPropValue (mem_ctx,
- &properties_array.lpProps[ll],&lpProps[k]);
- }
- }
- } else {
- ms = GetPropsAll (&obj_message, MAPI_UNICODE, &properties_array);
- if (ms != MAPI_E_SUCCESS)
- make_mapi_error (perror, "GetPropsAll", ms);
- }
+ if (!convert_mapi_props_to_props (conn, obj_folder, properties, &props, &propslen, &streams, &streamslen, mem_ctx, cancellable, perror)) {
+ ms = MAPI_E_CALL_FAILED;
+ make_mapi_error (perror, "convert_mapi_props_to_props", ms);
+ goto cleanup;
+ }
- if (has_attach && *has_attach && (MAPI_OPTIONS_FETCH_ATTACHMENTS & options)) {
- e_mapi_util_get_attachments (conn, fid, mem_ctx, &obj_message, &attach_list, NULL);
- }
+ if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
+ ms = MAPI_E_USER_CANCEL;
+ goto cleanup;
+ }
- if (options & MAPI_OPTIONS_FETCH_RECIPIENTS) {
- e_mapi_util_get_recipients (conn, mem_ctx, &obj_message, &recip_list, perror);
- }
+ if (props) {
+ /* set properties for the item */
+ ms = SetProps (obj_object, MAPI_PROPS_SKIP_NAMEDID_CHECK, props, propslen);
- /* get the main body stream no matter what */
- if (options & MAPI_OPTIONS_FETCH_BODY_STREAM) {
- e_mapi_util_read_body_stream (mem_ctx, &obj_message, &stream_list, &properties_array, (options & MAPI_OPTIONS_GETBESTBODY) != 0);
- }
+ talloc_free (props);
- relax:
- if (ms == MAPI_E_SUCCESS) {
- FetchItemsCallbackData *item_data;
+ if (ms != MAPI_E_SUCCESS) {
+ make_mapi_error (perror, "SetProps", ms);
+ goto cleanup;
+ }
+ }
- if ((options & MAPI_OPTIONS_DONT_OPEN_MESSAGE) == 0) {
- if ((options & MAPI_OPTIONS_FETCH_GENERIC_STREAMS) != 0) {
- uint32_t z;
- const uint32_t *cpid = e_mapi_util_find_array_propval (&properties_array, PR_INTERNET_CPID);
+ if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
+ ms = MAPI_E_USER_CANCEL;
+ goto cleanup;
+ }
- /* just to get all the other streams */
- for (z = 0; z < properties_array.cValues; z++) {
- if ((properties_array.lpProps[z].ulPropTag & 0xFFFF) == PT_BINARY)
- e_mapi_util_read_generic_stream (mem_ctx, &obj_message, cpid, properties_array.lpProps[z].ulPropTag, &stream_list, &properties_array, NULL);
- }
- }
- }
+ if (streams) {
+ guint ii;
- /* NOTE: stream_list, recipient_list and attach_list
- should be freed by the callback */
- item_data = g_new0 (FetchItemsCallbackData, 1);
- item_data->conn = conn;
- item_data->fid = *pfid;
- item_data->mid = *pmid;
- item_data->msg_flags = msg_flags ? *msg_flags : 0;
- item_data->properties = &properties_array;
- item_data->streams = stream_list;
- item_data->recipients = recip_list;
- item_data->attachments = attach_list;
- item_data->total = count; //Total entries in the table.
- item_data->index = cursor_pos + i; //cursor_pos + current_table_index
-
- global_unlock ();
- cb_retval = cb (item_data, data, cancellable, perror);
- global_lock ();
-
- g_free (item_data);
- } else {
- e_mapi_util_free_stream_list (&stream_list);
- e_mapi_util_free_recipient_list (&recip_list);
- e_mapi_util_free_attachment_list (&attach_list);
+ for (ii = 0; ii < streamslen; ii++) {
+ if (!write_streamed_prop (conn, obj_object, &streams[ii], cancellable, perror)) {
+ ms = MAPI_E_CALL_FAILED;
+ make_mapi_error (perror, "write_streamed_prop", ms);
+ break;
}
- if (propsTagArray && propsTagArray->cValues)
- talloc_free (properties_array.lpProps);
-
- loop_cleanup:
- if ((options & MAPI_OPTIONS_DONT_OPEN_MESSAGE) == 0)
- mapi_object_release (&obj_message);
-
- if (!cb_retval) break;
- }
-
- if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
- ms = MAPI_E_USER_CANCEL;
- goto cleanup;
+ if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
+ ms = MAPI_E_USER_CANCEL;
+ break;
+ }
}
- } while (cursor_pos < count && ms == MAPI_E_SUCCESS);
-
- result = ms == MAPI_E_SUCCESS;
+ g_free (streams);
+ }
cleanup:
- if (propsTagArray)
- talloc_free (propsTagArray);
- mapi_object_release(&obj_folder);
- mapi_object_release(&obj_table);
- talloc_free (mem_ctx);
UNLOCK ();
- e_mapi_debug_print("%s: Leaving %s: folder-id %016" G_GINT64_MODIFIER "X ", G_STRLOC, G_STRFUNC, fid);
-
- return result;
+ return ms == MAPI_E_SUCCESS;
}
-/* obj_folder and obj_message are released only when obj_folder is not NULL and when returned TRUE */
-gboolean
-e_mapi_connection_fetch_object_props (EMapiConnection *conn,
- mapi_object_t *obj_folder,
- mapi_id_t fid,
- mapi_id_t mid,
- mapi_object_t *obj_message,
- BuildReadPropsCB build_props,
- gpointer brp_data,
- FetchCallback cb,
- gpointer data,
- guint32 options,
- GCancellable *cancellable,
- GError **perror)
+static gboolean
+update_recipient_properties (EMapiConnection *conn,
+ mapi_object_t *obj_folder,
+ struct SRow *aRow,
+ EMapiRecipient *recipient,
+ gboolean is_resolved,
+ TALLOC_CTX *mem_ctx,
+ GCancellable *cancellable,
+ GError **perror)
{
- enum MAPISTATUS ms;
- TALLOC_CTX *mem_ctx;
- struct mapi_SPropValue_array properties_array;
- struct SPropTagArray *propsTagArray = NULL;
- GSList *attach_list = NULL;
- GSList *recip_list = NULL;
- GSList *stream_list = NULL;
- gboolean result = FALSE;
-
- CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
- e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
-
- e_mapi_debug_print("%s: Entering %s: folder %p message %p", G_STRLOC, G_STRFUNC, obj_folder, obj_message);
-
- LOCK ();
- mem_ctx = talloc_new (priv->session);
+ struct SPropValue *props = NULL;
+ uint32_t propslen = 0, ii;
- if (build_props) {
- propsTagArray = set_SPropTagArray (mem_ctx, 0x3,
- PR_MESSAGE_CLASS,
- PR_HASATTACH,
- PR_MSG_EDITOR_FORMAT);
+ g_return_val_if_fail (recipient != NULL, FALSE);
- if (!build_props (conn, fid, mem_ctx, propsTagArray, brp_data, cancellable, perror)) {
- make_mapi_error (perror, "build_props", MAPI_E_CALL_FAILED);
- goto cleanup;
- }
+ if (!convert_mapi_props_to_props (conn, obj_folder, &recipient->properties, &props, &propslen, NULL, NULL, mem_ctx, cancellable, perror))
+ return FALSE;
- if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
- ms = MAPI_E_USER_CANCEL;
- goto cleanup;
- }
+ for (ii = 0; ii < propslen; ii++) {
+ /* do not overwrite all properties, if recipient was resolved properly */
+ if (!is_resolved
+ || props[ii].ulPropTag == PidTagRecipientType
+ || props[ii].ulPropTag == PidTagSendInternetEncoding
+ || props[ii].ulPropTag == PidTagRecipientFlags
+ || props[ii].ulPropTag == PidTagRecipientTrackStatus)
+ SRow_addprop (aRow, props[ii]);
}
- if (propsTagArray && propsTagArray->cValues) {
- struct SPropValue *lpProps;
- uint32_t prop_count = 0, k, ll;
-
- lpProps = talloc_zero(mem_ctx, struct SPropValue);
+ return TRUE;
+}
- ms = GetProps (obj_message, MAPI_PROPS_SKIP_NAMEDID_CHECK | MAPI_UNICODE, propsTagArray, &lpProps, &prop_count);
- if (ms != MAPI_E_SUCCESS)
- make_mapi_error (perror, "GetProps", ms);
+static gboolean
+delete_object_recipients (EMapiConnection *conn,
+ mapi_object_t *obj_folder,
+ mapi_object_t *obj_object,
+ TALLOC_CTX *mem_ctx,
+ GCancellable *cancellable,
+ GError **perror)
+{
+ enum MAPISTATUS ms;
- if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
- ms = MAPI_E_USER_CANCEL;
- goto cleanup;
- }
+ CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
+ e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
- /* Conversion from SPropValue to mapi_SPropValue. (no padding here) */
- properties_array.cValues = prop_count;
- properties_array.lpProps = talloc_zero_array (mem_ctx, struct mapi_SPropValue, prop_count + 1);
- for (k = 0, ll = 0; k < prop_count; k++, ll++) {
- if (may_skip_property (lpProps[k].ulPropTag)) {
- ll--;
- properties_array.cValues--;
- } else {
- cast_mapi_SPropValue (mem_ctx,
- &properties_array.lpProps[ll], &lpProps[k]);
- }
- }
- } else {
- ms = GetPropsAll (obj_message, MAPI_UNICODE, &properties_array);
- if (ms != MAPI_E_SUCCESS)
- make_mapi_error (perror, "GetPropsAll", ms);
+ LOCK ();
- if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
- ms = MAPI_E_USER_CANCEL;
- goto cleanup;
- }
- }
+ ms = RemoveAllRecipients (obj_object);
+ if (ms != MAPI_E_SUCCESS)
+ make_mapi_error (perror, "RemoveAllRecipients", ms);
- /* Fetch attachments */
- if (options & MAPI_OPTIONS_FETCH_ATTACHMENTS) {
- const bool *has_attach = e_mapi_util_find_array_propval (&properties_array, PR_HASATTACH);
+ UNLOCK ();
- if (has_attach && *has_attach)
- e_mapi_util_get_attachments (conn, fid, mem_ctx, obj_message, &attach_list, NULL);
+ return ms == MAPI_E_SUCCESS;
+}
- if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
- ms = MAPI_E_USER_CANCEL;
- goto cleanup;
- }
- }
+static gboolean
+add_object_recipients (EMapiConnection *conn,
+ mapi_object_t *obj_folder,
+ mapi_object_t *obj_message,
+ EMapiRecipient *recipients,
+ TALLOC_CTX *mem_ctx,
+ GCancellable *cancellable,
+ GError **perror)
+{
+ const uint32_t required_tags[] = {PidTagEntryId,
+ PidTagDisplayName,
+ PidTagObjectType,
+ PidTagDisplayType,
+ PidTagTransmittableDisplayName,
+ PidTagEmailAddress,
+ PidTagAddressType,
+ PidTagSendRichInfo,
+ PidTag7BitDisplayName};
+ enum MAPISTATUS ms;
+ struct SPropTagArray *tags;
+ struct SRowSet *rows = NULL;
+ struct PropertyTagArray_r *flagList = NULL;
+ ResolveNamedIDsData *named_ids_list = NULL;
+ guint named_ids_len = 0;
+ const gchar **users = NULL;
+ EMapiRecipient *recipient;
+ EMapiRecipient **recips;
+ uint32_t ii, jj, count = 0;
+ GHashTable *all_proptags;
+ GHashTableIter iter;
+ gpointer key, value;
- /* Fetch recipients */
- if (options & MAPI_OPTIONS_FETCH_RECIPIENTS) {
- e_mapi_util_get_recipients (conn, mem_ctx, obj_message, &recip_list, NULL);
+ CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
+ e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
- if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
- ms = MAPI_E_USER_CANCEL;
- goto cleanup;
- }
+ count = 0;
+ for (recipient = recipients, ii = 0; recipient; recipient = recipient->next, ii++) {
+ if (!e_mapi_util_find_array_propval (&recipient->properties, PidTagPrimarySmtpAddress)
+ && !e_mapi_util_find_array_propval (&recipient->properties, PidTagDisplayName))
+ g_debug ("%s: Cannot get email or display name for a recipient %d, skipping it", G_STRFUNC, ii);
+ else
+ count++;
}
- /* get the main body stream no matter what */
- if (options & MAPI_OPTIONS_FETCH_BODY_STREAM) {
- e_mapi_util_read_body_stream (mem_ctx, obj_message, &stream_list, &properties_array, (options & MAPI_OPTIONS_GETBESTBODY) != 0);
+ if (!count)
+ return TRUE;
- if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
- ms = MAPI_E_USER_CANCEL;
- goto cleanup;
- }
+ LOCK ();
+
+ all_proptags = g_hash_table_new (g_direct_hash, g_direct_equal);
+ users = g_new0 (const gchar *, count + 1);
+ recips = g_new0 (EMapiRecipient *, count + 1);
+
+ for (ii = 0; ii < G_N_ELEMENTS (required_tags); ii++) {
+ g_hash_table_insert (all_proptags, GUINT_TO_POINTER (required_tags[ii]), GUINT_TO_POINTER (1));
}
- if (ms == MAPI_E_SUCCESS) {
- if ((options & MAPI_OPTIONS_FETCH_GENERIC_STREAMS)) {
- uint32_t z;
+ for (ii = 0, jj = 0, recipient = recipients; ii < count && recipient != NULL; ii++, recipient = recipient->next) {
+ users[ii] = e_mapi_util_find_array_propval (&recipient->properties, PidTagPrimarySmtpAddress);
+ if (!users[ii])
+ users[ii] = e_mapi_util_find_array_propval (&recipient->properties, PidTagDisplayName);
+ if (!users[ii]) {
+ ii--;
+ } else {
+ uint32_t kk;
- /* just to get all the other streams */
- for (z = 0; z < properties_array.cValues; z++) {
- if ((properties_array.lpProps[z].ulPropTag & 0xFFFF) == PT_BINARY) {
- e_mapi_util_read_generic_stream (mem_ctx, obj_message, e_mapi_util_find_array_propval (&properties_array, PR_INTERNET_CPID), properties_array.lpProps[z].ulPropTag, &stream_list, &properties_array, NULL);
- }
+ recips[jj] = recipient;
+ jj++;
- if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
- ms = MAPI_E_USER_CANCEL;
- goto cleanup;
- }
+ for (kk = 0; kk < recipient->properties.cValues; kk++) {
+ g_hash_table_insert (all_proptags, GUINT_TO_POINTER (recipient->properties.lpProps[kk].ulPropTag), GUINT_TO_POINTER (1));
}
}
}
- /* Release the objects so that the callback may use the store. */
- if (obj_folder) {
- /* obj_folder is not NULL, thus can do this */
- mapi_object_release (obj_message);
- mapi_object_release (obj_folder);
- }
+ /* Attempt to resolve names from the server */
+ tags = NULL;
+ g_hash_table_iter_init (&iter, all_proptags);
+ while (g_hash_table_iter_next (&iter, &key, &value)) {
+ uint32_t proptag = GPOINTER_TO_UINT (key);
- if (ms == MAPI_E_SUCCESS) {
- FetchItemsCallbackData *item_data = g_new0 (FetchItemsCallbackData, 1);
- item_data->conn = conn;
- item_data->fid = fid;
- item_data->mid = mid;
- item_data->properties = &properties_array;
- item_data->streams = stream_list;
- item_data->recipients = recip_list;
- item_data->attachments = attach_list;
-
- /* NOTE: stream_list, recipient_list and attach_list should be freed by the callback */
- global_unlock ();
- cb (item_data, data, cancellable, perror);
- global_lock ();
-
- g_free (item_data);
- } else {
- e_mapi_util_free_stream_list (&stream_list);
- e_mapi_util_free_recipient_list (&recip_list);
- e_mapi_util_free_attachment_list (&attach_list);
+ maybe_add_named_id_tag (proptag, &named_ids_list, &named_ids_len);
+
+ if (!tags)
+ tags = set_SPropTagArray (mem_ctx, 1, proptag);
+ else
+ SPropTagArray_add (mem_ctx, tags, proptag);
}
- result = ms == MAPI_E_SUCCESS;
+ if (named_ids_list) {
+ if (!e_mapi_connection_resolve_named_props (conn, mapi_object_get_id (obj_folder), named_ids_list, named_ids_len, cancellable, perror)) {
+ ms = MAPI_E_CALL_FAILED;
+ make_mapi_error (perror, "e_mapi_connection_resolve_named_props", ms);
+ goto cleanup;
+ }
-cleanup:
- talloc_free (mem_ctx);
- UNLOCK ();
+ for (ii = 0; ii < tags->cValues; ii++) {
+ uint32_t proptag = tags->aulPropTag[ii];
- e_mapi_debug_print("%s: Leaving %s ", G_STRLOC, G_STRFUNC);
+ maybe_replace_named_id_tag (&proptag, named_ids_list, named_ids_len);
- return result;
-}
+ tags->aulPropTag[ii] = proptag;
+ }
+ }
-gboolean
-e_mapi_connection_fetch_item (EMapiConnection *conn,
- mapi_id_t fid,
- mapi_id_t mid,
- BuildReadPropsCB build_props,
- gpointer brp_data,
- FetchCallback cb,
- gpointer data,
- guint32 options,
- GCancellable *cancellable,
- GError **perror)
-{
- enum MAPISTATUS ms;
- TALLOC_CTX *mem_ctx;
- mapi_object_t obj_folder;
- mapi_object_t obj_message;
- gboolean result = FALSE;
+ ms = ResolveNames (priv->session, users, tags, &rows, &flagList, MAPI_UNICODE);
+ if (ms != MAPI_E_SUCCESS) {
+ make_mapi_error (perror, "ResolveNames", ms);
+ goto cleanup;
+ }
- CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
- e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+ g_assert (count == flagList->cValues);
- e_mapi_debug_print("%s: Entering %s: folder-id %016" G_GINT64_MODIFIER "X message-id %016" G_GINT64_MODIFIER "X",
- G_STRLOC, G_STRFUNC, fid, mid);
+ if (!rows) /* This happens when there are ZERO RESOLVED recipients */
+ rows = talloc_zero (mem_ctx, struct SRowSet);
- LOCK ();
- mem_ctx = talloc_new (priv->session);
- mapi_object_init(&obj_folder);
- mapi_object_init(&obj_message);
+ for (ii = 0, jj = 0; ii < count; ii++) {
+ recipient = recips[ii];
- /* Attempt to open the folder */
- ms = open_folder (conn, 0, &fid, options, &obj_folder, perror);
- if (ms != MAPI_E_SUCCESS) {
- goto cleanup;
- }
+ if (flagList->aulPropTag[ii] == MAPI_AMBIGUOUS) {
+ /* We should never get an ambiguous resolution as we use the email-id for resolving.
+ * However, if we do still get an ambiguous entry, we can't handle it :-( */
+ ms = MAPI_E_AMBIGUOUS_RECIP;
+ /* Translators: %s is replaced with an email address which was found ambiguous on a remote server */
+ g_set_error (perror, E_MAPI_ERROR, ms, _("Recipient '%s' is ambiguous"), users[ii]);
+ goto cleanup;
+ } else if (flagList->aulPropTag[ii] == MAPI_UNRESOLVED) {
+ uint32_t last;
- if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
- ms = MAPI_E_USER_CANCEL;
- goto cleanup;
+ /* If the recipient is unresolved, consider it is a SMTP one */
+ rows->aRow = talloc_realloc (mem_ctx, rows->aRow, struct SRow, rows->cRows + 1);
+ last = rows->cRows;
+ rows->aRow[last].cValues = 0;
+ rows->aRow[last].lpProps = talloc_zero (mem_ctx, struct SPropValue);
+ if (!update_recipient_properties (conn, obj_folder, &rows->aRow[last], recipient, FALSE, mem_ctx, cancellable, perror)) {
+ ms = MAPI_E_CALL_FAILED;
+ goto cleanup;
+ }
+ rows->cRows += 1;
+ } else if (flagList->aulPropTag[ii] == MAPI_RESOLVED) {
+ if (!update_recipient_properties (conn, obj_folder, &rows->aRow[jj], recipient, TRUE, mem_ctx, cancellable, perror)) {
+ ms = MAPI_E_CALL_FAILED;
+ goto cleanup;
+ }
+ jj += 1;
+ }
}
- /* Open the item */
- ms = OpenMessage (&obj_folder, fid, mid, &obj_message, 0x0);
+ /* Modify the recipient table */
+ ms = ModifyRecipients (obj_message, rows);
if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "OpenMessage", ms);
- goto cleanup;
- }
-
- if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
- ms = MAPI_E_USER_CANCEL;
+ make_mapi_error (perror, "ModifyRecipients", ms);
goto cleanup;
}
- result = e_mapi_connection_fetch_object_props (conn, &obj_folder, fid, mid, &obj_message, build_props, brp_data, cb, data, options, cancellable, perror);
-
cleanup:
- if (!result) {
- mapi_object_release (&obj_message);
- mapi_object_release (&obj_folder);
- }
- talloc_free (mem_ctx);
UNLOCK ();
- e_mapi_debug_print ("%s: Leaving %s ", G_STRLOC, G_STRFUNC);
+ g_free (users);
+ g_free (recips);
+ g_free (named_ids_list);
+ g_hash_table_destroy (all_proptags);
- return result;
+ return ms == MAPI_E_SUCCESS;
}
-mapi_id_t
-e_mapi_connection_create_folder (EMapiConnection *conn,
- uint32_t olFolder,
- mapi_id_t pfid,
- guint32 fid_options,
- const gchar *name,
- GCancellable *cancellable,
- GError **perror)
+static gboolean
+delete_attachment_cb (EMapiConnection *conn,
+ TALLOC_CTX *mem_ctx,
+ struct SRow *srow,
+ guint32 row_index,
+ guint32 rows_total,
+ gpointer user_data,
+ GCancellable *cancellable,
+ GError **perror)
{
+ const uint32_t *attach_num;
+ mapi_object_t *obj_object = user_data;
enum MAPISTATUS ms;
- mapi_object_t obj_folder;
- mapi_object_t obj_top;
- struct SPropValue vals[1];
- const gchar *type;
- mapi_id_t fid = 0;
-
- CHECK_CORRECT_CONN_AND_GET_PRIV (conn, 0);
- e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, 0);
-
- e_mapi_debug_print("%s: Entering %s ", G_STRLOC, G_STRFUNC);
-
- LOCK ();
- mapi_object_init(&obj_top);
- mapi_object_init(&obj_folder);
- /* We now open the top/parent folder */
- ms = open_folder (conn, olFolder, &pfid, fid_options, &obj_top, perror);
- if (ms != MAPI_E_SUCCESS) {
- goto cleanup;
- }
-
- if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
- ms = MAPI_E_USER_CANCEL;
- goto cleanup;
- }
-
- /* Attempt to create the folder */
- ms = CreateFolder (&obj_top, FOLDER_GENERIC, name, "Created using Evolution/LibMAPI", OPEN_IF_EXISTS | MAPI_UNICODE, &obj_folder);
- if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "CreateFolder", ms);
- goto cleanup;
- }
-
- switch (olFolder) {
- case olFolderInbox:
- type = IPF_NOTE;
- break;
- case olFolderCalendar:
- type = IPF_APPOINTMENT;
- break;
- case olFolderContacts:
- type = IPF_CONTACT;
- break;
- case olFolderTasks:
- type = IPF_TASK;
- break;
- case olFolderNotes:
- type = IPF_STICKYNOTE;
- break;
- default:
- type = IPF_NOTE;
- }
+ g_return_val_if_fail (obj_object != NULL, FALSE);
- vals[0].value.lpszA = type;
- vals[0].ulPropTag = PR_CONTAINER_CLASS;
+ attach_num = e_mapi_util_find_row_propval (srow, PidTagAttachNumber);
+ g_return_val_if_fail (attach_num != NULL, FALSE);
- ms = SetProps (&obj_folder, MAPI_PROPS_SKIP_NAMEDID_CHECK, vals, 1);
+ ms = DeleteAttach (obj_object, *attach_num);
if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "SetProps", ms);
- goto cleanup;
- }
-
- fid = mapi_object_get_id (&obj_folder);
- e_mapi_debug_print("Folder %s created with id %016" G_GINT64_MODIFIER "X ", name, fid);
-
- g_static_rec_mutex_lock (&priv->folders_lock);
-
- /* we should also update folder list locally */
- if (fid != 0 && priv->folders != NULL) {
- EMapiFolder *folder = NULL;
- folder = e_mapi_folder_new (name, type, MAPI_PERSONAL_FOLDER, fid, pfid, 0, 0, 0);
- if (folder)
- priv->folders = g_slist_append (priv->folders, folder);
+ make_mapi_error (perror, "DeleteAttach", ms);
}
- g_static_rec_mutex_unlock (&priv->folders_lock);
-
- cleanup:
- mapi_object_release(&obj_folder);
- mapi_object_release(&obj_top);
-
- UNLOCK ();
-
- e_mapi_debug_print("%s: Leaving %s ", G_STRLOC, G_STRFUNC);
-
- /* Shouldn't we return (EMapiFolder *) instead of a plain fid ? */
- return fid;
+ return ms == MAPI_E_SUCCESS;
}
-gboolean
-e_mapi_connection_empty_folder (EMapiConnection *conn,
- mapi_id_t fid,
- guint32 fid_options,
- GCancellable *cancellable,
- GError **perror)
+static gboolean
+delete_object_attachments (EMapiConnection *conn,
+ mapi_object_t *obj_folder,
+ mapi_object_t *obj_object,
+ TALLOC_CTX *mem_ctx,
+ GCancellable *cancellable,
+ GError **perror)
{
enum MAPISTATUS ms;
- mapi_object_t obj_folder;
- gboolean result = FALSE;
+ mapi_object_t obj_table;
+ struct SPropTagArray *proptags;
CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
- e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
-
- e_mapi_debug_print("%s: Entering %s ", G_STRLOC, G_STRFUNC);
LOCK ();
- mapi_object_init (&obj_folder);
- /* Attempt to open the folder to be emptied */
- ms = open_folder (conn, 0, &fid, fid_options, &obj_folder, perror);
+ mapi_object_init (&obj_table);
+
+ /* open attachment table */
+ ms = GetAttachmentTable (obj_object, &obj_table);
if (ms != MAPI_E_SUCCESS) {
+ make_mapi_error (perror, "GetAttachmentTable", ms);
goto cleanup;
}
- if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
- ms = MAPI_E_USER_CANCEL;
- goto cleanup;
- }
+ proptags = set_SPropTagArray (mem_ctx, 1, PidTagAttachNumber);
- /* Empty the contents of the folder */
- ms = EmptyFolder (&obj_folder);
+ ms = SetColumns (&obj_table, proptags);
if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "EmptyFolder", ms);
+ make_mapi_error (perror, "SetColumns", ms);
goto cleanup;
}
- e_mapi_debug_print("Folder with id %016" G_GINT64_MODIFIER "X was emptied ", fid);
-
- result = TRUE;
+ ms = foreach_tablerow (conn, mem_ctx, &obj_table, delete_attachment_cb, obj_object, cancellable, perror);
+ if (ms != MAPI_E_SUCCESS) {
+ make_mapi_error (perror, "foreach_tablerow", ms);
+ }
cleanup:
- mapi_object_release(&obj_folder);
- UNLOCK ();
+ mapi_object_release (&obj_table);
- e_mapi_debug_print("%s: Leaving %s ", G_STRLOC, G_STRFUNC);
+ UNLOCK ();
- return result;
+ return ms == MAPI_E_SUCCESS;
}
-gboolean
-e_mapi_connection_remove_folder (EMapiConnection *conn,
- mapi_id_t fid,
- guint32 fid_options,
- GCancellable *cancellable,
- GError **perror)
+static gboolean update_message_with_object (EMapiConnection *conn,
+ mapi_object_t *obj_folder,
+ mapi_object_t *obj_message,
+ EMapiObject *object,
+ TALLOC_CTX *mem_ctx,
+ GCancellable *cancellable,
+ GError **perror);
+
+static gboolean
+add_object_attachments (EMapiConnection *conn,
+ mapi_object_t *obj_folder,
+ mapi_object_t *obj_message,
+ EMapiAttachment *attachments,
+ TALLOC_CTX *mem_ctx,
+ GCancellable *cancellable,
+ GError **perror)
{
- enum MAPISTATUS ms;
- mapi_object_t obj_top;
- mapi_object_t obj_folder;
- EMapiFolder *folder;
- gboolean result = FALSE;
- GSList *l;
+ enum MAPISTATUS ms = MAPI_E_SUCCESS;
+ EMapiAttachment *attachment;
CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+ e_return_val_mapi_error_if_fail (obj_folder != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+ e_return_val_mapi_error_if_fail (obj_message != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+ e_return_val_mapi_error_if_fail (mem_ctx != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
- g_return_val_if_fail (fid != 0, FALSE);
+ LOCK ();
- e_mapi_debug_print("%s: Entering %s ", G_STRLOC, G_STRFUNC);
+ for (attachment = attachments; attachment && ms == MAPI_E_SUCCESS; attachment = attachment->next) {
+ mapi_object_t obj_attach;
- folder = NULL;
- for (l = e_mapi_connection_peek_folders_list (conn); l; l = l->next) {
- folder = l->data;
- if (folder && folder->folder_id == fid)
+ if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
+ ms = MAPI_E_USER_CANCEL;
break;
- else
- folder = NULL;
- }
+ }
- e_return_val_mapi_error_if_fail (folder != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+ mapi_object_init (&obj_attach);
- LOCK ();
- mapi_object_init(&obj_top);
- mapi_object_init(&obj_folder);
+ ms = CreateAttach (obj_message, &obj_attach);
+ if (ms != MAPI_E_SUCCESS) {
+ make_mapi_error (perror, "CreateAttach", ms);
+ goto cleanup;
+ }
- /* FIXME: If the folder has sub-folders, open each of them in turn, empty them and delete them.
- * Note that this has to be done recursively, for the sub-folders as well.
- */
+ if (!update_props_on_object (conn, obj_folder, &obj_attach, &attachment->properties, mem_ctx, cancellable, perror)) {
+ ms = MAPI_E_CALL_FAILED;
+ make_mapi_error (perror, "update_props_on_object", ms);
+ goto cleanup;
+ }
- if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
- ms = MAPI_E_USER_CANCEL;
- goto cleanup;
- }
+ if (attachment->embedded_object) {
+ mapi_object_t obj_emb_msg;
- /* Attempt to open the folder to be removed */
- ms = open_folder (conn, 0, &fid, fid_options, &obj_folder, perror);
- if (ms != MAPI_E_SUCCESS) {
- goto cleanup;
- }
+ mapi_object_init (&obj_emb_msg);
- if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
- ms = MAPI_E_USER_CANCEL;
- goto cleanup;
- }
+ ms = OpenEmbeddedMessage (&obj_attach, &obj_emb_msg, MAPI_CREATE);
+ if (ms != MAPI_E_SUCCESS) {
+ make_mapi_error (perror, "OpenEmbeddedMessage", ms);
+ goto cleanup;
+ }
- /* Empty the contents of the folder */
- ms = EmptyFolder (&obj_folder);
- if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "EmptyFolder", ms);
- goto cleanup;
- }
+ if (!update_message_with_object (conn, obj_folder, &obj_emb_msg, attachment->embedded_object, mem_ctx, cancellable, perror)) {
+ ms = MAPI_E_CALL_FAILED;
+ make_mapi_error (perror, "SaveChangesMessage", ms);
+ mapi_object_release (&obj_emb_msg);
+ goto cleanup;
+ }
- e_mapi_debug_print("Folder with id %016" G_GINT64_MODIFIER "X was emptied ", fid);
+ ms = SaveChangesMessage (&obj_attach, &obj_emb_msg, KeepOpenReadOnly);
+ if (ms != MAPI_E_SUCCESS) {
+ make_mapi_error (perror, "SaveChangesMessage", ms);
+ mapi_object_release (&obj_emb_msg);
+ goto cleanup;
+ }
- /* Attempt to open the top/parent folder */
- ms = open_folder (conn, 0, &folder->parent_folder_id, fid_options, &obj_top, perror);
- if (ms != MAPI_E_SUCCESS) {
- goto cleanup;
- }
+ mapi_object_release (&obj_emb_msg);
+ }
- if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
- ms = MAPI_E_USER_CANCEL;
- goto cleanup;
- }
+ ms = SaveChangesAttachment (obj_message, &obj_attach, KeepOpenReadWrite);
+ if (ms != MAPI_E_SUCCESS) {
+ make_mapi_error (perror, "SaveChangesAttachment", ms);
+ goto cleanup;
+ }
- /* Call DeleteFolder on the folder to be removed */
- ms = DeleteFolder (&obj_top, fid, DEL_FOLDERS, NULL);
- if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "DeleteFolder", ms);
- goto cleanup;
+ cleanup:
+ mapi_object_release (&obj_attach);
}
- e_mapi_debug_print("Folder with id %016" G_GINT64_MODIFIER "X was deleted ", fid);
+ UNLOCK ();
- result = TRUE;
+ return ms == MAPI_E_SUCCESS;
+}
- cleanup:
- mapi_object_release(&obj_folder);
- mapi_object_release(&obj_top);
+static gboolean
+update_message_with_object (EMapiConnection *conn,
+ mapi_object_t *obj_folder,
+ mapi_object_t *obj_message,
+ EMapiObject *object,
+ TALLOC_CTX *mem_ctx,
+ GCancellable *cancellable,
+ GError **perror)
+{
+ CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
+ e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+ e_return_val_mapi_error_if_fail (obj_folder != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+ e_return_val_mapi_error_if_fail (obj_message != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+ e_return_val_mapi_error_if_fail (object != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
- g_static_rec_mutex_lock (&priv->folders_lock);
- priv->folders = g_slist_remove (priv->folders, folder);
- g_static_rec_mutex_unlock (&priv->folders_lock);
+ if (!update_props_on_object (conn, obj_folder, obj_message, &object->properties, mem_ctx, cancellable, perror))
+ return FALSE;
- e_mapi_folder_free (folder);
+ if (g_cancellable_set_error_if_cancelled (cancellable, perror))
+ return FALSE;
- UNLOCK ();
+ /* do not touch recipients if not set */
+ if (object->recipients) {
+ /* remove current recipients... */
+ if (!delete_object_recipients (conn, obj_folder, obj_message, mem_ctx, cancellable, perror))
+ return FALSE;
- e_mapi_debug_print("%s: Leaving %s ", G_STRLOC, G_STRFUNC);
+ if (g_cancellable_set_error_if_cancelled (cancellable, perror))
+ return FALSE;
- return result;
+ /* ... and add new */
+ if (!add_object_recipients (conn, obj_folder, obj_message, object->recipients, mem_ctx, cancellable, perror))
+ return FALSE;
+ }
+
+ if (g_cancellable_set_error_if_cancelled (cancellable, perror))
+ return FALSE;
+
+ /* remove current attachments... */
+ if (!delete_object_attachments (conn, obj_folder, obj_message, mem_ctx, cancellable, perror))
+ return FALSE;
+
+ if (g_cancellable_set_error_if_cancelled (cancellable, perror))
+ return FALSE;
+
+ /* ... and add new */
+ if (object->attachments && !add_object_attachments (conn, obj_folder, obj_message, object->attachments, mem_ctx, cancellable, perror))
+ return FALSE;
+
+ if (g_cancellable_set_error_if_cancelled (cancellable, perror))
+ return FALSE;
+
+ return TRUE;
}
gboolean
-e_mapi_connection_rename_folder (EMapiConnection *conn,
- mapi_id_t fid,
- guint32 fid_options,
- const gchar *new_name,
+e_mapi_connection_create_object (EMapiConnection *conn,
+ mapi_object_t *obj_folder,
+ uint32_t flags, /* bit-or of EMapiCreateFlags */
+ WriteObjectCB write_object_cb,
+ gpointer woc_data,
+ mapi_id_t *out_mid,
GCancellable *cancellable,
GError **perror)
{
enum MAPISTATUS ms;
- mapi_object_t obj_folder;
- struct SPropValue *props = NULL;
TALLOC_CTX *mem_ctx;
- gboolean result = FALSE;
+ EMapiObject *object = NULL;
+ mapi_object_t obj_message;
CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+ e_return_val_mapi_error_if_fail (obj_folder != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+ e_return_val_mapi_error_if_fail (write_object_cb != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+ e_return_val_mapi_error_if_fail (out_mid != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
- e_mapi_debug_print("%s: Entering %s ", G_STRLOC, G_STRFUNC);
+ LOCK ();
+
+ *out_mid = 0;
+
+ mem_ctx = talloc_new (priv->session);
+ mapi_object_init (&obj_message);
+
+ if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
+ ms = MAPI_E_USER_CANCEL;
+ goto cleanup;
+ }
+
+ if (!write_object_cb (conn, mem_ctx, &object, woc_data, cancellable, perror) || !object) {
+ ms = MAPI_E_CALL_FAILED;
+ make_mapi_error (perror, "write_object_cb", ms);
+ goto cleanup;
+ }
- LOCK ();
- mem_ctx = talloc_new (priv->session);
- mapi_object_init(&obj_folder);
+ if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
+ ms = MAPI_E_USER_CANCEL;
+ goto cleanup;
+ }
- /* Open the folder to be renamed */
- ms = open_folder (conn, 0, &fid, fid_options, &obj_folder, perror);
+ ms = CreateMessage (obj_folder, &obj_message);
if (ms != MAPI_E_SUCCESS) {
+ make_mapi_error (perror, "CreateMessage", ms);
goto cleanup;
}
@@ -5109,71 +3254,98 @@ e_mapi_connection_rename_folder (EMapiConnection *conn,
goto cleanup;
}
- props = talloc_zero(mem_ctx, struct SPropValue);
- set_SPropValue_proptag (props, PR_DISPLAY_NAME_UNICODE, new_name);
+ if (!update_message_with_object (conn, obj_folder, &obj_message, object, mem_ctx, cancellable, perror)) {
+ ms = MAPI_E_CALL_FAILED;
+ make_mapi_error (perror, "update_message_with_object", ms);
+ goto cleanup;
+ }
- ms = SetProps (&obj_folder, MAPI_PROPS_SKIP_NAMEDID_CHECK, props, 1);
+ if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
+ ms = MAPI_E_USER_CANCEL;
+ goto cleanup;
+ }
+
+ ms = SaveChangesMessage (obj_folder, &obj_message, KeepOpenReadWrite);
if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "SetProps", ms);
+ make_mapi_error (perror, "SaveChangesMessage", ms);
goto cleanup;
}
- result = TRUE;
+ if ((flags & E_MAPI_CREATE_FLAG_SUBMIT) != 0) {
+ /* Mark message as ready to be sent */
+ ms = SubmitMessage (&obj_message);
+ if (ms != MAPI_E_SUCCESS) {
+ mapi_id_t mid;
+ make_mapi_error (perror, "SubmitMessage", ms);
+
+ /*
+ The code is storing message right to Sent items instead of Outbox,
+ because fetching PR_ENTRYID or PR_IPM_SENTMAIL_ENTRYID didn't seem
+ to work in time of doing this change.
+
+ For more information and other possible (correct) approaches see:
+ https://bugzilla.gnome.org/show_bug.cgi?id=561794
+ */
+ mid = mapi_object_get_id (&obj_message);
+
+ mapi_object_release (&obj_message);
+ /* to not release a message object twice */
+ mapi_object_init (&obj_message);
+
+ ms = DeleteMessage (obj_folder, &mid, 1);
+ if (ms != MAPI_E_SUCCESS) {
+ make_mapi_error (perror, "DeleteMessage", ms);
+ }
+
+ goto cleanup;
+ }
+ }
+
+ *out_mid = mapi_object_get_id (&obj_message);
cleanup:
- mapi_object_release(&obj_folder);
- talloc_free(mem_ctx);
- UNLOCK ();
+ e_mapi_object_free (object);
+ mapi_object_release (&obj_message);
+ talloc_free (mem_ctx);
- e_mapi_debug_print("%s: Leaving %s ", G_STRLOC, G_STRFUNC);
+ UNLOCK ();
- return result;
+ return ms == MAPI_E_SUCCESS;
}
-/* moves folder 'src_fid' to folder 'des_fid' under name 'new_name' (no path in a new_name),
- 'src_parent_fid' is folder ID of a parent of the src_fid */
gboolean
-e_mapi_connection_move_folder (EMapiConnection *conn,
- mapi_id_t src_fid,
- mapi_id_t src_parent_fid,
- guint32 src_fid_options,
- mapi_id_t des_fid,
- guint32 des_fid_options,
- const gchar *new_name,
- GCancellable *cancellable,
- GError **perror)
+e_mapi_connection_modify_object (EMapiConnection *conn,
+ mapi_object_t *obj_folder,
+ mapi_id_t mid,
+ WriteObjectCB write_object_cb,
+ gpointer woc_data,
+ GCancellable *cancellable,
+ GError **perror)
{
enum MAPISTATUS ms;
- mapi_object_t obj_src, obj_src_parent, obj_des;
- gboolean result = FALSE;
+ TALLOC_CTX *mem_ctx;
+ EMapiObject *object = NULL;
+ mapi_object_t obj_message;
CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
-
- e_return_val_mapi_error_if_fail (src_fid != 0, MAPI_E_INVALID_PARAMETER, FALSE);
- e_return_val_mapi_error_if_fail (src_parent_fid != 0, MAPI_E_INVALID_PARAMETER, FALSE);
- e_return_val_mapi_error_if_fail (des_fid != 0, MAPI_E_INVALID_PARAMETER, FALSE);
- e_return_val_mapi_error_if_fail (new_name != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
- e_return_val_mapi_error_if_fail (strchr (new_name, '/') == NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+ e_return_val_mapi_error_if_fail (obj_folder != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+ e_return_val_mapi_error_if_fail (write_object_cb != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+ e_return_val_mapi_error_if_fail (mid != 0, MAPI_E_INVALID_PARAMETER, FALSE);
LOCK ();
- mapi_object_init (&obj_src);
- mapi_object_init (&obj_src_parent);
- mapi_object_init (&obj_des);
-
- ms = open_folder (conn, 0, &src_fid, src_fid_options, &obj_src, perror);
- if (ms != MAPI_E_SUCCESS) {
- goto cleanup;
- }
+ mem_ctx = talloc_new (priv->session);
+ mapi_object_init (&obj_message);
if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
ms = MAPI_E_USER_CANCEL;
goto cleanup;
}
- ms = open_folder (conn, 0, &src_parent_fid, src_fid_options, &obj_src_parent, perror);
- if (ms != MAPI_E_SUCCESS) {
+ if (!write_object_cb (conn, mem_ctx, &object, woc_data, cancellable, perror)) {
+ ms = MAPI_E_CALL_FAILED;
+ make_mapi_error (perror, "write_object_cb", ms);
goto cleanup;
}
@@ -5182,8 +3354,9 @@ e_mapi_connection_move_folder (EMapiConnection *conn,
goto cleanup;
}
- ms = open_folder (conn, 0, &des_fid, des_fid_options, &obj_des, perror);
+ ms = OpenMessage (obj_folder, mapi_object_get_id (obj_folder), mid, &obj_message, MAPI_MODIFY);
if (ms != MAPI_E_SUCCESS) {
+ make_mapi_error (perror, "OpenMessage", ms);
goto cleanup;
}
@@ -5192,118 +3365,149 @@ e_mapi_connection_move_folder (EMapiConnection *conn,
goto cleanup;
}
- ms = MoveFolder (&obj_src, &obj_src_parent, &obj_des, (gchar *)new_name, TRUE);
- if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "MoveFolder", ms);
+ if (!update_message_with_object (conn, obj_folder, &obj_message, object, mem_ctx, cancellable, perror)) {
+ ms = MAPI_E_CALL_FAILED;
+ make_mapi_error (perror, "update_message_with_object", ms);
goto cleanup;
}
- result = TRUE;
+ ms = SaveChangesMessage (obj_folder, &obj_message, KeepOpenReadOnly);
+ if (ms != MAPI_E_SUCCESS) {
+ make_mapi_error (perror, "SaveChangesMessage", ms);
+ goto cleanup;
+ }
cleanup:
- mapi_object_release (&obj_des);
- mapi_object_release (&obj_src_parent);
- mapi_object_release (&obj_src);
+ e_mapi_object_free (object);
+ mapi_object_release (&obj_message);
+ talloc_free (mem_ctx);
UNLOCK ();
- return result;
+ return ms == MAPI_E_SUCCESS;
}
-/* named_ids_list contains pointers to ResolveNamedIDsData structure */
-gboolean
-e_mapi_connection_resolve_named_props (EMapiConnection *conn,
- mapi_id_t fid,
- ResolveNamedIDsData *named_ids_list,
- guint named_ids_n_elems,
- GCancellable *cancellable,
- GError **perror)
+mapi_id_t
+e_mapi_connection_create_folder (EMapiConnection *conn,
+ uint32_t olFolder,
+ mapi_id_t pfid,
+ guint32 fid_options,
+ const gchar *name,
+ GCancellable *cancellable,
+ GError **perror)
{
enum MAPISTATUS ms;
- TALLOC_CTX *mem_ctx;
mapi_object_t obj_folder;
- struct mapi_nameid *nameid;
- struct SPropTagArray *SPropTagArray;
- guint i, j;
- GPtrArray *todo = NULL;
- gboolean res = FALSE;
+ mapi_object_t obj_top;
+ struct SPropValue vals[1];
+ const gchar *type;
+ mapi_id_t fid = 0;
- CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
- e_return_val_mapi_error_if_fail (named_ids_list != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
- e_return_val_mapi_error_if_fail (named_ids_n_elems > 0, MAPI_E_INVALID_PARAMETER, FALSE);
- e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+ CHECK_CORRECT_CONN_AND_GET_PRIV (conn, 0);
+ e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, 0);
- e_mapi_debug_print ("%s: Entering %s ", G_STRLOC, G_STRFUNC);
+ e_mapi_debug_print("%s: Entering %s ", G_STRLOC, G_STRFUNC);
LOCK ();
- if (priv->named_ids) {
- gint64 i64 = fid;
- GHashTable *ids = g_hash_table_lookup (priv->named_ids, &i64);
+ mapi_object_init(&obj_top);
+ mapi_object_init(&obj_folder);
- if (ids) {
- for (i = 0; i < named_ids_n_elems; i++) {
- ResolveNamedIDsData *data = &named_ids_list[i];
- uint32_t propid;
+ /* We now open the top/parent folder */
+ ms = open_folder (conn, olFolder, &pfid, fid_options, &obj_top, perror);
+ if (ms != MAPI_E_SUCCESS) {
+ goto cleanup;
+ }
- propid = GPOINTER_TO_UINT (g_hash_table_lookup (ids, GUINT_TO_POINTER (data->pidlid_propid)));
- if (propid) {
- data->propid = propid;
- } else {
- if (!todo)
- todo = g_ptr_array_new ();
- g_ptr_array_add (todo, data);
- }
- }
+ if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
+ ms = MAPI_E_USER_CANCEL;
+ goto cleanup;
+ }
- if (!todo) {
- UNLOCK ();
- e_mapi_debug_print ("%s: Leaving %s ", G_STRLOC, G_STRFUNC);
- return TRUE;
- }
- }
+ /* Attempt to create the folder */
+ ms = CreateFolder (&obj_top, FOLDER_GENERIC, name, "Created using Evolution/LibMAPI", OPEN_IF_EXISTS | MAPI_UNICODE, &obj_folder);
+ if (ms != MAPI_E_SUCCESS) {
+ make_mapi_error (perror, "CreateFolder", ms);
+ goto cleanup;
}
- mem_ctx = talloc_new (priv->session);
- mapi_object_init (&obj_folder);
+ switch (olFolder) {
+ case olFolderInbox:
+ type = IPF_NOTE;
+ break;
+ case olFolderCalendar:
+ type = IPF_APPOINTMENT;
+ break;
+ case olFolderContacts:
+ type = IPF_CONTACT;
+ break;
+ case olFolderTasks:
+ type = IPF_TASK;
+ break;
+ case olFolderNotes:
+ type = IPF_STICKYNOTE;
+ break;
+ default:
+ type = IPF_NOTE;
+ }
+
+ vals[0].value.lpszA = type;
+ vals[0].ulPropTag = PR_CONTAINER_CLASS;
+
+ ms = SetProps (&obj_folder, MAPI_PROPS_SKIP_NAMEDID_CHECK, vals, 1);
+ if (ms != MAPI_E_SUCCESS) {
+ make_mapi_error (perror, "SetProps", ms);
+ goto cleanup;
+ }
+
+ fid = mapi_object_get_id (&obj_folder);
+ e_mapi_debug_print("Folder %s created with id %016" G_GINT64_MODIFIER "X ", name, fid);
+
+ g_static_rec_mutex_lock (&priv->folders_lock);
+
+ /* we should also update folder list locally */
+ if (fid != 0 && priv->folders != NULL) {
+ EMapiFolder *folder = NULL;
+ folder = e_mapi_folder_new (name, type, MAPI_PERSONAL_FOLDER, fid, pfid, 0, 0, 0);
+ if (folder)
+ priv->folders = g_slist_append (priv->folders, folder);
+ }
+
+ g_static_rec_mutex_unlock (&priv->folders_lock);
- nameid = mapi_nameid_new (mem_ctx);
- SPropTagArray = talloc_zero (mem_ctx, struct SPropTagArray);
+ cleanup:
+ mapi_object_release(&obj_folder);
+ mapi_object_release(&obj_top);
- /* Attempt to open the folder */
- ms = open_folder (conn, 0, &fid, 0, &obj_folder, perror);
- if (ms != MAPI_E_SUCCESS) {
- goto cleanup;
- }
+ UNLOCK ();
- if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
- ms = MAPI_E_USER_CANCEL;
- goto cleanup;
- }
+ e_mapi_debug_print("%s: Leaving %s ", G_STRLOC, G_STRFUNC);
- if (!todo) {
- todo = g_ptr_array_new ();
- for (i = 0; i < named_ids_n_elems; i++) {
- g_ptr_array_add (todo, &named_ids_list[i]);
- }
- }
+ /* Shouldn't we return (EMapiFolder *) instead of a plain fid ? */
+ return fid;
+}
- for (i = 0; i < todo->len; i++) {
- ResolveNamedIDsData *data = todo->pdata[i];
+gboolean
+e_mapi_connection_empty_folder (EMapiConnection *conn,
+ mapi_id_t fid,
+ guint32 fid_options,
+ GCancellable *cancellable,
+ GError **perror)
+{
+ enum MAPISTATUS ms;
+ mapi_object_t obj_folder;
+ gboolean result = FALSE;
- if (mapi_nameid_canonical_add (nameid, data->pidlid_propid) != MAPI_E_SUCCESS)
- data->propid = MAPI_E_RESERVED;
- else
- data->propid = 0;
- }
+ CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
+ e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
- if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
- ms = MAPI_E_USER_CANCEL;
- goto cleanup;
- }
+ e_mapi_debug_print("%s: Entering %s ", G_STRLOC, G_STRFUNC);
- ms = mapi_nameid_GetIDsFromNames (nameid, &obj_folder, SPropTagArray);
+ LOCK ();
+ mapi_object_init (&obj_folder);
+
+ /* Attempt to open the folder to be emptied */
+ ms = open_folder (conn, 0, &fid, fid_options, &obj_folder, perror);
if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "mapi_nameid_GetIDsFromNames", ms);
goto cleanup;
}
@@ -5312,103 +3516,73 @@ e_mapi_connection_resolve_named_props (EMapiConnection *conn,
goto cleanup;
}
- for (i = 0, j = 0; i < SPropTagArray->cValues && j < todo->len; i++) {
- while (j < todo->len) {
- ResolveNamedIDsData *data = todo->pdata[j];
- if (data && data->propid == 0) {
- if ((SPropTagArray->aulPropTag[i] & 0xFFFF) == PT_ERROR)
- data->propid = MAPI_E_RESERVED;
- else
- data->propid = SPropTagArray->aulPropTag[i];
- break;
- }
-
- j++;
- }
+ /* Empty the contents of the folder */
+ ms = EmptyFolder (&obj_folder);
+ if (ms != MAPI_E_SUCCESS) {
+ make_mapi_error (perror, "EmptyFolder", ms);
+ goto cleanup;
}
- if (priv->named_ids) {
- gint64 i64 = fid;
- GHashTable *ids = g_hash_table_lookup (priv->named_ids, &i64);
-
- if (!ids) {
- gint64 *i64ptr = g_malloc (sizeof (gint64));
-
- *i64ptr = fid;
- ids = g_hash_table_new (g_direct_hash, g_direct_equal);
-
- g_hash_table_insert (priv->named_ids, i64ptr, ids);
- }
-
- for (i = 0; i < todo->len; i++) {
- ResolveNamedIDsData *data = todo->pdata[i];
-
- g_hash_table_insert (ids, GUINT_TO_POINTER (data->pidlid_propid), GUINT_TO_POINTER (data->propid));
- }
- }
+ e_mapi_debug_print("Folder with id %016" G_GINT64_MODIFIER "X was emptied ", fid);
- res = TRUE;
+ result = TRUE;
cleanup:
- if (todo)
- g_ptr_array_free (todo, TRUE);
- mapi_object_release (&obj_folder);
- talloc_free (mem_ctx);
-
+ mapi_object_release(&obj_folder);
UNLOCK ();
- e_mapi_debug_print ("%s: Leaving %s ", G_STRLOC, G_STRFUNC);
+ e_mapi_debug_print("%s: Leaving %s ", G_STRLOC, G_STRFUNC);
- return res;
+ return result;
}
-/* returns MAPI_E_RESERVED on any error */
-uint32_t
-e_mapi_connection_resolve_named_prop (EMapiConnection *conn,
- mapi_id_t fid,
- uint32_t pidlid_propid,
- GCancellable *cancellable,
- GError **perror)
+gboolean
+e_mapi_connection_remove_folder (EMapiConnection *conn,
+ mapi_id_t fid,
+ guint32 fid_options,
+ GCancellable *cancellable,
+ GError **perror)
{
enum MAPISTATUS ms;
- TALLOC_CTX *mem_ctx;
+ mapi_object_t obj_top;
mapi_object_t obj_folder;
- struct mapi_nameid *nameid;
- struct SPropTagArray *SPropTagArray;
- uint32_t res = MAPI_E_RESERVED;
+ EMapiFolder *folder;
+ gboolean result = FALSE;
+ GSList *l;
- CHECK_CORRECT_CONN_AND_GET_PRIV (conn, res);
- e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, res);
+ CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
+ e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+
+ g_return_val_if_fail (fid != 0, FALSE);
e_mapi_debug_print("%s: Entering %s ", G_STRLOC, G_STRFUNC);
- LOCK ();
+ folder = NULL;
+ for (l = e_mapi_connection_peek_folders_list (conn); l; l = l->next) {
+ folder = l->data;
+ if (folder && folder->folder_id == fid)
+ break;
+ else
+ folder = NULL;
+ }
- if (priv->named_ids) {
- gint64 i64 = fid;
- GHashTable *ids = g_hash_table_lookup (priv->named_ids, &i64);
+ e_return_val_mapi_error_if_fail (folder != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
- if (ids) {
- res = GPOINTER_TO_UINT (g_hash_table_lookup (ids, GUINT_TO_POINTER (pidlid_propid)));
- if (res != 0) {
- UNLOCK ();
- e_mapi_debug_print ("%s: Leaving %s ", G_STRLOC, G_STRFUNC);
+ LOCK ();
+ mapi_object_init(&obj_top);
+ mapi_object_init(&obj_folder);
- return res;
- }
+ /* FIXME: If the folder has sub-folders, open each of them in turn, empty them and delete them.
+ * Note that this has to be done recursively, for the sub-folders as well.
+ */
- res = MAPI_E_RESERVED;
- }
+ if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
+ ms = MAPI_E_USER_CANCEL;
+ goto cleanup;
}
- mem_ctx = talloc_new (priv->session);
- mapi_object_init(&obj_folder);
-
- nameid = mapi_nameid_new(mem_ctx);
- SPropTagArray = talloc_zero(mem_ctx, struct SPropTagArray);
-
- /* Attempt to open the folder */
- ms = open_folder (conn, 0, &fid, 0, &obj_folder, perror);
+ /* Attempt to open the folder to be removed */
+ ms = open_folder (conn, 0, &fid, fid_options, &obj_folder, perror);
if (ms != MAPI_E_SUCCESS) {
goto cleanup;
}
@@ -5418,144 +3592,142 @@ e_mapi_connection_resolve_named_prop (EMapiConnection *conn,
goto cleanup;
}
- mapi_nameid_canonical_add (nameid, pidlid_propid);
-
- ms = mapi_nameid_GetIDsFromNames(nameid, &obj_folder, SPropTagArray);
+ /* Empty the contents of the folder */
+ ms = EmptyFolder (&obj_folder);
if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "mapi_nameid_GetIDsFromNames", ms);
+ make_mapi_error (perror, "EmptyFolder", ms);
goto cleanup;
}
- res = SPropTagArray->aulPropTag[0];
- if ((res & 0xFFFF) == PT_ERROR)
- res = MAPI_E_RESERVED;
+ e_mapi_debug_print("Folder with id %016" G_GINT64_MODIFIER "X was emptied ", fid);
- if (priv->named_ids) {
- gint64 i64 = fid;
- GHashTable *ids = g_hash_table_lookup (priv->named_ids, &i64);
+ /* Attempt to open the top/parent folder */
+ ms = open_folder (conn, 0, &folder->parent_folder_id, fid_options, &obj_top, perror);
+ if (ms != MAPI_E_SUCCESS) {
+ goto cleanup;
+ }
- if (!ids) {
- gint64 *i64ptr = g_malloc (sizeof (gint64));
+ if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
+ ms = MAPI_E_USER_CANCEL;
+ goto cleanup;
+ }
- *i64ptr = fid;
- ids = g_hash_table_new (g_direct_hash, g_direct_equal);
+ /* Call DeleteFolder on the folder to be removed */
+ ms = DeleteFolder (&obj_top, fid, DEL_FOLDERS, NULL);
+ if (ms != MAPI_E_SUCCESS) {
+ make_mapi_error (perror, "DeleteFolder", ms);
+ goto cleanup;
+ }
- g_hash_table_insert (priv->named_ids, i64ptr, ids);
- }
+ e_mapi_debug_print("Folder with id %016" G_GINT64_MODIFIER "X was deleted ", fid);
- g_hash_table_insert (ids, GUINT_TO_POINTER (pidlid_propid), GUINT_TO_POINTER (res));
- }
+ result = TRUE;
cleanup:
mapi_object_release(&obj_folder);
- talloc_free(mem_ctx);
-
- UNLOCK ();
-
- e_mapi_debug_print("%s: Leaving %s ", G_STRLOC, G_STRFUNC);
-
- return res;
-}
-
-/* returns named id, aka PidLid/PidName for a given proptag, which might be previously
- obtained as a result of e_mapi_connection_resolve_named_prop/s.
- Returns MAPI_E_RESERVED when not found.
-*/
-uint32_t
-e_mapi_connection_unresolve_proptag_to_nameid (EMapiConnection *conn, mapi_id_t fid, uint32_t proptag)
-{
- uint32_t res = MAPI_E_RESERVED;
- /* to have this used in the below macros */
- GError **perror = NULL;
+ mapi_object_release(&obj_top);
- CHECK_CORRECT_CONN_AND_GET_PRIV (conn, res);
+ g_static_rec_mutex_lock (&priv->folders_lock);
+ priv->folders = g_slist_remove (priv->folders, folder);
+ g_static_rec_mutex_unlock (&priv->folders_lock);
- if (priv->named_ids) {
- gint64 i64 = fid;
- GHashTable *ids = g_hash_table_lookup (priv->named_ids, &i64);
+ e_mapi_folder_free (folder);
- if (ids) {
- GHashTableIter iter;
- gpointer stored_pidlid, stored_proptag, lookup_proptag = GUINT_TO_POINTER (proptag);
- gboolean is_error = PT_ERROR == (proptag & 0xFFFF);
+ UNLOCK ();
- g_hash_table_iter_init (&iter, ids);
- while (g_hash_table_iter_next (&iter, &stored_pidlid, &stored_proptag)) {
- if (stored_proptag == lookup_proptag || (is_error && (GPOINTER_TO_UINT (stored_proptag) & ~0xFFFF) == (proptag & ~0xFFFF))) {
- res = GPOINTER_TO_UINT (stored_pidlid);
- break;
- }
- }
- }
- }
+ e_mapi_debug_print("%s: Leaving %s ", G_STRLOC, G_STRFUNC);
- return res;
+ return result;
}
-mapi_id_t
-e_mapi_connection_get_default_folder_id (EMapiConnection *conn,
- uint32_t olFolder,
- GCancellable *cancellable,
- GError **perror)
+gboolean
+e_mapi_connection_rename_folder (EMapiConnection *conn,
+ mapi_id_t fid,
+ guint32 fid_options,
+ const gchar *new_name,
+ GCancellable *cancellable,
+ GError **perror)
{
enum MAPISTATUS ms;
- mapi_id_t fid = 0;
+ mapi_object_t obj_folder;
+ struct SPropValue *props = NULL;
+ TALLOC_CTX *mem_ctx;
+ gboolean result = FALSE;
- CHECK_CORRECT_CONN_AND_GET_PRIV (conn, 0);
- e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, 0);
+ CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
+ e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
e_mapi_debug_print("%s: Entering %s ", G_STRLOC, G_STRFUNC);
LOCK ();
+ mem_ctx = talloc_new (priv->session);
+ mapi_object_init(&obj_folder);
- ms = GetDefaultFolder (&priv->msg_store, &fid, olFolder);
+ /* Open the folder to be renamed */
+ ms = open_folder (conn, 0, &fid, fid_options, &obj_folder, perror);
if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "GetDefaultFolder", ms);
goto cleanup;
}
+ if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
+ ms = MAPI_E_USER_CANCEL;
+ goto cleanup;
+ }
+
+ props = talloc_zero(mem_ctx, struct SPropValue);
+ set_SPropValue_proptag (props, PR_DISPLAY_NAME_UNICODE, new_name);
+
+ ms = SetProps (&obj_folder, MAPI_PROPS_SKIP_NAMEDID_CHECK, props, 1);
+ if (ms != MAPI_E_SUCCESS) {
+ make_mapi_error (perror, "SetProps", ms);
+ goto cleanup;
+ }
+
+ result = TRUE;
+
cleanup:
+ mapi_object_release(&obj_folder);
+ talloc_free(mem_ctx);
UNLOCK ();
e_mapi_debug_print("%s: Leaving %s ", G_STRLOC, G_STRFUNC);
- return (ms == MAPI_E_SUCCESS ? fid : 0);
+ return result;
}
-mapi_id_t
-e_mapi_connection_create_item (EMapiConnection *conn,
- uint32_t olFolder,
- mapi_id_t fid,
- BuildWritePropsCB build_props,
- gpointer bwp_data,
- GSList *recipients,
- GSList *attachments,
- GSList *generic_streams,
- uint32_t options,
+/* moves folder 'src_fid' to folder 'des_fid' under name 'new_name' (no path in a new_name),
+ 'src_parent_fid' is folder ID of a parent of the src_fid */
+gboolean
+e_mapi_connection_move_folder (EMapiConnection *conn,
+ mapi_id_t src_fid,
+ mapi_id_t src_parent_fid,
+ guint32 src_fid_options,
+ mapi_id_t des_fid,
+ guint32 des_fid_options,
+ const gchar *new_name,
GCancellable *cancellable,
GError **perror)
{
enum MAPISTATUS ms;
- TALLOC_CTX *mem_ctx;
- mapi_object_t obj_folder;
- mapi_object_t obj_message;
- struct SPropValue *props = NULL;
- uint32_t propslen = 0;
- mapi_id_t mid = 0;
+ mapi_object_t obj_src, obj_src_parent, obj_des;
+ gboolean result = FALSE;
- CHECK_CORRECT_CONN_AND_GET_PRIV (conn, 0);
- e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, 0);
+ CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
+ e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
- e_mapi_debug_print("%s: Entering %s ", G_STRLOC, G_STRFUNC);
+ e_return_val_mapi_error_if_fail (src_fid != 0, MAPI_E_INVALID_PARAMETER, FALSE);
+ e_return_val_mapi_error_if_fail (src_parent_fid != 0, MAPI_E_INVALID_PARAMETER, FALSE);
+ e_return_val_mapi_error_if_fail (des_fid != 0, MAPI_E_INVALID_PARAMETER, FALSE);
+ e_return_val_mapi_error_if_fail (new_name != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+ e_return_val_mapi_error_if_fail (strchr (new_name, '/') == NULL, MAPI_E_INVALID_PARAMETER, FALSE);
LOCK ();
- mem_ctx = talloc_new (priv->session);
- mapi_object_init(&obj_folder);
- mapi_object_init(&obj_message);
+ mapi_object_init (&obj_src);
+ mapi_object_init (&obj_src_parent);
+ mapi_object_init (&obj_des);
- /* Attempt to open the folder */
- ms = open_folder (conn, olFolder, &fid, options, &obj_folder, perror);
+ ms = open_folder (conn, 0, &src_fid, src_fid_options, &obj_src, perror);
if (ms != MAPI_E_SUCCESS) {
goto cleanup;
}
@@ -5565,10 +3737,8 @@ e_mapi_connection_create_item (EMapiConnection *conn,
goto cleanup;
}
- /* Create the item */
- ms = CreateMessage (&obj_folder, &obj_message);
+ ms = open_folder (conn, 0, &src_parent_fid, src_fid_options, &obj_src_parent, perror);
if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "CreateMessage", ms);
goto cleanup;
}
@@ -5577,17 +3747,8 @@ e_mapi_connection_create_item (EMapiConnection *conn,
goto cleanup;
}
- /* Add regular props using callback */
- if (build_props && !build_props (conn, fid, mem_ctx, &props, &propslen, bwp_data, cancellable, perror)) {
- e_mapi_debug_print ("%s: (%s): build_props failed! propslen = %d ", G_STRLOC, G_STRFUNC, propslen);
- make_mapi_error (perror, "build_props", MAPI_E_CALL_FAILED);
- goto cleanup;
- }
-
- /* set properties for the item */
- ms = SetProps (&obj_message, MAPI_PROPS_SKIP_NAMEDID_CHECK, props, propslen);
+ ms = open_folder (conn, 0, &des_fid, des_fid_options, &obj_des, perror);
if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "SetProps", ms);
goto cleanup;
}
@@ -5596,132 +3757,223 @@ e_mapi_connection_create_item (EMapiConnection *conn,
goto cleanup;
}
- if (generic_streams) {
- if (!e_mapi_util_write_generic_streams (&obj_message, generic_streams, perror))
- goto cleanup;
+ ms = MoveFolder (&obj_src, &obj_src_parent, &obj_des, (gchar *)new_name, TRUE);
+ if (ms != MAPI_E_SUCCESS) {
+ make_mapi_error (perror, "MoveFolder", ms);
+ goto cleanup;
+ }
- if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
- ms = MAPI_E_USER_CANCEL;
- goto cleanup;
+ result = TRUE;
+
+ cleanup:
+ mapi_object_release (&obj_des);
+ mapi_object_release (&obj_src_parent);
+ mapi_object_release (&obj_src);
+
+ UNLOCK ();
+
+ return result;
+}
+
+/* named_ids_list contains pointers to ResolveNamedIDsData structure */
+gboolean
+e_mapi_connection_resolve_named_props (EMapiConnection *conn,
+ mapi_id_t fid,
+ ResolveNamedIDsData *named_ids_list,
+ guint named_ids_n_elems,
+ GCancellable *cancellable,
+ GError **perror)
+{
+ enum MAPISTATUS ms;
+ TALLOC_CTX *mem_ctx;
+ mapi_object_t obj_folder;
+ struct mapi_nameid *nameid;
+ struct SPropTagArray *SPropTagArray;
+ guint i, j;
+ GPtrArray *todo = NULL;
+ gboolean res = FALSE;
+
+ CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
+ e_return_val_mapi_error_if_fail (named_ids_list != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+ e_return_val_mapi_error_if_fail (named_ids_n_elems > 0, MAPI_E_INVALID_PARAMETER, FALSE);
+ e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+
+ e_mapi_debug_print ("%s: Entering %s ", G_STRLOC, G_STRFUNC);
+
+ LOCK ();
+ if (priv->named_ids) {
+ gint64 i64 = fid;
+ GHashTable *ids = g_hash_table_lookup (priv->named_ids, &i64);
+
+ if (ids) {
+ for (i = 0; i < named_ids_n_elems; i++) {
+ ResolveNamedIDsData *data = &named_ids_list[i];
+ uint32_t propid;
+
+ propid = GPOINTER_TO_UINT (g_hash_table_lookup (ids, GUINT_TO_POINTER (data->pidlid_propid)));
+ if (propid) {
+ data->propid = propid;
+ } else {
+ if (!todo)
+ todo = g_ptr_array_new ();
+ g_ptr_array_add (todo, data);
+ }
+ }
+
+ if (!todo) {
+ UNLOCK ();
+ e_mapi_debug_print ("%s: Leaving %s ", G_STRLOC, G_STRFUNC);
+ return TRUE;
+ }
}
}
- /* Set attachments if any */
- if (attachments) {
- if (!e_mapi_util_set_attachments (conn, fid, mem_ctx, &obj_message, attachments, FALSE, perror))
- goto cleanup;
+ mem_ctx = talloc_new (priv->session);
+ mapi_object_init (&obj_folder);
- if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
- ms = MAPI_E_USER_CANCEL;
- goto cleanup;
- }
+ nameid = mapi_nameid_new (mem_ctx);
+ SPropTagArray = talloc_zero (mem_ctx, struct SPropTagArray);
+
+ /* Attempt to open the folder */
+ ms = open_folder (conn, 0, &fid, 0, &obj_folder, perror);
+ if (ms != MAPI_E_SUCCESS) {
+ goto cleanup;
}
- /* Set recipients if any */
- if (recipients) {
- if (!e_mapi_util_modify_recipients (conn, mem_ctx, &obj_message, recipients, FALSE, perror))
- goto cleanup;
+ if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
+ ms = MAPI_E_USER_CANCEL;
+ goto cleanup;
+ }
- if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
- ms = MAPI_E_USER_CANCEL;
- goto cleanup;
+ if (!todo) {
+ todo = g_ptr_array_new ();
+ for (i = 0; i < named_ids_n_elems; i++) {
+ g_ptr_array_add (todo, &named_ids_list[i]);
}
}
- /* Finally, save all changes */
- ms = SaveChangesMessage (&obj_folder, &obj_message, KeepOpenReadWrite);
+ for (i = 0; i < todo->len; i++) {
+ ResolveNamedIDsData *data = todo->pdata[i];
+
+ if (mapi_nameid_canonical_add (nameid, data->pidlid_propid) != MAPI_E_SUCCESS)
+ data->propid = MAPI_E_RESERVED;
+ else
+ data->propid = 0;
+ }
+
+ if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
+ ms = MAPI_E_USER_CANCEL;
+ goto cleanup;
+ }
+
+ ms = mapi_nameid_GetIDsFromNames (nameid, &obj_folder, SPropTagArray);
if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "SaveChangesMessage", ms);
+ make_mapi_error (perror, "mapi_nameid_GetIDsFromNames", ms);
goto cleanup;
}
- if (recipients && !(options & MAPI_OPTIONS_DONT_SUBMIT)) {
- if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
- ms = MAPI_E_USER_CANCEL;
- goto cleanup;
+ if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
+ ms = MAPI_E_USER_CANCEL;
+ goto cleanup;
+ }
+
+ for (i = 0, j = 0; i < SPropTagArray->cValues && j < todo->len; i++) {
+ while (j < todo->len) {
+ ResolveNamedIDsData *data = todo->pdata[j];
+ if (data && data->propid == 0) {
+ if ((SPropTagArray->aulPropTag[i] & 0xFFFF) == PT_ERROR)
+ data->propid = MAPI_E_RESERVED;
+ else
+ data->propid = SPropTagArray->aulPropTag[i];
+ break;
+ }
+
+ j++;
}
+ }
- /* Mark message as ready to be sent */
- ms = SubmitMessage (&obj_message);
- if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "SubmitMessage", ms);
+ if (priv->named_ids) {
+ gint64 i64 = fid;
+ GHashTable *ids = g_hash_table_lookup (priv->named_ids, &i64);
- /*
- The code is storing message right to Sent items instead of Outbox,
- because fetching PR_ENTRYID or PR_IPM_SENTMAIL_ENTRYID didn't seem
- to work in time of doing this change.
+ if (!ids) {
+ gint64 *i64ptr = g_malloc (sizeof (gint64));
- For more information and other possible (correct) approaches see:
- https://bugzilla.gnome.org/show_bug.cgi?id=561794
- */
- if ((options & MAPI_OPTIONS_DELETE_ON_SUBMIT_FAILURE) != 0) {
- mid = mapi_object_get_id (&obj_message);
- mapi_object_release(&obj_message);
- /* to not release a message object twice */
- mapi_object_init (&obj_message);
+ *i64ptr = fid;
+ ids = g_hash_table_new (g_direct_hash, g_direct_equal);
- ms = DeleteMessage (&obj_folder, &mid, 1);
- if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "DeleteMessage", ms);
- }
+ g_hash_table_insert (priv->named_ids, i64ptr, ids);
+ }
- /* do not forget to set it back to 0, as the function failed */
- mid = 0;
- }
+ for (i = 0; i < todo->len; i++) {
+ ResolveNamedIDsData *data = todo->pdata[i];
- goto cleanup;
+ g_hash_table_insert (ids, GUINT_TO_POINTER (data->pidlid_propid), GUINT_TO_POINTER (data->propid));
}
}
- mid = mapi_object_get_id (&obj_message);
+ res = TRUE;
cleanup:
- mapi_object_release(&obj_message);
- mapi_object_release(&obj_folder);
- talloc_free(mem_ctx);
+ if (todo)
+ g_ptr_array_free (todo, TRUE);
+ mapi_object_release (&obj_folder);
+ talloc_free (mem_ctx);
UNLOCK ();
- e_mapi_debug_print("%s: Leaving %s ", G_STRLOC, G_STRFUNC);
+ e_mapi_debug_print ("%s: Leaving %s ", G_STRLOC, G_STRFUNC);
- return mid;
+ return res;
}
-gboolean
-e_mapi_connection_modify_item (EMapiConnection *conn,
- uint32_t olFolder,
- mapi_id_t fid,
- mapi_id_t mid,
- BuildWritePropsCB build_props,
- gpointer bwp_data,
- GSList *recipients,
- GSList *attachments,
- GSList *generic_streams,
- uint32_t options,
- GCancellable *cancellable,
- GError **perror)
+/* returns MAPI_E_RESERVED on any error */
+uint32_t
+e_mapi_connection_resolve_named_prop (EMapiConnection *conn,
+ mapi_id_t fid,
+ uint32_t pidlid_propid,
+ GCancellable *cancellable,
+ GError **perror)
{
enum MAPISTATUS ms;
TALLOC_CTX *mem_ctx;
mapi_object_t obj_folder;
- mapi_object_t obj_message;
- struct SPropValue *props = NULL;
- uint32_t propslen = 0;
- gboolean result = FALSE;
+ struct mapi_nameid *nameid;
+ struct SPropTagArray *SPropTagArray;
+ uint32_t res = MAPI_E_RESERVED;
- CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
- e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+ CHECK_CORRECT_CONN_AND_GET_PRIV (conn, res);
+ e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, res);
e_mapi_debug_print("%s: Entering %s ", G_STRLOC, G_STRFUNC);
LOCK ();
+ if (priv->named_ids) {
+ gint64 i64 = fid;
+ GHashTable *ids = g_hash_table_lookup (priv->named_ids, &i64);
+
+ if (ids) {
+ res = GPOINTER_TO_UINT (g_hash_table_lookup (ids, GUINT_TO_POINTER (pidlid_propid)));
+ if (res != 0) {
+ UNLOCK ();
+ e_mapi_debug_print ("%s: Leaving %s ", G_STRLOC, G_STRFUNC);
+
+ return res;
+ }
+
+ res = MAPI_E_RESERVED;
+ }
+ }
+
mem_ctx = talloc_new (priv->session);
mapi_object_init(&obj_folder);
- mapi_object_init(&obj_message);
+
+ nameid = mapi_nameid_new(mem_ctx);
+ SPropTagArray = talloc_zero(mem_ctx, struct SPropTagArray);
/* Attempt to open the folder */
- ms = open_folder (conn, olFolder, &fid, options, &obj_folder, perror);
+ ms = open_folder (conn, 0, &fid, 0, &obj_folder, perror);
if (ms != MAPI_E_SUCCESS) {
goto cleanup;
}
@@ -5731,104 +3983,108 @@ e_mapi_connection_modify_item (EMapiConnection *conn,
goto cleanup;
}
- /* Open the item to be modified */
- ms = OpenMessage (&obj_folder, fid, mid, &obj_message, MAPI_MODIFY);
- if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "OpenMessage", ms);
- goto cleanup;
- }
+ mapi_nameid_canonical_add (nameid, pidlid_propid);
- /* Add regular props using callback */
- if (build_props && !build_props (conn, fid, mem_ctx, &props, &propslen, bwp_data, cancellable, perror)) {
- e_mapi_debug_print ("%s: (%s): Could not build props ", G_STRLOC, G_STRFUNC);
- make_mapi_error (perror, "build_props", MAPI_E_CALL_FAILED);
+ ms = mapi_nameid_GetIDsFromNames(nameid, &obj_folder, SPropTagArray);
+ if (ms != MAPI_E_SUCCESS) {
+ make_mapi_error (perror, "mapi_nameid_GetIDsFromNames", ms);
goto cleanup;
}
- if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
- ms = MAPI_E_USER_CANCEL;
- goto cleanup;
- }
+ res = SPropTagArray->aulPropTag[0];
+ if ((res & 0xFFFF) == PT_ERROR)
+ res = MAPI_E_RESERVED;
- /* set properties for the item */
- ms = SetProps (&obj_message, MAPI_PROPS_SKIP_NAMEDID_CHECK, props, propslen);
- if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "SetProps", ms);
- goto cleanup;
- }
+ if (priv->named_ids) {
+ gint64 i64 = fid;
+ GHashTable *ids = g_hash_table_lookup (priv->named_ids, &i64);
- if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
- ms = MAPI_E_USER_CANCEL;
- goto cleanup;
- }
+ if (!ids) {
+ gint64 *i64ptr = g_malloc (sizeof (gint64));
- if (generic_streams) {
- if (!e_mapi_util_write_generic_streams (&obj_message, generic_streams, perror))
- goto cleanup;
+ *i64ptr = fid;
+ ids = g_hash_table_new (g_direct_hash, g_direct_equal);
- if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
- ms = MAPI_E_USER_CANCEL;
- goto cleanup;
+ g_hash_table_insert (priv->named_ids, i64ptr, ids);
}
+
+ g_hash_table_insert (ids, GUINT_TO_POINTER (pidlid_propid), GUINT_TO_POINTER (res));
}
- /* Set attachments if any */
- if (attachments) {
- if (!e_mapi_util_set_attachments (conn, fid, mem_ctx, &obj_message, attachments, TRUE, perror))
- goto cleanup;
+ cleanup:
+ mapi_object_release(&obj_folder);
+ talloc_free(mem_ctx);
- if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
- ms = MAPI_E_USER_CANCEL;
- goto cleanup;
- }
- } else {
- e_mapi_util_delete_attachments (mem_ctx, &obj_message, NULL);
- }
+ UNLOCK ();
- /* Set recipients if any */
- if (recipients) {
- if (!e_mapi_util_modify_recipients (conn, mem_ctx, &obj_message, recipients, TRUE, perror))
- goto cleanup;
+ e_mapi_debug_print("%s: Leaving %s ", G_STRLOC, G_STRFUNC);
- if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
- ms = MAPI_E_USER_CANCEL;
- goto cleanup;
- }
- }
+ return res;
+}
- /* Finally, save all changes */
- ms = SaveChangesMessage (&obj_folder, &obj_message, KeepOpenReadWrite);
- if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "SaveChangesMessage", ms);
- goto cleanup;
- }
+/* returns named id, aka PidLid/PidName for a given proptag, which might be previously
+ obtained as a result of e_mapi_connection_resolve_named_prop/s.
+ Returns MAPI_E_RESERVED when not found.
+*/
+uint32_t
+e_mapi_connection_unresolve_proptag_to_nameid (EMapiConnection *conn, mapi_id_t fid, uint32_t proptag)
+{
+ uint32_t res = MAPI_E_RESERVED;
+ /* to have this used in the below macros */
+ GError **perror = NULL;
- if (recipients && !(options & MAPI_OPTIONS_DONT_SUBMIT)) {
- if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
- ms = MAPI_E_USER_CANCEL;
- goto cleanup;
- }
+ CHECK_CORRECT_CONN_AND_GET_PRIV (conn, res);
- /* Mark message as ready to be sent */
- ms = SubmitMessage (&obj_message);
- if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "SubmitMessage", ms);
- goto cleanup;
+ if (priv->named_ids) {
+ gint64 i64 = fid;
+ GHashTable *ids = g_hash_table_lookup (priv->named_ids, &i64);
+
+ if (ids) {
+ GHashTableIter iter;
+ gpointer stored_pidlid, stored_proptag, lookup_proptag = GUINT_TO_POINTER (proptag);
+ gboolean is_error = PT_ERROR == (proptag & 0xFFFF);
+
+ g_hash_table_iter_init (&iter, ids);
+ while (g_hash_table_iter_next (&iter, &stored_pidlid, &stored_proptag)) {
+ if (stored_proptag == lookup_proptag || (is_error && (GPOINTER_TO_UINT (stored_proptag) & ~0xFFFF) == (proptag & ~0xFFFF))) {
+ res = GPOINTER_TO_UINT (stored_pidlid);
+ break;
+ }
+ }
}
}
- result = TRUE;
+ return res;
+}
- cleanup:
- mapi_object_release(&obj_message);
- mapi_object_release(&obj_folder);
- talloc_free(mem_ctx);
+mapi_id_t
+e_mapi_connection_get_default_folder_id (EMapiConnection *conn,
+ uint32_t olFolder,
+ GCancellable *cancellable,
+ GError **perror)
+{
+ enum MAPISTATUS ms;
+ mapi_id_t fid = 0;
+
+ CHECK_CORRECT_CONN_AND_GET_PRIV (conn, 0);
+ e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, 0);
+
+ e_mapi_debug_print("%s: Entering %s ", G_STRLOC, G_STRFUNC);
+
+ LOCK ();
+
+ ms = GetDefaultFolder (&priv->msg_store, &fid, olFolder);
+ if (ms != MAPI_E_SUCCESS) {
+ make_mapi_error (perror, "GetDefaultFolder", ms);
+ goto cleanup;
+ }
+ cleanup:
UNLOCK ();
e_mapi_debug_print("%s: Leaving %s ", G_STRLOC, G_STRFUNC);
- return result;
+ return (ms == MAPI_E_SUCCESS ? fid : 0);
}
gboolean
@@ -6022,7 +4278,7 @@ e_mapi_connection_remove_items (EMapiConnection *conn,
uint32_t olFolder,
mapi_id_t fid,
guint32 fid_options,
- GSList *mids,
+ const GSList *mids,
GCancellable *cancellable,
GError **perror)
{
@@ -6031,7 +4287,7 @@ e_mapi_connection_remove_items (EMapiConnection *conn,
mapi_object_t obj_folder;
uint32_t i;
mapi_id_t *id_messages;
- GSList *tmp = mids;
+ const GSList *tmp = mids;
gboolean result = FALSE;
CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
@@ -6044,10 +4300,10 @@ e_mapi_connection_remove_items (EMapiConnection *conn,
mem_ctx = talloc_new (priv->session);
mapi_object_init(&obj_folder);
- id_messages = talloc_array(mem_ctx, mapi_id_t, g_slist_length (mids));
- for (i=0; tmp; tmp=tmp->next, i++) {
- struct id_list *data = tmp->data;
- id_messages[i] = data->id;
+ id_messages = talloc_array(mem_ctx, mapi_id_t, g_slist_length ((GSList *) mids));
+ for (i = 0; tmp; tmp = tmp->next, i++) {
+ mapi_id_t *data = tmp->data;
+ id_messages[i] = *data;
}
/* Attempt to open the folder */
@@ -6092,7 +4348,6 @@ struct GetFolderHierarchyCBData
static gboolean
get_folder_hierarchy_cb (EMapiConnection *conn,
- mapi_id_t fid,
TALLOC_CTX *mem_ctx,
struct SRow *srow,
guint32 row_index,
@@ -6213,7 +4468,7 @@ get_child_folders (EMapiConnection *conn,
gfh.cb = cb;
gfh.cb_user_data = cb_user_data;
- ms = foreach_tablerow (conn, folder_id, mem_ctx, &obj_table, get_folder_hierarchy_cb, &gfh, cancellable, perror);
+ ms = foreach_tablerow (conn, mem_ctx, &obj_table, get_folder_hierarchy_cb, &gfh, cancellable, perror);
cleanup:
talloc_free (spropTagArray);
@@ -7231,3 +5486,149 @@ e_mapi_rename_profile (struct mapi_context *mapi_ctx,
}
/* profile related functions - end */
+
+EMapiRecipient *
+e_mapi_recipient_new (TALLOC_CTX *mem_ctx)
+{
+ EMapiRecipient *recipient;
+
+ recipient = talloc_zero (mem_ctx, EMapiRecipient);
+ g_assert (recipient != NULL);
+
+ recipient->properties.cValues = 0;
+ recipient->properties.lpProps = talloc_zero_array (mem_ctx, struct mapi_SPropValue, 1);
+ recipient->next = NULL;
+
+ g_assert (recipient->properties.lpProps != NULL);
+
+ return recipient;
+}
+
+void
+e_mapi_recipient_free (EMapiRecipient *recipient)
+{
+ if (!recipient)
+ return;
+
+ talloc_free (recipient->properties.lpProps);
+ talloc_free (recipient);
+}
+
+EMapiAttachment *
+e_mapi_attachment_new (TALLOC_CTX *mem_ctx)
+{
+ EMapiAttachment *attachment;
+
+ attachment = talloc_zero (mem_ctx, EMapiAttachment);
+ g_assert (attachment != NULL);
+
+ attachment->properties.cValues = 0;
+ attachment->properties.lpProps = talloc_zero_array (mem_ctx, struct mapi_SPropValue, 1);
+ attachment->embedded_object = NULL;
+ attachment->next = NULL;
+
+ g_assert (attachment->properties.lpProps != NULL);
+
+ return attachment;
+}
+
+void
+e_mapi_attachment_free (EMapiAttachment *attachment)
+{
+ if (!attachment)
+ return;
+
+ e_mapi_object_free (attachment->embedded_object);
+ talloc_free (attachment->properties.lpProps);
+ talloc_free (attachment);
+}
+
+EMapiObject *
+e_mapi_object_new (TALLOC_CTX *mem_ctx)
+{
+ EMapiObject *object;
+
+ object = talloc_zero (mem_ctx, EMapiObject);
+ g_assert (object != NULL);
+
+ object->properties.cValues = 0;
+ object->properties.lpProps = talloc_zero_array (mem_ctx, struct mapi_SPropValue, 1);
+ object->recipients = NULL;
+ object->attachments = NULL;
+ object->parent = NULL;
+
+ g_assert (object->properties.lpProps != NULL);
+
+ return object;
+}
+
+void
+e_mapi_object_free (EMapiObject *object)
+{
+ EMapiRecipient *recipient;
+ EMapiAttachment *attachment;
+
+ if (!object)
+ return;
+
+ recipient = object->recipients;
+ while (recipient) {
+ EMapiRecipient *r = recipient;
+
+ recipient = recipient->next;
+ e_mapi_recipient_free (r);
+ }
+
+ attachment = object->attachments;
+ while (attachment) {
+ EMapiAttachment *a = attachment;
+
+ attachment = attachment->next;
+ e_mapi_attachment_free (a);
+ }
+
+ talloc_free (object->properties.lpProps);
+ talloc_free (object);
+}
+
+void
+e_mapi_object_add_recipient (EMapiObject *object,
+ EMapiRecipient *recipient)
+{
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (recipient != NULL);
+ g_return_if_fail (recipient->next == NULL);
+
+ if (!object->recipients) {
+ object->recipients = recipient;
+ } else {
+ EMapiRecipient *recip = object->recipients;
+
+ while (recip->next) {
+ recip = recip->next;
+ }
+
+ recip->next = recipient;
+ }
+}
+
+void
+e_mapi_object_add_attachment (EMapiObject *object,
+ EMapiAttachment *attachment)
+{
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (attachment != NULL);
+ g_return_if_fail (attachment->next == NULL);
+
+ if (!object->attachments) {
+ object->attachments = attachment;
+ } else {
+ EMapiAttachment *attach = object->attachments;
+
+ while (attach->next) {
+ attach = attach->next;
+ }
+
+ attach->next = attachment;
+ }
+}
diff --git a/src/libexchangemapi/e-mapi-connection.h b/src/libexchangemapi/e-mapi-connection.h
index 5b05942..2c9b6ea 100644
--- a/src/libexchangemapi/e-mapi-connection.h
+++ b/src/libexchangemapi/e-mapi-connection.h
@@ -61,82 +61,6 @@ typedef enum {
MAPI_OPTIONS_DELETE_ON_SUBMIT_FAILURE = 1<<9
} ExchangeMAPIOptions;
-/* Flags for push notification APIs*/
-typedef enum {
- MAPI_EVENTS_USE_STORE = 1<<0,
- MAPI_EVENTS_USE_PF_STORE = 1<<1,
- MAPI_EVENTS_FOLDER = 1<<2,
-} ExchangeMAPIEventsOptions;
-
-#define MAPI_OPTIONS_FETCH_ALL MAPI_OPTIONS_FETCH_ATTACHMENTS | \
- MAPI_OPTIONS_FETCH_RECIPIENTS | \
- MAPI_OPTIONS_FETCH_BODY_STREAM | \
- MAPI_OPTIONS_FETCH_GENERIC_STREAMS
-
-typedef struct {
- GByteArray *value;
- uint32_t proptag;
-} ExchangeMAPIStream;
-
-typedef struct {
- GByteArray *value;
- uint32_t proptag;
- uint32_t editor_format;
-} ExchangeMAPIBodyStream;
-
-typedef struct {
- /* MANDATORY */
- TALLOC_CTX *mem_ctx;
- const gchar *email_id;
- const gchar *display_name;
-
- /* It is ideal to set all these properties on all recipients
- * as we never know if a recipient would be resolved or not. */
- struct {
- /* These are properties which would be set on the
- * recipients regardless if the recipient is resolved or not */
- uint32_t req_cValues;
- struct SPropValue *req_lpProps;
-
- /* These are properties which would be set on the
- * recipients only if the recipient is MAPI_UNRESOLVED */
- uint32_t ext_cValues;
- struct SPropValue *ext_lpProps;
- } in;
-
- /* These are properties which would be set on the
- * recipients after GetRecipientTable() */
- struct SRow out_SRow;
-} ExchangeMAPIRecipient;
-
-struct _MailItem;
-
-typedef struct {
- uint32_t cValues;
- struct SPropValue *lpProps;
- GSList *streams;
- GSList *objects;
- struct _MailItem *mail; /* not NULL when writing mail attachment; in this case are other members ignored */
-} ExchangeMAPIAttachment;
-
-typedef struct {
- EMapiConnection *conn;
- struct mapi_SPropValue_array *properties;
- mapi_id_t fid;
- mapi_id_t mid;
- uint32_t msg_flags; /* used only with fetch_items */
- GSList *attachments;
- GSList *recipients;
- GSList *gallist;
- GSList *streams;
- guint total; /*Total number of results*/
- guint index; /*Index of this Item*/
-} FetchItemsCallbackData;
-
-struct id_list {
- mapi_id_t id;
-};
-
typedef struct {
uint32_t pidlid_propid; /* PidLid or PidName legacy property named ID to resolve */
uint32_t propid; /* resolved prop ID; equals to MAPI_E_RESERVED when not found or other error */
@@ -199,10 +123,6 @@ typedef enum {
} EMapiCreateFlags;
/* callbacks return whether to continue in transfer of the next object */
-typedef gboolean (*FetchCallback) (FetchItemsCallbackData *item_data,
- gpointer data,
- GCancellable *cancellable,
- GError **perror);
typedef gboolean (*FetchGALCallback) (EMapiConnection *conn,
uint32_t row_index,
uint32_t n_rows,
@@ -210,14 +130,6 @@ typedef gboolean (*FetchGALCallback) (EMapiConnection *conn,
gpointer data,
GCancellable *cancellable,
GError **perror);
-typedef gboolean (*BuildWritePropsCB) (EMapiConnection *conn,
- mapi_id_t fid,
- TALLOC_CTX *mem_ctx,
- struct SPropValue **values,
- uint32_t *n_values,
- gpointer data,
- GCancellable *cancellable,
- GError **perror);
typedef gboolean (*BuildReadPropsCB) (EMapiConnection *conn,
mapi_id_t fid,
TALLOC_CTX *mem_ctx,
@@ -226,14 +138,12 @@ typedef gboolean (*BuildReadPropsCB) (EMapiConnection *conn,
GCancellable *cancellable,
GError **perror);
typedef gboolean (*BuildRestrictionsCB) (EMapiConnection *conn,
- mapi_id_t fid,
TALLOC_CTX *mem_ctx,
struct mapi_SRestriction **restrictions,
gpointer user_data,
GCancellable *cancellable,
GError **perror);
typedef gboolean (*ListObjectsCB) (EMapiConnection *conn,
- mapi_id_t fid,
TALLOC_CTX *mem_ctx,
const ListObjectsData *object_data,
guint32 obj_index,
@@ -256,7 +166,6 @@ typedef gboolean (*WriteObjectCB) (EMapiConnection *conn,
GCancellable *cancellable,
GError **perror);
typedef gboolean (*GetFolderPropertiesCB) (EMapiConnection *conn,
- mapi_id_t fid,
TALLOC_CTX *mem_ctx,
/* const */ struct mapi_SPropValue_array *properties,
gpointer user_data,
@@ -376,43 +285,6 @@ gboolean e_mapi_connection_modify_object (EMapiConnection *conn,
GCancellable *cancellable,
GError **perror);
-gboolean e_mapi_connection_fetch_object_props (EMapiConnection *conn,
- mapi_object_t *obj_folder,
- mapi_id_t fid,
- mapi_id_t mid,
- mapi_object_t *obj_message,
- BuildReadPropsCB build_props,
- gpointer brp_data,
- FetchCallback cb,
- gpointer data,
- guint32 options,
- GCancellable *cancellable,
- GError **perror);
-
-gboolean e_mapi_connection_fetch_item (EMapiConnection *conn,
- mapi_id_t fid,
- mapi_id_t mid,
- BuildReadPropsCB build_props,
- gpointer brp_data,
- FetchCallback cb,
- gpointer data,
- guint32 options,
- GCancellable *cancellable,
- GError **perror);
-
-gboolean e_mapi_connection_fetch_items (EMapiConnection *conn,
- mapi_id_t fid,
- BuildRestrictionsCB build_rs_cb,
- gpointer build_rs_cb_data,
- struct SSortOrderSet *sort_order,
- BuildReadPropsCB build_props,
- gpointer brp_data,
- FetchCallback cb,
- gpointer data,
- guint32 options,
- GCancellable *cancellable,
- GError **perror);
-
gboolean e_mapi_connection_fetch_gal (EMapiConnection *conn,
BuildRestrictionsCB build_rs_cb,
gpointer build_rs_cb_data,
@@ -464,30 +336,6 @@ mapi_id_t e_mapi_connection_get_default_folder_id (EMapiConnection *conn,
uint32_t olFolder,
GCancellable *cancellable,
GError **perror);
-mapi_id_t e_mapi_connection_create_item (EMapiConnection *conn,
- uint32_t olFolder,
- mapi_id_t fid,
- BuildWritePropsCB build_props,
- gpointer bwp_data,
- GSList *recipients,
- GSList *attachments,
- GSList *generic_streams,
- uint32_t options,
- GCancellable *cancellable,
- GError **perror);
-
-gboolean e_mapi_connection_modify_item (EMapiConnection *conn,
- uint32_t olFolder,
- mapi_id_t fid,
- mapi_id_t mid,
- BuildWritePropsCB build_props,
- gpointer bwp_data,
- GSList *recipients,
- GSList *attachments,
- GSList *generic_streams,
- uint32_t options,
- GCancellable *cancellable,
- GError **perror);
gboolean e_mapi_connection_set_flags (EMapiConnection *conn,
uint32_t olFolder,
@@ -501,7 +349,7 @@ gboolean e_mapi_connection_remove_items (EMapiConnection *conn,
uint32_t olFolder,
mapi_id_t fid,
guint32 fid_options,
- GSList *mids,
+ const GSList *mids, /* data is (mapi_id_t *) */
GCancellable *cancellable,
GError **perror);
gboolean e_mapi_connection_copy_items (EMapiConnection *conn,
diff --git a/src/libexchangemapi/e-mapi-fast-transfer.c b/src/libexchangemapi/e-mapi-fast-transfer.c
index 1170820..30ba551 100644
--- a/src/libexchangemapi/e-mapi-fast-transfer.c
+++ b/src/libexchangemapi/e-mapi-fast-transfer.c
@@ -58,152 +58,6 @@ struct _EMapiFXParserClosure {
EMapiObject *object;
};
-EMapiRecipient *
-e_mapi_recipient_new (TALLOC_CTX *mem_ctx)
-{
- EMapiRecipient *recipient;
-
- recipient = talloc_zero (mem_ctx, EMapiRecipient);
- g_assert (recipient != NULL);
-
- recipient->properties.cValues = 0;
- recipient->properties.lpProps = talloc_zero_array (mem_ctx, struct mapi_SPropValue, 1);
- recipient->next = NULL;
-
- g_assert (recipient->properties.lpProps != NULL);
-
- return recipient;
-}
-
-void
-e_mapi_recipient_free (EMapiRecipient *recipient)
-{
- if (!recipient)
- return;
-
- talloc_free (recipient->properties.lpProps);
- talloc_free (recipient);
-}
-
-EMapiAttachment *
-e_mapi_attachment_new (TALLOC_CTX *mem_ctx)
-{
- EMapiAttachment *attachment;
-
- attachment = talloc_zero (mem_ctx, EMapiAttachment);
- g_assert (attachment != NULL);
-
- attachment->properties.cValues = 0;
- attachment->properties.lpProps = talloc_zero_array (mem_ctx, struct mapi_SPropValue, 1);
- attachment->embedded_object = NULL;
- attachment->next = NULL;
-
- g_assert (attachment->properties.lpProps != NULL);
-
- return attachment;
-}
-
-void
-e_mapi_attachment_free (EMapiAttachment *attachment)
-{
- if (!attachment)
- return;
-
- e_mapi_object_free (attachment->embedded_object);
- talloc_free (attachment->properties.lpProps);
- talloc_free (attachment);
-}
-
-EMapiObject *
-e_mapi_object_new (TALLOC_CTX *mem_ctx)
-{
- EMapiObject *object;
-
- object = talloc_zero (mem_ctx, EMapiObject);
- g_assert (object != NULL);
-
- object->properties.cValues = 0;
- object->properties.lpProps = talloc_zero_array (mem_ctx, struct mapi_SPropValue, 1);
- object->recipients = NULL;
- object->attachments = NULL;
- object->parent = NULL;
-
- g_assert (object->properties.lpProps != NULL);
-
- return object;
-}
-
-void
-e_mapi_object_free (EMapiObject *object)
-{
- EMapiRecipient *recipient;
- EMapiAttachment *attachment;
-
- if (!object)
- return;
-
- recipient = object->recipients;
- while (recipient) {
- EMapiRecipient *r = recipient;
-
- recipient = recipient->next;
- e_mapi_recipient_free (r);
- }
-
- attachment = object->attachments;
- while (attachment) {
- EMapiAttachment *a = attachment;
-
- attachment = attachment->next;
- e_mapi_attachment_free (a);
- }
-
- talloc_free (object->properties.lpProps);
- talloc_free (object);
-}
-
-void
-e_mapi_object_add_recipient (EMapiObject *object,
- EMapiRecipient *recipient)
-{
- g_return_if_fail (object != NULL);
- g_return_if_fail (recipient != NULL);
- g_return_if_fail (recipient->next == NULL);
-
- if (!object->recipients) {
- object->recipients = recipient;
- } else {
- EMapiRecipient *recip = object->recipients;
-
- while (recip->next) {
- recip = recip->next;
- }
-
- recip->next = recipient;
- }
-}
-
-void
-e_mapi_object_add_attachment (EMapiObject *object,
- EMapiAttachment *attachment)
-{
- g_return_if_fail (object != NULL);
- g_return_if_fail (attachment != NULL);
- g_return_if_fail (attachment->next == NULL);
-
- if (!object->attachments) {
- object->attachments = attachment;
- } else {
- EMapiAttachment *attach = object->attachments;
-
- while (attach->next) {
- attach = attach->next;
- }
-
- attach->next = attachment;
- }
-}
-
static void
e_mapi_object_finish_read (EMapiObject *object)
{
diff --git a/src/libexchangemapi/e-mapi-mail-utils.c b/src/libexchangemapi/e-mapi-mail-utils.c
index a4e5333..5b69940 100644
--- a/src/libexchangemapi/e-mapi-mail-utils.c
+++ b/src/libexchangemapi/e-mapi-mail-utils.c
@@ -34,734 +34,274 @@
extern gint camel_application_is_exiting;
void
-mail_item_free (MailItem *item)
-{
- g_free (item->header.subject);
- g_free (item->header.from);
-
- g_free (item->header.to);
- g_free (item->header.cc);
- g_free (item->header.bcc);
-
- g_free (item->header.references);
- g_free (item->header.message_id);
- g_free (item->header.in_reply_to);
- g_free (item->header.content_class);
- g_free (item->header.transport_headers);
-
- e_mapi_util_free_attachment_list (&item->attachments);
- e_mapi_util_free_stream_list (&item->generic_streams);
- e_mapi_util_free_recipient_list (&item->recipients);
-
- g_free (item->msg_class);
- g_free (item->pid_name_content_type);
-
- g_free (item);
-}
-
-gboolean
-fetch_props_to_mail_item_cb (FetchItemsCallbackData *item_data,
- gpointer data,
- GCancellable *cancellable,
- GError **perror)
+e_mapi_mail_utils_decode_email_address (EMapiConnection *conn,
+ struct mapi_SPropValue_array *properties,
+ const uint32_t *name_proptags,
+ guint name_proptags_len,
+ const uint32_t *smtp_proptags,
+ guint smtp_proptags_len,
+ uint32_t email_type_proptag,
+ uint32_t email_proptag,
+ gchar **name,
+ gchar **email)
{
- long *flags = NULL;
- struct FILETIME *delivery_date = NULL;
- const gchar *msg_class = NULL, *content_class = NULL;
- ExchangeMAPIStream *body = NULL;
- uint32_t content_class_pid;
-
- MailItem *item;
- MailItem **i = (MailItem **)data;
- guint32 j = 0;
-
- g_return_val_if_fail (item_data != NULL, FALSE);
- g_return_val_if_fail (data != NULL, FALSE);
-
- if (camel_debug_start("mapi:folder")) {
- e_mapi_debug_dump_properties (item_data->conn, item_data->fid, item_data->properties, 3);
- camel_debug_end();
- }
-
- content_class_pid = e_mapi_connection_resolve_named_prop (item_data->conn, item_data->fid, PidNameContentClass, cancellable, perror);
- if (content_class_pid == MAPI_E_RESERVED)
- content_class_pid = 0;
-
- item = g_new0 (MailItem , 1);
- item->fid = item_data->fid;
- item->mid = item_data->mid;
-
- /*Hold a reference to Recipient List*/
- item->recipients = item_data->recipients;
-
- for (j = 0; j < item_data->properties->cValues; j++) {
+ gint ii;
+ const gchar *cname = NULL, *cemail = NULL;
+ const gchar *addr_type, *email_addr;
- gconstpointer prop_data = get_mapi_SPropValue_data(&item_data->properties->lpProps[j]);
+ g_return_if_fail (conn != NULL);
+ g_return_if_fail (properties != NULL);
+ g_return_if_fail (name_proptags_len == 0 || name_proptags != NULL);
+ g_return_if_fail (smtp_proptags_len == 0 || smtp_proptags != NULL);
+ g_return_if_fail (name != NULL);
+ g_return_if_fail (email != NULL);
- if (fetch_read_item_common_data (item, item_data->properties->lpProps[j].ulPropTag, prop_data))
- continue;
+ *name = NULL;
+ *email = NULL;
- switch (item_data->properties->lpProps[j].ulPropTag) {
- case PR_MESSAGE_CLASS:
- case PR_MESSAGE_CLASS_UNICODE:
- msg_class = (const gchar *) prop_data;
- break;
- case PR_MESSAGE_DELIVERY_TIME:
- delivery_date = (struct FILETIME *) prop_data;
- break;
- case PR_MESSAGE_FLAGS:
- flags = (long *) prop_data;
- break;
- default:
- if (content_class_pid != 0 && item_data->properties->lpProps[j].ulPropTag == content_class_pid)
- content_class = (const gchar *) prop_data;
- break;
- }
+ for (ii = 0; ii < name_proptags_len && !cname; ii++) {
+ cname = e_mapi_util_find_array_propval (properties, name_proptags[ii]);
}
- item->msg_class = g_strdup (msg_class);
- item->header.content_class = g_strdup (content_class);
-
- item->is_cal = FALSE;
- if (msg_class && g_str_has_prefix (msg_class, IPM_SCHEDULE_MEETING_PREFIX)) {
- guint8 *appointment_body_str = (guint8 *) e_mapi_cal_util_camel_helper (item_data->conn, item_data->fid, item_data->mid, NULL, msg_class,
- item_data->streams, item_data->recipients, item_data->attachments);
-
- if (appointment_body_str && *appointment_body_str) {
- body = g_new0(ExchangeMAPIStream, 1);
- body->proptag = PR_BODY_UNICODE;
- body->value = g_byte_array_new ();
- body->value = g_byte_array_append (body->value, appointment_body_str, strlen ((const gchar *)appointment_body_str));
+ addr_type = e_mapi_util_find_array_propval (properties, email_type_proptag);
+ email_addr = e_mapi_util_find_array_propval (properties, email_proptag);
- item->msg.body_parts = g_slist_append (item->msg.body_parts, body);
- item->is_cal = TRUE;
- }
+ if (addr_type && g_ascii_strcasecmp (addr_type, "SMTP") == 0)
+ cemail = email_addr;
- g_free (appointment_body_str);
+ for (ii = 0; ii < smtp_proptags_len && !cemail; ii++) {
+ cemail = e_mapi_util_find_array_propval (properties, smtp_proptags[ii]);
}
- if (!item->is_cal) {
- /* always prefer unicode version, as that can be properly read */
- if (!(body = e_mapi_util_find_stream (item_data->streams, PR_BODY_UNICODE)))
- body = e_mapi_util_find_stream (item_data->streams, PR_BODY);
-
- if (body)
- item->msg.body_parts = g_slist_append (item->msg.body_parts, body);
-
- body = e_mapi_util_find_stream (item_data->streams, PR_HTML);
- if (body)
- item->msg.body_parts = g_slist_append (item->msg.body_parts, body);
+ if (!cemail && addr_type && g_ascii_strcasecmp (addr_type, "EX") == 0 && email_addr) {
+ *email = e_mapi_connection_ex_to_smtp (conn, email_addr, name, NULL, NULL);
}
- if (delivery_date) {
- item->header.recieved_time = e_mapi_util_filetime_to_time_t (delivery_date);
+ if (!*email) {
+ *name = g_strdup (cname);
+ *email = g_strdup (cemail);
}
-
- if (flags && (*flags & MSGFLAG_READ) != 0)
- item->header.flags |= CAMEL_MESSAGE_SEEN;
- if (flags && (*flags & MSGFLAG_HASATTACH) != 0)
- item->header.flags |= CAMEL_MESSAGE_ATTACHMENTS;
-
- item->attachments = item_data->attachments;
-
- *i = item;
-
- if (camel_application_is_exiting)
- return FALSE;
-
- return TRUE;
}
-gboolean
-fetch_read_item_common_data (MailItem *item, uint32_t propTag, gconstpointer prop_data)
+void
+e_mapi_mail_utils_decode_email_address1 (EMapiConnection *conn,
+ struct mapi_SPropValue_array *properties,
+ uint32_t name_proptag,
+ uint32_t email_proptag,
+ uint32_t email_type_proptag,
+ gchar **name,
+ gchar **email)
{
- gboolean found = TRUE;
-
- #define sv(_x,_y) G_STMT_START { g_free (_x); _x = _y; } G_STMT_END
-
- switch (propTag) {
- case PR_INTERNET_CPID: {
- const uint32_t *ui32 = (const uint32_t *) prop_data;
- if (ui32)
- item->header.cpid = *ui32;
- } break;
- /* FIXME : Instead of duping. Use talloc_steal to reuse the memory */
- case PR_SUBJECT:
- sv (item->header.subject, g_strdup (prop_data));
- break;
- case PR_SUBJECT_UNICODE :
- sv (item->header.subject, g_strdup (prop_data));
- break;
- case PR_DISPLAY_TO :
- sv (item->header.to, g_strdup (prop_data));
- break;
- case PR_DISPLAY_TO_UNICODE :
- sv (item->header.to, g_strdup (prop_data));
- break;
- case PR_DISPLAY_CC:
- sv (item->header.cc, g_strdup (prop_data));
- break;
- case PR_DISPLAY_CC_UNICODE:
- sv (item->header.cc, g_strdup (prop_data));
- break;
- case PR_DISPLAY_BCC:
- sv (item->header.bcc, g_strdup (prop_data));
- break;
- case PR_DISPLAY_BCC_UNICODE:
- sv (item->header.bcc, g_strdup (prop_data));
- break;
- case PR_SENT_REPRESENTING_NAME:
- sv (item->header.from, g_strdup (prop_data));
- break;
- case PR_SENT_REPRESENTING_NAME_UNICODE:
- sv (item->header.from, g_strdup (prop_data));
- break;
- case PR_SENT_REPRESENTING_EMAIL_ADDRESS:
- sv (item->header.from_email, g_strdup (prop_data));
- break;
- case PR_SENT_REPRESENTING_EMAIL_ADDRESS_UNICODE:
- sv (item->header.from_email, g_strdup (prop_data));
- break;
- case PR_SENT_REPRESENTING_ADDRTYPE:
- sv (item->header.from_type, g_strdup (prop_data));
- break;
- case PR_SENT_REPRESENTING_ADDRTYPE_UNICODE:
- sv (item->header.from_type, g_strdup (prop_data));
- break;
- case PR_MESSAGE_SIZE:
- item->header.size = *(glong *)prop_data;
- break;
- case PR_INTERNET_MESSAGE_ID:
- item->header.message_id = g_strdup (prop_data);
- break;
- case PR_INTERNET_REFERENCES:
- item->header.references = g_strdup (prop_data);
- break;
- case PR_IN_REPLY_TO_ID:
- item->header.in_reply_to = g_strdup (prop_data);
- break;
- case PR_TRANSPORT_MESSAGE_HEADERS:
- sv (item->header.transport_headers, g_strdup (prop_data));
- break;
- case PR_TRANSPORT_MESSAGE_HEADERS_UNICODE:
- sv (item->header.transport_headers, g_strdup (prop_data));
- break;
- default:
- found = FALSE;
- break;
- }
+ uint32_t names[1];
- #undef sv
+ names[0] = name_proptag;
- return found;
+ e_mapi_mail_utils_decode_email_address (conn, properties, names, 1, NULL, 0, email_type_proptag, email_proptag, name, email);
}
-gboolean
-mapi_mail_get_item_prop_list (EMapiConnection *conn,
- mapi_id_t fid,
- TALLOC_CTX *mem_ctx,
- struct SPropTagArray *props,
- gpointer data,
- GCancellable *cancellable,
- GError **perror)
+void
+e_mapi_mail_utils_decode_recipients (EMapiConnection *conn,
+ EMapiRecipient *recipients,
+ CamelAddress *to_addr,
+ CamelAddress *cc_addr,
+ CamelAddress *bcc_addr)
{
- static const uint32_t item_props[] = {
- PR_FID,
- PR_MID,
- PR_INTERNET_CPID,
-
- PR_TRANSPORT_MESSAGE_HEADERS_UNICODE,
- PR_MESSAGE_CLASS,
- PR_MESSAGE_SIZE,
- PR_MESSAGE_FLAGS,
- PR_MESSAGE_DELIVERY_TIME,
- PR_MSG_EDITOR_FORMAT,
-
- PR_SUBJECT_UNICODE,
- PR_CONVERSATION_TOPIC_UNICODE,
-
- /*Properties used for message threading.*/
- PR_INTERNET_MESSAGE_ID,
- PR_INTERNET_REFERENCES,
- PR_IN_REPLY_TO_ID,
-
- PR_BODY,
- PR_BODY_UNICODE,
- PR_HTML,
-
- PR_DISPLAY_TO_UNICODE,
- PR_DISPLAY_CC_UNICODE,
- PR_DISPLAY_BCC_UNICODE,
-
- PR_CREATION_TIME,
- PR_LAST_MODIFICATION_TIME,
- PR_PRIORITY,
- PR_SENSITIVITY,
- PR_START_DATE,
- PR_END_DATE,
- PR_RESPONSE_REQUESTED,
- PR_OWNER_APPT_ID,
- PR_PROCESSED,
-
- PR_SENT_REPRESENTING_NAME_UNICODE,
- PR_SENT_REPRESENTING_ADDRTYPE_UNICODE,
- PR_SENT_REPRESENTING_EMAIL_ADDRESS_UNICODE,
-
- PR_SENDER_NAME_UNICODE,
- PR_SENDER_ADDRTYPE_UNICODE,
- PR_SENDER_EMAIL_ADDRESS_UNICODE,
-
- PR_RCVD_REPRESENTING_NAME_UNICODE,
- PR_RCVD_REPRESENTING_ADDRTYPE_UNICODE,
- PR_RCVD_REPRESENTING_EMAIL_ADDRESS_UNICODE
+ const uint32_t name_proptags[] = {
+ PROP_TAG (PT_UNICODE, 0x6001), /* PidTagNickname for Recipients table */
+ PidTagNickname,
+ PidTagDisplayName,
+ PidTagRecipientDisplayName,
+ PidTag7BitDisplayName
};
- /* do not make this array static, the function modifies it on run */
- ResolveNamedIDsData nids[] = {
- { PidNameContentClass, 0 }
+ const uint32_t email_proptags[] = {
+ PidTagPrimarySmtpAddress,
+ PidTagSmtpAddress
};
- g_return_val_if_fail (props != NULL, FALSE);
-
- if (!e_mapi_utils_add_props_to_props_array (mem_ctx, props, item_props, G_N_ELEMENTS (item_props)))
- return FALSE;
-
- return e_mapi_utils_add_named_ids_to_props_array (conn, fid, mem_ctx, props, nids, G_N_ELEMENTS (nids), cancellable, perror);
-}
-
-static gboolean
-name_is_email_user (const gchar *name, const gchar *email_id)
-{
- gint name_len, email_len;
-
- if (!name || !email_id)
- return FALSE;
-
- if (!*name || !*email_id || g_ascii_strcasecmp (email_id, name) == 0)
- return TRUE;
-
- name_len = strlen (name);
- email_len = strlen (email_id);
-
- return name_len < email_len && g_ascii_strncasecmp (email_id, name, name_len) == 0 && email_id[name_len] == '@';
-}
-
-static void
-mapi_mime_set_recipient_list (EMapiConnection *conn, CamelMimeMessage *msg, MailItem *item)
-{
- GSList *l = NULL;
- CamelInternetAddress *to_addr, *cc_addr, *bcc_addr;
-
- if (!item->recipients || item->header.transport_headers)
- return;
-
- to_addr = camel_internet_address_new ();
- cc_addr = camel_internet_address_new ();
- bcc_addr = camel_internet_address_new ();
-
- for (l = item->recipients; l; l=l->next) {
- gchar *display_name = NULL;
- const gchar *name = NULL;
- uint32_t rcpt_type = MAPI_TO;
- uint32_t *type = NULL;
- struct SRow *aRow;
- ExchangeMAPIRecipient *recip = (ExchangeMAPIRecipient *)(l->data);
-
- /* Build a SRow structure */
- aRow = &recip->out_SRow;
-
- /*Name is probably available in one of these props.*/
- name = recip->display_name;
- name = name ? name : e_mapi_util_find_row_propval (aRow, PR_DISPLAY_NAME_UNICODE);
- name = name ? name : e_mapi_util_find_row_propval (aRow, PR_RECIPIENT_DISPLAY_NAME_UNICODE);
- if (!name) {
- name = e_mapi_util_find_row_propval (aRow, PR_7BIT_DISPLAY_NAME_UNICODE);
- if (name && !strchr (name, '@')) {
- gchar *to_free;
-
- to_free = e_mapi_connection_ex_to_smtp (conn, recip->email_id, &display_name, NULL, NULL);
- g_free (to_free);
- }
- }
+ EMapiRecipient *recipient;
- type = (uint32_t *) e_mapi_util_find_row_propval (aRow, PR_RECIPIENT_TYPE);
+ g_return_if_fail (conn != NULL);
+ g_return_if_fail (to_addr != NULL);
+ g_return_if_fail (cc_addr != NULL);
+ g_return_if_fail (bcc_addr != NULL);
- if (!display_name && name && (!recip->email_id || !name_is_email_user (name, recip->email_id)))
- display_name = g_strdup (name);
- rcpt_type = (type ? *type : MAPI_TO);
+ for (recipient = recipients; recipient; recipient = recipient->next) {
+ const uint32_t *recip_type = e_mapi_util_find_array_propval (&recipient->properties, PidTagRecipientType);
+ gchar *name = NULL, *email = NULL;
+ CamelAddress *addr = NULL;
- if (!display_name && (!recip->email_id || !*recip->email_id))
- break;
+ if (!recip_type)
+ continue;
- switch (rcpt_type) {
+ switch (*recip_type) {
case MAPI_TO:
- camel_internet_address_add (to_addr, display_name, recip->email_id ? recip->email_id : "");
+ addr = to_addr;
break;
case MAPI_CC:
- camel_internet_address_add (cc_addr, display_name, recip->email_id ? recip->email_id : "");
+ addr = cc_addr;
break;
case MAPI_BCC:
- camel_internet_address_add (bcc_addr, display_name, recip->email_id ? recip->email_id : "");
+ addr = bcc_addr;
+ break;
+ default:
break;
}
- g_free (display_name);
- }
+ if (!addr)
+ continue;
- if (l != NULL) {
- /* some recipient didn't have set email or
- display name, fallback to PR_DISPLAY_TO/_CC/_BCC */
- camel_address_remove (CAMEL_ADDRESS (to_addr), -1);
- camel_address_remove (CAMEL_ADDRESS (cc_addr), -1);
- camel_address_remove (CAMEL_ADDRESS (bcc_addr), -1);
-
- if (item->header.to && *item->header.to)
- camel_address_decode (CAMEL_ADDRESS (to_addr), item->header.to);
- if (item->header.cc && *item->header.cc)
- camel_address_decode (CAMEL_ADDRESS (cc_addr), item->header.cc);
- if (item->header.bcc && *item->header.bcc)
- camel_address_decode (CAMEL_ADDRESS (bcc_addr), item->header.bcc);
- }
+ e_mapi_mail_utils_decode_email_address (conn, &recipient->properties,
+ name_proptags, G_N_ELEMENTS (name_proptags),
+ email_proptags, G_N_ELEMENTS (email_proptags),
+ PidTagAddressType, PidTagEmailAddress,
+ &name, &email);
- /*Add to message*/
- camel_mime_message_set_recipients (msg, "To", to_addr);
- camel_mime_message_set_recipients (msg, "Cc", cc_addr);
- camel_mime_message_set_recipients (msg, "Bcc", bcc_addr);
+ camel_internet_address_add (CAMEL_INTERNET_ADDRESS (addr), name, email ? email : "");
- g_object_unref (to_addr);
- g_object_unref (cc_addr);
- g_object_unref (bcc_addr);
+ g_free (name);
+ g_free (email);
+ }
}
static void
-mapi_mime_set_msg_headers (EMapiConnection *conn, CamelMimeMessage *msg, MailItem *item)
+build_body_part_content (CamelMimePart *part, EMapiObject *object, uint32_t proptag)
{
- gchar *temp_str = NULL;
- time_t recieved_time;
- CamelInternetAddress *addr = NULL;
- gint offset = 0;
- time_t actual_time;
-
- /* Setting headers from PR_TRANSPORT_MESSAGE_HEADERS */
- if (item->header.transport_headers) {
- CamelMimePart *part = camel_mime_part_new ();
- CamelStream *stream;
- CamelMimeParser *parser;
-
- stream = camel_stream_mem_new_with_buffer (item->header.transport_headers, strlen (item->header.transport_headers));
- parser = camel_mime_parser_new ();
- camel_mime_parser_init_with_stream (parser, stream, NULL);
- camel_mime_parser_scan_from (parser, FALSE);
- g_object_unref (stream);
-
- if (camel_mime_part_construct_from_parser_sync (part, parser, NULL, NULL)) {
- struct _camel_header_raw *h;
-
- for (h = part->headers; h; h = h->next) {
- const gchar *value = h->value;
-
- /* skip all headers describing content of a message,
- because it's overwritten on message decomposition */
- if (g_ascii_strncasecmp (h->name, "Content", 7) == 0)
- continue;
-
- while (value && camel_mime_is_lwsp (*value))
- value++;
-
- camel_medium_add_header (CAMEL_MEDIUM (msg), h->name, value);
- }
- }
-
- g_object_unref (parser);
- g_object_unref (part);
- } else {
- recieved_time = item->header.recieved_time;
- actual_time = camel_header_decode_date (ctime(&recieved_time), &offset);
- camel_mime_message_set_date (msg, actual_time, offset);
- }
-
- if (item->header.content_class)
- camel_medium_add_header (CAMEL_MEDIUM (msg), "Content-class", item->header.content_class);
-
- /* Overwrite headers if we have specific properties available*/
- temp_str = item->header.subject;
- if (temp_str)
- camel_mime_message_set_subject (msg, temp_str);
-
- if (item->header.from) {
- if ((item->header.from_type != NULL) && !g_utf8_collate (item->header.from_type, "EX")) {
- gchar *from_email;
-
- from_email = e_mapi_connection_ex_to_smtp (conn, item->header.from_email, NULL, NULL, NULL);
- g_free (item->header.from_email);
- item->header.from_email = from_email;
- }
-
- item->header.from_email = item->header.from_email ?
- item->header.from_email : item->header.from;
-
- /* add reply to */
- addr = camel_internet_address_new();
- camel_internet_address_add(addr, item->header.from, item->header.from_email);
- camel_mime_message_set_reply_to(msg, addr);
-
- /* add from */
- addr = camel_internet_address_new();
- camel_internet_address_add(addr, item->header.from, item->header.from_email);
- camel_mime_message_set_from(msg, addr);
- }
-
- /* Threading */
- if (item->header.message_id)
- camel_medium_add_header (CAMEL_MEDIUM (msg), "Message-ID", item->header.message_id);
-
- if (item->header.references)
- camel_medium_add_header (CAMEL_MEDIUM (msg), "References", item->header.references);
-
- if (item->header.in_reply_to)
- camel_medium_add_header (CAMEL_MEDIUM (msg), "In-Reply-To", item->header.in_reply_to);
+ gconstpointer value;
-}
+ g_return_if_fail (part != NULL);
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (proptag == PidTagHtml || proptag == PidTagBody);
-static CamelMimePart *
-mapi_mime_msg_body (MailItem *item, const ExchangeMAPIStream *body)
-{
- CamelMimePart *part = camel_mime_part_new ();
camel_mime_part_set_encoding (part, CAMEL_TRANSFER_ENCODING_8BIT);
- if (body && body->value && body->value->len > 0) {
+ value = e_mapi_util_find_array_propval (&object->properties, proptag);
+ if (value) {
const gchar *type = NULL;
- gchar *buff = NULL;
- gboolean strip_last_null;
+ gchar *buff = NULL, *in_utf8;
+ const uint32_t *pcpid = e_mapi_util_find_array_propval (&object->properties, PidTagInternetCodepage);
- if (item->is_cal)
- type = "text/calendar";
- else
- type = (body->proptag == PR_BODY || body->proptag == PR_BODY_UNICODE) ?
- "text/plain" : "text/html";
+ if (proptag == PidTagBody) {
+ type = "text/plain";
+ } else {
+ type = "text/html";
+ }
- if (item->header.cpid && (body->proptag & 0xFFFF) != PT_UNICODE) {
- if (item->header.cpid == 20127)
+ proptag = e_mapi_util_find_array_proptag (&object->properties, proptag);
+ if (pcpid && *pcpid && (proptag & 0xFFFF) != PT_UNICODE) {
+ uint32_t cpid = *pcpid;
+
+ if (cpid == 20127)
buff = g_strdup_printf ("%s; charset=\"us-ascii\"", type);
- else if (item->header.cpid >= 28591 && item->header.cpid <= 28599)
- buff = g_strdup_printf ("%s; charset=\"ISO-8859-%d\"", type, item->header.cpid % 10);
- else if (item->header.cpid == 28603)
+ else if (cpid >= 28591 && cpid <= 28599)
+ buff = g_strdup_printf ("%s; charset=\"ISO-8859-%d\"", type, cpid % 10);
+ else if (cpid == 28603)
buff = g_strdup_printf ("%s; charset=\"ISO-8859-13\"", type);
- else if (item->header.cpid == 28605)
+ else if (cpid == 28605)
buff = g_strdup_printf ("%s; charset=\"ISO-8859-15\"", type);
- else if (item->header.cpid == 65000)
+ else if (cpid == 65000)
buff = g_strdup_printf ("%s; charset=\"UTF-7\"", type);
- else if (item->header.cpid == 65001)
+ else if (cpid == 65001)
buff = g_strdup_printf ("%s; charset=\"UTF-8\"", type);
else
- buff = g_strdup_printf ("%s; charset=\"CP%d\"", type, item->header.cpid);
+ buff = g_strdup_printf ("%s; charset=\"CP%d\"", type, cpid);
type = buff;
}
- strip_last_null = body->value->len > 0 && body->value->data[body->value->len - 1] == '\0';
- camel_mime_part_set_content (part, (const gchar *) body->value->data, body->value->len + (strip_last_null ? -1 : 0), type);
+ in_utf8 = NULL;
+
+ if (proptag == PidTagHtml) {
+ const struct SBinary_short *html_bin = value;
+
+ if (e_mapi_utils_ensure_utf8_string (proptag, pcpid, html_bin->lpb, html_bin->cb, &in_utf8))
+ camel_mime_part_set_content (part, in_utf8, strlen (in_utf8), type);
+ else
+ camel_mime_part_set_content (part, (const gchar *) html_bin->lpb, html_bin->cb, type);
+
+ } else {
+ const gchar *str = value;
+
+ if (e_mapi_utils_ensure_utf8_string (proptag, pcpid, (const guint8 *) str, strlen (str), &in_utf8))
+ str = in_utf8;
+
+ camel_mime_part_set_content (part, str, strlen (str), type);
+ }
+ g_free (in_utf8);
g_free (buff);
} else
camel_mime_part_set_content (part, " ", strlen (" "), "text/plain");
-
- return part;
}
-#if 0
-
-/* GCompareFunc. Used for ordering body types in a GSList.*/
-static gint
-sort_bodies_cb (gconstpointer a, gconstpointer b)
+static gboolean
+is_apple_attach (EMapiAttachment *attach, guint32 *data_len, guint32 *resource_len)
{
- static const gint desired_order[] = { PR_BODY, PR_BODY_UNICODE, PR_HTML };
- const ExchangeMAPIStream *stream_a = a, *stream_b = b;
- gint aidx, bidx;
-
- if (a == b)
- return 0;
- if (!a)
- return -1;
- if (!b)
- return 1;
-
- for (aidx = 0; aidx < G_N_ELEMENTS (desired_order); aidx++) {
- if (desired_order[aidx] == stream_a->proptag)
- break;
- }
+ gboolean is_apple = FALSE;
+ const struct SBinary_short *encoding_bin = e_mapi_util_find_array_propval (&attach->properties, PidTagAttachEncoding);
+ guint8 apple_enc_magic[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x14, 0x03, 0x0B, 0x01 };
- for (bidx = 0; bidx < G_N_ELEMENTS (desired_order); bidx++) {
- if (desired_order[bidx] == stream_b->proptag)
- break;
+ if (encoding_bin && encoding_bin->lpb && encoding_bin->cb == G_N_ELEMENTS (apple_enc_magic)) {
+ gint idx;
+
+ is_apple = TRUE;
+ for (idx = 0; idx < encoding_bin->cb && is_apple; idx++) {
+ is_apple = apple_enc_magic[idx] == encoding_bin->lpb[idx];
+ }
}
- return aidx - bidx;
-}
+ if (is_apple) {
+ /* check boundaries too */
+ const struct SBinary_short *data_bin = e_mapi_util_find_array_propval (&attach->properties, PidTagAttachDataBinary);
-#endif
-
-/* Adds parts to multipart. Convenience function. */
-static void
-mapi_mime_multipart_add_attachments (CamelMultipart *multipart, GSList *attachs)
-{
- CamelMimePart *part;
- while (attachs) {
- part = attachs->data;
- camel_multipart_add_part (multipart, part);
- g_object_unref (part);
- attachs = attachs->next;
- }
-}
-
-/* Process body stream and related objects into a MIME mulitpart */
-static CamelMultipart *
-mapi_mime_build_multipart_related (MailItem *item, const ExchangeMAPIStream *stream,
- GSList *inline_attachs)
-{
- CamelMimePart *part;
- CamelMultipart *m_related = camel_multipart_new ();
- camel_data_wrapper_set_mime_type (CAMEL_DATA_WRAPPER (m_related), "multipart/related");
- camel_multipart_set_boundary (m_related, NULL);
-
- part = mapi_mime_msg_body (item, stream);
- camel_multipart_add_part (m_related, part);
- g_object_unref (part);
-
- mapi_mime_multipart_add_attachments (m_related, inline_attachs);
-
- return m_related;
-}
-
-/* Process multiple body types and pack them in a MIME mulitpart */
-static CamelMultipart *
-mapi_mime_build_multipart_alternative (MailItem *item, GSList *body_parts, GSList *inline_attachs)
-{
- CamelMimePart *part;
- CamelMultipart *m_alternative = camel_multipart_new ();
- camel_data_wrapper_set_mime_type (CAMEL_DATA_WRAPPER (m_alternative),
- "multipart/alternative");
- camel_multipart_set_boundary (m_alternative, NULL);
-
- while (body_parts) {
- const ExchangeMAPIStream *stream = (ExchangeMAPIStream *) body_parts->data;
- part = camel_mime_part_new ();
- if ((stream->proptag == PR_HTML)
- && inline_attachs) {
- CamelMultipart *m_related;
- m_related = mapi_mime_build_multipart_related (item, stream,
- inline_attachs);
- camel_medium_set_content (CAMEL_MEDIUM (part),
- CAMEL_DATA_WRAPPER (m_related));
- g_object_unref (m_related);
- } else
- part = mapi_mime_msg_body (item, stream);
-
- camel_multipart_add_part (m_alternative, part);
- g_object_unref (part);
-
- body_parts = body_parts->next;
- }
-
- return m_alternative;
-}
-
-static CamelMultipart *
-mapi_mime_build_multipart_mixed (CamelMultipart *content, GSList *attachs)
-{
- CamelMimePart *part = camel_mime_part_new ();
- CamelMultipart *m_mixed = camel_multipart_new ();
- camel_data_wrapper_set_mime_type (CAMEL_DATA_WRAPPER (m_mixed),
- "multipart/mixed");
- camel_multipart_set_boundary (m_mixed, NULL);
-
- camel_medium_set_content (CAMEL_MEDIUM (part), CAMEL_DATA_WRAPPER (content));
- camel_multipart_add_part (m_mixed, part);
-
- if (attachs)
- mapi_mime_multipart_add_attachments (m_mixed, attachs);
-
- return m_mixed;
-}
-
-static gboolean
-is_apple_attachment (ExchangeMAPIAttachment *attach, guint32 *data_len, guint32 *resource_len)
-{
- gboolean is_apple = FALSE;
- ExchangeMAPIStream *enc_stream = e_mapi_util_find_stream (attach->streams, PR_ATTACH_ENCODING);
- guint8 apple_enc_magic[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x14, 0x03, 0x0B, 0x01 };
-
- if (enc_stream && enc_stream->value && enc_stream->value->len == G_N_ELEMENTS (apple_enc_magic)) {
- gint idx;
-
- is_apple = TRUE;
- for (idx = 0; idx < enc_stream->value->len && is_apple; idx++) {
- is_apple = apple_enc_magic[idx] == enc_stream->value->data[idx];
- }
- } else {
- const struct Binary_r *bin = e_mapi_util_find_SPropVal_array_propval (attach->lpProps, PR_ATTACH_ENCODING);
- if (bin && bin->cb == G_N_ELEMENTS (apple_enc_magic)) {
- gint idx;
-
- is_apple = TRUE;
- for (idx = 0; idx < bin->cb && is_apple; idx++) {
- is_apple = apple_enc_magic[idx] == bin->lpb[idx];
- }
- }
- }
-
- if (is_apple) {
- /* check boundaries too */
- ExchangeMAPIStream *data_stream = e_mapi_util_find_stream (attach->streams, PR_ATTACH_DATA_BIN);
-
- is_apple = data_stream && data_stream->value && data_stream->value->len > 128;
+ is_apple = data_bin && data_bin->lpb && data_bin->cb > 128;
if (is_apple) {
- const guint8 *bin = data_stream->value->data;
+ const guint8 *bin = data_bin->lpb;
/* in big-endian format */
*data_len = (bin[83] << 24) | (bin[84] << 16) | (bin[85] << 8) | (bin[86]);
*resource_len = (bin[87] << 24) | (bin[88] << 16) | (bin[89] << 8) | (bin[90]);
/* +/- mod 128 (but the first 128 is a header length) */
- is_apple = 128 + *data_len + *resource_len <= data_stream->value->len && bin[1] < 64;
+ is_apple = 128 + *data_len + *resource_len <= data_bin->cb && bin[1] < 64;
}
}
return is_apple;
}
-/*Takes raw attachment streams and converts to MIME Parts. Parts are added to
- either inline / non-inline lists.*/
static void
-mapi_mime_classify_attachments (EMapiConnection *conn, mapi_id_t fid, const gchar *msg_class, GSList *attachments, GSList **inline_attachs, GSList **noninline)
+classify_attachments (EMapiConnection *conn, EMapiAttachment *attachments, const gchar *msg_class, GSList **inline_attachments, GSList **noninline_attachments)
{
- /* SMIME encrypted are without ending dot */
+ EMapiAttachment *attach;
gboolean is_smime = msg_class && strstr (msg_class, ".SMIME.") > msg_class;
- for (;attachments != NULL; attachments = attachments->next) {
- ExchangeMAPIAttachment *attach = (ExchangeMAPIAttachment *)attachments->data;
- ExchangeMAPIStream *stream = NULL;
+ g_return_if_fail (inline_attachments != NULL);
+ g_return_if_fail (noninline_attachments != NULL);
+
+ for (attach = attachments; attach != NULL; attach = attach->next) {
const gchar *filename, *mime_type, *content_id = NULL;
CamelContentType *content_type;
CamelMimePart *part;
const uint32_t *ui32;
+ const struct SBinary_short *data_bin;
gboolean is_apple;
guint32 apple_data_len = 0, apple_resource_len = 0;
- stream = e_mapi_util_find_stream (attach->streams, PR_ATTACH_DATA_BIN);
-
- if (!stream || stream->value->len <= 0) {
+ data_bin = e_mapi_util_find_array_propval (&attach->properties, PidTagAttachDataBinary);
+ if (!data_bin && !attach->embedded_object) {
+ g_debug ("%s: Skipping attachment without data and without embedded object", G_STRFUNC);
continue;
}
- is_apple = is_apple_attachment (attach, &apple_data_len, &apple_resource_len);
+ is_apple = is_apple_attach (attach, &apple_data_len, &apple_resource_len);
- /*Content-Type*/
- ui32 = (const uint32_t *) e_mapi_util_find_SPropVal_array_propval (attach->lpProps, PR_ATTACH_METHOD);
+ /* Content-Type */
+ ui32 = e_mapi_util_find_array_propval (&attach->properties, PidTagAttachMethod);
if (ui32 && *ui32 == ATTACH_EMBEDDED_MSG) {
mime_type = "message/rfc822";
} else {
- mime_type = (const gchar *) e_mapi_util_find_SPropVal_array_propval (attach->lpProps, PR_ATTACH_MIME_TAG);
+ mime_type = e_mapi_util_find_array_propval (&attach->properties, PidTagAttachMimeTag);
if (!mime_type)
mime_type = "application/octet-stream";
}
@@ -774,20 +314,16 @@ mapi_mime_classify_attachments (EMapiConnection *conn, mapi_id_t fid, const gcha
part = camel_mime_part_new ();
- filename = (const gchar *) e_mapi_util_find_SPropVal_array_propval(attach->lpProps,
- PR_ATTACH_LONG_FILENAME_UNICODE);
-
- if (!(filename && *filename))
- filename = (const gchar *) e_mapi_util_find_SPropVal_array_propval(attach->lpProps,
- PR_ATTACH_FILENAME_UNICODE);
+ filename = e_mapi_util_find_array_propval (&attach->properties, PidTagAttachLongFilename);
+ if (!filename || !*filename)
+ filename = e_mapi_util_find_array_propval (&attach->properties, PidTagAttachFilename);
camel_mime_part_set_filename (part, filename);
camel_content_type_set_param (((CamelDataWrapper *) part)->mime_type, "name", filename);
if (is_apple) {
- ExchangeMAPIStream *strm;
CamelMultipart *mp;
- uint32_t proptag;
gchar *apple_filename;
+ const struct SBinary_short *mac_info_bin;
mp = camel_multipart_new ();
camel_data_wrapper_set_mime_type (CAMEL_DATA_WRAPPER (mp), "multipart/appledouble");
@@ -795,15 +331,9 @@ mapi_mime_classify_attachments (EMapiConnection *conn, mapi_id_t fid, const gcha
camel_mime_part_set_encoding (part, CAMEL_TRANSFER_ENCODING_BASE64);
- strm = NULL;
- proptag = e_mapi_connection_resolve_named_prop (conn, fid, PidNameAttachmentMacInfo, NULL, NULL);
- if (proptag != MAPI_E_RESERVED)
- strm = e_mapi_util_find_stream (attach->streams, proptag);
- if (!strm)
- strm = e_mapi_util_find_stream (attach->streams, PidNameAttachmentMacInfo);
-
- if (strm && strm->value && strm->value->len > 0) {
- camel_mime_part_set_content (part, (const gchar *) strm->value->data, strm->value->len, mime_type);
+ mac_info_bin = e_mapi_util_find_array_propval (&attach->properties, PidNameAttachmentMacInfo);
+ if (mac_info_bin && mac_info_bin->lpb && mac_info_bin->cb > 0) {
+ camel_mime_part_set_content (part, (const gchar *) mac_info_bin->lpb, mac_info_bin->cb, mime_type);
} else {
/* RFC 1740 */
guint8 header[] = {
@@ -824,7 +354,7 @@ mapi_mime_classify_attachments (EMapiConnection *conn, mapi_id_t fid, const gcha
header[37] = (apple_resource_len ) & 0xFF;
g_byte_array_append (arr, header, G_N_ELEMENTS (header));
- g_byte_array_append (arr, stream->value->data + 128 + apple_data_len + (apple_data_len % 128), apple_resource_len);
+ g_byte_array_append (arr, data_bin->lpb + 128 + apple_data_len + (apple_data_len % 128), apple_resource_len);
camel_mime_part_set_content (part, (const gchar *) arr->data, arr->len, mime_type);
@@ -836,15 +366,15 @@ mapi_mime_classify_attachments (EMapiConnection *conn, mapi_id_t fid, const gcha
part = camel_mime_part_new ();
- apple_filename = g_strndup ((gchar *)stream->value->data + 2, stream->value->data[1]);
+ apple_filename = g_strndup ((const gchar *) data_bin->lpb + 2, data_bin->lpb[1]);
camel_mime_part_set_filename (part, (apple_filename && *apple_filename) ? apple_filename : filename);
g_free (apple_filename);
- mime_type = e_mapi_util_find_SPropVal_array_namedid (attach->lpProps, conn, fid, PidNameAttachmentMacContentType);
+ mime_type = e_mapi_util_find_array_propval (&attach->properties, PidNameAttachmentMacContentType);
if (!mime_type)
mime_type = "application/octet-stream";
- camel_mime_part_set_content (part, (const gchar *) stream->value->data + 128, apple_data_len, mime_type);
+ camel_mime_part_set_content (part, (const gchar *) data_bin->lpb + 128, apple_data_len, mime_type);
camel_mime_part_set_encoding (part, CAMEL_TRANSFER_ENCODING_BASE64);
camel_multipart_add_part (mp, part);
g_object_unref (part);
@@ -857,7 +387,7 @@ mapi_mime_classify_attachments (EMapiConnection *conn, mapi_id_t fid, const gcha
CamelStream *mem;
mem = camel_stream_mem_new ();
- camel_stream_write (mem, (const gchar *) stream->value->data, stream->value->len, NULL, NULL);
+ camel_stream_write (mem, (const gchar *) data_bin->lpb, data_bin->cb, NULL, NULL);
g_seekable_seek (G_SEEKABLE (mem), 0, G_SEEK_SET, NULL, NULL);
parser = camel_mime_parser_new ();
@@ -881,7 +411,33 @@ mapi_mime_classify_attachments (EMapiConnection *conn, mapi_id_t fid, const gcha
}
if (!is_smime && !is_apple) {
- camel_mime_part_set_content (part, (const gchar *) stream->value->data, stream->value->len, mime_type);
+ if (ui32 && *ui32 == ATTACH_EMBEDDED_MSG && attach->embedded_object) {
+ CamelMimeMessage *embedded_msg;
+
+ embedded_msg = e_mapi_mail_utils_object_to_message (conn, attach->embedded_object);
+ if (embedded_msg) {
+ CamelStream *mem;
+ GByteArray *data;
+
+ data = g_byte_array_new ();
+
+ mem = camel_stream_mem_new ();
+ camel_stream_mem_set_byte_array (CAMEL_STREAM_MEM (mem), data);
+ camel_data_wrapper_write_to_stream_sync (
+ CAMEL_DATA_WRAPPER (embedded_msg), mem, NULL, NULL);
+
+ g_object_unref (mem);
+ g_object_unref (embedded_msg);
+
+ camel_mime_part_set_content (part, (const gchar *) data->data, data->len, mime_type);
+
+ g_byte_array_free (data, TRUE);
+ } else {
+ camel_mime_part_set_content (part, (const gchar *) data_bin->lpb, data_bin->cb, mime_type);
+ }
+ } else {
+ camel_mime_part_set_content (part, (const gchar *) data_bin->lpb, data_bin->cb, mime_type);
+ }
content_type = camel_mime_part_get_content_type (part);
if (content_type && camel_content_type_is (content_type, "text", "*"))
@@ -890,1946 +446,821 @@ mapi_mime_classify_attachments (EMapiConnection *conn, mapi_id_t fid, const gcha
camel_mime_part_set_encoding (part, CAMEL_TRANSFER_ENCODING_BASE64);
}
- /*Content-ID*/
- content_id = (const gchar *) e_mapi_util_find_SPropVal_array_propval(attach->lpProps,
- PR_ATTACH_CONTENT_ID);
+ /* Content-ID */
+ content_id = e_mapi_util_find_array_propval (&attach->properties, PidTagAttachContentId);
+
/* TODO : Add disposition */
if (content_id && !is_apple && !is_smime) {
camel_mime_part_set_content_id (part, content_id);
- *inline_attachs = g_slist_append (*inline_attachs, part);
+ *inline_attachments = g_slist_append (*inline_attachments, part);
} else
- *noninline = g_slist_append (*noninline, part);
+ *noninline_attachments = g_slist_append (*noninline_attachments, part);
}
}
-CamelMimeMessage *
-mapi_mail_item_to_mime_message (EMapiConnection *conn, MailItem *item)
+static void
+add_multipart_attachments (CamelMultipart *multipart, GSList *attachments)
{
- CamelMimeMessage *msg = NULL;
- CamelMultipart *multipart_body = NULL;
+ CamelMimePart *part;
+ while (attachments) {
+ part = attachments->data;
+ camel_multipart_add_part (multipart, part);
+ attachments = attachments->next;
+ }
+}
- GSList *attach_list = NULL;
- GSList *inline_attachs = NULL; /*Used for mulitpart/related*/
- GSList *noninline_attachs = NULL;
+static CamelMultipart *
+build_multipart_related (EMapiObject *object, GSList *inline_attachments)
+{
+ CamelMimePart *part;
+ CamelMultipart *m_related = camel_multipart_new ();
+ camel_data_wrapper_set_mime_type (CAMEL_DATA_WRAPPER (m_related), "multipart/related");
+ camel_multipart_set_boundary (m_related, NULL);
- gboolean build_alternative = FALSE;
- gboolean build_related = FALSE;
- gboolean skip_set_content = FALSE;
+ if (e_mapi_util_find_array_propval (&object->properties, PidTagHtml)) {
+ part = camel_mime_part_new ();
+ build_body_part_content (part, object, PidTagHtml);
+ camel_multipart_add_part (m_related, part);
+ g_object_unref (part);
+ } else if (e_mapi_util_find_array_propval (&object->properties, PidTagBody)) {
+ part = camel_mime_part_new ();
+ build_body_part_content (part, object, PidTagBody);
+ camel_multipart_add_part (m_related, part);
+ g_object_unref (part);
+ }
- g_return_val_if_fail (conn != NULL, NULL);
- g_return_val_if_fail (item != NULL, NULL);
+ add_multipart_attachments (m_related, inline_attachments);
- attach_list = item->attachments;
- msg = camel_mime_message_new ();
+ return m_related;
+}
- mapi_mime_set_recipient_list (conn, msg, item);
- mapi_mime_set_msg_headers (conn, msg, item);
- mapi_mime_classify_attachments (conn, item->fid, item->msg_class, attach_list, &inline_attachs, &noninline_attachs);
+static CamelMultipart *
+build_multipart_alternative (EMapiObject *object, GSList *inline_attachments)
+{
+ CamelMimePart *part;
+ CamelMultipart *m_alternative;
- build_alternative = g_slist_length (item->msg.body_parts) > 1;
- build_related = !build_alternative && inline_attachs;
+ m_alternative = camel_multipart_new ();
+ camel_data_wrapper_set_mime_type (CAMEL_DATA_WRAPPER (m_alternative), "multipart/alternative");
+ camel_multipart_set_boundary (m_alternative, NULL);
- if (build_alternative) {
- multipart_body = mapi_mime_build_multipart_alternative (item, item->msg.body_parts,
- inline_attachs);
- } else if (build_related) {
- multipart_body = mapi_mime_build_multipart_related (item,
- item->msg.body_parts ? item->msg.body_parts->data : NULL,
- inline_attachs);
- } else { /* Simple multipart/mixed */
- CamelMimePart *part;
- multipart_body = camel_multipart_new ();
- camel_data_wrapper_set_mime_type (CAMEL_DATA_WRAPPER (multipart_body),
- "multipart/mixed");
- camel_multipart_set_boundary (multipart_body, NULL);
- part = mapi_mime_msg_body (item, item->msg.body_parts ? item->msg.body_parts->data : NULL);
- camel_multipart_add_part (multipart_body, part);
+ if (e_mapi_util_find_array_propval (&object->properties, PidTagBody)) {
+ part = camel_mime_part_new ();
+ build_body_part_content (part, object, PidTagBody);
+ camel_multipart_add_part (m_alternative, part);
g_object_unref (part);
}
- if (noninline_attachs) { /* multipart/mixed */
- if (build_alternative || build_related) {
- multipart_body = mapi_mime_build_multipart_mixed (multipart_body, noninline_attachs);
- } else if (g_slist_length (noninline_attachs) == 1 && item->msg_class && strstr (item->msg_class, ".SMIME") > item->msg_class) {
- CamelMimePart *part = noninline_attachs->data;
-
- skip_set_content = TRUE;
-
- camel_medium_set_content (CAMEL_MEDIUM (msg), CAMEL_DATA_WRAPPER (part));
+ if (e_mapi_util_find_array_propval (&object->properties, PidTagHtml)) {
+ part = camel_mime_part_new ();
+ if (inline_attachments) {
+ CamelMultipart *m_related;
- if (!strstr (item->msg_class, ".SMIME.")) {
- /* encrypted */
- camel_medium_set_content (CAMEL_MEDIUM (msg), camel_medium_get_content (CAMEL_MEDIUM (part)));
- camel_mime_part_set_encoding (CAMEL_MIME_PART (msg), camel_mime_part_get_encoding (part));
- } else {
- /* signed */
- camel_medium_set_content (CAMEL_MEDIUM (msg), CAMEL_DATA_WRAPPER (part));
- }
+ m_related = build_multipart_related (object, inline_attachments);
+ camel_medium_set_content (CAMEL_MEDIUM (part), CAMEL_DATA_WRAPPER (m_related));
+ g_object_unref (m_related);
} else {
- mapi_mime_multipart_add_attachments (multipart_body, noninline_attachs);
+ build_body_part_content (part, object, PidTagHtml);
}
+ camel_multipart_add_part (m_alternative, part);
+ g_object_unref (part);
}
- if (!skip_set_content)
- camel_medium_set_content (CAMEL_MEDIUM (msg), CAMEL_DATA_WRAPPER(multipart_body));
-
- g_object_unref (multipart_body);
- g_slist_free (inline_attachs);
- g_slist_free (noninline_attachs);
-
- return msg;
+ return m_alternative;
}
-void
-e_mapi_mail_utils_decode_email_address (EMapiConnection *conn,
- struct mapi_SPropValue_array *properties,
- const uint32_t *name_proptags,
- guint name_proptags_len,
- const uint32_t *smtp_proptags,
- guint smtp_proptags_len,
- uint32_t email_type_proptag,
- uint32_t email_proptag,
- gchar **name,
- gchar **email)
+static CamelMultipart *
+build_multipart_mixed (CamelMultipart *content, GSList *attachments)
{
- gint ii;
- const gchar *cname = NULL, *cemail = NULL;
- const gchar *addr_type, *email_addr;
-
- g_return_if_fail (conn != NULL);
- g_return_if_fail (properties != NULL);
- g_return_if_fail (name_proptags_len == 0 || name_proptags != NULL);
- g_return_if_fail (smtp_proptags_len == 0 || smtp_proptags != NULL);
- g_return_if_fail (name != NULL);
- g_return_if_fail (email != NULL);
-
- *name = NULL;
- *email = NULL;
+ CamelMimePart *part = camel_mime_part_new ();
+ CamelMultipart *m_mixed = camel_multipart_new ();
+ camel_data_wrapper_set_mime_type (CAMEL_DATA_WRAPPER (m_mixed), "multipart/mixed");
+ camel_multipart_set_boundary (m_mixed, NULL);
- for (ii = 0; ii < name_proptags_len && !cname; ii++) {
- cname = e_mapi_util_find_array_propval (properties, name_proptags[ii]);
- }
+ camel_medium_set_content (CAMEL_MEDIUM (part), CAMEL_DATA_WRAPPER (content));
+ camel_multipart_add_part (m_mixed, part);
+ g_object_unref (part);
- addr_type = e_mapi_util_find_array_propval (properties, email_type_proptag);
- email_addr = e_mapi_util_find_array_propval (properties, email_proptag);
+ add_multipart_attachments (m_mixed, attachments);
- if (addr_type && g_ascii_strcasecmp (addr_type, "SMTP") == 0)
- cemail = email_addr;
+ return m_mixed;
+}
- for (ii = 0; ii < smtp_proptags_len && !cemail; ii++) {
- cemail = e_mapi_util_find_array_propval (properties, smtp_proptags[ii]);
- }
-
- if (!cemail && addr_type && g_ascii_strcasecmp (addr_type, "EX") == 0 && email_addr) {
- *email = e_mapi_connection_ex_to_smtp (conn, email_addr, name, NULL, NULL);
- }
-
- if (!*email) {
- *name = g_strdup (cname);
- *email = g_strdup (cemail);
- }
-}
-
-void
-e_mapi_mail_utils_decode_email_address1 (EMapiConnection *conn,
- struct mapi_SPropValue_array *properties,
- uint32_t name_proptag,
- uint32_t email_proptag,
- uint32_t email_type_proptag,
- gchar **name,
- gchar **email)
-{
- uint32_t names[1];
-
- names[0] = name_proptag;
-
- e_mapi_mail_utils_decode_email_address (conn, properties, names, 1, NULL, 0, email_type_proptag, email_proptag, name, email);
-}
-
-void
-e_mapi_mail_utils_decode_recipients (EMapiConnection *conn,
- EMapiRecipient *recipients,
- CamelAddress *to_addr,
- CamelAddress *cc_addr,
- CamelAddress *bcc_addr)
-{
- const uint32_t name_proptags[] = {
- PROP_TAG (PT_UNICODE, 0x6001), /* PidTagNickname for Recipients table */
- PidTagNickname,
- PidTagDisplayName,
- PidTagRecipientDisplayName,
- PidTag7BitDisplayName
- };
-
- const uint32_t email_proptags[] = {
- PidTagPrimarySmtpAddress,
- PidTagSmtpAddress
- };
-
- EMapiRecipient *recipient;
-
- g_return_if_fail (conn != NULL);
- g_return_if_fail (to_addr != NULL);
- g_return_if_fail (cc_addr != NULL);
- g_return_if_fail (bcc_addr != NULL);
-
- for (recipient = recipients; recipient; recipient = recipient->next) {
- const uint32_t *recip_type = e_mapi_util_find_array_propval (&recipient->properties, PidTagRecipientType);
- gchar *name = NULL, *email = NULL;
- CamelAddress *addr = NULL;
-
- if (!recip_type)
- continue;
-
- switch (*recip_type) {
- case MAPI_TO:
- addr = to_addr;
- break;
- case MAPI_CC:
- addr = cc_addr;
- break;
- case MAPI_BCC:
- addr = bcc_addr;
- break;
- default:
- break;
- }
-
- if (!addr)
- continue;
-
- e_mapi_mail_utils_decode_email_address (conn, &recipient->properties,
- name_proptags, G_N_ELEMENTS (name_proptags),
- email_proptags, G_N_ELEMENTS (email_proptags),
- PidTagAddressType, PidTagEmailAddress,
- &name, &email);
-
- camel_internet_address_add (CAMEL_INTERNET_ADDRESS (addr), name, email ? email : "");
-
- g_free (name);
- g_free (email);
- }
-}
-
-static void
-build_body_part_content (CamelMimePart *part, EMapiObject *object, uint32_t proptag)
-{
- gconstpointer value;
-
- g_return_if_fail (part != NULL);
- g_return_if_fail (object != NULL);
- g_return_if_fail (proptag == PidTagHtml || proptag == PidTagBody);
-
- camel_mime_part_set_encoding (part, CAMEL_TRANSFER_ENCODING_8BIT);
-
- value = e_mapi_util_find_array_propval (&object->properties, proptag);
- if (value) {
- const gchar *type = NULL;
- gchar *buff = NULL, *in_utf8;
- const uint32_t *pcpid = e_mapi_util_find_array_propval (&object->properties, PidTagInternetCodepage);
-
- if (proptag == PidTagBody) {
- type = "text/plain";
- } else {
- type = "text/html";
- }
-
- proptag = e_mapi_util_find_array_proptag (&object->properties, proptag);
- if (pcpid && *pcpid && (proptag & 0xFFFF) != PT_UNICODE) {
- uint32_t cpid = *pcpid;
-
- if (cpid == 20127)
- buff = g_strdup_printf ("%s; charset=\"us-ascii\"", type);
- else if (cpid >= 28591 && cpid <= 28599)
- buff = g_strdup_printf ("%s; charset=\"ISO-8859-%d\"", type, cpid % 10);
- else if (cpid == 28603)
- buff = g_strdup_printf ("%s; charset=\"ISO-8859-13\"", type);
- else if (cpid == 28605)
- buff = g_strdup_printf ("%s; charset=\"ISO-8859-15\"", type);
- else if (cpid == 65000)
- buff = g_strdup_printf ("%s; charset=\"UTF-7\"", type);
- else if (cpid == 65001)
- buff = g_strdup_printf ("%s; charset=\"UTF-8\"", type);
- else
- buff = g_strdup_printf ("%s; charset=\"CP%d\"", type, cpid);
- type = buff;
- }
-
- in_utf8 = NULL;
-
- if (proptag == PidTagHtml) {
- const struct SBinary_short *html_bin = value;
-
- if (e_mapi_utils_ensure_utf8_string (proptag, pcpid, html_bin->lpb, html_bin->cb, &in_utf8))
- camel_mime_part_set_content (part, in_utf8, strlen (in_utf8), type);
- else
- camel_mime_part_set_content (part, (const gchar *) html_bin->lpb, html_bin->cb, type);
-
- } else {
- const gchar *str = value;
-
- if (e_mapi_utils_ensure_utf8_string (proptag, pcpid, (const guint8 *) str, strlen (str), &in_utf8))
- str = in_utf8;
-
- camel_mime_part_set_content (part, str, strlen (str), type);
- }
-
- g_free (in_utf8);
- g_free (buff);
- } else
- camel_mime_part_set_content (part, " ", strlen (" "), "text/plain");
-}
-
-static gboolean
-is_apple_attach (EMapiAttachment *attach, guint32 *data_len, guint32 *resource_len)
-{
- gboolean is_apple = FALSE;
- const struct SBinary_short *encoding_bin = e_mapi_util_find_array_propval (&attach->properties, PidTagAttachEncoding);
- guint8 apple_enc_magic[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x14, 0x03, 0x0B, 0x01 };
-
- if (encoding_bin && encoding_bin->lpb && encoding_bin->cb == G_N_ELEMENTS (apple_enc_magic)) {
- gint idx;
-
- is_apple = TRUE;
- for (idx = 0; idx < encoding_bin->cb && is_apple; idx++) {
- is_apple = apple_enc_magic[idx] == encoding_bin->lpb[idx];
- }
- }
-
- if (is_apple) {
- /* check boundaries too */
- const struct SBinary_short *data_bin = e_mapi_util_find_array_propval (&attach->properties, PidTagAttachDataBinary);
-
- is_apple = data_bin && data_bin->lpb && data_bin->cb > 128;
-
- if (is_apple) {
- const guint8 *bin = data_bin->lpb;
-
- /* in big-endian format */
- *data_len = (bin[83] << 24) | (bin[84] << 16) | (bin[85] << 8) | (bin[86]);
- *resource_len = (bin[87] << 24) | (bin[88] << 16) | (bin[89] << 8) | (bin[90]);
-
- /* +/- mod 128 (but the first 128 is a header length) */
- is_apple = 128 + *data_len + *resource_len <= data_bin->cb && bin[1] < 64;
- }
- }
-
- return is_apple;
-}
-
-static void
-classify_attachments (EMapiConnection *conn, EMapiAttachment *attachments, const gchar *msg_class, GSList **inline_attachments, GSList **noninline_attachments)
-{
- EMapiAttachment *attach;
- gboolean is_smime = msg_class && strstr (msg_class, ".SMIME.") > msg_class;
-
- g_return_if_fail (inline_attachments != NULL);
- g_return_if_fail (noninline_attachments != NULL);
-
- for (attach = attachments; attach != NULL; attach = attach->next) {
- const gchar *filename, *mime_type, *content_id = NULL;
- CamelContentType *content_type;
- CamelMimePart *part;
- const uint32_t *ui32;
- const struct SBinary_short *data_bin;
- gboolean is_apple;
- guint32 apple_data_len = 0, apple_resource_len = 0;
-
- data_bin = e_mapi_util_find_array_propval (&attach->properties, PidTagAttachDataBinary);
- if (!data_bin && !attach->embedded_object) {
- g_debug ("%s: Skipping attachment without data and without embedded object", G_STRFUNC);
- continue;
- }
-
- is_apple = is_apple_attach (attach, &apple_data_len, &apple_resource_len);
-
- /* Content-Type */
- ui32 = e_mapi_util_find_array_propval (&attach->properties, PidTagAttachMethod);
- if (ui32 && *ui32 == ATTACH_EMBEDDED_MSG) {
- mime_type = "message/rfc822";
- } else {
- mime_type = e_mapi_util_find_array_propval (&attach->properties, PidTagAttachMimeTag);
- if (!mime_type)
- mime_type = "application/octet-stream";
- }
-
- if (is_apple) {
- mime_type = "application/applefile";
- } else if (strstr (mime_type, "apple") != NULL) {
- mime_type = "application/octet-stream";
- }
-
- part = camel_mime_part_new ();
-
- filename = e_mapi_util_find_array_propval (&attach->properties, PidTagAttachLongFilename);
- if (!filename || !*filename)
- filename = e_mapi_util_find_array_propval (&attach->properties, PidTagAttachFilename);
- camel_mime_part_set_filename (part, filename);
- camel_content_type_set_param (((CamelDataWrapper *) part)->mime_type, "name", filename);
-
- if (is_apple) {
- CamelMultipart *mp;
- gchar *apple_filename;
- const struct SBinary_short *mac_info_bin;
-
- mp = camel_multipart_new ();
- camel_data_wrapper_set_mime_type (CAMEL_DATA_WRAPPER (mp), "multipart/appledouble");
- camel_multipart_set_boundary (mp, NULL);
-
- camel_mime_part_set_encoding (part, CAMEL_TRANSFER_ENCODING_BASE64);
-
- mac_info_bin = e_mapi_util_find_array_propval (&attach->properties, PidNameAttachmentMacInfo);
- if (mac_info_bin && mac_info_bin->lpb && mac_info_bin->cb > 0) {
- camel_mime_part_set_content (part, (const gchar *) mac_info_bin->lpb, mac_info_bin->cb, mime_type);
- } else {
- /* RFC 1740 */
- guint8 header[] = {
- 0x00, 0x05, 0x16, 0x07, /* magic */
- 0x00, 0x02, 0x00, 0x00, /* version */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* filler */
- 0x00, 0x01, /* number of entries */
- 0x00, 0x00, 0x00, 0x02, /* entry ID - resource fork */
- 0x00, 0x00, 0x00, 0x26, /* entry offset - 38th byte*/
- 0x00, 0x00, 0x00, 0x00 /* entry length */
- };
-
- GByteArray *arr = g_byte_array_sized_new (apple_resource_len + G_N_ELEMENTS (header));
-
- header[34] = (apple_resource_len >> 24) & 0xFF;
- header[35] = (apple_resource_len >> 16) & 0xFF;
- header[36] = (apple_resource_len >> 8) & 0xFF;
- header[37] = (apple_resource_len ) & 0xFF;
-
- g_byte_array_append (arr, header, G_N_ELEMENTS (header));
- g_byte_array_append (arr, data_bin->lpb + 128 + apple_data_len + (apple_data_len % 128), apple_resource_len);
-
- camel_mime_part_set_content (part, (const gchar *) arr->data, arr->len, mime_type);
-
- g_byte_array_free (arr, TRUE);
- }
-
- camel_multipart_add_part (mp, part);
- g_object_unref (part);
-
- part = camel_mime_part_new ();
-
- apple_filename = g_strndup ((const gchar *) data_bin->lpb + 2, data_bin->lpb[1]);
- camel_mime_part_set_filename (part, (apple_filename && *apple_filename) ? apple_filename : filename);
- g_free (apple_filename);
-
- mime_type = e_mapi_util_find_array_propval (&attach->properties, PidNameAttachmentMacContentType);
- if (!mime_type)
- mime_type = "application/octet-stream";
-
- camel_mime_part_set_content (part, (const gchar *) data_bin->lpb + 128, apple_data_len, mime_type);
- camel_mime_part_set_encoding (part, CAMEL_TRANSFER_ENCODING_BASE64);
- camel_multipart_add_part (mp, part);
- g_object_unref (part);
-
- part = camel_mime_part_new ();
- camel_medium_set_content (CAMEL_MEDIUM (part), CAMEL_DATA_WRAPPER (mp));
- g_object_unref (mp);
- } else if (is_smime) {
- CamelMimeParser *parser;
- CamelStream *mem;
-
- mem = camel_stream_mem_new ();
- camel_stream_write (mem, (const gchar *) data_bin->lpb, data_bin->cb, NULL, NULL);
- g_seekable_seek (G_SEEKABLE (mem), 0, G_SEEK_SET, NULL, NULL);
-
- parser = camel_mime_parser_new ();
- camel_mime_parser_scan_from (parser, FALSE);
- camel_mime_parser_scan_pre_from (parser, FALSE);
- camel_mime_parser_init_with_stream (parser, mem, NULL);
-
- if (camel_mime_parser_step (parser, NULL, NULL) == CAMEL_MIME_PARSER_STATE_HEADER
- && camel_mime_parser_content_type (parser) != NULL) {
- g_object_unref (part);
- part = camel_mime_part_new ();
-
- camel_data_wrapper_set_mime_type_field (CAMEL_DATA_WRAPPER (part), camel_mime_parser_content_type (parser));
- camel_mime_part_construct_content_from_parser (part, parser, NULL, NULL);
- } else {
- is_smime = FALSE;
- }
-
- g_object_unref (parser);
- g_object_unref (mem);
- }
-
- if (!is_smime && !is_apple) {
- if (ui32 && *ui32 == ATTACH_EMBEDDED_MSG && attach->embedded_object) {
- CamelMimeMessage *embedded_msg;
-
- embedded_msg = e_mapi_mail_utils_object_to_message (conn, attach->embedded_object);
- if (embedded_msg) {
- CamelStream *mem;
- GByteArray *data;
-
- data = g_byte_array_new ();
-
- mem = camel_stream_mem_new ();
- camel_stream_mem_set_byte_array (CAMEL_STREAM_MEM (mem), data);
- camel_data_wrapper_write_to_stream_sync (
- CAMEL_DATA_WRAPPER (embedded_msg), mem, NULL, NULL);
-
- g_object_unref (mem);
- g_object_unref (embedded_msg);
-
- camel_mime_part_set_content (part, (const gchar *) data->data, data->len, mime_type);
-
- g_byte_array_free (data, TRUE);
- } else {
- camel_mime_part_set_content (part, (const gchar *) data_bin->lpb, data_bin->cb, mime_type);
- }
- } else {
- camel_mime_part_set_content (part, (const gchar *) data_bin->lpb, data_bin->cb, mime_type);
- }
-
- content_type = camel_mime_part_get_content_type (part);
- if (content_type && camel_content_type_is (content_type, "text", "*"))
- camel_mime_part_set_encoding (part, CAMEL_TRANSFER_ENCODING_QUOTEDPRINTABLE);
- else if (!ui32 || *ui32 != ATTACH_EMBEDDED_MSG)
- camel_mime_part_set_encoding (part, CAMEL_TRANSFER_ENCODING_BASE64);
- }
-
- /* Content-ID */
- content_id = e_mapi_util_find_array_propval (&attach->properties, PidTagAttachContentId);
-
- /* TODO : Add disposition */
- if (content_id && !is_apple && !is_smime) {
- camel_mime_part_set_content_id (part, content_id);
- *inline_attachments = g_slist_append (*inline_attachments, part);
- } else
- *noninline_attachments = g_slist_append (*noninline_attachments, part);
- }
-}
-
-static void
-add_multipart_attachments (CamelMultipart *multipart, GSList *attachments)
-{
- CamelMimePart *part;
- while (attachments) {
- part = attachments->data;
- camel_multipart_add_part (multipart, part);
- attachments = attachments->next;
- }
-}
-
-static CamelMultipart *
-build_multipart_related (EMapiObject *object, GSList *inline_attachments)
-{
- CamelMimePart *part;
- CamelMultipart *m_related = camel_multipart_new ();
- camel_data_wrapper_set_mime_type (CAMEL_DATA_WRAPPER (m_related), "multipart/related");
- camel_multipart_set_boundary (m_related, NULL);
-
- if (e_mapi_util_find_array_propval (&object->properties, PidTagHtml)) {
- part = camel_mime_part_new ();
- build_body_part_content (part, object, PidTagHtml);
- camel_multipart_add_part (m_related, part);
- g_object_unref (part);
- } else if (e_mapi_util_find_array_propval (&object->properties, PidTagBody)) {
- part = camel_mime_part_new ();
- build_body_part_content (part, object, PidTagBody);
- camel_multipart_add_part (m_related, part);
- g_object_unref (part);
- }
-
- add_multipart_attachments (m_related, inline_attachments);
-
- return m_related;
-}
-
-static CamelMultipart *
-build_multipart_alternative (EMapiObject *object, GSList *inline_attachments)
-{
- CamelMimePart *part;
- CamelMultipart *m_alternative;
-
- m_alternative = camel_multipart_new ();
- camel_data_wrapper_set_mime_type (CAMEL_DATA_WRAPPER (m_alternative), "multipart/alternative");
- camel_multipart_set_boundary (m_alternative, NULL);
-
- if (e_mapi_util_find_array_propval (&object->properties, PidTagBody)) {
- part = camel_mime_part_new ();
- build_body_part_content (part, object, PidTagBody);
- camel_multipart_add_part (m_alternative, part);
- g_object_unref (part);
- }
-
- if (e_mapi_util_find_array_propval (&object->properties, PidTagHtml)) {
- part = camel_mime_part_new ();
- if (inline_attachments) {
- CamelMultipart *m_related;
-
- m_related = build_multipart_related (object, inline_attachments);
- camel_medium_set_content (CAMEL_MEDIUM (part), CAMEL_DATA_WRAPPER (m_related));
- g_object_unref (m_related);
- } else {
- build_body_part_content (part, object, PidTagHtml);
- }
- camel_multipart_add_part (m_alternative, part);
- g_object_unref (part);
- }
-
- return m_alternative;
-}
-
-static CamelMultipart *
-build_multipart_mixed (CamelMultipart *content, GSList *attachments)
-{
- CamelMimePart *part = camel_mime_part_new ();
- CamelMultipart *m_mixed = camel_multipart_new ();
- camel_data_wrapper_set_mime_type (CAMEL_DATA_WRAPPER (m_mixed), "multipart/mixed");
- camel_multipart_set_boundary (m_mixed, NULL);
-
- camel_medium_set_content (CAMEL_MEDIUM (part), CAMEL_DATA_WRAPPER (content));
- camel_multipart_add_part (m_mixed, part);
- g_object_unref (part);
-
- add_multipart_attachments (m_mixed, attachments);
-
- return m_mixed;
-}
-
-static gchar *
-build_ical_string (EMapiConnection *conn,
- EMapiObject *object,
- const gchar *msg_class)
-{
- gchar *ical_string = NULL, *use_uid;
- icalcomponent_kind ical_kind = ICAL_NO_COMPONENT;
- icalproperty_method ical_method = ICAL_METHOD_NONE;
- const uint64_t *pmid;
- ECalComponent *comp;
- icalcomponent *icalcomp;
- GSList *detached_components = NULL, *iter;
-
- g_return_val_if_fail (conn != NULL, NULL);
- g_return_val_if_fail (object != NULL, NULL);
- g_return_val_if_fail (msg_class != NULL, NULL);
-
- if (!g_ascii_strcasecmp (msg_class, IPM_SCHEDULE_MEETING_REQUEST)) {
- ical_method = ICAL_METHOD_REQUEST;
- ical_kind = ICAL_VEVENT_COMPONENT;
- } else if (!g_ascii_strcasecmp (msg_class, IPM_SCHEDULE_MEETING_CANCELED)) {
- ical_method = ICAL_METHOD_CANCEL;
- ical_kind = ICAL_VEVENT_COMPONENT;
- } else if (g_str_has_prefix (msg_class, IPM_SCHEDULE_MEETING_RESP_PREFIX)) {
- ical_method = ICAL_METHOD_REPLY;
- ical_kind = ICAL_VEVENT_COMPONENT;
- } else {
- return NULL;
- }
-
- pmid = e_mapi_util_find_array_propval (&object->properties, PidTagMid);
- if (pmid)
- use_uid = e_mapi_util_mapi_id_to_string (*pmid);
- else
- use_uid = e_cal_component_gen_uid ();
-
- comp = e_mapi_cal_util_object_to_comp (conn, object, ical_kind, ical_method == ICAL_METHOD_REPLY, NULL, use_uid, &detached_components);
-
- g_free (use_uid);
-
- if (!comp)
- return NULL;
-
- icalcomp = e_cal_util_new_top_level ();
- icalcomponent_set_method (icalcomp, ical_method);
- if (comp)
- icalcomponent_add_component (icalcomp,
- icalcomponent_new_clone (e_cal_component_get_icalcomponent (comp)));
- for (iter = detached_components; iter; iter = g_slist_next (iter)) {
- icalcomponent_add_component (icalcomp,
- icalcomponent_new_clone (e_cal_component_get_icalcomponent (iter->data)));
- }
-
- ical_string = icalcomponent_as_ical_string_r (icalcomp);
-
- icalcomponent_free (icalcomp);
- g_slist_free_full (detached_components, g_object_unref);
- g_object_unref (comp);
-
- return ical_string;
-}
-
-CamelMimeMessage *
-e_mapi_mail_utils_object_to_message (EMapiConnection *conn, /* const */ EMapiObject *object)
-{
- CamelMimeMessage *msg;
- CamelMultipart *multipart_body = NULL;
- GSList *inline_attachments, *noninline_attachments;
- gboolean build_alternative, build_related, build_calendar;
- const gchar *str, *msg_class;
- gboolean skip_set_content = FALSE;
- gchar *ical_string = NULL;
-
- g_return_val_if_fail (conn != NULL, NULL);
- g_return_val_if_fail (object != NULL, NULL);
-
- msg = camel_mime_message_new ();
-
- str = e_mapi_util_find_array_propval (&object->properties, PidTagTransportMessageHeaders);
- if (str && *str) {
- CamelMimePart *part = camel_mime_part_new ();
- CamelStream *stream;
- CamelMimeParser *parser;
-
- stream = camel_stream_mem_new_with_buffer (str, strlen (str));
- parser = camel_mime_parser_new ();
- camel_mime_parser_init_with_stream (parser, stream, NULL);
- camel_mime_parser_scan_from (parser, FALSE);
- g_object_unref (stream);
-
- if (camel_mime_part_construct_from_parser_sync (part, parser, NULL, NULL)) {
- struct _camel_header_raw *h;
-
- for (h = part->headers; h; h = h->next) {
- const gchar *value = h->value;
-
- /* skip all headers describing content of a message,
- because it's overwritten on message decomposition */
- if (g_ascii_strncasecmp (h->name, "Content", 7) == 0)
- continue;
-
- while (value && camel_mime_is_lwsp (*value))
- value++;
-
- camel_medium_add_header (CAMEL_MEDIUM (msg), h->name, value);
- }
- }
-
- g_object_unref (parser);
- g_object_unref (part);
- } else {
- CamelInternetAddress *to_addr, *cc_addr, *bcc_addr;
- const struct FILETIME *delivery_time;
- gchar *name, *email;
-
- to_addr = camel_internet_address_new ();
- cc_addr = camel_internet_address_new ();
- bcc_addr = camel_internet_address_new ();
-
- e_mapi_mail_utils_decode_recipients (conn, object->recipients, (CamelAddress *) to_addr, (CamelAddress *) cc_addr, (CamelAddress *) bcc_addr);
-
- camel_mime_message_set_recipients (msg, CAMEL_RECIPIENT_TYPE_TO, to_addr);
- camel_mime_message_set_recipients (msg, CAMEL_RECIPIENT_TYPE_CC, cc_addr);
- camel_mime_message_set_recipients (msg, CAMEL_RECIPIENT_TYPE_BCC, bcc_addr);
-
- g_object_unref (to_addr);
- g_object_unref (cc_addr);
- g_object_unref (bcc_addr);
-
- delivery_time = e_mapi_util_find_array_propval (&object->properties, PidTagMessageDeliveryTime);
- if (delivery_time) {
- time_t received_time, actual_time;
- gint offset = 0;
-
- received_time = e_mapi_util_filetime_to_time_t (delivery_time);
- actual_time = camel_header_decode_date (ctime (&received_time), &offset);
- camel_mime_message_set_date (msg, actual_time, offset);
- }
-
- str = e_mapi_util_find_array_propval (&object->properties, PidTagSubject);
- if (str)
- camel_mime_message_set_subject (msg, str);
-
- name = NULL;
- email = NULL;
-
- e_mapi_mail_utils_decode_email_address1 (conn, &object->properties,
- PidTagSentRepresentingName,
- PidTagSentRepresentingEmailAddress,
- PidTagSentRepresentingAddressType,
- &name, &email);
-
- if (email && *email) {
- CamelInternetAddress *addr;
-
- addr = camel_internet_address_new();
- camel_internet_address_add (addr, name, email);
- camel_mime_message_set_from (msg, addr);
- }
-
- g_free (name);
- g_free (email);
-
- /* Threading */
- str = e_mapi_util_find_array_propval (&object->properties, PidTagInternetMessageId);
- if (str)
- camel_medium_add_header (CAMEL_MEDIUM (msg), "Message-ID", str);
-
- str = e_mapi_util_find_array_propval (&object->properties, PidTagInternetReferences);
- if (str)
- camel_medium_add_header (CAMEL_MEDIUM (msg), "References", str);
-
- str = e_mapi_util_find_array_propval (&object->properties, PidTagInReplyToId);
- if (str)
- camel_medium_add_header (CAMEL_MEDIUM (msg), "In-Reply-To", str);
- }
-
- str = e_mapi_util_find_array_propval (&object->properties, PidNameContentClass);
- if (str)
- camel_medium_add_header (CAMEL_MEDIUM (msg), "Content-class", str);
-
- inline_attachments = NULL;
- noninline_attachments = NULL;
- msg_class = e_mapi_util_find_array_propval (&object->properties, PidTagMessageClass);
- classify_attachments (conn, object->attachments, msg_class, &inline_attachments, &noninline_attachments);
-
- build_calendar = msg_class && g_str_has_prefix (msg_class, IPM_SCHEDULE_MEETING_PREFIX);
- if (build_calendar) {
- ical_string = build_ical_string (conn, object, msg_class);
- if (!ical_string)
- build_calendar = FALSE;
- }
-
- build_alternative = !build_calendar
- && e_mapi_util_find_array_propval (&object->properties, PidTagHtml)
- && e_mapi_util_find_array_propval (&object->properties, PidTagBody);
- build_related = !build_calendar && !build_alternative && inline_attachments;
-
- if (build_calendar) {
- g_return_val_if_fail (ical_string != NULL, msg);
-
- camel_mime_part_set_content (CAMEL_MIME_PART (msg), ical_string, strlen (ical_string), "text/calendar");
- } else if (build_alternative) {
- multipart_body = build_multipart_alternative (object, inline_attachments);
- } else if (build_related) {
- multipart_body = build_multipart_related (object, inline_attachments);
- } else if (noninline_attachments) {
- /* Simple multipart/mixed */
- CamelMimePart *part = camel_mime_part_new ();
-
- multipart_body = camel_multipart_new ();
- camel_data_wrapper_set_mime_type (CAMEL_DATA_WRAPPER (multipart_body), "multipart/mixed");
- camel_multipart_set_boundary (multipart_body, NULL);
- if (e_mapi_util_find_array_propval (&object->properties, PidTagHtml))
- build_body_part_content (part, object, PidTagHtml);
- else
- build_body_part_content (part, object, PidTagBody);
- camel_multipart_add_part (multipart_body, part);
- g_object_unref (part);
- } else {
- /* Flat message */
- if (e_mapi_util_find_array_propval (&object->properties, PidTagHtml))
- build_body_part_content (CAMEL_MIME_PART (msg), object, PidTagHtml);
- else
- build_body_part_content (CAMEL_MIME_PART (msg), object, PidTagBody);
- }
-
- if (noninline_attachments) { /* multipart/mixed */
- if (build_alternative || build_related || build_calendar) {
- multipart_body = build_multipart_mixed (multipart_body, noninline_attachments);
- } else if (g_slist_length (noninline_attachments) == 1 && msg_class && strstr (msg_class, ".SMIME") > msg_class) {
- CamelMimePart *part = noninline_attachments->data;
-
- skip_set_content = TRUE;
-
- camel_medium_set_content (CAMEL_MEDIUM (msg), CAMEL_DATA_WRAPPER (part));
-
- if (!strstr (msg_class, ".SMIME.")) {
- /* encrypted */
- camel_medium_set_content (CAMEL_MEDIUM (msg), camel_medium_get_content (CAMEL_MEDIUM (part)));
- camel_mime_part_set_encoding (CAMEL_MIME_PART (msg), camel_mime_part_get_encoding (part));
- } else {
- /* signed */
- camel_medium_set_content (CAMEL_MEDIUM (msg), CAMEL_DATA_WRAPPER (part));
- }
- } else {
- add_multipart_attachments (multipart_body, noninline_attachments);
- }
- }
-
- if (!skip_set_content && multipart_body)
- camel_medium_set_content (CAMEL_MEDIUM (msg), CAMEL_DATA_WRAPPER (multipart_body));
-
- if (multipart_body)
- g_object_unref (multipart_body);
- g_slist_free_full (inline_attachments, g_object_unref);
- g_slist_free_full (noninline_attachments, g_object_unref);
- g_free (ical_string);
-
- return msg;
-}
-
-static void
-e_mapi_mail_add_recipients (EMapiObject *object,
- CamelInternetAddress *addresses,
- OlMailRecipientType recip_type)
-{
- gint ii;
- const gchar *name = NULL, *email = NULL;
-
- g_return_if_fail (object != NULL);
-
- for (ii = 0; addresses && camel_internet_address_get (addresses, ii, &name, &email); ii++) {
- EMapiRecipient *recipient;
- uint32_t ui32 = 0;
- bool bl;
-
- recipient = e_mapi_recipient_new (object);
- e_mapi_object_add_recipient (object, recipient);
-
- #define set_value(pt,vl) { \
- if (!e_mapi_utils_add_property (&recipient->properties, pt, vl, recipient)) { \
- g_warning ("%s: Failed to set property 0x%x", G_STRFUNC, pt); \
- \
- return; \
- } \
- }
-
- ui32 = recip_type;
- set_value (PidTagRecipientType, &ui32);
-
- if (!name || !*name)
- name = email;
-
- if (name && *name) {
- set_value (PidTagDisplayName, name);
- set_value (PidTagRecipientDisplayName, name);
- }
- if (email && *email) {
- set_value (PidTagAddressType, "SMTP");
- set_value (PidTagEmailAddress, email);
-
- set_value (PidTagSmtpAddress, email);
- set_value (PidTagPrimarySmtpAddress, email);
- }
-
- ui32 = 0;
- set_value (PidTagSendInternetEncoding, &ui32);
-
- ui32 = DT_MAILUSER;
- set_value (PidTagDisplayType, &ui32);
-
- ui32 = MAPI_MAILUSER;
- set_value (PidTagObjectType, &ui32);
-
- bl = false;
- set_value (PidTagSendRichInfo, &bl);
-
- #undef set_value
-
- name = NULL;
- email = NULL;
- }
-}
-
-static CamelStream *
-get_content_stream (CamelMimePart *part, GCancellable *cancellable)
-{
- CamelStream *content_stream;
- CamelStream *filter_stream = NULL;
- CamelMimeFilterWindows *windows = NULL;
- CamelDataWrapper *dw;
-
- g_return_val_if_fail (part != NULL, NULL);
-
- dw = camel_medium_get_content (CAMEL_MEDIUM (part));
- g_return_val_if_fail (dw != NULL, NULL);
-
- content_stream = camel_stream_mem_new();
-
- if (camel_mime_part_get_content_type (part)) {
- const gchar *charset = camel_content_type_param (camel_mime_part_get_content_type (part), "charset");
-
- if (charset && *charset && g_ascii_strcasecmp (charset, "utf8") != 0 && g_ascii_strcasecmp (charset, "utf-8") != 0) {
- if (g_ascii_strncasecmp (charset, "iso-8859-", 9) == 0) {
- CamelStream *null;
-
- /* Since a few Windows mailers like to claim they sent
- * out iso-8859-# encoded text when they really sent
- * out windows-cp125#, do some simple sanity checking
- * before we move on... */
-
- null = camel_stream_null_new ();
- filter_stream = camel_stream_filter_new (null);
- g_object_unref (null);
-
- windows = (CamelMimeFilterWindows *)camel_mime_filter_windows_new (charset);
- camel_stream_filter_add (
- CAMEL_STREAM_FILTER (filter_stream),
- CAMEL_MIME_FILTER (windows));
-
- camel_data_wrapper_decode_to_stream_sync (
- dw, (CamelStream *)filter_stream, cancellable, NULL);
- camel_stream_flush ((CamelStream *)filter_stream, cancellable, NULL);
- g_object_unref (filter_stream);
-
- charset = camel_mime_filter_windows_real_charset (windows);
- }
-
- if (charset && *charset) {
- CamelMimeFilter *filter;
-
- filter_stream = camel_stream_filter_new (content_stream);
-
- if ((filter = camel_mime_filter_charset_new (charset, "UTF-8"))) {
- camel_stream_filter_add (
- CAMEL_STREAM_FILTER (filter_stream),
- CAMEL_MIME_FILTER (filter));
- g_object_unref (filter);
- } else {
- g_object_unref (filter_stream);
- filter_stream = NULL;
- }
- }
- }
- }
-
- if (filter_stream) {
- camel_data_wrapper_decode_to_stream_sync (dw, (CamelStream *) filter_stream, cancellable, NULL);
- camel_stream_flush (filter_stream, cancellable, NULL);
- g_object_unref (filter_stream);
- } else {
- camel_data_wrapper_decode_to_stream_sync (dw, (CamelStream *) content_stream, cancellable, NULL);
- }
-
- if (windows)
- g_object_unref (windows);
-
- g_seekable_seek (G_SEEKABLE (content_stream), 0, G_SEEK_SET, NULL, NULL);
-
- return content_stream;
-}
-
-static void
-e_mapi_mail_content_stream_to_bin (CamelStream *content_stream,
- struct SBinary_short *bin,
- TALLOC_CTX *mem_ctx,
- GCancellable *cancellable)
-{
- guint8 *buf;
- guint32 read_size;
-
- g_return_if_fail (content_stream != NULL);
- g_return_if_fail (bin != NULL);
- g_return_if_fail (mem_ctx != NULL);
-
- buf = g_new0 (guint8 , STREAM_SIZE);
-
- bin->cb = 0;
- bin->lpb = NULL;
-
- g_seekable_seek (G_SEEKABLE (content_stream), 0, G_SEEK_SET, NULL, NULL);
- while (read_size = camel_stream_read (content_stream, (gchar *) buf, STREAM_SIZE, cancellable, NULL), read_size > 0) {
- bin->lpb = talloc_realloc (mem_ctx, bin->lpb, uint8_t, bin->cb + read_size);
- memcpy (bin->lpb + bin->cb, buf, read_size);
- bin->cb += read_size;
- }
-
- g_free (buf);
-}
-
-#define set_attach_value(pt,vl) { \
- if (!e_mapi_utils_add_property (&attach->properties, pt, vl, attach)) { \
- g_warning ("%s: Failed to set property 0x%x", G_STRFUNC, pt); \
- return FALSE; \
- } \
-}
-
-static gboolean
-e_mapi_mail_add_attach (EMapiObject *object,
- CamelMimePart *part,
- CamelStream *content_stream,
- GCancellable *cancellable)
-{
- EMapiAttachment *attach;
- CamelContentType *content_type;
- const gchar *content_id;
- const gchar *filename;
- struct SBinary_short bin;
- uint32_t ui32;
-
- g_return_val_if_fail (object != NULL, FALSE);
- g_return_val_if_fail (part != NULL, FALSE);
- g_return_val_if_fail (content_stream != NULL, FALSE);
-
- attach = e_mapi_attachment_new (object);
- e_mapi_object_add_attachment (object, attach);
-
- ui32 = ATTACH_BY_VALUE;
- set_attach_value (PidTagAttachMethod, &ui32);
- ui32 = -1;
- set_attach_value (PidTagRenderingPosition, &ui32);
-
- filename = camel_mime_part_get_filename (part);
- if (filename) {
- set_attach_value (PidTagAttachFilename, filename);
- set_attach_value (PidTagAttachLongFilename, filename);
- }
-
- content_id = camel_mime_part_get_content_id (part);
- if (content_id)
- set_attach_value (PidTagAttachContentId, content_id);
-
- content_type = camel_mime_part_get_content_type (part);
- if (content_type) {
- gchar *ct = camel_content_type_simple (content_type);
- if (ct)
- set_attach_value (PidTagAttachMimeTag, ct);
- g_free (ct);
- }
-
- e_mapi_mail_content_stream_to_bin (content_stream, &bin, attach, cancellable);
- set_attach_value (PidTagAttachDataBinary, &bin);
-
- return TRUE;
-}
-
-static gboolean
-e_mapi_mail_add_body (EMapiObject *object,
- CamelStream *content_stream,
- uint32_t proptag,
- GCancellable *cancellable)
-{
- struct SBinary_short bin = { 0 };
- gchar *str;
-
- e_mapi_mail_content_stream_to_bin (content_stream, &bin, object, cancellable);
- str = talloc_strndup (object, (const gchar *) bin.lpb, bin.cb);
- talloc_free (bin.lpb);
-
- if ((proptag & 0xFFFF) == PT_BINARY) {
- bin.lpb = (uint8_t *) (str ? str : "");
- bin.cb = strlen ((const gchar *) bin.lpb) + 1;
- /* include trailing zero ................ ^^^ */
-
- return e_mapi_utils_add_property (&object->properties, proptag, &bin, object);
- } else if (str) {
- if (!e_mapi_utils_add_property (&object->properties, proptag, str, object)) {
- talloc_free (str);
- return FALSE;
- }
-
- talloc_free (str);
- } else {
- return e_mapi_utils_add_property (&object->properties, proptag, "", object);
- }
-
- return TRUE;
-}
-
-static gboolean
-e_mapi_mail_do_smime_encrypted (EMapiObject *object,
- CamelMedium *message,
- gchar **pmsg_class,
- gchar **ppid_name_content_type,
- GCancellable *cancellable)
-{
- EMapiAttachment *attach;
- CamelStream *content_stream;
- CamelDataWrapper *dw;
- CamelContentType *type;
- uint32_t ui32;
- struct SBinary_short bin;
- gchar *content_type_str;
-
- g_return_val_if_fail (object != NULL, FALSE);
- g_return_val_if_fail (message != NULL, FALSE);
- g_return_val_if_fail (pmsg_class != NULL, FALSE);
- g_return_val_if_fail (ppid_name_content_type != NULL, FALSE);
-
- g_free (*pmsg_class);
- *pmsg_class = g_strdup ("IPM.Note.SMIME");
-
- type = camel_data_wrapper_get_mime_type_field (CAMEL_DATA_WRAPPER (message));
- dw = camel_medium_get_content (message);
- content_type_str = camel_content_type_format (type);
-
- g_free (*ppid_name_content_type);
- *ppid_name_content_type = content_type_str; /* will be freed within the caller */
-
- content_stream = camel_stream_mem_new ();
- camel_data_wrapper_decode_to_stream_sync (dw, (CamelStream *) content_stream, cancellable, NULL);
-
- attach = e_mapi_attachment_new (object);
- e_mapi_object_add_attachment (object, attach);
-
- ui32 = ATTACH_BY_VALUE;
- set_attach_value (PidTagAttachMethod, &ui32);
- ui32 = -1;
- set_attach_value (PidTagRenderingPosition, &ui32);
- set_attach_value (PidTagAttachMimeTag, content_type_str);
- set_attach_value (PidTagAttachFilename, "SMIME.txt");
- set_attach_value (PidTagAttachLongFilename, "SMIME.txt");
- set_attach_value (PidTagDisplayName, "SMIME.txt");
-
- e_mapi_mail_content_stream_to_bin (content_stream, &bin, attach, cancellable);
- set_attach_value (PidTagAttachDataBinary, &bin);
-
- g_object_unref (content_stream);
-
- return TRUE;
-}
-
-static gboolean
-e_mapi_mail_do_smime_signed (EMapiObject *object,
- CamelMultipart *multipart,
- gchar **pmsg_class,
- GCancellable *cancellable)
+static gchar *
+build_ical_string (EMapiConnection *conn,
+ EMapiObject *object,
+ const gchar *msg_class)
{
- EMapiAttachment *attach;
- CamelMimePart *content, *signature;
- CamelStream *content_stream;
- CamelContentType *type;
- CamelDataWrapper *dw;
- uint32_t ui32;
- struct SBinary_short bin;
- gchar *content_type_str;
-
- g_free (*pmsg_class);
- *pmsg_class = g_strdup ("IPM.Note.SMIME.MultipartSigned");
-
- content = camel_multipart_get_part (multipart, CAMEL_MULTIPART_SIGNED_CONTENT);
- signature = camel_multipart_get_part (multipart, CAMEL_MULTIPART_SIGNED_SIGNATURE);
-
- g_return_val_if_fail (content != NULL, FALSE);
- g_return_val_if_fail (signature != NULL, FALSE);
+ gchar *ical_string = NULL, *use_uid;
+ icalcomponent_kind ical_kind = ICAL_NO_COMPONENT;
+ icalproperty_method ical_method = ICAL_METHOD_NONE;
+ const uint64_t *pmid;
+ ECalComponent *comp;
+ icalcomponent *icalcomp;
+ GSList *detached_components = NULL, *iter;
- content_stream = get_content_stream (content, cancellable);
- type = camel_mime_part_get_content_type (content);
+ g_return_val_if_fail (conn != NULL, NULL);
+ g_return_val_if_fail (object != NULL, NULL);
+ g_return_val_if_fail (msg_class != NULL, NULL);
- if (camel_content_type_is (type, "text", "plain")) {
- e_mapi_mail_add_body (object, content_stream, PidTagBody, cancellable);
- } else if (camel_content_type_is (type, "text", "html")) {
- e_mapi_mail_add_body (object, content_stream, PidTagHtml, cancellable);
+ if (!g_ascii_strcasecmp (msg_class, IPM_SCHEDULE_MEETING_REQUEST)) {
+ ical_method = ICAL_METHOD_REQUEST;
+ ical_kind = ICAL_VEVENT_COMPONENT;
+ } else if (!g_ascii_strcasecmp (msg_class, IPM_SCHEDULE_MEETING_CANCELED)) {
+ ical_method = ICAL_METHOD_CANCEL;
+ ical_kind = ICAL_VEVENT_COMPONENT;
+ } else if (g_str_has_prefix (msg_class, IPM_SCHEDULE_MEETING_RESP_PREFIX)) {
+ ical_method = ICAL_METHOD_REPLY;
+ ical_kind = ICAL_VEVENT_COMPONENT;
} else {
- e_mapi_mail_add_attach (object, content, content_stream, cancellable);
+ return NULL;
}
- if (content_stream)
- g_object_unref (content_stream);
-
- content_stream = camel_stream_mem_new ();
- dw = CAMEL_DATA_WRAPPER (multipart);
- type = camel_data_wrapper_get_mime_type_field (dw);
- content_type_str = camel_content_type_format (type);
-
- #define wstr(str) camel_stream_write (content_stream, str, strlen (str), cancellable, NULL)
- wstr("Content-Type: ");
- wstr(content_type_str);
- wstr("\n\n");
- #undef wstr
+ pmid = e_mapi_util_find_array_propval (&object->properties, PidTagMid);
+ if (pmid)
+ use_uid = e_mapi_util_mapi_id_to_string (*pmid);
+ else
+ use_uid = e_cal_component_gen_uid ();
- g_free (content_type_str);
+ comp = e_mapi_cal_util_object_to_comp (conn, object, ical_kind, ical_method == ICAL_METHOD_REPLY, NULL, use_uid, &detached_components);
- camel_data_wrapper_write_to_stream_sync (dw, (CamelStream *) content_stream, cancellable, NULL);
+ g_free (use_uid);
- attach = e_mapi_attachment_new (object);
- e_mapi_object_add_attachment (object, attach);
+ if (!comp)
+ return NULL;
- ui32 = ATTACH_BY_VALUE;
- set_attach_value (PidTagAttachMethod, &ui32);
- ui32 = -1;
- set_attach_value (PidTagRenderingPosition, &ui32);
- set_attach_value (PidTagAttachMimeTag, "multipart/signed");
- set_attach_value (PidTagAttachFilename, "SMIME.txt");
- set_attach_value (PidTagAttachLongFilename, "SMIME.txt");
- set_attach_value (PidTagDisplayName, "SMIME.txt");
+ icalcomp = e_cal_util_new_top_level ();
+ icalcomponent_set_method (icalcomp, ical_method);
+ if (comp)
+ icalcomponent_add_component (icalcomp,
+ icalcomponent_new_clone (e_cal_component_get_icalcomponent (comp)));
+ for (iter = detached_components; iter; iter = g_slist_next (iter)) {
+ icalcomponent_add_component (icalcomp,
+ icalcomponent_new_clone (e_cal_component_get_icalcomponent (iter->data)));
+ }
- e_mapi_mail_content_stream_to_bin (content_stream, &bin, attach, cancellable);
- set_attach_value (PidTagAttachDataBinary, &bin);
+ ical_string = icalcomponent_as_ical_string_r (icalcomp);
- g_object_unref (content_stream);
+ icalcomponent_free (icalcomp);
+ g_slist_free_full (detached_components, g_object_unref);
+ g_object_unref (comp);
- return TRUE;
+ return ical_string;
}
-static gboolean
-e_mapi_mail_do_multipart (EMapiObject *object,
- CamelMultipart *mp,
- gboolean *is_first,
- GCancellable *cancellable)
+CamelMimeMessage *
+e_mapi_mail_utils_object_to_message (EMapiConnection *conn, /* const */ EMapiObject *object)
{
- CamelDataWrapper *dw;
- CamelStream *content_stream;
- CamelContentType *type;
- CamelMimePart *part;
- gint nn, ii;
+ CamelMimeMessage *msg;
+ CamelMultipart *multipart_body = NULL;
+ GSList *inline_attachments, *noninline_attachments;
+ gboolean build_alternative, build_related, build_calendar;
+ const gchar *str, *msg_class;
+ gboolean skip_set_content = FALSE;
+ gchar *ical_string = NULL;
- g_return_val_if_fail (is_first != NULL, FALSE);
+ g_return_val_if_fail (conn != NULL, NULL);
+ g_return_val_if_fail (object != NULL, NULL);
- nn = camel_multipart_get_number (mp);
- for (ii = 0; ii < nn; ii++) {
- /* getting part */
- part = camel_multipart_get_part (mp, ii);
- if (!part)
- continue;
+ msg = camel_mime_message_new ();
- dw = camel_medium_get_content (CAMEL_MEDIUM (part));
- if (CAMEL_IS_MULTIPART (dw)) {
- /* recursive */
- if (!e_mapi_mail_do_multipart (object, CAMEL_MULTIPART (dw), is_first, cancellable))
- return FALSE;
- continue;
- }
+ str = e_mapi_util_find_array_propval (&object->properties, PidTagTransportMessageHeaders);
+ if (str && *str) {
+ CamelMimePart *part = camel_mime_part_new ();
+ CamelStream *stream;
+ CamelMimeParser *parser;
- if (CAMEL_IS_MIME_MESSAGE (dw)) {
- CamelMimeMessage *message;
- EMapiObject *embedded = NULL;
- EMapiAttachment *attach;
+ stream = camel_stream_mem_new_with_buffer (str, strlen (str));
+ parser = camel_mime_parser_new ();
+ camel_mime_parser_init_with_stream (parser, stream, NULL);
+ camel_mime_parser_scan_from (parser, FALSE);
+ g_object_unref (stream);
- attach = e_mapi_attachment_new (object);
- message = CAMEL_MIME_MESSAGE (dw);
- if (e_mapi_mail_utils_message_to_object (message, 0, E_MAPI_CREATE_FLAG_NONE, &embedded, attach, cancellable, NULL)) {
- uint32_t ui32;
- const gchar *str;
+ if (camel_mime_part_construct_from_parser_sync (part, parser, NULL, NULL)) {
+ struct _camel_header_raw *h;
- e_mapi_object_add_attachment (object, attach);
- attach->embedded_object = embedded;
- embedded->parent = object;
+ for (h = part->headers; h; h = h->next) {
+ const gchar *value = h->value;
- ui32 = ATTACH_EMBEDDED_MSG;
- set_attach_value (PidTagAttachMethod, &ui32);
- ui32 = 0;
- set_attach_value (PidTagRenderingPosition, &ui32);
- set_attach_value (PidTagAttachMimeTag, "message/rfc822");
+ /* skip all headers describing content of a message,
+ because it's overwritten on message decomposition */
+ if (g_ascii_strncasecmp (h->name, "Content", 7) == 0)
+ continue;
- str = camel_mime_message_get_subject (message);
- if (str)
- set_attach_value (PidTagAttachFilename, str);
- continue;
- } else {
- e_mapi_attachment_free (attach);
+ while (value && camel_mime_is_lwsp (*value))
+ value++;
+
+ camel_medium_add_header (CAMEL_MEDIUM (msg), h->name, value);
}
}
- content_stream = get_content_stream (part, cancellable);
- type = camel_mime_part_get_content_type (part);
+ g_object_unref (parser);
+ g_object_unref (part);
+ } else {
+ CamelInternetAddress *to_addr, *cc_addr, *bcc_addr;
+ const struct FILETIME *delivery_time;
+ gchar *name, *email;
- if (ii == 0 && (*is_first) && camel_content_type_is (type, "text", "plain")) {
- e_mapi_mail_add_body (object, content_stream, PidTagBody, cancellable);
- *is_first = FALSE;
- } else if (camel_content_type_is (type, "text", "html")) {
- e_mapi_mail_add_body (object, content_stream, PidTagHtml, cancellable);
- } else {
- e_mapi_mail_add_attach (object, part, content_stream, cancellable);
- }
+ to_addr = camel_internet_address_new ();
+ cc_addr = camel_internet_address_new ();
+ bcc_addr = camel_internet_address_new ();
- if (content_stream)
- g_object_unref (content_stream);
- }
+ e_mapi_mail_utils_decode_recipients (conn, object->recipients, (CamelAddress *) to_addr, (CamelAddress *) cc_addr, (CamelAddress *) bcc_addr);
- return TRUE;
-}
+ camel_mime_message_set_recipients (msg, CAMEL_RECIPIENT_TYPE_TO, to_addr);
+ camel_mime_message_set_recipients (msg, CAMEL_RECIPIENT_TYPE_CC, cc_addr);
+ camel_mime_message_set_recipients (msg, CAMEL_RECIPIENT_TYPE_BCC, bcc_addr);
-#undef set_attach_value
+ g_object_unref (to_addr);
+ g_object_unref (cc_addr);
+ g_object_unref (bcc_addr);
-gboolean
-e_mapi_mail_utils_message_to_object (struct _CamelMimeMessage *message,
- guint32 message_camel_flags,
- EMapiCreateFlags create_flags,
- EMapiObject **pobject,
- TALLOC_CTX *mem_ctx,
- GCancellable *cancellable,
- GError **perror)
-{
- EMapiObject *object;
- CamelContentType *content_type;
- CamelInternetAddress *addresses;
- const gchar *namep = NULL, *addressp = NULL;
- const gchar *str;
- gchar *msg_class = NULL;
- gchar *pid_name_content_type = NULL;
- gint ii = 0;
- uint32_t ui32;
- bool bl;
+ delivery_time = e_mapi_util_find_array_propval (&object->properties, PidTagMessageDeliveryTime);
+ if (delivery_time) {
+ time_t received_time, actual_time;
+ gint offset = 0;
- g_return_val_if_fail (message != NULL, FALSE);
- g_return_val_if_fail (pobject != NULL, FALSE);
- g_return_val_if_fail (*pobject == NULL, FALSE);
- g_return_val_if_fail (mem_ctx != NULL, FALSE);
+ received_time = e_mapi_util_filetime_to_time_t (delivery_time);
+ actual_time = camel_header_decode_date (ctime (&received_time), &offset);
+ camel_mime_message_set_date (msg, actual_time, offset);
+ }
- content_type = camel_data_wrapper_get_mime_type_field (CAMEL_DATA_WRAPPER (message));
- g_return_val_if_fail (content_type != NULL, FALSE);
+ str = e_mapi_util_find_array_propval (&object->properties, PidTagSubject);
+ if (str)
+ camel_mime_message_set_subject (msg, str);
- /* headers */
- if ((create_flags & E_MAPI_CREATE_FLAG_SUBMIT) == 0) {
- /* though invalid, then possible, to pass in a message without any 'from' */
- CamelInternetAddress *from = camel_mime_message_get_from (message);
- if (!from || !camel_internet_address_get (from, 0, &namep, &addressp))
- namep = NULL;
- }
+ name = NULL;
+ email = NULL;
- object = e_mapi_object_new (mem_ctx);
+ e_mapi_mail_utils_decode_email_address1 (conn, &object->properties,
+ PidTagSentRepresentingName,
+ PidTagSentRepresentingEmailAddress,
+ PidTagSentRepresentingAddressType,
+ &name, &email);
- #define set_value(pt,vl) { \
- if (!e_mapi_utils_add_property (&object->properties, pt, vl, object)) { \
- e_mapi_object_free (object); \
- g_free (msg_class); \
- g_free (pid_name_content_type); \
- \
- g_warning ("%s: Failed to set property 0x%x", G_STRFUNC, pt); \
- \
- return FALSE; \
- } \
- }
+ if (email && *email) {
+ CamelInternetAddress *addr;
+
+ addr = camel_internet_address_new();
+ camel_internet_address_add (addr, name, email);
+ camel_mime_message_set_from (msg, addr);
+ }
+
+ g_free (name);
+ g_free (email);
- ui32 = 65001; /* UTF8 - also used with PR_HTML */
- set_value (PidTagInternetCodepage, &ui32);
+ /* Threading */
+ str = e_mapi_util_find_array_propval (&object->properties, PidTagInternetMessageId);
+ if (str)
+ camel_medium_add_header (CAMEL_MEDIUM (msg), "Message-ID", str);
- if ((create_flags & E_MAPI_CREATE_FLAG_SUBMIT) == 0) {
- ui32 = 0;
- if (message_camel_flags & CAMEL_MESSAGE_SEEN)
- ui32 |= MSGFLAG_READ;
- if (message_camel_flags & CAMEL_MESSAGE_ATTACHMENTS)
- ui32 |= MSGFLAG_HASATTACH;
- } else {
- ui32 = MSGFLAG_UNSENT;
- }
- set_value (PidTagMessageFlags, &ui32);
+ str = e_mapi_util_find_array_propval (&object->properties, PidTagInternetReferences);
+ if (str)
+ camel_medium_add_header (CAMEL_MEDIUM (msg), "References", str);
- bl = false;
- set_value (PidTagSendRichInfo, &bl);
+ str = e_mapi_util_find_array_propval (&object->properties, PidTagInReplyToId);
+ if (str)
+ camel_medium_add_header (CAMEL_MEDIUM (msg), "In-Reply-To", str);
+ }
- /* PidTagConversationTopic and PidTagNormalizedSubject, together with PidTagSubjectPrefix
- are computed from PidTagSubject by a server */
- str = camel_mime_message_get_subject (message);
+ str = e_mapi_util_find_array_propval (&object->properties, PidNameContentClass);
if (str)
- set_value (PidTagSubject, str);
+ camel_medium_add_header (CAMEL_MEDIUM (msg), "Content-class", str);
- /* some properties may not be set when submitting a message */
- if ((create_flags & E_MAPI_CREATE_FLAG_SUBMIT) == 0) {
- time_t msg_time = 0;
- gint msg_time_offset = 0;
- GArray *headers;
+ inline_attachments = NULL;
+ noninline_attachments = NULL;
+ msg_class = e_mapi_util_find_array_propval (&object->properties, PidTagMessageClass);
+ classify_attachments (conn, object->attachments, msg_class, &inline_attachments, &noninline_attachments);
- if (namep && *namep)
- set_value (PidTagSentRepresentingName, namep);
+ build_calendar = msg_class && g_str_has_prefix (msg_class, IPM_SCHEDULE_MEETING_PREFIX);
+ if (build_calendar) {
+ ical_string = build_ical_string (conn, object, msg_class);
+ if (!ical_string)
+ build_calendar = FALSE;
+ }
- if (addressp && *addressp) {
- set_value (PidTagSentRepresentingAddressType, "SMTP");
- set_value (PidTagSentRepresentingEmailAddress, addressp);
- }
+ build_alternative = !build_calendar
+ && e_mapi_util_find_array_propval (&object->properties, PidTagHtml)
+ && e_mapi_util_find_array_propval (&object->properties, PidTagBody);
+ build_related = !build_calendar && !build_alternative && inline_attachments;
- msg_time = camel_mime_message_get_date (message, &msg_time_offset);
- if (msg_time == CAMEL_MESSAGE_DATE_CURRENT)
- msg_time = camel_mime_message_get_date_received (message, &msg_time_offset);
- if (msg_time != 0) {
- struct FILETIME msg_date = { 0 };
+ if (build_calendar) {
+ g_return_val_if_fail (ical_string != NULL, msg);
- e_mapi_util_time_t_to_filetime (msg_time, &msg_date);
+ camel_mime_part_set_content (CAMEL_MIME_PART (msg), ical_string, strlen (ical_string), "text/calendar");
+ } else if (build_alternative) {
+ multipart_body = build_multipart_alternative (object, inline_attachments);
+ } else if (build_related) {
+ multipart_body = build_multipart_related (object, inline_attachments);
+ } else if (noninline_attachments) {
+ /* Simple multipart/mixed */
+ CamelMimePart *part = camel_mime_part_new ();
- set_value (PidTagMessageDeliveryTime, &msg_date);
- }
+ multipart_body = camel_multipart_new ();
+ camel_data_wrapper_set_mime_type (CAMEL_DATA_WRAPPER (multipart_body), "multipart/mixed");
+ camel_multipart_set_boundary (multipart_body, NULL);
+ if (e_mapi_util_find_array_propval (&object->properties, PidTagHtml))
+ build_body_part_content (part, object, PidTagHtml);
+ else
+ build_body_part_content (part, object, PidTagBody);
+ camel_multipart_add_part (multipart_body, part);
+ g_object_unref (part);
+ } else {
+ /* Flat message */
+ if (e_mapi_util_find_array_propval (&object->properties, PidTagHtml))
+ build_body_part_content (CAMEL_MIME_PART (msg), object, PidTagHtml);
+ else
+ build_body_part_content (CAMEL_MIME_PART (msg), object, PidTagBody);
+ }
- headers = camel_medium_get_headers (CAMEL_MEDIUM (message));
- if (headers) {
- GString *hstr = g_string_new ("");
+ if (noninline_attachments) { /* multipart/mixed */
+ if (build_alternative || build_related || build_calendar) {
+ multipart_body = build_multipart_mixed (multipart_body, noninline_attachments);
+ } else if (g_slist_length (noninline_attachments) == 1 && msg_class && strstr (msg_class, ".SMIME") > msg_class) {
+ CamelMimePart *part = noninline_attachments->data;
- for (ii = 0; ii < headers->len; ii++) {
- CamelMediumHeader *h = &g_array_index (headers, CamelMediumHeader, ii);
+ skip_set_content = TRUE;
- if (!h->name || !*h->name || g_ascii_strncasecmp (h->name, "X-Evolution", 11) == 0)
- continue;
+ camel_medium_set_content (CAMEL_MEDIUM (msg), CAMEL_DATA_WRAPPER (part));
- g_string_append_printf (hstr, "%s: %s\n", h->name, h->value ? h->value : "");
+ if (!strstr (msg_class, ".SMIME.")) {
+ /* encrypted */
+ camel_medium_set_content (CAMEL_MEDIUM (msg), camel_medium_get_content (CAMEL_MEDIUM (part)));
+ camel_mime_part_set_encoding (CAMEL_MIME_PART (msg), camel_mime_part_get_encoding (part));
+ } else {
+ /* signed */
+ camel_medium_set_content (CAMEL_MEDIUM (msg), CAMEL_DATA_WRAPPER (part));
}
-
- camel_medium_free_headers (CAMEL_MEDIUM (message), headers);
-
- if (hstr->len && hstr->str)
- set_value (PidTagTransportMessageHeaders, hstr->str);
-
- g_string_free (hstr, TRUE);
+ } else {
+ add_multipart_attachments (multipart_body, noninline_attachments);
}
}
- str = camel_medium_get_header ((CamelMedium *) message, "References");
- if (str)
- set_value (PidTagInternetReferences, str);
-
- str = camel_medium_get_header ((CamelMedium *) message, "In-Reply-To");
- if (str)
- set_value (PidTagInReplyToId, str);
+ if (!skip_set_content && multipart_body)
+ camel_medium_set_content (CAMEL_MEDIUM (msg), CAMEL_DATA_WRAPPER (multipart_body));
- str = camel_medium_get_header ((CamelMedium *) message, "Message-ID");
- if (str)
- set_value (PidTagInternetMessageId, str);
+ if (multipart_body)
+ g_object_unref (multipart_body);
+ g_slist_free_full (inline_attachments, g_object_unref);
+ g_slist_free_full (noninline_attachments, g_object_unref);
+ g_free (ical_string);
- addresses = camel_mime_message_get_recipients (message, CAMEL_RECIPIENT_TYPE_TO);
- e_mapi_mail_add_recipients (object, addresses, olTo);
+ return msg;
+}
- addresses = camel_mime_message_get_recipients (message, CAMEL_RECIPIENT_TYPE_CC);
- e_mapi_mail_add_recipients (object, addresses, olCC);
+static void
+e_mapi_mail_add_recipients (EMapiObject *object,
+ CamelInternetAddress *addresses,
+ OlMailRecipientType recip_type)
+{
+ gint ii;
+ const gchar *name = NULL, *email = NULL;
- addresses = camel_mime_message_get_recipients (message, CAMEL_RECIPIENT_TYPE_BCC);
- e_mapi_mail_add_recipients (object, addresses, olBCC);
+ g_return_if_fail (object != NULL);
- if (camel_content_type_is (content_type, "application", "x-pkcs7-mime") ||
- camel_content_type_is (content_type, "application", "pkcs7-mime")) {
- e_mapi_mail_do_smime_encrypted (object, CAMEL_MEDIUM (message), &msg_class, &pid_name_content_type, cancellable);
- } else {
- CamelDataWrapper *dw = NULL;
- CamelStream *content_stream;
- CamelMultipart *multipart;
+ for (ii = 0; addresses && camel_internet_address_get (addresses, ii, &name, &email); ii++) {
+ EMapiRecipient *recipient;
+ uint32_t ui32 = 0;
+ bool bl;
- /* contents body */
- dw = camel_medium_get_content (CAMEL_MEDIUM (message));
- if (CAMEL_IS_MULTIPART (dw)) {
- gboolean is_first = TRUE;
+ recipient = e_mapi_recipient_new (object);
+ e_mapi_object_add_recipient (object, recipient);
- multipart = CAMEL_MULTIPART (dw);
+ #define set_value(pt,vl) { \
+ if (!e_mapi_utils_add_property (&recipient->properties, pt, vl, recipient)) { \
+ g_warning ("%s: Failed to set property 0x%x", G_STRFUNC, pt); \
+ \
+ return; \
+ } \
+ }
- if (CAMEL_IS_MULTIPART_SIGNED (multipart) && camel_multipart_get_number (multipart) == 2) {
- e_mapi_mail_do_smime_signed (object, multipart, &msg_class, cancellable);
- } else {
- e_mapi_mail_do_multipart (object, multipart, &is_first, cancellable);
- }
- } else if (dw) {
- CamelContentType *type;
- CamelMimePart *part = CAMEL_MIME_PART (message);
+ ui32 = recip_type;
+ set_value (PidTagRecipientType, &ui32);
- content_stream = get_content_stream (part, cancellable);
- type = camel_data_wrapper_get_mime_type_field (dw);
+ if (!name || !*name)
+ name = email;
- if (camel_content_type_is (type, "text", "plain")) {
- e_mapi_mail_add_body (object, content_stream, PidTagBody, cancellable);
- } else if (camel_content_type_is (type, "text", "html")) {
- e_mapi_mail_add_body (object, content_stream, PidTagHtml, cancellable);
- } else {
- e_mapi_mail_add_attach (object, part, content_stream, cancellable);
- }
+ if (name && *name) {
+ set_value (PidTagDisplayName, name);
+ set_value (PidTagRecipientDisplayName, name);
+ }
+ if (email && *email) {
+ set_value (PidTagAddressType, "SMTP");
+ set_value (PidTagEmailAddress, email);
- if (content_stream)
- g_object_unref (content_stream);
+ set_value (PidTagSmtpAddress, email);
+ set_value (PidTagPrimarySmtpAddress, email);
}
- }
- if (msg_class)
- set_value (PidTagMessageClass, msg_class);
+ ui32 = 0;
+ set_value (PidTagSendInternetEncoding, &ui32);
- if (pid_name_content_type)
- set_value (PidNameContentType, pid_name_content_type);
+ ui32 = DT_MAILUSER;
+ set_value (PidTagDisplayType, &ui32);
- g_free (msg_class);
- g_free (pid_name_content_type);
+ ui32 = MAPI_MAILUSER;
+ set_value (PidTagObjectType, &ui32);
- *pobject = object;
+ bl = false;
+ set_value (PidTagSendRichInfo, &bl);
- #undef set_value
+ #undef set_value
- return TRUE;
+ name = NULL;
+ email = NULL;
+ }
}
-static void
-mail_item_add_recipient (const gchar *recipients, OlMailRecipientType type, GSList **recipient_list)
+static CamelStream *
+get_content_stream (CamelMimePart *part, GCancellable *cancellable)
{
- ExchangeMAPIRecipient *recipient;
- uint32_t val = 0;
- uint8_t bVal;
- const gchar *str = NULL;
+ CamelStream *content_stream;
+ CamelStream *filter_stream = NULL;
+ CamelMimeFilterWindows *windows = NULL;
+ CamelDataWrapper *dw;
+
+ g_return_val_if_fail (part != NULL, NULL);
+
+ dw = camel_medium_get_content (CAMEL_MEDIUM (part));
+ g_return_val_if_fail (dw != NULL, NULL);
+
+ content_stream = camel_stream_mem_new();
- if (!recipients)
- return;
+ if (camel_mime_part_get_content_type (part)) {
+ const gchar *charset = camel_content_type_param (camel_mime_part_get_content_type (part), "charset");
- recipient = g_new0 (ExchangeMAPIRecipient, 1);
+ if (charset && *charset && g_ascii_strcasecmp (charset, "utf8") != 0 && g_ascii_strcasecmp (charset, "utf-8") != 0) {
+ if (g_ascii_strncasecmp (charset, "iso-8859-", 9) == 0) {
+ CamelStream *null;
- recipient->email_id = recipients;
+ /* Since a few Windows mailers like to claim they sent
+ * out iso-8859-# encoded text when they really sent
+ * out windows-cp125#, do some simple sanity checking
+ * before we move on... */
- /* this memory should be freed somewhere, perhaps in the existing
- * e_mapi_util_free_recipient_list() */
- recipient->in.req_cValues = 2;
- recipient->in.req_lpProps = g_new0 (struct SPropValue, recipient->in.req_cValues + 1);
+ null = camel_stream_null_new ();
+ filter_stream = camel_stream_filter_new (null);
+ g_object_unref (null);
- set_SPropValue_proptag (&(recipient->in.req_lpProps[0]), PR_RECIPIENT_TYPE, (gconstpointer ) &type);
+ windows = (CamelMimeFilterWindows *)camel_mime_filter_windows_new (charset);
+ camel_stream_filter_add (
+ CAMEL_STREAM_FILTER (filter_stream),
+ CAMEL_MIME_FILTER (windows));
- val = 0;
- set_SPropValue_proptag (&(recipient->in.req_lpProps[1]), PR_SEND_INTERNET_ENCODING, (gconstpointer )&val);
+ camel_data_wrapper_decode_to_stream_sync (
+ dw, (CamelStream *)filter_stream, cancellable, NULL);
+ camel_stream_flush ((CamelStream *)filter_stream, cancellable, NULL);
+ g_object_unref (filter_stream);
- /* External recipient properties - set them only when the recipient is unresolved */
- recipient->in.ext_cValues = 8;
- recipient->in.ext_lpProps = g_new0 (struct SPropValue, recipient->in.ext_cValues + 1);
+ charset = camel_mime_filter_windows_real_charset (windows);
+ }
- val = DT_MAILUSER;
- set_SPropValue_proptag (&(recipient->in.ext_lpProps[0]), PR_DISPLAY_TYPE, (gconstpointer )&val);
- val = MAPI_MAILUSER;
- set_SPropValue_proptag (&(recipient->in.ext_lpProps[1]), PR_OBJECT_TYPE, (gconstpointer )&val);
- str = "SMTP";
- set_SPropValue_proptag (&(recipient->in.ext_lpProps[2]), PR_ADDRTYPE_UNICODE, (gconstpointer )(str));
- str = recipient->email_id;
- set_SPropValue_proptag (&(recipient->in.ext_lpProps[3]), PR_SMTP_ADDRESS_UNICODE, (gconstpointer )(str));
- /* FIXME: Please add the correct names here instead of the e-mail ID */
- set_SPropValue_proptag (&(recipient->in.ext_lpProps[4]), PR_GIVEN_NAME_UNICODE, (gconstpointer )(str));
- set_SPropValue_proptag (&(recipient->in.ext_lpProps[5]), PR_DISPLAY_NAME_UNICODE, (gconstpointer )(str));
- set_SPropValue_proptag (&(recipient->in.ext_lpProps[6]), PR_7BIT_DISPLAY_NAME_UNICODE, (gconstpointer )(str));
+ if (charset && *charset) {
+ CamelMimeFilter *filter;
- bVal = FALSE;
- set_SPropValue_proptag (&(recipient->in.ext_lpProps[7]), PR_SEND_RICH_INFO, &bVal);
+ filter_stream = camel_stream_filter_new (content_stream);
- *recipient_list = g_slist_append (*recipient_list, recipient);
-}
+ if ((filter = camel_mime_filter_charset_new (charset, "UTF-8"))) {
+ camel_stream_filter_add (
+ CAMEL_STREAM_FILTER (filter_stream),
+ CAMEL_MIME_FILTER (filter));
+ g_object_unref (filter);
+ } else {
+ g_object_unref (filter_stream);
+ filter_stream = NULL;
+ }
+ }
+ }
+ }
-static void
-mail_item_set_from(MailItem *item, const gchar *from_name, const gchar *from_email)
-{
- if (item->header.from)
- g_free (item->header.from);
- if (item->header.from_email)
- g_free (item->header.from_email);
+ if (filter_stream) {
+ camel_data_wrapper_decode_to_stream_sync (dw, (CamelStream *) filter_stream, cancellable, NULL);
+ camel_stream_flush (filter_stream, cancellable, NULL);
+ g_object_unref (filter_stream);
+ } else {
+ camel_data_wrapper_decode_to_stream_sync (dw, (CamelStream *) content_stream, cancellable, NULL);
+ }
- item->header.from = g_strdup (from_name);
- item->header.from_email = g_strdup (from_email);
-}
+ if (windows)
+ g_object_unref (windows);
-static void
-mail_item_set_subject(MailItem *item, const gchar *subject)
-{
- if (item->header.subject)
- g_free (item->header.subject);
+ g_seekable_seek (G_SEEKABLE (content_stream), 0, G_SEEK_SET, NULL, NULL);
- item->header.subject = g_strdup (subject);
+ return content_stream;
}
-#define MAX_READ_SIZE 0x1000
-
static void
-mail_item_set_body_stream (MailItem *item, CamelStream *body, MailItemPartType part_type, GCancellable *cancellable)
+e_mapi_mail_content_stream_to_bin (CamelStream *content_stream,
+ struct SBinary_short *bin,
+ TALLOC_CTX *mem_ctx,
+ GCancellable *cancellable)
{
- guint8 *buf = g_new0 (guint8 , STREAM_SIZE);
- guint32 read_size = 0, i;
- ExchangeMAPIStream *stream = g_new0 (ExchangeMAPIStream, 1);
- gboolean contains_only_7bit = TRUE, is_null_terminated = FALSE;
-
- g_seekable_seek (G_SEEKABLE (body), 0, G_SEEK_SET, NULL, NULL);
+ guint8 *buf;
+ guint32 read_size;
- stream->value = g_byte_array_new ();
+ g_return_if_fail (content_stream != NULL);
+ g_return_if_fail (bin != NULL);
+ g_return_if_fail (mem_ctx != NULL);
- while (read_size = camel_stream_read (body, (gchar *)buf, STREAM_SIZE, cancellable, NULL), read_size > 0) {
- stream->value = g_byte_array_append (stream->value, buf, read_size);
+ buf = g_new0 (guint8 , STREAM_SIZE);
- is_null_terminated = buf [read_size - 1] == 0;
+ bin->cb = 0;
+ bin->lpb = NULL;
- for (i = 0; i < read_size && contains_only_7bit; i++) {
- contains_only_7bit = buf[i] < 128;
- }
+ g_seekable_seek (G_SEEKABLE (content_stream), 0, G_SEEK_SET, NULL, NULL);
+ while (read_size = camel_stream_read (content_stream, (gchar *) buf, STREAM_SIZE, cancellable, NULL), read_size > 0) {
+ bin->lpb = talloc_realloc (mem_ctx, bin->lpb, uint8_t, bin->cb + read_size);
+ memcpy (bin->lpb + bin->cb, buf, read_size);
+ bin->cb += read_size;
}
g_free (buf);
+}
- switch (part_type) {
- case PART_TYPE_TEXT_HTML :
- stream->proptag = PR_HTML;
- break;
- case PART_TYPE_PLAIN_TEXT:
- stream->proptag = PR_BODY_UNICODE;
- break;
- }
-
- if (stream->value->len < MAX_READ_SIZE && contains_only_7bit) {
- if (!is_null_terminated)
- g_byte_array_append (stream->value, (const guint8 *)"", 1);
-
- item->msg.body_parts = g_slist_append (item->msg.body_parts, stream);
- } else if (stream->proptag == PR_HTML) {
- /* PR_HTML shouldn't be in UTF-16 */
- if (!is_null_terminated)
- g_byte_array_append (stream->value, (const guint8 *)"", 1);
-
- item->generic_streams = g_slist_append (item->generic_streams, stream);
- } else {
- gsize written = 0;
- gchar *in_unicode;
-
- if (is_null_terminated)
- stream->value->len--;
-
- /* convert to unicode, because stream is supposed to be in it */
- in_unicode = g_convert ((const gchar *)stream->value->data, stream->value->len, "UTF-16", "UTF-8", NULL, &written, NULL);
- if (in_unicode && written > 0) {
- g_byte_array_set_size (stream->value, 0);
- /* skip Unicode marker, if there */
- if (written >= 2 && (const guchar) in_unicode[0] == 0xFF && (const guchar) in_unicode[1] == 0xFE)
- g_byte_array_append (stream->value, (const guint8 *) in_unicode + 2, written - 2);
- else
- g_byte_array_append (stream->value, (const guint8 *) in_unicode, written);
-
- /* null-terminated unicode string */
- g_byte_array_append (stream->value, (const guint8 *)"", 1);
- g_byte_array_append (stream->value, (const guint8 *)"", 1);
- }
- g_free (in_unicode);
-
- item->generic_streams = g_slist_append (item->generic_streams, stream);
- }
-
+#define set_attach_value(pt,vl) { \
+ if (!e_mapi_utils_add_property (&attach->properties, pt, vl, attach)) { \
+ g_warning ("%s: Failed to set property 0x%x", G_STRFUNC, pt); \
+ return FALSE; \
+ } \
}
static gboolean
-mail_item_add_attach (MailItem *item, CamelMimePart *part, CamelStream *content_stream, GCancellable *cancellable)
+e_mapi_mail_add_attach (EMapiObject *object,
+ CamelMimePart *part,
+ CamelStream *content_stream,
+ GCancellable *cancellable)
{
- guint8 *buf = g_new0 (guint8 , STREAM_SIZE);
- const gchar *content_id = NULL;
- guint32 read_size, flag, i = 0;
+ EMapiAttachment *attach;
CamelContentType *content_type;
+ const gchar *content_id;
+ const gchar *filename;
+ struct SBinary_short bin;
+ uint32_t ui32;
- ExchangeMAPIAttachment *item_attach;
- ExchangeMAPIStream *stream;
-
- const gchar *filename = camel_mime_part_get_filename (part);
-
- item_attach = g_new0 (ExchangeMAPIAttachment, 1);
-
- item_attach->lpProps = g_new0 (struct SPropValue, 6 + 1);
+ g_return_val_if_fail (object != NULL, FALSE);
+ g_return_val_if_fail (part != NULL, FALSE);
+ g_return_val_if_fail (content_stream != NULL, FALSE);
- flag = ATTACH_BY_VALUE;
- set_SPropValue_proptag(&(item_attach->lpProps[i++]), PR_ATTACH_METHOD, (gconstpointer ) (&flag));
+ attach = e_mapi_attachment_new (object);
+ e_mapi_object_add_attachment (object, attach);
- /* MSDN Documentation: When the supplied offset is -1 (0xFFFFFFFF), the
- * attachment is not rendered using the PR_RENDERING_POSITION property.
- * All values other than -1 indicate the position within PR_BODY at which
- * the attachment is to be rendered.
- */
- flag = 0xFFFFFFFF;
- set_SPropValue_proptag(&(item_attach->lpProps[i++]), PR_RENDERING_POSITION, (gconstpointer ) (&flag));
+ ui32 = ATTACH_BY_VALUE;
+ set_attach_value (PidTagAttachMethod, &ui32);
+ ui32 = -1;
+ set_attach_value (PidTagRenderingPosition, &ui32);
+ filename = camel_mime_part_get_filename (part);
if (filename) {
- set_SPropValue_proptag(&(item_attach->lpProps[i++]),
- PR_ATTACH_FILENAME_UNICODE,
- (gconstpointer ) g_strdup(filename));
-
- set_SPropValue_proptag(&(item_attach->lpProps[i++]),
- PR_ATTACH_LONG_FILENAME_UNICODE,
- (gconstpointer ) g_strdup(filename));
+ set_attach_value (PidTagAttachFilename, filename);
+ set_attach_value (PidTagAttachLongFilename, filename);
}
- /* mime type : multipart/related */
content_id = camel_mime_part_get_content_id (part);
- if (content_id) {
- set_SPropValue_proptag(&(item_attach->lpProps[i++]),
- PR_ATTACH_CONTENT_ID,
- (gconstpointer ) g_strdup(content_id));
- }
+ if (content_id)
+ set_attach_value (PidTagAttachContentId, content_id);
content_type = camel_mime_part_get_content_type (part);
if (content_type) {
gchar *ct = camel_content_type_simple (content_type);
- if (ct) {
- set_SPropValue_proptag (&(item_attach->lpProps[i++]),
- PR_ATTACH_MIME_TAG,
- (gconstpointer ) ct);
- }
+ if (ct)
+ set_attach_value (PidTagAttachMimeTag, ct);
+ g_free (ct);
}
- item_attach->cValues = i;
+ e_mapi_mail_content_stream_to_bin (content_stream, &bin, attach, cancellable);
+ set_attach_value (PidTagAttachDataBinary, &bin);
- stream = g_new0 (ExchangeMAPIStream, 1);
- stream->proptag = PR_ATTACH_DATA_BIN;
- stream->value = g_byte_array_new ();
+ return TRUE;
+}
- g_seekable_seek (G_SEEKABLE (content_stream), 0, G_SEEK_SET, NULL, NULL);
- while (read_size = camel_stream_read(content_stream, (gchar *)buf, STREAM_SIZE, cancellable, NULL), read_size > 0) {
- stream->value = g_byte_array_append (stream->value, buf, read_size);
- }
+static gboolean
+e_mapi_mail_add_body (EMapiObject *object,
+ CamelStream *content_stream,
+ uint32_t proptag,
+ GCancellable *cancellable)
+{
+ struct SBinary_short bin = { 0 };
+ gchar *str;
+
+ e_mapi_mail_content_stream_to_bin (content_stream, &bin, object, cancellable);
+ str = talloc_strndup (object, (const gchar *) bin.lpb, bin.cb);
+ talloc_free (bin.lpb);
- item_attach->streams = g_slist_append (item_attach->streams, stream);
- item->attachments = g_slist_append(item->attachments, item_attach);
+ if ((proptag & 0xFFFF) == PT_BINARY) {
+ bin.lpb = (uint8_t *) (str ? str : "");
+ bin.cb = strlen ((const gchar *) bin.lpb) + 1;
+ /* include trailing zero ................ ^^^ */
- g_free (buf);
+ return e_mapi_utils_add_property (&object->properties, proptag, &bin, object);
+ } else if (str) {
+ if (!e_mapi_utils_add_property (&object->properties, proptag, str, object)) {
+ talloc_free (str);
+ return FALSE;
+ }
+
+ talloc_free (str);
+ } else {
+ return e_mapi_utils_add_property (&object->properties, proptag, "", object);
+ }
return TRUE;
}
-static void
-mapi_do_smime_signed (MailItem *item, CamelMultipart *multipart, GCancellable *cancellable, GError **error)
+static gboolean
+e_mapi_mail_do_smime_encrypted (EMapiObject *object,
+ CamelMedium *message,
+ gchar **pmsg_class,
+ gchar **ppid_name_content_type,
+ GCancellable *cancellable)
{
- CamelMimePart *content, *signature;
- ExchangeMAPIAttachment *item_attach;
- ExchangeMAPIStream *stream;
+ EMapiAttachment *attach;
CamelStream *content_stream;
- CamelContentType *type;
CamelDataWrapper *dw;
+ CamelContentType *type;
uint32_t ui32;
- guint8 *buf;
- guint32 read_size;
+ struct SBinary_short bin;
gchar *content_type_str;
- g_free (item->msg_class);
- item->msg_class = g_strdup ("IPM.Note.SMIME.MultipartSigned");
-
- content = camel_multipart_get_part (multipart, CAMEL_MULTIPART_SIGNED_CONTENT);
- signature = camel_multipart_get_part (multipart, CAMEL_MULTIPART_SIGNED_SIGNATURE);
-
- g_return_if_fail (content != NULL);
- g_return_if_fail (signature != NULL);
-
- content_stream = get_content_stream (content, cancellable);
- type = camel_mime_part_get_content_type (content);
-
- if (camel_content_type_is (type, "text", "plain")) {
- mail_item_set_body_stream (item, content_stream, PART_TYPE_PLAIN_TEXT, cancellable);
- } else if (camel_content_type_is (type, "text", "html")) {
- mail_item_set_body_stream (item, content_stream, PART_TYPE_TEXT_HTML, cancellable);
- } else {
- mail_item_add_attach (item, content, content_stream, cancellable);
- }
+ g_return_val_if_fail (object != NULL, FALSE);
+ g_return_val_if_fail (message != NULL, FALSE);
+ g_return_val_if_fail (pmsg_class != NULL, FALSE);
+ g_return_val_if_fail (ppid_name_content_type != NULL, FALSE);
- if (content_stream)
- g_object_unref (content_stream);
+ g_free (*pmsg_class);
+ *pmsg_class = g_strdup ("IPM.Note.SMIME");
- content_stream = camel_stream_mem_new ();
- dw = CAMEL_DATA_WRAPPER (multipart);
- type = camel_data_wrapper_get_mime_type_field (dw);
+ type = camel_data_wrapper_get_mime_type_field (CAMEL_DATA_WRAPPER (message));
+ dw = camel_medium_get_content (message);
content_type_str = camel_content_type_format (type);
- #define wstr(str) camel_stream_write (content_stream, str, strlen (str), cancellable, NULL)
- wstr("Content-Type: ");
- wstr(content_type_str);
- wstr("\n\n");
- #undef wstr
-
- g_free (content_type_str);
+ g_free (*ppid_name_content_type);
+ *ppid_name_content_type = content_type_str; /* will be freed within the caller */
- camel_data_wrapper_write_to_stream_sync (dw, (CamelStream *) content_stream, cancellable, NULL);
+ content_stream = camel_stream_mem_new ();
+ camel_data_wrapper_decode_to_stream_sync (dw, (CamelStream *) content_stream, cancellable, NULL);
- item_attach = g_new0 (ExchangeMAPIAttachment, 1);
- item_attach->lpProps = g_new0 (struct SPropValue, 6 + 1);
- item_attach->cValues = 6;
+ attach = e_mapi_attachment_new (object);
+ e_mapi_object_add_attachment (object, attach);
ui32 = ATTACH_BY_VALUE;
- set_SPropValue_proptag (&(item_attach->lpProps[0]), PR_ATTACH_METHOD, &ui32);
+ set_attach_value (PidTagAttachMethod, &ui32);
ui32 = -1;
- set_SPropValue_proptag (&(item_attach->lpProps[1]), PR_RENDERING_POSITION, &ui32);
- set_SPropValue_proptag (&(item_attach->lpProps[2]), PR_ATTACH_MIME_TAG, "multipart/signed");
- set_SPropValue_proptag (&(item_attach->lpProps[3]), PR_ATTACH_FILENAME_UNICODE, "SMIME.txt");
- set_SPropValue_proptag (&(item_attach->lpProps[4]), PR_ATTACH_LONG_FILENAME_UNICODE, "SMIME.txt");
- set_SPropValue_proptag (&(item_attach->lpProps[5]), PR_DISPLAY_NAME_UNICODE, "SMIME.txt");
-
- stream = g_new0 (ExchangeMAPIStream, 1);
- stream->proptag = PR_ATTACH_DATA_BIN;
- stream->value = g_byte_array_new ();
-
- buf = g_new0 (guint8 , STREAM_SIZE);
+ set_attach_value (PidTagRenderingPosition, &ui32);
+ set_attach_value (PidTagAttachMimeTag, content_type_str);
+ set_attach_value (PidTagAttachFilename, "SMIME.txt");
+ set_attach_value (PidTagAttachLongFilename, "SMIME.txt");
+ set_attach_value (PidTagDisplayName, "SMIME.txt");
- g_seekable_seek (G_SEEKABLE (content_stream), 0, G_SEEK_SET, NULL, NULL);
- while (read_size = camel_stream_read (content_stream, (gchar *) buf, STREAM_SIZE, cancellable, NULL), read_size > 0) {
- stream->value = g_byte_array_append (stream->value, buf, read_size);
- }
+ e_mapi_mail_content_stream_to_bin (content_stream, &bin, attach, cancellable);
+ set_attach_value (PidTagAttachDataBinary, &bin);
- g_free (buf);
g_object_unref (content_stream);
- item_attach->streams = g_slist_append (item_attach->streams, stream);
- item->attachments = g_slist_append (item->attachments, item_attach);
+ return TRUE;
}
-static void
-mapi_do_smime_encrypted (MailItem *item, CamelMedium *message, GCancellable *cancellable, GError **error)
+static gboolean
+e_mapi_mail_do_smime_signed (EMapiObject *object,
+ CamelMultipart *multipart,
+ gchar **pmsg_class,
+ GCancellable *cancellable)
{
- ExchangeMAPIAttachment *item_attach;
- ExchangeMAPIStream *stream;
+ EMapiAttachment *attach;
+ CamelMimePart *content, *signature;
CamelStream *content_stream;
- CamelDataWrapper *dw;
CamelContentType *type;
+ CamelDataWrapper *dw;
uint32_t ui32;
- guint8 *buf;
- guint32 read_size;
+ struct SBinary_short bin;
gchar *content_type_str;
- g_free (item->msg_class);
- item->msg_class = g_strdup ("IPM.Note.SMIME");
+ g_free (*pmsg_class);
+ *pmsg_class = g_strdup ("IPM.Note.SMIME.MultipartSigned");
- type = camel_data_wrapper_get_mime_type_field (CAMEL_DATA_WRAPPER (message));
- dw = camel_medium_get_content (message);
+ content = camel_multipart_get_part (multipart, CAMEL_MULTIPART_SIGNED_CONTENT);
+ signature = camel_multipart_get_part (multipart, CAMEL_MULTIPART_SIGNED_SIGNATURE);
+
+ g_return_val_if_fail (content != NULL, FALSE);
+ g_return_val_if_fail (signature != NULL, FALSE);
+
+ content_stream = get_content_stream (content, cancellable);
+ type = camel_mime_part_get_content_type (content);
+
+ if (camel_content_type_is (type, "text", "plain")) {
+ e_mapi_mail_add_body (object, content_stream, PidTagBody, cancellable);
+ } else if (camel_content_type_is (type, "text", "html")) {
+ e_mapi_mail_add_body (object, content_stream, PidTagHtml, cancellable);
+ } else {
+ e_mapi_mail_add_attach (object, content, content_stream, cancellable);
+ }
+
+ if (content_stream)
+ g_object_unref (content_stream);
+ content_stream = camel_stream_mem_new ();
+ dw = CAMEL_DATA_WRAPPER (multipart);
+ type = camel_data_wrapper_get_mime_type_field (dw);
content_type_str = camel_content_type_format (type);
- g_free (item->pid_name_content_type);
- item->pid_name_content_type = content_type_str; /* will be freed with the MailItem structure */
+ #define wstr(str) camel_stream_write (content_stream, str, strlen (str), cancellable, NULL)
+ wstr("Content-Type: ");
+ wstr(content_type_str);
+ wstr("\n\n");
+ #undef wstr
+
+ g_free (content_type_str);
- content_stream = camel_stream_mem_new ();
- camel_data_wrapper_decode_to_stream_sync (dw, (CamelStream *) content_stream, cancellable, NULL);
+ camel_data_wrapper_write_to_stream_sync (dw, (CamelStream *) content_stream, cancellable, NULL);
- item_attach = g_new0 (ExchangeMAPIAttachment, 1);
- item_attach->lpProps = g_new0 (struct SPropValue, 6 + 1);
- item_attach->cValues = 6;
+ attach = e_mapi_attachment_new (object);
+ e_mapi_object_add_attachment (object, attach);
ui32 = ATTACH_BY_VALUE;
- set_SPropValue_proptag (&(item_attach->lpProps[0]), PR_ATTACH_METHOD, &ui32);
+ set_attach_value (PidTagAttachMethod, &ui32);
ui32 = -1;
- set_SPropValue_proptag (&(item_attach->lpProps[1]), PR_RENDERING_POSITION, &ui32);
- set_SPropValue_proptag (&(item_attach->lpProps[2]), PR_ATTACH_MIME_TAG, content_type_str);
- set_SPropValue_proptag (&(item_attach->lpProps[3]), PR_ATTACH_FILENAME_UNICODE, "SMIME.txt");
- set_SPropValue_proptag (&(item_attach->lpProps[4]), PR_ATTACH_LONG_FILENAME_UNICODE, "SMIME.txt");
- set_SPropValue_proptag (&(item_attach->lpProps[5]), PR_DISPLAY_NAME_UNICODE, "SMIME.txt");
-
- stream = g_new0 (ExchangeMAPIStream, 1);
- stream->proptag = PR_ATTACH_DATA_BIN;
- stream->value = g_byte_array_new ();
-
- buf = g_new0 (guint8 , STREAM_SIZE);
+ set_attach_value (PidTagRenderingPosition, &ui32);
+ set_attach_value (PidTagAttachMimeTag, "multipart/signed");
+ set_attach_value (PidTagAttachFilename, "SMIME.txt");
+ set_attach_value (PidTagAttachLongFilename, "SMIME.txt");
+ set_attach_value (PidTagDisplayName, "SMIME.txt");
- g_seekable_seek (G_SEEKABLE (content_stream), 0, G_SEEK_SET, NULL, NULL);
- while (read_size = camel_stream_read (content_stream, (gchar *) buf, STREAM_SIZE, cancellable, NULL), read_size > 0) {
- stream->value = g_byte_array_append (stream->value, buf, read_size);
- }
+ e_mapi_mail_content_stream_to_bin (content_stream, &bin, attach, cancellable);
+ set_attach_value (PidTagAttachDataBinary, &bin);
- g_free (buf);
g_object_unref (content_stream);
- item_attach->streams = g_slist_append (item_attach->streams, stream);
- item->attachments = g_slist_append (item->attachments, item_attach);
+ return TRUE;
}
static gboolean
-mapi_do_multipart (CamelMultipart *mp, MailItem *item, gboolean *is_first, GCancellable *cancellable)
+e_mapi_mail_do_multipart (EMapiObject *object,
+ CamelMultipart *mp,
+ gboolean *is_first,
+ GCancellable *cancellable)
{
CamelDataWrapper *dw;
CamelStream *content_stream;
CamelContentType *type;
CamelMimePart *part;
- gint n_part, i_part;
+ gint nn, ii;
g_return_val_if_fail (is_first != NULL, FALSE);
- n_part = camel_multipart_get_number(mp);
- for (i_part = 0; i_part < n_part; i_part++) {
+ nn = camel_multipart_get_number (mp);
+ for (ii = 0; ii < nn; ii++) {
/* getting part */
- part = camel_multipart_get_part(mp, i_part);
+ part = camel_multipart_get_part (mp, ii);
+ if (!part)
+ continue;
+
dw = camel_medium_get_content (CAMEL_MEDIUM (part));
- if (CAMEL_IS_MULTIPART(dw)) {
+ if (CAMEL_IS_MULTIPART (dw)) {
/* recursive */
- if (!mapi_do_multipart (CAMEL_MULTIPART (dw), item, is_first, cancellable))
+ if (!e_mapi_mail_do_multipart (object, CAMEL_MULTIPART (dw), is_first, cancellable))
return FALSE;
continue;
}
if (CAMEL_IS_MIME_MESSAGE (dw)) {
CamelMimeMessage *message;
- CamelInternetAddress *message_from;
- CamelAddress *use_from = NULL;
- MailItem *mail;
+ EMapiObject *embedded = NULL;
+ EMapiAttachment *attach;
+ attach = e_mapi_attachment_new (object);
message = CAMEL_MIME_MESSAGE (dw);
- message_from = camel_mime_message_get_from (message);
- if (message_from)
- use_from = CAMEL_ADDRESS (message_from);
- mail = mapi_mime_message_to_mail_item (message, 0, use_from, cancellable, NULL);
- if (mail) {
- ExchangeMAPIAttachment *item_attach = g_new0 (ExchangeMAPIAttachment, 1);
+ if (e_mapi_mail_utils_message_to_object (message, 0, E_MAPI_CREATE_FLAG_NONE, &embedded, attach, cancellable, NULL)) {
+ uint32_t ui32;
+ const gchar *str;
+
+ e_mapi_object_add_attachment (object, attach);
+ attach->embedded_object = embedded;
+ embedded->parent = object;
- item_attach->mail = mail;
- item->attachments = g_slist_append (item->attachments, item_attach);
+ ui32 = ATTACH_EMBEDDED_MSG;
+ set_attach_value (PidTagAttachMethod, &ui32);
+ ui32 = 0;
+ set_attach_value (PidTagRenderingPosition, &ui32);
+ set_attach_value (PidTagAttachMimeTag, "message/rfc822");
+ str = camel_mime_message_get_subject (message);
+ if (str)
+ set_attach_value (PidTagAttachFilename, str);
continue;
+ } else {
+ e_mapi_attachment_free (attach);
}
}
content_stream = get_content_stream (part, cancellable);
+ type = camel_mime_part_get_content_type (part);
- type = camel_mime_part_get_content_type(part);
-
- if (i_part == 0 && (*is_first) && camel_content_type_is (type, "text", "plain")) {
- mail_item_set_body_stream (item, content_stream, PART_TYPE_PLAIN_TEXT, cancellable);
+ if (ii == 0 && (*is_first) && camel_content_type_is (type, "text", "plain")) {
+ e_mapi_mail_add_body (object, content_stream, PidTagBody, cancellable);
*is_first = FALSE;
} else if (camel_content_type_is (type, "text", "html")) {
- mail_item_set_body_stream (item, content_stream, PART_TYPE_TEXT_HTML, cancellable);
+ e_mapi_mail_add_body (object, content_stream, PidTagHtml, cancellable);
} else {
- mail_item_add_attach (item, part, content_stream, cancellable);
+ e_mapi_mail_add_attach (object, part, content_stream, cancellable);
}
if (content_stream)
@@ -2839,225 +1270,201 @@ mapi_do_multipart (CamelMultipart *mp, MailItem *item, gboolean *is_first, GCanc
return TRUE;
}
-static void
-mail_item_set_time (time_t *item_time, time_t camel_time, gint camel_offset)
-{
- if (camel_time == CAMEL_MESSAGE_DATE_CURRENT) {
- *item_time = 0;
- } else {
- /* Convert to UTC */
- /*camel_time -= (camel_offset / 100) * 60 * 60;
- camel_time -= (camel_offset % 100) * 60;*/
- *item_time = camel_time;
- }
-}
+#undef set_attach_value
-MailItem *
-mapi_mime_message_to_mail_item (CamelMimeMessage *message, gint32 message_camel_flags, CamelAddress *from, GCancellable *cancellable, GError **error)
+gboolean
+e_mapi_mail_utils_message_to_object (struct _CamelMimeMessage *message,
+ guint32 message_camel_flags,
+ EMapiCreateFlags create_flags,
+ EMapiObject **pobject,
+ TALLOC_CTX *mem_ctx,
+ GCancellable *cancellable,
+ GError **perror)
{
- CamelDataWrapper *dw = NULL;
- CamelStream *content_stream;
- CamelMultipart *multipart;
+ EMapiObject *object;
CamelContentType *content_type;
- CamelInternetAddress *to, *cc, *bcc;
- MailItem *item = g_new0 (MailItem, 1);
- const gchar *namep = NULL;
- const gchar *addressp = NULL;
- time_t msg_time = 0;
- gint msg_time_offset = 0;
- GArray *headers;
+ CamelInternetAddress *addresses;
+ const gchar *namep = NULL, *addressp = NULL;
+ const gchar *str;
+ gchar *msg_class = NULL;
+ gchar *pid_name_content_type = NULL;
+ gint ii = 0;
+ uint32_t ui32;
+ bool bl;
- GSList *recipient_list = NULL;
- gint i = 0;
+ g_return_val_if_fail (message != NULL, FALSE);
+ g_return_val_if_fail (pobject != NULL, FALSE);
+ g_return_val_if_fail (*pobject == NULL, FALSE);
+ g_return_val_if_fail (mem_ctx != NULL, FALSE);
- /* headers */
+ content_type = camel_data_wrapper_get_mime_type_field (CAMEL_DATA_WRAPPER (message));
+ g_return_val_if_fail (content_type != NULL, FALSE);
- if (from) {
- if (!camel_internet_address_get ((CamelInternetAddress *)from, 0, &namep, &addressp)) {
- g_warning ("%s: Invalid 'from' passed in", G_STRFUNC);
- g_free (item);
- return NULL;
- }
- } else {
+ /* headers */
+ if ((create_flags & E_MAPI_CREATE_FLAG_SUBMIT) == 0) {
/* though invalid, then possible, to pass in a message without any 'from' */
- namep = NULL;
+ CamelInternetAddress *from = camel_mime_message_get_from (message);
+ if (!from || !camel_internet_address_get (from, 0, &namep, &addressp))
+ namep = NULL;
}
- item->header.flags = 0;
- if (message_camel_flags & CAMEL_MESSAGE_SEEN)
- item->header.flags |= MSGFLAG_READ;
- if (message_camel_flags & CAMEL_MESSAGE_ATTACHMENTS)
- item->header.flags |= MSGFLAG_HASATTACH;
-
- mail_item_set_from (item, namep, addressp);
-
- msg_time = camel_mime_message_get_date (message, &msg_time_offset);
- if (msg_time == CAMEL_MESSAGE_DATE_CURRENT)
- msg_time = camel_mime_message_get_date_received (message, &msg_time_offset);
- mail_item_set_time (&item->header.recieved_time, msg_time, msg_time_offset);
+ object = e_mapi_object_new (mem_ctx);
- to = camel_mime_message_get_recipients(message, CAMEL_RECIPIENT_TYPE_TO);
- for (i = 0; to && camel_internet_address_get (to, i, &namep, &addressp); i++) {
- mail_item_add_recipient (addressp, olTo, &recipient_list);
+ #define set_value(pt,vl) { \
+ if (!e_mapi_utils_add_property (&object->properties, pt, vl, object)) { \
+ e_mapi_object_free (object); \
+ g_free (msg_class); \
+ g_free (pid_name_content_type); \
+ \
+ g_warning ("%s: Failed to set property 0x%x", G_STRFUNC, pt); \
+ \
+ return FALSE; \
+ } \
}
- cc = camel_mime_message_get_recipients(message, CAMEL_RECIPIENT_TYPE_CC);
- for (i = 0; cc && camel_internet_address_get (cc, i, &namep, &addressp); i++) {
- mail_item_add_recipient (addressp, olCC, &recipient_list);
- }
+ ui32 = 65001; /* UTF8 - also used with PR_HTML */
+ set_value (PidTagInternetCodepage, &ui32);
- bcc = camel_mime_message_get_recipients(message, CAMEL_RECIPIENT_TYPE_BCC);
- for (i = 0; bcc && camel_internet_address_get (bcc, i, &namep, &addressp); i++) {
- mail_item_add_recipient (addressp, olBCC, &recipient_list);
+ if ((create_flags & E_MAPI_CREATE_FLAG_SUBMIT) == 0) {
+ ui32 = 0;
+ if (message_camel_flags & CAMEL_MESSAGE_SEEN)
+ ui32 |= MSGFLAG_READ;
+ if (message_camel_flags & CAMEL_MESSAGE_ATTACHMENTS)
+ ui32 |= MSGFLAG_HASATTACH;
+ } else {
+ ui32 = MSGFLAG_UNSENT;
}
+ set_value (PidTagMessageFlags, &ui32);
- if (camel_mime_message_get_subject(message)) {
- mail_item_set_subject(item, camel_mime_message_get_subject(message));
- }
+ bl = false;
+ set_value (PidTagSendRichInfo, &bl);
- headers = camel_medium_get_headers (CAMEL_MEDIUM (message));
- if (headers) {
- GString *hstr = g_string_new ("");
- gint i;
+ /* PidTagConversationTopic and PidTagNormalizedSubject, together with PidTagSubjectPrefix
+ are computed from PidTagSubject by a server */
+ str = camel_mime_message_get_subject (message);
+ if (str)
+ set_value (PidTagSubject, str);
- for (i = 0; i < headers->len; i++) {
- CamelMediumHeader *h = &g_array_index (headers, CamelMediumHeader, i);
+ /* some properties may not be set when submitting a message */
+ if ((create_flags & E_MAPI_CREATE_FLAG_SUBMIT) == 0) {
+ time_t msg_time = 0;
+ gint msg_time_offset = 0;
+ GArray *headers;
- if (!h->name || !*h->name || g_ascii_strncasecmp (h->name, "X-Evolution", 11) == 0)
- continue;
+ if (namep && *namep)
+ set_value (PidTagSentRepresentingName, namep);
- g_string_append_printf (hstr, "%s: %s\n", h->name, h->value ? h->value : "");
+ if (addressp && *addressp) {
+ set_value (PidTagSentRepresentingAddressType, "SMTP");
+ set_value (PidTagSentRepresentingEmailAddress, addressp);
}
- camel_medium_free_headers (CAMEL_MEDIUM (message), headers);
-
- item->header.transport_headers = g_string_free (hstr, hstr->len == 0);
- }
-
- /*Add message threading properties */
- item->header.references = g_strdup (camel_medium_get_header ((CamelMedium *) message, "References"));
- item->header.in_reply_to = g_strdup (camel_medium_get_header ((CamelMedium *) message, "In-Reply-To"));
- item->header.message_id = g_strdup (camel_medium_get_header ((CamelMedium *) message, "Message-ID"));
+ msg_time = camel_mime_message_get_date (message, &msg_time_offset);
+ if (msg_time == CAMEL_MESSAGE_DATE_CURRENT)
+ msg_time = camel_mime_message_get_date_received (message, &msg_time_offset);
+ if (msg_time != 0) {
+ struct FILETIME msg_date = { 0 };
- item->recipients = recipient_list;
+ e_mapi_util_time_t_to_filetime (msg_time, &msg_date);
- content_type = camel_data_wrapper_get_mime_type_field (CAMEL_DATA_WRAPPER (message));
- g_return_val_if_fail (content_type != NULL, item);
+ set_value (PidTagMessageDeliveryTime, &msg_date);
+ }
- if (camel_content_type_is (content_type, "application", "x-pkcs7-mime") || camel_content_type_is (content_type, "application", "pkcs7-mime")) {
- mapi_do_smime_encrypted (item, CAMEL_MEDIUM (message), cancellable, error);
- } else {
- /* contents body */
- dw = camel_medium_get_content (CAMEL_MEDIUM (message));
+ headers = camel_medium_get_headers (CAMEL_MEDIUM (message));
+ if (headers) {
+ GString *hstr = g_string_new ("");
- if (CAMEL_IS_MULTIPART (dw)) {
- gboolean is_first = TRUE;
+ for (ii = 0; ii < headers->len; ii++) {
+ CamelMediumHeader *h = &g_array_index (headers, CamelMediumHeader, ii);
- multipart = CAMEL_MULTIPART (dw);
+ if (!h->name || !*h->name || g_ascii_strncasecmp (h->name, "X-Evolution", 11) == 0)
+ continue;
- if (CAMEL_IS_MULTIPART_SIGNED (multipart) && camel_multipart_get_number (multipart) == 2) {
- mapi_do_smime_signed (item, multipart, cancellable, error);
- } else {
- mapi_do_multipart (multipart, item, &is_first, cancellable);
+ g_string_append_printf (hstr, "%s: %s\n", h->name, h->value ? h->value : "");
}
- } else if (dw) {
- content_stream = get_content_stream ((CamelMimePart *) message, cancellable);
- mail_item_set_body_stream (item, content_stream, PART_TYPE_PLAIN_TEXT, cancellable);
+ camel_medium_free_headers (CAMEL_MEDIUM (message), headers);
+
+ if (hstr->len && hstr->str)
+ set_value (PidTagTransportMessageHeaders, hstr->str);
- if (content_stream)
- g_object_unref (content_stream);
+ g_string_free (hstr, TRUE);
}
}
- return item;
-}
+ str = camel_medium_get_header ((CamelMedium *) message, "References");
+ if (str)
+ set_value (PidTagInternetReferences, str);
-gboolean
-mapi_mail_utils_create_item_build_props (EMapiConnection *conn,
- mapi_id_t fid,
- TALLOC_CTX *mem_ctx,
- struct SPropValue **values,
- uint32_t *n_values,
- gpointer data,
- GCancellable *cancellable,
- GError **perror)
-{
+ str = camel_medium_get_header ((CamelMedium *) message, "In-Reply-To");
+ if (str)
+ set_value (PidTagInReplyToId, str);
- MailItem *item = (MailItem *) data;
- GSList *l;
- bool send_rich_info;
- uint32_t cpid;
+ str = camel_medium_get_header ((CamelMedium *) message, "Message-ID");
+ if (str)
+ set_value (PidTagInternetMessageId, str);
- #define set_value(hex, val) G_STMT_START { \
- if (!e_mapi_utils_add_spropvalue (mem_ctx, values, n_values, hex, val)) \
- return FALSE; \
- } G_STMT_END
+ addresses = camel_mime_message_get_recipients (message, CAMEL_RECIPIENT_TYPE_TO);
+ e_mapi_mail_add_recipients (object, addresses, olTo);
- if (item->msg_class) {
- set_value (PR_MESSAGE_CLASS, item->msg_class);
- }
-
- if (item->pid_name_content_type) {
- if (!e_mapi_utils_add_spropvalue_namedid (conn, fid, mem_ctx, values, n_values, PidNameContentType, item->pid_name_content_type, cancellable, perror))
- return FALSE;
- }
+ addresses = camel_mime_message_get_recipients (message, CAMEL_RECIPIENT_TYPE_CC);
+ e_mapi_mail_add_recipients (object, addresses, olCC);
- cpid = 65001; /* UTF8 - also used with PR_HTML */
- set_value (PR_INTERNET_CPID, &cpid);
- set_value (PR_SUBJECT_UNICODE, item->header.subject);
- /* PR_CONVERSATION_TOPIC_UNICODE and PR_NORMALIZED_SUBJECT_UNICODE, together with PR_SUBJECT_PREFIX_UNICODE
- are computed from PR_SUBJECT by the server */
+ addresses = camel_mime_message_get_recipients (message, CAMEL_RECIPIENT_TYPE_BCC);
+ e_mapi_mail_add_recipients (object, addresses, olBCC);
- send_rich_info = false;
- set_value (PR_SEND_RICH_INFO, &send_rich_info);
+ if (camel_content_type_is (content_type, "application", "x-pkcs7-mime") ||
+ camel_content_type_is (content_type, "application", "pkcs7-mime")) {
+ e_mapi_mail_do_smime_encrypted (object, CAMEL_MEDIUM (message), &msg_class, &pid_name_content_type, cancellable);
+ } else {
+ CamelDataWrapper *dw = NULL;
+ CamelStream *content_stream;
+ CamelMultipart *multipart;
- set_value (PR_MESSAGE_FLAGS, &item->header.flags);
+ /* contents body */
+ dw = camel_medium_get_content (CAMEL_MEDIUM (message));
+ if (CAMEL_IS_MULTIPART (dw)) {
+ gboolean is_first = TRUE;
- if (item->header.from && *item->header.from)
- set_value (PR_SENT_REPRESENTING_NAME_UNICODE, item->header.from);
+ multipart = CAMEL_MULTIPART (dw);
- if (item->header.from_email && *item->header.from_email) {
- set_value (PR_SENT_REPRESENTING_ADDRTYPE_UNICODE, "SMTP");
- set_value (PR_SENT_REPRESENTING_EMAIL_ADDRESS_UNICODE, item->header.from_email);
- }
+ if (CAMEL_IS_MULTIPART_SIGNED (multipart) && camel_multipart_get_number (multipart) == 2) {
+ e_mapi_mail_do_smime_signed (object, multipart, &msg_class, cancellable);
+ } else {
+ e_mapi_mail_do_multipart (object, multipart, &is_first, cancellable);
+ }
+ } else if (dw) {
+ CamelContentType *type;
+ CamelMimePart *part = CAMEL_MIME_PART (message);
- if (item->header.recieved_time != 0) {
- struct FILETIME msg_date = { 0 };
+ content_stream = get_content_stream (part, cancellable);
+ type = camel_data_wrapper_get_mime_type_field (dw);
- e_mapi_util_time_t_to_filetime (item->header.recieved_time, &msg_date);
+ if (camel_content_type_is (type, "text", "plain")) {
+ e_mapi_mail_add_body (object, content_stream, PidTagBody, cancellable);
+ } else if (camel_content_type_is (type, "text", "html")) {
+ e_mapi_mail_add_body (object, content_stream, PidTagHtml, cancellable);
+ } else {
+ e_mapi_mail_add_attach (object, part, content_stream, cancellable);
+ }
- set_value (PR_MESSAGE_DELIVERY_TIME, &msg_date);
+ if (content_stream)
+ g_object_unref (content_stream);
+ }
}
- if (item->header.transport_headers && *item->header.transport_headers)
- set_value (PR_TRANSPORT_MESSAGE_HEADERS_UNICODE, item->header.transport_headers);
-
- /* Message threading information */
- if (item->header.references)
- set_value (PR_INTERNET_REFERENCES, item->header.references);
-
- if (item->header.in_reply_to)
- set_value (PR_IN_REPLY_TO_ID, item->header.in_reply_to);
+ if (msg_class)
+ set_value (PidTagMessageClass, msg_class);
- if (item->header.message_id)
- set_value (PR_INTERNET_MESSAGE_ID, item->header.message_id);
+ if (pid_name_content_type)
+ set_value (PidNameContentType, pid_name_content_type);
- for (l = item->msg.body_parts; l; l = l->next) {
- ExchangeMAPIStream *stream = (ExchangeMAPIStream *) (l->data);
- struct SBinary_short *bin = g_new0 (struct SBinary_short, 1);
+ g_free (msg_class);
+ g_free (pid_name_content_type);
- bin->cb = stream->value->len;
- bin->lpb = (uint8_t *)stream->value->data;
- if (stream->proptag == PR_HTML)
- set_value (stream->proptag, bin);
- else if (stream->proptag == PR_BODY_UNICODE)
- set_value (stream->proptag, stream->value->data);
- }
+ *pobject = object;
- /* FIXME : */
- /* editor = EDITOR_FORMAT_PLAINTEXT; */
- /* set_value (PR_MSG_EDITOR_FORMAT, &editor); */
+ #undef set_value
return TRUE;
}
diff --git a/src/libexchangemapi/e-mapi-mail-utils.h b/src/libexchangemapi/e-mapi-mail-utils.h
index 01518fc..1cf2357 100644
--- a/src/libexchangemapi/e-mapi-mail-utils.h
+++ b/src/libexchangemapi/e-mapi-mail-utils.h
@@ -31,77 +31,9 @@
#include <e-mapi-connection.h>
-typedef enum {
- PART_TYPE_PLAIN_TEXT=1,
- PART_TYPE_TEXT_HTML
-} MailItemPartType;
-
-typedef struct {
- gchar *subject;
- gchar *from;
- gchar *from_email;
- gchar *from_type;
-
- gchar *references;
- gchar *message_id;
- gchar *in_reply_to;
- /*TODO : Obsolete this. Moved to recipient list*/
- gchar *to;
- gchar *cc;
- gchar *bcc;
-
- gint flags;
- glong size;
- time_t recieved_time;
- time_t send_time;
- guint cpid; /* codepage id */
- gchar *transport_headers;
- gchar *content_class;
-} MailItemHeader;
-
-typedef struct {
- GSList *body_parts;
-} MailItemMessage;
-
-typedef struct _MailItem {
- mapi_id_t fid;
- mapi_id_t mid;
- gchar *msg_class;
- gchar *pid_name_content_type; /* for PidNameContentType */
-
- MailItemHeader header;
- MailItemMessage msg;
-
- gboolean is_cal;
-
- GSList *recipients;
- GSList *attachments;
- GSList *generic_streams;
-} MailItem;
-
-void mail_item_free (MailItem *item);
-
-/* fetch callback, the 'data' is pointer to a MailItem pointer, where new MailItem will be placed */
-gboolean fetch_props_to_mail_item_cb (FetchItemsCallbackData *item_data,
- gpointer data,
- GCancellable *cancellable,
- GError **perror);
-
-/* returns TRUE when filled an entry in the MailItem based on the propTag and its value */
-gboolean fetch_read_item_common_data (MailItem *item, uint32_t propTag, gconstpointer prop_data);
-
-gboolean mapi_mail_get_item_prop_list (EMapiConnection *conn,
- mapi_id_t fid,
- TALLOC_CTX *mem_ctx,
- struct SPropTagArray *props, gpointer data,
- GCancellable *cancellable,
- GError **perror);
-
struct _CamelAddress;
struct _CamelMimeMessage;
-struct _CamelMimeMessage *mapi_mail_item_to_mime_message (EMapiConnection *conn, MailItem *item);
-
struct _CamelMimeMessage *e_mapi_mail_utils_object_to_message (EMapiConnection *conn,
/* const */ EMapiObject *object);
@@ -136,16 +68,4 @@ void e_mapi_mail_utils_decode_recipients (EMapiConnection *conn,
struct _CamelAddress *cc,
struct _CamelAddress *bcc);
-MailItem *mapi_mime_message_to_mail_item (struct _CamelMimeMessage *message, gint32 message_camel_flags, struct _CamelAddress *from, GCancellable *cancellable, GError **error);
-
-/* uses MailItem * as 'data' pointer */
-gboolean mapi_mail_utils_create_item_build_props (EMapiConnection *conn,
- mapi_id_t fid,
- TALLOC_CTX *mem_ctx,
- struct SPropValue **values,
- uint32_t *n_values,
- gpointer data,
- GCancellable *cancellable,
- GError **perror);
-
#endif /* E_MAPI_MAIL_UTILS */
diff --git a/src/libexchangemapi/e-mapi-utils.c b/src/libexchangemapi/e-mapi-utils.c
index 2a25502..dbda865 100644
--- a/src/libexchangemapi/e-mapi-utils.c
+++ b/src/libexchangemapi/e-mapi-utils.c
@@ -106,25 +106,6 @@ e_mapi_util_find_SPropVal_array_propval (struct SPropValue *values, uint32_t pro
return (get_SPropValue(values, proptag));
}
-gconstpointer
-e_mapi_util_find_SPropVal_array_namedid (struct SPropValue *values, EMapiConnection *conn, mapi_id_t fid, uint32_t namedid)
-{
- uint32_t proptag;
- gconstpointer res = NULL;
-
- g_return_val_if_fail (values != NULL, NULL);
- g_return_val_if_fail (conn != NULL, NULL);
-
- proptag = e_mapi_connection_resolve_named_prop (conn, fid, namedid, NULL, NULL);
- if (proptag != MAPI_E_RESERVED)
- res = e_mapi_util_find_SPropVal_array_propval (values, proptag);
-
- if (!res)
- res = e_mapi_util_find_SPropVal_array_propval (values, namedid);
-
- return res;
-}
-
/*
* Retrieve the property value for a given SRow and property tag.
*
@@ -277,129 +258,6 @@ e_mapi_util_find_array_datetime_propval (struct timeval *tv, struct mapi_SPropVa
return get_mapi_SPropValue_array_date_timeval (tv, properties, proptag);
}
-enum MAPISTATUS
-e_mapi_util_find_array_datetime_namedid (struct timeval *tv, struct mapi_SPropValue_array *properties, EMapiConnection *conn, mapi_id_t fid, uint32_t namedid)
-{
- enum MAPISTATUS res = MAPI_E_NOT_FOUND;
- uint32_t proptag;
-
- g_return_val_if_fail (tv != NULL, MAPI_E_INVALID_PARAMETER);
- g_return_val_if_fail (properties != NULL, MAPI_E_INVALID_PARAMETER);
- g_return_val_if_fail (conn != NULL, MAPI_E_INVALID_PARAMETER);
-
- proptag = e_mapi_connection_resolve_named_prop (conn, fid, namedid, NULL, NULL);
- if (proptag != MAPI_E_RESERVED)
- res = e_mapi_util_find_array_datetime_propval (tv, properties, proptag);
-
- if (res == MAPI_E_NOT_FOUND)
- res = e_mapi_util_find_array_datetime_propval (tv, properties, namedid);
-
- return res;
-}
-
-ExchangeMAPIStream *
-e_mapi_util_find_stream (GSList *stream_list, uint32_t proptag)
-{
- GSList *l = stream_list;
-
- for (; l != NULL; l = l->next) {
- ExchangeMAPIStream *stream = (ExchangeMAPIStream *) (l->data);
- if (stream->proptag == proptag)
- return stream;
- }
-
- return NULL;
-}
-
-ExchangeMAPIStream *
-e_mapi_util_find_stream_namedid (GSList *stream_list, EMapiConnection *conn, mapi_id_t fid, uint32_t namedid)
-{
- uint32_t proptag;
- gconstpointer res = NULL;
-
- g_return_val_if_fail (conn != NULL, NULL);
-
- if (!stream_list)
- return NULL;
-
- proptag = e_mapi_connection_resolve_named_prop (conn, fid, namedid, NULL, NULL);
- if (proptag != MAPI_E_RESERVED)
- res = e_mapi_util_find_stream (stream_list, proptag);
-
- if (!res)
- res = e_mapi_util_find_stream (stream_list, namedid);
-
- return (ExchangeMAPIStream *) res;
-}
-
-void
-e_mapi_util_free_attachment_list (GSList **attach_list)
-{
- GSList *l = *attach_list;
-
- if (!l)
- return;
-
- for (; l != NULL; l = l->next) {
- ExchangeMAPIAttachment *attachment = (ExchangeMAPIAttachment *) (l->data);
-
- if (attachment->mail) {
- mail_item_free (attachment->mail);
- } else {
- g_free (attachment->lpProps);
- e_mapi_util_free_stream_list (&(attachment->streams));
- }
-
- g_free (attachment);
- l->data = NULL;
- }
- g_slist_free (*attach_list);
- *attach_list = NULL;
-}
-
-void
-e_mapi_util_free_recipient_list (GSList **recip_list)
-{
- GSList *l = *recip_list;
-
- if (!l)
- return;
-
- for (; l != NULL; l = l->next) {
- ExchangeMAPIRecipient *recipient = (ExchangeMAPIRecipient *) (l->data);
-
- talloc_free (recipient->mem_ctx);
- if (recipient->in.ext_cValues)
- g_free (recipient->in.ext_lpProps);
- if (recipient->in.req_cValues)
- g_free (recipient->in.req_lpProps);
-/* if (recipient->out_SRow.cValues)
- g_free (recipient->out_SRow.lpProps);
-*/ g_free (recipient);
- }
- g_slist_free (*recip_list);
- *recip_list = NULL;
-}
-
-void
-e_mapi_util_free_stream_list (GSList **stream_list)
-{
- GSList *l = *stream_list;
-
- if (!l)
- return;
-
- for (; l != NULL; l = l->next) {
- ExchangeMAPIStream *stream = (ExchangeMAPIStream *) (l->data);
- g_byte_array_free (stream->value, TRUE);
- stream->value = NULL;
- g_free (stream);
- stream = NULL;
- }
- g_slist_free (*stream_list);
- *stream_list = NULL;
-}
-
static void
e_mapi_util_bin_append_uint16 (TALLOC_CTX *mem_ctx, struct Binary_r *bin, const uint16_t val)
{
@@ -770,69 +628,6 @@ e_mapi_util_recip_entryid_decode (EMapiConnection *conn, const struct Binary_r *
}
/**
- * exchange_lf_to_crlf:
- * @in: input text in UNIX ("\n") format
- *
- * Creates a copy of @in with all LFs converted to CRLFs.
- *
- * Return value: the converted text, which the caller must free.
- **/
-gchar *
-exchange_lf_to_crlf (const gchar *in)
-{
- gint len;
- const gchar *s;
- gchar *out, *d;
-
- g_return_val_if_fail (in != NULL, NULL);
-
- len = strlen (in);
- for (s = strchr (in, '\n'); s; s = strchr (s + 1, '\n'))
- len++;
-
- out = g_malloc (len + 1);
- for (s = in, d = out; *s; s++) {
- if (*s == '\n')
- *d++ = '\r';
- *d++ = *s;
- }
- *d = '\0';
-
- return out;
-}
-
-/**
- * exchange_crlf_to_lf:
- * @in: input text in network ("\r\n") format
- *
- * Creates a copy of @in with all CRLFs converted to LFs. (Actually,
- * it just strips CRs, so any raw CRs will be removed.)
- *
- * Return value: the converted text, which the caller must free.
- **/
-gchar *
-exchange_crlf_to_lf (const gchar *in)
-{
- const gchar *s;
- gchar *out;
- GString *str;
-
- g_return_val_if_fail (in != NULL, NULL);
-
- str = g_string_new ("");
-
- for (s = in; *s; s++) {
- if (*s != '\r')
- str = g_string_append_c (str, *s);
- }
-
- out = str->str;
- g_string_free (str, FALSE);
-
- return out;
-}
-
-/**
* e_mapi_util_profiledata_from_settings:
* @empd: destination for profile settings
* @settings: a #CamelMapiSettings
@@ -1359,7 +1154,6 @@ e_mapi_utils_ensure_utf8_string (uint32_t proptag,
*/
gboolean
e_mapi_utils_build_last_modify_restriction (EMapiConnection *conn,
- mapi_id_t fid,
TALLOC_CTX *mem_ctx,
struct mapi_SRestriction **restrictions,
gpointer user_data,
@@ -1396,7 +1190,6 @@ e_mapi_utils_build_last_modify_restriction (EMapiConnection *conn,
gboolean
e_mapi_utils_get_folder_basic_properties_cb (EMapiConnection *conn,
- mapi_id_t fid,
TALLOC_CTX *mem_ctx,
/* const */ struct mapi_SPropValue_array *properties,
gpointer user_data,
diff --git a/src/libexchangemapi/e-mapi-utils.h b/src/libexchangemapi/e-mapi-utils.h
index 04c9459..25f6a39 100644
--- a/src/libexchangemapi/e-mapi-utils.h
+++ b/src/libexchangemapi/e-mapi-utils.h
@@ -32,7 +32,6 @@ gchar * e_mapi_util_mapi_id_to_string (mapi_id_t id);
gboolean e_mapi_util_mapi_id_from_string (const gchar *str, mapi_id_t *id);
gconstpointer e_mapi_util_find_SPropVal_array_propval (struct SPropValue *values, uint32_t proptag);
-gconstpointer e_mapi_util_find_SPropVal_array_namedid (struct SPropValue *values, EMapiConnection *conn, mapi_id_t fid, uint32_t namedid);
gconstpointer e_mapi_util_find_row_propval (struct SRow *aRow, uint32_t proptag);
gconstpointer e_mapi_util_find_row_namedid (struct SRow *aRow, EMapiConnection *conn, mapi_id_t fid, uint32_t namedid);
gconstpointer e_mapi_util_find_array_propval (struct mapi_SPropValue_array *properties, uint32_t proptag);
@@ -40,22 +39,11 @@ gconstpointer e_mapi_util_find_array_namedid (struct mapi_SPropValue_array *prop
uint32_t e_mapi_util_find_array_proptag (struct mapi_SPropValue_array *properties, uint32_t proptag);
enum MAPISTATUS e_mapi_util_find_array_datetime_propval (struct timeval *tv, struct mapi_SPropValue_array *properties, uint32_t proptag);
-enum MAPISTATUS e_mapi_util_find_array_datetime_namedid (struct timeval *tv, struct mapi_SPropValue_array *properties, EMapiConnection *conn, mapi_id_t fid, uint32_t namedid);
-
-ExchangeMAPIStream *e_mapi_util_find_stream (GSList *stream_list, uint32_t proptag);
-ExchangeMAPIStream *e_mapi_util_find_stream_namedid (GSList *stream_list, EMapiConnection *conn, mapi_id_t fid, uint32_t namedid);
-
-void e_mapi_util_free_attachment_list (GSList **attach_list);
-void e_mapi_util_free_recipient_list (GSList **recip_list);
-void e_mapi_util_free_stream_list (GSList **stream_list);
void e_mapi_util_recip_entryid_generate_smtp (TALLOC_CTX *mem_ctx, struct Binary_r *entryid, const gchar *display_name, const gchar *email);
void e_mapi_util_recip_entryid_generate_ex (TALLOC_CTX *mem_ctx, struct Binary_r *entryid, const gchar *exchange_dn);
gboolean e_mapi_util_recip_entryid_decode (EMapiConnection *conn, const struct Binary_r *entyrid, gchar **display_name, gchar **email);
-gchar *exchange_lf_to_crlf (const gchar *in);
-gchar *exchange_crlf_to_lf (const gchar *in);
-
void e_mapi_util_profiledata_from_settings (EMapiProfileData *empd, CamelMapiSettings *settings);
gchar * e_mapi_util_profile_name (struct mapi_context *mapi_ctx,
const EMapiProfileData *empd,
@@ -117,7 +105,6 @@ gboolean e_mapi_utils_create_mapi_context (struct mapi_context **mapi_ctx,
void e_mapi_utils_destroy_mapi_context (struct mapi_context *mapi_ctx);
gboolean e_mapi_utils_build_last_modify_restriction (EMapiConnection *conn,
- mapi_id_t fid,
TALLOC_CTX *mem_ctx,
struct mapi_SRestriction **restrictions,
gpointer user_data, /* const time_t * */
@@ -131,7 +118,6 @@ struct FolderBasicPropertiesData
};
gboolean e_mapi_utils_get_folder_basic_properties_cb (EMapiConnection *conn,
- mapi_id_t fid,
TALLOC_CTX *mem_ctx,
/* const */ struct mapi_SPropValue_array *properties,
gpointer user_data, /* struct FolderBasicPropertiesData * */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]