Blame gcr/gcr-gnupg-records.c

Packit b00eeb
/*
Packit b00eeb
 * Copyright (C) 2011 Collabora Ltd.
Packit b00eeb
 *
Packit b00eeb
 * This program is free software; you can redistribute it and/or modify
Packit b00eeb
 * it under the terms of the GNU Lesser General Public License as
Packit b00eeb
 * published by the Free Software Foundation; either version 2.1 of
Packit b00eeb
 * the License, or (at your option) any later version.
Packit b00eeb
 *
Packit b00eeb
 * This program is distributed in the hope that it will be useful, but
Packit b00eeb
 * WITHOUT ANY WARRANTY; without even the implied warranty of
Packit b00eeb
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit b00eeb
 * Lesser General Public License for more details.
Packit b00eeb
 *
Packit b00eeb
 * You should have received a copy of the GNU Lesser General Public
Packit b00eeb
 * License along with this program; if not, see <http://www.gnu.org/licenses/>.
Packit b00eeb
 *
Packit b00eeb
 * Author: Stef Walter <stefw@collabora.co.uk>
Packit b00eeb
 */
Packit b00eeb
Packit b00eeb
#include "config.h"
Packit b00eeb
Packit b00eeb
#include "gcr-gnupg-records.h"
Packit b00eeb
#include "gcr-record.h"
Packit b00eeb
#include "gcr-memory-icon.h"
Packit b00eeb
Packit b00eeb
#include "gck/gck.h"
Packit b00eeb
Packit b00eeb
#include <glib/gi18n-lib.h>
Packit b00eeb
Packit b00eeb
/* Copied from GPGME */
Packit b00eeb
gboolean
Packit b00eeb
_gcr_gnupg_records_parse_user_id (const gchar *user_id,
Packit b00eeb
                                  gchar **rname,
Packit b00eeb
                                  gchar **remail,
Packit b00eeb
                                  gchar **rcomment)
