labfy-investigation/src/models/person_evidence_selection.c

300 lines
12 KiB
C

#include "models/person_evidence_selection.h"
struct PersonEvidenceSelectionItem {
char *identifier;
PersonEvidenceOrigin origin;
PersonEvidenceState state;
EvidenceRecord *record;
char *evidence_identifier;
char *source_path;
char *staging_path;
char *original_name;
char *mime_type;
char *type_identifier;
char *sha256;
char *description;
char *prepared_at;
guint64 size_bytes;
};
struct PersonEvidenceSelection {
GPtrArray *items;
char *active_identifier;
};
static GQuark selection_error(void)
{
return g_quark_from_static_string("person-evidence-selection-error");
}
static void item_free(gpointer data)
{
PersonEvidenceSelectionItem *item = data;
if (item == NULL) return;
g_free(item->identifier);
evidence_record_free(item->record);
g_free(item->evidence_identifier);
g_free(item->source_path);
g_free(item->staging_path);
g_free(item->original_name);
g_free(item->mime_type);
g_free(item->type_identifier);
g_free(item->sha256);
g_free(item->description);
g_free(item->prepared_at);
g_free(item);
}
static PersonEvidenceSelectionItem *find_item(
const PersonEvidenceSelection *selection, const char *identifier)
{
for (guint i = 0; selection != NULL && identifier != NULL &&
i < selection->items->len; i++) {
PersonEvidenceSelectionItem *item =
g_ptr_array_index(selection->items, i);
if (g_strcmp0(item->identifier, identifier) == 0) return item;
}
return NULL;
}
static gboolean duplicate(const PersonEvidenceSelection *selection,
const char *evidence_identifier, const char *source_path,
const char *sha256)
{
for (guint i = 0; selection != NULL && i < selection->items->len; i++) {
PersonEvidenceSelectionItem *item =
g_ptr_array_index(selection->items, i);
if ((evidence_identifier != NULL &&
g_strcmp0(item->evidence_identifier, evidence_identifier) == 0) ||
(source_path != NULL &&
g_strcmp0(item->source_path, source_path) == 0) ||
(sha256 != NULL && g_strcmp0(item->sha256, sha256) == 0))
return TRUE;
}
return FALSE;
}
PersonEvidenceSelection *person_evidence_selection_new(void)
{
PersonEvidenceSelection *selection =
g_new0(PersonEvidenceSelection, 1);
selection->items = g_ptr_array_new_with_free_func(item_free);
return selection;
}
PersonEvidenceSelection *person_evidence_selection_copy(
const PersonEvidenceSelection *source)
{
PersonEvidenceSelection *copy = person_evidence_selection_new();
for (guint i = 0; source != NULL && i < source->items->len; i++) {
PersonEvidenceSelectionItem *item =
g_ptr_array_index(source->items, i);
if (item->origin == PERSON_EVIDENCE_ORIGIN_EXISTING) {
if (person_evidence_selection_add_existing(
copy, item->record, NULL))
person_evidence_selection_set_type(copy, item->identifier,
item->type_identifier);
} else {
person_evidence_selection_add_staged(copy, item->source_path,
item->staging_path, item->original_name, item->mime_type,
item->type_identifier, item->size_bytes, item->sha256,
item->description, item->prepared_at, NULL);
PersonEvidenceSelectionItem *copied_item =
g_ptr_array_index(copy->items, copy->items->len - 1);
g_free(copied_item->identifier);
copied_item->identifier = g_strdup(item->identifier);
}
}
if (source != NULL && source->active_identifier != NULL) {
PersonEvidenceSelectionItem *active =
find_item(source, source->active_identifier);
for (guint i = 0; active != NULL && i < copy->items->len; i++) {
PersonEvidenceSelectionItem *candidate =
g_ptr_array_index(copy->items, i);
if (g_strcmp0(candidate->evidence_identifier,
active->evidence_identifier) == 0 ||
(candidate->source_path != NULL &&
g_strcmp0(candidate->source_path, active->source_path) == 0))
person_evidence_selection_set_active(
copy, candidate->identifier);
}
}
return copy;
}
void person_evidence_selection_free(PersonEvidenceSelection *selection)
{
if (selection == NULL) return;
g_ptr_array_unref(selection->items);
g_free(selection->active_identifier);
g_free(selection);
}
guint person_evidence_selection_get_count(
const PersonEvidenceSelection *selection)
{
return selection != NULL ? selection->items->len : 0;
}
const PersonEvidenceSelectionItem *person_evidence_selection_get(
const PersonEvidenceSelection *selection, guint index)
{
return selection != NULL && index < selection->items->len
? g_ptr_array_index(selection->items, index) : NULL;
}
const PersonEvidenceSelectionItem *person_evidence_selection_get_active(
const PersonEvidenceSelection *selection)
{
return find_item(selection,
selection != NULL ? selection->active_identifier : NULL);
}
gboolean person_evidence_selection_set_active(
PersonEvidenceSelection *selection, const char *item_identifier)
{
if (selection == NULL ||
(item_identifier != NULL &&
find_item(selection, item_identifier) == NULL)) return FALSE;
g_free(selection->active_identifier);
selection->active_identifier = g_strdup(item_identifier);
return TRUE;
}
gboolean person_evidence_selection_add_existing(
PersonEvidenceSelection *selection, const EvidenceRecord *record,
GError **error)
{
PersonEvidenceSelectionItem *item;
const char *identifier;
if (selection == NULL || record == NULL ||
(identifier = evidence_record_get_identifier(record)) == NULL) {
g_set_error_literal(error, selection_error(), 1,
"La preuve existante est invalide.");
return FALSE;
}
if (duplicate(selection, identifier, NULL,
evidence_record_get_sha256(record))) {
g_set_error_literal(error, selection_error(), 2,
"Cette preuve est déjà dans la sélection.");
return FALSE;
}
item = g_new0(PersonEvidenceSelectionItem, 1);
item->identifier = g_strdup(identifier);
item->origin = PERSON_EVIDENCE_ORIGIN_EXISTING;
item->state = PERSON_EVIDENCE_STATE_READY;
item->record = evidence_record_copy(record);
item->evidence_identifier = g_strdup(identifier);
item->original_name = g_strdup(evidence_record_get_original_name(record));
item->mime_type = g_strdup(evidence_record_get_mime_type(record));
item->type_identifier =
g_strdup(evidence_record_get_type_identifier(record));
item->sha256 = g_strdup(evidence_record_get_sha256(record));
item->description = g_strdup(evidence_record_get_description(record));
item->size_bytes = evidence_record_get_size_bytes(record);
g_ptr_array_add(selection->items, item);
if (selection->active_identifier == NULL)
selection->active_identifier = g_strdup(item->identifier);
return TRUE;
}
gboolean person_evidence_selection_add_staged(
PersonEvidenceSelection *selection, const char *source_path,
const char *staging_path, const char *original_name,
const char *mime_type, const char *type_identifier, guint64 size_bytes,
const char *sha256, const char *description, const char *prepared_at,
GError **error)
{
PersonEvidenceSelectionItem *item;
if (selection == NULL || source_path == NULL || staging_path == NULL ||
original_name == NULL || mime_type == NULL || type_identifier == NULL ||
sha256 == NULL || prepared_at == NULL) {
g_set_error_literal(error, selection_error(), 1,
"Le fichier préparé est invalide.");
return FALSE;
}
if (duplicate(selection, NULL, source_path, sha256)) {
g_set_error_literal(error, selection_error(), 2,
"Ce contenu est déjà dans la sélection.");
return FALSE;
}
item = g_new0(PersonEvidenceSelectionItem, 1);
item->identifier = g_uuid_string_random();
item->origin = PERSON_EVIDENCE_ORIGIN_STAGED;
item->state = PERSON_EVIDENCE_STATE_READY;
item->source_path = g_strdup(source_path);
item->staging_path = g_strdup(staging_path);
item->original_name = g_strdup(original_name);
item->mime_type = g_strdup(mime_type);
item->type_identifier = g_strdup(type_identifier);
item->sha256 = g_strdup(sha256);
item->description = g_strdup(description);
item->prepared_at = g_strdup(prepared_at);
item->size_bytes = size_bytes;
g_ptr_array_add(selection->items, item);
if (selection->active_identifier == NULL)
selection->active_identifier = g_strdup(item->identifier);
return TRUE;
}
gboolean person_evidence_selection_remove(PersonEvidenceSelection *selection,
const char *item_identifier)
{
for (guint i = 0; selection != NULL && item_identifier != NULL &&
i < selection->items->len; i++) {
PersonEvidenceSelectionItem *item =
g_ptr_array_index(selection->items, i);
if (g_strcmp0(item->identifier, item_identifier) == 0) {
gboolean active = g_strcmp0(selection->active_identifier,
item_identifier) == 0;
g_ptr_array_remove_index(selection->items, i);
if (active) {
g_clear_pointer(&selection->active_identifier, g_free);
if (selection->items->len > 0)
selection->active_identifier = g_strdup(
((PersonEvidenceSelectionItem *) g_ptr_array_index(
selection->items, MIN(i,
selection->items->len - 1)))->identifier);
}
return TRUE;
}
}
return FALSE;
}
gboolean person_evidence_selection_set_type(PersonEvidenceSelection *selection,
const char *item_identifier, const char *type_identifier)
{
PersonEvidenceSelectionItem *item = find_item(selection, item_identifier);
if (item == NULL || type_identifier == NULL ||
type_identifier[0] == '\0') return FALSE;
g_free(item->type_identifier);
item->type_identifier = g_strdup(type_identifier);
return TRUE;
}
gboolean person_evidence_selection_is_confirmable(
const PersonEvidenceSelection *selection)
{
for (guint i = 0; selection != NULL && i < selection->items->len; i++)
if (((PersonEvidenceSelectionItem *) g_ptr_array_index(
selection->items, i))->state != PERSON_EVIDENCE_STATE_READY)
return FALSE;
return selection != NULL;
}
const char *person_evidence_selection_find_existing_by_sha256(
const PersonEvidenceSelection *selection, const char *sha256)
{
for (guint i = 0; selection != NULL && sha256 != NULL &&
i < selection->items->len; i++) {
PersonEvidenceSelectionItem *item =
g_ptr_array_index(selection->items, i);
if (item->origin == PERSON_EVIDENCE_ORIGIN_EXISTING &&
g_strcmp0(item->sha256, sha256) == 0)
return item->evidence_identifier;
}
return NULL;
}
#define ITEM_GETTER(name, type, field) \
type person_evidence_selection_item_get_##name( \
const PersonEvidenceSelectionItem *item) { \
return item != NULL ? item->field : (type) 0; \
}
ITEM_GETTER(identifier, const char *, identifier)
ITEM_GETTER(origin, PersonEvidenceOrigin, origin)
ITEM_GETTER(state, PersonEvidenceState, state)
ITEM_GETTER(record, const EvidenceRecord *, record)
ITEM_GETTER(evidence_identifier, const char *, evidence_identifier)
ITEM_GETTER(source_path, const char *, source_path)
ITEM_GETTER(staging_path, const char *, staging_path)
ITEM_GETTER(original_name, const char *, original_name)
ITEM_GETTER(mime_type, const char *, mime_type)
ITEM_GETTER(type_identifier, const char *, type_identifier)
ITEM_GETTER(sha256, const char *, sha256)
ITEM_GETTER(description, const char *, description)
ITEM_GETTER(prepared_at, const char *, prepared_at)
ITEM_GETTER(size_bytes, guint64, size_bytes)