Get rid of the EBCDIC stuff in the find dialog - it's not supported yet,
authorGuy Harris <guy@alum.mit.edu>
Fri, 29 Aug 2003 04:03:46 +0000 (04:03 -0000)
committerGuy Harris <guy@alum.mit.edu>
Fri, 29 Aug 2003 04:03:46 +0000 (04:03 -0000)
so we shouldn't torment the users by offering it.

Check the string type and convert it to an internal representation in
the GUI code; have the search code deal only with the internal
representation.

Save the case-sensitivity flag, and the indication of where string
searches look, along with other search parameters.

Upper-casify the string, for case-insensitive searches, in the GUI code;
don't save the upper-casified string, so it doesn't SHOUT at you when
you next pop up a "find" dialog.

Convert the hex value string to raw binary data in the GUI code, rather
than doing so in the search code.  Check that it's a valid string.

Connect the signals to the radio buttons after the pointers have been
attached to various GUI items - the signal handlers expect some of those
pointers to be attached, and aren't happy if they're not.

Have "find_packet()" contain a framework for searching, but not contain
the matching code; instead, pass it a pointer to a matching routine and
an opaque pointer to be passed to the matching routine.  Have all the
routines that do different types of searching have their own matching
routines, and use the common "find_packet()" code, rather than
duplicating that code.

Search for the Info column by column type, not by name (the user can
change the name).

When matching on the protocol tree, don't format the entire protocol
tree into a big buffer - just have a routine that matches the text
representation of a protocol tree item against a string, and, if it
finds a match, sets a "we found a match flag" and returns; have that
routine not bother doing any more work if that flag is set.
(Unfortunately, you can't abort "g_node_children_foreach()" in the
middle of a traversal.)

Free the generated display filter code after a find-by-display-filter
finishes.

svn path=/trunk/; revision=8306

cfile.h
file.c
file.h
gtk/find_dlg.c

diff --git a/cfile.h b/cfile.h
index f6939e39f032aa7945f98ed802b460257b45c944..f2e8b29e8553238892f00de16266bb409b0af5b4 100644 (file)
--- a/cfile.h
+++ b/cfile.h
@@ -1,7 +1,7 @@
 /* cfile.h
  * capture_file definition & GUI-independent manipulation
  *
 /* cfile.h
  * capture_file definition & GUI-independent manipulation
  *
- * $Id: cfile.h,v 1.2 2003/07/22 23:08:47 guy Exp $
+ * $Id: cfile.h,v 1.3 2003/08/29 04:03:45 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@ethereal.com>
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@ethereal.com>
@@ -33,6 +33,14 @@ typedef enum {
        FILE_READ_DONE          /* Read completed */
 } file_state;
 
        FILE_READ_DONE          /* Read completed */
 } file_state;
 
