Now that WinPcap is a DLL, I can load it at run-time rather than load-time.
[obnox/wireshark/wip.git] / file.c
diff --git a/file.c b/file.c
index 80d5154b1f1a655b05ece6d73a8fd67c69a9ea70..ff5527c1f960e0641a3b79423bb96ffeeff5839a 100644 (file)
--- a/file.c
+++ b/file.c
@@ -1,7 +1,7 @@
 /* file.c
  * File I/O routines
  *
- * $Id: file.c,v 1.198 2000/07/09 23:22:18 guy Exp $
+ * $Id: file.c,v 1.235 2001/03/24 02:14:54 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@zing.org>
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
-#include <sys/stat.h>
 #include <errno.h>
-#include <fcntl.h>
 #include <signal.h>
 
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+
 #ifdef NEED_SNPRINTF_H
-# ifdef HAVE_STDARG_H
-#  include <stdarg.h>
-# else
-#  include <varargs.h>
-# endif
 # include "snprintf.h"
 #endif
 
 # include <netinet/in.h>
 #endif
 
+#include <epan.h>
+
 #include "gtk/main.h"
+#include "color.h"
+#include "gtk/color_utils.h"
 #include "column.h"
 #include "packet.h"
 #include "print.h"
 #include "menu.h"
 #include "util.h"
 #include "simple_dialog.h"
+#include "progress_dlg.h"
 #include "ui_util.h"
 #include "prefs.h"
 #include "gtk/proto_draw.h"
-#include "dfilter.h"
+#include "gtk/packet_win.h"
+#include "dfilter/dfilter.h"
 #include "conversation.h"
 #include "globals.h"
+#include "gtk/colors.h"
 
-#include "plugins.h"
-
-extern GtkWidget *packet_list, *info_bar, *byte_view, *tree_view;
+extern GtkWidget *packet_list, *info_bar, *byte_nb_ptr, *tree_view;
 extern guint      file_ctx;
 
 gboolean auto_scroll_live = FALSE;
@@ -96,7 +102,7 @@ static guint32 prevsec, prevusec;
 static void read_packet(capture_file *cf, int offset);
 
 static void rescan_packets(capture_file *cf, const char *action,
-       gboolean refilter);
+       gboolean refilter, gboolean redissect);
 
 static void set_selected_row(int row);
 
@@ -105,6 +111,7 @@ static void thaw_clist(capture_file *cf);
 
 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);
 
 /* Update the progress bar this many times when reading a file. */
 #define N_PROGBAR_UPDATES      100
@@ -140,7 +147,7 @@ open_cap_file(char *fname, gboolean is_tempfile, capture_file *cf)
   close_cap_file(cf, info_bar);
 
   /* Initialize the table of conversations. */
-  conversation_init();
+  epan_conversation_init();
 
   /* Initialize protocol-specific variables */
   init_all_protocols();
@@ -165,6 +172,7 @@ open_cap_file(char *fname, gboolean is_tempfile, capture_file *cf)
 
   cf->cd_t      = wtap_file_type(cf->wth);
   cf->count     = 0;
+  cf->drops_known = FALSE;
   cf->drops     = 0;
   cf->esec      = 0;
   cf->eusec     = 0;
@@ -183,7 +191,7 @@ open_cap_file(char *fname, gboolean is_tempfile, capture_file *cf)
   return (0);
 
 fail:
-  simple_dialog(ESD_TYPE_WARN, NULL,
+  simple_dialog(ESD_TYPE_CRIT, NULL,
                        file_open_error_message(err, FALSE), fname);
   return (err);
 }
@@ -219,7 +227,7 @@ close_cap_file(capture_file *cf, void *w)
     cf->plist_chunk = NULL;
   }
   if (cf->rfcode != NULL) {
-    dfilter_destroy(cf->rfcode);
+    dfilter_free(cf->rfcode);
     cf->rfcode = NULL;
   }
   cf->plist = NULL;
@@ -247,6 +255,7 @@ close_cap_file(capture_file *cf, void *w)
   set_menus_for_captured_packets(FALSE);
   set_menus_for_selected_packet(FALSE);
   set_menus_for_capture_in_progress(FALSE);
+  set_menus_for_selected_tree_row(FALSE);
 
   /* We have no file open. */
   cf->state = FILE_CLOSED;
@@ -259,7 +268,8 @@ set_display_filename(capture_file *cf)
 {
   gchar  *name_ptr;
   size_t  msg_len;
-  gchar  *done_fmt = " File: %s  Drops: %u";
+  static const gchar done_fmt_nodrops[] = " File: %s";
+  static const gchar done_fmt_drops[] = " File: %s  Drops: %u";
   gchar  *done_msg;
   gchar  *win_name_fmt = "%s - Ethereal";
   gchar  *win_name;
@@ -274,9 +284,15 @@ set_display_filename(capture_file *cf)
     name_ptr = "<capture>";
   }
 
-  msg_len = strlen(name_ptr) + strlen(done_fmt) + 64;
-  done_msg = g_malloc(msg_len);
-  snprintf(done_msg, msg_len, done_fmt, name_ptr, cf->drops);
+  if (cf->drops_known) {
+    msg_len = strlen(name_ptr) + strlen(done_fmt_drops) + 64;
+    done_msg = g_malloc(msg_len);
+    snprintf(done_msg, msg_len, done_fmt_drops, name_ptr, cf->drops);
+  } else {
+    msg_len = strlen(name_ptr) + strlen(done_fmt_nodrops);
+    done_msg = g_malloc(msg_len);
+    snprintf(done_msg, msg_len, done_fmt_nodrops, name_ptr);
+  }
   gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx, done_msg);
   g_free(done_msg);
 
