[evolution-data-server] Bug 670114 - Provide list of Mail certificates in UI
- From: Milan Crha <mcrha src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-data-server] Bug 670114 - Provide list of Mail certificates in UI
- Date: Thu, 11 Dec 2014 14:54:45 +0000 (UTC)
commit 752390607cbbb5f3a6fbc4b984814e45062764fd
Author: Milan Crha <mcrha redhat com>
Date: Thu Dec 11 15:53:13 2014 +0100
Bug 670114 - Provide list of Mail certificates in UI
Added necessary functions to be able to list and
load certificate files from the UI.
camel/camel-certdb.c | 151 +++++++++++++++++++++++++++++++++++++++++
camel/camel-certdb.h | 9 ++-
camel/camel-network-service.c | 122 ++-------------------------------
3 files changed, 167 insertions(+), 115 deletions(-)
---
diff --git a/camel/camel-certdb.c b/camel/camel-certdb.c
index 89fed39..c86cdd3 100644
--- a/camel/camel-certdb.c
+++ b/camel/camel-certdb.c
@@ -298,6 +298,123 @@ camel_cert_unref (CamelCert *cert)
}
}
+static const gchar *
+certdb_get_cert_dir (void)
+{
+ static gchar *cert_dir = NULL;
+
+ if (G_UNLIKELY (cert_dir == NULL)) {
+ const gchar *data_dir;
+ const gchar *home_dir;
+ gchar *old_dir;
+
+ home_dir = g_get_home_dir ();
+ data_dir = g_get_user_data_dir ();
+
+ cert_dir = g_build_filename (data_dir, "camel_certs", NULL);
+
+ /* Move the old certificate directory if present. */
+ old_dir = g_build_filename (home_dir, ".camel_certs", NULL);
+ if (g_file_test (old_dir, G_FILE_TEST_IS_DIR)) {
+ if (g_rename (old_dir, cert_dir) == -1) {
+ g_warning ("%s: Failed to rename '%s' to '%s': %s", G_STRFUNC, old_dir,
cert_dir, g_strerror (errno));
+ }
+ }
+ g_free (old_dir);
+
+ g_mkdir_with_parents (cert_dir, 0700);
+ }
+
+ return cert_dir;
+}
+
+gboolean
+camel_cert_load_cert_file (CamelCert *cert,
+ GError **error)
+{
+ gchar *contents = NULL;
+ gchar *filename;
+ gsize length;
+ const gchar *cert_dir;
+
+ g_return_val_if_fail (cert != NULL, FALSE);
+
+ if (cert->rawcert) {
+ g_bytes_unref (cert->rawcert);
+ cert->rawcert = NULL;
+ }
+
+ cert_dir = certdb_get_cert_dir ();
+ filename = g_build_filename (cert_dir, cert->fingerprint, NULL);
+
+ if (g_file_get_contents (filename, &contents, &length, error))
+ cert->rawcert = g_bytes_new_take (contents, length);
+
+ g_free (filename);
+
+ return cert->rawcert != NULL;
+}
+
+gboolean
+camel_cert_save_cert_file (CamelCert *cert,
+ const GByteArray *der_data,
+ GError **error)
+{
+ GFile *file;
+ GFileOutputStream *output_stream;
+ gchar *filename;
+ const gchar *cert_dir;
+
+ g_return_val_if_fail (cert != NULL, FALSE);
+ g_return_val_if_fail (der_data != NULL, FALSE);
+
+ if (cert->rawcert) {
+ g_bytes_unref (cert->rawcert);
+ cert->rawcert = NULL;
+ }
+
+ cert_dir = certdb_get_cert_dir ();
+ filename = g_build_filename (cert_dir, cert->fingerprint, NULL);
+ file = g_file_new_for_path (filename);
+
+ output_stream = g_file_replace (
+ file, NULL, FALSE,
+ G_FILE_CREATE_REPLACE_DESTINATION,
+ NULL, error);
+
+ g_object_unref (file);
+ g_free (filename);
+
+ if (output_stream != NULL) {
+ gssize n_written;
+ GBytes *bytes;
+
+ /* XXX Treat GByteArray as though its data is owned by
+ * GTlsCertificate. That means avoiding functions
+ * like g_byte_array_free_to_bytes() that alter or
+ * reset the GByteArray. */
+ bytes = g_bytes_new (der_data->data, der_data->len);
+
+ /* XXX Not handling partial writes, but GIO does not make
+ * it easy. Need a g_output_stream_write_all_bytes().
+ * (see: https://bugzilla.gnome.org/708838) */
+ n_written = g_output_stream_write_bytes (
+ G_OUTPUT_STREAM (output_stream),
+ bytes, NULL, error);
+
+ if (n_written < 0) {
+ g_bytes_unref (bytes);
+ bytes = NULL;
+ }
+
+ cert->rawcert = bytes;
+
+ g_object_unref (output_stream);
+ }
+
+ return cert->rawcert != NULL;
+}
+
CamelCertDB *
camel_certdb_new (void)
{
@@ -659,3 +776,37 @@ camel_certdb_clear (CamelCertDB *certdb)
g_mutex_unlock (&certdb->priv->db_lock);
}
+/**
+ * camel_certdb_list_certs:
+ * @certdb: a #CamelCertDB
+ *
+ * Gathers a list of known certificates. Each certificate in the returned #GSList
+ * is referenced, thus unref it with camel_cert_unref() when done with it, the same
+ * as free the list itself.
+ *
+ * Returns: (transfer full): (element-type CamelCert): Newly allocated list of
+ * referenced CamelCert-s, which are stored in the @certdb.
+ *
+ * Since: 3.14
+ **/
+GSList *
+camel_certdb_list_certs (CamelCertDB *certdb)
+{
+ GSList *certs = NULL;
+ gint ii;
+
+ g_return_val_if_fail (CAMEL_IS_CERTDB (certdb), NULL);
+
+ g_mutex_lock (&certdb->priv->db_lock);
+
+ for (ii = 0; ii < certdb->priv->certs->len; ii++) {
+ CamelCert *cert = (CamelCert *) certdb->priv->certs->pdata[ii];
+
+ camel_cert_ref (cert);
+ certs = g_slist_prepend (certs, cert);
+ }
+
+ g_mutex_unlock (&certdb->priv->db_lock);
+
+ return g_slist_reverse (certs);
+}
diff --git a/camel/camel-certdb.h b/camel/camel-certdb.h
index 7f400c3..517e67f 100644
--- a/camel/camel-certdb.h
+++ b/camel/camel-certdb.h
@@ -70,7 +70,7 @@ typedef struct {
gchar *fingerprint;
CamelCertTrust trust;
- GBytes *rawcert;
+ GBytes *rawcert; /* loaded on demand, with camel_cert_load_cert_file() */
} CamelCert;
struct _CamelCertDB {
@@ -96,6 +96,11 @@ struct _CamelCertDBClass {
CamelCert * camel_cert_new (void);
void camel_cert_ref (CamelCert *cert);
void camel_cert_unref (CamelCert *cert);
+gboolean camel_cert_load_cert_file (CamelCert *cert,
+ GError **error);
+gboolean camel_cert_save_cert_file (CamelCert *cert,
+ const GByteArray *der_data,
+ GError **error);
GType camel_certdb_get_type (void) G_GNUC_CONST;
CamelCertDB * camel_certdb_new (void);
@@ -126,6 +131,8 @@ void camel_certdb_remove_host (CamelCertDB *certdb,
void camel_certdb_clear (CamelCertDB *certdb);
+GSList * camel_certdb_list_certs (CamelCertDB *certdb);
+
G_END_DECLS
#endif /* CAMEL_CERTDB_H */
diff --git a/camel/camel-network-service.c b/camel/camel-network-service.c
index 188b2bb..b70afc0 100644
--- a/camel/camel-network-service.c
+++ b/camel/camel-network-service.c
@@ -66,36 +66,6 @@ G_DEFINE_INTERFACE (
camel_network_service,
CAMEL_TYPE_SERVICE)
-static const gchar *
-network_service_get_cert_dir (void)
-{
- static gchar *cert_dir = NULL;
-
- if (G_UNLIKELY (cert_dir == NULL)) {
- const gchar *data_dir;
- const gchar *home_dir;
- gchar *old_dir;
-
- home_dir = g_get_home_dir ();
- data_dir = g_get_user_data_dir ();
-
- cert_dir = g_build_filename (data_dir, "camel_certs", NULL);
-
- /* Move the old certificate directory if present. */
- old_dir = g_build_filename (home_dir, ".camel_certs", NULL);
- if (g_file_test (old_dir, G_FILE_TEST_IS_DIR)) {
- if (g_rename (old_dir, cert_dir) == -1) {
- g_warning ("%s: Failed to rename '%s' to '%s': %s", G_STRFUNC, old_dir,
cert_dir, g_strerror (errno));
- }
- }
- g_free (old_dir);
-
- g_mkdir_with_parents (cert_dir, 0700);
- }
-
- return cert_dir;
-}
-
static gchar *
network_service_generate_fingerprint (GTlsCertificate *certificate)
{
@@ -139,86 +109,6 @@ network_service_generate_fingerprint (GTlsCertificate *certificate)
return g_string_free (fingerprint, FALSE);
}
-static GBytes *
-network_service_load_cert_file (const gchar *fingerprint,
- GError **error)
-{
- GBytes *bytes = NULL;
- gchar *contents = NULL;
- gchar *filename;
- gsize length;
- const gchar *cert_dir;
-
- cert_dir = network_service_get_cert_dir ();
- filename = g_build_filename (cert_dir, fingerprint, NULL);
-
- if (g_file_get_contents (filename, &contents, &length, error))
- bytes = g_bytes_new_take (contents, length);
-
- g_free (filename);
-
- return bytes;
-}
-
-static GBytes *
-network_service_save_cert_file (GTlsCertificate *certificate,
- GError **error)
-{
- GByteArray *der;
- GBytes *bytes = NULL;
- GFile *file;
- GFileOutputStream *output_stream;
- gchar *filename;
- gchar *fingerprint;
- const gchar *cert_dir;
-
- /* XXX No accessor function for this property. */
- g_object_get (certificate, "certificate", &der, NULL);
- g_return_val_if_fail (der != NULL, NULL);
-
- fingerprint = network_service_generate_fingerprint (certificate);
- g_return_val_if_fail (fingerprint != NULL, NULL);
-
- cert_dir = network_service_get_cert_dir ();
- filename = g_build_filename (cert_dir, fingerprint, NULL);
- file = g_file_new_for_path (filename);
-
- output_stream = g_file_replace (
- file, NULL, FALSE,
- G_FILE_CREATE_REPLACE_DESTINATION,
- NULL, error);
-
- g_object_unref (file);
- g_free (filename);
-
- if (output_stream != NULL) {
- gssize n_written;
-
- /* XXX Treat GByteArray as though its data is owned by
- * GTlsCertificate. That means avoiding functions
- * like g_byte_array_free_to_bytes() that alter or
- * reset the GByteArray. */
- bytes = g_bytes_new (der->data, der->len);
-
- /* XXX Not handling partial writes, but GIO does not make
- * it easy. Need a g_output_stream_write_all_bytes().
- * (see: https://bugzilla.gnome.org/708838) */
- n_written = g_output_stream_write_bytes (
- G_OUTPUT_STREAM (output_stream),
- bytes, NULL, error);
-
- if (n_written < 0) {
- g_bytes_unref (bytes);
- bytes = NULL;
- }
- }
-
- g_byte_array_unref (der);
- g_free (fingerprint);
-
- return bytes;
-}
-
static CamelCert *
network_service_certdb_lookup (CamelCertDB *certdb,
GTlsCertificate *certificate,
@@ -239,8 +129,7 @@ network_service_certdb_lookup (CamelCertDB *certdb,
if (cert->rawcert == NULL) {
GError *local_error = NULL;
- cert->rawcert = network_service_load_cert_file (
- fingerprint, &local_error);
+ camel_cert_load_cert_file (cert, &local_error);
/* Sanity check. */
g_warn_if_fail (
@@ -285,10 +174,15 @@ network_service_certdb_store (CamelCertDB *certdb,
CamelCert *cert,
GTlsCertificate *certificate)
{
+ GByteArray *der = NULL;
GError *local_error = NULL;
- cert->rawcert = network_service_save_cert_file (
- certificate, &local_error);
+ g_object_get (certificate, "certificate", &der, NULL);
+ g_return_if_fail (der != NULL);
+
+ camel_cert_save_cert_file (cert, der, &local_error);
+
+ g_byte_array_unref (der);
/* Sanity check. */
g_warn_if_fail (
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]