labfy-investigation/src/views/evidence_import_dialog.c
2026-07-20 09:35:36 +02:00

1705 lines
31 KiB
C

/******************************************************************************
* @file evidence_import_dialog.c
* @brief Dialogue GTK de saisie des métadonnées d'une preuve.
******************************************************************************/
#include "views/evidence_import_dialog.h"
#include "models/evidence_type.h"
#include <string.h>
#include <glib.h>
/**
* @struct EvidenceImportDialogResult
* @brief Métadonnées validées avant le lancement d'un import.
*/
struct EvidenceImportDialogResult
{
char *type_identifier;
char *collected_at;
char *source;
char *description;
};
/**
* @brief État privé conservé pendant l'affichage du dialogue.
*/
typedef struct
{
GtkWindow *window;
GtkDropDown *type_drop_down;
GtkEntry *collected_at_entry;
GtkEntry *source_entry;
GtkTextView *description_text_view;
GtkLabel *error_label;
char *file_path;
GPtrArray *type_codes;
EvidenceImportDialogCallback callback;
gpointer callback_data;
gboolean completed;
} EvidenceImportDialogState;
/**
* @brief Vérifie qu'une chaîne contient du texte non blanc.
*/
static gboolean evidence_import_dialog_value_has_text(
const char *value
)
{
char *normalized_value = NULL;
gboolean has_text = FALSE;
if (value == NULL)
{
return FALSE;
}
normalized_value =
g_strdup(
value
);
if (normalized_value == NULL)
{
return FALSE;
}
g_strstrip(
normalized_value
);
has_text =
normalized_value[0] != '\0';
g_free(
normalized_value
);
return has_text;
}
/**
* @brief Vérifie qu'une date contient un fuseau horaire explicite.
*
* Les formats acceptés sont notamment :
*
* - 2026-07-20T08:30:00Z
* - 2026-07-20T10:30:00+02
* - 2026-07-20T10:30:00+02:00
*/
static gboolean evidence_import_dialog_has_explicit_timezone(
const char *value
)
{
gsize length = 0;
const char *offset = NULL;
if (value == NULL)
{
return FALSE;
}
length =
strlen(
value
);
if (length == 0)
{
return FALSE;
}
/*
* Fuseau UTC explicite.
*/
if (value[length - 1] == 'Z' ||
value[length - 1] == 'z')
{
return TRUE;
}
/*
* Vérifie une terminaison de la forme +02:00 ou -05:30.
*/
if (length >= 6)
{
offset =
value + length - 6;
if ((offset[0] == '+' ||
offset[0] == '-') &&
g_ascii_isdigit(offset[1]) &&
g_ascii_isdigit(offset[2]) &&
offset[3] == ':' &&
g_ascii_isdigit(offset[4]) &&
g_ascii_isdigit(offset[5]))
{
return TRUE;
}
}
/*
* Vérifie une terminaison ISO 8601 courte :
* +02 ou -05.
*/
if (length >= 3)
{
offset =
value + length - 3;
if ((offset[0] == '+' ||
offset[0] == '-') &&
g_ascii_isdigit(offset[1]) &&
g_ascii_isdigit(offset[2]))
{
return TRUE;
}
}
return FALSE;
}
/**
* @brief Convertit une date ISO 8601 en UTC au format EvidenceRecord.
*
* Exemple :
*
* 2026-07-20T09:16:01.492569+02
* devient :
* 2026-07-20T07:16:01Z
*
* @return Nouvelle chaîne possédée par l'appelant, ou NULL.
*/
static char *evidence_import_dialog_normalize_collected_at(
const char *value,
GError **error
)
{
char *normalized_value = NULL;
char *utc_value = NULL;
GDateTime *date_time = NULL;
GDateTime *utc_date_time = NULL;
g_return_val_if_fail(
error == NULL || *error == NULL,
NULL
);
if (!evidence_import_dialog_value_has_text(
value
))
{
g_set_error_literal(
error,
EVIDENCE_IMPORT_DIALOG_ERROR,
EVIDENCE_IMPORT_DIALOG_ERROR_INVALID_DATA,
"La date de collecte est obligatoire."
);
return NULL;
}
normalized_value =
g_strdup(
value
);
if (normalized_value == NULL)
{
g_set_error_literal(
error,
EVIDENCE_IMPORT_DIALOG_ERROR,
EVIDENCE_IMPORT_DIALOG_ERROR_MEMORY,
"Impossible de copier la date de collecte."
);
return NULL;
}
g_strstrip(
normalized_value
);
date_time =
g_date_time_new_from_iso8601(
normalized_value,
NULL
);
g_free(
normalized_value
);
if (date_time == NULL)
{
g_set_error_literal(
error,
EVIDENCE_IMPORT_DIALOG_ERROR,
EVIDENCE_IMPORT_DIALOG_ERROR_INVALID_DATA,
"La date de collecte n'est pas une date ISO 8601 valide."
);
return NULL;
}
utc_date_time =
g_date_time_to_utc(
date_time
);
g_date_time_unref(
date_time
);
if (utc_date_time == NULL)
{
g_set_error_literal(
error,
EVIDENCE_IMPORT_DIALOG_ERROR,
EVIDENCE_IMPORT_DIALOG_ERROR_MEMORY,
"Impossible de convertir la date de collecte en UTC."
);
return NULL;
}
utc_value =
g_date_time_format(
utc_date_time,
"%Y-%m-%dT%H:%M:%SZ"
);
g_date_time_unref(
utc_date_time
);
if (utc_value == NULL)
{
g_set_error_literal(
error,
EVIDENCE_IMPORT_DIALOG_ERROR,
EVIDENCE_IMPORT_DIALOG_ERROR_MEMORY,
"Impossible de formater la date de collecte."
);
return NULL;
}
return utc_value;
}
GQuark evidence_import_dialog_error_quark(void)
{
return g_quark_from_static_string(
"evidence-import-dialog-error-quark"
);
}
/**
* @brief Retourne une copie nettoyée ou NULL pour une valeur vide.
*/
static char *evidence_import_dialog_duplicate_optional_text(
const char *value
)
{
char *normalized_value = NULL;
if (value == NULL)
{
return NULL;
}
normalized_value =
g_strdup(
value
);
if (normalized_value == NULL)
{
return NULL;
}
g_strstrip(
normalized_value
);
if (normalized_value[0] == '\0')
{
g_free(
normalized_value
);
return NULL;
}
return normalized_value;
}
/**
* @brief Affiche un message de validation dans le dialogue.
*/
static void evidence_import_dialog_show_error(
EvidenceImportDialogState *state,
const char *message
)
{
if (state == NULL ||
state->error_label == NULL)
{
return;
}
gtk_label_set_text(
state->error_label,
message != NULL
? message
: "Les métadonnées sont invalides."
);
gtk_widget_set_visible(
GTK_WIDGET(
state->error_label
),
TRUE
);
}
/**
* @brief Libère l'état privé du dialogue.
*/
static void evidence_import_dialog_state_free(
gpointer user_data
)
{
EvidenceImportDialogState *state =
user_data;
if (state == NULL)
{
return;
}
g_free(
state->file_path
);
g_ptr_array_unref(
state->type_codes
);
g_free(
state
);
}
/**
* @brief Retourne le contenu complet de la description.
*/
static char *evidence_import_dialog_get_description_text(
EvidenceImportDialogState *state
)
{
GtkTextBuffer *buffer = NULL;
GtkTextIter start;
GtkTextIter end;
if (state == NULL ||
state->description_text_view == NULL)
{
return NULL;
}
buffer =
gtk_text_view_get_buffer(
state->description_text_view
);
gtk_text_buffer_get_bounds(
buffer,
&start,
&end
);
return gtk_text_buffer_get_text(
buffer,
&start,
&end,
FALSE
);
}
/**
* @brief Termine le dialogue avec une annulation.
*/
static void evidence_import_dialog_cancel(
EvidenceImportDialogState *state
)
{
if (state == NULL ||
state->completed)
{
return;
}
state->completed =
TRUE;
if (state->callback != NULL)
{
state->callback(
NULL,
state->callback_data
);
}
}
/**
* @brief Traite la fermeture native de la fenêtre.
*/
static gboolean evidence_import_dialog_on_close_requested(
GtkWindow *window,
gpointer user_data
)
{
EvidenceImportDialogState *state =
user_data;
(void) window;
evidence_import_dialog_cancel(
state
);
/*
* FALSE laisse GTK exécuter son comportement normal de fermeture.
*/
return FALSE;
}
/**
* @brief Traite le bouton Annuler.
*/
static void evidence_import_dialog_on_cancel_clicked(
GtkButton *button,
gpointer user_data
)
{
EvidenceImportDialogState *state =
user_data;
(void) button;
if (state == NULL)
{
return;
}
evidence_import_dialog_cancel(
state
);
gtk_window_close(
state->window
);
}
/**
* @brief Traite la validation du formulaire.
*/
static void evidence_import_dialog_on_import_clicked(
GtkButton *button,
gpointer user_data
)
{
EvidenceImportDialogState *state =
user_data;
EvidenceImportDialogResult *result = NULL;
guint selected_index =
GTK_INVALID_LIST_POSITION;
const char *type_identifier = NULL;
const char *collected_at = NULL;
const char *source = NULL;
char *description = NULL;
char *normalized_collected_at = NULL;
GError *normalization_error = NULL;
GError *validation_error = NULL;
(void) button;
if (state == NULL ||
state->completed)
{
return;
}
selected_index =
gtk_drop_down_get_selected(
state->type_drop_down
);
if (selected_index ==
GTK_INVALID_LIST_POSITION ||
selected_index >= state->type_codes->len)
{
evidence_import_dialog_show_error(
state,
"Sélectionnez un type de preuve."
);
return;
}
type_identifier =
g_ptr_array_index(
state->type_codes,
selected_index
);
collected_at =
gtk_editable_get_text(
GTK_EDITABLE(
state->collected_at_entry
)
);
source =
gtk_editable_get_text(
GTK_EDITABLE(
state->source_entry
)
);
description =
evidence_import_dialog_get_description_text(
state
);
if (!evidence_import_dialog_validate_values(
state->file_path,
type_identifier,
collected_at,
&validation_error
))
{
evidence_import_dialog_show_error(
state,
validation_error != NULL
? validation_error->message
: "Les métadonnées sont invalides."
);
g_clear_error(
&validation_error
);
g_free(
description
);
return;
}
normalized_collected_at =
evidence_import_dialog_normalize_collected_at(
collected_at,
&normalization_error
);
if (normalized_collected_at == NULL)
{
evidence_import_dialog_show_error(
state,
normalization_error != NULL
? normalization_error->message
: "Impossible de normaliser la date de collecte."
);
g_clear_error(
&normalization_error
);
g_free(
description
);
return;
}
result =
g_try_new0(
EvidenceImportDialogResult,
1
);
if (result == NULL)
{
g_free(
normalized_collected_at
);
g_free(
description
);
evidence_import_dialog_show_error(
state,
"Impossible d'allouer le résultat du formulaire."
);
return;
}
g_strstrip(
normalized_collected_at
);
result->type_identifier =
g_strdup(
type_identifier
);
result->collected_at =
normalized_collected_at;
result->source =
evidence_import_dialog_duplicate_optional_text(
source
);
result->description =
evidence_import_dialog_duplicate_optional_text(
description
);
g_free(
description
);
if (result->type_identifier == NULL)
{
evidence_import_dialog_result_free(
result
);
evidence_import_dialog_show_error(
state,
"Impossible de conserver le type de preuve."
);
return;
}
state->completed =
TRUE;
if (state->callback != NULL)
{
state->callback(
result,
state->callback_data
);
}
else
{
evidence_import_dialog_result_free(
result
);
}
gtk_window_close(
state->window
);
}
gboolean evidence_import_dialog_present(
GtkWindow *parent,
const char *file_path,
const GPtrArray *evidence_types,
EvidenceImportDialogCallback callback,
gpointer user_data,
GError **error
)
{
EvidenceImportDialogState *state = NULL;
GtkStringList *type_labels = NULL;
GtkWidget *root_box = NULL;
GtkWidget *title_label = NULL;
GtkWidget *path_title_label = NULL;
GtkWidget *path_label = NULL;
GtkWidget *grid = NULL;
GtkWidget *type_label = NULL;
GtkWidget *collected_at_label = NULL;
GtkWidget *source_label = NULL;
GtkWidget *description_label = NULL;
GtkWidget *description_scrolled_window = NULL;
GtkWidget *button_box = NULL;
GtkWidget *cancel_button = NULL;
GtkWidget *import_button = NULL;
GDateTime *current_date_time = NULL;
char *current_date_time_iso8601 = NULL;
guint default_type_index = 0;
guint type_index = 0;
g_return_val_if_fail(
error == NULL || *error == NULL,
FALSE
);
if (parent == NULL ||
!GTK_IS_WINDOW(parent) ||
file_path == NULL ||
file_path[0] == '\0' ||
evidence_types == NULL ||
callback == NULL)
{
g_set_error_literal(
error,
EVIDENCE_IMPORT_DIALOG_ERROR,
EVIDENCE_IMPORT_DIALOG_ERROR_INVALID_ARGUMENT,
"Les arguments du dialogue d'import sont invalides."
);
return FALSE;
}
if (evidence_types->len == 0)
{
g_set_error_literal(
error,
EVIDENCE_IMPORT_DIALOG_ERROR,
EVIDENCE_IMPORT_DIALOG_ERROR_EMPTY_TYPES,
"Aucun type de preuve n'est disponible."
);
return FALSE;
}
state =
g_try_new0(
EvidenceImportDialogState,
1
);
if (state == NULL)
{
g_set_error_literal(
error,
EVIDENCE_IMPORT_DIALOG_ERROR,
EVIDENCE_IMPORT_DIALOG_ERROR_MEMORY,
"Impossible d'allouer l'état du dialogue."
);
return FALSE;
}
state->file_path =
g_strdup(
file_path
);
state->type_codes =
g_ptr_array_new_with_free_func(
g_free
);
state->callback =
callback;
state->callback_data =
user_data;
if (state->file_path == NULL ||
state->type_codes == NULL)
{
evidence_import_dialog_state_free(
state
);
g_set_error_literal(
error,
EVIDENCE_IMPORT_DIALOG_ERROR,
EVIDENCE_IMPORT_DIALOG_ERROR_MEMORY,
"Impossible de préparer les données du dialogue."
);
return FALSE;
}
type_labels =
gtk_string_list_new(
NULL
);
if (type_labels == NULL)
{
evidence_import_dialog_state_free(
state
);
g_set_error_literal(
error,
EVIDENCE_IMPORT_DIALOG_ERROR,
EVIDENCE_IMPORT_DIALOG_ERROR_MEMORY,
"Impossible de créer la liste des types de preuve."
);
return FALSE;
}
for (type_index = 0;
type_index < evidence_types->len;
type_index++)
{
const EvidenceType *evidence_type =
g_ptr_array_index(
evidence_types,
type_index
);
const char *code =
evidence_type_get_code(
evidence_type
);
const char *label =
evidence_type_get_label(
evidence_type
);
char *code_copy = NULL;
if (evidence_type == NULL ||
code == NULL ||
code[0] == '\0' ||
label == NULL ||
label[0] == '\0')
{
g_object_unref(
type_labels
);
evidence_import_dialog_state_free(
state
);
g_set_error_literal(
error,
EVIDENCE_IMPORT_DIALOG_ERROR,
EVIDENCE_IMPORT_DIALOG_ERROR_INVALID_ARGUMENT,
"La liste contient un type de preuve invalide."
);
return FALSE;
}
code_copy =
g_strdup(
code
);
if (code_copy == NULL)
{
g_object_unref(
type_labels
);
evidence_import_dialog_state_free(
state
);
g_set_error_literal(
error,
EVIDENCE_IMPORT_DIALOG_ERROR,
EVIDENCE_IMPORT_DIALOG_ERROR_MEMORY,
"Impossible de copier un type de preuve."
);
return FALSE;
}
g_ptr_array_add(
state->type_codes,
code_copy
);
gtk_string_list_append(
type_labels,
label
);
if (g_strcmp0(
code,
"document"
) == 0)
{
default_type_index =
type_index;
}
}
state->window =
GTK_WINDOW(
gtk_window_new()
);
gtk_window_set_title(
state->window,
"Importer une preuve"
);
gtk_window_set_transient_for(
state->window,
parent
);
gtk_window_set_modal(
state->window,
TRUE
);
gtk_window_set_destroy_with_parent(
state->window,
TRUE
);
gtk_window_set_default_size(
state->window,
620,
520
);
root_box =
gtk_box_new(
GTK_ORIENTATION_VERTICAL,
12
);
gtk_widget_set_margin_top(
root_box,
18
);
gtk_widget_set_margin_bottom(
root_box,
18
);
gtk_widget_set_margin_start(
root_box,
18
);
gtk_widget_set_margin_end(
root_box,
18
);
title_label =
gtk_label_new(
NULL
);
gtk_label_set_markup(
GTK_LABEL(title_label),
"<b>Saisir les métadonnées de la preuve</b>"
);
gtk_label_set_xalign(
GTK_LABEL(title_label),
0.0F
);
gtk_box_append(
GTK_BOX(root_box),
title_label
);
path_title_label =
gtk_label_new(
"Fichier sélectionné"
);
gtk_label_set_xalign(
GTK_LABEL(path_title_label),
0.0F
);
gtk_box_append(
GTK_BOX(root_box),
path_title_label
);
path_label =
gtk_label_new(
state->file_path
);
gtk_label_set_xalign(
GTK_LABEL(path_label),
0.0F
);
gtk_label_set_wrap(
GTK_LABEL(path_label),
TRUE
);
gtk_label_set_selectable(
GTK_LABEL(path_label),
TRUE
);
gtk_box_append(
GTK_BOX(root_box),
path_label
);
grid =
gtk_grid_new();
gtk_grid_set_row_spacing(
GTK_GRID(grid),
10
);
gtk_grid_set_column_spacing(
GTK_GRID(grid),
12
);
gtk_widget_set_vexpand(
grid,
TRUE
);
type_label =
gtk_label_new(
"Type de preuve"
);
gtk_label_set_xalign(
GTK_LABEL(type_label),
0.0F
);
state->type_drop_down =
GTK_DROP_DOWN(
gtk_drop_down_new(
G_LIST_MODEL(type_labels),
NULL
)
);
/*
* gtk_drop_down_new() prend possession de la référence
* de type_labels.
*/
type_labels = NULL;
gtk_drop_down_set_selected(
state->type_drop_down,
default_type_index
);
gtk_widget_set_hexpand(
GTK_WIDGET(
state->type_drop_down
),
TRUE
);
collected_at_label =
gtk_label_new(
"Date de collecte"
);
gtk_label_set_xalign(
GTK_LABEL(collected_at_label),
0.0F
);
state->collected_at_entry =
GTK_ENTRY(
gtk_entry_new()
);
gtk_entry_set_placeholder_text(
state->collected_at_entry,
"2026-07-20T10:30:00+02:00"
);
current_date_time =
g_date_time_new_now_local();
if (current_date_time != NULL)
{
current_date_time_iso8601 =
g_date_time_format_iso8601(
current_date_time
);
g_date_time_unref(
current_date_time
);
}
if (current_date_time_iso8601 != NULL)
{
gtk_editable_set_text(
GTK_EDITABLE(
state->collected_at_entry
),
current_date_time_iso8601
);
g_free(
current_date_time_iso8601
);
}
source_label =
gtk_label_new(
"Source"
);
gtk_label_set_xalign(
GTK_LABEL(source_label),
0.0F
);
state->source_entry =
GTK_ENTRY(
gtk_entry_new()
);
gtk_entry_set_placeholder_text(
state->source_entry,
"Ex. : conversation Instagram, email reçu..."
);
description_label =
gtk_label_new(
"Description"
);
gtk_label_set_xalign(
GTK_LABEL(description_label),
0.0F
);
state->description_text_view =
GTK_TEXT_VIEW(
gtk_text_view_new()
);
gtk_text_view_set_wrap_mode(
state->description_text_view,
GTK_WRAP_WORD_CHAR
);
description_scrolled_window =
gtk_scrolled_window_new();
gtk_scrolled_window_set_child(
GTK_SCROLLED_WINDOW(
description_scrolled_window
),
GTK_WIDGET(
state->description_text_view
)
);
gtk_widget_set_size_request(
description_scrolled_window,
-1,
130
);
gtk_grid_attach(
GTK_GRID(grid),
type_label,
0,
0,
1,
1
);
gtk_grid_attach(
GTK_GRID(grid),
GTK_WIDGET(
state->type_drop_down
),
1,
0,
1,
1
);
gtk_grid_attach(
GTK_GRID(grid),
collected_at_label,
0,
1,
1,
1
);
gtk_grid_attach(
GTK_GRID(grid),
GTK_WIDGET(
state->collected_at_entry
),
1,
1,
1,
1
);
gtk_grid_attach(
GTK_GRID(grid),
source_label,
0,
2,
1,
1
);
gtk_grid_attach(
GTK_GRID(grid),
GTK_WIDGET(
state->source_entry
),
1,
2,
1,
1
);
gtk_grid_attach(
GTK_GRID(grid),
description_label,
0,
3,
1,
1
);
gtk_grid_attach(
GTK_GRID(grid),
description_scrolled_window,
1,
3,
1,
1
);
gtk_box_append(
GTK_BOX(root_box),
grid
);
state->error_label =
GTK_LABEL(
gtk_label_new(
NULL
)
);
gtk_label_set_xalign(
state->error_label,
0.0F
);
gtk_label_set_wrap(
state->error_label,
TRUE
);
gtk_widget_add_css_class(
GTK_WIDGET(
state->error_label
),
"error"
);
gtk_widget_set_visible(
GTK_WIDGET(
state->error_label
),
FALSE
);
gtk_box_append(
GTK_BOX(root_box),
GTK_WIDGET(
state->error_label
)
);
button_box =
gtk_box_new(
GTK_ORIENTATION_HORIZONTAL,
8
);
gtk_widget_set_halign(
button_box,
GTK_ALIGN_END
);
cancel_button =
gtk_button_new_with_label(
"Annuler"
);
import_button =
gtk_button_new_with_label(
"Importer"
);
gtk_widget_add_css_class(
import_button,
"suggested-action"
);
gtk_box_append(
GTK_BOX(button_box),
cancel_button
);
gtk_box_append(
GTK_BOX(button_box),
import_button
);
gtk_box_append(
GTK_BOX(root_box),
button_box
);
gtk_window_set_child(
state->window,
root_box
);
g_object_set_data_full(
G_OBJECT(
state->window
),
"labfy-evidence-import-dialog-state",
state,
evidence_import_dialog_state_free
);
g_signal_connect(
state->window,
"close-request",
G_CALLBACK(
evidence_import_dialog_on_close_requested
),
state
);
g_signal_connect(
cancel_button,
"clicked",
G_CALLBACK(
evidence_import_dialog_on_cancel_clicked
),
state
);
g_signal_connect(
import_button,
"clicked",
G_CALLBACK(
evidence_import_dialog_on_import_clicked
),
state
);
gtk_window_set_default_widget(
state->window,
import_button
);
gtk_window_present(
state->window
);
return TRUE;
}
gboolean evidence_import_dialog_validate_values(
const char *file_path,
const char *type_identifier,
const char *collected_at,
GError **error
)
{
char *normalized_type_identifier = NULL;
char *normalized_collected_at = NULL;
GDateTime *collected_date_time = NULL;
gboolean valid = FALSE;
g_return_val_if_fail(
error == NULL || *error == NULL,
FALSE
);
if (file_path == NULL ||
file_path[0] == '\0')
{
g_set_error_literal(
error,
EVIDENCE_IMPORT_DIALOG_ERROR,
EVIDENCE_IMPORT_DIALOG_ERROR_INVALID_DATA,
"Le chemin du fichier est obligatoire."
);
return FALSE;
}
/*
* Le chemin n'est pas normalisé avec g_strstrip(), car les espaces
* peuvent faire partie d'un nom de fichier Unix valide.
*/
if (!g_file_test(
file_path,
G_FILE_TEST_IS_REGULAR
))
{
g_set_error(
error,
EVIDENCE_IMPORT_DIALOG_ERROR,
EVIDENCE_IMPORT_DIALOG_ERROR_INVALID_DATA,
"Le fichier sélectionné est absent ou n'est pas un fichier "
"ordinaire : %s",
file_path
);
return FALSE;
}
if (!evidence_import_dialog_value_has_text(
type_identifier
))
{
g_set_error_literal(
error,
EVIDENCE_IMPORT_DIALOG_ERROR,
EVIDENCE_IMPORT_DIALOG_ERROR_INVALID_DATA,
"Le type de preuve est obligatoire."
);
return FALSE;
}
normalized_type_identifier =
g_strdup(
type_identifier
);
if (normalized_type_identifier == NULL)
{
g_set_error_literal(
error,
EVIDENCE_IMPORT_DIALOG_ERROR,
EVIDENCE_IMPORT_DIALOG_ERROR_MEMORY,
"Impossible de normaliser le type de preuve."
);
return FALSE;
}
g_strstrip(
normalized_type_identifier
);
if (!evidence_import_dialog_value_has_text(
collected_at
))
{
g_set_error_literal(
error,
EVIDENCE_IMPORT_DIALOG_ERROR,
EVIDENCE_IMPORT_DIALOG_ERROR_INVALID_DATA,
"La date de collecte est obligatoire."
);
goto cleanup;
}
normalized_collected_at =
g_strdup(
collected_at
);
if (normalized_collected_at == NULL)
{
g_set_error_literal(
error,
EVIDENCE_IMPORT_DIALOG_ERROR,
EVIDENCE_IMPORT_DIALOG_ERROR_MEMORY,
"Impossible de normaliser la date de collecte."
);
goto cleanup;
}
g_strstrip(
normalized_collected_at
);
if (!evidence_import_dialog_has_explicit_timezone(
normalized_collected_at
))
{
g_set_error_literal(
error,
EVIDENCE_IMPORT_DIALOG_ERROR,
EVIDENCE_IMPORT_DIALOG_ERROR_INVALID_DATA,
"La date de collecte doit contenir un fuseau horaire."
);
goto cleanup;
}
collected_date_time =
g_date_time_new_from_iso8601(
normalized_collected_at,
NULL
);
if (collected_date_time == NULL)
{
g_set_error_literal(
error,
EVIDENCE_IMPORT_DIALOG_ERROR,
EVIDENCE_IMPORT_DIALOG_ERROR_INVALID_DATA,
"La date de collecte n'est pas une date ISO 8601 valide."
);
goto cleanup;
}
valid = TRUE;
cleanup:
if (collected_date_time != NULL)
{
g_date_time_unref(
collected_date_time
);
}
g_free(
normalized_collected_at
);
g_free(
normalized_type_identifier
);
return valid;
}
void evidence_import_dialog_result_free(
EvidenceImportDialogResult *result
)
{
if (result == NULL)
{
return;
}
g_free(
result->type_identifier
);
g_free(
result->collected_at
);
g_free(
result->source
);
g_free(
result->description
);
g_free(
result
);
}
const char *evidence_import_dialog_result_get_type_identifier(
const EvidenceImportDialogResult *result
)
{
if (result == NULL)
{
return NULL;
}
return result->type_identifier;
}
const char *evidence_import_dialog_result_get_collected_at(
const EvidenceImportDialogResult *result
)
{
if (result == NULL)
{
return NULL;
}
return result->collected_at;
}
const char *evidence_import_dialog_result_get_source(
const EvidenceImportDialogResult *result
)
{
if (result == NULL)
{
return NULL;
}
return result->source;
}
const char *evidence_import_dialog_result_get_description(
const EvidenceImportDialogResult *result
)
{
if (result == NULL)
{
return NULL;
}
return result->description;
}