[evolution-mapi] Free/Busy search implementation in MAPI.
- From: Bharath Acharya <abharath src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-mapi] Free/Busy search implementation in MAPI.
- Date: Tue, 1 Jun 2010 04:53:57 +0000 (UTC)
commit ed6da0101b60436b221216ad133168ca119f5156
Author: Bharath Acharya <abharath novell com>
Date: Tue Jun 1 10:21:15 2010 +0530
Free/Busy search implementation in MAPI.
Works for all basic cases. Please find more comments at
https://bugzilla.gnome.org/show_bug.cgi?id=601486
src/calendar/e-cal-backend-mapi.c | 8 +-
src/libexchangemapi/exchange-mapi-cal-utils.c | 230 ++++++++++++++++++++++++
src/libexchangemapi/exchange-mapi-cal-utils.h | 2 +
src/libexchangemapi/exchange-mapi-connection.c | 20 ++
src/libexchangemapi/exchange-mapi-connection.h | 2 +
5 files changed, 261 insertions(+), 1 deletions(-)
---
diff --git a/src/calendar/e-cal-backend-mapi.c b/src/calendar/e-cal-backend-mapi.c
index fe62667..68dddc3 100644
--- a/src/calendar/e-cal-backend-mapi.c
+++ b/src/calendar/e-cal-backend-mapi.c
@@ -2266,9 +2266,15 @@ static ECalBackendSyncStatus
e_cal_backend_mapi_get_free_busy (ECalBackendSync *backend, EDataCal *cal,
GList *users, time_t start, time_t end, GList **freebusy)
{
+ ECalBackendMAPI *cbmapi;
+ ECalBackendMAPIPrivate *priv;
- return GNOME_Evolution_Calendar_Success;
+ cbmapi = E_CAL_BACKEND_MAPI (backend);
+ priv = cbmapi->priv;
+
+ exchange_mapi_cal_utils_get_free_busy_data (priv->conn, users, start, end, freebusy);
+ return GNOME_Evolution_Calendar_Success;
}
typedef struct {
diff --git a/src/libexchangemapi/exchange-mapi-cal-utils.c b/src/libexchangemapi/exchange-mapi-cal-utils.c
index f059e17..f8ffcc6 100644
--- a/src/libexchangemapi/exchange-mapi-cal-utils.c
+++ b/src/libexchangemapi/exchange-mapi-cal-utils.c
@@ -2120,6 +2120,236 @@ exchange_mapi_cal_util_get_new_appt_id (ExchangeMapiConnection *conn, mapi_id_t
return id;
}
+static time_t
+mapi_get_date_from_string (const gchar *dtstring)
+{
+ time_t t = 0;
+ GTimeVal t_val;
+
+ g_return_val_if_fail (dtstring != NULL, 0);
+
+ if (g_time_val_from_iso8601 (dtstring, &t_val)) {
+ t = (time_t) t_val.tv_sec;
+ } else if (strlen (dtstring) == 8) {
+ /* It might be a date value */
+ GDate date;
+ struct tm tt;
+ guint16 year;
+ guint month;
+ guint8 day;
+
+ g_date_clear (&date, 1);
+#define digit_at(x,y) (x[y] - '0')
+ year = digit_at (dtstring, 0) * 1000
+ + digit_at (dtstring, 1) * 100
+ + digit_at (dtstring, 2) * 10
+ + digit_at (dtstring, 3);
+ month = digit_at (dtstring, 4) * 10 + digit_at (dtstring, 5);
+ day = digit_at (dtstring, 6) * 10 + digit_at (dtstring, 7);
+
+ g_date_set_year (&date, year);
+ g_date_set_month (&date, month);
+ g_date_set_day (&date, day);
+
+ g_date_to_struct_tm (&date, &tt);
+ t = mktime (&tt);
+
+ } else
+ g_warning ("Could not parse the string \n");
+
+ return t;
+}
+
+static void
+populate_freebusy_data (struct Binary_r *bin, uint32_t month, uint32_t year, GList **freebusy, const gchar *accept_type, ECalComponent *comp)
+{
+ uint16_t event_start;
+ uint16_t event_end;
+ uint32_t i;
+ uint32_t hour;
+ uint32_t day;
+ const char *month_name;
+ uint32_t minutes;
+ uint32_t real_month;
+ gchar *date_string = NULL;
+ gchar *start = NULL, *end = NULL;
+ time_t start_date, end_date;
+ icalcomponent *icalcomp = NULL;
+
+ if (!bin)
+ return;
+ /* bin.cb must be a multiple of 4 */
+ if (bin->cb % 4)
+ return;
+
+ year = mapidump_freebusy_year(month, year);
+ month_name = mapidump_freebusy_month(month, year);
+ if (!month_name)
+ return;
+
+ for (i = 0; i < bin->cb; i+= 4) {
+ event_start = (bin->lpb[i + 1] << 8) | bin->lpb[i];
+ event_end = (bin->lpb[i + 3] << 8) | bin->lpb[i + 2];
+
+ for (hour = 0; hour < 24; hour++) {
+ if (!(((event_start - (60 * hour)) % 1440) && (((event_start - (60 * hour)) % 1440) - 30))) {
+ struct icalperiodtype ipt;
+ icalproperty *icalprop;
+ icaltimetype itt;
+
+ day = ((event_start - (60 * hour)) / 1440) + 1;
+ minutes = (event_start - (60 * hour)) % 1440;
+ real_month = month - (year * 16);
+
+ date_string = g_strdup_printf ("%.2u-%.2u-%.2u", year, real_month, day);
+ start = g_strdup_printf ("%sT%.2u:%.2u:00Z", date_string, hour + daylight, minutes);
+ g_free (date_string);
+
+ day = ((event_end - (60 * hour)) / 1440) + 1;
+ minutes = (event_end - (60 * hour)) % 1440;
+
+ if (minutes >= 60) {
+ hour += minutes / 60;
+ minutes %= 60;
+ }
+
+ date_string = g_strdup_printf ("%.2u-%.2u-%.2u", year, real_month, day);
+ end = g_strdup_printf ("%sT%.2u:%.2u:00Z", date_string, hour + daylight, minutes);
+ g_free (date_string);
+
+ start_date = mapi_get_date_from_string (start);
+ end_date = mapi_get_date_from_string (end);
+
+ memset (&ipt, 0, sizeof (struct icalperiodtype));
+
+ itt = icaltime_from_timet_with_zone (start_date, 0, icaltimezone_get_utc_timezone ());
+ ipt.start = itt;
+
+ itt = icaltime_from_timet_with_zone (end_date, 0, icaltimezone_get_utc_timezone ());
+ ipt.end = itt;
+
+ icalcomp = e_cal_component_get_icalcomponent (comp);
+ icalprop = icalproperty_new_freebusy (ipt);
+
+ if (!strcmp (accept_type, "Busy"))
+ icalproperty_set_parameter_from_string (icalprop, "FBTYPE", "BUSY");
+ else if (!strcmp (accept_type, "Tentative"))
+ icalproperty_set_parameter_from_string (icalprop, "FBTYPE", "BUSY-TENTATIVE");
+ else if (!strcmp (accept_type, "OutOfOffice"))
+ icalproperty_set_parameter_from_string (icalprop, "FBTYPE", "BUSY-UNAVAILABLE");
+
+ icalcomponent_add_property(icalcomp, icalprop);
+ g_free (start);
+ g_free (end);
+ }
+ }
+ }
+}
+
+gboolean
+exchange_mapi_cal_utils_get_free_busy_data (ExchangeMapiConnection *conn, GList *users, time_t start, time_t end, GList **freebusy)
+{
+ struct SRow aRow;
+ enum MAPISTATUS retval;
+ uint32_t i;
+ mapi_object_t obj_store;
+ GList *l;
+
+ const uint32_t *publish_start;
+ const struct LongArray_r *busy_months;
+ const struct BinaryArray_r *busy_events;
+ const struct LongArray_r *tentative_months;
+ const struct BinaryArray_r *tentative_events;
+ const struct LongArray_r *oof_months;
+ const struct BinaryArray_r *oof_events;
+ uint32_t year;
+ uint32_t event_year;
+
+ gchar *name = NULL;
+ ECalComponent *comp;
+ ECalComponentAttendee attendee;
+ GSList *attendee_list = NULL;
+ icalcomponent *icalcomp = NULL;
+ icaltimetype start_time, end_time;
+ icaltimezone *default_zone = NULL;
+
+ exchange_mapi_connection_get_public_folder (conn, &obj_store);
+
+ for ( l = users; l != NULL; l = g_list_next (l)) {
+ retval = GetUserFreeBusyData (&obj_store, (const gchar *)l->data, &aRow);
+
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* Step 2. Dump properties */
+ publish_start = (const uint32_t *) find_SPropValue_data(&aRow, PR_FREEBUSY_START_RANGE);
+ busy_months = (const struct LongArray_r *) find_SPropValue_data(&aRow, PR_FREEBUSY_BUSY_MONTHS);
+ busy_events = (const struct BinaryArray_r *) find_SPropValue_data(&aRow, PR_FREEBUSY_BUSY_EVENTS);
+ tentative_months = (const struct LongArray_r *) find_SPropValue_data(&aRow, PR_FREEBUSY_TENTATIVE_MONTHS);
+ tentative_events = (const struct BinaryArray_r *) find_SPropValue_data(&aRow, PR_FREEBUSY_TENTATIVE_EVENTS);
+ oof_months = (const struct LongArray_r *) find_SPropValue_data(&aRow, PR_FREEBUSY_OOF_MONTHS);
+ oof_events = (const struct BinaryArray_r *) find_SPropValue_data(&aRow, PR_FREEBUSY_OOF_EVENTS);
+
+ year = GetFreeBusyYear(publish_start);
+
+ comp = e_cal_component_new ();
+ e_cal_component_set_new_vtype (comp, E_CAL_COMPONENT_FREEBUSY);
+ e_cal_component_commit_sequence (comp);
+ icalcomp = e_cal_component_get_icalcomponent (comp);
+
+ start_time = icaltime_from_timet_with_zone (start, 0, default_zone ? default_zone : NULL);
+ end_time = icaltime_from_timet_with_zone (end, 0, default_zone ? default_zone : NULL);
+ icalcomponent_set_dtstart (icalcomp, start_time);
+ icalcomponent_set_dtend (icalcomp, end_time);
+
+ memset (&attendee, 0, sizeof (ECalComponentAttendee));
+ if (name)
+ attendee.cn = name;
+ if (l->data)
+ attendee.value = l->data;
+
+ attendee.cutype = ICAL_CUTYPE_INDIVIDUAL;
+ attendee.role = ICAL_ROLE_REQPARTICIPANT;
+ attendee.status = ICAL_PARTSTAT_NEEDSACTION;
+
+ attendee_list = g_slist_append (attendee_list, &attendee);
+
+ e_cal_component_set_attendee_list (comp, attendee_list);
+ g_slist_free (attendee_list);
+ g_free ((gchar *) name);
+ g_free ((gchar *) l->data);
+
+ if (busy_months && ((*(const uint32_t *) busy_months) != MAPI_E_NOT_FOUND) &&
+ busy_events && ((*(const uint32_t *) busy_events) != MAPI_E_NOT_FOUND)) {
+ for (i = 0; i < busy_months->cValues; i++) {
+ event_year = mapidump_freebusy_year(busy_months->lpl[i], year);
+ populate_freebusy_data (&busy_events->lpbin[i], busy_months->lpl[i], event_year, freebusy, "Busy", comp);
+ }
+ }
+
+ if (tentative_months && ((*(const uint32_t *) tentative_months) != MAPI_E_NOT_FOUND) &&
+ tentative_events && ((*(const uint32_t *) tentative_events) != MAPI_E_NOT_FOUND)) {
+ for (i = 0; i < tentative_months->cValues; i++) {
+ event_year = mapidump_freebusy_year(tentative_months->lpl[i], year);
+ populate_freebusy_data (&tentative_events->lpbin[i], tentative_months->lpl[i], event_year, freebusy, "Tentative", comp);
+ }
+ }
+
+ if (oof_months && ((*(const uint32_t *) oof_months) != MAPI_E_NOT_FOUND) &&
+ oof_events && ((*(const uint32_t *) oof_events) != MAPI_E_NOT_FOUND)) {
+ for (i = 0; i < oof_months->cValues; i++) {
+ event_year = mapidump_freebusy_year(oof_months->lpl[i], year);
+ populate_freebusy_data (&oof_events->lpbin[i], oof_months->lpl[i], event_year, freebusy, "OutOfOffice", comp);
+ }
+ }
+
+ e_cal_component_commit_sequence (comp);
+ *freebusy = g_list_append (*freebusy, e_cal_component_get_as_string (comp));
+// g_object_unref (comp);
+ MAPIFreeBuffer(aRow.lpProps);
+ }
+ return TRUE;
+}
+
/* beware, the 'data' pointer is an integer of the event kind */
gboolean
exchange_mapi_cal_utils_get_props_cb (ExchangeMapiConnection *conn, mapi_id_t fid, TALLOC_CTX *mem_ctx, struct SPropTagArray *props, gpointer data)
diff --git a/src/libexchangemapi/exchange-mapi-cal-utils.h b/src/libexchangemapi/exchange-mapi-cal-utils.h
index 196abd8..bc8416d 100644
--- a/src/libexchangemapi/exchange-mapi-cal-utils.h
+++ b/src/libexchangemapi/exchange-mapi-cal-utils.h
@@ -101,6 +101,8 @@ gboolean exchange_mapi_cal_utils_add_named_ids (ExchangeMapiConnection *conn, ma
gboolean exchange_mapi_cal_utils_get_props_cb (ExchangeMapiConnection *conn, mapi_id_t fid, TALLOC_CTX *mem_ctx, struct SPropTagArray *props, gpointer data);
gboolean exchange_mapi_cal_utils_write_props_cb (ExchangeMapiConnection *conn, mapi_id_t fid, TALLOC_CTX *mem_ctx, struct SPropValue **values, uint32_t *n_values, gpointer data);
+gboolean exchange_mapi_cal_utils_get_free_busy_data (ExchangeMapiConnection *conn, GList *users, time_t start, time_t end, GList **freebusy);
+
G_END_DECLS
#endif
diff --git a/src/libexchangemapi/exchange-mapi-connection.c b/src/libexchangemapi/exchange-mapi-connection.c
index fc3c99e..701fe73 100644
--- a/src/libexchangemapi/exchange-mapi-connection.c
+++ b/src/libexchangemapi/exchange-mapi-connection.c
@@ -1088,6 +1088,26 @@ exchange_mapi_connection_fetch_gal (ExchangeMapiConnection *conn, BuildReadProps
return retval == MAPI_E_SUCCESS;
}
+gboolean
+exchange_mapi_connection_get_public_folder (ExchangeMapiConnection *conn, mapi_object_t *obj_store)
+{
+ enum MAPISTATUS retval;
+
+ CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
+ g_return_val_if_fail (priv->session != NULL, FALSE);
+
+ mapi_object_init (&priv->public_store);
+
+ retval = OpenPublicFolder (priv->session, &priv->public_store);
+
+ if (retval != MAPI_E_SUCCESS) {
+ mapi_errstr ("OpenPublicFolder", GetLastError());
+ exit(1);
+ }
+
+ *obj_store = priv->public_store;
+}
+
/* Returns TRUE if all recipients were read succcesfully, else returns FALSE */
static gboolean
exchange_mapi_util_get_recipients (mapi_object_t *obj_message, GSList **recip_list)
diff --git a/src/libexchangemapi/exchange-mapi-connection.h b/src/libexchangemapi/exchange-mapi-connection.h
index 5f31a5d..8a4a595 100644
--- a/src/libexchangemapi/exchange-mapi-connection.h
+++ b/src/libexchangemapi/exchange-mapi-connection.h
@@ -175,6 +175,8 @@ gboolean exchange_mapi_connection_fetch_gal (ExchangeMapiConnection *conn,
BuildReadPropsCB build_props, gpointer brp_data,
FetchGALCallback cb, gpointer data);
+gboolean exchange_mapi_connection_get_public_folder (ExchangeMapiConnection *conn, mapi_object_t *obj_object);
+
mapi_id_t exchange_mapi_connection_create_folder (ExchangeMapiConnection *conn, uint32_t olFolder, mapi_id_t pfid, const gchar *name);
gboolean exchange_mapi_connection_remove_folder (ExchangeMapiConnection *conn, mapi_id_t fid);
gboolean exchange_mapi_connection_empty_folder (ExchangeMapiConnection *conn, mapi_id_t fid);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]