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);
}
示例#2
0
/**
 * 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);
	}
}