Fix a few minor memory leaks...
[obnox/wireshark/wip.git] / file.c
diff --git a/file.c b/file.c
index 01acf931306742f53a1c7fa00a1230fa10b6d01b..799130b6153cf6e918b8d746f2faa6de839a5aae 100644 (file)
--- a/file.c
+++ b/file.c
 #include <epan/conversation.h>
 #include <epan/epan_dissect.h>
 #include <epan/tap.h>
-#include "stat_menu.h"
-#include "tap_dfilter_dlg.h"
 #include <epan/dissectors/packet-data.h>
 #include <epan/dissectors/packet-ber.h>
 #include <epan/timestamp.h>
-#include "file_util.h"
-
-
+#include <epan/dfilter/dfilter-macro.h>
+#include <wsutil/file_util.h>
+#include <epan/column-utils.h>
+#include <epan/strutil.h>
 
 #ifdef HAVE_LIBPCAP
 gboolean auto_scroll_live;
@@ -129,34 +128,60 @@ static   gboolean copy_binary_file(const char *from_filename, const char *to_fil
 #define        FRAME_DATA_CHUNK_SIZE   1024
 
 
-/* one callback for now, we could have a list later */
-static cf_callback_t cf_cb = NULL;
-static gpointer cf_cb_user_data = NULL;
+/* this callback mechanism should possibly be replaced by the g_signal_...() stuff (if I only would know how :-) */
+typedef struct {
+    cf_callback_t cb_fct;
+    gpointer user_data;
+} cf_callback_data_t;
+
+static GList *cf_callbacks = NULL;
 
-void
+static void
 cf_callback_invoke(int event, gpointer data)
 {
-    g_assert(cf_cb != NULL);
-    cf_cb(event, data, cf_cb_user_data);
+    cf_callback_data_t *cb;
+    GList *cb_item = cf_callbacks;
+
+    /* there should be at least one interested */
+    g_assert(cb_item != NULL);
+
+    while(cb_item != NULL) {
+        cb = cb_item->data;
+        cb->cb_fct(event, data, cb->user_data);
+        cb_item = g_list_next(cb_item);
+    }
 }
 
 
 void
 cf_callback_add(cf_callback_t func, gpointer user_data)
 {
-    /* More than one callback listener is currently not implemented,
-       but should be easy to do. */
-    g_assert(cf_cb == NULL);
-    cf_cb = func;
-    cf_cb_user_data = user_data;
+    cf_callback_data_t *cb;
+
+    cb = g_malloc(sizeof(cf_callback_data_t));
+    cb->cb_fct = func;
+    cb->user_data = user_data;
+
+    cf_callbacks = g_list_append(cf_callbacks, cb);
 }
 
 void
-cf_callback_remove(cf_callback_t func _U_)
+cf_callback_remove(cf_callback_t func)
 {
-    g_assert(cf_cb != NULL);
-    cf_cb = NULL;
-    cf_cb_user_data = NULL;
+    cf_callback_data_t *cb;
+    GList *cb_item = cf_callbacks;
+
+    while(cb_item != NULL) {
+        cb = cb_item->data;
+        if(cb->cb_fct == func) {
+            cf_callbacks = g_list_remove(cf_callbacks, cb);
+            g_free(cb);
+            return;
+        }
+        cb_item = g_list_next(cb_item);
+    }
+
+    g_assert_not_reached();
 }
 
 void
@@ -301,7 +326,7 @@ cf_reset_state(capture_file *cf)
   if (cf->filename != NULL) {
     /* If it's a temporary file, remove it. */
     if (cf->is_tempfile)
-      eth_unlink(cf->filename);
+      ws_unlink(cf->filename);
     g_free(cf->filename);
     cf->filename = NULL;
   }
@@ -324,6 +349,7 @@ cf_reset_state(capture_file *cf)
 
   /* No frame selected, no field in that frame selected. */
   cf->current_frame = NULL;
+  cf->current_row = 0;
   cf->finfo_selected = NULL;
 
   /* Clear the packet list. */
@@ -378,7 +404,6 @@ cf_read(capture_file *cf)
   const gchar *name_ptr;
   const char  *errmsg;
   char         errmsg_errno[1024+1];
-  gchar        err_str[2048+1];
   gint64       data_offset;
   progdlg_t *volatile progbar = NULL;
   gboolean     stop_flag;
@@ -392,7 +417,7 @@ cf_read(capture_file *cf)
   dfilter_t   *dfcode;
 
   /* Compile the current display filter.
-   * We assume this will not fail since cf->dfilter is only set in 
+   * We assume this will not fail since cf->dfilter is only set in
    * cf_filter IFF the filter was valid.
    */
   dfcode=NULL;
@@ -403,7 +428,6 @@ cf_read(capture_file *cf)
   cum_bytes=0;
 
   reset_tap_listeners();
-  tap_dfilter_dlg_update();
 
   cf_callback_invoke(cf_cb_file_read_start, cf);
 
@@ -543,6 +567,8 @@ cf_read(capture_file *cf)
   cf->lnk_t = wtap_file_encap(cf->wth);
 
   cf->current_frame = cf->first_displayed;
+  cf->current_row = 0;
+
   packet_list_thaw();
 
   cf_callback_invoke(cf_cb_file_read_finished, cf);
@@ -603,8 +629,7 @@ cf_read(capture_file *cf)
       errmsg = errmsg_errno;
       break;
     }
-    g_snprintf(err_str, sizeof err_str, errmsg);
-    simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, err_str);
+    simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", errmsg);
     return CF_READ_ERROR;
   } else
     return CF_READ_OK;
@@ -629,7 +654,7 @@ cf_continue_tail(capture_file *cf, volatile int to_read, int *err)
   dfilter_t   *dfcode;
 
   /* Compile the current display filter.
-   * We assume this will not fail since cf->dfilter is only set in 
+   * We assume this will not fail since cf->dfilter is only set in
    * cf_filter IFF the filter was valid.
    */
   dfcode=NULL;
@@ -639,6 +664,7 @@ cf_continue_tail(capture_file *cf, volatile int to_read, int *err)
 
   *err = 0;
 
+  packet_list_check_end();
   packet_list_freeze();
 
   /*g_log(NULL, G_LOG_LEVEL_MESSAGE, "cf_continue_tail: %u new: %u", cf->count, to_read);*/
@@ -694,7 +720,7 @@ cf_continue_tail(capture_file *cf, volatile int to_read, int *err)
   /* XXX - this causes "flickering" of the list */
   packet_list_thaw();
 
-  /* moving to the end of the packet list - if the user requested so and 
+  /* moving to the end of the packet list - if the user requested so and
      we have some new packets.
      this doesn't seem to work well with a frozen GTK_Clist, so do this after
      packet_list_thaw() is done, see bugzilla 1188 */
@@ -729,7 +755,7 @@ cf_finish_tail(capture_file *cf, int *err)
   dfilter_t   *dfcode;
 
   /* Compile the current display filter.
-   * We assume this will not fail since cf->dfilter is only set in 
+   * We assume this will not fail since cf->dfilter is only set in
    * cf_filter IFF the filter was valid.
    */
   dfcode=NULL;
@@ -742,6 +768,7 @@ cf_finish_tail(capture_file *cf, int *err)
     return CF_READ_ERROR;
   }
 
