feat(osint): integrate public username and email research tools
This commit is contained in:
parent
832e3eca32
commit
4e97d0979a
8 changed files with 402 additions and 3 deletions
|
|
@ -69,6 +69,9 @@ typedef void (*EntityDetailsPanelPersonNameCallback)(
|
|||
/** @brief Callback appelé pour gérer les preuves d'une personne. */
|
||||
typedef void (*EntityDetailsPanelPersonEvidenceCallback)(
|
||||
const char *entity_identifier, gpointer user_data);
|
||||
/** @brief Callback appelé pour ouvrir les recherches OSINT compatibles. */
|
||||
typedef void (*EntityDetailsPanelOsintCallback)(
|
||||
const char *entity_identifier, gpointer user_data);
|
||||
|
||||
/**
|
||||
* @brief Crée un volet de détails fermé.
|
||||
|
|
@ -175,6 +178,9 @@ void entity_details_panel_set_person_name_callback(
|
|||
void entity_details_panel_set_person_evidence_callback(
|
||||
EntityDetailsPanel *details_panel,
|
||||
EntityDetailsPanelPersonEvidenceCallback callback, gpointer user_data);
|
||||
/** @brief Définit le callback du bouton de recherche OSINT. */
|
||||
void entity_details_panel_set_osint_callback(EntityDetailsPanel *details_panel,
|
||||
EntityDetailsPanelOsintCallback callback, gpointer user_data);
|
||||
/**
|
||||
* @brief Affiche les preuves associées à la personne courante.
|
||||
* @param details_panel Volet à mettre à jour.
|
||||
|
|
|
|||
|
|
@ -218,6 +218,7 @@ typedef struct
|
|||
typedef struct
|
||||
{
|
||||
Application *application;
|
||||
char *action_identifier;
|
||||
char *target_identifier;
|
||||
char *target_value;
|
||||
char *started_at;
|
||||
|
|
@ -231,6 +232,8 @@ typedef struct
|
|||
char *execution_identifier;
|
||||
GPtrArray *proposals;
|
||||
} ApplicationOsintReviewContext;
|
||||
static char *application_osint_output_to_utf8(GBytes *bytes);
|
||||
static char *application_osint_create_timestamp(void);
|
||||
/** @brief Contexte possédé pendant la révision d'une analyse EML. */
|
||||
typedef struct { Application *application; char *evidence_identifier; }
|
||||
ApplicationEmlReviewContext;
|
||||
|
|
@ -380,10 +383,153 @@ static void application_osint_action_context_free(
|
|||
|
||||
g_free(context->target_value);
|
||||
g_free(context->target_identifier);
|
||||
g_free(context->action_identifier);
|
||||
g_free(context->started_at);
|
||||
g_free(context);
|
||||
}
|
||||
|
||||
/** @brief Extrait un pseudo final depuis une URL de profil social. */
|
||||
static char *application_osint_search_target(const char *action_identifier,
|
||||
const char *target_value)
|
||||
{
|
||||
char *target = g_strdup(target_value != NULL ? target_value : "");
|
||||
char *query = NULL;
|
||||
char *slash = NULL;
|
||||
if (target == NULL) return NULL;
|
||||
if (g_str_has_prefix(action_identifier, "social-"))
|
||||
{
|
||||
query = strchr(target, '?');
|
||||
if (query != NULL) *query = '\0';
|
||||
slash = strrchr(target, '/');
|
||||
if (slash != NULL && slash[1] != '\0')
|
||||
{
|
||||
char *username = g_strdup(slash + 1);
|
||||
g_free(target);
|
||||
target = username;
|
||||
}
|
||||
}
|
||||
return target;
|
||||
}
|
||||
|
||||
/** @brief Présente et archive la sortie d'une recherche sociale/email. */
|
||||
static void application_on_osint_search_completed(BackgroundTask *task,
|
||||
gpointer user_data)
|
||||
{
|
||||
ApplicationOsintActionContext *context = user_data;
|
||||
const ToolTaskResult *task_result = NULL;
|
||||
const ToolProcessResult *process_result = NULL;
|
||||
GBytes *stdout_bytes = NULL;
|
||||
GBytes *stderr_bytes = NULL;
|
||||
char *stdout_text = NULL;
|
||||
char *stderr_text = NULL;
|
||||
char *details = NULL;
|
||||
char *output_directory = NULL;
|
||||
char *output_name = NULL;
|
||||
char *output_path = NULL;
|
||||
const InvestigationProject *project = NULL;
|
||||
GError *error = NULL;
|
||||
if (context == NULL || context->application == NULL) return;
|
||||
if (background_task_get_state(task) == BACKGROUND_TASK_STATE_CANCELLED)
|
||||
{
|
||||
main_window_set_status(context->application->main_window,
|
||||
"Recherche OSINT annulée.");
|
||||
return;
|
||||
}
|
||||
if (background_task_get_state(task) != BACKGROUND_TASK_STATE_COMPLETED)
|
||||
{
|
||||
error = background_task_dup_error(task);
|
||||
application_present_error(context->application, "Recherche OSINT impossible",
|
||||
error != NULL ? error->message : "L'outil OSINT a échoué.");
|
||||
g_clear_error(&error);
|
||||
return;
|
||||
}
|
||||
task_result = tool_task_result_from_background_task(task);
|
||||
process_result = tool_task_result_get_process_result(task_result);
|
||||
stdout_bytes = tool_process_result_ref_stdout(process_result);
|
||||
stderr_bytes = tool_process_result_ref_stderr(process_result);
|
||||
stdout_text = application_osint_output_to_utf8(stdout_bytes);
|
||||
stderr_text = application_osint_output_to_utf8(stderr_bytes);
|
||||
project = investigation_session_get_project(context->application->session);
|
||||
output_directory = project != NULL ? g_build_filename(
|
||||
investigation_project_get_root_path(project), "02_Preuves_Traitees",
|
||||
"Extractions", "OSINT", NULL) : NULL;
|
||||
if (output_directory == NULL || g_mkdir_with_parents(output_directory, 0750) != 0)
|
||||
goto failure;
|
||||
output_name = g_strdup_printf("%s-%s.txt", context->target_identifier,
|
||||
context->action_identifier);
|
||||
output_path = g_build_filename(output_directory, output_name, NULL);
|
||||
details = g_strdup_printf("Cible : %s\nAction : %s\n\n%s%s%s",
|
||||
context->target_value, context->action_identifier,
|
||||
stdout_text != NULL ? stdout_text : "",
|
||||
stderr_text != NULL && stderr_text[0] != '\0' ? "\n\nErreur :\n" : "",
|
||||
stderr_text != NULL ? stderr_text : "");
|
||||
if (!g_file_set_contents(output_path, details, -1, &error)) goto failure;
|
||||
application_message_dialog_present_details_action(
|
||||
main_window_get_window(context->application->main_window),
|
||||
APPLICATION_MESSAGE_DIALOG_INFORMATION, "Résultat de la recherche OSINT",
|
||||
"La sortie publique a été archivée dans les preuves traitées.",
|
||||
details, NULL, NULL, NULL, NULL);
|
||||
goto cleanup;
|
||||
failure:
|
||||
application_present_error(context->application, "Archivage OSINT impossible",
|
||||
error != NULL ? error->message : "La sortie n'a pas pu être conservée.");
|
||||
cleanup:
|
||||
g_clear_error(&error); g_clear_pointer(&stdout_bytes, g_bytes_unref);
|
||||
g_clear_pointer(&stderr_bytes, g_bytes_unref); g_free(stdout_text);
|
||||
g_free(stderr_text); g_free(details); g_free(output_directory);
|
||||
g_free(output_name); g_free(output_path);
|
||||
}
|
||||
|
||||
/** @brief Lance Sherlock, Maigret ou Holehe selon l'action choisie. */
|
||||
static void application_start_osint_search(Application *application,
|
||||
const char *action_identifier, const char *target_identifier,
|
||||
const char *target_value)
|
||||
{
|
||||
const char *tool_identifier = NULL;
|
||||
const char *arguments[4] = { NULL, NULL, NULL, NULL };
|
||||
char *search_target = NULL;
|
||||
ToolTask *tool_task = NULL;
|
||||
BackgroundTask *background_task = NULL;
|
||||
ApplicationOsintActionContext *context = NULL;
|
||||
GError *error = NULL;
|
||||
if (g_strcmp0(action_identifier, "social-username-sherlock") == 0)
|
||||
{ tool_identifier = "osint.sherlock"; arguments[0] = "--print-found";
|
||||
arguments[1] = "--no-color"; }
|
||||
else if (g_strcmp0(action_identifier, "social-username-maigret") == 0)
|
||||
{ tool_identifier = "osint.maigret"; arguments[0] = "--json";
|
||||
arguments[1] = "simple"; }
|
||||
else if (g_strcmp0(action_identifier, "email-account-holehe") == 0)
|
||||
{ tool_identifier = "osint.holehe"; arguments[0] = "--no-color"; }
|
||||
else return;
|
||||
search_target = application_osint_search_target(action_identifier, target_value);
|
||||
arguments[2] = search_target;
|
||||
tool_task = tool_task_new(tool_initializer_get_registry(application->tool_initializer),
|
||||
tool_identifier, "Recherche OSINT", arguments, NULL, &error);
|
||||
if (tool_task == NULL) goto failure;
|
||||
context = g_new0(ApplicationOsintActionContext, 1);
|
||||
context->application = application;
|
||||
context->action_identifier = g_strdup(action_identifier);
|
||||
context->target_identifier = g_strdup(target_identifier);
|
||||
context->target_value = g_strdup(search_target);
|
||||
context->started_at = application_osint_create_timestamp();
|
||||
background_task = tool_task_get_background_task(tool_task);
|
||||
if (context->action_identifier == NULL || context->target_identifier == NULL ||
|
||||
context->target_value == NULL || context->started_at == NULL ||
|
||||
!task_manager_add(application->task_manager, background_task, &error) ||
|
||||
!tool_task_start(tool_task, application_on_osint_search_completed, context,
|
||||
application_osint_action_context_free, &error)) goto failure;
|
||||
context = NULL;
|
||||
main_window_set_status(application->main_window,
|
||||
"Recherche OSINT lancée ; progression disponible dans les tâches.");
|
||||
goto cleanup;
|
||||
failure:
|
||||
application_osint_action_context_free(context);
|
||||
application_present_error(application, "Recherche OSINT impossible",
|
||||
error != NULL ? error->message : "Impossible de démarrer l'outil.");
|
||||
cleanup:
|
||||
g_clear_error(&error); tool_task_free(tool_task); g_free(search_target);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Libère le contexte du dialogue de métadonnées.
|
||||
*/
|
||||
|
|
@ -1678,6 +1824,15 @@ static void application_on_osint_action_requested(
|
|||
return;
|
||||
}
|
||||
|
||||
if (g_strcmp0(action_identifier, "social-username-sherlock") == 0 ||
|
||||
g_strcmp0(action_identifier, "social-username-maigret") == 0 ||
|
||||
g_strcmp0(action_identifier, "email-account-holehe") == 0)
|
||||
{
|
||||
application_start_osint_search(application, action_identifier,
|
||||
target_identifier, target_value);
|
||||
return;
|
||||
}
|
||||
|
||||
application_present_error(
|
||||
application,
|
||||
"Action OSINT inconnue",
|
||||
|
|
@ -7555,6 +7710,36 @@ static void application_on_activate(
|
|||
);
|
||||
}
|
||||
|
||||
/** @brief Ajoute le répertoire privé des outils OSINT au PATH du processus. */
|
||||
static void application_prepare_osint_tool_path(void)
|
||||
{
|
||||
const char *current_path = g_getenv("PATH");
|
||||
const char *home_directory = g_get_home_dir();
|
||||
char *osint_directory = NULL;
|
||||
char *new_path = NULL;
|
||||
|
||||
if (home_directory == NULL || home_directory[0] == '\0') return;
|
||||
osint_directory = g_build_filename(home_directory, ".local", "share",
|
||||
"labfy-osint", "bin", NULL);
|
||||
if (!g_file_test(osint_directory, G_FILE_TEST_IS_DIR))
|
||||
{
|
||||
g_free(osint_directory);
|
||||
return;
|
||||
}
|
||||
if (current_path != NULL && g_strstr_len(current_path, -1,
|
||||
osint_directory) != NULL)
|
||||
{
|
||||
g_free(osint_directory);
|
||||
return;
|
||||
}
|
||||
new_path = g_strdup_printf("%s%s%s", osint_directory,
|
||||
current_path != NULL && current_path[0] != '\0' ? G_SEARCHPATH_SEPARATOR_S :
|
||||
"", current_path != NULL ? current_path : "");
|
||||
g_setenv("PATH", new_path, TRUE);
|
||||
g_free(new_path);
|
||||
g_free(osint_directory);
|
||||
}
|
||||
|
||||
Application *application_new(void)
|
||||
{
|
||||
Application *application = NULL;
|
||||
|
|
@ -7565,6 +7750,8 @@ Application *application_new(void)
|
|||
1
|
||||
);
|
||||
|
||||
application_prepare_osint_tool_path();
|
||||
|
||||
application->task_manager =
|
||||
task_manager_new();
|
||||
|
||||
|
|
|
|||
|
|
@ -84,6 +84,21 @@ static const char *const tool_catalog_qpdf_version_arguments[] =
|
|||
"--version",
|
||||
NULL
|
||||
};
|
||||
static const char *const tool_catalog_sherlock_version_arguments[] =
|
||||
{
|
||||
"--version",
|
||||
NULL
|
||||
};
|
||||
static const char *const tool_catalog_maigret_version_arguments[] =
|
||||
{
|
||||
"--version",
|
||||
NULL
|
||||
};
|
||||
static const char *const tool_catalog_holehe_version_arguments[] =
|
||||
{
|
||||
"--version",
|
||||
NULL
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Catalogue statique initial.
|
||||
|
|
@ -174,6 +189,30 @@ static const ToolCatalogEntry tool_catalog_entries[] =
|
|||
.requirement = TOOL_REQUIREMENT_OPTIONAL,
|
||||
.version_arguments = tool_catalog_qpdf_version_arguments,
|
||||
.version_argument_count = 1
|
||||
},
|
||||
{
|
||||
.identifier = "osint.sherlock",
|
||||
.display_name = "Sherlock",
|
||||
.executable_name = "sherlock",
|
||||
.requirement = TOOL_REQUIREMENT_OPTIONAL,
|
||||
.version_arguments = tool_catalog_sherlock_version_arguments,
|
||||
.version_argument_count = 1
|
||||
},
|
||||
{
|
||||
.identifier = "osint.maigret",
|
||||
.display_name = "Maigret",
|
||||
.executable_name = "maigret",
|
||||
.requirement = TOOL_REQUIREMENT_OPTIONAL,
|
||||
.version_arguments = tool_catalog_maigret_version_arguments,
|
||||
.version_argument_count = 1
|
||||
},
|
||||
{
|
||||
.identifier = "osint.holehe",
|
||||
.display_name = "Holehe (vérification email)",
|
||||
.executable_name = "holehe",
|
||||
.requirement = TOOL_REQUIREMENT_OPTIONAL,
|
||||
.version_arguments = tool_catalog_holehe_version_arguments,
|
||||
.version_argument_count = 1
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -75,6 +75,9 @@ OsintActionCatalog *osint_action_catalog_new_defaults(void)
|
|||
OsintActionCatalog *catalog = g_try_new0(OsintActionCatalog, 1);
|
||||
OsintAction *demonstration_action = NULL;
|
||||
OsintAction *dns_action = NULL;
|
||||
OsintAction *sherlock_action = NULL;
|
||||
OsintAction *maigret_action = NULL;
|
||||
OsintAction *holehe_action = NULL;
|
||||
if (catalog == NULL) return NULL;
|
||||
catalog->actions = g_ptr_array_new_with_free_func(osint_action_free);
|
||||
demonstration_action = osint_action_new(
|
||||
|
|
@ -88,16 +91,41 @@ OsintActionCatalog *osint_action_catalog_new_defaults(void)
|
|||
OSINT_SELECTION_CONTEXT_KIND_ENTITY, "domain_name", "dns.dig", FALSE,
|
||||
"L'outil requis n'a pas encore été vérifié."
|
||||
);
|
||||
sherlock_action = osint_action_new(
|
||||
"social-username-sherlock", "Rechercher le pseudo (Sherlock)",
|
||||
"Recherche des profils publics correspondant au pseudo sélectionné.",
|
||||
OSINT_SELECTION_CONTEXT_KIND_ENTITY, "social_account", "osint.sherlock",
|
||||
FALSE, "L'outil requis n'a pas encore été vérifié."
|
||||
);
|
||||
maigret_action = osint_action_new(
|
||||
"social-username-maigret", "Rechercher le pseudo (Maigret)",
|
||||
"Recherche complémentaire de profils publics par pseudo.",
|
||||
OSINT_SELECTION_CONTEXT_KIND_ENTITY, "social_account", "osint.maigret",
|
||||
FALSE, "L'outil requis n'a pas encore été vérifié."
|
||||
);
|
||||
holehe_action = osint_action_new(
|
||||
"email-account-holehe", "Rechercher l'email (Holehe)",
|
||||
"Vérification publique optionnelle des services associés à l'email.",
|
||||
OSINT_SELECTION_CONTEXT_KIND_ENTITY, "email_address", "osint.holehe",
|
||||
FALSE, "L'outil requis n'a pas encore été vérifié."
|
||||
);
|
||||
if (catalog->actions == NULL || demonstration_action == NULL ||
|
||||
dns_action == NULL)
|
||||
dns_action == NULL || sherlock_action == NULL || maigret_action == NULL ||
|
||||
holehe_action == NULL)
|
||||
{
|
||||
osint_action_free(demonstration_action);
|
||||
osint_action_free(dns_action);
|
||||
osint_action_free(sherlock_action);
|
||||
osint_action_free(maigret_action);
|
||||
osint_action_free(holehe_action);
|
||||
osint_action_catalog_free(catalog);
|
||||
return NULL;
|
||||
}
|
||||
g_ptr_array_add(catalog->actions, demonstration_action);
|
||||
g_ptr_array_add(catalog->actions, dns_action);
|
||||
g_ptr_array_add(catalog->actions, sherlock_action);
|
||||
g_ptr_array_add(catalog->actions, maigret_action);
|
||||
g_ptr_array_add(catalog->actions, holehe_action);
|
||||
return catalog;
|
||||
}
|
||||
|
||||
|
|
@ -109,6 +137,21 @@ static gint osint_action_compare(gconstpointer first, gconstpointer second)
|
|||
return g_strcmp0((*a)->label, (*b)->label);
|
||||
}
|
||||
|
||||
/** @brief Regroupe les types de comptes sociaux pour les recherches publiques. */
|
||||
static gboolean osint_action_social_type_matches(const char *expected,
|
||||
const char *actual)
|
||||
{
|
||||
gboolean expected_social = g_strcmp0(expected, "social_account") == 0;
|
||||
gboolean actual_social = actual != NULL &&
|
||||
(g_strcmp0(actual, "social_account") == 0 ||
|
||||
g_strcmp0(actual, "instagram_account") == 0 ||
|
||||
g_strcmp0(actual, "tiktok_account") == 0 ||
|
||||
g_strcmp0(actual, "facebook_account") == 0 ||
|
||||
g_strcmp0(actual, "telegram_account") == 0 ||
|
||||
g_strcmp0(actual, "x_account") == 0);
|
||||
return expected_social && actual_social;
|
||||
}
|
||||
|
||||
GPtrArray *osint_action_catalog_list_compatible(
|
||||
const OsintActionCatalog *catalog,
|
||||
const OsintSelectionContext *context
|
||||
|
|
@ -126,9 +169,11 @@ GPtrArray *osint_action_catalog_list_compatible(
|
|||
gboolean kind_matches = action->target_kind ==
|
||||
OSINT_SELECTION_CONTEXT_KIND_UNKNOWN ||
|
||||
action->target_kind == osint_selection_context_get_kind(context);
|
||||
const char *context_type = osint_selection_context_get_type(context);
|
||||
gboolean type_matches = action->compatible_type == NULL ||
|
||||
g_strcmp0(action->compatible_type,
|
||||
osint_selection_context_get_type(context)) == 0;
|
||||
g_strcmp0(action->compatible_type, context_type) == 0 ||
|
||||
osint_action_social_type_matches(action->compatible_type,
|
||||
context_type);
|
||||
if (kind_matches && type_matches)
|
||||
g_ptr_array_add(compatible_actions, action);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ struct EntityDetailsPanel
|
|||
GtkWidget *root_revealer;
|
||||
GtkWidget *frame;
|
||||
GtkWidget *add_relation_button;
|
||||
GtkWidget *osint_button;
|
||||
GtkWidget *close_button;
|
||||
|
||||
GtkWidget *entity_title_label;
|
||||
|
|
@ -40,6 +41,7 @@ struct EntityDetailsPanel
|
|||
GtkWidget *person_evidence_summary_label;
|
||||
|
||||
char *selected_entity_identifier;
|
||||
char *selected_entity_type;
|
||||
|
||||
EntityDetailsPanelCloseCallback close_callback;
|
||||
gpointer close_user_data;
|
||||
|
|
@ -59,7 +61,32 @@ struct EntityDetailsPanel
|
|||
gpointer person_name_user_data;
|
||||
EntityDetailsPanelPersonEvidenceCallback person_evidence_callback;
|
||||
gpointer person_evidence_user_data;
|
||||
EntityDetailsPanelOsintCallback osint_callback;
|
||||
gpointer osint_user_data;
|
||||
};
|
||||
|
||||
/** @brief Indique si un type représente un compte social. */
|
||||
static gboolean entity_details_panel_is_social_type(const char *type)
|
||||
{
|
||||
return g_strcmp0(type, "social_account") == 0 ||
|
||||
g_strcmp0(type, "instagram_account") == 0 ||
|
||||
g_strcmp0(type, "tiktok_account") == 0 ||
|
||||
g_strcmp0(type, "facebook_account") == 0 ||
|
||||
g_strcmp0(type, "telegram_account") == 0 ||
|
||||
g_strcmp0(type, "x_account") == 0;
|
||||
}
|
||||
|
||||
/** @brief Transmet la demande de recherche OSINT depuis la fiche. */
|
||||
static void entity_details_panel_on_osint_clicked(GtkButton *button,
|
||||
gpointer user_data)
|
||||
{
|
||||
EntityDetailsPanel *panel = user_data;
|
||||
(void) button;
|
||||
if (panel != NULL && panel->osint_callback != NULL &&
|
||||
panel->selected_entity_identifier != NULL)
|
||||
panel->osint_callback(panel->selected_entity_identifier,
|
||||
panel->osint_user_data);
|
||||
}
|
||||
/** @brief Relaie la demande de gestion des preuves d'une personne. */
|
||||
static void entity_details_panel_on_person_evidence_clicked(GtkButton *button,
|
||||
gpointer user_data)
|
||||
|
|
@ -418,6 +445,8 @@ EntityDetailsPanel *entity_details_panel_new(void)
|
|||
gtk_button_new_from_icon_name(
|
||||
"list-add-symbolic"
|
||||
);
|
||||
details_panel->osint_button = gtk_button_new_from_icon_name(
|
||||
"system-search-symbolic");
|
||||
|
||||
details_panel->close_button =
|
||||
gtk_button_new_from_icon_name(
|
||||
|
|
@ -461,6 +490,7 @@ EntityDetailsPanel *entity_details_panel_new(void)
|
|||
if (details_panel->root_revealer == NULL ||
|
||||
details_panel->frame == NULL ||
|
||||
details_panel->add_relation_button == NULL ||
|
||||
details_panel->osint_button == NULL ||
|
||||
details_panel->close_button == NULL ||
|
||||
content_box == NULL ||
|
||||
header_box == NULL ||
|
||||
|
|
@ -588,6 +618,10 @@ EntityDetailsPanel *entity_details_panel_new(void)
|
|||
details_panel->add_relation_button,
|
||||
"flat"
|
||||
);
|
||||
gtk_widget_set_tooltip_text(details_panel->osint_button,
|
||||
"Recherches OSINT compatibles");
|
||||
gtk_widget_add_css_class(details_panel->osint_button, "flat");
|
||||
gtk_widget_set_sensitive(details_panel->osint_button, FALSE);
|
||||
|
||||
gtk_widget_set_sensitive(
|
||||
details_panel->add_relation_button,
|
||||
|
|
@ -609,6 +643,8 @@ EntityDetailsPanel *entity_details_panel_new(void)
|
|||
header_label
|
||||
);
|
||||
|
||||
gtk_box_append(GTK_BOX(header_box), details_panel->osint_button);
|
||||
|
||||
gtk_box_append(
|
||||
GTK_BOX(header_box),
|
||||
details_panel->add_relation_button
|
||||
|
|
@ -880,6 +916,9 @@ EntityDetailsPanel *entity_details_panel_new(void)
|
|||
details_panel->frame
|
||||
);
|
||||
|
||||
g_signal_connect(
|
||||
details_panel->osint_button, "clicked",
|
||||
G_CALLBACK(entity_details_panel_on_osint_clicked), details_panel);
|
||||
g_signal_connect(
|
||||
details_panel->add_relation_button,
|
||||
"clicked",
|
||||
|
|
@ -937,6 +976,7 @@ void entity_details_panel_set_entity(
|
|||
&details_panel->selected_entity_identifier,
|
||||
g_free
|
||||
);
|
||||
g_clear_pointer(&details_panel->selected_entity_type, g_free);
|
||||
|
||||
if (entity_record == NULL)
|
||||
{
|
||||
|
|
@ -953,6 +993,12 @@ void entity_details_panel_set_entity(
|
|||
entity_record
|
||||
)
|
||||
);
|
||||
details_panel->selected_entity_type = g_strdup(
|
||||
entity_record_get_type_identifier(entity_record));
|
||||
gtk_widget_set_sensitive(details_panel->osint_button,
|
||||
details_panel->osint_callback != NULL &&
|
||||
(g_strcmp0(details_panel->selected_entity_type, "email_address") == 0 ||
|
||||
entity_details_panel_is_social_type(details_panel->selected_entity_type)));
|
||||
|
||||
gboolean is_person = g_strcmp0(entity_record_get_type_identifier(
|
||||
entity_record), "person") == 0;
|
||||
|
|
@ -1098,6 +1144,9 @@ void entity_details_panel_clear(
|
|||
&details_panel->selected_entity_identifier,
|
||||
g_free
|
||||
);
|
||||
g_clear_pointer(&details_panel->selected_entity_type, g_free);
|
||||
if (details_panel->osint_button != NULL)
|
||||
gtk_widget_set_sensitive(details_panel->osint_button, FALSE);
|
||||
|
||||
entity_details_panel_update_add_relation_button(
|
||||
details_panel
|
||||
|
|
@ -1246,6 +1295,18 @@ void entity_details_panel_set_person_evidence_callback(
|
|||
details_panel->person_evidence_callback = callback;
|
||||
details_panel->person_evidence_user_data = user_data;
|
||||
}
|
||||
void entity_details_panel_set_osint_callback(EntityDetailsPanel *details_panel,
|
||||
EntityDetailsPanelOsintCallback callback, gpointer user_data)
|
||||
{
|
||||
if (details_panel == NULL) return;
|
||||
details_panel->osint_callback = callback;
|
||||
details_panel->osint_user_data = user_data;
|
||||
if (details_panel->osint_button != NULL)
|
||||
gtk_widget_set_sensitive(details_panel->osint_button,
|
||||
callback != NULL && details_panel->selected_entity_type != NULL &&
|
||||
(g_strcmp0(details_panel->selected_entity_type, "email_address") == 0 ||
|
||||
entity_details_panel_is_social_type(details_panel->selected_entity_type)));
|
||||
}
|
||||
void entity_details_panel_set_person_evidences(EntityDetailsPanel *panel,
|
||||
const GPtrArray *records)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -444,6 +444,18 @@ static void workspace_update_osint_tools_menu(
|
|||
g_clear_pointer(&compatible_actions, g_ptr_array_unref);
|
||||
}
|
||||
|
||||
/** @brief Ouvre le menu OSINT depuis le bouton de la fiche entité. */
|
||||
static void workspace_on_entity_osint_requested(const char *entity_identifier,
|
||||
gpointer user_data)
|
||||
{
|
||||
Workspace *workspace = user_data;
|
||||
(void) entity_identifier;
|
||||
if (workspace == NULL || workspace->osint_tools_popover == NULL) return;
|
||||
workspace_update_osint_tools_menu(workspace,
|
||||
workspace->osint_selection_context);
|
||||
gtk_popover_popup(GTK_POPOVER(workspace->osint_tools_popover));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Ajoute une ligne de métadonnée dans la grille.
|
||||
*
|
||||
|
|
@ -1945,6 +1957,8 @@ Workspace *workspace_new(void)
|
|||
entity_details_panel_set_person_evidence_callback(
|
||||
workspace->entity_details_panel,
|
||||
workspace_on_person_evidence_requested, workspace);
|
||||
entity_details_panel_set_osint_callback(workspace->entity_details_panel,
|
||||
workspace_on_entity_osint_requested, workspace);
|
||||
|
||||
gtk_overlay_set_child(
|
||||
GTK_OVERLAY(
|
||||
|
|
|
|||
|
|
@ -50,6 +50,34 @@ static void test_non_domain_actions(void)
|
|||
osint_action_catalog_free(catalog);
|
||||
}
|
||||
|
||||
static void test_social_and_email_actions(void)
|
||||
{
|
||||
OsintActionCatalog *catalog = osint_action_catalog_new_defaults();
|
||||
OsintSelectionContext *social = create_entity_context("social_account");
|
||||
OsintSelectionContext *email = create_entity_context("email_address");
|
||||
OsintSelectionContext *instagram = create_entity_context("instagram_account");
|
||||
OsintSelectionContext *facebook = create_entity_context("facebook_account");
|
||||
GPtrArray *actions = osint_action_catalog_list_compatible(catalog, social);
|
||||
GPtrArray *email_actions = osint_action_catalog_list_compatible(catalog, email);
|
||||
GPtrArray *instagram_actions = osint_action_catalog_list_compatible(catalog, instagram);
|
||||
GPtrArray *facebook_actions = osint_action_catalog_list_compatible(catalog, facebook);
|
||||
g_assert_cmpuint(actions->len, ==, 3U);
|
||||
g_assert_cmpuint(email_actions->len, ==, 2U);
|
||||
g_assert_cmpuint(instagram_actions->len, ==, 3U);
|
||||
g_assert_cmpuint(facebook_actions->len, ==, 3U);
|
||||
g_assert_cmpstr(osint_action_get_identifier(g_ptr_array_index(email_actions, 1)),
|
||||
==, "email-account-holehe");
|
||||
g_ptr_array_unref(actions);
|
||||
g_ptr_array_unref(email_actions);
|
||||
g_ptr_array_unref(instagram_actions);
|
||||
g_ptr_array_unref(facebook_actions);
|
||||
osint_selection_context_free(social);
|
||||
osint_selection_context_free(email);
|
||||
osint_selection_context_free(instagram);
|
||||
osint_selection_context_free(facebook);
|
||||
osint_action_catalog_free(catalog);
|
||||
}
|
||||
|
||||
static void test_invalid_arguments(void)
|
||||
{
|
||||
OsintActionCatalog *catalog = osint_action_catalog_new_defaults();
|
||||
|
|
@ -92,6 +120,7 @@ int main(int argc, char **argv)
|
|||
g_test_init(&argc, &argv, NULL);
|
||||
g_test_add_func("/osint-action-catalog/domain", test_domain_actions);
|
||||
g_test_add_func("/osint-action-catalog/non-domain", test_non_domain_actions);
|
||||
g_test_add_func("/osint-action-catalog/social-email", test_social_and_email_actions);
|
||||
g_test_add_func("/osint-action-catalog/invalid", test_invalid_arguments);
|
||||
g_test_add_func("/osint-action-catalog/tool-states", test_tool_states);
|
||||
return g_test_run();
|
||||
|
|
|
|||
|
|
@ -86,6 +86,24 @@ static const ExpectedToolCatalogEntry expected_catalog_entries[] =
|
|||
.display_name = "qpdf",
|
||||
.executable_name = "qpdf",
|
||||
.version_argument = "--version"
|
||||
},
|
||||
{
|
||||
.identifier = "osint.sherlock",
|
||||
.display_name = "Sherlock",
|
||||
.executable_name = "sherlock",
|
||||
.version_argument = "--version"
|
||||
},
|
||||
{
|
||||
.identifier = "osint.maigret",
|
||||
.display_name = "Maigret",
|
||||
.executable_name = "maigret",
|
||||
.version_argument = "--version"
|
||||
},
|
||||
{
|
||||
.identifier = "osint.holehe",
|
||||
.display_name = "Holehe (vérification email)",
|
||||
.executable_name = "holehe",
|
||||
.version_argument = "--version"
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue