static void
complete_read_buffer (GcrImporter *self, gssize count, GError *error)
{
	g_assert (GCR_IS_IMPORTER (self));
	g_assert (self->pv->buffer);
	
	/* A failure */
	if (count == -1) {
		g_propagate_error (&self->pv->error, error);
		next_state (self, state_failure);
	} else {
	
		g_return_if_fail (count >= 0 && count <= BLOCK);
		g_byte_array_set_size (self->pv->buffer, self->pv->buffer->len - (BLOCK - count));
		
		/* Finished reading */
		if (count == 0) {
			
			/* Optimization, unref input early */
			g_object_unref (self->pv->input);
			self->pv->input = NULL;
			
			next_state (self, state_parse_buffer);
			
		/* Read the next block */
		} else {
			next_state (self, state_read_buffer);
		}
	}
	
}
static void 
state_read_buffer (GcrImporter *self, gboolean async)
{
	GError *error = NULL;
	gssize count;
	gsize at;
	
	g_assert (GCR_IS_IMPORTER (self));
	g_assert (G_IS_INPUT_STREAM (self->pv->input));
	
	if (!self->pv->buffer)
		self->pv->buffer = g_byte_array_sized_new (BLOCK);

	at = self->pv->buffer->len;
	g_byte_array_set_size (self->pv->buffer, at + BLOCK);
	
	if (async) {
		g_input_stream_read_async (self->pv->input, self->pv->buffer->data + at, 
		                           BLOCK, G_PRIORITY_DEFAULT, self->pv->cancel,
		                           on_read_buffer, self);
	} else {
		count = g_input_stream_read (self->pv->input, self->pv->buffer->data + at, 
		                             BLOCK, self->pv->cancel, &error);
		complete_read_buffer (self, count, error);
	}
}
static void
state_initialize_pin (GcrImporter *self, gboolean async)
{
	GP11TokenInfo *info;
	gboolean initialize;
	CK_RV rv;
	
	g_assert (GCR_IS_IMPORTER (self));
	
	/* HACK: Doesn't function when async */
	if (!async) {
		g_return_if_fail (self->pv->slot);
		info = gp11_slot_get_token_info (self->pv->slot);
		g_return_if_fail (info);
	
		initialize = !(info->flags & CKF_USER_PIN_INITIALIZED);
		gp11_token_info_free (info);
		
		if (initialize) {
			rv = hacky_perform_initialize_pin (self->pv->slot);
			if (rv != CKR_OK) {
				g_propagate_error (&self->pv->error, g_error_new (GP11_ERROR, rv, "%s", gp11_message_from_rv (rv)));
				next_state (self, state_failure);
				return;
			} 
		}
	}

	next_state (self, state_open_session);
}
gboolean
gcr_importer_import (GcrImporter *self, GInputStream *input,
                     GCancellable *cancel, GError **error)
{
	g_return_val_if_fail (GCR_IS_IMPORTER (self), FALSE);
	g_return_val_if_fail (G_IS_INPUT_STREAM (input), FALSE);
	g_return_val_if_fail (!error || !*error, FALSE);
	g_return_val_if_fail (!self->pv->processing, FALSE);
	
	cleanup_import_data (self);
	
	self->pv->input = g_object_ref (input);
	if (cancel)
		self->pv->cancel = g_object_ref (cancel);
	self->pv->processing = TRUE;
	self->pv->async = FALSE;
	
	next_state (self, state_read_buffer);
	
	g_assert (!self->pv->processing);
	g_assert (!self->pv->input);
	g_assert (!self->pv->cancel);
	
	if (!self->pv->succeeded) {
		g_propagate_error (error, self->pv->error);
		self->pv->error = NULL;
		return FALSE;
	}
	
	return TRUE;
}
예제 #5
0
파일: gcr-importer.c 프로젝트: UIKit0/gcr
/**
 * gcr_importer_set_interaction:
 * @importer: the importer
 * @interaction: the interaction used by the importer
 *
 * Set the interaction used to prompt the user when needed by this
 * importer.
 */
