void
gkd_secret_objects_emit_item_deleted (GkdSecretObjects *self,
				      GckObject *collection,
				      const gchar *item_path)
{
	GkdExportedCollection *skeleton;
	gchar *collection_path;
	gchar **items;

	g_return_if_fail (GKD_SECRET_IS_OBJECTS (self));
	g_return_if_fail (GCK_OBJECT (collection));
	g_return_if_fail (item_path != NULL);

	collection_path = object_path_for_collection (collection);
	skeleton = g_hash_table_lookup (self->collections_to_skeletons, collection_path);
	g_return_if_fail (skeleton != NULL);

	gkd_secret_objects_unregister_item (self, item_path);
	gkd_exported_collection_emit_item_deleted (skeleton, item_path);

	items = gkd_secret_objects_get_collection_items (self, collection_path);
	gkd_exported_collection_set_items (skeleton, (const gchar **) items);

	g_strfreev (items);
	g_free (collection_path);
}
void
gkd_secret_objects_foreach_collection (GkdSecretObjects *self,
				       const gchar *caller,
				       GkdSecretObjectsForeach callback,
				       gpointer user_data)
{
	GckBuilder builder = GCK_BUILDER_INIT;
	GckSession *session;
	GError *error = NULL;
	GList *collections, *l;
	gpointer identifier;
	gsize n_identifier;
	gchar *path;

	g_return_if_fail (GKD_SECRET_IS_OBJECTS (self));
	g_return_if_fail (callback);

	/* The session we're using to access the object */
	if (caller == NULL) {
		session = gkd_secret_service_internal_pkcs11_session (self->service);
	} else {
		session = gkd_secret_service_get_pkcs11_session (self->service, caller);
	}

	gck_builder_add_ulong (&builder, CKA_CLASS, CKO_G_COLLECTION);

	collections = gck_session_find_objects (session, gck_builder_end (&builder), NULL, &error);

	if (error != NULL) {
		g_warning ("couldn't lookup collections: %s", egg_error_message (error));
		g_clear_error (&error);
		return;
	}

	for (l = collections; l; l = g_list_next (l)) {

		identifier = gck_object_get_data (l->data, CKA_ID, NULL, &n_identifier, &error);
		if (identifier == NULL) {
			g_warning ("couldn't get collection identifier: %s", egg_error_message (error));
			g_clear_error (&error);
			continue;
		}

		path = gkd_secret_util_build_path (SECRET_COLLECTION_PREFIX, identifier, n_identifier);
		g_free (identifier);

		(callback) (self, path, l->data, user_data);
		g_free (path);
	}

	gck_list_unref_free (collections);
}
GVariant *
gkd_secret_objects_append_collection_paths (GkdSecretObjects *self,
					    const gchar *caller)
{
	GVariantBuilder builder;

	g_return_val_if_fail (GKD_SECRET_IS_OBJECTS (self), NULL);

	g_variant_builder_init (&builder, G_VARIANT_TYPE ("ao"));
	gkd_secret_objects_foreach_collection (self, caller, on_object_path_append_to_builder, &builder);

	return g_variant_builder_end (&builder);
}
void
gkd_secret_objects_foreach_item (GkdSecretObjects *self,
				 const gchar *caller,
				 const gchar *base,
				 GkdSecretObjectsForeach callback,
				 gpointer user_data)
{
	GckBuilder builder = GCK_BUILDER_INIT;
	GckSession *session;
	GError *error = NULL;
	gchar *identifier;
	GList *items;

	g_return_if_fail (GKD_SECRET_IS_OBJECTS (self));
	g_return_if_fail (base != NULL);
	g_return_if_fail (callback != NULL);

	/* The session we're using to access the object */
	if (caller == NULL) {
		session = gkd_secret_service_internal_pkcs11_session (self->service);
	} else {
		session = gkd_secret_service_get_pkcs11_session (self->service, caller);
	}

	if (!gkd_secret_util_parse_path (base, &identifier, NULL))
		g_return_if_reached ();

	gck_builder_add_ulong (&builder, CKA_CLASS, CKO_SECRET_KEY);
	gck_builder_add_string (&builder, CKA_G_COLLECTION, identifier);

	items = gck_session_find_objects (session, gck_builder_end (&builder), NULL, &error);

	if (error == NULL) {
		objects_foreach_item (self, items, base, callback, user_data);

	} else {
		g_warning ("couldn't lookup items in '%s' collection: %s", identifier, egg_error_message (error));
		g_clear_error (&error);
	}

	gck_list_unref_free (items);
	g_free (identifier);
}
GckObject*
gkd_secret_objects_lookup_item (GkdSecretObjects *self, const gchar *caller,
				const gchar *path)
{
	GckBuilder builder = GCK_BUILDER_INIT;
	GckObject *object = NULL;
	GError *error = NULL;
	GList *objects;
	GckSession *session;
	gchar *collection;
	gchar *identifier;

	g_return_val_if_fail (GKD_SECRET_IS_OBJECTS (self), NULL);
	g_return_val_if_fail (caller, NULL);
	g_return_val_if_fail (path, NULL);

	if (!gkd_secret_util_parse_path (path, &collection, &identifier))
		return NULL;

	/* The session we're using to access the object */
	session = gkd_secret_service_get_pkcs11_session (self->service, caller);
	g_return_val_if_fail (session, NULL);

	gck_builder_add_ulong (&builder, CKA_CLASS, CKO_SECRET_KEY);
	gck_builder_add_string (&builder, CKA_ID, identifier);
	gck_builder_add_string (&builder, CKA_G_COLLECTION, collection);

	objects = gck_session_find_objects (session, gck_builder_end (&builder), NULL, &error);

	g_free (identifier);
	g_free (collection);

	if (error != NULL) {
		g_warning ("couldn't lookup item: %s: %s", path, egg_error_message (error));
		g_clear_error (&error);
	}

	if (objects)
		object = g_object_ref (objects->data);

	gck_list_unref_free (objects);
	return object;
}
void
gkd_secret_objects_emit_item_changed (GkdSecretObjects *self,
				      GckObject *item)
{
	GkdExportedCollection *skeleton;
	gchar *collection_path;
	gchar *item_path;

	g_return_if_fail (GKD_SECRET_IS_OBJECTS (self));
	g_return_if_fail (GCK_OBJECT (item));

	collection_path = collection_path_for_item (item);
	skeleton = g_hash_table_lookup (self->collections_to_skeletons, collection_path);
	g_return_if_fail (skeleton != NULL);

	item_path = object_path_for_item (collection_path, item);
	gkd_exported_collection_emit_item_changed (skeleton, item_path);

	g_free (item_path);
	g_free (collection_path);
}
GckSlot*
gkd_secret_objects_get_pkcs11_slot (GkdSecretObjects *self)
{
	g_return_val_if_fail (GKD_SECRET_IS_OBJECTS (self), NULL);
	return self->pkcs11_slot;
}