+/* Character set for text search. */
+typedef enum {
+       SCS_ASCII_AND_UNICODE,
+       SCS_ASCII,
+       SCS_UNICODE
+       /* add EBCDIC when it's implemented */
+} search_charset_t;
+
 typedef struct _capture_file {
   file_state   state;     /* Current state of capture file */
   int          filed;     /* File descriptor of capture file */
 typedef struct _capture_file {
   file_state   state;     /* Current state of capture file */
   int          filed;     /* File descriptor of capture file */
@@ -64,10 +72,13 @@ typedef struct _capture_file {
   gchar       *cfilter;   /* Capture filter string */
 #endif
   gchar       *sfilter;   /* Search filter string */
   gchar       *cfilter;   /* Capture filter string */
 #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 */
+  gboolean     sbackward; /* TRUE if search is backward, FALSE if forward */
+  gboolean     hex;       /* TRUE is raw data search is being performed */
+  gboolean     ascii;     /* TRUE is text search is being performed */
+  search_charset_t scs_type; /* Character set for text search */
+  gboolean     case_type; /* TRUE if case-insensitive text search */
+  gboolean     decode_data; /* TRUE if searching protocol tree text */
+  gboolean     summary_data; /* TRUE if searching Info column text */
   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 */
   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 */
diff --git a/file.c b/file.c
index ca8f80f0413c2193bfb4383d7b1ec0c000f7c237..53d74b0969580dd732a4e3de1a25ffc898d8377a 100644 (file)
--- a/file.c
+++ b/file.c
@@ -1,7 +1,7 @@
 /* file.c
  * File I/O routines
  *
 /* file.c
  * File I/O routines
  *
- * $Id: file.c,v 1.303 2003/08/14 22:32:45 sharpe Exp $
+ * $Id: file.c,v 1.304 2003/08/29 04:03:45 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@ethereal.com>
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@ethereal.com>
@@ -42,6 +42,7 @@
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
+#include <ctype.h>
 #include <errno.h>
 #include <signal.h>
 
 #include <errno.h>
 #include <signal.h>
 
@@ -97,14 +98,31 @@ static void read_packet(capture_file *cf, long offset);
 static void rescan_packets(capture_file *cf, const char *action, const char *action_item,
        gboolean refilter, gboolean redissect);
 
 static void rescan_packets(capture_file *cf, const char *action, const char *action_item,
        gboolean refilter, gboolean redissect);
 
+static gboolean match_protocol_tree(capture_file *cf, frame_data *fdata,
+       void *criterion);
+static void match_subtree_text(GNode *node, gpointer data);
+static gboolean match_summary_line(capture_file *cf, frame_data *fdata,
+       void *criterion);
+static gboolean match_ascii_and_unicode(capture_file *cf, frame_data *fdata,
+       void *criterion);
+static gboolean match_ascii(capture_file *cf, frame_data *fdata,
+       void *criterion);
+static gboolean match_unicode(capture_file *cf, frame_data *fdata,
+       void *criterion);
+static gboolean match_binary(capture_file *cf, frame_data *fdata,
+       void *criterion);
+static gboolean match_dfilter(capture_file *cf, frame_data *fdata,
+       void *criterion);
+static gboolean find_packet(capture_file *cf,
+       gboolean (*match_function)(capture_file *, frame_data *, void *),
+       void *criterion);
+
 static void freeze_plist(capture_file *cf);
 static void thaw_plist(capture_file *cf);
 static void freeze_plist(capture_file *cf);
 static void thaw_plist(capture_file *cf);
-static void proto_tree_get_node(GNode *node, gpointer data);
 
 static char *file_rename_error_message(int err);
 static char *file_close_error_message(int err);
 static gboolean copy_binary_file(char *from_filename, char *to_filename);
 
 static char *file_rename_error_message(int err);
 static char *file_close_error_message(int err);
 static gboolean copy_binary_file(char *from_filename, char *to_filename);
-static char decode_data[MAX_DECODE_BUFFER_SIZE];
 
 /* Update the progress bar this many times when reading a file. */
 #define N_PROGBAR_UPDATES      100
 
 /* Update the progress bar this many times when reading a file. */
 #define N_PROGBAR_UPDATES      100
@@ -1448,543 +1466,333 @@ change_time_formats(capture_file *cf)
   thaw_plist(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));
-    }
-}
+typedef struct {
+       const char      *string;
+       size_t          string_len;
+       capture_file    *cf;
+       gboolean        frame_matched;
+} match_data;
 
 
-static char*
-get_info_string(epan_dissect_t* edt)
+gboolean
+find_packet_protocol_tree(capture_file *cf, const char *string)
 {
 {
-    int i;
+  match_data           mdata;
 
 
-    for (i=0;i<edt->pi.cinfo->num_cols;i++) {
-        if (strcmp(edt->pi.cinfo->col_title[i], "Info")==0) {
-            return edt->pi.cinfo->col_data[i];
-        }
-    }
-    return NULL;
+  mdata.string = string;
+  mdata.string_len = strlen(string);
+  return find_packet(cf, match_protocol_tree, &mdata);
 }
 
 }
 