Packit b00eeb
{
Packit b00eeb
	gchar *src, *tail, *x;
Packit b00eeb
	int in_name = 0;
Packit b00eeb
	int in_email = 0;
Packit b00eeb
	int in_comment = 0;
Packit b00eeb
	gboolean anything;
Packit b00eeb
	const gchar *name = NULL;
Packit b00eeb
	const gchar *email = NULL;
Packit b00eeb
	const gchar *comment = NULL;
Packit b00eeb
Packit b00eeb
	x = tail = src = g_strdup (user_id);
Packit b00eeb
Packit b00eeb
	while (*src) {
Packit b00eeb
		if (in_email) {
Packit b00eeb
			/* Not legal but anyway.  */
Packit b00eeb
			if (*src == '<')
Packit b00eeb
				in_email++;
Packit b00eeb
			else if (*src == '>') {
Packit b00eeb
				if (!--in_email && !email) {
Packit b00eeb
					email = tail;
Packit b00eeb
					*src = 0;
Packit b00eeb
					tail = src + 1;
Packit b00eeb
				}
Packit b00eeb
			}
Packit b00eeb
		} else if (in_comment) {
Packit b00eeb
			if (*src == '(')
Packit b00eeb
				in_comment++;
Packit b00eeb
			else if (*src == ')') {
Packit b00eeb
				if (!--in_comment && !comment) {
Packit b00eeb
					comment = tail;
Packit b00eeb
					*src = 0;
Packit b00eeb
					tail = src + 1;
Packit b00eeb
				}
Packit b00eeb
			}
Packit b00eeb
		} else if (*src == '<') {
Packit b00eeb
			if (in_name) {
Packit b00eeb
				if (!name) {
Packit b00eeb
					name = tail;
Packit b00eeb
					*src = 0;
Packit b00eeb
					tail = src + 1;
Packit b00eeb
				}
Packit b00eeb
				in_name = 0;
Packit b00eeb
			} else
Packit b00eeb
				tail = src + 1;
Packit b00eeb
Packit b00eeb
			in_email = 1;
Packit b00eeb
		} else if (*src == '(') {
Packit b00eeb
			if (in_name) {
Packit b00eeb
				if (!name) {
Packit b00eeb
					name = tail;
Packit b00eeb
					*src = 0;
Packit b00eeb
					tail = src + 1;
Packit b00eeb
				}
Packit b00eeb
				in_name = 0;
Packit b00eeb
			}
Packit b00eeb
			in_comment = 1;
Packit b00eeb
		} else if (!in_name && *src != ' ' && *src != '\t') {
Packit b00eeb
			in_name = 1;
Packit b00eeb
		}
Packit b00eeb
		src++;
Packit b00eeb
	}
Packit b00eeb
Packit b00eeb
	if (in_name) {
Packit b00eeb
		if (!name) {
Packit b00eeb
			name = tail;
Packit b00eeb
			*src = 0;
Packit b00eeb
		}
Packit b00eeb
	}
Packit b00eeb
Packit b00eeb
	anything = FALSE;
Packit b00eeb
Packit b00eeb
	if (rname) {
Packit b00eeb
		*rname = g_strdup (name);
Packit b00eeb
		if (name) {
Packit b00eeb
			g_strstrip (*rname);
Packit b00eeb
			anything = TRUE;
Packit b00eeb
		}
Packit b00eeb
	}
Packit b00eeb
Packit b00eeb
	if (remail) {
Packit b00eeb
		*remail = g_strdup (email);
Packit b00eeb
		if (email) {
Packit b00eeb
			g_strstrip (*remail);
Packit b00eeb
			anything = TRUE;
Packit b00eeb
		}
Packit b00eeb
	}
Packit b00eeb
Packit b00eeb
	if (rcomment) {
Packit b00eeb
		*rcomment = g_strdup (comment);
Packit b00eeb
		if (comment) {
Packit b00eeb
			g_strstrip (*rcomment);
Packit b00eeb
			anything = TRUE;
Packit b00eeb
		}
Packit b00eeb
	}
Packit b00eeb
Packit b00eeb
	g_free (x);
Packit b00eeb
	return anything;
Packit b00eeb
}
Packit b00eeb
Packit b00eeb
const gchar *
Packit b00eeb
_gcr_gnupg_records_get_keyid (GPtrArray *records)
Packit b00eeb
{
Packit b00eeb
	GcrRecord *record;
Packit b00eeb
Packit b00eeb
	record = _gcr_records_find (records, GCR_RECORD_SCHEMA_PUB);
Packit b00eeb
	if (record != NULL)
Packit b00eeb
		return _gcr_record_get_raw (record, GCR_RECORD_KEY_KEYID);
Packit b00eeb
	record = _gcr_records_find (records, GCR_RECORD_SCHEMA_SEC);
Packit b00eeb
	if (record != NULL)
Packit b00eeb
		return _gcr_record_get_raw (record, GCR_RECORD_KEY_KEYID);
Packit b00eeb
	return NULL;
Packit b00eeb
}
Packit b00eeb
Packit b00eeb
const gchar *
Packit b00eeb
_gcr_gnupg_records_get_short_keyid (GPtrArray *records)
Packit b00eeb
{
Packit b00eeb
	const gchar *keyid;
Packit b00eeb
	gsize length;
Packit b00eeb
Packit b00eeb
	keyid = _gcr_gnupg_records_get_keyid (records);
Packit b00eeb
	if (keyid == NULL)
Packit b00eeb
		return NULL;
Packit b00eeb
Packit b00eeb
	length = strlen (keyid);
Packit b00eeb
	if (length > 8)
Packit b00eeb
		keyid += (length - 8);
Packit b00eeb
Packit b00eeb
	return keyid;
Packit b00eeb
}
Packit b00eeb
Packit b00eeb
gchar *
Packit b00eeb
_gcr_gnupg_records_get_user_id (GPtrArray *records)
Packit b00eeb
{
Packit b00eeb
	GcrRecord *record;
Packit b00eeb
Packit b00eeb
	record = _gcr_records_find (records, GCR_RECORD_SCHEMA_UID);
Packit b00eeb
	if (record != NULL)
Packit b00eeb
		return _gcr_record_get_string (record, GCR_RECORD_UID_USERID);
Packit b00eeb
	return NULL;
Packit b00eeb
}
Packit b00eeb
Packit b00eeb
const gchar *
Packit b00eeb
_gcr_gnupg_records_get_fingerprint (GPtrArray *records)
Packit b00eeb
{
Packit b00eeb
	GcrRecord *record;
Packit b00eeb
Packit b00eeb
	record = _gcr_records_find (records, GCR_RECORD_SCHEMA_FPR);
Packit b00eeb
	if (record != NULL)
Packit b00eeb
		return _gcr_record_get_raw (record, GCR_RECORD_FPR_FINGERPRINT);
Packit b00eeb
	return NULL;
Packit b00eeb
}
Packit b00eeb
Packit b00eeb
#define TYPE_IMAGE 0x01
Packit b00eeb
#define IMAGE_HEADER_LEN 0x10
Packit b00eeb
#define IMAGE_JPEG_SIG "\x10\x00\x01\x01"
Packit b00eeb
#define IMAGE_JPEG_SIG_LEN 4
Packit b00eeb
Packit b00eeb
static void
Packit b00eeb
add_emblem_to_icon (GIcon **icon,
Packit b00eeb
                    const gchar *emblem_name)