@@ -324,7 +340,7 @@ read_cap_file(capture_file *cf, int *err)
   progbar = create_progress_dlg(load_msg, "Stop", &stop_flag);
   g_free(load_msg);
 
-  while ((data_offset = wtap_read(cf->wth, err)) > 0) {
+  while ((wtap_read(cf->wth, err, &data_offset))) {
     /* 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()"
@@ -384,7 +400,7 @@ read_cap_file(capture_file *cf, int *err)
   if (cf->first_displayed != NULL)
     gtk_signal_emit_by_name(GTK_OBJECT(packet_list), "select_row", 0);
 
-  if (data_offset < 0) {
+  if (*err != 0) {
     /* Put up a message box noting that the read failed somewhere along
        the line.  Don't throw out the stuff we managed to read, though,
        if any. */
@@ -409,13 +425,14 @@ read_cap_file(capture_file *cf, int *err)
       break;
 
     default:
-      sprintf(errmsg_errno, "An error occurred while reading the"
-                              " capture file: %s.", wtap_strerror(*err));
+      snprintf(errmsg_errno, sizeof(errmsg_errno),
+              "An error occurred while reading the"
+              " capture file: %s.", wtap_strerror(*err));
       errmsg = errmsg_errno;
       break;
     }
     snprintf(err_str, sizeof err_str, errmsg);
-    simple_dialog(ESD_TYPE_WARN, NULL, err_str);
+    simple_dialog(ESD_TYPE_CRIT, NULL, err_str);
     return (READ_ERROR);
   } else
     return (READ_SUCCESS);
@@ -462,7 +479,7 @@ continue_tail_cap_file(capture_file *cf, int to_read, int *err)
 
   gtk_clist_freeze(GTK_CLIST(packet_list));
 