-/*
- * Find the data source for a specified field, and return a pointer
- * to the data in it.
- */
-static const guint8 *
-get_field_data(GSList *src_list, field_info *fi)
+static gboolean
+match_protocol_tree(capture_file *cf, frame_data *fdata, void *criterion)
 {
 {
-       GSList *src_le;
-       data_source *src;
-       tvbuff_t *src_tvb;
-
-       for (src_le = src_list; src_le != NULL; src_le = src_le->next) {
-               src = src_le->data;
-               src_tvb = src->tvb;
-               if (fi->ds_tvb == src_tvb) {
-                       /*
-                        * Found it.
-                        */
-            if(tvb_length_remaining(src_tvb, 0) < fi->length+fi->start){
-                return NULL;
-            }
-                       return tvb_get_ptr(src_tvb, fi->start, fi->length);
-               }
-       }
-       return NULL;    /* not found */
+  match_data           *mdata = criterion;
+  epan_dissect_t       *edt;
+
+  /* Construct the protocol tree, including the displayed text */
+  edt = epan_dissect_new(TRUE, TRUE);
+  /* We don't need the column information */
+  epan_dissect_run(edt, &cf->pseudo_header, cf->pd, fdata, NULL);
+
+  /* Iterate through all the nodes, seeing if they have text that matches. */
+  mdata->cf = cf;
+  mdata->frame_matched = FALSE;
+  g_node_children_foreach((GNode*) edt->tree, G_TRAVERSE_ALL,
+                         match_subtree_text, mdata);
+  epan_dissect_free(edt);
+  return mdata->frame_matched;
 }
 
 }
 
-/* Print a tree's data, and any child nodes to the buffer. */
-static
-void proto_tree_get_node(GNode *node, gpointer data)
+static void
+match_subtree_text(GNode *node, gpointer data)
 {
 {
-       field_info      *fi = PITEM_FINFO(node);
-       print_data      *pdata = (print_data*) data;
-       const guint8    *pd;
-       gchar           label_str[ITEM_LABEL_LENGTH];
-       gchar           *label_ptr, *string_ptr;
-
-    string_ptr = decode_data;
+  match_data   *mdata = (match_data*) data;
+  const gchar  *string = mdata->string;
+  size_t       string_len = mdata->string_len;
+  capture_file *cf = mdata->cf;
+  field_info   *fi = PITEM_FINFO(node);
+  gchar                label_str[ITEM_LABEL_LENGTH];
+  gchar                *label_ptr;
+  size_t       label_len;
+  guint32      i;
+  guint8       c_char;
+  size_t       c_match = 0;
+
+  if (mdata->frame_matched) {
+    /* We already had a match; don't bother doing any more work. */
+    return;
+  }
 
 
-       /* Don't print invisible entries. */
-       if (!fi->visible)
-               return;
+  /* Don't match invisible entries. */
+  if (!fi->visible)
+    return;
 
 
-       /* was a free format label produced? */
-       if (fi->representation) {
-               label_ptr = fi->representation;
-       }
-       else { /* no, make a generic label */
-               label_ptr = label_str;
-               proto_item_fill_label(fi, label_str);
-       }
+  /* was a free format label produced? */
+  if (fi->representation) {
+    label_ptr = fi->representation;
+  } else {
+    /* no, make a generic label */
+    label_ptr = label_str;
+    proto_item_fill_label(fi, label_str);
+  }
     
     
-    if (strlen(string_ptr)+strlen(label_ptr) < MAX_DECODE_BUFFER_SIZE) {
-        strcat(string_ptr, label_ptr);
-    }
-    else
-    {
-        simple_dialog(ESD_TYPE_CRIT, NULL, "Decode Buffer Size Exceeded.");
-        return;
-    }
+  /* Does that label match? */
+  label_len = strlen(label_ptr);
+  for (i = 0; i < label_len; i++) {
+    c_char = label_ptr[i];
+    if (cf->case_type)
+      c_char = toupper(c_char);
+    if (c_char == string[c_match]) {
+      c_match++;
+      if (c_match == string_len) {
+       /* No need to look further; we have a match */
+       mdata->frame_matched = TRUE;
+       return;
+      }
+    } else
+      c_match = 0;
+  }
+  
+  /* Recurse into the subtree, if it exists */
+  if (g_node_n_children(node) > 0)
+    g_node_children_foreach(node, G_TRAVERSE_ALL, match_subtree_text, mdata);
+}
 
 
-    /*
-        * Find the data for this field.
-        */
-       pd = get_field_data(pdata->src_list, fi);
-    if (pd!=NULL) {
-        if (strlen(pd) > 0) {
-            if (strlen(pd)+strlen(string_ptr) < MAX_DECODE_BUFFER_SIZE ) {
-                strcat(string_ptr, pd);
-            }
-            else
-            {
-                simple_dialog(ESD_TYPE_CRIT, NULL, "Decode Buffer Size Exceeded.");
-                return;
-            }
-        }
-    }
+gboolean
+find_packet_summary_line(capture_file *cf, const char *string)
+{
+  match_data           mdata;
 
 
-       /* If we're printing all levels, or if this node is one with a
-          subtree and its subtree is expanded, recurse into the subtree,
-          if it exists. */
-       g_assert(fi->tree_type >= -1 && fi->tree_type < num_tree_types);
-       if (pdata->print_all_levels ||
-           (fi->tree_type >= 0 && tree_is_expanded[fi->tree_type])) {
-               if (g_node_n_children(node) > 0) {
-                       pdata->level++;
-                       g_node_children_foreach(node, G_TRAVERSE_ALL,
-                               proto_tree_get_node, pdata);
-                       pdata->level--;
-               }
-       }
+  mdata.string = string;
+  mdata.string_len = strlen(string);
+  return find_packet(cf, match_summary_line, &mdata);
 }
 
 }
 