+  packet_list_check_end();
   packet_list_freeze();
 
   while ((wtap_read(cf->wth, err, &err_info, &data_offset))) {
@@ -936,11 +963,13 @@ add_packet_to_packet_list(frame_data *fdata, capture_file *cf,
 
        we have tap listeners;
 
+       we have custom columns;
+
      allocate a protocol tree root node, so that we'll construct
      a protocol tree against which a filter expression can be
      evaluated. */
   if ((dfcode != NULL && refilter) || color_filters_used()
-        || num_tap_filters != 0)
+      || num_tap_filters != 0 || have_custom_cols(&cf->cinfo))
          create_proto_tree = TRUE;
 
   /* Dissect the frame. */
@@ -953,6 +982,9 @@ add_packet_to_packet_list(frame_data *fdata, capture_file *cf,
   if (color_filters_used()) {
       color_filters_prime_edt(edt);
   }
+
+  col_custom_prime_edt(edt, &cf->cinfo);
+
   tap_queue_init(edt);
   epan_dissect_run(edt, pseudo_header, buf, fdata, &cf->cinfo);
   tap_push_tapped_queue(edt);
@@ -973,15 +1005,15 @@ add_packet_to_packet_list(frame_data *fdata, capture_file *cf,
     /* This frame either passed the display filter list or is marked as
        a time reference frame.  All time reference frames are displayed
        even if they dont pass the display filter */
-    /* if this was a TIME REF frame we should reset the cul bytes field */
     if(edt->pi.fd->flags.ref_time){
+      /* if this was a TIME REF frame we should reset the cul bytes field */
       cum_bytes = fdata->pkt_len;
-      fdata->cum_bytes  = cum_bytes;
+      fdata->cum_bytes =  cum_bytes;
+    } else {
+      /* increase cum_bytes with this packets length */
+      cum_bytes += fdata->pkt_len;
     }
 
-    /* increase cum_bytes with this packets length */
-    cum_bytes += fdata->pkt_len;
-
     epan_dissect_fill_in_columns(edt);
 
     /* If we haven't yet seen the first frame, this is it.
@@ -1003,15 +1035,19 @@ add_packet_to_packet_list(frame_data *fdata, capture_file *cf,
     /* This is the last frame we've seen so far. */
     cf->last_displayed = fdata;
 
+    fdata->col_expr.col_expr = cf->cinfo.col_expr.col_expr;
+    fdata->col_expr.col_expr_val = cf->cinfo.col_expr.col_expr_val;
+
     row = packet_list_append(cf->cinfo.col_data, fdata);
 
-    /* colorize packet: if packet is marked, use preferences,
-       otherwise try to apply color filters */
+    /* colorize packet: first apply color filters
+     * then if packet is marked, use preferences to overwrite color
+     * we do both to make sure that when a packet gets un-marked, the
+     * color will be correctly set (fixes bug 2038)
+     */
+      fdata->color_filter = color_filters_colorize_packet(row, edt);
       if (fdata->flags.marked) {
-          fdata->color_filter = NULL;
           packet_list_set_colors(row, &prefs.gui_marked_fg, &prefs.gui_marked_bg);
-      } else {
-          fdata->color_filter = color_filters_colorize_packet(row, edt);
       }
 
     /* Set the time of the previous displayed frame to the time of this
@@ -1087,7 +1123,9 @@ read_packet(capture_file *cf, dfilter_t *dfcode, gint64 offset)
     cf->count++;
     cf->f_datalen = offset + phdr->caplen;
     fdata->num = cf->count;
-    row = add_packet_to_packet_list(fdata, cf, dfcode, pseudo_header, buf, TRUE);
+    if (!cf->redissecting) {
+      row = add_packet_to_packet_list(fdata, cf, dfcode, pseudo_header, buf, TRUE);
+    }
   } else {
     /* XXX - if we didn't have read filters, or if we could avoid
        allocating the "frame_data" structure until we knew whether
@@ -1118,7 +1156,6 @@ cf_merge_files(char **out_filenamep, int in_file_count,
   int               err_fileno;
   int               i;
   char              errmsg_errno[1024+1];
-  gchar             err_str[2048+1];
   const char       *errmsg;
   gboolean          got_read_error = FALSE, got_write_error = FALSE;
   gint64            data_offset;
@@ -1134,7 +1171,7 @@ cf_merge_files(char **out_filenamep, int in_file_count,
   /* open the input files */
   if (!merge_open_in_files(in_file_count, in_filenames, &in_files,
                            &open_err, &err_info, &err_fileno)) {
-    free(in_files);
+    g_free(in_files);
     cf_open_failure_alert_box(in_filenames[err_fileno], open_err, err_info,
                               FALSE, 0);
     return CF_ERROR;
@@ -1142,7 +1179,7 @@ cf_merge_files(char **out_filenamep, int in_file_count,
 
   if (*out_filenamep != NULL) {
     out_filename = *out_filenamep;
-    out_fd = eth_open(out_filename, O_CREAT|O_TRUNC|O_BINARY, 0600);
+    out_fd = ws_open(out_filename, O_CREAT|O_TRUNC|O_BINARY, 0600);
     if (out_fd == -1)
       open_err = errno;
   } else {
@@ -1155,7 +1192,7 @@ cf_merge_files(char **out_filenamep, int in_file_count,
   if (out_fd == -1) {
     err_info = NULL;
     merge_close_in_files(in_file_count, in_files);
-    free(in_files);
+    g_free(in_files);
     cf_open_failure_alert_box(out_filename, open_err, NULL, TRUE, file_type);
     return CF_ERROR;
   }
@@ -1165,9 +1202,9 @@ cf_merge_files(char **out_filenamep, int in_file_count,
       merge_max_snapshot_length(in_file_count, in_files),
          FALSE /* compressed */, &open_err);
   if (pdh == NULL) {
-    eth_close(out_fd);
+    ws_close(out_fd);
     merge_close_in_files(in_file_count, in_files);
-    free(in_files);
+    g_free(in_files);
     cf_open_failure_alert_box(out_filename, open_err, err_info, TRUE,
                               file_type);
     return CF_ERROR;
@@ -1310,8 +1347,7 @@ cf_merge_files(char **out_filenamep, int in_file_count,
          errmsg = errmsg_errno;
          break;
        }
-       g_snprintf(err_str, sizeof err_str, errmsg, in_files[i].filename);
-        simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, err_str);
+        simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, errmsg, in_files[i].filename);
       }
     }
   }
@@ -1327,7 +1363,7 @@ cf_merge_files(char **out_filenamep, int in_file_count,
        have to. */
     return CF_ERROR;
   } else
-    return CF_READ_OK;
+    return CF_OK;
 }
 
 cf_status_t
@@ -1454,7 +1490,7 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item,
   dfilter_t   *dfcode;
 
   /* Compile the current display filter.
-   * We assume this will not fail since cf->dfilter is only set in 
+   * We assume this will not fail since cf->dfilter is only set in
    * cf_filter IFF the filter was valid.
    */
   dfcode=NULL;
@@ -1480,6 +1516,10 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item,
        which might cause the state information to be constructed differently
        by that dissector. */
 
+    /* We might receive new packets while redissecting, and we don't
+       want to dissect those before their time. */
+    cf->redissecting = TRUE;
+
     /* Initialize all data structures used for dissection. */
     init_dissection();
   }
@@ -1626,6 +1666,9 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item,
     prev_frame = fdata;
   }
 