Packit b00eeb
{
Packit b00eeb
	GIcon *emblem_icon;
Packit b00eeb
	GIcon *result;
Packit b00eeb
	GEmblem *emblem;
Packit b00eeb
Packit b00eeb
	emblem_icon = g_themed_icon_new (emblem_name);
Packit b00eeb
	emblem = g_emblem_new_with_origin (emblem_icon, G_EMBLEM_ORIGIN_LIVEMETADATA);
Packit b00eeb
	result = g_emblemed_icon_new (*icon, emblem);
Packit b00eeb
	g_object_unref (*icon);
Packit b00eeb
	*icon = result;
Packit b00eeb
	g_object_unref (emblem);
Packit b00eeb
	g_object_unref (emblem_icon);
Packit b00eeb
}
Packit b00eeb
Packit b00eeb
GIcon *
Packit b00eeb
_gcr_gnupg_records_get_icon (GPtrArray *records)
Packit b00eeb
{
Packit b00eeb
	GcrRecord *record;
Packit b00eeb
	gchar validity;
Packit b00eeb
	guchar *data;
Packit b00eeb
	gsize n_data;
Packit b00eeb
	guint type;
Packit b00eeb
	GIcon *icon;
Packit b00eeb
	guint i;
Packit b00eeb
Packit b00eeb
	for (i = 0; i < records->len; i++) {
Packit b00eeb
		record = records->pdata[i];
Packit b00eeb
		if (GCR_RECORD_SCHEMA_XA1 != _gcr_record_get_schema (record))
Packit b00eeb
			continue;
Packit b00eeb
		if (!_gcr_record_get_uint (record, GCR_RECORD_XA1_TYPE, &type))
Packit b00eeb
			continue;
Packit b00eeb
		if (type != TYPE_IMAGE)
Packit b00eeb
			continue;
Packit b00eeb
Packit b00eeb
		data = _gcr_record_get_base64 (record, GCR_RECORD_XA1_DATA, &n_data);
Packit b00eeb
		g_return_val_if_fail (data != NULL, NULL);
Packit b00eeb
Packit b00eeb
		/* Header is 16 bytes long */
Packit b00eeb
		if (n_data <= IMAGE_HEADER_LEN) {
Packit b00eeb
			g_free (data);
Packit b00eeb
			continue;
Packit b00eeb
		}
Packit b00eeb
Packit b00eeb
		/* These are the header bytes. See gnupg doc/DETAILS */
Packit b00eeb
		g_assert (IMAGE_JPEG_SIG_LEN < IMAGE_HEADER_LEN);
Packit b00eeb
		if (memcmp (data, IMAGE_JPEG_SIG, IMAGE_JPEG_SIG_LEN) != 0) {
Packit b00eeb
			g_free (data);
Packit b00eeb
			continue;
Packit b00eeb
		}
Packit b00eeb
Packit b00eeb
		icon = G_ICON (_gcr_memory_icon_new_full ("image/jpeg", data,
Packit b00eeb
		                                          n_data, IMAGE_HEADER_LEN,
Packit b00eeb
		                                          g_free));
Packit b00eeb
Packit b00eeb
		validity = _gcr_record_get_char (record, GCR_RECORD_XA1_TRUST);
Packit b00eeb
		if (validity != 0 && validity != 'm' && validity != 'f' && validity != 'u')
Packit b00eeb
			add_emblem_to_icon (&icon, "dialog-question");
Packit b00eeb
Packit b00eeb
		/* We have a valid header */
Packit b00eeb
		return icon;
Packit b00eeb
	}
Packit b00eeb
Packit b00eeb
	if (_gcr_records_find (records, GCR_RECORD_SCHEMA_SEC))
Packit b00eeb
		return g_themed_icon_new ("gcr-key-pair");
Packit b00eeb
	else
Packit b00eeb
		return g_themed_icon_new ("gcr-key");
Packit b00eeb
Packit b00eeb
	return NULL;
Packit b00eeb
}