void
gcr_importer_set_interaction (GcrImporter *importer,
                              GTlsInteraction *interaction)
{
	g_return_if_fail (GCR_IS_IMPORTER (importer));
	g_object_set (importer, "interaction", interaction, NULL);
}
GcrParser*
gcr_importer_get_parser (GcrImporter *self)
{
	g_return_val_if_fail (GCR_IS_IMPORTER (self), NULL);
	if (!self->pv->parser) 
		self->pv->parser = gcr_parser_new ();
	return self->pv->parser;
}
static void
on_parser_parsed (GcrParser *parser, GcrImporter *self)
{
	GP11Attributes *attrs;
	
	g_return_if_fail (GCR_IS_PARSER (parser));
	g_return_if_fail (GCR_IS_IMPORTER (self));
	
	attrs = gcr_parser_get_parsed_attributes (parser);
	g_return_if_fail (attrs);
	g_queue_push_tail (&self->pv->queue, gp11_attributes_ref (attrs));
}
static void
next_state (GcrImporter *self, void (*state) (GcrImporter*, gboolean))
{
	g_assert (GCR_IS_IMPORTER (self));
	g_assert (self->pv->processing);
	g_assert (state);
	
	if (self->pv->cancel && g_cancellable_is_cancelled (self->pv->cancel))
		state = state_cancelled;
	
	(state) (self, self->pv->async);
}
void 
gcr_importer_set_slot (GcrImporter *self, GP11Slot *slot)
{
	g_return_if_fail (GCR_IS_IMPORTER (self));
	
	if (slot)
		g_object_ref (slot);
	if (self->pv->slot)
		g_object_unref (self->pv->slot);
	self->pv->slot = slot;
	g_object_notify (G_OBJECT (self), "slot");
}
void
gcr_importer_set_parser (GcrImporter *self, GcrParser *parser)
{
	g_return_if_fail (GCR_IS_IMPORTER (self));
	
	if (parser)
		g_object_ref (parser);
	if (self->pv->parser)
		g_object_unref (self->pv->parser);
	self->pv->parser = parser;
	g_object_notify (G_OBJECT (self), "parser");
}
예제 #11
0
파일: gcr-importer.c 프로젝트: UIKit0/gcr
/**
 * gcr_importer_get_interaction:
 * @importer: the importer
 *
 * Get the interaction used to prompt the user when needed by this
 * importer.
 *
 * Returns: (transfer none) (allow-none): the interaction or %NULL
 */
GTlsInteraction *
gcr_importer_get_interaction (GcrImporter *importer)
{
	GTlsInteraction *interaction = NULL;

	g_return_val_if_fail (GCR_IS_IMPORTER (importer), NULL);

	g_object_get (importer, "interaction", &interaction, NULL);

	if (interaction != NULL)
		g_object_unref (interaction);

	return interaction;
}
static void 
state_import_prompt (GcrImporter *self, gboolean async)
{
	GcrImportDialog *dialog;
	gboolean prompt;
	gint response;
	
	g_assert (GCR_IS_IMPORTER (self));
	
	/* No need to prompt */
	if (self->pv->prompted == TRUE)
		prompt = FALSE;
	else if (self->pv->behavior == GCR_IMPORTER_PROMPT_ALWAYS)
		prompt = TRUE;
	else if (self->pv->behavior == GCR_IMPORTER_PROMPT_NEVER)
		prompt = FALSE;
	else 
		prompt = self->pv->slot ? FALSE : TRUE;
	
	if (prompt == FALSE) {
		next_state (self, state_initialize_pin);
		
	} else {
		
		dialog = _gcr_import_dialog_new ();

		_gcr_import_dialog_set_primary_text (dialog, _("Import Certificates/Keys"));
		_gcr_import_dialog_hide_password (dialog);
		
		if (self->pv->slot) {
			_gcr_import_dialog_set_selected_slot (dialog, self->pv->slot);
			_gcr_import_dialog_hide_selected_slot (dialog);
		} else {
			_gcr_import_dialog_set_secondary_text (dialog, _("Choose a location to store the imported certificates/keys."));
		}
			
		/* Prompt without blocking main loop */
		if (async) {
			g_signal_connect (dialog, "response", G_CALLBACK (on_prompt_response), self);
			gtk_widget_show (GTK_WIDGET (dialog));
			
		/* Block mainloop */
		} else {
			response = gtk_dialog_run (GTK_DIALOG (dialog));
			complete_import_prompt (self, dialog, response);
			g_object_unref (dialog);
		}
	}
}
예제 #13
0
파일: gcr-importer.c 프로젝트: UIKit0/gcr
/**
 * gcr_importer_queue_for_parsed:
 * @importer: an importer to add additional items to
 * @parsed: a parsed item to import
 *
 * Queues an additional item to be imported. The parsed item is represented
 * by the state of the #GcrParser at the time of calling this method.
 *
 * If the parsed item is incompatible with the importer, then this will
 * fail and the item will not be queued.
 *
 * Returns: whether the item was queued or not
 */