-gboolean
-find_in_gtk_data(capture_file *cf, gpointer *data, char *ascii_text, gboolean case_type, gboolean summary_search)
+static gboolean
+match_summary_line(capture_file *cf, frame_data *fdata, void *criterion)
 {
 {
-    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;
-    gchar       *uppercase;
-    epan_dissect_t*   new_edt;
-    char        *info_string;
-       print_data  ndata;
-
-    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;
-
-      if (case_type) {
-          g_strup(ascii_text);
+  match_data           *mdata = criterion;
+  const gchar          *string = mdata->string;
+  size_t               string_len = mdata->string_len;
+  epan_dissect_t       *edt;
+  const char           *info_column;
+  size_t               info_column_len;
+  gboolean             frame_matched = FALSE;
+  gint                 colx;
+  guint32              i;
+  guint8               c_char;
+  size_t               c_match = 0;
+
+  /* Don't bother constructing the protocol tree */
+  edt = epan_dissect_new(FALSE, FALSE);
+  /* Get the column information */
+  epan_dissect_run(edt, &cf->pseudo_header, cf->pd, fdata, &cf->cinfo);
+
+  /* Find the Info column */
+  for (colx = 0; colx < cf->cinfo.num_cols; colx++) {
+    if (cf->cinfo.fmt_matx[colx][COL_INFO]) {
+      /* Found it.  See if we match. */
+      info_column = edt->pi.cinfo->col_data[colx];
+      info_column_len = strlen(info_column);
+      for (i = 0; i < info_column_len; i++) {
+       c_char = info_column[i];
+       if (cf->case_type)
+         c_char = toupper(c_char);
+       if (c_char == string[c_match]) {
+         c_match++;
+         if (c_match == string_len) {
+           frame_matched = TRUE;
+           break;
+         }
+       } else
+         c_match = 0;
       }
       }
+      break;
+    }
+  }
+  epan_dissect_free(edt);
+  return frame_matched;
+}
 
 
-      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;
+typedef struct {
+       const guint8 *data;
+       size_t data_len;
+} cbs_t;       /* "Counted byte string" */
 
 
-          /* 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);
-          }
+gboolean
+find_packet_data(capture_file *cf, const guint8 *string, size_t string_size)
+{
+  cbs_t info;
 
 
-          cf->progbar_nextstep += cf->progbar_quantum;
-        }
+  info.data = string;
+  info.data_len = string_size;
 
 
-        if (stop_flag) {
-          /* Well, the user decided to abort the search.  Go back to the
-             frame where we started. */
-          new_fd = start_fd;
-          break;
-        }
+  /* String or hex search? */
+  if (cf->ascii) {
+    /* String search - what type of string? */
+    switch (cf->scs_type) {
 
 
-        /* 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 */
-        }
+    case SCS_ASCII_AND_UNICODE:
+      return find_packet(cf, match_ascii_and_unicode, &info);
 
 
-        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);
-          new_edt = epan_dissect_new(TRUE, TRUE);
-          epan_dissect_run(new_edt, &cfile.pseudo_header, cfile.pd, fdata, &cfile.cinfo);
-          if (summary_search) {
-              info_string = get_info_string(new_edt);
-              if (info_string == NULL) {
-                  simple_dialog(ESD_TYPE_CRIT, NULL, "Can't find info column. Terminating.");
-                  return FALSE;
-              }
-          }
-          else
-          {
-              strcpy(decode_data,"\0");
-              info_string = decode_data;
-              ndata.level = 0;
-              ndata.fh = NULL;
-              ndata.src_list = new_edt->pi.data_src;
-              ndata.encoding = new_edt->pi.fd->flags.encoding;
-              ndata.print_all_levels = TRUE;
-              ndata.print_hex_for_data = FALSE;
-              ndata.format = 0;
-              g_node_children_foreach((GNode*) new_edt->tree, G_TRAVERSE_ALL,
-                  proto_tree_get_node, &ndata);
-          }
-          if (case_type) {
-              g_strup(info_string);
-          }
-          frame_matched = FALSE;
-          buf_len = strlen(info_string);
-          for (i=0;i<buf_len;i++) {
-              c_char = info_string[i];
-              if (c_char == ascii_text[c_match]) {
-                 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! */
-          }
-          epan_dissect_free(new_edt);
-        }
+    case SCS_ASCII:
+      return find_packet(cf, match_ascii, &info);
 
 
-        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;
-        }
-      }
+    case SCS_UNICODE:
+      return find_packet(cf, match_unicode, &info);
 
 
-      /* We're done scanning the packets; destroy the progress bar if it
-         was created. */
-      if (progbar != NULL)
-        destroy_progress_dlg(progbar);
+    default:
+      g_assert_not_reached();
+      return FALSE;
     }
     }
