/* * Copyright (C) 2005 Kouji TAKAO * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 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 Library General Public License for more details. * * You should have received a copy of the GNU 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. */ #ifdef HAVE_CONFIG_H # include #endif #include #include #include "gpass/file.h" #include "file-100.h" /*********************************************************** * * GPassFile100Reader * ***********************************************************/ static GError * reader_read_number(GPassDecryptStream *decrypt, gint *number) { guchar buffer[4]; gsize read_len; GError *error = gpass_decrypt_stream_read(decrypt, buffer, 4, &read_len); if (error != NULL) { return error; } if (read_len != 4) { g_set_error(&error, 0, 0, _("data is too short")); return error; } *number = GINT_FROM_LE(*((gint *) buffer)); return NULL; } static GError * reader_read_string(GPassDecryptStream *decrypt, gchar **str) { gchar *result; gint len; gsize read_len; GError *error = reader_read_number(decrypt, &len); if (error != NULL) { return error; } result = g_malloc(sizeof(gchar) * len + 1); error = gpass_decrypt_stream_read(decrypt, result, len, &read_len); if (error != NULL) { g_free(result); return error; } if (read_len != len) { g_free(result); g_set_error(&error, 0, 0, _("data is too short")); return error; } result[len] = '\0'; *str = result; return NULL; } static GError * file_100_reader_read_entry(GPassFileReader *self, guint *id, guint *parent_id, GPassEntry **entry) { gchar *type; GPassEntry *result; GPassAttributeList *attributes; GPassAttribute *attr; gint len; guchar *buffer; gsize read_len; GError *error = NULL; error = reader_read_number(self->decrypt, id); if (error != NULL) { return error; } error = reader_read_number(self->decrypt, parent_id); if (error != NULL) { return error; } error = reader_read_string(self->decrypt, &type); if (error != NULL) { return error; } error = gpass_entry_factory_create_entry(self->factory, type, &result); g_free(type); if (error != NULL) { return error; } error = reader_read_number(self->decrypt, &len); if (error != NULL) { goto end; } buffer = g_malloc(sizeof(guchar) * len); error = gpass_decrypt_stream_read(self->decrypt, buffer, len, &read_len); if (error != NULL) { g_free(buffer); goto end; } if (read_len != len) { g_free(buffer); g_set_error(&error, 0, 0, _("data is too short")); goto end; } attributes = gpass_entry_class_attributes(GPASS_ENTRY_GET_CLASS(result)); attr = g_object_new(GPASS_TYPE_ATTRIBUTE, "type", GPASS_ATTRIBUTE_TYPE_ENTRY_TYPE, "name", "type", NULL); error = gpass_attribute_list_prepend(attributes, attr); g_object_unref(attr); if (error == NULL) { error = gpass_attribute_list_load(attributes, buffer, len, &read_len); } g_free(buffer); if (error != NULL) { g_object_unref(attributes); goto end; } if (read_len != len) { g_object_unref(attributes); g_set_error(&error, 0, 0, _("invalid data")); goto end; } gpass_entry_set_attributes(result, attributes); g_object_unref(attributes); end: if (error != NULL) { g_object_unref(result); } else { *entry = result; } return error; } static void file_100_reader_class_initialize(gpointer g_class, gpointer g_class_data) { GPassFileReaderClass *reader_class = GPASS_FILE_READER_CLASS(g_class); reader_class->read_entry = file_100_reader_read_entry; } GType gpass_file_100_reader_get_type(void) { static GType type = 0; if (type == 0) { static const GTypeInfo info = { sizeof(GPassFile100ReaderClass), NULL, NULL, file_100_reader_class_initialize, NULL, NULL, sizeof(GPassFileReader), 0, NULL, }; type = g_type_register_static(GPASS_TYPE_FILE_READER, "GPassFile100Reader", &info, 0); } return type; } /*********************************************************** * * GPassFile100Writer * ***********************************************************/ static GError * writer_write_number(GPassEncryptStream *encrypt, gint number) { guchar *data; number = GINT_TO_LE(number); data = (guchar *) &number; return gpass_encrypt_stream_write(encrypt, data, sizeof(gint)); } static GError * writer_write_string(GPassEncryptStream *encrypt, const gchar *str) { gint len; GError *error; if (str == NULL || *str == '\0') { return writer_write_number(encrypt, 0); } len = strlen(str); error = writer_write_number(encrypt, len); if (error != NULL) { return error; } return gpass_encrypt_stream_write(encrypt, str, len); } static GError * file_100_writer_write_entry(GPassFileWriter *self, guint id, guint parent_id, GPassEntry *entry) { GPassAttributeList *attributes; GPassAttribute *attr; const gchar *type; GString *buf; GError *error; error = writer_write_number(self->encrypt, id); if (error != NULL) { return error; } error = writer_write_number(self->encrypt, parent_id); if (error != NULL) { return error; } g_object_get(entry, "type", &type, NULL); error = writer_write_string(self->encrypt, type); if (error != NULL) { return error; } attributes = gpass_entry_class_attributes(GPASS_ENTRY_GET_CLASS(entry)); gpass_entry_get_attributes(entry, attributes); attr = g_object_new(GPASS_TYPE_ATTRIBUTE, "type", GPASS_ATTRIBUTE_TYPE_ENTRY_TYPE, "name", "type", NULL); gpass_attribute_set(attr, type); error = gpass_attribute_list_prepend(attributes, attr); g_object_unref(attr); if (error != NULL) { g_object_unref(attributes); return error; } buf = g_string_new(NULL); error = gpass_attribute_list_dump(attributes, &buf); g_object_unref(attributes); if (error != NULL) { goto end; } error = writer_write_number(self->encrypt, buf->len); if (error != NULL) { goto end; } error = gpass_encrypt_stream_write(self->encrypt, buf->str, buf->len); end: g_string_free(buf, TRUE); return error; } static void file_100_writer_class_initialize(gpointer g_class, gpointer g_class_data) { GPassFileWriterClass *writer_class = GPASS_FILE_WRITER_CLASS(g_class); writer_class->write_entry = file_100_writer_write_entry; } GType gpass_file_100_writer_get_type(void) { static GType type = 0; if (type == 0) { static const GTypeInfo info = { sizeof(GPassFile100WriterClass), NULL, NULL, file_100_writer_class_initialize, NULL, NULL, sizeof(GPassFileWriter), 0, NULL, }; type = g_type_register_static(GPASS_TYPE_FILE_WRITER, "GPassFile100Writer", &info, 0); } return type; }