+  /* We are done redissecting the packet list. */
+  cf->redissecting = FALSE;
+
   /* Re-sort the list using the previously selected order */
   packet_list_set_sort_column();
 
@@ -1696,6 +1739,10 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item,
     /* Either the frame that was selected passed the filter, or we've
        found the nearest displayed frame to that frame.  Select it, make
        it the focus row, and make it visible. */
+    if (selected_row == 0) {
+      /* Set to invalid to force update of packet list and packet details */
+      cf->current_row = -1;
+    }
     packet_list_set_selected_row(selected_row);
   }
 
@@ -1868,7 +1915,7 @@ cf_retap_packets(capture_file *cf, gboolean do_columns)
                                     do_columns ? &cf->cinfo : NULL)) {
   case PSP_FINISHED:
     /* Completed successfully. */
-    return CF_OK;
+    return CF_READ_OK;
 
   case PSP_STOPPED:
     /* Well, the user decided to abort the refiltering.
@@ -1916,7 +1963,7 @@ print_packet(capture_file *cf, frame_data *fdata,
      the dissection or the hex data.
      XXX - do we need it if we're just printing the hex data? */
   proto_tree_needed =
-      args->print_args->print_dissections != print_dissections_none || args->print_args->print_hex;
+      args->print_args->print_dissections != print_dissections_none || args->print_args->print_hex || have_custom_cols(&cf->cinfo);
   edt = epan_dissect_new(proto_tree_needed, proto_tree_needed);
 
   /* Fill in the column information if we're printing the summary
@@ -2200,7 +2247,7 @@ cf_write_pdml_packets(capture_file *cf, print_args_t *print_args)
   FILE        *fh;
   psp_return_t ret;
 
-  fh = eth_fopen(print_args->file, "w");
+  fh = ws_fopen(print_args->file, "w");
   if (fh == NULL)
     return CF_PRINT_OPEN_ERROR;        /* attempt to open destination failed */
 
@@ -2251,9 +2298,12 @@ write_psml_packet(capture_file *cf, frame_data *fdata,
 {
   FILE *fh = argsp;
   epan_dissect_t *edt;
+  gboolean proto_tree_needed;
 
-  /* Fill in the column information, but don't create the protocol tree. */
-  edt = epan_dissect_new(FALSE, FALSE);
+  /* Fill in the column information, only create the protocol tree
+     if having custom columns. */
+  proto_tree_needed = have_custom_cols(&cf->cinfo);
+  edt = epan_dissect_new(proto_tree_needed, proto_tree_needed);
   epan_dissect_run(edt, pseudo_header, pd, fdata, &cf->cinfo);
   epan_dissect_fill_in_columns(edt);
 
@@ -2271,7 +2321,7 @@ cf_write_psml_packets(capture_file *cf, print_args_t *print_args)
   FILE        *fh;
   psp_return_t ret;
 
-  fh = eth_fopen(print_args->file, "w");
+  fh = ws_fopen(print_args->file, "w");
   if (fh == NULL)
     return CF_PRINT_OPEN_ERROR;        /* attempt to open destination failed */
 
@@ -2322,9 +2372,12 @@ write_csv_packet(capture_file *cf, frame_data *fdata,
 {
   FILE *fh = argsp;
   epan_dissect_t *edt;
+  gboolean proto_tree_needed;
 
-  /* Fill in the column information, but don't create the protocol tree. */
-  edt = epan_dissect_new(FALSE, FALSE);
+  /* Fill in the column information, only create the protocol tree
+     if having custom columns. */
+  proto_tree_needed = have_custom_cols(&cf->cinfo);
+  edt = epan_dissect_new(proto_tree_needed, proto_tree_needed);
   epan_dissect_run(edt, pseudo_header, pd, fdata, &cf->cinfo);
   epan_dissect_fill_in_columns(edt);
 
@@ -2342,7 +2395,7 @@ cf_write_csv_packets(capture_file *cf, print_args_t *print_args)
   FILE        *fh;
   psp_return_t ret;
 
-  fh = eth_fopen(print_args->file, "w");
+  fh = ws_fopen(print_args->file, "w");
   if (fh == NULL)
     return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
 
@@ -2386,6 +2439,65 @@ cf_write_csv_packets(capture_file *cf, print_args_t *print_args)
   return CF_PRINT_OK;
 }
 
+static gboolean
+write_carrays_packet(capture_file *cf _U_, frame_data *fdata,
+                    union wtap_pseudo_header *pseudo_header _U_,
+                    const guint8 *pd, void *argsp)
+{
+  FILE *fh = argsp;
+
+  proto_tree_write_carrays(pd, fdata->cap_len, fdata->num, fh);
+  return !ferror(fh);
+}
+
+cf_print_status_t
+cf_write_carrays_packets(capture_file *cf, print_args_t *print_args)
+{
+  FILE        *fh;
+  psp_return_t ret;
+
+  fh = ws_fopen(print_args->file, "w");
+
+  if (fh == NULL)
+    return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
+
+  write_carrays_preamble(fh);
+
+  if (ferror(fh)) {
+    fclose(fh);
+    return CF_PRINT_WRITE_ERROR;
+  }
+
+  /* Iterate through the list of packets, printing the packets we were
+     told to print. */
+  ret = process_specified_packets(cf, &print_args->range,
+                                 "Writing C Arrays",
+                                 "selected packets", TRUE,
+                                  write_carrays_packet, fh);
+  switch (ret) {
+  case PSP_FINISHED:
+    /* Completed successfully. */
+    break;
+  case PSP_STOPPED:
+    /* Well, the user decided to abort the printing. */
+    break;
+  case PSP_FAILED:
+    /* Error while printing. */
+    fclose(fh);
+    return CF_PRINT_WRITE_ERROR;
+  }
+
+  write_carrays_finale(fh);
+
+  if (ferror(fh)) {
+    fclose(fh);
+    return CF_PRINT_WRITE_ERROR;
+  }
+
+  fclose(fh);
+  return CF_PRINT_OK;
+}
+
 /* Scan through the packet list and change all columns that use the
    "command-line-specified" time stamp format to use the current
    value of that format. */
@@ -2403,7 +2515,6 @@ cf_change_time_formats(capture_file *cf)
   gchar       status_str[100];
   int         progbar_nextstep;
   int         progbar_quantum;
-  int         first, last;
   gboolean    sorted_by_frame_column;
 
 
@@ -2416,14 +2527,16 @@ cf_change_time_formats(capture_file *cf)
      XXX - we have to force the "column is writable" flag on, as it
      might be off from the last frame that was dissected. */
   col_set_writable(&cf->cinfo, TRUE);
-  if (!check_col(&cf->cinfo, COL_CLS_TIME)) {
+  if (!check_col(&cf->cinfo, COL_CLS_TIME) &&
+      !check_col(&cf->cinfo, COL_ABS_TIME) &&
+      !check_col(&cf->cinfo, COL_ABS_DATE_TIME) &&
+      !check_col(&cf->cinfo, COL_REL_TIME) &&
+      !check_col(&cf->cinfo, COL_DELTA_TIME) &&
+      !check_col(&cf->cinfo, COL_DELTA_TIME_DIS)) {
     /* No, there aren't any columns in that format, so we have no work
        to do. */
     return;
   }
-  first = cf->cinfo.col_first[COL_CLS_TIME];
-  g_assert(first >= 0);
-  last = cf->cinfo.col_last[COL_CLS_TIME];
 
   /* Freeze the packet list while we redo it, so we don't get any
      screen updates while it happens. */
@@ -2529,12 +2642,12 @@ cf_change_time_formats(capture_file *cf)
     if (row != -1) {
       /* This packet is in the summary list, on row "row". */
 
-      for (i = first; i <= last; i++) {
-        if (cf->cinfo.fmt_matx[i][COL_CLS_TIME]) {
+      for (i = 0; i < cf->cinfo.num_cols; i++) {
+        if (col_has_time_fmt(&cf->cinfo, i)) {
           /* This is one of the columns that shows the time in
              "command-line-specified" format; update it. */
           cf->cinfo.col_buf[i][0] = '\0';
-          col_set_cls_time(fdata, &cf->cinfo, i);
+          col_set_fmt_time(fdata, &cf->cinfo, cf->cinfo.col_fmt[i], i);
           packet_list_set_text(row, i, cf->cinfo.col_data[i]);
         }
       }
@@ -2548,9 +2661,9 @@ cf_change_time_formats(capture_file *cf)
 
   /* Set the column widths of those columns that show the time in
      "command-line-specified" format. */
-  for (i = first; i <= last; i++) {
-    if (cf->cinfo.fmt_matx[i][COL_CLS_TIME]) {
-      packet_list_set_cls_time_width(i);
+  for (i = 0; i < cf->cinfo.num_cols; i++) {
+    if (col_has_time_fmt(&cf->cinfo, i)) {
+      packet_list_set_time_width(cf->cinfo.col_fmt[i], i);
     }
   }
 
@@ -2744,7 +2857,7 @@ static gboolean
 match_ascii_and_unicode(capture_file *cf, frame_data *fdata, void *criterion)
 {
   cbs_t                *info = criterion;
-  const char   *ascii_text = info->data;
+  const guint8 *ascii_text = info->data;
   size_t       textlen = info->data_len;
   gboolean     frame_matched;
   guint32      buf_len;
@@ -2778,7 +2891,7 @@ static gboolean
 match_ascii(capture_file *cf, frame_data *fdata, void *criterion)
 {
   cbs_t                *info = criterion;
-  const char   *ascii_text = info->data;
+  const guint8 *ascii_text = info->data;
   size_t       textlen = info->data_len;
   gboolean     frame_matched;
   guint32      buf_len;
@@ -2810,7 +2923,7 @@ static gboolean
 match_unicode(capture_file *cf, frame_data *fdata, void *criterion)
 {
   cbs_t                *info = criterion;
-  const char   *ascii_text = info->data;
+  const guint8 *ascii_text = info->data;
   size_t       textlen = info->data_len;
   gboolean     frame_matched;
   guint32      buf_len;
@@ -2829,7 +2942,7 @@ match_unicode(capture_file *cf, frame_data *fdata, void *criterion)
       i++;
       if (c_match == textlen) {
        frame_matched = TRUE;
-       cf->search_pos = i; /* Save the position of the last character 
+       cf->search_pos = i; /* Save the position of the last character
                               for highlighting the field. */
        break;
       }
@@ -2857,7 +2970,7 @@ match_binary(capture_file *cf, frame_data *fdata, void *criterion)
       c_match++;
       if (c_match == datalen) {
        frame_matched = TRUE;
-       cf->search_pos = i; /* Save the position of the last character 
+       cf->search_pos = i; /* Save the position of the last character
                               for highlighting the field. */
        break;
       }
@@ -3236,6 +3349,7 @@ cf_select_packet(capture_file *cf, int row)
 
   /* Record that this frame is the current frame. */
   cf->current_frame = fdata;
+  cf->current_row = row;
 
   /* Create the logical protocol tree. */
   if (cf->edt != NULL) {
@@ -3248,6 +3362,8 @@ cf_select_packet(capture_file *cf, int row)
   epan_dissect_run(cf->edt, &cf->pseudo_header, cf->pd, cf->current_frame,
           NULL);
 
+  dfilter_macro_build_ftv_cache(cf->edt->tree);
+
   cf_callback_invoke(cf_cb_packet_selected, cf);
 }
 
@@ -3263,6 +3379,7 @@ cf_unselect_packet(capture_file *cf)
 
   /* No packet is selected. */
   cf->current_frame = NULL;
+  cf->current_row = 0;
 
   cf_callback_invoke(cf_cb_packet_unselected, cf);
 
@@ -3396,7 +3513,7 @@ cf_save(capture_file *cf, const char *fname, packet_range_t *range, guint save_f
          capture, so it doesn't need to stay around under that name;
         first, try renaming the capture buffer file to the new name. */
 #ifndef _WIN32
-      if (eth_rename(cf->filename, fname) == 0) {
+      if (ws_rename(cf->filename, fname) == 0) {
        /* That succeeded - there's no need to copy the source file. */
        from_filename = NULL;
        do_copy = FALSE;
@@ -3684,22 +3801,24 @@ file_rename_error_message(int err)
 }
 
 char *
-cf_read_error_message(int err, const gchar *err_info)
+cf_read_error_message(int err, gchar *err_info)
 {
   static char errmsg_errno[1024+1];
 
   switch (err) {
 
   case WTAP_ERR_UNSUPPORTED_ENCAP:
-      g_snprintf(errmsg_errno, sizeof(errmsg_errno),
+    g_snprintf(errmsg_errno, sizeof(errmsg_errno),
                "The file \"%%s\" has a packet with a network type that Wireshark doesn't support.\n(%s)",
                err_info);
-      break;
+    g_free(err_info);
+    break;
 
   case WTAP_ERR_BAD_RECORD:
     g_snprintf(errmsg_errno, sizeof(errmsg_errno),
             "An error occurred while reading from the file \"%%s\": %s.\n(%s)",
             wtap_strerror(err), err_info);
+    g_free(err_info);
     break;
 
   default:
@@ -3825,7 +3944,7 @@ copy_binary_file(const char *from_filename, const char *to_filename)
   guint8        pd[65536];
 
   /* Copy the raw bytes of the file. */
-  from_fd = eth_open(from_filename, O_RDONLY | O_BINARY, 0000 /* no creation so don't matter */);
+  from_fd = ws_open(from_filename, O_RDONLY | O_BINARY, 0000 /* no creation so don't matter */);
   if (from_fd < 0) {
     open_failure_alert_box(from_filename, errno, FALSE);
     goto done;
@@ -3836,23 +3955,23 @@ copy_binary_file(const char *from_filename, const char *to_filename)
      may open the file in text mode, not binary mode, but we want
      to copy the raw bytes of the file, so we need the output file
      to be open in binary mode. */
-  to_fd = eth_open(to_filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);
+  to_fd = ws_open(to_filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);
   if (to_fd < 0) {
     open_failure_alert_box(to_filename, errno, TRUE);
-    eth_close(from_fd);
+    ws_close(from_fd);
     goto done;
   }
 
-  while ((nread = eth_read(from_fd, pd, sizeof pd)) > 0) {
-    nwritten = eth_write(to_fd, pd, nread);
+  while ((nread = ws_read(from_fd, pd, sizeof pd)) > 0) {
+    nwritten = ws_write(to_fd, pd, nread);
     if (nwritten < nread) {
       if (nwritten < 0)
        err = errno;
       else
        err = WTAP_ERR_SHORT_WRITE;
       write_failure_alert_box(to_filename, err);
-      eth_close(from_fd);
-      eth_close(to_fd);
+      ws_close(from_fd);
+      ws_close(to_fd);
       goto done;
     }
   }
@@ -3861,12 +3980,12 @@ copy_binary_file(const char *from_filename, const char *to_filename)
     simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
                  "An error occurred while reading from the file \"%s\": %s.",
                  from_filename, strerror(err));
-    eth_close(from_fd);
-    eth_close(to_fd);
+    ws_close(from_fd);
+    ws_close(to_fd);
     goto done;
   }
-  eth_close(from_fd);
-  if (eth_close(to_fd) < 0) {
+  ws_close(from_fd);
+  if (ws_close(to_fd) < 0) {
     write_failure_alert_box(to_filename, errno);
     goto done;
   }