+  } else
+    return find_packet(cf, match_binary, &info);
+}
 
 
-    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);
+static gboolean
+match_ascii_and_unicode(capture_file *cf, frame_data *fdata, void *criterion)
+{
+  cbs_t                *info = criterion;
+  const char   *ascii_text = info->data;
+  size_t       textlen = info->data_len;
+  gboolean     frame_matched;
+  guint32      buf_len;
+  guint32      i;
+  guint8       c_char;
+  size_t       c_match = 0;
+
+  frame_matched = FALSE;
+  buf_len = fdata->pkt_len;
+  for (i = 0; i < buf_len; i++) {
+    c_char = cf->pd[i];
+    if (cf->case_type)
+      c_char = toupper(c_char);
+    if (c_char != 0) {
+      if (c_char == ascii_text[c_match]) {
+       c_match++;
+       if (c_match == textlen) {
+         frame_matched = TRUE;
+         break;
+       }
+      } else
+       c_match = 0;
+    }
+  }
+  return frame_matched;
+}
 
 
-      /* Select that row, make it the focus row, and make it visible. */
-      packet_list_set_selected_row(row);
-      return TRUE;     /* success */
+static gboolean
+match_ascii(capture_file *cf, frame_data *fdata, void *criterion)
+{
+  cbs_t                *info = criterion;
+  const char   *ascii_text = info->data;
+  size_t       textlen = info->data_len;
+  gboolean     frame_matched;
+  guint32      buf_len;
+  guint32      i;
+  guint8       c_char;
+  size_t       c_match = 0;
+
+  frame_matched = FALSE;
+  buf_len = fdata->pkt_len;
+  for (i = 0; i < buf_len; i++) {
+    c_char = cf->pd[i];
+    if (cf->case_type)
+      c_char = toupper(c_char);
+    if (c_char == ascii_text[c_match]) {
+      c_match++;
+      if (c_match == textlen) {
+       frame_matched = TRUE;
+       break;
+      }
     } else
     } else
-      return FALSE;    /* failure */
+      c_match = 0;
+  }
+  return frame_matched;
 }
 
 }
 
