/* * 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/configuration.h" #include "folder.h" #include "general-password.h" #include "gpass/error.h" #include "gpass/entry-factory.h" typedef struct { const gchar *type; GType (*get_type)(void); GPassEntryClass *klass; gint index; const gchar *nick; gchar *launcher; } get_type_entry_t; static get_type_entry_t get_types[] = { { "folder", gpass_folder_get_type }, { "general", gpass_general_password_get_type }, }; #define DEFAULT_TYPE "general" /*********************************************************** * * GPassEntryFactoryCursor * ***********************************************************/ static void gpass_entry_factory_cursor_instance_init(GTypeInstance *instance, gpointer g_class) { GPassEntryFactoryCursor *self = GPASS_ENTRY_FACTORY_CURSOR(instance); self->entry_factory = NULL; self->index = 0; self->max_index = 0; } enum { CURSOR_PROP_0, CURSOR_PROP_ENTRY_FACTORY, CURSOR_PROP_INDEX, CURSOR_PROP_MAX_INDEX, CURSOR_PROP_TYPE, CURSOR_PROP_NICK, CURSOR_PROP_LAUNCHER, CURSOR_PROP_ICON_ID, CURSOR_PROP_CAN_HAVE_CHILD, CURSOR_PROP_ENTRY_CLASS, }; static gboolean check_index(GPassEntryFactoryCursor *self) { if (self->index < 0 || self->index >= self->max_index) { return FALSE; } return TRUE; } static void gpass_entry_factory_cursor_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { GPassEntryFactoryCursor *self = GPASS_ENTRY_FACTORY_CURSOR(object); gpointer ptr; gint index; switch (prop_id) { case CURSOR_PROP_ENTRY_FACTORY: ptr = g_value_get_pointer(value); if (self->entry_factory != ptr) { self->entry_factory = ptr; } break; case CURSOR_PROP_INDEX: index = g_value_get_int(value); if (self->index != index) { if (index < 0) { index = self->max_index + index; } self->index = index; } break; case CURSOR_PROP_MAX_INDEX: self->max_index = g_value_get_int(value); break; case CURSOR_PROP_LAUNCHER: if (check_index(self)) { get_type_entry_t *entry = &get_types[self->index]; const gchar *launcher; GPassConfiguration *config; launcher = g_value_get_string(value); if (strcmp(launcher, entry->launcher) != 0) { g_free(entry->launcher); entry->launcher = g_strdup(launcher); config = gpass_configuration_instance(); gpass_configuration_set_launcher(config, entry->type, entry->launcher); } } break; case CURSOR_PROP_ENTRY_CLASS: if (check_index(self)) { get_type_entry_t *entry = &get_types[self->index]; GPassEntryClass *entry_class; entry_class = GPASS_ENTRY_CLASS(g_value_get_pointer(value)); if (entry->klass != NULL) { g_type_class_unref(entry->klass); } entry->klass = entry_class; } break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void gpass_entry_factory_cursor_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { GPassEntryFactoryCursor *self = GPASS_ENTRY_FACTORY_CURSOR(object); switch (prop_id) { case CURSOR_PROP_INDEX: g_value_set_int(value, self->index); break; case CURSOR_PROP_MAX_INDEX: g_value_set_int(value, self->max_index); break; case CURSOR_PROP_TYPE: if (check_index(self)) { g_value_set_static_string(value, get_types[self->index].type); } else { g_value_set_static_string(value, NULL); } break; case CURSOR_PROP_NICK: if (check_index(self)) { g_value_set_static_string(value, get_types[self->index].nick); } else { g_value_set_static_string(value, NULL); } break; case CURSOR_PROP_LAUNCHER: if (check_index(self)) { g_value_set_static_string(value, get_types[self->index].launcher); } else { g_value_set_static_string(value, NULL); } break; case CURSOR_PROP_ICON_ID: if (check_index(self)) { GPassEntryClass *klass = get_types[self->index].klass; const gchar *icon_id = gpass_entry_class_icon_id(klass); g_value_set_static_string(value, icon_id); } else { g_value_set_static_string(value, NULL); } break; case CURSOR_PROP_CAN_HAVE_CHILD: if (check_index(self)) { GPassEntryClass *klass = get_types[self->index].klass; gboolean can_have_child = gpass_entry_class_can_have_child(klass); g_value_set_boolean(value, can_have_child); } else { g_value_set_boolean(value, FALSE); } break; case CURSOR_PROP_ENTRY_CLASS: if (check_index(self)) { g_value_set_pointer(value, get_types[self->index].klass); } else { g_value_set_pointer(value, NULL); } break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void gpass_entry_factory_cursor_class_init(gpointer g_class, gpointer g_class_data) { GObjectClass *gobject_class = G_OBJECT_CLASS(g_class); gobject_class->set_property = gpass_entry_factory_cursor_set_property; gobject_class->get_property = gpass_entry_factory_cursor_get_property; g_object_class_install_property (gobject_class, CURSOR_PROP_ENTRY_FACTORY, g_param_spec_pointer("entry_factory", _("GPassEntryFactory"), _("The pointer of GPassEntryFactory"), G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); g_object_class_install_property (gobject_class, CURSOR_PROP_INDEX, g_param_spec_int("index", _("Index"), _("The index of cursor"), G_MININT, G_MAXINT, 0, G_PARAM_READWRITE)); g_object_class_install_property (gobject_class, CURSOR_PROP_MAX_INDEX, g_param_spec_int("max_index", _("Max index"), _("The maximum index of cursor"), 0, G_MAXINT, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); g_object_class_install_property (gobject_class, CURSOR_PROP_TYPE, g_param_spec_string("type", _("Type"), _("The type of GPassEntry subclass"), NULL, G_PARAM_READABLE)); g_object_class_install_property (gobject_class, CURSOR_PROP_NICK, g_param_spec_string("nick", _("Nickname"), _("The nickname of GPassEntry subclass"), NULL, G_PARAM_READABLE)); g_object_class_install_property (gobject_class, CURSOR_PROP_LAUNCHER, g_param_spec_string("launcher", _("Launcher"), _("The launcher of GPassEntry subclass"), NULL, G_PARAM_READWRITE)); g_object_class_install_property (gobject_class, CURSOR_PROP_ICON_ID, g_param_spec_string("icon_id", _("Icon ID"), _("The identifier of icon"), NULL, G_PARAM_READABLE)); g_object_class_install_property (gobject_class, CURSOR_PROP_CAN_HAVE_CHILD, g_param_spec_boolean("can_have_child", _("Can have child"), _("Wether entry can have child"), FALSE, G_PARAM_READABLE)); g_object_class_install_property (gobject_class, CURSOR_PROP_ENTRY_CLASS, g_param_spec_pointer("entry_class", _("GPassEntryClass"), _("The pointer of GPassEntry subclass"), G_PARAM_READWRITE)); } GType gpass_entry_factory_cursor_get_type(void) { static GType type = 0; if (type == 0) { static const GTypeInfo info = { sizeof(GPassEntryFactoryCursorClass), NULL, NULL, gpass_entry_factory_cursor_class_init, NULL, NULL, sizeof(GPassEntryFactoryCursor), 0, gpass_entry_factory_cursor_instance_init }; type = g_type_register_static(G_TYPE_OBJECT, "GPassEntryFactoryCursor", &info, 0); } return type; } void gpass_entry_factory_cursor_next(GPassEntryFactoryCursor *self) { self->index++; } static GError *lookup_get_type_entry(GPassEntryFactory *self, const gchar *type, get_type_entry_t **entry); GError * gpass_entry_factory_cursor_seek(GPassEntryFactoryCursor *self, const gchar *type) { get_type_entry_t *entry; GError *error; error = lookup_get_type_entry(self->entry_factory, type, &entry); if (error != NULL) { return error; } self->index = entry->index; return NULL; } gboolean gpass_entry_factory_cursor_is_done(GPassEntryFactoryCursor *self) { return !(self->index < self->max_index); } /*********************************************************** * * GPassEntryFactory * ***********************************************************/ static GObjectClass *parent_class = NULL; static void get_type_entry_destroy(gpointer value) { get_type_entry_t *entry = value; g_type_class_unref(entry->klass); g_free(entry->launcher); } static void gpass_entry_factory_instance_init(GTypeInstance *instance, gpointer g_class) { GPassEntryFactory *self = GPASS_ENTRY_FACTORY(instance); GPassConfiguration *config; int i; self->get_types = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, get_type_entry_destroy); config = gpass_configuration_instance(); for (i = 0; i < G_N_ELEMENTS(get_types); i++) { gchar *launcher; get_types[i].klass = g_type_class_ref(get_types[i].get_type()); get_types[i].index = i; get_types[i].nick = gpass_entry_class_nick(get_types[i].klass); gpass_configuration_get_launcher(config, get_types[i].type, &launcher); if (launcher == NULL) { launcher = g_strdup (gpass_entry_class_default_launcher(get_types[i].klass)); gpass_configuration_set_launcher(config, get_types[i].type, launcher); } get_types[i].launcher = launcher; g_hash_table_insert(self->get_types, (gpointer) get_types[i].type, &get_types[i]); } } static void gpass_entry_factory_instance_finalize(GObject *object) { GPassEntryFactory *self = GPASS_ENTRY_FACTORY(object); g_hash_table_destroy(self->get_types); G_OBJECT_CLASS(parent_class)->finalize(object); } static void gpass_entry_factory_class_init(gpointer g_class, gpointer g_class_data) { GObjectClass *gobject_class = G_OBJECT_CLASS(g_class); parent_class = g_type_class_peek_parent(g_class); gobject_class->finalize = gpass_entry_factory_instance_finalize; } GType gpass_entry_factory_get_type(void) { static GType type = 0; if (type == 0) { static const GTypeInfo info = { sizeof(GPassEntryFactoryClass), NULL, NULL, gpass_entry_factory_class_init, NULL, NULL, sizeof(GPassEntryFactory), 0, gpass_entry_factory_instance_init }; type = g_type_register_static(G_TYPE_OBJECT, "GPassEntryFactoryType", &info, 0); } return type; } static GError * lookup_get_type_entry(GPassEntryFactory *self, const gchar *type, get_type_entry_t **entry) { GError *error = NULL; if (type == NULL) { type = DEFAULT_TYPE; } *entry = g_hash_table_lookup(self->get_types, type); if (*entry == NULL) { g_set_error(&error, 0, 0,_("No such password type: %s\n"), type); } return error; } GError * gpass_entry_factory_create_entry(GPassEntryFactory *self, const gchar *type, GPassEntry **entry) { get_type_entry_t *e; GError *error; error = lookup_get_type_entry(self, type, &e); if (error != NULL) { return error; } *entry = GPASS_ENTRY(g_object_new(e->get_type(), NULL)); return NULL; } GError * gpass_entry_factory_create_default_entry(GPassEntryFactory *self, GPassEntry **entry) { get_type_entry_t *e; GError *error; error = lookup_get_type_entry(self, DEFAULT_TYPE, &e); if (error != NULL) { return error; } *entry = GPASS_ENTRY(g_object_new(e->get_type(), NULL)); return NULL; } GPassEntryFactoryCursor * gpass_entry_factory_create_cursor(GPassEntryFactory *self) { gint max_index = g_hash_table_size(self->get_types); return g_object_new(GPASS_TYPE_ENTRY_FACTORY_CURSOR, "entry_factory", self, "max_index", max_index, NULL); }