diff --git a/CMakeLists.txt b/CMakeLists.txt index cb44e7e..6815851 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -40,7 +40,7 @@ set(SOURCES src/ncurses/column_select_win.c src/ncurses/filter_win.c src/ncurses/msg_diff_win.c - src/ncurses/ui_save.c + src/ncurses/save_win.c src/ncurses/ui_settings.c src/ncurses/stats_win.c src/ncurses/window.c diff --git a/src/capture/capture.c b/src/capture/capture.c index 5a03a48..ee92814 100644 --- a/src/capture/capture.c +++ b/src/capture/capture.c @@ -270,4 +270,10 @@ guint capture_sources_count(CaptureManager *manager) { return g_slist_length(manager->inputs); -} \ No newline at end of file +} + +void +capture_manager_set_pause(CaptureManager *manager, gboolean paused) +{ + manager->paused = paused; +} diff --git a/src/capture/capture.h b/src/capture/capture.h index 3144184..b8a508d 100644 --- a/src/capture/capture.h +++ b/src/capture/capture.h @@ -282,4 +282,10 @@ capture_tls_server(CaptureManager *manager); guint capture_sources_count(CaptureManager *manager); +/** + * @brief Set pause status in given capture manager + */ +void +capture_manager_set_pause(CaptureManager *manager, gboolean paused); + #endif diff --git a/src/ncurses/call_flow_win.c b/src/ncurses/call_flow_win.c index 79c3e7a..349df5c 100644 --- a/src/ncurses/call_flow_win.c +++ b/src/ncurses/call_flow_win.c @@ -36,7 +36,7 @@ #include "ncurses/call_flow_win.h" #include "ncurses/call_raw_win.h" #include "ncurses/msg_diff_win.h" -#include "ncurses/ui_save.h" +#include "ncurses/save_win.h" #include "timeval.h" #include "glib-utils.h" #include "option.h" diff --git a/src/ncurses/call_list_win.c b/src/ncurses/call_list_win.c index 981e0ea..3d43a40 100644 --- a/src/ncurses/call_list_win.c +++ b/src/ncurses/call_list_win.c @@ -46,7 +46,7 @@ #include "ncurses/call_raw_win.h" #include "ncurses/stats_win.h" #include "ncurses/filter_win.h" -#include "ncurses/ui_save.h" +#include "ncurses/save_win.h" #include "storage.h" #include "column_select_win.h" diff --git a/src/ncurses/call_raw_win.c b/src/ncurses/call_raw_win.c index 35212ad..f8e8088 100644 --- a/src/ncurses/call_raw_win.c +++ b/src/ncurses/call_raw_win.c @@ -34,7 +34,7 @@ #include #include "ncurses/manager.h" #include "ncurses/call_raw_win.h" -#include "ncurses/ui_save.h" +#include "ncurses/save_win.h" #include "capture/capture_pcap.h" #include "packet/dissectors/packet_sip.h" @@ -246,7 +246,6 @@ call_raw_move_down(Window *window, guint times) static int call_raw_handle_key(Window *window, int key) { - Window *next_ui; guint rnpag_steps = (guint) setting_get_intvalue(SETTING_CR_SCROLLSTEP); int action = -1; @@ -281,9 +280,8 @@ call_raw_handle_key(Window *window, int key) break; } if (info->group) { - // KEY_S, Display save panel - next_ui = ncurses_create_window(WINDOW_SAVE); - save_set_group(next_ui, info->group); + // Display save panel + save_set_group(ncurses_create_window(WINDOW_SAVE), info->group); } break; case ACTION_TOGGLE_SYNTAX: diff --git a/src/ncurses/manager.c b/src/ncurses/manager.c index 0419149..8b0e973 100644 --- a/src/ncurses/manager.c +++ b/src/ncurses/manager.c @@ -43,7 +43,7 @@ #include "ncurses/msg_diff_win.h" #include "ncurses/column_select_win.h" #include "ncurses/stats_win.h" -#include "ncurses/ui_save.h" +#include "ncurses/save_win.h" #include "ncurses/ui_settings.h" /** @@ -224,6 +224,9 @@ ncurses_find_by_type(enum WindowTypes type) case WINDOW_MSG_DIFF: window = msg_diff_win_new(); break; + case WINDOW_SAVE: + window = save_win_new(); + break; default: break; } diff --git a/src/ncurses/ui_save.c b/src/ncurses/save_win.c similarity index 70% rename from src/ncurses/ui_save.c rename to src/ncurses/save_win.c index 733d958..0d38fb4 100644 --- a/src/ncurses/ui_save.c +++ b/src/ncurses/save_win.c @@ -20,10 +20,10 @@ ** ****************************************************************************/ /** - * @file ui_save_pcap.c + * @file save_win.c * @author Ivan Alonso [aka Kaian] * - * @brief Source of functions defined in ui_save_pcap.c + * @brief Source of functions defined in save_win.h */ #include "config.h" #include @@ -35,219 +35,76 @@ #include #include #include "glib-utils.h" -#include "ui_save.h" +#include "save_win.h" #include "setting.h" #include "capture/capture_pcap.h" #include "capture/capture_txt.h" #include "filter.h" + /** - * Ui Structure definition for Save panel + * @brief Get custom information of given panel + * + * Return ncurses users pointer of the given panel into panel's + * information structure pointer. + * + * @param window UI structure pointer + * @return a pointer to info structure of given panel */ -Window ui_save = { - .type = WINDOW_SAVE, - .panel = NULL, - .create = save_create, - .draw = save_draw, - .handle_key = save_handle_key, - .destroy = save_destroy -}; - -void -save_create(Window *ui) +static SaveWinInfo * +save_info(Window *window) { - save_info_t *info; - char savepath[MAX_SETTING_LEN]; - - // Pause the capture while saving - capture_manager()->paused = TRUE; - - // Cerate a new indow for the panel and form - window_init(ui, 15, 68); - - // Initialize save panel specific data - info = g_malloc0(sizeof(save_info_t)); - - // Store it into panel userptr - set_panel_userptr(ui->panel, (void*) info); - - // Initialize the fields int total, displayed; - - info->fields[FLD_SAVE_PATH] = new_field(1, 52, 3, 13, 0, 0); - info->fields[FLD_SAVE_FILE] = new_field(1, 47, 4, 13, 0, 0); - info->fields[FLD_SAVE_ALL] = new_field(1, 1, 7, 4, 0, 0); - info->fields[FLD_SAVE_SELECTED] = new_field(1, 1, 8, 4, 0, 0); - info->fields[FLD_SAVE_DISPLAYED] = new_field(1, 1, 9, 4, 0, 0); - info->fields[FLD_SAVE_MESSAGE] = new_field(1, 1, 10, 4, 0, 0); - info->fields[FLD_SAVE_PCAP] = new_field(1, 1, 7, 36, 0, 0); - info->fields[FLD_SAVE_PCAP_RTP] = new_field(1, 1, 8, 36, 0, 0); - info->fields[FLD_SAVE_TXT] = new_field(1, 1, 9, 36, 0, 0); - info->fields[FLD_SAVE_SAVE] = new_field(1, 10, ui->height - 2, 20, 0, 0); - info->fields[FLD_SAVE_CANCEL] = new_field(1, 10, ui->height - 2, 40, 0, 0); - info->fields[FLD_SAVE_COUNT] = NULL; - - // Set fields options - field_opts_off(info->fields[FLD_SAVE_PATH], O_STATIC); - field_opts_off(info->fields[FLD_SAVE_PATH], O_AUTOSKIP); - field_opts_off(info->fields[FLD_SAVE_FILE], O_STATIC); - field_opts_off(info->fields[FLD_SAVE_FILE], O_AUTOSKIP); - field_opts_off(info->fields[FLD_SAVE_ALL], O_AUTOSKIP); - field_opts_off(info->fields[FLD_SAVE_SELECTED], O_AUTOSKIP); - field_opts_off(info->fields[FLD_SAVE_DISPLAYED], O_AUTOSKIP); - field_opts_off(info->fields[FLD_SAVE_MESSAGE], O_VISIBLE); - - // Limit max save path and file length - set_max_field(info->fields[FLD_SAVE_PATH], MAX_SETTING_LEN); - set_max_field(info->fields[FLD_SAVE_FILE], MAX_SETTING_LEN); - - // Change background of input fields - set_field_back(info->fields[FLD_SAVE_PATH], A_UNDERLINE); - set_field_back(info->fields[FLD_SAVE_FILE], A_UNDERLINE); - - // Disable Save RTP if RTP packets are not being captured - if (!setting_enabled(SETTING_CAPTURE_RTP)) - field_opts_off(info->fields[FLD_SAVE_PCAP_RTP], O_ACTIVE); - - // Create the form and post it - info->form = new_form(info->fields); - set_form_sub(info->form, ui->win); - post_form(info->form); - form_opts_off(info->form, O_BS_OVERLOAD); - - // Set Default field values - sprintf(savepath, "%s", setting_get_value(SETTING_SAVEPATH)); - - set_field_buffer(info->fields[FLD_SAVE_PATH], 0, savepath); - set_field_buffer(info->fields[FLD_SAVE_SAVE], 0, "[ Save ]"); - set_field_buffer(info->fields[FLD_SAVE_CANCEL], 0, "[ Cancel ]"); - - // Set window boxes - wattron(ui->win, COLOR_PAIR(CP_BLUE_ON_DEF)); - // Window border - title_foot_box(ui->panel); - - // Header and footer lines - mvwhline(ui->win, ui->height - 3, 1, ACS_HLINE, ui->width - 1); - mvwaddch(ui->win, ui->height - 3, 0, ACS_LTEE); - mvwaddch(ui->win, ui->height - 3, ui->width - 1, ACS_RTEE); - - // Save mode box - mvwaddch(ui->win, 6, 2, ACS_ULCORNER); - mvwhline(ui->win, 6, 3, ACS_HLINE, 30); - mvwaddch(ui->win, 6, 32, ACS_URCORNER); - mvwvline(ui->win, 7, 2, ACS_VLINE, 4); - mvwvline(ui->win, 7, 32, ACS_VLINE, 4); - mvwaddch(ui->win, 11, 2, ACS_LLCORNER); - mvwhline(ui->win, 11, 3, ACS_HLINE, 30); - mvwaddch(ui->win, 11, 32, ACS_LRCORNER); - - // Save mode box - mvwaddch(ui->win, 6, 34, ACS_ULCORNER); - mvwhline(ui->win, 6, 35, ACS_HLINE, 30); - mvwaddch(ui->win, 6, 64, ACS_URCORNER); - mvwvline(ui->win, 7, 34, ACS_VLINE, 3); - mvwvline(ui->win, 7, 64, ACS_VLINE, 3); - mvwaddch(ui->win, 10, 34, ACS_LLCORNER); - mvwhline(ui->win, 10, 35, ACS_HLINE, 30); - mvwaddch(ui->win, 10, 64, ACS_LRCORNER); - - wattroff(ui->win, COLOR_PAIR(CP_BLUE_ON_DEF)); - - // Set screen labels - mvwprintw(ui->win, 1, 27, "Save capture"); - mvwprintw(ui->win, 3, 3, "Path:"); - mvwprintw(ui->win, 4, 3, "Filename:"); - wattron(ui->win, COLOR_PAIR(CP_BLUE_ON_DEF)); - mvwprintw(ui->win, 6, 4, " Dialogs "); - mvwprintw(ui->win, 6, 36, " Format "); - wattroff(ui->win, COLOR_PAIR(CP_BLUE_ON_DEF)); - - // Set default cursor position - set_current_field(info->form, info->fields[FLD_SAVE_FILE]); - form_driver(info->form, REQ_END_LINE); - curs_set(1); - - // Get filter stats - sip_stats_t stats = storage_calls_stats(); - - // Set default save modes - info->savemode = (stats.displayed == stats.total) ? SAVE_ALL : SAVE_DISPLAYED; - info->saveformat = (setting_enabled(SETTING_CAPTURE_RTP))? SAVE_PCAP_RTP : SAVE_PCAP; - + return (SaveWinInfo*) panel_userptr(window->panel); } -void -save_destroy(Window *ui) -{ - save_info_t *info; - int i; - - // Get panel information - if ((info = save_info(ui))) { - // Remove panel form and fields - unpost_form(info->form); - free_form(info->form); - for (i = 0; i < FLD_SAVE_COUNT; i++) - free_field(info->fields[i]); - - // Remove panel window and custom info - g_free(info); - } - - // Delete panel - window_deinit(ui); - - // Resume capture - capture_manager()->paused = FALSE; - - // Disable cursor position - curs_set(0); -} - -save_info_t * -save_info(Window *ui) -{ - return (save_info_t*) panel_userptr(ui->panel); -} - -int -save_draw(Window *ui) +/** + * @brief Draw the Save panel + * + * This function will drawn the panel into the screen based on its stored + * status + * + * @param window UI structure pointer + * @return 0 if the panel has been drawn, -1 otherwise + */ +static int +save_draw(Window *window) { char field_value[MAX_SETTING_LEN]; // Get panel information - save_info_t *info = save_info(ui); + SaveWinInfo *info = save_info(window); + g_return_val_if_fail(info != NULL, -1); // Get filter stats sip_stats_t stats = storage_calls_stats(); - mvwprintw(ui->win, 7, 3, "( ) all dialogs "); - mvwprintw(ui->win, 8, 3, "( ) selected dialogs [%d]", call_group_count(info->group)); - mvwprintw(ui->win, 9, 3, "( ) filtered dialogs [%d]", stats.displayed); + mvwprintw(window->win, 7, 3, "( ) all dialogs "); + mvwprintw(window->win, 8, 3, "( ) selected dialogs [%d]", call_group_count(info->group)); + mvwprintw(window->win, 9, 3, "( ) filtered dialogs [%d]", stats.displayed); // Print 'current SIP message' field label if required if (info->msg != NULL) - mvwprintw(ui->win, 10, 3, "( ) current SIP message"); + mvwprintw(window->win, 10, 3, "( ) current SIP message"); - mvwprintw(ui->win, 7, 35, "( ) .pcap (SIP)"); - mvwprintw(ui->win, 8, 35, "( ) .pcap (SIP + RTP)"); - mvwprintw(ui->win, 9, 35, "( ) .txt"); + mvwprintw(window->win, 7, 35, "( ) .pcap (SIP)"); + mvwprintw(window->win, 8, 35, "( ) .pcap (SIP + RTP)"); + mvwprintw(window->win, 9, 35, "( ) .txt"); // Get filename field value. memset(field_value, 0, sizeof(field_value)); strcpy(field_value, field_buffer(info->fields[FLD_SAVE_FILE], 0)); g_strstrip(field_value); - mvwprintw(ui->win, 4, 60, " "); + mvwprintw(window->win, 4, 60, " "); if (strstr(field_value, ".pcap")) { info->saveformat = (setting_enabled(SETTING_CAPTURE_RTP))? SAVE_PCAP_RTP : SAVE_PCAP; } else if (strstr(field_value, ".txt")) { info->saveformat = SAVE_TXT; } else { if (info->saveformat == SAVE_PCAP || info->saveformat == SAVE_PCAP_RTP) - mvwprintw(ui->win, 4, 60, ".pcap"); + mvwprintw(window->win, 4, 60, ".pcap"); else - mvwprintw(ui->win, 4, 60, ".txt "); + mvwprintw(window->win, 4, 60, ".txt "); } set_field_buffer(info->fields[FLD_SAVE_ALL], 0, (info->savemode == SAVE_ALL) ? "*" : " "); @@ -271,145 +128,26 @@ save_draw(Window *ui) return 0; } -int -save_handle_key(Window *ui, int key) +/** + * @brief Callback function to save a single packet into a capture output + */ +static void +save_packet_cb(Packet *packet, CaptureOutput *output) { - int field_idx; - int action = -1; - - // Get panel information - save_info_t *info = save_info(ui); - - // Get current field id - field_idx = field_index(current_field(info->form)); - - // Check actions for this key - while ((action = key_find_action(key, action)) != ERR) { - // Check if we handle this action - switch (action) { - case ACTION_PRINTABLE: - if (field_idx == FLD_SAVE_PATH || field_idx == FLD_SAVE_FILE) { - form_driver(info->form, key); - break; - } - continue; - case ACTION_NEXT_FIELD: - form_driver(info->form, REQ_NEXT_FIELD); - form_driver(info->form, REQ_END_LINE); - break; - case ACTION_PREV_FIELD: - form_driver(info->form, REQ_PREV_FIELD); - form_driver(info->form, REQ_END_LINE); - break; - case ACTION_RIGHT: - form_driver(info->form, REQ_RIGHT_CHAR); - break; - case ACTION_LEFT: - form_driver(info->form, REQ_LEFT_CHAR); - break; - case ACTION_BEGIN: - form_driver(info->form, REQ_BEG_LINE); - break; - case ACTION_END: - form_driver(info->form, REQ_END_LINE); - break; - case ACTION_DELETE: - form_driver(info->form, REQ_DEL_CHAR); - break; - case ACTION_BACKSPACE: - form_driver(info->form, REQ_DEL_PREV); - break; - case ACTION_CLEAR: - form_driver(info->form, REQ_CLR_FIELD); - break; - case ACTION_SELECT: - switch (field_idx) { - case FLD_SAVE_ALL: - info->savemode = SAVE_ALL; - break; - case FLD_SAVE_SELECTED: - info->savemode = SAVE_SELECTED; - break; - case FLD_SAVE_DISPLAYED: - info->savemode = SAVE_DISPLAYED; - break; - case FLD_SAVE_MESSAGE: - info->savemode = SAVE_MESSAGE; - break; - case FLD_SAVE_PCAP: - info->saveformat = SAVE_PCAP; - break; - case FLD_SAVE_PCAP_RTP: - info->saveformat = SAVE_PCAP_RTP; - break; - case FLD_SAVE_TXT: - info->saveformat = SAVE_TXT; - break; - case FLD_SAVE_FILE: - form_driver(info->form, key); - break; - default: - break; - } - break; - case ACTION_CONFIRM: - if (field_idx != FLD_SAVE_CANCEL) { - save_to_file(ui); - } - window_destroy(ui); - return KEY_HANDLED; - default: - // Parse next action - continue; - } - - // This panel has handled the key successfully - break; - } - - // Validate all input data - form_driver(info->form, REQ_VALIDATION); - - // Change background and cursor of "button fields" - set_field_back(info->fields[FLD_SAVE_SAVE], A_NORMAL); - set_field_back(info->fields[FLD_SAVE_CANCEL], A_NORMAL); - curs_set(1); - - // Change current field background - field_idx = field_index(current_field(info->form)); - if (field_idx == FLD_SAVE_SAVE || field_idx == FLD_SAVE_CANCEL) { - set_field_back(info->fields[field_idx], A_REVERSE); - curs_set(0); - } - - // Return if this panel has handled or not the key - return (action == ERR) ? KEY_NOT_HANDLED : KEY_HANDLED; + output->write(output, packet); } -void -save_set_group(Window *ui, CallGroup *group) -{ - // Get panel information - save_info_t *info = save_info(ui); - info->group = group; - if (call_group_count(group)) { - info->savemode = SAVE_SELECTED; - } -} - -void -save_set_msg(Window *ui, Message *msg) -{ - // Get panel information - save_info_t *info = save_info(ui); - info->msg = msg; - - // make 'current SIP message' field visible - field_opts_on(info->fields[FLD_SAVE_MESSAGE], O_VISIBLE); -} - -int -save_to_file(Window *ui) +/** + * @brief Save form data to options + * + * Save capture packets to a file based on selected modes on screen + * It will display an error or success dialog before exit + * + * @param window UI structure pointer + * @returns 1 in case of error, 0 otherwise. + */ +static int +save_to_file(Window *window) { char savepath[MAX_SETTING_LEN]; char savefile[MAX_SETTING_LEN]; @@ -422,7 +160,7 @@ save_to_file(Window *ui) GError *error = NULL; // Get panel information - save_info_t *info = save_info(ui); + SaveWinInfo *info = save_info(window); // Get current path field value. memset(savepath, 0, sizeof(savepath)); @@ -502,8 +240,8 @@ save_to_file(Window *ui) for (guint i = 0; i < g_ptr_array_len(calls); i++) { Call *call = g_ptr_array_index(calls, i); // Save SIP message content - for (guint i = 0; i < g_ptr_array_len(call->msgs); i++) { - Message *msg = g_ptr_array_index(call->msgs, i); + for (guint j = 0; j < g_ptr_array_len(call->msgs); j++) { + Message *msg = g_ptr_array_index(call->msgs, j); output->write(output, msg->packet); } } @@ -532,8 +270,8 @@ save_to_file(Window *ui) continue; // Save SIP message content - for (guint i = 0; i < g_ptr_array_len(call->msgs); i++) { - Message * msg = g_ptr_array_index(call->msgs, i); + for (guint j = 0; j < g_ptr_array_len(call->msgs); j++) { + Message * msg = g_ptr_array_index(call->msgs, j); // Update progress bar dialog dialog_progress_set_value(progress, (++cur * 100) / total); g_ptr_array_add(packets, msg->packet); @@ -551,11 +289,7 @@ save_to_file(Window *ui) } g_ptr_array_sort(packets, capture_packet_time_sorter); - - // Save sorted packets - for (guint i = 0; i < g_ptr_array_len(packets); i++) { - output->write(output, g_ptr_array_index(packets, i)); - } + g_ptr_array_foreach(packets, (GFunc) save_packet_cb, output); dialog_progress_destroy(progress); } @@ -565,10 +299,316 @@ save_to_file(Window *ui) // Show success popup if (info->savemode == SAVE_MESSAGE) { - dialog_run("Successfully saved selected SIP message to %s", savefile); + dialog_run("Successfully saved selected SIP message to %s", savefile); } else { - dialog_run("Successfully saved %d dialogs to %s", total, savefile); + dialog_run("Successfully saved %d dialogs to %s", total, savefile); } return 0; } + +/** + * @brief Manage pressed keys for save panel + * + * This function is called by UI manager every time a + * key is pressed. This allow the save panel to manage + * its own keys. + * + * @param window UI structure pointer + * @param key key code + * @return enum @key_handler_ret + */ +static int +save_handle_key(Window *window, int key) +{ + // Get panel information + SaveWinInfo *info = save_info(window); + g_return_val_if_fail(info != NULL, KEY_NOT_HANDLED); + + // Get current field id + gint field_idx = field_index(current_field(info->form)); + + // Check actions for this key + gint action = -1; + while ((action = key_find_action(key, action)) != ERR) { + // Check if we handle this action + switch (action) { + case ACTION_PRINTABLE: + if (field_idx == FLD_SAVE_PATH || field_idx == FLD_SAVE_FILE) { + form_driver(info->form, key); + break; + } + continue; + case ACTION_NEXT_FIELD: + form_driver(info->form, REQ_NEXT_FIELD); + form_driver(info->form, REQ_END_LINE); + break; + case ACTION_PREV_FIELD: + form_driver(info->form, REQ_PREV_FIELD); + form_driver(info->form, REQ_END_LINE); + break; + case ACTION_RIGHT: + form_driver(info->form, REQ_RIGHT_CHAR); + break; + case ACTION_LEFT: + form_driver(info->form, REQ_LEFT_CHAR); + break; + case ACTION_BEGIN: + form_driver(info->form, REQ_BEG_LINE); + break; + case ACTION_END: + form_driver(info->form, REQ_END_LINE); + break; + case ACTION_DELETE: + form_driver(info->form, REQ_DEL_CHAR); + break; + case ACTION_BACKSPACE: + form_driver(info->form, REQ_DEL_PREV); + break; + case ACTION_CLEAR: + form_driver(info->form, REQ_CLR_FIELD); + break; + case ACTION_SELECT: + switch (field_idx) { + case FLD_SAVE_ALL: + info->savemode = SAVE_ALL; + break; + case FLD_SAVE_SELECTED: + info->savemode = SAVE_SELECTED; + break; + case FLD_SAVE_DISPLAYED: + info->savemode = SAVE_DISPLAYED; + break; + case FLD_SAVE_MESSAGE: + info->savemode = SAVE_MESSAGE; + break; + case FLD_SAVE_PCAP: + info->saveformat = SAVE_PCAP; + break; + case FLD_SAVE_PCAP_RTP: + info->saveformat = SAVE_PCAP_RTP; + break; + case FLD_SAVE_TXT: + info->saveformat = SAVE_TXT; + break; + case FLD_SAVE_FILE: + form_driver(info->form, key); + break; + default: + break; + } + break; + case ACTION_CONFIRM: + if (field_idx != FLD_SAVE_CANCEL) { + save_to_file(window); + } + window_destroy(window); + return KEY_HANDLED; + default: + // Parse next action + continue; + } + + // This panel has handled the key successfully + break; + } + + // Validate all input data + form_driver(info->form, REQ_VALIDATION); + + // Change background and cursor of "button fields" + set_field_back(info->fields[FLD_SAVE_SAVE], A_NORMAL); + set_field_back(info->fields[FLD_SAVE_CANCEL], A_NORMAL); + curs_set(1); + + // Change current field background + field_idx = field_index(current_field(info->form)); + if (field_idx == FLD_SAVE_SAVE || field_idx == FLD_SAVE_CANCEL) { + set_field_back(info->fields[field_idx], A_REVERSE); + curs_set(0); + } + + // Return if this panel has handled or not the key + return (action == ERR) ? KEY_NOT_HANDLED : KEY_HANDLED; +} + +void +save_set_group(Window *window, CallGroup *group) +{ + // Get panel information + SaveWinInfo *info = save_info(window); + g_return_if_fail(info != NULL); + g_return_if_fail(group != NULL); + + info->group = group; + if (call_group_count(group)) { + info->savemode = SAVE_SELECTED; + } +} + +void +save_set_msg(Window *window, Message *msg) +{ + // Get panel information + SaveWinInfo *info = save_info(window); + g_return_if_fail(info != NULL); + g_return_if_fail(msg != NULL); + + info->msg = msg; + + // make 'current SIP message' field visible + field_opts_on(info->fields[FLD_SAVE_MESSAGE], O_VISIBLE); +} + +void +save_win_free(Window *window) +{ + SaveWinInfo *info; + int i; + + // Get panel information + if ((info = save_info(window))) { + // Remove panel form and fields + unpost_form(info->form); + free_form(info->form); + for (i = 0; i < FLD_SAVE_COUNT; i++) + free_field(info->fields[i]); + + // Remove panel window and custom info + g_free(info); + } + + // Delete panel + window_deinit(window); + + // Resume capture + capture_manager()->paused = FALSE; + + // Disable cursor position + curs_set(0); +} + +Window * +save_win_new() +{ + Window *window = g_malloc0(sizeof(Window)); + window->type = WINDOW_SAVE; + window->destroy = save_win_free; + window->draw = save_draw; + window->handle_key = save_handle_key; + + // Cerate a new indow for the panel and form + window_init(window, 15, 68); + + // Pause the capture while saving + capture_manager_set_pause(capture_manager(), TRUE); + + // Initialize save panel specific data + SaveWinInfo *info = g_malloc0(sizeof(SaveWinInfo)); + set_panel_userptr(window->panel, (void*) info); + + // Initialize the fields int total, displayed; + info->fields[FLD_SAVE_PATH] = new_field(1, 52, 3, 13, 0, 0); + info->fields[FLD_SAVE_FILE] = new_field(1, 47, 4, 13, 0, 0); + info->fields[FLD_SAVE_ALL] = new_field(1, 1, 7, 4, 0, 0); + info->fields[FLD_SAVE_SELECTED] = new_field(1, 1, 8, 4, 0, 0); + info->fields[FLD_SAVE_DISPLAYED] = new_field(1, 1, 9, 4, 0, 0); + info->fields[FLD_SAVE_MESSAGE] = new_field(1, 1, 10, 4, 0, 0); + info->fields[FLD_SAVE_PCAP] = new_field(1, 1, 7, 36, 0, 0); + info->fields[FLD_SAVE_PCAP_RTP] = new_field(1, 1, 8, 36, 0, 0); + info->fields[FLD_SAVE_TXT] = new_field(1, 1, 9, 36, 0, 0); + info->fields[FLD_SAVE_SAVE] = new_field(1, 10, window->height - 2, 20, 0, 0); + info->fields[FLD_SAVE_CANCEL] = new_field(1, 10, window->height - 2, 40, 0, 0); + info->fields[FLD_SAVE_COUNT] = NULL; + + // Set fields options + field_opts_off(info->fields[FLD_SAVE_PATH], O_STATIC); + field_opts_off(info->fields[FLD_SAVE_PATH], O_AUTOSKIP); + field_opts_off(info->fields[FLD_SAVE_FILE], O_STATIC); + field_opts_off(info->fields[FLD_SAVE_FILE], O_AUTOSKIP); + field_opts_off(info->fields[FLD_SAVE_ALL], O_AUTOSKIP); + field_opts_off(info->fields[FLD_SAVE_SELECTED], O_AUTOSKIP); + field_opts_off(info->fields[FLD_SAVE_DISPLAYED], O_AUTOSKIP); + field_opts_off(info->fields[FLD_SAVE_MESSAGE], O_VISIBLE); + + // Limit max save path and file length + set_max_field(info->fields[FLD_SAVE_PATH], MAX_SETTING_LEN); + set_max_field(info->fields[FLD_SAVE_FILE], MAX_SETTING_LEN); + + // Change background of input fields + set_field_back(info->fields[FLD_SAVE_PATH], A_UNDERLINE); + set_field_back(info->fields[FLD_SAVE_FILE], A_UNDERLINE); + + // Disable Save RTP if RTP packets are not being captured + if (!setting_enabled(SETTING_CAPTURE_RTP)) + field_opts_off(info->fields[FLD_SAVE_PCAP_RTP], O_ACTIVE); + + // Create the form and post it + info->form = new_form(info->fields); + set_form_sub(info->form, window->win); + post_form(info->form); + form_opts_off(info->form, O_BS_OVERLOAD); + + // Set Default field values + char savepath[MAX_SETTING_LEN]; + sprintf(savepath, "%s", setting_get_value(SETTING_SAVEPATH)); + + set_field_buffer(info->fields[FLD_SAVE_PATH], 0, savepath); + set_field_buffer(info->fields[FLD_SAVE_SAVE], 0, "[ Save ]"); + set_field_buffer(info->fields[FLD_SAVE_CANCEL], 0, "[ Cancel ]"); + + // Set window boxes + wattron(window->win, COLOR_PAIR(CP_BLUE_ON_DEF)); + // Window border + title_foot_box(window->panel); + + // Header and footer lines + mvwhline(window->win, window->height - 3, 1, ACS_HLINE, window->width - 1); + mvwaddch(window->win, window->height - 3, 0, ACS_LTEE); + mvwaddch(window->win, window->height - 3, window->width - 1, ACS_RTEE); + + // Save mode box + mvwaddch(window->win, 6, 2, ACS_ULCORNER); + mvwhline(window->win, 6, 3, ACS_HLINE, 30); + mvwaddch(window->win, 6, 32, ACS_URCORNER); + mvwvline(window->win, 7, 2, ACS_VLINE, 4); + mvwvline(window->win, 7, 32, ACS_VLINE, 4); + mvwaddch(window->win, 11, 2, ACS_LLCORNER); + mvwhline(window->win, 11, 3, ACS_HLINE, 30); + mvwaddch(window->win, 11, 32, ACS_LRCORNER); + + // Save mode box + mvwaddch(window->win, 6, 34, ACS_ULCORNER); + mvwhline(window->win, 6, 35, ACS_HLINE, 30); + mvwaddch(window->win, 6, 64, ACS_URCORNER); + mvwvline(window->win, 7, 34, ACS_VLINE, 3); + mvwvline(window->win, 7, 64, ACS_VLINE, 3); + mvwaddch(window->win, 10, 34, ACS_LLCORNER); + mvwhline(window->win, 10, 35, ACS_HLINE, 30); + mvwaddch(window->win, 10, 64, ACS_LRCORNER); + + wattroff(window->win, COLOR_PAIR(CP_BLUE_ON_DEF)); + + // Set screen labels + mvwprintw(window->win, 1, 27, "Save capture"); + mvwprintw(window->win, 3, 3, "Path:"); + mvwprintw(window->win, 4, 3, "Filename:"); + wattron(window->win, COLOR_PAIR(CP_BLUE_ON_DEF)); + mvwprintw(window->win, 6, 4, " Dialogs "); + mvwprintw(window->win, 6, 36, " Format "); + wattroff(window->win, COLOR_PAIR(CP_BLUE_ON_DEF)); + + // Set default cursor position + set_current_field(info->form, info->fields[FLD_SAVE_FILE]); + form_driver(info->form, REQ_END_LINE); + curs_set(1); + + // Get filter stats + sip_stats_t stats = storage_calls_stats(); + + // Set default save modes + info->savemode = (stats.displayed == stats.total) ? SAVE_ALL : SAVE_DISPLAYED; + info->saveformat = (setting_enabled(SETTING_CAPTURE_RTP))? SAVE_PCAP_RTP : SAVE_PCAP; + + return window; +} diff --git a/src/ncurses/ui_save.h b/src/ncurses/save_win.h similarity index 62% rename from src/ncurses/ui_save.h rename to src/ncurses/save_win.h index 45366fc..ec80196 100644 --- a/src/ncurses/ui_save.h +++ b/src/ncurses/save_win.h @@ -20,18 +20,19 @@ ** ****************************************************************************/ /** - * @file ui_save_pcap.h + * @file save_win.h * @author Ivan Alonso [aka Kaian] * - * @brief Functions to manage ui window for saving captured packages + * @brief Functions to manage ui window for saving captured packets * * This file contains the functions and structures to manage the save * dialog, that can be used to copy the temporal sngrep file to another location * */ -#ifndef __UI_SAVE_PCAP_H -#define __UI_SAVE_PCAP_H +#ifndef __SNGREP_SAVE_WIN_H +#define __SNGREP_SAVE_WIN_H + #include "config.h" #include #include "group.h" @@ -43,7 +44,7 @@ * Dialog form has a field array. Following enum represents the * order this fields are stored in panel info structure. */ -enum save_field_list { +enum SaveWinField { FLD_SAVE_PATH = 0, FLD_SAVE_FILE, FLD_SAVE_ALL, @@ -61,7 +62,7 @@ enum save_field_list { /** * @brief Dialogs to be saved */ -enum save_mode { +enum SaveWinMode { SAVE_ALL = 0, SAVE_SELECTED, SAVE_DISPLAYED, @@ -71,29 +72,29 @@ enum save_mode { /** * @brief Save file formats */ -enum save_format { +enum SaveWinFormat { SAVE_PCAP = 0, SAVE_PCAP_RTP, SAVE_TXT }; //! Sorter declaration of struct save_info -typedef struct save_info save_info_t; +typedef struct _SaveWinInfo SaveWinInfo; /** * @brief Save panel private information * * This structure contains the durable data of save panel. */ -struct save_info { +struct _SaveWinInfo { //! Form that contains the save fields FORM *form; //! An array of fields FIELD *fields[FLD_SAVE_COUNT + 1]; //! Save mode @see save_modes - enum save_mode savemode; + enum SaveWinMode savemode; //! Save format @see save_formats - enum save_format saveformat; + enum SaveWinFormat saveformat; //! Call group to be saved CallGroup *group; //! Message to be saved @@ -108,58 +109,20 @@ struct save_info { * static information of the panel that will never be * redrawn. * - * @param ui UI structure pointer + * @param window UI structure pointer */ -void -save_create(Window *ui); +Window * +save_win_new(); /** * @brief Destroy save panel * * This function do the final cleanups for this panel * - * @param ui UI structure pointer + * @param window UI structure pointer */ void -save_destroy(Window *ui); - -/** - * @brief Get custom information of given panel - * - * Return ncurses users pointer of the given panel into panel's - * information structure pointer. - * - * @param ui UI structure pointer - * @return a pointer to info structure of given panel - */ -save_info_t * -save_info(Window *ui); - -/** - * @brief Draw the Save panel - * - * This function will drawn the panel into the screen based on its stored - * status - * - * @param ui UI structure pointer - * @return 0 if the panel has been drawn, -1 otherwise - */ -int -save_draw(Window *ui); - -/** - * @brief Manage pressed keys for save panel - * - * This function is called by UI manager every time a - * key is pressed. This allow the save panel to manage - * its own keys. - * - * @param ui UI structure pointer - * @param key key code - * @return enum @key_handler_ret - */ -int -save_handle_key(Window *ui, int key); +save_win_free(Window *window); /** * @brief Set the group call of the panel @@ -167,11 +130,11 @@ save_handle_key(Window *ui, int key); * This function will access the panel information and will set the * group call pointer to the selected calls * - * @param ui UI structure pointer + * @param window UI structure pointer * @param group Call group pointer to be set in the internal info struct */ void -save_set_group(Window *ui, CallGroup *group); +save_set_group(Window *window, CallGroup *group); /** * @brief Set the SIP message to be saved @@ -179,33 +142,10 @@ save_set_group(Window *ui, CallGroup *group); * This function will access the panel information and will set the * pointer to the selected SIP message * - * @param ui UI structure pointer + * @param window UI structure pointer * @param msg SIP message pointer to be set in the internal info struct */ void -save_set_msg(Window *ui, Message *msg); - -/** - * @brief Print an error message in Save panel - * - * General function to print any save error message - * - * @param ui UI structure pointer - * @param message Message to be printed in the panel - */ -void -save_error_message(Window *ui, const char *message); - -/** - * @brief Save form data to options - * - * Save capture packets to a file based on selected modes on screen - * It will display an error or success dialog before exit - * - * @param ui UI structure pointer - * @returns 1 in case of error, 0 otherwise. - */ -int -save_to_file(Window *ui); +save_set_msg(Window *window, Message *msg); #endif