/* Chrysalide - Outil d'analyse de fichiers binaires * item.c - gestion d'éléments destinés à une collection générique * * Copyright (C) 2014 Cyrille Bagard * * This file is part of Chrysalide. * * Chrysalide 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 3 of the License, or * (at your option) any later version. * * Chrysalide 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Foobar. If not, see . */ #include "item.h" #include #include #include #include #include "item-int.h" #include "../../common/io.h" #include "../../core/params.h" /* Initialise la classe des bases d'éléments pour collection. */ static void g_db_item_class_init(GDbItemClass *); /* Initialise une base d'élément pour collection générique. */ static void g_db_item_init(GDbItem *); /* Supprime toutes les références externes. */ static void g_db_item_dispose(GDbItem *); /* Procède à la libération totale de la mémoire. */ static void g_db_item_finalize(GDbItem *); /* Importe la définition d'une base d'éléments pour collection. */ static bool g_db_item_recv_from_fd(GDbItem *, int, int); /* Exporte la définition d'une base d'éléments pour collection. */ static bool g_db_item_send_to_fd(const GDbItem *, int, int); /* --------------------- MANIPULATIONS AVEC UNE BASE DE DONNEES --------------------- */ /* Constitue les champs destinés à une insertion / modification. */ static bool _g_db_item_prepare_db_statement(const GDbItem *, bound_value **, size_t *); /* Charge les valeurs utiles pour un élément de collection. */ static bool _g_db_item_load(GDbItem *, const bound_value *, size_t); /* Indique le type défini pour une base d'élément de collection générique. */ G_DEFINE_TYPE(GDbItem, g_db_item, G_TYPE_OBJECT); /****************************************************************************** * * * Paramètres : klass = classe à initialiser. * * * * Description : Initialise la classe des bases d'éléments pour collection. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void g_db_item_class_init(GDbItemClass *klass) { GObjectClass *object; /* Autre version de la classe */ object = G_OBJECT_CLASS(klass); object->dispose = (GObjectFinalizeFunc/* ! */)g_db_item_dispose; object->finalize = (GObjectFinalizeFunc)g_db_item_finalize; klass->cmp = (cmp_db_item_fc)g_db_item_cmp; klass->recv = (recv_db_item_fc)g_db_item_recv_from_fd; klass->send = (send_db_item_fc)g_db_item_send_to_fd; klass->prepare_stmt = (prepare_db_statement)_g_db_item_prepare_db_statement; klass->load = (load_db_item_fc)_g_db_item_load; } /****************************************************************************** * * * Paramètres : item = instance à initialiser. * * * * Description : Initialise une base d'élément pour collection générique. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void g_db_item_init(GDbItem *item) { const char *author; /* Identification à diffuser */ bool status; /* Bilan d'une obtention */ status = g_generic_config_get_value(get_main_configuration(), MPK_AUTHOR_NAME, &author); assert(status); set_rle_string(&item->author, author); item->is_volatile = false; } /****************************************************************************** * * * Paramètres : item = instance d'objet GLib à traiter. * * * * Description : Supprime toutes les références externes. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void g_db_item_dispose(GDbItem *item) { G_OBJECT_CLASS(g_db_item_parent_class)->dispose(G_OBJECT(item)); } /****************************************************************************** * * * Paramètres : item = instance d'objet GLib à traiter. * * * * Description : Procède à la libération totale de la mémoire. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void g_db_item_finalize(GDbItem *item) { exit_rle_string(&item->author); exit_rle_string(&item->tool); if (item->label != NULL) free(item->label); G_OBJECT_CLASS(g_db_item_parent_class)->finalize(G_OBJECT(item)); } /****************************************************************************** * * * Paramètres : item = élément de collection à consulter. * * * * Description : Indique la fonctionnalité représentée par l'élément. * * * * Retour : Identifiant valide pour le protocole. * * * * Remarques : - * * * ******************************************************************************/ DBFeatures g_db_item_get_feature(const GDbItem *item) { return G_DB_ITEM_GET_CLASS(item)->feature; } /****************************************************************************** * * * Paramètres : item = élément de collection à traiter. * * * * Description : Indique à l'élément qu'il se trouve du côté serveur. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ void g_db_item_set_server_side(GDbItem *item) { init_timestamp(&item->created); item->timestamp = item->created; } /****************************************************************************** * * * Paramètres : a = premier élément à analyser. * * b = second élément à analyser. * * with = précise les horodatages à prendre en compte. * * * * Description : Effectue la comparaison entre deux éléments de collection. * * * * Retour : Bilan de la comparaison : -1, 0 ou 1. * * * * Remarques : - * * * ******************************************************************************/ gint g_db_item_cmp(GDbItem *a, GDbItem *b, bool with) { gint result; /* Bilan à retourner */ if (with) result = cmp_timestamp(&a->timestamp, &b->timestamp); else result = 0; if (result == 0) result = cmp_timestamp(&a->created, &b->created); if (result == 0) result = strcmp(g_db_item_get_label(a), g_db_item_get_label(b)); return result; } /****************************************************************************** * * * Paramètres : a = premier élément à analyser. * * b = second élément à analyser. * * * * Description : Effectue la comparaison entre deux éléments de collection. * * * * Retour : Bilan de la comparaison : -1, 0 ou 1. * * * * Remarques : - * * * ******************************************************************************/ gint g_db_item_compare_with_timestamp(GDbItem *a, GDbItem *b) { return G_DB_ITEM_GET_CLASS(a)->cmp(a, b, true); } /****************************************************************************** * * * Paramètres : a = premier élément à analyser. * * b = second élément à analyser. * * * * Description : Effectue la comparaison entre deux éléments de collection. * * * * Retour : Bilan de la comparaison : -1, 0 ou 1. * * * * Remarques : - * * * ******************************************************************************/ gint g_db_item_compare_without_timestamp(GDbItem *a, GDbItem *b) { return G_DB_ITEM_GET_CLASS(a)->cmp(a, b, false); } /****************************************************************************** * * * Paramètres : item = base d'éléments à charger. [OUT] * * fd = flux ouvert en lecture pour l'importation. * * flags = éventuelles options d'envoi supplémentaires. * * * * Description : Importe la définition d'une base d'éléments pour collection. * * * * Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ static bool g_db_item_recv_from_fd(GDbItem *item, int fd, int flags) { bool status; /* Bilan d'une réception */ status = recv_timestamp(&item->created, fd, flags); if (!status) return false; status = recv_timestamp(&item->timestamp, fd, flags); if (!status) return false; status = recv_rle_string(&item->author, fd, flags); if (!status) return false; status = recv_rle_string(&item->tool, fd, flags); if (!status) return false; return true; } /****************************************************************************** * * * Paramètres : item = base d'éléments à charger. [OUT] * * fd = flux ouvert en lecture pour l'importation. * * flags = éventuelles options d'envoi supplémentaires. * * * * Description : Importe la définition d'une base d'éléments pour collection. * * * * Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ bool g_db_item_recv(GDbItem *item, int fd, int flags) { bool result; /* Bilan à retourner */ result = G_DB_ITEM_GET_CLASS(item)->recv(item, fd, flags); return result; } /****************************************************************************** * * * Paramètres : item = informations à sauvegarer. * * fd = flux ouvert en écriture pour l'exportation. * * flags = éventuelles options d'envoi supplémentaires. * * * * Description : Exporte la définition d'une base d'éléments pour collection. * * * * Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ static bool g_db_item_send_to_fd(const GDbItem *item, int fd, int flags) { bool status; /* Bilan d'une émission */ status = send_timestamp(&item->created, fd, MSG_MORE | flags); if (!status) return false; status = send_timestamp(&item->timestamp, fd, MSG_MORE | flags); if (!status) return false; status = send_rle_string(&item->author, fd, MSG_MORE | flags); if (!status) return false; status = send_rle_string(&item->tool, fd, flags); if (!status) return false; return true; } /****************************************************************************** * * * Paramètres : item = informations à sauvegarer. * * fd = flux ouvert en écriture pour l'exportation. * * flags = éventuelles options d'envoi supplémentaires. * * * * Description : Exporte la définition d'une base d'éléments pour collection. * * * * Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ bool g_db_item_send(const GDbItem *item, int fd, int flags) { return G_DB_ITEM_GET_CLASS(item)->send(item, fd, flags); } /****************************************************************************** * * * Paramètres : item = élément de collection à manipuler. * * binary = binaire chargé en mémoire à modifier. * * * * Description : Applique un élément de collection sur un binaire. * * * * Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ bool g_db_item_apply(GDbItem *item, GLoadedBinary *binary) { bool result; /* Bilan à faire remonter */ assert(g_db_item_is_active(item)); result = G_DB_ITEM_GET_CLASS(item)->apply(item, binary); return result; } /****************************************************************************** * * * Paramètres : item = élément de collection à manipuler. * * binary = binaire chargé en mémoire à modifier. * * * * Description : Annule une bascule d'affichage d'opérande sur un binaire. * * * * Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ bool g_db_item_cancel(GDbItem *item, GLoadedBinary *binary) { bool result; /* Bilan à faire remonter */ assert(!g_db_item_is_active(item)); result = G_DB_ITEM_GET_CLASS(item)->cancel(item, binary); return result; } /****************************************************************************** * * * Paramètres : item = élément de collection à consulter. * * * * Description : Décrit l'élément de collection en place. * * * * Retour : Chaîne de caractère correspondante. * * * * Remarques : - * * * ******************************************************************************/ const char *g_db_item_get_label(GDbItem *item) { if (item->label == NULL) { G_DB_ITEM_GET_CLASS(item)->build_label(item); assert(item->label != NULL); } return item->label; } /****************************************************************************** * * * Paramètres : item = élément de collection à consulter. * * * * Description : Fournit l'horodatage associé à l'élément de collection. * * * * Retour : Date d'activité de l'élément. * * * * Remarques : - * * * ******************************************************************************/ timestamp_t g_db_item_get_timestamp(const GDbItem *item) { return item->timestamp; } /****************************************************************************** * * * Paramètres : item = élément de collection à mettre à jour. * * binary = binaire chargé en mémoire à modifier. * * first = horodatage du premier élément désactivé ou NULL. * * * * Description : Active ou désactive un élément de collection en place. * * * * Retour : Bilan de la mise à jour de l'élément. * * * * Remarques : - * * * ******************************************************************************/ bool g_db_item_set_activity(GDbItem *item, GLoadedBinary *binary, timestamp_t *first) { bool result; /* Bilan à faire remonter */ bool active; /* Etat avant changement */ active = g_db_item_is_active(item); /* Archivage de l'état */ if (first == NULL) { assert(!active); item->timestamp = item->created; } else { assert(active); item->timestamp = --(*first); } /* Application de l'état */ if (binary != NULL) { if (active) result = g_db_item_cancel(item, binary); else result = g_db_item_apply(item, binary); } else result = true; return result; } /****************************************************************************** * * * Paramètres : item = élément de collection à consulter. * * * * Description : Indique si l'élément est activé ou désactivé. * * * * Retour : Etat de l'activité de l'élément. * * * * Remarques : - * * * ******************************************************************************/ bool g_db_item_is_active(const GDbItem *item) { return (cmp_timestamp(&item->created, &item->timestamp) == 0); } /****************************************************************************** * * * Paramètres : item = base d'éléments à modifier. * * is_volatile = état du besoin en sauvegarde. * * * * Description : Définit si l'élément contient des données à oublier ou non. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ void g_db_item_set_volatile(GDbItem *item, bool is_volatile) { item->is_volatile = is_volatile; } /****************************************************************************** * * * Paramètres : item = base d'éléments à consulter. * * * * Description : Indique si l'élément contient des données à oublier ou non. * * * * Retour : Etat du besoin en sauvegarde. * * * * Remarques : - * * * ******************************************************************************/ bool g_db_item_is_volatile(const GDbItem *item) { return item->is_volatile; } /* ---------------------------------------------------------------------------------- */ /* MANIPULATIONS AVEC UNE BASE DE DONNEES */ /* ---------------------------------------------------------------------------------- */ /****************************************************************************** * * * Paramètres : item = base d'éléments sur laquelle s'appuyer. * * values = couples de champs et de valeurs à lier. [OUT] * * count = nombre de ces couples. [OUT] * * * * Description : Constitue les champs destinés à une insertion / modification.* * * * Retour : Bilan de l'opération : succès ou non. * * * * Remarques : - * * * ******************************************************************************/ static bool _g_db_item_prepare_db_statement(const GDbItem *item, bound_value **values, size_t *count) { bool result; /* Bilan à retourner */ result = true; result &= prepare_db_statement_for_timestamp(&item->created, "created", values, count); result &= prepare_db_statement_for_timestamp(&item->timestamp, "timestamp", values, count); result &= prepare_db_statement_for_rle_string(&item->author, "author", values, count); result &= prepare_db_statement_for_rle_string(&item->tool, "tool", values, count); return result; } /****************************************************************************** * * * Paramètres : item = base d'éléments sur laquelle s'appuyer. * * values = couples de champs et de valeurs à lier. [OUT] * * count = nombre de ces couples. [OUT] * * * * Description : Constitue les champs destinés à une insertion / modification.* * * * Retour : Bilan de l'opération : succès ou non. * * * * Remarques : - * * * ******************************************************************************/ bool g_db_item_prepare_db_statement(const GDbItem *item, bound_value **values, size_t *count) { *values = NULL; *count = 0; return G_DB_ITEM_GET_CLASS(item)->prepare_stmt(item, values, count); } /****************************************************************************** * * * Paramètres : item = base d'éléments à charger depuis les réponses. * * values = tableau d'éléments à consulter. * * count = nombre de descriptions renseignées. * * * * Description : Charge les valeurs utiles pour un élément de collection. * * * * Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ static bool _g_db_item_load(GDbItem *item, const bound_value *values, size_t count) { bool result; /* Bilan global à retourner */ result = true; result &= load_timestamp(&item->created, "created", values, count); result &= load_timestamp(&item->timestamp, "timestamp", values, count); result &= load_rle_string(&item->author, "author", values, count); result &= load_rle_string(&item->tool, "tool", values, count); return result; } /****************************************************************************** * * * Paramètres : item = base d'éléments à charger depuis les réponses. * * values = tableau d'éléments à consulter. * * count = nombre de descriptions renseignées. * * * * Description : Charge les valeurs utiles pour un élément de collection. * * * * Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ bool g_db_item_load(GDbItem *item, const bound_value *values, size_t count) { bool result; /* Bilan à retourner */ result = G_DB_ITEM_GET_CLASS(item)->load(item, values, count); return result; }