feat: display evidence details and organize imports
This commit is contained in:
parent
5d87b35242
commit
a4765e8de2
5 changed files with 1115 additions and 53 deletions
|
|
@ -11,6 +11,7 @@
|
|||
#include "core/investigation_node.h"
|
||||
#include "core/task_manager.h"
|
||||
#include "widgets/evidence_category_model.h"
|
||||
#include "models/evidence_record.h"
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
|
|
@ -187,6 +188,19 @@ void main_window_set_selected_node(
|
|||
const InvestigationNode *node
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Affiche la fiche de la preuve sélectionnée.
|
||||
*
|
||||
* MainWindow ne conserve pas le EvidenceRecord.
|
||||
*
|
||||
* @param main_window Fenêtre principale.
|
||||
* @param evidence_record Preuve sélectionnée, ou NULL.
|
||||
*/
|
||||
void main_window_set_selected_evidence(
|
||||
MainWindow *main_window,
|
||||
const EvidenceRecord *evidence_record
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Met à jour le texte de la barre d'état.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
|
||||
#include "core/investigation_node.h"
|
||||
#include "models/evidence_record.h"
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
|
|
@ -56,6 +57,22 @@ void workspace_set_selected_node(
|
|||
const InvestigationNode *node
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Affiche la fiche détaillée d'une preuve.
|
||||
*
|
||||
* Les valeurs sont immédiatement copiées par les widgets GTK.
|
||||
* Le Workspace ne conserve pas le pointeur EvidenceRecord.
|
||||
*
|
||||
* Passer NULL restaure la page d'accueil.
|
||||
*
|
||||
* @param workspace Zone de travail à mettre à jour.
|
||||
* @param evidence_record Preuve sélectionnée, ou NULL.
|
||||
*/
|
||||
void workspace_set_selected_evidence(
|
||||
Workspace *workspace,
|
||||
const EvidenceRecord *evidence_record
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Libère la structure d'encapsulation de la zone de travail.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -36,12 +36,6 @@
|
|||
*/
|
||||
#define APPLICATION_ID "com.labfytools.investigation"
|
||||
|
||||
/**
|
||||
* @brief Dossier physique recevant les documents importés.
|
||||
*/
|
||||
#define APPLICATION_EVIDENCE_DIRECTORY \
|
||||
"01_Preuves_Originales/Documents"
|
||||
|
||||
/**
|
||||
* @brief Erreurs produites lors du chargement d'une enquête.
|
||||
*/
|
||||
|
|
@ -60,6 +54,12 @@ typedef enum
|
|||
#define APPLICATION_OPEN_ERROR \
|
||||
application_open_error_quark()
|
||||
|
||||
/**
|
||||
* @brief Dossier racine contenant les preuves originales.
|
||||
*/
|
||||
#define APPLICATION_EVIDENCE_ROOT_DIRECTORY \
|
||||
"01_Preuves_Originales"
|
||||
|
||||
/**
|
||||
* @brief Retourne le domaine d'erreur du chargement d'une enquête.
|
||||
*
|
||||
|
|
@ -1511,6 +1511,15 @@ static void application_on_evidence_import_completed(
|
|||
|
||||
GError *error = NULL;
|
||||
|
||||
GError *evidence_refresh_error =
|
||||
NULL;
|
||||
|
||||
gboolean tree_refreshed =
|
||||
FALSE;
|
||||
|
||||
gboolean evidence_refreshed =
|
||||
FALSE;
|
||||
|
||||
if (task == NULL ||
|
||||
context == NULL)
|
||||
{
|
||||
|
|
@ -1560,56 +1569,117 @@ static void application_on_evidence_import_completed(
|
|||
evidence_record
|
||||
);
|
||||
|
||||
/*
|
||||
* L'utilisateur peut avoir changé d'enquête pendant
|
||||
* l'exécution asynchrone de l'import.
|
||||
*
|
||||
* Dans ce cas, la preuve reste correctement importée dans
|
||||
* l'ancienne enquête, mais l'interface actuelle ne doit pas
|
||||
* être rafraîchie avec ses données.
|
||||
*/
|
||||
if (application_session_matches_root(
|
||||
application,
|
||||
context->investigation_root_path
|
||||
))
|
||||
{
|
||||
if (application_refresh_investigation_tree(
|
||||
tree_refreshed =
|
||||
application_refresh_investigation_tree(
|
||||
application,
|
||||
context->investigation_root_path
|
||||
))
|
||||
);
|
||||
|
||||
evidence_refreshed =
|
||||
application_refresh_evidence_models(
|
||||
application,
|
||||
&evidence_refresh_error
|
||||
);
|
||||
|
||||
if (!tree_refreshed)
|
||||
{
|
||||
g_warning(
|
||||
"La preuve a été importée, mais l'arborescence de '%s' "
|
||||
"n'a pas pu être reconstruite.",
|
||||
context->investigation_root_path
|
||||
);
|
||||
}
|
||||
|
||||
if (!evidence_refreshed)
|
||||
{
|
||||
g_warning(
|
||||
"La preuve a été importée, mais la liste des preuves "
|
||||
"n'a pas pu être actualisée : %s",
|
||||
evidence_refresh_error != NULL
|
||||
? evidence_refresh_error->message
|
||||
: "erreur inconnue"
|
||||
);
|
||||
}
|
||||
|
||||
if (tree_refreshed &&
|
||||
evidence_refreshed)
|
||||
{
|
||||
status_message =
|
||||
g_strdup_printf(
|
||||
"Preuve importée : %s",
|
||||
original_name != NULL
|
||||
original_name != NULL &&
|
||||
original_name[0] != '\0'
|
||||
? original_name
|
||||
: "(nom indisponible)"
|
||||
);
|
||||
}
|
||||
else if (!tree_refreshed &&
|
||||
evidence_refreshed)
|
||||
{
|
||||
status_message =
|
||||
g_strdup_printf(
|
||||
"Preuve importée : %s — "
|
||||
"arborescence non actualisée",
|
||||
original_name != NULL &&
|
||||
original_name[0] != '\0'
|
||||
? original_name
|
||||
: "(nom indisponible)"
|
||||
);
|
||||
}
|
||||
else if (tree_refreshed &&
|
||||
!evidence_refreshed)
|
||||
{
|
||||
status_message =
|
||||
g_strdup_printf(
|
||||
"Preuve importée : %s — "
|
||||
"liste des preuves non actualisée",
|
||||
original_name != NULL &&
|
||||
original_name[0] != '\0'
|
||||
? original_name
|
||||
: "(nom indisponible)"
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* L’import reste valide même si le rafraîchissement visuel
|
||||
* échoue. Le fichier et la ligne SQLite ne doivent surtout
|
||||
* pas être présentés comme un échec.
|
||||
*/
|
||||
status_message =
|
||||
g_strdup_printf(
|
||||
"Preuve importée : %s — "
|
||||
"arborescence non actualisée",
|
||||
original_name != NULL
|
||||
"interface non actualisée",
|
||||
original_name != NULL &&
|
||||
original_name[0] != '\0'
|
||||
? original_name
|
||||
: "(nom indisponible)"
|
||||
);
|
||||
|
||||
g_warning(
|
||||
"La preuve a été importée, mais l’arborescence de '%s' "
|
||||
"n’a pas pu être reconstruite.",
|
||||
context->investigation_root_path
|
||||
);
|
||||
}
|
||||
|
||||
main_window_set_status(
|
||||
application->main_window,
|
||||
status_message
|
||||
);
|
||||
|
||||
g_clear_error(
|
||||
&evidence_refresh_error
|
||||
);
|
||||
}
|
||||
|
||||
g_message(
|
||||
"Preuve importée dans '%s' : %s",
|
||||
context->investigation_root_path,
|
||||
original_name != NULL
|
||||
original_name != NULL &&
|
||||
original_name[0] != '\0'
|
||||
? original_name
|
||||
: "(nom indisponible)"
|
||||
);
|
||||
|
|
@ -1663,6 +1733,77 @@ static void application_on_evidence_import_completed(
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Retourne le dossier de stockage associé à un type de preuve.
|
||||
*
|
||||
* La chaîne retournée est statique et ne doit pas être libérée.
|
||||
*/
|
||||
static const char *application_get_evidence_subdirectory(
|
||||
const char *type_identifier
|
||||
)
|
||||
{
|
||||
if (g_strcmp0(
|
||||
type_identifier,
|
||||
"screenshot"
|
||||
) == 0)
|
||||
{
|
||||
return "Captures_Ecran";
|
||||
}
|
||||
|
||||
if (g_strcmp0(
|
||||
type_identifier,
|
||||
"photo"
|
||||
) == 0)
|
||||
{
|
||||
return "Photos";
|
||||
}
|
||||
|
||||
if (g_strcmp0(
|
||||
type_identifier,
|
||||
"video"
|
||||
) == 0)
|
||||
{
|
||||
return "Videos";
|
||||
}
|
||||
|
||||
if (g_strcmp0(
|
||||
type_identifier,
|
||||
"email"
|
||||
) == 0)
|
||||
{
|
||||
return "Emails";
|
||||
}
|
||||
|
||||
if (g_strcmp0(
|
||||
type_identifier,
|
||||
"audio"
|
||||
) == 0)
|
||||
{
|
||||
return "Audios";
|
||||
}
|
||||
|
||||
if (g_strcmp0(
|
||||
type_identifier,
|
||||
"archive"
|
||||
) == 0)
|
||||
{
|
||||
return "Archives";
|
||||
}
|
||||
|
||||
if (g_strcmp0(
|
||||
type_identifier,
|
||||
"conversation"
|
||||
) == 0)
|
||||
{
|
||||
return "Conversations";
|
||||
}
|
||||
|
||||
/*
|
||||
* Documents, textes, autres types et types inconnus.
|
||||
*/
|
||||
return "Documents";
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Prépare et démarre l’import asynchrone d’un fichier.
|
||||
*/
|
||||
|
|
@ -1680,6 +1821,10 @@ static void application_start_evidence_import(
|
|||
const char *root_path = NULL;
|
||||
const char *database_path = NULL;
|
||||
|
||||
const char *evidence_subdirectory = NULL;
|
||||
|
||||
char *relative_directory = NULL;
|
||||
|
||||
EvidenceImportTaskRequest request =
|
||||
{0};
|
||||
|
||||
|
|
@ -1748,11 +1893,33 @@ static void application_start_evidence_import(
|
|||
return;
|
||||
}
|
||||
|
||||
evidence_subdirectory =
|
||||
application_get_evidence_subdirectory(
|
||||
type_identifier
|
||||
);
|
||||
|
||||
relative_directory =
|
||||
g_build_filename(
|
||||
APPLICATION_EVIDENCE_ROOT_DIRECTORY,
|
||||
evidence_subdirectory,
|
||||
NULL
|
||||
);
|
||||
|
||||
if (relative_directory == NULL)
|
||||
{
|
||||
application_present_error(
|
||||
application,
|
||||
"Import impossible",
|
||||
"Impossible de construire le chemin relatif de la preuve."
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
destination_directory =
|
||||
g_build_filename(
|
||||
root_path,
|
||||
"01_Preuves_Originales",
|
||||
"Documents",
|
||||
relative_directory,
|
||||
NULL
|
||||
);
|
||||
|
||||
|
|
@ -1764,6 +1931,10 @@ static void application_start_evidence_import(
|
|||
"Impossible de construire le dossier de destination."
|
||||
);
|
||||
|
||||
g_free(
|
||||
relative_directory
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -1859,7 +2030,7 @@ static void application_start_evidence_import(
|
|||
destination_directory;
|
||||
|
||||
request.relative_directory =
|
||||
APPLICATION_EVIDENCE_DIRECTORY;
|
||||
relative_directory;
|
||||
|
||||
request.type_identifier =
|
||||
type_identifier;
|
||||
|
|
@ -1908,6 +2079,10 @@ static void application_start_evidence_import(
|
|||
destination_directory
|
||||
);
|
||||
|
||||
g_free(
|
||||
relative_directory
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -1952,6 +2127,10 @@ static void application_start_evidence_import(
|
|||
g_free(
|
||||
destination_directory
|
||||
);
|
||||
|
||||
g_free(
|
||||
relative_directory
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -2368,6 +2547,224 @@ static void application_on_tree_node_selected(
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Traite la sélection d'une preuve dans la Sidebar.
|
||||
*
|
||||
* L'identifiant est emprunté uniquement pendant cet appel.
|
||||
* La preuve complète est relue depuis SQLite avant d'être transmise
|
||||
* au Workspace.
|
||||
*
|
||||
* @param evidence_identifier UUID de la preuve, ou NULL.
|
||||
* @param user_data Pointeur vers Application.
|
||||
*/
|
||||
static void application_on_evidence_selected(
|
||||
const char *evidence_identifier,
|
||||
gpointer user_data
|
||||
)
|
||||
{
|
||||
Application *application =
|
||||
user_data;
|
||||
|
||||
Database *database =
|
||||
NULL;
|
||||
|
||||
EvidenceDao *evidence_dao =
|
||||
NULL;
|
||||
|
||||
EvidenceRecord *evidence_record =
|
||||
NULL;
|
||||
|
||||
const char *original_name =
|
||||
NULL;
|
||||
|
||||
char *status_message =
|
||||
NULL;
|
||||
|
||||
GError *error =
|
||||
NULL;
|
||||
|
||||
if (application == NULL ||
|
||||
application->main_window == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Une catégorie ou une sélection vide transmet NULL.
|
||||
*/
|
||||
if (evidence_identifier == NULL ||
|
||||
evidence_identifier[0] == '\0')
|
||||
{
|
||||
main_window_set_selected_evidence(
|
||||
application->main_window,
|
||||
NULL
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (application->session == NULL)
|
||||
{
|
||||
main_window_set_selected_evidence(
|
||||
application->main_window,
|
||||
NULL
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
database =
|
||||
investigation_session_get_database(
|
||||
application->session
|
||||
);
|
||||
|
||||
if (database == NULL)
|
||||
{
|
||||
main_window_set_selected_evidence(
|
||||
application->main_window,
|
||||
NULL
|
||||
);
|
||||
|
||||
application_present_error(
|
||||
application,
|
||||
"Preuve indisponible",
|
||||
"La session ne fournit aucune connexion SQLite."
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
evidence_dao =
|
||||
evidence_dao_new(
|
||||
database,
|
||||
&error
|
||||
);
|
||||
|
||||
if (evidence_dao == NULL)
|
||||
{
|
||||
g_warning(
|
||||
"Impossible de créer le DAO des preuves : %s",
|
||||
error != NULL
|
||||
? error->message
|
||||
: "erreur inconnue"
|
||||
);
|
||||
|
||||
main_window_set_selected_evidence(
|
||||
application->main_window,
|
||||
NULL
|
||||
);
|
||||
|
||||
application_present_error(
|
||||
application,
|
||||
"Preuve indisponible",
|
||||
error != NULL
|
||||
? error->message
|
||||
: "Impossible d'accéder aux preuves enregistrées."
|
||||
);
|
||||
|
||||
g_clear_error(
|
||||
&error
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
evidence_record =
|
||||
evidence_dao_find_by_identifier(
|
||||
evidence_dao,
|
||||
evidence_identifier,
|
||||
&error
|
||||
);
|
||||
|
||||
evidence_dao_free(
|
||||
evidence_dao
|
||||
);
|
||||
|
||||
if (error != NULL)
|
||||
{
|
||||
g_warning(
|
||||
"Impossible de charger la preuve '%s' : %s",
|
||||
evidence_identifier,
|
||||
error->message
|
||||
);
|
||||
|
||||
main_window_set_selected_evidence(
|
||||
application->main_window,
|
||||
NULL
|
||||
);
|
||||
|
||||
application_present_error(
|
||||
application,
|
||||
"Preuve indisponible",
|
||||
error->message
|
||||
);
|
||||
|
||||
g_clear_error(
|
||||
&error
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Une preuve absente retourne NULL sans erreur.
|
||||
*/
|
||||
if (evidence_record == NULL)
|
||||
{
|
||||
g_warning(
|
||||
"La preuve '%s' n'existe plus dans la base.",
|
||||
evidence_identifier
|
||||
);
|
||||
|
||||
main_window_set_selected_evidence(
|
||||
application->main_window,
|
||||
NULL
|
||||
);
|
||||
|
||||
main_window_set_status(
|
||||
application->main_window,
|
||||
"La preuve sélectionnée est introuvable."
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Workspace copie immédiatement les valeurs dans ses widgets GTK.
|
||||
*/
|
||||
main_window_set_selected_evidence(
|
||||
application->main_window,
|
||||
evidence_record
|
||||
);
|
||||
|
||||
original_name =
|
||||
evidence_record_get_original_name(
|
||||
evidence_record
|
||||
);
|
||||
|
||||
status_message =
|
||||
g_strdup_printf(
|
||||
"Preuve sélectionnée : %s",
|
||||
original_name != NULL &&
|
||||
original_name[0] != '\0'
|
||||
? original_name
|
||||
: "(sans nom)"
|
||||
);
|
||||
|
||||
main_window_set_status(
|
||||
application->main_window,
|
||||
status_message
|
||||
);
|
||||
|
||||
g_free(
|
||||
status_message
|
||||
);
|
||||
|
||||
evidence_record_free(
|
||||
evidence_record
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Ferme proprement l'application.
|
||||
*
|
||||
|
|
@ -2446,6 +2843,12 @@ static void application_on_activate(
|
|||
application
|
||||
);
|
||||
|
||||
main_window_set_evidence_selection_callback(
|
||||
application->main_window,
|
||||
application_on_evidence_selected,
|
||||
application
|
||||
);
|
||||
|
||||
main_window_set_new_investigation_callback(
|
||||
application->main_window,
|
||||
application_on_new_investigation_requested,
|
||||
|
|
|
|||
|
|
@ -368,11 +368,6 @@ MainWindow *main_window_new(
|
|||
FALSE
|
||||
);
|
||||
|
||||
main_window->quit_button =
|
||||
gtk_button_new_with_label(
|
||||
"Quitter"
|
||||
);
|
||||
|
||||
gtk_box_append(
|
||||
GTK_BOX(main_window->action_bar),
|
||||
main_window->new_investigation_button
|
||||
|
|
@ -978,6 +973,22 @@ void main_window_set_selected_node(
|
|||
);
|
||||
}
|
||||
|
||||
void main_window_set_selected_evidence(
|
||||
MainWindow *main_window,
|
||||
const EvidenceRecord *evidence_record
|
||||
)
|
||||
{
|
||||
if (main_window == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
workspace_set_selected_evidence(
|
||||
main_window->workspace,
|
||||
evidence_record
|
||||
);
|
||||
}
|
||||
|
||||
void main_window_free(
|
||||
MainWindow *main_window
|
||||
)
|
||||
|
|
@ -1017,6 +1028,17 @@ void main_window_free(
|
|||
sidebar_set_tree_model(
|
||||
main_window->sidebar,
|
||||
NULL
|
||||
);
|
||||
|
||||
sidebar_set_evidence_selection_callback(
|
||||
main_window->sidebar,
|
||||
NULL,
|
||||
NULL
|
||||
);
|
||||
|
||||
sidebar_set_evidence_model(
|
||||
main_window->sidebar,
|
||||
NULL
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,8 @@
|
|||
|
||||
#define WORKSPACE_PAGE_WELCOME "welcome"
|
||||
#define WORKSPACE_PAGE_NODE_INFORMATION "node-information"
|
||||
|
||||
#define WORKSPACE_PAGE_EVIDENCE_INFORMATION \
|
||||
"evidence-information"
|
||||
/**
|
||||
* @struct Workspace
|
||||
* @brief Représentation interne de la zone de travail.
|
||||
|
|
@ -25,6 +26,22 @@ struct Workspace
|
|||
GtkWidget *welcome_instruction_label;
|
||||
|
||||
GtkWidget *node_page;
|
||||
|
||||
GtkWidget *evidence_page;
|
||||
GtkWidget *evidence_name_label;
|
||||
|
||||
GtkWidget *evidence_type_label;
|
||||
GtkWidget *evidence_integrity_label;
|
||||
GtkWidget *evidence_size_label;
|
||||
GtkWidget *evidence_imported_at_label;
|
||||
GtkWidget *evidence_collected_at_label;
|
||||
GtkWidget *evidence_source_label;
|
||||
GtkWidget *evidence_description_label;
|
||||
GtkWidget *evidence_relative_path_label;
|
||||
GtkWidget *evidence_internal_name_label;
|
||||
GtkWidget *evidence_identifier_label;
|
||||
GtkWidget *evidence_sha256_label;
|
||||
|
||||
GtkWidget *node_name_label;
|
||||
GtkWidget *node_path_label;
|
||||
GtkWidget *node_type_label;
|
||||
|
|
@ -32,6 +49,173 @@ struct Workspace
|
|||
GtkWidget *node_children_label;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Ajoute une ligne de métadonnée dans la grille.
|
||||
*
|
||||
* @return Label GTK destiné à recevoir la valeur.
|
||||
*/
|
||||
static GtkWidget *workspace_add_evidence_field(
|
||||
GtkGrid *grid,
|
||||
gint row,
|
||||
const char *title
|
||||
)
|
||||
{
|
||||
GtkWidget *title_label = NULL;
|
||||
GtkWidget *value_label = NULL;
|
||||
|
||||
if (grid == NULL ||
|
||||
title == NULL ||
|
||||
title[0] == '\0')
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
title_label =
|
||||
gtk_label_new(
|
||||
title
|
||||
);
|
||||
|
||||
value_label =
|
||||
gtk_label_new(
|
||||
NULL
|
||||
);
|
||||
|
||||
if (title_label == NULL ||
|
||||
value_label == NULL)
|
||||
{
|
||||
g_clear_object(
|
||||
&value_label
|
||||
);
|
||||
|
||||
g_clear_object(
|
||||
&title_label
|
||||
);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gtk_label_set_xalign(
|
||||
GTK_LABEL(title_label),
|
||||
0.0F
|
||||
);
|
||||
|
||||
gtk_widget_set_valign(
|
||||
title_label,
|
||||
GTK_ALIGN_START
|
||||
);
|
||||
|
||||
gtk_widget_add_css_class(
|
||||
title_label,
|
||||
"dim-label"
|
||||
);
|
||||
|
||||
gtk_label_set_xalign(
|
||||
GTK_LABEL(value_label),
|
||||
0.0F
|
||||
);
|
||||
|
||||
gtk_label_set_wrap(
|
||||
GTK_LABEL(value_label),
|
||||
TRUE
|
||||
);
|
||||
|
||||
gtk_label_set_wrap_mode(
|
||||
GTK_LABEL(value_label),
|
||||
PANGO_WRAP_WORD_CHAR
|
||||
);
|
||||
|
||||
gtk_label_set_selectable(
|
||||
GTK_LABEL(value_label),
|
||||
TRUE
|
||||
);
|
||||
|
||||
gtk_widget_set_hexpand(
|
||||
value_label,
|
||||
TRUE
|
||||
);
|
||||
|
||||
gtk_widget_set_halign(
|
||||
value_label,
|
||||
GTK_ALIGN_FILL
|
||||
);
|
||||
|
||||
gtk_widget_set_valign(
|
||||
value_label,
|
||||
GTK_ALIGN_START
|
||||
);
|
||||
|
||||
gtk_grid_attach(
|
||||
grid,
|
||||
title_label,
|
||||
0,
|
||||
row,
|
||||
1,
|
||||
1
|
||||
);
|
||||
|
||||
gtk_grid_attach(
|
||||
grid,
|
||||
value_label,
|
||||
1,
|
||||
row,
|
||||
1,
|
||||
1
|
||||
);
|
||||
|
||||
return value_label;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Définit une valeur avec un texte de remplacement.
|
||||
*/
|
||||
static void workspace_set_field_text(
|
||||
GtkWidget *label,
|
||||
const char *value,
|
||||
const char *fallback
|
||||
)
|
||||
{
|
||||
if (label == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
gtk_label_set_text(
|
||||
GTK_LABEL(label),
|
||||
value != NULL && value[0] != '\0'
|
||||
? value
|
||||
: fallback
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Convertit un statut d'intégrité en texte utilisateur.
|
||||
*/
|
||||
static const char *workspace_get_integrity_status_text(
|
||||
EvidenceIntegrityStatus integrity_status
|
||||
)
|
||||
{
|
||||
switch (integrity_status)
|
||||
{
|
||||
case EVIDENCE_INTEGRITY_STATUS_UNKNOWN:
|
||||
return "Non vérifiée";
|
||||
|
||||
case EVIDENCE_INTEGRITY_STATUS_VALID:
|
||||
return "Valide";
|
||||
|
||||
case EVIDENCE_INTEGRITY_STATUS_MISSING:
|
||||
return "Fichier absent";
|
||||
|
||||
case EVIDENCE_INTEGRITY_STATUS_MODIFIED:
|
||||
return "Fichier modifié";
|
||||
|
||||
case EVIDENCE_INTEGRITY_STATUS_ERROR:
|
||||
return "Erreur de vérification";
|
||||
|
||||
default:
|
||||
return "Statut inconnu";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Affiche la page d'accueil.
|
||||
*/
|
||||
|
|
@ -52,6 +236,10 @@ static void workspace_show_welcome(
|
|||
|
||||
Workspace *workspace_new(void)
|
||||
{
|
||||
GtkWidget *evidence_content = NULL;
|
||||
GtkWidget *evidence_separator = NULL;
|
||||
GtkWidget *evidence_grid = NULL;
|
||||
|
||||
Workspace *workspace = NULL;
|
||||
|
||||
workspace = g_new0(Workspace, 1);
|
||||
|
|
@ -233,6 +421,270 @@ Workspace *workspace_new(void)
|
|||
WORKSPACE_PAGE_NODE_INFORMATION
|
||||
);
|
||||
|
||||
/*
|
||||
* Page détaillée d'une preuve.
|
||||
*/
|
||||
workspace->evidence_page =
|
||||
gtk_scrolled_window_new();
|
||||
|
||||
if (workspace->evidence_page == NULL)
|
||||
{
|
||||
workspace_free(
|
||||
workspace
|
||||
);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gtk_widget_set_hexpand(
|
||||
workspace->evidence_page,
|
||||
TRUE
|
||||
);
|
||||
|
||||
gtk_widget_set_vexpand(
|
||||
workspace->evidence_page,
|
||||
TRUE
|
||||
);
|
||||
|
||||
gtk_scrolled_window_set_policy(
|
||||
GTK_SCROLLED_WINDOW(
|
||||
workspace->evidence_page
|
||||
),
|
||||
GTK_POLICY_AUTOMATIC,
|
||||
GTK_POLICY_AUTOMATIC
|
||||
);
|
||||
|
||||
evidence_content =
|
||||
gtk_box_new(
|
||||
GTK_ORIENTATION_VERTICAL,
|
||||
16
|
||||
);
|
||||
|
||||
if (evidence_content == NULL)
|
||||
{
|
||||
workspace_free(
|
||||
workspace
|
||||
);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gtk_widget_set_margin_start(
|
||||
evidence_content,
|
||||
24
|
||||
);
|
||||
|
||||
gtk_widget_set_margin_end(
|
||||
evidence_content,
|
||||
24
|
||||
);
|
||||
|
||||
gtk_widget_set_margin_top(
|
||||
evidence_content,
|
||||
24
|
||||
);
|
||||
|
||||
gtk_widget_set_margin_bottom(
|
||||
evidence_content,
|
||||
24
|
||||
);
|
||||
|
||||
workspace->evidence_name_label =
|
||||
gtk_label_new(
|
||||
NULL
|
||||
);
|
||||
|
||||
if (workspace->evidence_name_label == NULL)
|
||||
{
|
||||
workspace_free(
|
||||
workspace
|
||||
);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gtk_label_set_xalign(
|
||||
GTK_LABEL(
|
||||
workspace->evidence_name_label
|
||||
),
|
||||
0.0F
|
||||
);
|
||||
|
||||
gtk_label_set_wrap(
|
||||
GTK_LABEL(
|
||||
workspace->evidence_name_label
|
||||
),
|
||||
TRUE
|
||||
);
|
||||
|
||||
gtk_label_set_selectable(
|
||||
GTK_LABEL(
|
||||
workspace->evidence_name_label
|
||||
),
|
||||
TRUE
|
||||
);
|
||||
|
||||
gtk_widget_add_css_class(
|
||||
workspace->evidence_name_label,
|
||||
"title-2"
|
||||
);
|
||||
|
||||
gtk_box_append(
|
||||
GTK_BOX(evidence_content),
|
||||
workspace->evidence_name_label
|
||||
);
|
||||
|
||||
evidence_separator =
|
||||
gtk_separator_new(
|
||||
GTK_ORIENTATION_HORIZONTAL
|
||||
);
|
||||
|
||||
gtk_box_append(
|
||||
GTK_BOX(evidence_content),
|
||||
evidence_separator
|
||||
);
|
||||
|
||||
evidence_grid =
|
||||
gtk_grid_new();
|
||||
|
||||
if (evidence_grid == NULL)
|
||||
{
|
||||
workspace_free(
|
||||
workspace
|
||||
);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gtk_grid_set_column_spacing(
|
||||
GTK_GRID(evidence_grid),
|
||||
24
|
||||
);
|
||||
|
||||
gtk_grid_set_row_spacing(
|
||||
GTK_GRID(evidence_grid),
|
||||
12
|
||||
);
|
||||
|
||||
gtk_widget_set_hexpand(
|
||||
evidence_grid,
|
||||
TRUE
|
||||
);
|
||||
|
||||
workspace->evidence_type_label =
|
||||
workspace_add_evidence_field(
|
||||
GTK_GRID(evidence_grid),
|
||||
0,
|
||||
"Type"
|
||||
);
|
||||
|
||||
workspace->evidence_integrity_label =
|
||||
workspace_add_evidence_field(
|
||||
GTK_GRID(evidence_grid),
|
||||
1,
|
||||
"Intégrité"
|
||||
);
|
||||
|
||||
workspace->evidence_size_label =
|
||||
workspace_add_evidence_field(
|
||||
GTK_GRID(evidence_grid),
|
||||
2,
|
||||
"Taille"
|
||||
);
|
||||
|
||||
workspace->evidence_imported_at_label =
|
||||
workspace_add_evidence_field(
|
||||
GTK_GRID(evidence_grid),
|
||||
3,
|
||||
"Importée le"
|
||||
);
|
||||
|
||||
workspace->evidence_collected_at_label =
|
||||
workspace_add_evidence_field(
|
||||
GTK_GRID(evidence_grid),
|
||||
4,
|
||||
"Collectée le"
|
||||
);
|
||||
|
||||
workspace->evidence_source_label =
|
||||
workspace_add_evidence_field(
|
||||
GTK_GRID(evidence_grid),
|
||||
5,
|
||||
"Source"
|
||||
);
|
||||
|
||||
workspace->evidence_description_label =
|
||||
workspace_add_evidence_field(
|
||||
GTK_GRID(evidence_grid),
|
||||
6,
|
||||
"Description"
|
||||
);
|
||||
|
||||
workspace->evidence_relative_path_label =
|
||||
workspace_add_evidence_field(
|
||||
GTK_GRID(evidence_grid),
|
||||
7,
|
||||
"Chemin relatif"
|
||||
);
|
||||
|
||||
workspace->evidence_internal_name_label =
|
||||
workspace_add_evidence_field(
|
||||
GTK_GRID(evidence_grid),
|
||||
8,
|
||||
"Nom interne"
|
||||
);
|
||||
|
||||
workspace->evidence_identifier_label =
|
||||
workspace_add_evidence_field(
|
||||
GTK_GRID(evidence_grid),
|
||||
9,
|
||||
"Identifiant"
|
||||
);
|
||||
|
||||
workspace->evidence_sha256_label =
|
||||
workspace_add_evidence_field(
|
||||
GTK_GRID(evidence_grid),
|
||||
10,
|
||||
"SHA-256"
|
||||
);
|
||||
|
||||
if (workspace->evidence_type_label == NULL ||
|
||||
workspace->evidence_integrity_label == NULL ||
|
||||
workspace->evidence_size_label == NULL ||
|
||||
workspace->evidence_imported_at_label == NULL ||
|
||||
workspace->evidence_collected_at_label == NULL ||
|
||||
workspace->evidence_source_label == NULL ||
|
||||
workspace->evidence_description_label == NULL ||
|
||||
workspace->evidence_relative_path_label == NULL ||
|
||||
workspace->evidence_internal_name_label == NULL ||
|
||||
workspace->evidence_identifier_label == NULL ||
|
||||
workspace->evidence_sha256_label == NULL)
|
||||
{
|
||||
workspace_free(
|
||||
workspace
|
||||
);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gtk_box_append(
|
||||
GTK_BOX(evidence_content),
|
||||
evidence_grid
|
||||
);
|
||||
|
||||
gtk_scrolled_window_set_child(
|
||||
GTK_SCROLLED_WINDOW(
|
||||
workspace->evidence_page
|
||||
),
|
||||
evidence_content
|
||||
);
|
||||
|
||||
gtk_stack_add_named(
|
||||
GTK_STACK(workspace->stack),
|
||||
workspace->evidence_page,
|
||||
WORKSPACE_PAGE_EVIDENCE_INFORMATION
|
||||
);
|
||||
|
||||
workspace_show_welcome(workspace);
|
||||
|
||||
return workspace;
|
||||
|
|
@ -367,6 +819,160 @@ void workspace_set_selected_node(
|
|||
g_free(parent_text);
|
||||
}
|
||||
|
||||
void workspace_set_selected_evidence(
|
||||
Workspace *workspace,
|
||||
const EvidenceRecord *evidence_record
|
||||
)
|
||||
{
|
||||
char *human_size = NULL;
|
||||
char *size_text = NULL;
|
||||
|
||||
guint64 size_bytes = 0;
|
||||
|
||||
if (workspace == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (evidence_record == NULL)
|
||||
{
|
||||
workspace_show_welcome(
|
||||
workspace
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
size_bytes =
|
||||
evidence_record_get_size_bytes(
|
||||
evidence_record
|
||||
);
|
||||
|
||||
human_size =
|
||||
g_format_size_full(
|
||||
size_bytes,
|
||||
G_FORMAT_SIZE_IEC_UNITS
|
||||
);
|
||||
|
||||
size_text =
|
||||
g_strdup_printf(
|
||||
"%s (%" G_GUINT64_FORMAT " octets)",
|
||||
human_size != NULL
|
||||
? human_size
|
||||
: "taille inconnue",
|
||||
size_bytes
|
||||
);
|
||||
|
||||
workspace_set_field_text(
|
||||
workspace->evidence_name_label,
|
||||
evidence_record_get_original_name(
|
||||
evidence_record
|
||||
),
|
||||
"(sans nom)"
|
||||
);
|
||||
|
||||
workspace_set_field_text(
|
||||
workspace->evidence_type_label,
|
||||
evidence_record_get_type_identifier(
|
||||
evidence_record
|
||||
),
|
||||
"(type inconnu)"
|
||||
);
|
||||
|
||||
workspace_set_field_text(
|
||||
workspace->evidence_integrity_label,
|
||||
workspace_get_integrity_status_text(
|
||||
evidence_record_get_integrity_status(
|
||||
evidence_record
|
||||
)
|
||||
),
|
||||
"Statut inconnu"
|
||||
);
|
||||
|
||||
workspace_set_field_text(
|
||||
workspace->evidence_size_label,
|
||||
size_text,
|
||||
"Taille inconnue"
|
||||
);
|
||||
|
||||
workspace_set_field_text(
|
||||
workspace->evidence_imported_at_label,
|
||||
evidence_record_get_imported_at(
|
||||
evidence_record
|
||||
),
|
||||
"(date inconnue)"
|
||||
);
|
||||
|
||||
workspace_set_field_text(
|
||||
workspace->evidence_collected_at_label,
|
||||
evidence_record_get_collected_at(
|
||||
evidence_record
|
||||
),
|
||||
"Non renseignée"
|
||||
);
|
||||
|
||||
workspace_set_field_text(
|
||||
workspace->evidence_source_label,
|
||||
evidence_record_get_source(
|
||||
evidence_record
|
||||
),
|
||||
"Non renseignée"
|
||||
);
|
||||
|
||||
workspace_set_field_text(
|
||||
workspace->evidence_description_label,
|
||||
evidence_record_get_description(
|
||||
evidence_record
|
||||
),
|
||||
"Non renseignée"
|
||||
);
|
||||
|
||||
workspace_set_field_text(
|
||||
workspace->evidence_relative_path_label,
|
||||
evidence_record_get_relative_path(
|
||||
evidence_record
|
||||
),
|
||||
"(chemin inconnu)"
|
||||
);
|
||||
|
||||
workspace_set_field_text(
|
||||
workspace->evidence_internal_name_label,
|
||||
evidence_record_get_internal_name(
|
||||
evidence_record
|
||||
),
|
||||
"(nom interne inconnu)"
|
||||
);
|
||||
|
||||
workspace_set_field_text(
|
||||
workspace->evidence_identifier_label,
|
||||
evidence_record_get_identifier(
|
||||
evidence_record
|
||||
),
|
||||
"(identifiant inconnu)"
|
||||
);
|
||||
|
||||
workspace_set_field_text(
|
||||
workspace->evidence_sha256_label,
|
||||
evidence_record_get_sha256(
|
||||
evidence_record
|
||||
),
|
||||
"(empreinte inconnue)"
|
||||
);
|
||||
|
||||
gtk_stack_set_visible_child_name(
|
||||
GTK_STACK(workspace->stack),
|
||||
WORKSPACE_PAGE_EVIDENCE_INFORMATION
|
||||
);
|
||||
|
||||
g_free(
|
||||
size_text
|
||||
);
|
||||
|
||||
g_free(
|
||||
human_size
|
||||
);
|
||||
}
|
||||
|
||||
void workspace_free(Workspace *workspace)
|
||||
{
|
||||
if (workspace == NULL)
|
||||
|
|
|
|||
Loading…
Reference in a new issue