-  while (to_read != 0 && (data_offset = wtap_read(cf->wth, err)) > 0) {
+  while (to_read != 0 && (wtap_read(cf->wth, err, &data_offset))) {
     if (cf->state == FILE_READ_ABORTED) {
       /* Well, the user decided to exit Ethereal.  Break out of the
          loop, and let the code below (which is called even if there
@@ -488,7 +505,7 @@ continue_tail_cap_file(capture_file *cf, int to_read, int *err)
        "finish_tail_cap_file()" will be called, and it will clean up
        and exit. */
     return READ_ABORTED;
-  } else if (data_offset < 0) {
+  } else if (*err != 0) {
     /* We got an error reading the capture file.
        XXX - pop up a dialog box? */
     return (READ_ERROR);
@@ -503,7 +520,7 @@ finish_tail_cap_file(capture_file *cf, int *err)
 
   gtk_clist_freeze(GTK_CLIST(packet_list));
 
-  while ((data_offset = wtap_read(cf->wth, err)) > 0) {
+  while ((wtap_read(cf->wth, err, &data_offset))) {
     if (cf->state == FILE_READ_ABORTED) {
       /* Well, the user decided to abort the read.  Break out of the
          loop, and let the code below (which is called even if there
@@ -557,7 +574,7 @@ finish_tail_cap_file(capture_file *cf, int *err)
   set_menus_for_capture_file(TRUE);
   set_menus_for_unsaved_capture_file(!cf->user_saved);
 
-  if (data_offset < 0) {
+  if (*err != 0) {
     /* We got an error reading the capture file.
        XXX - pop up a dialog box? */
     return (READ_ERROR);
@@ -568,9 +585,7 @@ finish_tail_cap_file(capture_file *cf, int *err)
 
 typedef struct {
   color_filter_t *colorf;
-  proto_tree   *protocol_tree;
-  const guint8 *pd;
-  frame_data   *fdata;
+  epan_dissect_t *edt;
 } apply_color_filter_args;
 
 /*
@@ -585,7 +600,7 @@ apply_color_filter(gpointer filter_arg, gpointer argp)
   apply_color_filter_args *args = argp;
 
   if (colorf->c_colorfilter != NULL && args->colorf == NULL) {
-    if (dfilter_apply(colorf->c_colorfilter, args->protocol_tree, args->pd, args->fdata->cap_len))
+    if (dfilter_apply_edt(colorf->c_colorfilter, args->edt))
       args->colorf = colorf;
   }
 }
@@ -598,6 +613,8 @@ add_packet_to_packet_list(frame_data *fdata, capture_file *cf,
   apply_color_filter_args args;
   gint          i, row;
   proto_tree   *protocol_tree = NULL;
+  epan_dissect_t *edt;
+  GdkColor      fg, bg;
 
   /* We don't yet have a color filter to apply. */
   args.colorf = NULL;
@@ -610,18 +627,10 @@ add_packet_to_packet_list(frame_data *fdata, capture_file *cf,
     firstusec = fdata->abs_usecs;
   }
 
-  /* Get the time elapsed between the first packet and this packet. */
-  cf->esec = fdata->abs_secs - firstsec;
-  if (firstusec <= fdata->abs_usecs) {
-    cf->eusec = fdata->abs_usecs - firstusec;
-  } else {
-    cf->eusec = (fdata->abs_usecs + 1000000) - firstusec;
-    cf->esec--;
-  }
-
   fdata->cinfo = &cf->cinfo;
   for (i = 0; i < fdata->cinfo->num_cols; i++) {
-    fdata->cinfo->col_data[i][0] = '\0';
+    fdata->cinfo->col_buf[i][0] = '\0';
+    fdata->cinfo->col_data[i] = fdata->cinfo->col_buf[i];
   }
 
   /* If either
@@ -630,20 +639,14 @@ add_packet_to_packet_list(frame_data *fdata, capture_file *cf,
 
        we have a list of color filters;
 
-       we have plugins to apply;
-
      allocate a protocol tree root node, so that we'll construct
      a protocol tree against which a filter expression can be
      evaluated. */
-  if ((cf->dfcode != NULL && refilter) || filter_list != NULL
-#ifdef HAVE_PLUGINS
-       || enabled_plugins_number > 0
-#endif
-       )
+  if ((cf->dfcode != NULL && refilter) || filter_list != NULL)
     protocol_tree = proto_tree_create_root();
 
   /* Dissect the frame. */
-  dissect_packet(pseudo_header, buf, fdata, protocol_tree);
+  edt = epan_dissect_new(pseudo_header, buf, fdata, protocol_tree);
 
   /* If we have a display filter, apply it if we're refiltering, otherwise
      leave the "passed_dfilter" flag alone.
@@ -652,7 +655,7 @@ add_packet_to_packet_list(frame_data *fdata, capture_file *cf,
   if (cf->dfcode != NULL) {
     if (refilter) {
       if (cf->dfcode != NULL)
-        fdata->flags.passed_dfilter = dfilter_apply(cf->dfcode, protocol_tree, buf, fdata->cap_len) ? 1 : 0;
+        fdata->flags.passed_dfilter = dfilter_apply_edt(cf->dfcode, edt) ? 1 : 0;
       else
         fdata->flags.passed_dfilter = 1;
     }
@@ -663,9 +666,7 @@ add_packet_to_packet_list(frame_data *fdata, capture_file *cf,
      the color filters. */
   if (fdata->flags.passed_dfilter) {
     if (filter_list != NULL) {
-      args.protocol_tree = protocol_tree;
-      args.pd = buf;
-      args.fdata = fdata;
+      args.edt = edt;
       g_slist_foreach(filter_list, apply_color_filter, &args);
     }
   }
@@ -675,6 +676,8 @@ add_packet_to_packet_list(frame_data *fdata, capture_file *cf,
   if (protocol_tree != NULL)
     proto_tree_free(protocol_tree);
 
+  epan_dissect_free(edt);
+
   if (fdata->flags.passed_dfilter) {
     /* This frame passed the display filter, so add it to the clist. */
 
@@ -688,18 +691,22 @@ add_packet_to_packet_list(frame_data *fdata, capture_file *cf,
     }
 
     /* Get the time elapsed between the first packet and this packet. */
-    fdata->rel_secs = cf->esec;
-    fdata->rel_usecs = cf->eusec;
+    compute_timestamp_diff(&fdata->rel_secs, &fdata->rel_usecs,
+               fdata->abs_secs, fdata->abs_usecs, firstsec, firstusec);
+
+    /* If it's greater than the current elapsed time, set the elapsed time
+       to it (we check for "greater than" so as not to be confused by
+       time moving backwards). */
+    if (cf->esec < fdata->rel_secs
+       || (cf->esec == fdata->rel_secs && cf->eusec < fdata->rel_usecs)) {
+      cf->esec = fdata->rel_secs;
+      cf->eusec = fdata->rel_usecs;
+    }
   
     /* Get the time elapsed between the previous displayed packet and
        this packet. */
-    fdata->del_secs = fdata->abs_secs - prevsec;
-    if (prevusec <= fdata->abs_usecs) {
-      fdata->del_usecs = fdata->abs_usecs - prevusec;
-    } else {
-      fdata->del_usecs = (fdata->abs_usecs + 1000000) - prevusec;
-      fdata->del_secs--;
-    }
+    compute_timestamp_diff(&fdata->del_secs, &fdata->del_usecs,
+               fdata->abs_secs, fdata->abs_usecs, prevsec, prevusec);
     prevsec = fdata->abs_secs;
     prevusec = fdata->abs_usecs;
 
@@ -727,15 +734,18 @@ add_packet_to_packet_list(frame_data *fdata, capture_file *cf,
     row = gtk_clist_append(GTK_CLIST(packet_list), fdata->cinfo->col_data);
     gtk_clist_set_row_data(GTK_CLIST(packet_list), row, fdata);
 
-    if (filter_list != NULL && (args.colorf != NULL)) {
-        gtk_clist_set_background(GTK_CLIST(packet_list), row,
-                   &args.colorf->bg_color);
-        gtk_clist_set_foreground(GTK_CLIST(packet_list), row,
-                   &args.colorf->fg_color);
+    if (fdata->flags.marked) {
+       color_t_to_gdkcolor(&bg, &prefs.gui_marked_bg);
+       color_t_to_gdkcolor(&fg, &prefs.gui_marked_fg);
+    } else if (filter_list != NULL && (args.colorf != NULL)) {
+       bg = args.colorf->bg_color;
+       fg = args.colorf->fg_color;
     } else {
-        gtk_clist_set_background(GTK_CLIST(packet_list), row, &WHITE);
-        gtk_clist_set_foreground(GTK_CLIST(packet_list), row, &BLACK);
+       bg = WHITE;
+       fg = BLACK;
     }
+    gtk_clist_set_background(GTK_CLIST(packet_list), row, &bg);
+    gtk_clist_set_foreground(GTK_CLIST(packet_list), row, &fg);
   } else {
     /* This frame didn't pass the display filter, so it's not being added
        to the clist, and thus has no row. */
@@ -755,6 +765,7 @@ read_packet(capture_file *cf, int offset)
   int           passed;
   proto_tree   *protocol_tree;
   frame_data   *plist_end;
+  epan_dissect_t *edt;
 
   /* Allocate the next list entry, and add it to the list. */
   fdata = g_mem_chunk_alloc(cf->plist_chunk);
@@ -762,6 +773,7 @@ read_packet(capture_file *cf, int offset)
   fdata->next = NULL;
   fdata->prev = NULL;
   fdata->pfd  = NULL;
+  fdata->data_src  = NULL;
   fdata->pkt_len  = phdr->len;
   fdata->cap_len  = phdr->caplen;
   fdata->file_off = offset;
@@ -770,14 +782,16 @@ read_packet(capture_file *cf, int offset)
   fdata->abs_usecs = phdr->ts.tv_usec;
   fdata->flags.encoding = CHAR_ASCII;
   fdata->flags.visited = 0;
+  fdata->flags.marked = 0;
   fdata->cinfo = NULL;
 
   passed = TRUE;
   if (cf->rfcode) {
     protocol_tree = proto_tree_create_root();
-    dissect_packet(pseudo_header, buf, fdata, protocol_tree);
-    passed = dfilter_apply(cf->rfcode, protocol_tree, buf, fdata->cap_len);
+    edt = epan_dissect_new(pseudo_header, buf, fdata, protocol_tree);
+    passed = dfilter_apply_edt(cf->rfcode, edt);
     proto_tree_free(protocol_tree);
+    epan_dissect_free(edt);
   }   
   if (passed) {
     plist_end = cf->plist_end;
@@ -807,7 +821,7 @@ read_packet(capture_file *cf, int offset)
 int
 filter_packets(capture_file *cf, gchar *dftext)
 {
-  dfilter *dfcode;
+  dfilter_t *dfcode;
 
   if (dftext == NULL) {
     /* The new filter is an empty filter (i.e., display all packets). */
@@ -816,9 +830,9 @@ filter_packets(capture_file *cf, gchar *dftext)
     /*
      * We have a filter; try to compile it.
      */
-    if (dfilter_compile(dftext, &dfcode) != 0) {
+    if (!dfilter_compile(dftext, &dfcode)) {
       /* The attempt failed; report an error. */
-      simple_dialog(ESD_TYPE_WARN, NULL, dfilter_error_msg);
+      simple_dialog(ESD_TYPE_CRIT, NULL, dfilter_error_msg);
       return 0;
     }
 
@@ -835,24 +849,25 @@ filter_packets(capture_file *cf, gchar *dftext)
     g_free(cf->dfilter);
   cf->dfilter = dftext;
   if (cf->dfcode != NULL)
-    dfilter_destroy(cf->dfcode);
+    dfilter_free(cf->dfcode);
   cf->dfcode = dfcode;
 
-  /* Now rescan the packet list, applying the new filter. */
-  rescan_packets(cf, "Filtering", TRUE);
+  /* Now rescan the packet list, applying the new filter, but not
+     throwing away information constructed on a previous pass. */
+  rescan_packets(cf, "Filtering", TRUE, FALSE);
   return 1;
 }
 
 void
 colorize_packets(capture_file *cf)
 {
-  rescan_packets(cf, "Colorizing", FALSE);
+  rescan_packets(cf, "Colorizing", FALSE, FALSE);
 }
 
 void
 redissect_packets(capture_file *cf)
 {
-  rescan_packets(cf, "Reprocessing", TRUE);
+  rescan_packets(cf, "Reprocessing", TRUE, TRUE);
 }
 
 /* Rescan the list of packets, reconstructing the CList.
@@ -860,9 +875,15 @@ redissect_packets(capture_file *cf)
    "action" describes why we're doing this; it's used in the progress
    dialog box.
 
-   "refilter" is TRUE if we need to re-evaluate the filter expression. */
+   "refilter" is TRUE if we need to re-evaluate the filter expression.
+
+   "redissect" is TRUE if we need to make the dissectors reconstruct
+   any state information they have (because a preference that affects
+   some dissector has changed, meaning some dissector might construct
+   its state differently from the way it was constructed the last time). */
 static void
-rescan_packets(capture_file *cf, const char *action, gboolean refilter)
+rescan_packets(capture_file *cf, const char *action, gboolean refilter,
+               gboolean redissect)
 {
   frame_data *fdata;
   progdlg_t *progbar;
@@ -884,14 +905,18 @@ rescan_packets(capture_file *cf, const char *action, gboolean refilter)
      rebuild the clist, however. */
   selected_row = -1;
 
-  /* We need to re-initialize all the state information that protocols
-     keep, because we're making a fresh pass through all the packets. */
+  if (redissect) {
+    /* We need to re-initialize all the state information that protocols
+       keep, because some preference that controls a dissector has changed,
+       which might cause the state information to be constructed differently
+       by that dissector. */
 
-  /* Initialize the table of conversations. */
-  conversation_init();
+    /* Initialize the table of conversations. */
+    epan_conversation_init();
 
-  /* Initialize protocol-specific variables */
-  init_all_protocols();
+    /* Initialize protocol-specific variables */
+    init_all_protocols();
+  }
 
   /* Freeze the packet list while we redo it, so we don't get any
      screen updates while it happens. */
@@ -958,6 +983,22 @@ rescan_packets(capture_file *cf, const char *action, gboolean refilter)
 
     count++;
 
+    if (redissect) {
+      /* Since all state for the frame was destroyed, mark the frame
+       * as not visited, free the GSList referring to the state
+       * data (the per-frame data itself was freed by
+       * "init_all_protocols()"), and null out the GSList pointer. */
+      fdata->flags.visited = 0;
+      if (fdata->pfd) {
+       g_slist_free(fdata->pfd);
+      }
+      fdata->pfd = NULL;
+      if (fdata->data_src) {   /* release data source list */
+       g_slist_free(fdata->data_src);
+      }
+      fdata->data_src = NULL;
+    }
+
     wtap_seek_read (cf->wth, fdata->file_off, &cf->pseudo_header,
        cf->pd, fdata->cap_len);
 
@@ -967,6 +1008,29 @@ rescan_packets(capture_file *cf, const char *action, gboolean refilter)
       selected_row = row;
   }
  
+  if (redissect) {
+    /* Clear out what remains of the visited flags and per-frame data
+       pointers.
+
+       XXX - that may cause various forms of bogosity when dissecting
+       these frames, as they won't have been seen by this sequential
+       pass, but the only alternative I see is to keep scanning them
+       even though the user requested that the scan stop, and that
+       would leave the user stuck with an Ethereal grinding on
+       until it finishes.  Should we just stick them with that? */
+    for (; fdata != NULL; fdata = fdata->next) {
+      fdata->flags.visited = 0;
+      if (fdata->pfd) {
+       g_slist_free(fdata->pfd);
+      }
+      fdata->pfd = NULL;
+      if (fdata->data_src) {
+       g_slist_free(fdata->data_src);
+      }
+      fdata->data_src = NULL;
+    }
+  }
+
   /* We're done filtering the packets; destroy the progress bar. */
   destroy_progress_dlg(progbar);
 
@@ -1005,6 +1069,7 @@ print_packets(capture_file *cf, print_args_t *print_args)
   char        *cp;
   int         column_len;
   int         line_len;
+  epan_dissect_t *edt = NULL;
 
   cf->print_fh = open_print_dest(print_args->to_file, print_args->dest);
   if (cf->print_fh == NULL)
@@ -1118,9 +1183,10 @@ print_packets(capture_file *cf, print_args_t *print_args)
            the logical protocol tree. */
         fdata->cinfo = &cf->cinfo;
         for (i = 0; i < fdata->cinfo->num_cols; i++) {
-          fdata->cinfo->col_data[i][0] = '\0';
+          fdata->cinfo->col_buf[i][0] = '\0';
+          fdata->cinfo->col_data[i] = fdata->cinfo->col_buf[i];
         }
-        dissect_packet(&cf->pseudo_header, cf->pd, fdata, NULL);
+        edt = epan_dissect_new(&cf->pseudo_header, cf->pd, fdata, NULL);
         fill_in_columns(fdata);
         cp = &line_buf[0];
         line_len = 0;
@@ -1157,7 +1223,7 @@ print_packets(capture_file *cf, print_args_t *print_args)
 
         /* Create the logical protocol tree. */
         protocol_tree = proto_tree_create_root();
-        dissect_packet(&cf->pseudo_header, cf->pd, fdata, protocol_tree);
+        edt = epan_dissect_new(&cf->pseudo_header, cf->pd, fdata, protocol_tree);
 
         /* Print the information in that tree. */
         proto_tree_print(FALSE, print_args, (GNode *)protocol_tree,
@@ -1167,13 +1233,13 @@ print_packets(capture_file *cf, print_args_t *print_args)
 
        if (print_args->print_hex) {
          /* Print the full packet data as hex. */
-         print_hex_data(cf->print_fh, print_args->format, cf->pd,
-                       fdata->cap_len, fdata->flags.encoding);
+         print_hex_data(cf->print_fh, print_args->format, fdata);
        }
 
         /* Print a blank line if we print anything after this. */
         print_separator = TRUE;
       }
+      epan_dissect_free(edt);
     }
   }
 
@@ -1277,7 +1343,7 @@ change_time_formats(capture_file *cf)
           if (cf->cinfo.fmt_matx[i][COL_CLS_TIME]) {
             /* This is one of the columns that shows the time in
                "command-line-specified" format; update it. */
-            cf->cinfo.col_data[i][0] = '\0';
+            cf->cinfo.col_buf[i][0] = '\0';
             col_set_cls_time(fdata, i);
             gtk_clist_set_text(GTK_CLIST(packet_list), row, i,
                          cf->cinfo.col_data[i]);
@@ -1308,19 +1374,32 @@ static void
 clear_tree_and_hex_views(void)
 {
   /* Clear the hex dump. */
-  gtk_text_freeze(GTK_TEXT(byte_view));
-  gtk_text_set_point(GTK_TEXT(byte_view), 0);
-  gtk_text_forward_delete(GTK_TEXT(byte_view),
-    gtk_text_get_length(GTK_TEXT(byte_view)));
-  gtk_text_thaw(GTK_TEXT(byte_view));
 
+  GtkWidget *byte_view;
+  int i;
+
+/* Get the current tab scroll window, then get the text widget  */
+/* from the E_BYTE_VIEW_TEXT_INFO_KEY data field               */
+
+  i = gtk_notebook_get_current_page( GTK_NOTEBOOK(byte_nb_ptr));
+
+  if ( i >= 0){
+    byte_view = gtk_notebook_get_nth_page( GTK_NOTEBOOK(byte_nb_ptr), i);
+    byte_view = gtk_object_get_data(GTK_OBJECT(byte_view), E_BYTE_VIEW_TEXT_INFO_KEY);
+
+    gtk_text_freeze(GTK_TEXT(byte_view));
+    gtk_text_set_point(GTK_TEXT(byte_view), 0);
+    gtk_text_forward_delete(GTK_TEXT(byte_view),
+      gtk_text_get_length(GTK_TEXT(byte_view)));
+    gtk_text_thaw(GTK_TEXT(byte_view));
+  }
   /* Remove all nodes in ctree. This is how it's done in testgtk.c in GTK+ */
   gtk_clist_clear ( GTK_CLIST(tree_view) );
 
 }
 
 gboolean
-find_packet(capture_file *cf, dfilter *sfcode)
+find_packet(capture_file *cf, dfilter_t *sfcode)
 {
   frame_data *start_fd;
   frame_data *fdata;
@@ -1333,6 +1412,7 @@ find_packet(capture_file *cf, dfilter *sfcode)
   proto_tree *protocol_tree;
   gboolean frame_matched;
   int row;
+  epan_dissect_t       *edt;
 
   start_fd = cf->current_frame;
   if (start_fd != NULL)  {
@@ -1397,9 +1477,10 @@ find_packet(capture_file *cf, dfilter *sfcode)
         protocol_tree = proto_tree_create_root();
         wtap_seek_read(cf->wth, fdata->file_off, &cf->pseudo_header,
                        cf->pd, fdata->cap_len);
-        dissect_packet(&cf->pseudo_header, cf->pd, fdata, protocol_tree);
-        frame_matched = dfilter_apply(sfcode, protocol_tree, cf->pd, fdata->cap_len);
+        edt = epan_dissect_new(&cf->pseudo_header, cf->pd, fdata, protocol_tree);
+        frame_matched = dfilter_apply_edt(sfcode, edt);
         proto_tree_free(protocol_tree);
+       epan_dissect_free(edt);
         if (frame_matched) {
           new_fd = fdata;
           break;       /* found it! */
@@ -1458,6 +1539,8 @@ void
 select_packet(capture_file *cf, int row)
 {
   frame_data *fdata;
+  tvbuff_t *bv_tvb;
+  int i;
 
   /* Get the frame data struct pointer for this frame */
   fdata = (frame_data *) gtk_clist_get_row_data(GTK_CLIST(packet_list), row);
@@ -1505,15 +1588,21 @@ select_packet(capture_file *cf, int row)
       proto_tree_free(cf->protocol_tree);
   cf->protocol_tree = proto_tree_create_root();
   proto_tree_is_visible = TRUE;
-  dissect_packet(&cf->pseudo_header, cf->pd, cf->current_frame,
+  cf->edt = epan_dissect_new(&cf->pseudo_header, cf->pd, cf->current_frame,
                cf->protocol_tree);
   proto_tree_is_visible = FALSE;
 
   /* Display the GUI protocol tree and hex dump. */
   clear_tree_and_hex_views();
+
+  i = 0; 
+  while((bv_tvb = g_slist_nth_data ( cf->current_frame->data_src, i++))){
+       add_byte_view( tvb_get_name( bv_tvb), tvb_get_ptr(bv_tvb, 0, -1), tvb_length(bv_tvb));
+  }
+
   proto_tree_draw(cf->protocol_tree, tree_view);
-  packet_hex_print(GTK_TEXT(byte_view), cf->pd, cf->current_frame->cap_len,
-                       -1, -1, cf->current_frame->flags.encoding);
+
+  set_notebook_page( byte_nb_ptr, 0);
 
   /* A packet is selected. */
   set_menus_for_selected_packet(TRUE);
@@ -1527,6 +1616,7 @@ unselect_packet(capture_file *cf)
   if (cf->protocol_tree != NULL) {
     proto_tree_free(cf->protocol_tree);
     cf->protocol_tree = NULL;
+    epan_dissect_free(cf->edt);
   }
 
   finfo_selected = NULL;
@@ -1598,7 +1688,7 @@ thaw_clist(capture_file *cf)
 }
 
 int
-save_cap_file(char *fname, capture_file *cf, gboolean save_filtered,
+save_cap_file(char *fname, capture_file *cf, gboolean save_filtered, gboolean save_marked,
                guint save_format)
 {
   gchar        *from_filename;
@@ -1606,7 +1696,6 @@ save_cap_file(char *fname, capture_file *cf, gboolean save_filtered,
   size_t        msg_len;
   int           err;
   gboolean      do_copy;
-  int           from_fd, to_fd, nread, nwritten;
   wtap_dumper  *pdh;
   frame_data   *fdata;
   struct wtap_pkthdr hdr;
@@ -1620,7 +1709,7 @@ save_cap_file(char *fname, capture_file *cf, gboolean save_filtered,
   gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx, save_msg);
   g_free(save_msg);
 
-  if (!save_filtered && save_format == cf->cd_t) {
+  if (!save_filtered && !save_marked && save_format == cf->cd_t) {
     /* We're not filtering packets, and we're saving it in the format
        it's already in, so we can just move or copy the raw data. */
 
@@ -1651,7 +1740,7 @@ save_cap_file(char *fname, capture_file *cf, gboolean save_filtered,
             the temporary directory, and that might be fixable - but
             is it worth requiring the user to go off and fix it?) */
          err = errno;
-         simple_dialog(ESD_TYPE_WARN, NULL,
+         simple_dialog(ESD_TYPE_CRIT, NULL,
                                file_rename_error_message(err), fname);
          goto done;
        }
@@ -1668,58 +1757,9 @@ save_cap_file(char *fname, capture_file *cf, gboolean save_filtered,
     }
     /* Copy the file, if we haven't moved it. */
     if (do_copy) {
-      /* Copy the raw bytes of the file. */
-      from_fd = open(from_filename, O_RDONLY | O_BINARY);
-      if (from_fd < 0) {
-       err = errno;
-       simple_dialog(ESD_TYPE_WARN, NULL,
-                       file_open_error_message(err, TRUE), from_filename);
-       goto done;
-      }
-
-      /* Use open() instead of creat() so that we can pass the O_BINARY
-         flag, which is relevant on Win32; it appears that "creat()"
-        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 = open(fname, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);
-      if (to_fd < 0) {
-       err = errno;
-       simple_dialog(ESD_TYPE_WARN, NULL,
-                       file_open_error_message(err, TRUE), fname);
-       close(from_fd);
-       goto done;
-      }
-
-      while ((nread = read(from_fd, pd, sizeof pd)) > 0) {
-       nwritten = write(to_fd, pd, nread);
-       if (nwritten < nread) {
-         if (nwritten < 0)
-           err = errno;
-         else
-           err = WTAP_ERR_SHORT_WRITE;
-         simple_dialog(ESD_TYPE_WARN, NULL,
-                               file_write_error_message(err), fname);
-         close(from_fd);
-         close(to_fd);
-         goto done;
-       }
-      }
-      if (nread < 0) {
-       err = errno;
-       simple_dialog(ESD_TYPE_WARN, NULL,
-                       file_read_error_message(err), from_filename);
-       close(from_fd);
-       close(to_fd);
-       goto done;
-      }
-      close(from_fd);
-      if (close(to_fd) < 0) {
-       err = errno;
-       simple_dialog(ESD_TYPE_WARN, NULL,
-               file_close_error_message(err), fname);
-       goto done;
-      }
+           if (!copy_binary_file(from_filename, fname)) {
+               goto done;
+           }
     }
   } else {
     /* Either we're filtering packets, or we're saving in a different
@@ -1727,22 +1767,30 @@ save_cap_file(char *fname, capture_file *cf, gboolean save_filtered,
        we have to do it by writing the packets out in Wiretap. */
     pdh = wtap_dump_open(fname, save_format, cf->lnk_t, cf->snap, &err);
     if (pdh == NULL) {
-      simple_dialog(ESD_TYPE_WARN, NULL,
+      simple_dialog(ESD_TYPE_CRIT, NULL,
                        file_open_error_message(err, TRUE), fname);
       goto done;
     }
 
     /* XXX - have a way to save only the packets currently selected by
-       the display filter.
+       the display filter or the marked ones.
 
        If we do that, should we make that file the current file?  If so,
        it means we can no longer get at the other packets.  What does
        NetMon do? */
     for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
       /* XXX - do a progress bar */
-      if (!save_filtered || fdata->flags.passed_dfilter) {
-       /* Either we're saving all frames, or we're saving filtered frames
-          and this one passed the display filter - save it. */
+      if ((!save_filtered && !save_marked) ||
+         (save_filtered && fdata->flags.passed_dfilter && !save_marked) ||
+         (save_marked && fdata->flags.marked && !save_filtered) ||
+         (save_filtered && save_marked && fdata->flags.passed_dfilter &&
+          fdata->flags.marked)) {
+       /* Either :
+          - we're saving all frames, or
+          - we're saving filtered frames and this one passed the display filter or
+          - we're saving marked frames (and it has been marked) or
+          - we're saving filtered _and_ marked frames,
+          save it. */
         hdr.ts.tv_sec = fdata->abs_secs;
         hdr.ts.tv_usec = fdata->abs_usecs;
         hdr.caplen = fdata->cap_len;
@@ -1752,7 +1800,7 @@ save_cap_file(char *fname, capture_file *cf, gboolean save_filtered,
                pd, fdata->cap_len);
 
         if (!wtap_dump(pdh, &hdr, &pseudo_header, pd, &err)) {
-           simple_dialog(ESD_TYPE_WARN, NULL,
+           simple_dialog(ESD_TYPE_CRIT, NULL,
                                file_write_error_message(err), fname);
            wtap_dump_close(pdh, &err);
            goto done;
@@ -1772,7 +1820,7 @@ done:
   /* Pop the "Saving:" message off the status bar. */
   gtk_statusbar_pop(GTK_STATUSBAR(info_bar), file_ctx);
   if (err == 0) {
-    if (!save_filtered) {
+    if (!save_filtered && !save_marked) {
       /* We saved the entire capture, not just some packets from it.
          Open and read the file we saved it to.
 
@@ -1811,7 +1859,7 @@ done:
 }
 
 char *
-file_open_error_message(int err, int for_writing)
+file_open_error_message(int err, gboolean for_writing)
 {
   char *errmsg;
   static char errmsg_errno[1024+1];
@@ -1819,7 +1867,7 @@ file_open_error_message(int err, int for_writing)
   switch (err) {
 
   case WTAP_ERR_NOT_REGULAR_FILE:
-    errmsg = "The file \"%s\" is invalid.";
+    errmsg = "The file \"%s\" is a \"special file\" or socket or other non-regular file.";
     break;
 
   case WTAP_ERR_FILE_UNKNOWN_FORMAT:
@@ -1875,8 +1923,13 @@ file_open_error_message(int err, int for_writing)
       errmsg = "You do not have permission to read the file \"%s\".";
     break;
 
+  case EISDIR:
+    errmsg = "\"%s\" is a directory (folder), not a file.";
+    break;
+
   default:
-    sprintf(errmsg_errno, "The file \"%%s\" could not be opened: %s.",
+    snprintf(errmsg_errno, sizeof(errmsg_errno),
+                   "The file \"%%s\" could not be opened: %s.",
                                wtap_strerror(err));
     errmsg = errmsg_errno;
     break;
@@ -1901,7 +1954,8 @@ file_rename_error_message(int err)
     break;
 
   default:
-    sprintf(errmsg_errno, "The file \"%%s\" could not be moved: %s.",
+    snprintf(errmsg_errno, sizeof(errmsg_errno),
+                   "The file \"%%s\" could not be moved: %s.",
                                wtap_strerror(err));
     errmsg = errmsg_errno;
     break;
@@ -1914,7 +1968,8 @@ file_read_error_message(int err)
 {
   static char errmsg_errno[1024+1];
 
-  sprintf(errmsg_errno, "An error occurred while reading from the file \"%%s\": %s.",
+  snprintf(errmsg_errno, sizeof(errmsg_errno),
+                 "An error occurred while reading from the file \"%%s\": %s.",
                                wtap_strerror(err));
   return errmsg_errno;
 }
@@ -1938,7 +1993,8 @@ file_write_error_message(int err)
 #endif
 
   default:
-    sprintf(errmsg_errno, "An error occurred while writing to the file \"%%s\": %s.",
+    snprintf(errmsg_errno, sizeof(errmsg_errno),
+                   "An error occurred while writing to the file \"%%s\": %s.",
                                wtap_strerror(err));
     errmsg = errmsg_errno;
     break;
@@ -1963,7 +2019,7 @@ file_close_error_message(int err)
     break;
 
   case WTAP_ERR_SHORT_WRITE:
-    errmsg = "Not all the data could be written to the file \"%s\".";
+    errmsg = "Not all the packets could be written to the file \"%s\".";
     break;
 
   case ENOSPC:
@@ -1977,10 +2033,83 @@ file_close_error_message(int err)
 #endif
 
   default:
-    sprintf(errmsg_errno, "An error occurred while closing the file \"%%s\": %s.",
+    snprintf(errmsg_errno, sizeof(errmsg_errno),
+                   "An error occurred while closing the file \"%%s\": %s.",
                                wtap_strerror(err));
     errmsg = errmsg_errno;
     break;
   }
   return errmsg;
 }
+
+
+/* Copies a file in binary mode, for those operating systems that care about
+ * such things.
+ * Returns TRUE on success, FALSE on failure. If a failure, it also
+ * displays a simple dialog window with the error message.
+ */
+static gboolean
+copy_binary_file(char *from_filename, char *to_filename)
+{
+       int           from_fd, to_fd, nread, nwritten, err;
+       guint8        pd[65536]; /* XXX - Hmm, 64K here, 64K in save_cap_file(),
+                                   perhaps we should make just one 64K buffer. */
+
+      /* Copy the raw bytes of the file. */
+      from_fd = open(from_filename, O_RDONLY | O_BINARY);
+      if (from_fd < 0) {
+       err = errno;
+       simple_dialog(ESD_TYPE_CRIT, NULL,
+                       file_open_error_message(err, TRUE), from_filename);
+       goto done;
+      }
+
+      /* Use open() instead of creat() so that we can pass the O_BINARY
+         flag, which is relevant on Win32; it appears that "creat()"
+        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 = open(to_filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);
+      if (to_fd < 0) {
+       err = errno;
+       simple_dialog(ESD_TYPE_CRIT, NULL,
+                       file_open_error_message(err, TRUE), to_filename);
+       close(from_fd);
+       goto done;
+      }
+
+      while ((nread = read(from_fd, pd, sizeof pd)) > 0) {
+       nwritten = write(to_fd, pd, nread);
+       if (nwritten < nread) {
+         if (nwritten < 0)
+           err = errno;
+         else
+           err = WTAP_ERR_SHORT_WRITE;
+         simple_dialog(ESD_TYPE_CRIT, NULL,
+                               file_write_error_message(err), to_filename);
+         close(from_fd);
+         close(to_fd);
+         goto done;
+       }
+      }
+      if (nread < 0) {
+       err = errno;
+       simple_dialog(ESD_TYPE_CRIT, NULL,
+                       file_read_error_message(err), from_filename);
+       close(from_fd);
+       close(to_fd);
+       goto done;
+      }
+      close(from_fd);
+      if (close(to_fd) < 0) {
+       err = errno;
+       simple_dialog(ESD_TYPE_CRIT, NULL,
+               file_close_error_message(err), to_filename);
+       goto done;
+      }
+
+      return TRUE;
+
+   done:
+      return FALSE;
+}