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; }
/** * 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"); }
/** * 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); } } }
/** * 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); }
/** * 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); }
/** * 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; }
/** * 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); }