summaryrefslogtreecommitdiff
path: root/gcr/gcr-record.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcr/gcr-record.c')
-rw-r--r--gcr/gcr-record.c811
1 files changed, 0 insertions, 811 deletions
diff --git a/gcr/gcr-record.c b/gcr/gcr-record.c
deleted file mode 100644
index 7b065eb0..00000000
--- a/gcr/gcr-record.c
+++ /dev/null
@@ -1,811 +0,0 @@
-/*
- * gnome-keyring
- *
- * Copyright (C) 2011 Collabora Ltd.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
- *
- * Author: Stef Walter <stefw@collabora.co.uk>
- */
-
-#include "config.h"
-
-#include "gcr-record.h"
-#define DEBUG_FLAG GCR_DEBUG_PARSE
-#include "gcr-debug.h"
-
-#include "egg/egg-timegm.h"
-
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-
-#define MAX_COLUMNS 32
-
-typedef struct {
- gpointer next;
- gsize n_value;
- gchar value[1];
- /* Hangs off the end */
-} GcrRecordBlock;
-
-struct _GcrRecord {
- GcrRecordBlock *block;
- const gchar *columns[MAX_COLUMNS];
- guint n_columns;
- gchar delimiter;
-};
-
-G_DEFINE_BOXED_TYPE (GcrRecord, _gcr_record, _gcr_record_copy, _gcr_record_free);
-
-static GcrRecordBlock *
-record_block_new (const gchar *value,
- gsize length)
-{
- GcrRecordBlock *block;
-
- block = g_malloc (sizeof (GcrRecordBlock) + length);
- block->next = NULL;
- block->n_value = length;
-
- if (value != NULL) {
- memcpy (block->value, value, length);
- block->value[length] = 0;
- } else {
- block->value[0] = 0;
- }
-
- return block;
-}
-
-static GcrRecordBlock *
-record_block_take (gchar *value,
- gsize length)
-{
- GcrRecordBlock *block;
-
- g_assert (value);
-
- block = g_realloc (value, sizeof (GcrRecordBlock) + length);
- memmove (((gchar*)block) + G_STRUCT_OFFSET (GcrRecordBlock, value),
- block, length);
- block->next = NULL;
- block->n_value = length;
- block->value[length] = 0;
-
- return block;
-}
-
-static GcrRecord *
-record_flatten (GcrRecord *record)
-{
- GcrRecord *result;
- GcrRecordBlock *block;
- gsize total;
- gsize at;
- gsize len;
- guint i;
-
- /* Calculate the length of what we need */
- total = 0;
- for (i = 0; i < record->n_columns; i++)
- total += strlen (record->columns[i]) + 1;
-
- /* Allocate a new GcrRecordData which will hold all that */
- result = g_slice_new0 (GcrRecord);
- result->block = block = record_block_new (NULL, total);
-
- at = 0;
- for (i = 0; i < record->n_columns; i++) {
- len = strlen (record->columns[i]);
- result->columns[i] = block->value + at;
- memcpy ((gchar *)result->columns[i], record->columns[i], len + 1);
- at += len + 1;
- }
-
- result->n_columns = record->n_columns;
- result->delimiter = record->delimiter;
- g_assert (at == total);
-
- return result;
-}
-
-static void
-print_record_to_string (GcrRecord *record,
- GString *string)
-{
- guint i;
-
- for (i = 0; i < record->n_columns; i++) {
- g_string_append (string, record->columns[i]);
- g_string_append_c (string, record->delimiter);
- }
-}
-
-gchar *
-_gcr_record_format (GcrRecord *record)
-{
- GString *string;
-
- g_return_val_if_fail (record, NULL);
-
- string = g_string_new ("");
- print_record_to_string (record, string);
- return g_string_free (string, FALSE);
-}
-
-GcrRecord *
-_gcr_record_new (GQuark schema,
- guint n_columns,
- gchar delimiter)
-{
- GcrRecord *result;
- guint i;
-
- result = g_slice_new0 (GcrRecord);
- result->block = NULL;
- result->delimiter = delimiter;
-
- for (i = 0; i < n_columns; i++)
- result->columns[i] = "";
- result->columns[0] = g_quark_to_string (schema);
- result->n_columns = n_columns;
-
- return result;
-}
-
-GcrRecord *
-_gcr_record_copy (GcrRecord *record)
-{
- return record_flatten (record);
-}
-
-static GcrRecord *
-take_and_parse_internal (GcrRecordBlock *block,
- gchar delimiter,
- gboolean allow_empty)
-{
- GcrRecord *result;
- gchar *at, *beg, *end;
-
- g_assert (block);
-
- result = g_slice_new0 (GcrRecord);
- result->block = block;
- result->delimiter = delimiter;
-
- _gcr_debug ("parsing line %s", block->value);
-
- at = block->value;
- for (;;) {
- if (result->n_columns >= MAX_COLUMNS) {
- _gcr_debug ("too many record (%d) in gnupg line", MAX_COLUMNS);
- _gcr_record_free (result);
- return NULL;
- }
-
- beg = at;
- result->columns[result->n_columns] = beg;
-
- at = strchr (beg, delimiter);
- if (at == NULL) {
- end = (block->value + block->n_value) - 1;
- } else {
- at[0] = '\0';
- end = at;
- at++;
- }
-
- if (allow_empty || end > beg)
- result->n_columns++;
-
- if (at == NULL)
- break;
- }
-
- return result;
-}
-
-GcrRecord*
-_gcr_record_parse_colons (const gchar *line, gssize n_line)
-{
- g_return_val_if_fail (line, NULL);
- if (n_line < 0)
- n_line = strlen (line);
- return take_and_parse_internal (record_block_new (line, n_line), ':', TRUE);
-}
-
-GcrRecord*
-_gcr_record_parse_spaces (const gchar *line, gssize n_line)
-{
- g_return_val_if_fail (line, NULL);
- if (n_line < 0)
- n_line = strlen (line);
- return take_and_parse_internal (record_block_new (line, n_line), ' ', FALSE);
-}
-
-guint
-_gcr_record_get_count (GcrRecord *record)
-{
- g_return_val_if_fail (record, 0);
- return record->n_columns;
-}
-
-static void
-record_take_column (GcrRecord *record,
- guint column,
- GcrRecordBlock *block)
-{
- g_assert (block->next == NULL);
- block->next = record->block;
- record->block = block;
-
- g_assert (column < record->n_columns);
- record->columns[column] = block->value;
-}
-
-static const char HEXC_LOWER[] = "0123456789abcdef";
-
-/* Will return NULL if unescaping failed or not needed */
-static gchar *
-c_colons_unescape (const gchar *source,
- gsize *length)
-{
- const gchar *p = source, *octal, *hex;
- gchar *dest = NULL;
- gchar *q = dest;
- gchar *pos;
-
- while (*p) {
- if (*p == '\\') {
- if (dest == NULL) {
- dest = g_malloc (strlen (source) + 1);
- memcpy (dest, source, (p - source));
- q = dest + (p - source);
- }
-
- p++;
- switch (*p) {
- case '\0': /* invalid trailing backslash */
- g_free (dest);
- return NULL;
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7':
- *q = 0;
- octal = p;
- while ((p < octal + 3) && (*p >= '0') && (*p <= '7')) {
- *q = (*q * 8) + (*p - '0');
- p++;
- }
- q++;
- p--;
- break;
- case 'x':
- *q = 0;
- hex = p;
- while (p < hex + 2) {
- pos = strchr (HEXC_LOWER, g_ascii_tolower (*p));
- if (pos == 0) { /* invalid bad hex character */
- g_free (dest);
- return NULL;
- }
- *q = (*q * 16) + (pos - HEXC_LOWER);
- p++;
- }
- q++;
- p--;
- break;
- case 'b':
- *q++ = '\b';
- break;
- case 'f':
- *q++ = '\f';
- break;
- case 'n':
- *q++ = '\n';
- break;
- case 'r':
- *q++ = '\r';
- break;
- case 't':
- *q++ = '\t';
- break;
- default: /* Also handles \" and \\ */
- *q++ = *p;
- break;
- }
- } else if (q != NULL) {
- *q++ = *p;
- }
- p++;
- }
-
- if (q != NULL) {
- *q = 0;
- if (length)
- *length = q - dest;
- }
-
- return dest;
-}
-
-/* Will return NULL if no escaping needed */
-static gchar *
-c_colons_escape (const gchar *source,
- const gchar extra,
- gsize *length)
-{
- const guchar *p;
- gchar *dest = NULL;
- gchar *q = NULL;
- gchar escape;
- gsize off;
-
- g_return_val_if_fail (source != NULL, NULL);
-
- p = (guchar *) source;
-
- while (*p) {
- escape = 0;
- switch (*p) {
- case '\b':
- escape = 'b';
- break;
- case '\f':
- escape = 'f';
- break;
- case '\n':
- escape = 'n';
- break;
- case '\r':
- escape = 'r';
- break;
- case '\t':
- escape = 't';
- break;
- case '\\':
- escape = '\\';
- break;
- case '"':
- escape = '"';
- break;
- }
-
- if (escape != 0 || *p < ' ' || *p >= 0x127 || *p == extra) {
- if (dest == NULL) {
- /* Each source byte needs maximally four destination chars (\xff) */
- dest = g_malloc (strlen (source) * 4 + 1);
- off = (gchar *)p - source;
- memcpy (dest, source, off);
- q = dest + off;
- }
-
- if (escape) {
- *q++ = '\\';
- *q++ = escape;
- } else {
- *q++ = '\\';
- *q++ = 'x';
- *q++ = HEXC_LOWER[*p >> 4 & 0xf];
- *q++ = HEXC_LOWER[*p & 0xf];
- }
- } else if (q != NULL) {
- *q++ = *p;
- }
- p++;
- }
-
- if (q != NULL) {
- *q = 0;
- if (length)
- *length = q - dest;
- }
-
- return dest;
-}
-
-gchar*
-_gcr_record_get_string (GcrRecord *record, guint column)
-{
- const gchar *value;
- gchar *text = NULL;
-
- g_return_val_if_fail (record, NULL);
-
- value = _gcr_record_get_raw (record, column);
- if (!value)
- return NULL;
-
- text = c_colons_unescape (value, NULL);
- if (text != NULL)
- value = text;
-
- /* If it's not UTF-8, we guess that it's latin1 */
- if (!g_utf8_validate (value, -1, NULL)) {
- gchar *conv = g_convert (value, -1, "UTF-8", "ISO-8859-1", NULL, NULL, NULL);
- g_free (text);
- value = text = conv;
- }
-
- /*
- * latin1 to utf-8 conversion can't really fail, just produce
- * garbage... so there's no need to check here.
- */
-
- return (text == value) ? text : g_strdup (value);
-}
-
-void
-_gcr_record_set_string (GcrRecord *record,
- guint column,
- const gchar *string)
-{
- GcrRecordBlock *block;
- gchar *escaped;
-
- g_return_if_fail (record != NULL);
- g_return_if_fail (string != NULL);
- g_return_if_fail (column < record->n_columns);
-
- escaped = c_colons_escape (string, record->delimiter, NULL);
- if (escaped != NULL)
- block = record_block_take (escaped, strlen (escaped));
- else
- block = record_block_new (string, strlen (string));
-
- record_take_column (record, column, block);
-}
-
-gchar
-_gcr_record_get_char (GcrRecord *record,
- guint column)
-{
- const gchar *value;
-
- g_return_val_if_fail (record, 0);
-
- value = _gcr_record_get_raw (record, column);
- if (!value)
- return 0;
-
- if (value[0] != 0 && value[1] == 0)
- return value[0];
-
- return 0;
-}
-
-void
-_gcr_record_set_char (GcrRecord *record,
- guint column,
- gchar value)
-{
- g_return_if_fail (record != NULL);
- g_return_if_fail (column < record->n_columns);
- g_return_if_fail (value != 0);
-
- record_take_column (record, column, record_block_new (&value, 1));
-}
-
-gboolean
-_gcr_record_get_uint (GcrRecord *record, guint column, guint *value)
-{
- const gchar *raw;
- gint64 result;
- gchar *end = NULL;
-
- g_return_val_if_fail (record, FALSE);
-
- raw = _gcr_record_get_raw (record, column);
- if (raw == NULL)
- return FALSE;
-
- result = g_ascii_strtoll (raw, &end, 10);
- if (!end || end[0]) {
- _gcr_debug ("invalid unsigned integer value: %s", raw);
- return FALSE;
- }
-
- if (result < 0 || result > G_MAXUINT32) {
- _gcr_debug ("unsigned integer value is out of range: %s", raw);
- return FALSE;
- }
-
- if (value)
- *value = (guint)result;
- return TRUE;
-}
-
-void
-_gcr_record_set_uint (GcrRecord *record,
- guint column,
- guint value)
-{
- gchar *escaped;
-
- g_return_if_fail (record != NULL);
- g_return_if_fail (column < record->n_columns);
-
- escaped = g_strdup_printf ("%u", value);
- record_take_column (record, column,
- record_block_take (escaped, strlen (escaped)));
-}
-
-gboolean
-_gcr_record_get_ulong (GcrRecord *record,
- guint column,
- gulong *value)
-{
- const gchar *raw;
- gint64 result;
- gchar *end = NULL;
-
- g_return_val_if_fail (record, FALSE);
-
- raw = _gcr_record_get_raw (record, column);
- if (raw == NULL)
- return FALSE;
-
- result = g_ascii_strtoull (raw, &end, 10);
- if (!end || end[0]) {
- _gcr_debug ("invalid unsigned long value: %s", raw);
- return FALSE;
- }
-
- if (result < 0 || result > G_MAXULONG) {
- _gcr_debug ("unsigned long value is out of range: %s", raw);
- return FALSE;
- }
-
- if (value)
- *value = (guint)result;
- return TRUE;
-
-}
-
-void
-_gcr_record_set_ulong (GcrRecord *record,
- guint column,
- gulong value)
-{
- gchar *escaped;
-
- g_return_if_fail (record != NULL);
- g_return_if_fail (column < record->n_columns);
-
- escaped = g_strdup_printf ("%lu", value);
- record_take_column (record, column,
- record_block_take (escaped, strlen (escaped)));
-}
-
-GDateTime *
-_gcr_record_get_date (GcrRecord *record,
- guint column)
-{
- const gchar *raw;
- gulong result;
- gchar *end = NULL;
- struct tm tm;
-
- g_return_val_if_fail (record, NULL);
-
- raw = _gcr_record_get_raw (record, column);
- if (raw == NULL)
- return NULL;
-
- /* Try to parse as a number */
- result = strtoul (raw, &end, 10);
- if (end != NULL && end[0] == '\0')
- return g_date_time_new_from_unix_utc (result);
-
- /* Try to parse as a date */
- memset (&tm, 0, sizeof (tm));
- end = strptime (raw, "%Y-%m-%d", &tm);
- if (!end || end[0]) {
- _gcr_debug ("invalid date value: %s", raw);
- return NULL;
- }
-
- return g_date_time_new_utc (tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, 0, 0, 0);
-}
-
-/**
- * _gcr_record_get_base64:
- * @record: The record
- * @column: The column to decode.
- * @n_data: Location to return size of returned data.
- *
- * Decode a column of a record as base64 data.
- *
- * Returns: (transfer full): The decoded value, or %NULL if not found.
- */
-gpointer
-_gcr_record_get_base64 (GcrRecord *record, guint column, gsize *n_data)
-{
- const gchar *raw;
-
- g_return_val_if_fail (record, NULL);
-
- raw = _gcr_record_get_raw (record, column);
- if (raw == NULL)
- return NULL;
-
- return g_base64_decode (raw, n_data);
-}
-
-void
-_gcr_record_set_base64 (GcrRecord *record,
- guint column,
- gconstpointer data,
- gsize n_data)
-{
- GcrRecordBlock *block;
- gint state, save;
- gsize estimate;
- gsize length;
-
- g_return_if_fail (record != NULL);
- g_return_if_fail (column < record->n_columns);
-
- estimate = n_data * 4 / 3 + n_data * 4 / (3 * 65) + 7;
- block = record_block_new (NULL, estimate);
-
- /* The actual base64 data, without line breaks */
- state = save = 0;
- length = g_base64_encode_step ((guchar *)data, n_data, FALSE,
- block->value, &state, &save);
- length += g_base64_encode_close (TRUE, block->value + length,
- &state, &save);
- block->value[length] = 0;
- g_assert (length < estimate);
-
- g_strchomp (block->value);
- record_take_column (record, column, block);
-}
-
-const gchar*
-_gcr_record_get_raw (GcrRecord *record, guint column)
-{
- g_return_val_if_fail (record, NULL);
-
- if (column >= record->n_columns) {
- _gcr_debug ("only %d columns exist, tried to access %d",
- record->n_columns, column);
- return NULL;
- }
-
- return record->columns[column];
-}
-
-void
-_gcr_record_set_raw (GcrRecord *record,
- guint column,
- const gchar *value)
-{
- g_return_if_fail (record != NULL);
- g_return_if_fail (value != NULL);
- g_return_if_fail (column < record->n_columns);
-
- record_take_column (record, column,
- record_block_new (value, strlen (value)));
-}
-
-void
-_gcr_record_take_raw (GcrRecord *record,
- guint column,
- gchar *value)
-{
- g_return_if_fail (record != NULL);
- g_return_if_fail (value != NULL);
- g_return_if_fail (column < record->n_columns);
-
- record_take_column (record, column,
- record_block_take (value, strlen (value)));
-}
-
-void
-_gcr_record_free (gpointer record)
-{
- GcrRecordBlock *block, *next;
- GcrRecord *rec = record;
-
- if (!record)
- return;
-
- for (block = rec->block; block != NULL; block = next) {
- next = block->next;
- g_free (block);
- }
-
- g_slice_free (GcrRecord, record);
-}
-
-GQuark
-_gcr_record_get_schema (GcrRecord *record)
-{
- const gchar *value;
-
- value = _gcr_record_get_raw (record, GCR_RECORD_SCHEMA);
- if (value != NULL)
- return g_quark_try_string (value);
- return 0;
-}
-
-GcrRecord *
-_gcr_records_find (GPtrArray *records,
- GQuark schema)
-{
- guint i;
-
- g_return_val_if_fail (records, NULL);
- g_return_val_if_fail (schema, NULL);
-
- for (i = 0; i < records->len; i++) {
- if (schema == _gcr_record_get_schema (records->pdata[i]))
- return records->pdata[i];
- }
-
- return NULL;
-}
-
-gchar *
-_gcr_records_format (GPtrArray *records)
-{
- GString *string;
- guint i;
-
- g_return_val_if_fail (records, NULL);
-
- string = g_string_new ("");
- for (i = 0; i < records->len; i++) {
- print_record_to_string (records->pdata[i], string);
- g_string_append_c (string, '\n');
- }
- return g_string_free (string, FALSE);
-}
-
-GPtrArray *
-_gcr_records_parse_colons (gconstpointer data,
- gssize n_data)
-{
- GPtrArray *result = NULL;
- GcrRecordBlock *block;
- GcrRecord *record;
- gchar **lines;
- guint i;
-
- lines = g_strsplit (data, "\n", n_data);
- result = g_ptr_array_new_with_free_func (_gcr_record_free);
-
- for (i = 0; lines[i] != NULL; i++) {
- block = record_block_take (lines[i], strlen (lines[i]));
- record = take_and_parse_internal (block, ':', TRUE);
- if (record == NULL) {
- g_ptr_array_unref (result);
- result = NULL;
- break;
- }
- g_ptr_array_add (result, record);
- }
-
- /* Free any not done */
- for (; lines[i] != NULL; i++)
- g_free (lines[i]);
-
- /* Individual lines already freed */
- g_free (lines);
-
- return result;
-}