-gboolean
-find_ascii(capture_file *cf, char *ascii_text, gboolean ascii_search, char *ftype, gboolean case_type)
+static gboolean
+match_unicode(capture_file *cf, frame_data *fdata, void *criterion)
 {
 {
-    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;
-    gchar       *uppercase;
-
-    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;
-
-      if (case_type && ascii_search) {
-          g_strup(ascii_text);
+  cbs_t                *info = criterion;
+  const char   *ascii_text = info->data;
+  size_t       textlen = info->data_len;
+  gboolean     frame_matched;
+  guint32      buf_len;
+  guint32      i;
+  guint8       c_char;
+  size_t       c_match = 0;
+
+  frame_matched = FALSE;
+  buf_len = fdata->pkt_len;
+  for (i = 0; i < buf_len; i++) {
+    c_char = cf->pd[i];
+    if (cf->case_type)
+      c_char = toupper(c_char);
+    if (c_char == ascii_text[c_match]) {
+      c_match++;
+      i++;
+      if (c_match == textlen) {
+       frame_matched = TRUE;
+       break;
       }
       }
+    } else
+      c_match = 0;
+  }
+  return frame_matched;
+}
 
 
-      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++) {
-              if (ascii_search && case_type) {
-                  uppercase = &cf->pd[i];
-                  g_strup(uppercase);
-                  c_char = uppercase[0];
-              }
-              else
-                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;
-        }
+static gboolean
+match_binary(capture_file *cf, frame_data *fdata, void *criterion)
+{
+  cbs_t                *info = criterion;
+  const guint8 *binary_data = info->data;
+  size_t       datalen = info->data_len;
+  gboolean     frame_matched;
+  guint32      buf_len;
+  guint32      i;
+  size_t       c_match = 0;
+
+  frame_matched = FALSE;
+  buf_len = fdata->pkt_len;
+  for (i = 0; i < buf_len; i++) {
+    if (cf->pd[i] == binary_data[c_match]) {
+      c_match++;
+      if (c_match == datalen) {
+       frame_matched = TRUE;
+       break;
       }
       }
+    } else
+      c_match = 0;
+  }
+  return frame_matched;
+}
 
 
-      /* We're done scanning the packets; destroy the progress bar if it
-         was created. */
-      if (progbar != NULL)
-        destroy_progress_dlg(progbar);
-    }
+gboolean
+find_packet_dfilter(capture_file *cf, dfilter_t *sfcode)
+{
+  return find_packet(cf, match_dfilter, sfcode);
+}
 
 
-    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);
+static gboolean
+match_dfilter(capture_file *cf, frame_data *fdata, void *criterion)
+{
+  dfilter_t            *sfcode = criterion;
+  epan_dissect_t       *edt;
+  gboolean             frame_matched;
 
 
-      /* 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 */
+  edt = epan_dissect_new(TRUE, FALSE);
+  epan_dissect_prime_dfilter(edt, sfcode);
+  epan_dissect_run(edt, &cf->pseudo_header, cf->pd, fdata, NULL);
+  frame_matched = dfilter_apply_edt(sfcode, edt);
+  epan_dissect_free(edt);
+  return frame_matched;
 }
 
 }
 
