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);
	}
}
Esempio n. 2
0
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);
}