static gboolean proppatch_sd (E2kContext *ctx, ExchangeDelegatesFolder *folder) { GByteArray *binsd; E2kProperties *props; const gchar *href = ""; E2kResultIter *iter; E2kResult *result; E2kHTTPStatus status; binsd = e2k_security_descriptor_to_binary (folder->sd); if (!binsd) return FALSE; props = e2k_properties_new (); e2k_properties_set_binary (props, E2K_PR_EXCHANGE_SD_BINARY, binsd); iter = e2k_context_bproppatch_start (ctx, NULL, folder->uri, &href, 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); return E2K_HTTP_STATUS_IS_SUCCESSFUL (status); }
/** * e2k_freebusy_save: * @fb: an #E2kFreebusy * * Saves the data in @fb back to the server. * * Return value: a libsoup or HTTP status code **/ E2kHTTPStatus e2k_freebusy_save (E2kFreebusy *fb) { E2kProperties *props; char *timestamp; E2kHTTPStatus status; props = e2k_properties_new (); e2k_properties_set_string (props, E2K_PR_EXCHANGE_MESSAGE_CLASS, g_strdup ("IPM.Post")); e2k_properties_set_int (props, PR_FREEBUSY_START_RANGE, fb->start); e2k_properties_set_int (props, PR_FREEBUSY_END_RANGE, fb->end); e2k_properties_set_string (props, PR_FREEBUSY_EMAIL_ADDRESS, g_strdup (fb->dn)); add_events (fb->events[E2K_BUSYSTATUS_ALL], props, PR_FREEBUSY_ALL_MONTHS, PR_FREEBUSY_ALL_EVENTS); add_events (fb->events[E2K_BUSYSTATUS_TENTATIVE], props, PR_FREEBUSY_TENTATIVE_MONTHS, PR_FREEBUSY_TENTATIVE_EVENTS); add_events (fb->events[E2K_BUSYSTATUS_BUSY], props, PR_FREEBUSY_BUSY_MONTHS, PR_FREEBUSY_BUSY_EVENTS); add_events (fb->events[E2K_BUSYSTATUS_OOF], props, PR_FREEBUSY_OOF_MONTHS, PR_FREEBUSY_OOF_EVENTS); timestamp = e2k_make_timestamp (e2k_context_get_last_timestamp (fb->ctx)); e2k_properties_set_date (props, PR_FREEBUSY_LAST_MODIFIED, timestamp); status = e2k_context_proppatch (fb->ctx, NULL, fb->uri, props, TRUE, NULL); e2k_properties_free (props); return status; }
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); } }