gboolean
gcr_importer_queue_for_parsed (GcrImporter *importer,
                               GcrParsed *parsed)
{
	GcrImporterIface *iface;

	g_return_val_if_fail (GCR_IS_IMPORTER (importer), FALSE);
	g_return_val_if_fail (parsed != NULL, FALSE);

	iface = GCR_IMPORTER_GET_INTERFACE (importer);
	g_return_val_if_fail (iface != NULL, FALSE);
	g_return_val_if_fail (iface->queue_for_parsed != NULL, FALSE);

	return (iface->queue_for_parsed) (importer, parsed);
}
예제 #14
0
파일: gcr-importer.c 프로젝트: UIKit0/gcr
/**
 * gcr_importer_import_finish:
 * @importer: the importer
 * @result: an asynchronous result
 * @error: the location to place an error on failure, or %NULL
 *
 * Complete an asynchronous operation to import queued items.
 *
 * Returns: whether the import succeeded or failed
 */
gboolean
gcr_importer_import_finish (GcrImporter *importer,
                            GAsyncResult *result,
                            GError **error)
{
	GcrImporterIface *iface;

	g_return_val_if_fail (GCR_IS_IMPORTER (importer), FALSE);
	g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);

	iface = GCR_IMPORTER_GET_INTERFACE (importer);
	g_return_val_if_fail (iface != NULL, FALSE);
	g_return_val_if_fail (iface->import_finish != NULL, FALSE);

	return (iface->import_finish) (importer, result, error);
}
예제 #15
0
파일: gcr-importer.c 프로젝트: UIKit0/gcr
/**
 * gcr_importer_import_async:
 * @importer: the importer
 * @cancellable: a #GCancellable, or %NULL
 * @callback: called when the operation completes
 * @user_data: data to be passed to the callback
 *
 * Import the queued items in the importer. This function returns immediately
 * and completes asynchronously.
 */
void
gcr_importer_import_async (GcrImporter *importer,
                           GCancellable *cancellable,
                           GAsyncReadyCallback callback,
                           gpointer user_data)
{
	GcrImporterIface *iface;

	g_return_if_fail (GCR_IS_IMPORTER (importer));
	g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));

	iface = GCR_IMPORTER_GET_INTERFACE (importer);
	g_return_if_fail (iface != NULL);
	g_return_if_fail (iface->import_async != NULL);

	return (iface->import_async) (importer, cancellable, callback, user_data);
}
gboolean
gcr_importer_import_finish (GcrImporter *self, GAsyncResult *res, GError **error)
{
	g_return_val_if_fail (GCR_IS_IMPORTER (self), FALSE);
	g_return_val_if_fail (GCR_IMPORTER (res) == self, FALSE);
	g_return_val_if_fail (!error || !*error, FALSE);
	g_return_val_if_fail (!self->pv->processing, FALSE);

	g_assert (!self->pv->input);
	g_assert (!self->pv->cancel);
	
	if (!self->pv->succeeded) {
		g_propagate_error (error, self->pv->error);
		self->pv->error = NULL;
		return FALSE;
	}
	
	return TRUE;
}
void
gcr_importer_import_async (GcrImporter *self, GInputStream *input, GCancellable *cancel,
                           GAsyncReadyCallback callback, gpointer user_data)
{
	g_return_if_fail (GCR_IS_IMPORTER (self));
	g_return_if_fail (G_IS_INPUT_STREAM (input));
	g_return_if_fail (!self->pv->processing);
	
	cleanup_import_data (self);
	
	self->pv->input = g_object_ref (input);
	if (cancel)
		self->pv->cancel = g_object_ref (cancel);
	self->pv->processing = TRUE;
	self->pv->async = TRUE;
	self->pv->callback = callback;
	self->pv->user_data = user_data;
	
	next_state (self, state_read_buffer);
	g_assert (self->pv->processing);
}
static void 
state_parse_buffer (GcrImporter *self, gboolean async)
{
	GError *error = NULL;
	GcrParser *parser;
	gulong parsed_conn;
	gulong auth_conn;
	gboolean ret;
	
	g_assert (GCR_IS_IMPORTER (self));
	g_assert (self->pv->buffer);
	
	parser = gcr_importer_get_parser (self);
	g_object_ref (parser);

	/* Listen in to the parser */
	parsed_conn = g_signal_connect (parser, "parsed", G_CALLBACK (on_parser_parsed), self);
	auth_conn = g_signal_connect (parser, "authenticate", G_CALLBACK (on_parser_authenticate), self);

	ret = gcr_parser_parse_data (parser, self->pv->buffer->data, self->pv->buffer->len, &error);
	
	/* An optimization to free data early as possible */
	g_byte_array_free (self->pv->buffer, TRUE);
	self->pv->buffer = NULL;
	
	g_signal_handler_disconnect (parser, parsed_conn);
	g_signal_handler_disconnect (parser, auth_conn);
	g_object_unref (parser);
	
	if (ret == TRUE) {
		next_state (self, state_import_prompt);
	} else {
		g_propagate_error (&self->pv->error, error);
		next_state (self, state_failure);
	}
}
GP11Slot*
gcr_importer_get_slot (GcrImporter *self)
{
	g_return_val_if_fail (GCR_IS_IMPORTER (self), NULL);
	return self->pv->slot;
}
예제 #20
0
파일: gcr-importer.c 프로젝트: UIKit0/gcr
/**
 * gcr_importer_import:
 * @importer: the importer
 * @cancellable: a #GCancellable, or %NULL
 * @error: the location to place an error on failure, or %NULL
 *
 * Import the queued items in the importer. This call will block
 * until the operation completes.
 *
 * Returns: whether the items were imported successfully or not
 */
