aboutsummaryrefslogtreecommitdiffstats
path: root/gtk/find_dlg.c
diff options
context:
space:
mode:
Diffstat (limited to 'gtk/find_dlg.c')
-rw-r--r--gtk/find_dlg.c345
1 files changed, 270 insertions, 75 deletions
diff --git a/gtk/find_dlg.c b/gtk/find_dlg.c
index cbdb97b3b8..c0ca252f1d 100644
--- a/gtk/find_dlg.c
+++ b/gtk/find_dlg.c
@@ -1,7 +1,7 @@
/* find_dlg.c
* Routines for "find frame" window
*
- * $Id: find_dlg.c,v 1.32 2003/08/28 23:25:55 guy Exp $
+ * $Id: find_dlg.c,v 1.33 2003/08/29 04:03:46 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
@@ -22,11 +22,13 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
-
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
+#include <string.h>
+#include <ctype.h>
+
#include <gtk/gtk.h>
#include <epan/proto.h>
@@ -44,17 +46,17 @@
#include "keys.h"
/* Capture callback data keys */
-#define E_FIND_FILT_KEY "find_filter_te"
-#define E_FIND_BACKWARD_KEY "find_backward"
-#define E_FIND_HEXDATA_KEY "find_hex"
-#define E_FIND_ASCIIDATA_KEY "find_ascii"
+#define E_FIND_FILT_KEY "find_filter_te"
+#define E_FIND_BACKWARD_KEY "find_backward"
+#define E_FIND_HEXDATA_KEY "find_hex"
+#define E_FIND_ASCIIDATA_KEY "find_ascii"
#define E_FIND_FILTERDATA_KEY "find_filter"
#define E_FIND_STRINGTYPE_KEY "find_string_type"
-#define E_CASE_SEARCH_KEY "case_insensitive_search"
-#define E_SOURCE_HEX_KEY "hex_data_source"
-#define E_SOURCE_DECODE_KEY "decode_data_source"
-#define E_SOURCE_SUMMARY_KEY "summary_data_source"
-#define E_FILT_TE_BUTTON_KEY "find_filter_button"
+#define E_CASE_SEARCH_KEY "case_insensitive_search"
+#define E_SOURCE_HEX_KEY "hex_data_source"
+#define E_SOURCE_DECODE_KEY "decode_data_source"
+#define E_SOURCE_SUMMARY_KEY "summary_data_source"
+#define E_FILT_TE_BUTTON_KEY "find_filter_button"
static gboolean case_type = TRUE;
static gboolean summary_data = FALSE;
@@ -207,7 +209,6 @@ find_frame_cb(GtkWidget *w _U_, gpointer d _U_)
gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(filter_rb), !cfile.hex && !cfile.ascii);
gtk_box_pack_start(GTK_BOX(hex_hb), filter_rb, TRUE, TRUE, 0);
gtk_tooltips_set_tip (tooltips, filter_rb, ("Search for data by display filter syntax.\ne.g. ip.addr==10.1.1.1"), NULL);
- SIGNAL_CONNECT(filter_rb, "clicked", filter_selected_cb, find_frame_w);
gtk_widget_show(filter_rb);
/* Hex */
@@ -237,7 +238,6 @@ find_frame_cb(GtkWidget *w _U_, gpointer d _U_)
gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(ascii_rb), cfile.ascii);
gtk_box_pack_start(GTK_BOX(hex_hb), ascii_rb, TRUE, TRUE, 0);
gtk_tooltips_set_tip (tooltips, ascii_rb, ("Search for data by string value.\ne.g. My String"), NULL);
- SIGNAL_CONNECT(ascii_rb, "clicked", ascii_selected_cb, find_frame_w);
gtk_widget_show(ascii_rb);
string_window_frame = gtk_frame_new("Search in");
@@ -306,8 +306,8 @@ find_frame_cb(GtkWidget *w _U_, gpointer d _U_)
glist = g_list_append(glist, "ASCII Unicode & Non-Unicode");
glist = g_list_append(glist, "ASCII Non-Unicode");
glist = g_list_append(glist, "ASCII Unicode");
- glist = g_list_append(glist, "EBCDIC");
+ /* XXX - make it non-editable - or make this an option menu instead */
gtk_combo_set_popdown_strings(GTK_COMBO(combo_cb), glist);
gtk_container_border_width(GTK_CONTAINER(combo_cb), 1);
gtk_container_add(GTK_CONTAINER(string_char_frame), combo_cb);
@@ -375,6 +375,14 @@ find_frame_cb(GtkWidget *w _U_, gpointer d _U_)
OBJECT_SET_DATA(find_frame_w, E_SOURCE_SUMMARY_KEY, summary_data_rb);
OBJECT_SET_DATA(find_frame_w, E_FILT_TE_BUTTON_KEY, filter_bt);
+ /*
+ * Now that we've attached the pointers, connect the signals - if
+ * we do so before we've attached the pointers, the signals may
+ * be delivered before the pointers are attached; the signal
+ * handlers expect the pointers to be attached, and won't be happy.
+ */
+ SIGNAL_CONNECT(ascii_rb, "clicked", ascii_selected_cb, find_frame_w);
+ SIGNAL_CONNECT(filter_rb, "clicked", filter_selected_cb, find_frame_w);
ascii_selected_cb(NULL, find_frame_w);
filter_selected_cb(NULL, find_frame_w);
@@ -452,14 +460,118 @@ filter_selected_cb(GtkWidget *button_rb _U_, gpointer parent_w)
return;
}
+static guint8 *
+convert_string_to_hex(const char *string, size_t *nbytes)
+{
+ size_t n_bytes;
+ const char *p;
+ guchar c;
+ guint8 *bytes, *q, byte_val;
+
+ n_bytes = 0;
+ p = &string[0];
+ for (;;) {
+ c = *p++;
+ if (c == '\0')
+ break;
+ if (isspace(c))
+ continue; /* allow white space */
+ if (!isxdigit(c)) {
+ /* Not a valid hex digit - fail */
+ return NULL;
+ }
+
+ /*
+ * We can only match bytes, not nibbles; we must have a valid
+ * hex digit immediately after that hex digit.
+ */
+ c = *p++;
+ if (!isxdigit(c))
+ return NULL;
+
+ /* 2 hex digits = 1 byte */
+ n_bytes++;
+ }
+
+ /*
+ * Were we given any hex digits?
+ */
+ if (n_bytes == 0) {
+ /* No. */
+ return NULL;
+ }
+
+ /*
+ * OK, it's valid, and it generates "n_bytes" bytes; generate the
+ * raw byte array.
+ */
+ bytes = g_malloc(n_bytes);
+ p = &string[0];
+ q = &bytes[0];
+ for (;;) {
+ c = *p++;
+ if (c == '\0')
+ break;
+ if (isspace(c))
+ continue; /* allow white space */
+ /* From the loop above, we know this is a hex digit */
+ if (isdigit(c))
+ byte_val = c - '0';
+ else if (c >= 'a')
+ byte_val = (c - 'a') + 10;
+ else
+ byte_val = (c - 'A') + 10;
+ byte_val <<= 4;
+
+ /* We also know this is a hex digit */
+ c = *p++;
+ if (isdigit(c))
+ byte_val |= c - '0';
+ else if (c >= 'a')
+ byte_val |= (c - 'a') + 10;
+ else if (c >= 'A')
+ byte_val |= (c - 'A') + 10;
+
+ *q++ = byte_val;
+ }
+ *nbytes = n_bytes;
+ return bytes;
+}
+
+static char *
+convert_string_case(const char *string, gboolean case_insensitive)
+{
+ char *out_string;
+ const char *p;
+ char c;
+ char *q;
+
+ /*
+ * Copy if if it's a case-sensitive search; uppercase it if it's
+ * a case-insensitive search.
+ */
+ if (case_insensitive) {
+ out_string = g_malloc(strlen(string) + 1);
+ for (p = &string[0], q = &out_string[0]; (c = *p) != '\0'; p++, q++)
+ *q = toupper((unsigned char)*p);
+ *q = '\0';
+ } else
+ out_string = g_strdup(string);
+ return out_string;
+}
static void
find_frame_ok_cb(GtkWidget *ok_bt _U_, gpointer parent_w)
{
- GtkWidget *filter_te, *backward_rb, *hex_rb, *ascii_rb, *combo_cb, *case_cb,
- *decode_data_rb, *summary_data_rb;
- gchar *filter_text, *string_type;
- dfilter_t *sfcode;
+ GtkWidget *filter_te, *backward_rb, *hex_rb, *ascii_rb, *combo_cb,
+ *case_cb, *decode_data_rb, *summary_data_rb;
+ gchar *filter_text, *string_type;
+ search_charset_t scs_type = SCS_ASCII_AND_UNICODE;
+ guint8 *bytes = NULL;
+ size_t nbytes;
+ char *string = NULL;
+ dfilter_t *sfcode;
+ gboolean found_packet;
filter_te = (GtkWidget *)OBJECT_GET_DATA(parent_w, E_FIND_FILT_KEY);
backward_rb = (GtkWidget *)OBJECT_GET_DATA(parent_w, E_FIND_BACKWARD_KEY);
@@ -478,61 +590,116 @@ find_frame_ok_cb(GtkWidget *ok_bt _U_, gpointer parent_w)
summary_data = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(summary_data_rb));
/*
- * Try to compile the filter.
+ * Process the search criterion.
*/
- if (!dfilter_compile(filter_text, &sfcode) && !GTK_TOGGLE_BUTTON (hex_rb)->active && !GTK_TOGGLE_BUTTON (ascii_rb)->active) {
- /* The attempt failed; report an error. */
- simple_dialog(ESD_TYPE_CRIT, NULL, dfilter_error_msg);
- return;
- }
+ if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (hex_rb))) {
+ /*
+ * Hex search - scan the search string to make sure it's valid hex
+ * and to find out how many bytes there are.
+ */
+ bytes = convert_string_to_hex(filter_text, &nbytes);
+ if (bytes == NULL) {
+ simple_dialog(ESD_TYPE_CRIT, NULL,
+ "You didn't specify a valid hex string.");
+ return;
+ }
+ } else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (ascii_rb))) {
+ /*
+ * String search.
+ * Get the character set type.
+ */
+ if (strcmp(string_type, "ASCII Unicode & Non-Unicode") == 0)
+ scs_type = SCS_ASCII_AND_UNICODE;
+ else if (strcmp(string_type, "ASCII Non-Unicode") == 0)
+ scs_type = SCS_ASCII;
+ else if (strcmp(string_type, "ASCII Unicode") == 0)
+ scs_type = SCS_UNICODE;
+ else {
+ simple_dialog(ESD_TYPE_CRIT, NULL, "You didn't choose a valid character set.");
+ return;
+ }
+ string = convert_string_case(filter_text, case_type);
+ } else {
+ /*
+ * Display filter search - try to compile the filter.
+ */
+ if (!dfilter_compile(filter_text, &sfcode)) {
+ /* The attempt failed; report an error. */
+ simple_dialog(ESD_TYPE_CRIT, NULL, dfilter_error_msg);
+ return;
+ }
- /* Was it empty? */
- if (sfcode == NULL && !GTK_TOGGLE_BUTTON (hex_rb)->active && !GTK_TOGGLE_BUTTON (ascii_rb)->active) {
- /* Yes - complain. */
- simple_dialog(ESD_TYPE_CRIT, NULL,
- "You didn't specify valid search criteria.");
- return;
+ /* Was it empty? */
+ if (sfcode == NULL) {
+ /* Yes - complain. */
+ simple_dialog(ESD_TYPE_CRIT, NULL,
+ "You didn't specify a valid filter expression.");
+ return;
+ }
}
/*
- * Remember the filter.
+ * Remember the search parameters.
*/
if (cfile.sfilter)
g_free(cfile.sfilter);
cfile.sfilter = g_strdup(filter_text);
-
cfile.sbackward = GTK_TOGGLE_BUTTON (backward_rb)->active;
- cfile.hex = GTK_TOGGLE_BUTTON (hex_rb)->active;
- cfile.ascii = GTK_TOGGLE_BUTTON (ascii_rb)->active;
- cfile.ftype = g_strdup(string_type);
-
- if (!GTK_TOGGLE_BUTTON (hex_rb)->active && !GTK_TOGGLE_BUTTON (ascii_rb)->active ) {
- if (!find_packet(&cfile, sfcode)) {
+ cfile.hex = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (hex_rb));
+ cfile.ascii = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (ascii_rb));
+ cfile.scs_type = scs_type;
+ cfile.case_type = case_type;
+ cfile.decode_data = decode_data;
+ cfile.summary_data = summary_data;
+
+ if (cfile.hex) {
+ found_packet = find_packet_data(&cfile, bytes, nbytes);
+ g_free(bytes);
+ if (!found_packet) {
+ /* We didn't find a packet */
+ simple_dialog(ESD_TYPE_CRIT, NULL, "No packet contained those bytes.");
+ g_free(bytes);
+ return;
+ }
+ } else if (cfile.ascii) {
+ /* OK, what are we searching? */
+ if (cfile.decode_data) {
+ /* The text in the protocol tree */
+ found_packet = find_packet_protocol_tree(&cfile, string);
+ g_free(string);
+ if (!found_packet) {
/* We didn't find the packet. */
- simple_dialog(ESD_TYPE_CRIT, NULL, "No packet matched that filter.");
+ simple_dialog(ESD_TYPE_CRIT, NULL, "No packet contained that string in its dissected display.");
return;
}
- }
- else
- {
- if (!decode_data && !summary_data) {
- if (!find_ascii(&cfile, filter_text, cfile.ascii, string_type, case_type)) {
- /* We didn't find the packet. */
- simple_dialog(ESD_TYPE_CRIT, NULL, "No packet matched search criteria.");
- return;
- }
+ } else if (cfile.summary_data) {
+ /* The text in the summary line */
+ found_packet = find_packet_summary_line(&cfile, string);
+ g_free(string);
+ if (!found_packet) {
+ /* We didn't find the packet. */
+ simple_dialog(ESD_TYPE_CRIT, NULL, "No packet contained that string in its Info column.");
+ return;
}
- else
- {
- /* Use the cfile.hex to indicate if summary or decode search */
- /* This way the Next and Previous find options will work */
- cfile.hex = summary_data;
- if (!find_in_gtk_data(&cfile, parent_w, filter_text, case_type, summary_data)) {
- /* We didn't find the packet. */
- simple_dialog(ESD_TYPE_CRIT, NULL, "No packet matched search criteria.");
- return;
- }
+ } else {
+ /* The raw packet data */
+ found_packet = find_packet_data(&cfile, string, strlen(string));
+ g_free(string);
+ if (!found_packet) {
+ /* We didn't find the packet. */
+ simple_dialog(ESD_TYPE_CRIT, NULL, "No packet contained that string in its data.");
+ return;
}
+ }
+ } else {
+ found_packet = find_packet_dfilter(&cfile, sfcode);
+ dfilter_free(sfcode);
+ if (!found_packet) {
+ /* We didn't find a packet */
+ simple_dialog(ESD_TYPE_CRIT, NULL, "No packet matched that filter.");
+ g_free(bytes);
+ return;
+ }
}
gtk_widget_destroy(GTK_WIDGET(parent_w));
}
@@ -554,28 +721,56 @@ find_frame_destroy_cb(GtkWidget *win _U_, gpointer user_data _U_)
static void
find_previous_next(GtkWidget *w, gpointer d, gboolean sens)
{
+ guint8 *bytes;
+ size_t nbytes;
+ char *string;
dfilter_t *sfcode;
-
if (cfile.sfilter) {
- if (!dfilter_compile(cfile.sfilter, &sfcode) && !cfile.hex && !cfile.ascii)
+ cfile.sbackward = sens;
+ if (cfile.hex) {
+ bytes = convert_string_to_hex(cfile.sfilter, &nbytes);
+ if (bytes == NULL) {
+ /*
+ * XXX - this shouldn't happen, as we've already successfully
+ * translated the string once.
+ */
return;
- if (sfcode == NULL && !cfile.hex && !cfile.ascii)
+ }
+ find_packet_data(&cfile, bytes, nbytes);
+ g_free(bytes);
+ } else if (cfile.ascii) {
+ string = convert_string_case(cfile.sfilter, cfile.case_type);
+ /* OK, what are we searching? */
+ if (cfile.decode_data) {
+ /* The text in the protocol tree */
+ find_packet_protocol_tree(&cfile, string);
+ } else if (cfile.summary_data) {
+ /* The text in the summary line */
+ find_packet_summary_line(&cfile, string);
+ } else {
+ /* The raw packet data */
+ find_packet_data(&cfile, string, strlen(string));
+ }
+ g_free(string);
+ } else {
+ if (!dfilter_compile(cfile.sfilter, &sfcode)) {
+ /*
+ * XXX - this shouldn't happen, as we've already successfully
+ * translated the string once.
+ */
return;
- cfile.sbackward = sens;
- if (cfile.hex || cfile.ascii)
- {
- if (!decode_data && !summary_data) {
- find_ascii(&cfile, cfile.sfilter, cfile.ascii, cfile.ftype, case_type);
- }
- else {
- find_in_gtk_data(&cfile, d, cfile.sfilter, case_type, cfile.hex);
- }
- }
- else
- {
- find_packet(&cfile, sfcode);
- }
+ }
+ if (sfcode == NULL) {
+ /*
+ * XXX - this shouldn't happen, as we've already found that the
+ * string wasn't null.
+ */
+ return;
+ }
+ find_packet_dfilter(&cfile, sfcode);
+ dfilter_free(sfcode);
+ }
} else
find_frame_cb(w, d);
}