-gboolean
-find_packet(capture_file *cf, dfilter_t *sfcode)
+static gboolean
+find_packet(capture_file *cf,
+            gboolean (*match_function)(capture_file *, frame_data *, void *),
+            void *criterion)
 {
   frame_data *start_fd;
   frame_data *fdata;
 {
   frame_data *start_fd;
   frame_data *fdata;
@@ -1993,9 +1801,7 @@ find_packet(capture_file *cf, dfilter_t *sfcode)
   gboolean    stop_flag;
   int         count;
   int         err;
   gboolean    stop_flag;
   int         count;
   int         err;
-  gboolean    frame_matched;
   int         row;
   int         row;
-  epan_dissect_t       *edt;
   float       prog_val;
   GTimeVal    start_time;
   gchar       status_str[100];
   float       prog_val;
   GTimeVal    start_time;
   gchar       status_str[100];
@@ -2069,16 +1875,13 @@ find_packet(capture_file *cf, dfilter_t *sfcode)
 
       /* Is this packet in the display? */
       if (fdata->flags.passed_dfilter) {
 
       /* Is this packet in the display? */
       if (fdata->flags.passed_dfilter) {
-        /* Yes.  Does it match the search filter? */
+       /* Yes.  Load its data. */
         /* XXX - do something with "err" */
         wtap_seek_read(cf->wth, fdata->file_off, &cf->pseudo_header,
                        cf->pd, fdata->cap_len, &err);
         /* XXX - do something with "err" */
         wtap_seek_read(cf->wth, fdata->file_off, &cf->pseudo_header,
                        cf->pd, fdata->cap_len, &err);
-        edt = epan_dissect_new(TRUE, FALSE);
-        epan_dissect_prime_dfilter(edt, sfcode);
-        epan_dissect_run(edt, &cf->pseudo_header, cf->pd, fdata, NULL);
-        frame_matched = dfilter_apply_edt(sfcode, edt);
-        epan_dissect_free(edt);
-        if (frame_matched) {
+
+       /* Does it match the search criterion? */
+       if ((*match_function)(cf, fdata, criterion)) {
           new_fd = fdata;
           break;       /* found it! */
         }
           new_fd = fdata;
           break;       /* found it! */
         }
diff --git a/file.h b/file.h
index 94ce1895cc294a8997e48cc15cd919abadaf43e7..0a7396802ba0583b17481742beff457b446735c0 100644 (file)
--- a/file.h
+++ b/file.h
@@ -1,7 +1,7 @@
 /* file.h
  * Definitions for file structures and routines
  *
 /* file.h
  * Definitions for file structures and routines
  *
- * $Id: file.h,v 1.103 2003/08/11 22:41:09 sharpe Exp $
+ * $Id: file.h,v 1.104 2003/08/29 04:03:45 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@ethereal.com>
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@ethereal.com>
@@ -55,7 +55,13 @@ 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 *);
 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_protocol_tree(capture_file *cf, const char *string);
+gboolean find_packet_summary_line(capture_file *cf, const char *string);
+gboolean find_packet_data(capture_file *cf, const guint8 *string,
+                         size_t string_size);
+gboolean find_packet_dfilter(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 case_type);
 gboolean find_in_gtk_data(capture_file *cf, gpointer *data, char *ascii_text, gboolean case_type, gboolean search_type);
 guint8 get_int_value(char char_val);
 gboolean find_ascii(capture_file *cf, char *ascii_text, gboolean ascii_search, char *ftype, gboolean case_type);
 gboolean find_in_gtk_data(capture_file *cf, gpointer *data, char *ascii_text, gboolean case_type, gboolean search_type);
index cbdb97b3b86a5105a6b9c72b6d25ca569d25b12b..c0ca252f1de9ccb424f3fa083ea0a56d90dac3a2 100644 (file)
@@ -1,7 +1,7 @@
 /* find_dlg.c
  * Routines for "find frame" window
  *
 /* 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>
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@ethereal.com>
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
-
 #ifdef HAVE_CONFIG_H
 # include "config.h"
 #endif
 
 #ifdef HAVE_CONFIG_H
 # include "config.h"
 #endif
 
+#include <string.h>
+#include <ctype.h>
+
 #include <gtk/gtk.h>
 
 #include <epan/proto.h>
 #include <gtk/gtk.h>
 
 #include <epan/proto.h>
 #include "keys.h"
 
 /* Capture callback data keys */
 #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_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;
 
 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);
   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 */
   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);
   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");
   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, "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);
   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);
   
   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);
 
   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;
 }
 
     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)
 {
 
 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);
 
   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));
 
   /*
   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);
    */
   if (cfile.sfilter)
     g_free(cfile.sfilter);
   cfile.sfilter = g_strdup(filter_text);
-
   cfile.sbackward = GTK_TOGGLE_BUTTON (backward_rb)->active;
   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. */
         /* 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;
       }
         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));
 }
   }
   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)
 {
 static void
 find_previous_next(GtkWidget *w, gpointer d, gboolean sens)
 {
+  guint8    *bytes;
+  size_t     nbytes;
+  char      *string;
   dfilter_t *sfcode;
 
   dfilter_t *sfcode;
 
-
   if (cfile.sfilter) {
   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;
         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;
         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);
 }
   } else
      find_frame_cb(w, d);
 }