static void delegates_apply (ExchangeDelegates *delegates) { ExchangeDelegatesUser *user; E2kGlobalCatalog *gc; E2kContext *ctx; GPtrArray *display_names, *entryids, *privflags; GByteArray *entryid_dup; gchar *error = NULL; E2kProperties *props; gint i; E2kGlobalCatalogStatus status; if (!delegates->loaded_folders) return; /* We can't do this atomically/transactionally, so we need to * make sure that if we fail at any step, things are still in * a semi-consistent state. So we do: * * 1. Remove old delegates from AD * 2. Update LocalFreebusy.EML (the canonical list of delegates) * 3. Add new delegates to AD * 4. Update security descriptors * * If step 1 fails, nothing is changed. * * If step 2 fails, delegates who should have been removed * will have been removed from AD but nothing else, so they * will still show up as being delegates and the user can try * to remove them again later. * * If step 3 fails, delegates who should have been added will * not be in AD, but will be listed as delegates, so the user * can remove them and try adding them again later. * * If step 4 fails, the user can still correct the folder * permissions by hand. */ gc = exchange_account_get_global_catalog (delegates->account); if (!gc) { error = g_strdup (_("Could not access Active Directory")); goto done; } if ((delegates->removed_users || delegates->added_users) && !delegates->self_dn) { E2kGlobalCatalogEntry *entry; status = e2k_global_catalog_lookup ( gc, NULL, /* FIXME: cancellable */ E2K_GLOBAL_CATALOG_LOOKUP_BY_LEGACY_EXCHANGE_DN, delegates->account->legacy_exchange_dn, 0, &entry); if (status != E2K_GLOBAL_CATALOG_OK) { error = g_strdup (_("Could not find self in Active Directory")); goto done; } delegates->self_dn = g_strdup (entry->dn); e2k_global_catalog_entry_free (gc, entry); } /* 1. Remove old delegates from AD */ while (delegates->removed_users && delegates->removed_users->len) { user = delegates->removed_users->pdata[0]; if (!user->dn && !get_user_dn (gc, user)) { error = g_strdup_printf ( _("Could not find delegate %s in Active Directory"), user->display_name); goto done; } /* FIXME: cancellable */ status = e2k_global_catalog_remove_delegate (gc, NULL, delegates->self_dn, user->dn); if (status != E2K_GLOBAL_CATALOG_OK && status != E2K_GLOBAL_CATALOG_NO_DATA) { error = g_strdup_printf ( _("Could not remove delegate %s"), user->display_name); goto done; } g_object_unref (user); g_ptr_array_remove_index_fast (delegates->removed_users, 0); } /* 2. Update LocalFreebusy.EML */ ctx = exchange_account_get_context (delegates->account); if (delegates->users->len) { display_names = g_ptr_array_new (); entryids = g_ptr_array_new (); privflags = g_ptr_array_new (); for (i = 0; i < delegates->users->len; i++) { user = delegates->users->pdata[i]; g_ptr_array_add (display_names, g_strdup (user->display_name)); entryid_dup = g_byte_array_new (); g_byte_array_append (entryid_dup, user->entryid->data, user->entryid->len); g_ptr_array_add (entryids, entryid_dup); g_ptr_array_add (privflags, g_strdup_printf ("%d", user->see_private)); } props = e2k_properties_new (); e2k_properties_set_string_array ( props, PR_DELEGATES_DISPLAY_NAMES, display_names); e2k_properties_set_binary_array ( props, PR_DELEGATES_ENTRYIDS, entryids); e2k_properties_set_int_array ( props, PR_DELEGATES_SEE_PRIVATE, privflags); } else if (delegates->removed_users) { props = e2k_properties_new (); e2k_properties_remove (props, PR_DELEGATES_DISPLAY_NAMES); e2k_properties_remove (props, PR_DELEGATES_ENTRYIDS); e2k_properties_remove (props, PR_DELEGATES_SEE_PRIVATE); } else props = NULL; if (props) { E2kResultIter *iter; E2kResult *result; iter = e2k_context_bproppatch_start ( ctx, NULL, delegates->account->home_uri, &exchange_localfreebusy_path, 1, props, FALSE); e2k_properties_free (props); result = e2k_result_iter_next (iter); if (result) { status = result->status; e2k_result_iter_free (iter); } else status = e2k_result_iter_free (iter); if (!E2K_HTTP_STATUS_IS_SUCCESSFUL (status)) { error = g_strdup (_("Could not update list of delegates.")); goto done; } } /* 3. Add new delegates to AD */ while (delegates->added_users && delegates->added_users->len) { user = delegates->added_users->pdata[0]; /* An added user must have come from the GC so * we know user->dn is set. */ /* FIXME: cancellable */ status = e2k_global_catalog_add_delegate (gc, NULL, delegates->self_dn, user->dn); if (status != E2K_GLOBAL_CATALOG_OK && status != E2K_GLOBAL_CATALOG_EXISTS) { error = g_strdup_printf ( _("Could not add delegate %s"), user->display_name); goto done; } g_ptr_array_remove_index_fast (delegates->added_users, 0); g_object_unref (user); } /* 4. Update security descriptors */ for (i = 0; i < EXCHANGE_DELEGATES_LAST; i++) proppatch_sd (ctx, &delegates->folder[i]); proppatch_sd (ctx, &delegates->freebusy_folder); done: if (error) { e_alert_run_dialog_for_args (GTK_WINDOW (delegates->table), ERROR_DOMAIN ":delegate-fail-error", error, NULL); g_free (error); } }
static void add_events (GArray *events_array, E2kProperties *props, const char *month_list_prop, const char *data_list_prop) { E2kFreebusyEvent *events = (E2kFreebusyEvent *)events_array->data; int i, evt_start, evt_end, monthyear; struct tm start_tm, end_tm; time_t start, end; GPtrArray *monthyears, *datas; GByteArray *data; char startend[4]; if (!events_array->len) { e2k_properties_remove (props, month_list_prop); e2k_properties_remove (props, data_list_prop); return; } monthyears = g_ptr_array_new (); start_tm = *gmtime (&events[0].start); end_tm = *gmtime (&events[events_array->len - 1].end); while (start_tm.tm_year <= end_tm.tm_year || start_tm.tm_mon <= end_tm.tm_mon) { monthyear = ((start_tm.tm_year + 1900) * 16) + (start_tm.tm_mon + 1); g_ptr_array_add (monthyears, g_strdup_printf ("%d", monthyear)); start_tm.tm_mon++; if (start_tm.tm_mon == 12) { start_tm.tm_year++; start_tm.tm_mon = 0; } } e2k_properties_set_int_array (props, month_list_prop, monthyears); datas = g_ptr_array_new (); start = events[0].start; i = 0; while (i < events_array->len) { start_tm = *gmtime (&start); start_tm.tm_mon++; end = e_mktime_utc (&start_tm); data = g_byte_array_new (); while (i << events_array->len && events[i].end > start && events[i].start < end) { if (events[i].start < start) evt_start = 0; else evt_start = (events[i].start - start) / 60; if (events[i].end > end) evt_end = (end - start) / 60; else evt_end = (events[i].end - start) / 60; startend[0] = evt_start & 0xFF; startend[1] = evt_start >> 8; startend[2] = evt_end & 0xFF; startend[3] = evt_end >> 8; g_byte_array_append (data, startend, 4); i++; } g_ptr_array_add (datas, data); start = end; } e2k_properties_set_binary_array (props, data_list_prop, datas); }