From Greg Morris: code to support searches for text or raw binary data

in a frame in Find Frame.

svn path=/trunk/; revision=8067
This commit is contained in:
Guy Harris 2003-07-22 23:08:48 +00:00
parent d6ed142549
commit 487d0def6b
5 changed files with 368 additions and 19 deletions

View File

@ -1307,6 +1307,7 @@ Andrew Esh <Andrew.Esh[AT]tricord.com> {
Greg Morris <GMORRIS[AT]novell.com> {
NCP - NetWare Core Protocol
NDPS - Novell Distributed Print System
"Find Frame" code to search for text or binary data
}
Dirk Steinberg <dws[AT]dirksteinberg.de> {

View File

@ -1,7 +1,7 @@
/* cfile.h
* capture_file definition & GUI-independent manipulation
*
* $Id: cfile.h,v 1.1 2002/09/06 23:14:04 sahlberg Exp $
* $Id: cfile.h,v 1.2 2003/07/22 23:08:47 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
@ -65,6 +65,9 @@ typedef struct _capture_file {
#endif
gchar *sfilter; /* Search filter string */
gboolean sbackward; /* TRUE if search is backward, FALSE if forward */
gboolean hex; /* TRUE is Hex search is being performed */
gboolean ascii; /* TRUE is ASCII search is being performed */
char *ftype; /* Find Frame String Type */
union wtap_pseudo_header pseudo_header; /* Packet pseudo_header */
guint8 pd[WTAP_MAX_PACKET_SIZE]; /* Packet data */
GMemChunk *plist_chunk; /* Memory chunk for frame_data structures */

242
file.c
View File

@ -1,7 +1,7 @@
/* file.c
* File I/O routines
*
* $Id: file.c,v 1.299 2003/06/24 06:14:46 guy Exp $
* $Id: file.c,v 1.300 2003/07/22 23:08:47 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
@ -1428,6 +1428,246 @@ change_time_formats(capture_file *cf)
thaw_plist(cf);
}
guint8
get_int_value(char char_val)
{
switch (char_val) {
case 'a':
case 'A':
return(10);
case 'b':
case 'B':
return(11);
case 'c':
case 'C':
return(12);
case 'd':
case 'D':
return(13);
case 'e':
case 'E':
return(14);
case 'f':
case 'F':
return(15);
default:
return(atoi(&char_val));
}
}
gboolean
find_ascii(capture_file *cf, char *ascii_text, gboolean ascii_search, char *ftype)
{
frame_data *start_fd;
frame_data *fdata;
frame_data *new_fd = NULL;
progdlg_t *progbar = NULL;
gboolean stop_flag;
int count;
int err;
guint32 i;
guint16 c_match=0;
gboolean frame_matched;
int row;
float prog_val;
GTimeVal start_time;
gchar status_str[100];
guint8 c_char=0;
guint32 buf_len=0;
guint8 hex_val=0;
char char_val;
guint8 num1, num2;
start_fd = cf->current_frame;
if (start_fd != NULL) {
/* Iterate through the list of packets, starting at the packet we've
picked, calling a routine to run the filter on the packet, see if
it matches, and stop if so. */
count = 0;
fdata = start_fd;
cf->progbar_nextstep = 0;
/* When we reach the value that triggers a progress bar update,
bump that value by this amount. */
cf->progbar_quantum = cf->count/N_PROGBAR_UPDATES;
stop_flag = FALSE;
g_get_current_time(&start_time);
fdata = start_fd;
for (;;) {
/* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
when we update it, we have to run the GTK+ main loop to get it
to repaint what's pending, and doing so may involve an "ioctl()"
to see if there's any pending input from an X server, and doing
that for every packet can be costly, especially on a big file. */
if (count >= cf->progbar_nextstep) {
/* let's not divide by zero. I should never be started
* with count == 0, so let's assert that
*/
g_assert(cf->count > 0);
prog_val = (gfloat) count / cf->count;
/* Create the progress bar if necessary */
if (progbar == NULL)
progbar = delayed_create_progress_dlg("Searching", cf->sfilter, "Cancel",
&stop_flag, &start_time, prog_val);
if (progbar != NULL) {
g_snprintf(status_str, sizeof(status_str),
"%4u of %u frames", count, cf->count);
update_progress_dlg(progbar, prog_val, status_str);
}
cf->progbar_nextstep += cf->progbar_quantum;
}
if (stop_flag) {
/* Well, the user decided to abort the search. Go back to the
frame where we started. */
new_fd = start_fd;
break;
}
/* Go past the current frame. */
if (cf->sbackward) {
/* Go on to the previous frame. */
fdata = fdata->prev;
if (fdata == NULL)
fdata = cf->plist_end; /* wrap around */
} else {
/* Go on to the next frame. */
fdata = fdata->next;
if (fdata == NULL)
fdata = cf->plist; /* wrap around */
}
count++;
/* Is this packet in the display? */
if (fdata->flags.passed_dfilter) {
/* Yes. Does it match the search filter? */
/* XXX - do something with "err" */
wtap_seek_read(cf->wth, fdata->file_off, &cf->pseudo_header,
cf->pd, fdata->cap_len, &err);
frame_matched = FALSE;
buf_len = fdata->pkt_len;
for (i=0;i<buf_len;i++) {
c_char = cf->pd[i];
/* Check to see if this is an String or Hex search */
if (ascii_search) {
/* Now check the String Type */
if(strcmp(ftype,"ASCII Unicode & Non-Unicode")==0)
{
if (c_char != 0) {
if (c_char == ascii_text[c_match]) {
c_match++;
if (c_match == strlen(ascii_text)) {
frame_matched = TRUE;
break;
}
}
else
{
c_match = 0;
}
}
}
else if(strcmp(ftype,"ASCII Non-Unicode")==0)
{
if (c_char == ascii_text[c_match]) {
c_match++;
if (c_match == strlen(ascii_text)) {
frame_matched = TRUE;
break;
}
}
else
{
c_match = 0;
}
}
else if(strcmp(ftype, "ASCII Unicode")==0)
{
if (c_char == ascii_text[c_match]) {
c_match++;
i++;
if (c_match == strlen(ascii_text)) {
frame_matched = TRUE;
break;
}
}
else
{
c_match = 0;
}
}
else if(strcmp(ftype,"EBCDIC")==0)
{
simple_dialog(ESD_TYPE_CRIT, NULL,
"EBCDIC Find Not supported yet.");
return TRUE;
}
else
{
simple_dialog(ESD_TYPE_CRIT, NULL,
"Invalid String type specified.");
return TRUE;
}
}
else /* Hex Search */
{
char_val = ascii_text[c_match];
num1 = get_int_value(char_val);
char_val = ascii_text[++c_match];
num2 = get_int_value(char_val);
hex_val = (num1*0x10)+num2;
if ( c_char == hex_val) {
c_match++;
if (c_match == strlen(ascii_text)) {
frame_matched = TRUE;
break;
}
}
else
{
c_match = 0;
}
}
}
if (frame_matched) {
new_fd = fdata;
break; /* found it! */
}
}
if (fdata == start_fd) {
/* We're back to the frame we were on originally, and that frame
doesn't match the search filter. The search failed. */
break;
}
}
/* We're done scanning the packets; destroy the progress bar if it
was created. */
if (progbar != NULL)
destroy_progress_dlg(progbar);
}
if (new_fd != NULL) {
/* We found a frame. Find what row it's in. */
row = packet_list_find_row_from_data(new_fd);
g_assert(row != -1);
/* Select that row, make it the focus row, and make it visible. */
packet_list_set_selected_row(row);
return TRUE; /* success */
} else
return FALSE; /* failure */
}
gboolean
find_packet(capture_file *cf, dfilter_t *sfcode)
{

6
file.h
View File

@ -1,7 +1,7 @@
/* file.h
* Definitions for file structures and routines
*
* $Id: file.h,v 1.99 2003/03/02 22:07:21 guy Exp $
* $Id: file.h,v 1.100 2003/07/22 23:08:47 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
@ -55,7 +55,9 @@ void colorize_packets(capture_file *);
void redissect_packets(capture_file *cf);
int print_packets(capture_file *cf, print_args_t *print_args);
void change_time_formats(capture_file *);
gboolean find_packet(capture_file *cf, dfilter_t *sfcode);
gboolean find_packet(capture_file *cf, dfilter_t *sfcode);
guint8 get_int_value(char char_val);
gboolean find_ascii(capture_file *cf, char *ascii_text, gboolean ascii_search, char *ftype);
gboolean goto_frame(capture_file *cf, guint fnumber);

View File

@ -1,7 +1,7 @@
/* find_dlg.c
* Routines for "find frame" window
*
* $Id: find_dlg.c,v 1.28 2003/04/24 23:18:07 guy Exp $
* $Id: find_dlg.c,v 1.29 2003/07/22 23:08:48 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
@ -39,10 +39,16 @@
#include "simple_dialog.h"
#include "dlg_utils.h"
#include "compat_macros.h"
#include "prefs.h"
#include "prefs_dlg.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_FILTERDATA_KEY "find_filter"
#define E_FIND_STRINGTYPE_KEY "find_string_type"
static void
find_frame_ok_cb(GtkWidget *ok_bt, gpointer parent_w);
@ -65,11 +71,14 @@ void
find_frame_cb(GtkWidget *w _U_, gpointer d _U_)
{
GtkWidget *main_vb, *filter_hb, *filter_bt, *filter_te,
*direction_hb, *forward_rb, *backward_rb,
*direction_hb, *forward_rb, *backward_rb,
*hex_hb, *hex_rb, *ascii_rb, *filter_rb,
*combo_hb, *combo_cb, *combo_lb,
*bbox, *ok_bt, *cancel_bt;
#if GTK_MAJOR_VERSION < 2
GtkAccelGroup *accel_group;
#endif
GList *glist = NULL;
/* No Apply button, but "OK" not only sets our text widget, it
activates it (i.e., it causes us to do the search). */
static construct_args_t args = {
@ -145,6 +154,71 @@ find_frame_cb(GtkWidget *w _U_, gpointer d _U_)
gtk_box_pack_start(GTK_BOX(direction_hb), backward_rb, TRUE, TRUE, 0);
gtk_widget_show(backward_rb);
/* Filter/Hex/Ascii Search */
/* Filter */
hex_hb = gtk_hbox_new(FALSE, 3);
gtk_container_add(GTK_CONTAINER(main_vb), hex_hb);
gtk_widget_show(hex_hb);
#if GTK_MAJOR_VERSION < 2
filter_rb = dlg_radio_button_new_with_label_with_mnemonic(NULL, "_Display Filter",
accel_group);
#else
filter_rb = gtk_radio_button_new_with_mnemonic(NULL, "_Display Filter");
#endif
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_widget_show(filter_rb);
/* Hex */
#if GTK_MAJOR_VERSION < 2
hex_rb = dlg_radio_button_new_with_label_with_mnemonic(
gtk_radio_button_group(GTK_RADIO_BUTTON(filter_rb)),
"_Hex", accel_group);
#else
hex_rb = gtk_radio_button_new_with_mnemonic_from_widget(
GTK_RADIO_BUTTON(filter_rb), "_Hex");
#endif
gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(hex_rb), cfile.hex);
gtk_box_pack_start(GTK_BOX(hex_hb), hex_rb, TRUE, TRUE, 0);
gtk_widget_show(hex_rb);
/* ASCII Search */
#if GTK_MAJOR_VERSION < 2
ascii_rb = dlg_radio_button_new_with_label_with_mnemonic(
gtk_radio_button_group(GTK_RADIO_BUTTON(filter_rb)),
"_String", accel_group);
#else
ascii_rb = gtk_radio_button_new_with_mnemonic_from_widget(
GTK_RADIO_BUTTON(filter_rb), "_String");
#endif
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_widget_show(ascii_rb);
/* String Type Selection Dropdown Box */
combo_hb = gtk_hbox_new(FALSE, 3);
gtk_container_add(GTK_CONTAINER(main_vb), combo_hb);
gtk_widget_show(combo_hb);
/* Create Label */
combo_lb = gtk_label_new("Find String Type:");
gtk_box_pack_start(GTK_BOX(combo_hb), combo_lb, FALSE, FALSE, 6);
gtk_widget_show(combo_lb);
/* Create Combo Box */
combo_cb = gtk_combo_new();
/*gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), "Find String Type:");*/
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");
gtk_combo_set_popdown_strings(GTK_COMBO(combo_cb), glist);
gtk_container_add(GTK_CONTAINER(main_vb), combo_cb);
gtk_widget_show(combo_cb);
/* Button row: OK and cancel buttons */
bbox = gtk_hbutton_box_new();
gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), GTK_BUTTONBOX_END);
@ -176,6 +250,11 @@ find_frame_cb(GtkWidget *w _U_, gpointer d _U_)
/* Attach pointers to needed widgets to the capture prefs window/object */
OBJECT_SET_DATA(find_frame_w, E_FIND_FILT_KEY, filter_te);
OBJECT_SET_DATA(find_frame_w, E_FIND_BACKWARD_KEY, backward_rb);
OBJECT_SET_DATA(find_frame_w, E_FIND_FILTERDATA_KEY, filter_rb);
OBJECT_SET_DATA(find_frame_w, E_FIND_HEXDATA_KEY, hex_rb);
OBJECT_SET_DATA(find_frame_w, E_FIND_ASCIIDATA_KEY, ascii_rb);
OBJECT_SET_DATA(find_frame_w, E_FIND_STRINGTYPE_KEY, combo_cb);
/* Catch the "activate" signal on the filter text entry, so that
if the user types Return there, we act as if the "OK" button
@ -197,29 +276,33 @@ find_frame_cb(GtkWidget *w _U_, gpointer d _U_)
static void
find_frame_ok_cb(GtkWidget *ok_bt _U_, gpointer parent_w)
{
GtkWidget *filter_te, *backward_rb;
gchar *filter_text;
GtkWidget *filter_te, *backward_rb, *hex_rb, *ascii_rb, *combo_cb;
gchar *filter_text, *string_type;
dfilter_t *sfcode;
filter_te = (GtkWidget *)OBJECT_GET_DATA(parent_w, E_FIND_FILT_KEY);
backward_rb = (GtkWidget *)OBJECT_GET_DATA(parent_w, E_FIND_BACKWARD_KEY);
hex_rb = (GtkWidget *)OBJECT_GET_DATA(parent_w, E_FIND_HEXDATA_KEY);
ascii_rb = (GtkWidget *)OBJECT_GET_DATA(parent_w, E_FIND_ASCIIDATA_KEY);
combo_cb = (GtkWidget *)OBJECT_GET_DATA(parent_w, E_FIND_STRINGTYPE_KEY);
filter_text = gtk_entry_get_text(GTK_ENTRY(filter_te));
string_type = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(combo_cb)->entry));
/*
* Try to compile the filter.
*/
if (!dfilter_compile(filter_text, &sfcode)) {
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;
}
/* Was it empty? */
if (sfcode == NULL) {
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 a filter to use when searching for a frame.");
"You didn't specify valid search criteria.");
return;
}
@ -231,13 +314,25 @@ find_frame_ok_cb(GtkWidget *ok_bt _U_, gpointer parent_w)
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 (!find_packet(&cfile, sfcode)) {
/* We didn't find the packet. */
simple_dialog(ESD_TYPE_CRIT, NULL, "No packet matched that filter.");
return;
if (!GTK_TOGGLE_BUTTON (hex_rb)->active && !GTK_TOGGLE_BUTTON (ascii_rb)->active ) {
if (!find_packet(&cfile, sfcode)) {
/* We didn't find the packet. */
simple_dialog(ESD_TYPE_CRIT, NULL, "No packet matched that filter.");
return;
}
}
else
{
if (!find_ascii(&cfile, filter_text, cfile.ascii, string_type)) {
/* We didn't find the packet. */
simple_dialog(ESD_TYPE_CRIT, NULL, "No packet matched search criteria.");
return;
}
}
gtk_widget_destroy(GTK_WIDGET(parent_w));
}
@ -260,13 +355,21 @@ find_previous_next(GtkWidget *w, gpointer d, gboolean sens)
{
dfilter_t *sfcode;
if (cfile.sfilter) {
if (!dfilter_compile(cfile.sfilter, &sfcode))
if (!dfilter_compile(cfile.sfilter, &sfcode) && !cfile.hex && !cfile.ascii)
return;
if (sfcode == NULL)
if (sfcode == NULL && !cfile.hex && !cfile.ascii)
return;
cfile.sbackward = sens;
find_packet(&cfile, sfcode);
if (cfile.hex || cfile.ascii)
{
find_ascii(&cfile, cfile.sfilter, cfile.ascii, cfile.ftype);
}
else
{
find_packet(&cfile, sfcode);
}
} else
find_frame_cb(w, d);
}