/* * 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 "util.h" #include "gpass/entry.h" static GObjectClass *parent_class = NULL; static void entry_instance_init(GTypeInstance *instance, gpointer g_class) { GPassEntry *self = GPASS_ENTRY(instance); self->type = "entry"; self->node = g_node_new(self); self->name = g_strdup(""); self->description = g_strdup(""); self->creation_time = 0; self->modification_time = 0; self->expiration = FALSE; self->expiration_time = 0; } enum { PROP_0, PROP_TYPE, PROP_NAME, PROP_DESCRIPTION, PROP_CREATION_TIME, PROP_MODIFICATION_TIME, PROP_EXPIRATION, PROP_EXPIRATION_TIME, PROP_ID, }; static void entry_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { GPassEntry *self = GPASS_ENTRY(object); switch (prop_id) { case PROP_NAME: g_free(self->name); self->name = g_value_dup_string(value); break; case PROP_DESCRIPTION: g_free(self->description); self->description = g_value_dup_string(value); break; case PROP_CREATION_TIME: self->creation_time = (time_t) g_value_get_ulong(value); break; case PROP_MODIFICATION_TIME: self->modification_time = (time_t) g_value_get_ulong(value); break; case PROP_EXPIRATION: self->expiration = g_value_get_boolean(value); break; case PROP_EXPIRATION_TIME: self->expiration_time = (time_t) g_value_get_ulong(value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void entry_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { GPassEntry *self = GPASS_ENTRY(object); switch (prop_id) { case PROP_TYPE: g_value_set_static_string(value, self->type); break; case PROP_NAME: g_value_set_static_string(value, self->name); break; case PROP_DESCRIPTION: g_value_set_static_string(value, self->description); break; case PROP_CREATION_TIME: g_value_set_ulong(value, (gulong) self->creation_time); break; case PROP_MODIFICATION_TIME: g_value_set_ulong(value, (gulong) self->modification_time); break; case PROP_EXPIRATION: g_value_set_boolean(value, self->expiration); break; case PROP_EXPIRATION_TIME: g_value_set_ulong(value, (gulong) self->expiration_time); break; case PROP_ID: g_value_set_static_string(value, self->name); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void finalize_children(GPassEntry *self) { GPassEntry *p, *next; p = gpass_entry_first_child(self); while (p != NULL) { next = gpass_entry_next_sibling(p); g_object_unref(p); p = next; } } static void entry_instance_finalize(GObject *object) { GPassEntry *self = GPASS_ENTRY(object); finalize_children(self); g_node_unlink(self->node); g_node_destroy(self->node); g_free(self->name); g_free(self->description); G_OBJECT_CLASS(parent_class)->finalize(object); } static const gchar * entry_class_nick(void) { return ""; } static const gchar * entry_class_icon_id(void) { return ""; } static const gchar * entry_class_default_launcher(void) { return ""; } static gboolean entry_class_can_have_child(void) { return FALSE; } static void entry_class_attributes(GPassEntryClass *self_class, GPassAttributeList *attributes) { GObjectClass *g_object_class = G_OBJECT_CLASS(self_class); GPassAttribute *attr; GParamSpec *spec; spec = g_object_class_find_property(g_object_class, "name"); attr = gpass_param_spec_to_attribute(spec, GPASS_ATTRIBUTE_TYPE_STRING); gpass_attribute_list_append(attributes, attr); g_object_unref(attr); spec = g_object_class_find_property(g_object_class, "description"); attr = gpass_param_spec_to_attribute(spec, GPASS_ATTRIBUTE_TYPE_TEXT); gpass_attribute_list_append(attributes, attr); g_object_unref(attr); spec = g_object_class_find_property(g_object_class, "creation-time"); attr = gpass_param_spec_to_attribute(spec, GPASS_ATTRIBUTE_TYPE_TIME); gpass_attribute_list_append(attributes, attr); g_object_unref(attr); spec = g_object_class_find_property(g_object_class, "modification-time"); attr = gpass_param_spec_to_attribute(spec, GPASS_ATTRIBUTE_TYPE_TIME); gpass_attribute_list_append(attributes, attr); g_object_unref(attr); spec = g_object_class_find_property(g_object_class, "expiration"); attr = gpass_param_spec_to_attribute(spec, GPASS_ATTRIBUTE_TYPE_BOOLEAN); gpass_attribute_list_append(attributes, attr); g_object_unref(attr); spec = g_object_class_find_property(g_object_class, "expiration-time"); attr = gpass_param_spec_to_attribute(spec, GPASS_ATTRIBUTE_TYPE_TIME); gpass_attribute_list_append(attributes, attr); g_object_unref(attr); } static void entry_instance_set_attributes(GPassEntry *self, GPassAttributeList *attributes) { GPassAttribute *attr; attr = gpass_attribute_list_lookup(attributes, "name"); if (attr != NULL) { g_object_set_property(G_OBJECT(self), "name", attr->value); } attr = gpass_attribute_list_lookup(attributes, "description"); if (attr != NULL) { g_object_set_property(G_OBJECT(self), "description", attr->value); } attr = gpass_attribute_list_lookup(attributes, "creation-time"); if (attr != NULL) { g_object_set_property(G_OBJECT(self), "creation-time", attr->value); } attr = gpass_attribute_list_lookup(attributes, "modification-time"); if (attr != NULL) { g_object_set_property(G_OBJECT(self), "modification-time", attr->value); } attr = gpass_attribute_list_lookup(attributes, "expiration"); if (attr != NULL) { g_object_set_property(G_OBJECT(self), "expiration", attr->value); } attr = gpass_attribute_list_lookup(attributes, "expiration-time"); if (attr != NULL) { g_object_set_property(G_OBJECT(self), "expiration-time", attr->value); } } static void entry_instance_get_attributes(GPassEntry *self, GPassAttributeList *attributes) { GPassAttribute *attr; attr = gpass_attribute_list_lookup(attributes, "name"); if (attr != NULL) { gpass_attribute_set(attr, self->name); } attr = gpass_attribute_list_lookup(attributes, "description"); if (attr != NULL) { gpass_attribute_set(attr, self->description); } attr = gpass_attribute_list_lookup(attributes, "creation-time"); if (attr != NULL) { gpass_attribute_set(attr, self->creation_time); } attr = gpass_attribute_list_lookup(attributes, "modification-time"); if (attr != NULL) { gpass_attribute_set(attr, self->modification_time); } attr = gpass_attribute_list_lookup(attributes, "expiration"); if (attr != NULL) { gpass_attribute_set(attr, self->expiration); } attr = gpass_attribute_list_lookup(attributes, "expiration-time"); if (attr != NULL) { gpass_attribute_set(attr, self->expiration_time); } } static gboolean entry_instance_include(GPassEntry *self, const gchar *string) { if (strstr(self->name, string)) { return TRUE; } if (strstr(self->description, string)) { return TRUE; } return FALSE; } static gboolean entry_instance_equal(GPassEntry *self, GPassEntry *target) { if (gpass_strcmp(self->name, target->name) != 0) { return FALSE; } if (gpass_strcmp(self->description, target->description) != 0) { return FALSE; } if (gpass_strcmp(self->type, target->type) != 0) { return FALSE; } if (self->creation_time != target->creation_time) { return FALSE; } if (self->modification_time != target->modification_time) { return FALSE; } if (self->expiration != target->expiration) { return FALSE; } if (self->expiration && self->expiration_time != target->expiration_time) { return FALSE; } return TRUE; } static void entry_class_init(gpointer g_class, gpointer g_class_data) { GObjectClass *gobject_class = G_OBJECT_CLASS(g_class); GPassEntryClass *entry_class = GPASS_ENTRY_CLASS(g_class); parent_class = g_type_class_peek_parent(g_class); gobject_class->set_property = entry_set_property; gobject_class->get_property = entry_get_property; gobject_class->finalize = entry_instance_finalize; entry_class->nick = entry_class_nick; entry_class->icon_id = entry_class_icon_id; entry_class->default_launcher = entry_class_default_launcher; entry_class->can_have_child = entry_class_can_have_child; entry_class->attributes = entry_class_attributes; entry_class->set_attributes = entry_instance_set_attributes; entry_class->get_attributes = entry_instance_get_attributes; entry_class->include = entry_instance_include; entry_class->equal = entry_instance_equal; g_object_class_install_property (gobject_class, PROP_TYPE, g_param_spec_string("type", _("Type"), _("The entry type"), NULL, G_PARAM_READABLE)); g_object_class_install_property (gobject_class, PROP_NAME, g_param_spec_string("name", _("Name"), _("The name of entry"), NULL, G_PARAM_READWRITE)); g_object_class_install_property (gobject_class, PROP_DESCRIPTION, g_param_spec_string("description", _("Description"), _("Description"), NULL, G_PARAM_READWRITE)); g_object_class_install_property (gobject_class, PROP_CREATION_TIME, g_param_spec_ulong("creation-time", _("Creation Time"), _("The creation time of entry"), 0, G_MAXULONG, 0, G_PARAM_READWRITE)); g_object_class_install_property (gobject_class, PROP_MODIFICATION_TIME, g_param_spec_ulong("modification-time", _("Modification Time"), _("The modification time of entry"), 0, G_MAXULONG, 0, G_PARAM_READWRITE)); g_object_class_install_property (gobject_class, PROP_EXPIRATION, g_param_spec_boolean("expiration", _("Expiration"), _("Whether it expires it or not?"), FALSE, G_PARAM_READWRITE)); g_object_class_install_property (gobject_class, PROP_EXPIRATION_TIME, g_param_spec_ulong("expiration-time", _("Expiration Time"), _("The expiration time of entry"), 0, G_MAXULONG, 0, G_PARAM_READWRITE)); g_object_class_install_property (gobject_class, PROP_ID, g_param_spec_string("id", _("ID"), _("The ID of entry"), NULL, G_PARAM_READABLE)); } GType gpass_entry_get_type(void) { static GType type = 0; if (type == 0) { static const GTypeInfo info = { sizeof(GPassEntryClass), NULL, NULL, entry_class_init, NULL, NULL, sizeof(GPassEntry), 0, entry_instance_init }; type = g_type_register_static(G_TYPE_OBJECT, "GPassEntry", &info, G_TYPE_FLAG_ABSTRACT); } return type; } const gchar * gpass_entry_class_nick(GPassEntryClass *self_class) { return self_class->nick(); } const gchar * gpass_entry_class_icon_id(GPassEntryClass *self_class) { return self_class->icon_id(); } const gchar * gpass_entry_class_default_launcher(GPassEntryClass *self_class) { return self_class->default_launcher(); } gboolean gpass_entry_class_can_have_child(GPassEntryClass *self_class) { return self_class->can_have_child(); } GPassAttributeList * gpass_entry_class_attributes(GPassEntryClass *self_class) { GPassAttributeList *attributes = g_object_new(GPASS_TYPE_ATTRIBUTE_LIST, NULL); self_class->attributes(self_class, attributes); return attributes; } void gpass_entry_set_attributes(GPassEntry *self, GPassAttributeList *attributes) { GPASS_ENTRY_GET_CLASS(self)->set_attributes(self, attributes); } void gpass_entry_get_attributes(GPassEntry *self, GPassAttributeList *attributes) { GPASS_ENTRY_GET_CLASS(self)->get_attributes(self, attributes); } #define TERMINATOR '@' static gboolean get_terminated_string(GString **string, const gchar **ptr, const gchar *ptr_end) { while (*ptr <= ptr_end) { if (**ptr == '\\') { *string = g_string_append_c(*string, '\\'); (*ptr)++; if (*ptr > ptr_end) { break; } } else if (**ptr == TERMINATOR) { (*ptr)++; return TRUE; } *string = g_string_append_c(*string, **ptr); (*ptr)++; } return FALSE; } static void format_string(GPassAttributeList *attributes, const gchar *format, GString **result) { GString *name; const gchar *ptr, *ptr_end; GValue string_value = { 0 }; gboolean found; name = g_string_new(NULL); g_value_init(&string_value, G_TYPE_STRING); ptr = format; ptr_end = format + strlen(format); while (ptr <= ptr_end) { if (get_terminated_string(result, &ptr, ptr_end)) { name = g_string_truncate(name, 0); found = get_terminated_string(&name, &ptr, ptr_end); if (found) { GPassAttribute *attr = gpass_attribute_list_lookup(attributes, name->str); if (attr != NULL && g_value_transform(attr->value, &string_value)) { *result = g_string_append (*result, g_value_get_string(&string_value)); continue; } } *result = g_string_append_c(*result, TERMINATOR); *result = g_string_append(*result, name->str); if (found) { *result = g_string_append_c(*result, TERMINATOR); } } } g_value_unset(&string_value); g_string_free(name, TRUE); } void gpass_entry_format(GPassEntry *self, const gchar *format, GString **result) { GPassAttributeList *attributes; attributes = gpass_entry_class_attributes(GPASS_ENTRY_GET_CLASS(self)); gpass_entry_get_attributes(self, attributes); *result = g_string_truncate(*result, 0); format_string(attributes, format, result); g_object_unref(attributes); } gboolean gpass_entry_include(GPassEntry *self, const gchar *string) { return GPASS_ENTRY_GET_CLASS(self)->include(self, string); } gboolean gpass_entry_equal(GPassEntry *self, GPassEntry *target) { return GPASS_ENTRY_GET_CLASS(self)->equal(self, target); } GPassEntry * gpass_entry_prev_sibling(GPassEntry *self) { g_return_val_if_fail(self != NULL, NULL); if (self->node->prev == NULL) { return NULL; } return GPASS_ENTRY(self->node->prev->data); } GPassEntry * gpass_entry_next_sibling(GPassEntry *self) { g_return_val_if_fail(self != NULL, NULL); if (self->node->next == NULL) { return NULL; } return GPASS_ENTRY(self->node->next->data); } GPassEntry * gpass_entry_first_child(GPassEntry *self) { g_return_val_if_fail(self != NULL, NULL); if (self->node->children == NULL) { return NULL; } return GPASS_ENTRY(self->node->children->data); } GPassEntry * gpass_entry_parent(GPassEntry *self) { g_return_val_if_fail(self != NULL, NULL); if (self->node->parent == NULL) { return NULL; } return GPASS_ENTRY(self->node->parent->data); } GPassEntry * gpass_entry_root(GPassEntry *self) { GNode *parent; g_return_val_if_fail(self != NULL, NULL); parent = g_node_get_root(self->node); if (parent == NULL) { return NULL; } return GPASS_ENTRY(parent->data); } gboolean gpass_entry_has_child(GPassEntry *self) { return gpass_entry_first_child(self) != NULL; } GPassEntry * gpass_entry_insert_before(GPassEntry *parent, GPassEntry *sibling, GPassEntry *entry) { g_return_val_if_fail(entry != NULL, NULL); g_node_insert_before(parent ? parent->node : NULL, sibling ? sibling->node : NULL, entry->node); return entry; } GPassEntry * gpass_entry_insert_after(GPassEntry *parent, GPassEntry *sibling, GPassEntry *entry) { g_return_val_if_fail(entry != NULL, NULL); g_node_insert_after(parent ? parent->node : NULL, sibling ? sibling->node : NULL, entry->node); return entry; } GPassEntry * gpass_entry_unlink(GPassEntry *self) { g_return_val_if_fail(self != NULL, NULL); g_node_unlink(self->node); return self; }