gboolean
gcr_importer_import (GcrImporter *importer,
                     GCancellable *cancellable,
                     GError **error)
{
	gboolean result;
	ImportClosure *closure;
	GcrImporterIface *iface;

	g_return_val_if_fail (GCR_IS_IMPORTER (importer), FALSE);
	g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);

	iface = GCR_IMPORTER_GET_INTERFACE (importer);
	if (iface->import_sync)
		return (iface->import_sync) (importer, cancellable, error);

	g_return_val_if_fail (iface->import_async != NULL, FALSE);
	g_return_val_if_fail (iface->import_finish != NULL, FALSE);

	closure = g_new0 (ImportClosure, 1);
	closure->cond = g_new (GCond, 1);
	g_cond_init (closure->cond);
	closure->mutex = g_new (GMutex, 1);
	g_mutex_init (closure->mutex);
	closure->context = g_main_context_get_thread_default ();
	g_mutex_lock (closure->mutex);

	(iface->import_async) (importer, cancellable, on_import_async_complete, closure);

	/*
	 * Handle the case where we've been called from within the main context
	 * or in the case where the main context is not running. This approximates
	 * the behavior of a modal dialog.
	 */
	if (g_main_context_acquire (closure->context)) {
		while (!closure->complete) {
			g_mutex_unlock (closure->mutex);
			g_main_context_iteration (closure->context, TRUE);
			g_mutex_lock (closure->mutex);
		}

		g_main_context_release (closure->context);

	/*
	 * Handle the case where we're in a different thread than the main
	 * context and a main loop is running.
	 */
	} else {
		while (!closure->complete)
			g_cond_wait (closure->cond, closure->mutex);
	}

	g_mutex_unlock (closure->mutex);

	result = (closure->error == NULL);
	if (closure->error)
		g_propagate_error (error, closure->error);

	g_cond_clear (closure->cond);
	g_free (closure->cond);
	g_mutex_clear (closure->mutex);
	g_free (closure->mutex);
	g_free (closure);

	return result;
}
GcrImporterPromptBehavior
gcr_importer_get_prompt_behavior (GcrImporter *self)
{
	g_return_val_if_fail (GCR_IS_IMPORTER (self), GCR_IMPORTER_PROMPT_NEEDED);
	return self->pv->behavior;
}
static gpointer
gcr_importer_real_get_user_data (GAsyncResult *base)
{
	g_return_val_if_fail (GCR_IS_IMPORTER (base), NULL);
	return GCR_IMPORTER (base)->pv->user_data;
}
static GObject* 
gcr_importer_real_get_source_object (GAsyncResult *base)
{
	g_return_val_if_fail (GCR_IS_IMPORTER (base), NULL);
	return G_OBJECT (base);
}