Sets the packet printing, column display, TCP stream coloring, and GUI
options (see L<"Preferences"> below).
-=item Edit:Filters
+=item Edit:Capture Filters
-Edits the saved list of filters, allowing filters to be added, changed,
-or deleted, and lets a selected filter be applied to the current
-capture, if any.
+Edits the saved list of capture filters, allowing filters to be added,
+changed, or deleted.
+
+=item Edit:Display Filters
+
+Edits the saved list of display filters, allowing filters to be added,
+changed, or deleted.
=item Edit:Protocols
The I<Column title> entry is used to specify the title of the column
displayed at the top of the packet list. The type of data that the column
-displays can be specified using the I<Column format> option menu. The row
-of buttons on the left perform the following actions:
+displays can be specified using the I<Column format> option menu.
+The row of buttons on the left perform the following actions:
=over 6
=back
-=item Filters
+=item Edit Capture Filter List
+
+=item Edit Display Filter List
+
+=item Capture Filter
+
+=item Display Filter
+
+=item Read Filter
+
+=item Search Filter
+
+The I<Edit Capture Filter List> dialog lets you create, modify, and
+delete capture filters, and the I<Edit Display Filter List> dialog lets
+you create, modify, and delete display filters.
+
+The I<Capture Filter> dialog lets you do all of the editing operations
+listed, and also lets you choose or construct a filter to be used when
+capturing packets.
+
+The I<Display Filter> dialog lets you do all of the editing operations
+listed, and also lets you choose or construct a filter to be used to
+filter the current capture being viewed.
+
+The I<Read Filter> dialog lets you do all of the editing operations
+listed, and also lets you choose or construct a filter to be used to
+as a read filter for a capture file you open.
-The I<Filters> dialog lets you create and modify filters, and set the
-default filter to use when capturing data or opening a capture file.
+The I<Search Filter> dialog lets you do all of the editing operations
+listed, and also lets you choose or construct a filter expression to be
+used in a find operation.
-The I<Filter name> entry specifies a descriptive name for a filter, e.g.
-B<Web and DNS traffic>. The I<Filter string> entry is the text that
-actually describes the filtering action to take, as described above.The
-dialog buttons perform the following actions:
+In all of those dialogs, the I<Filter name> entry specifies a
+descriptive name for a filter, e.g. B<Web and DNS traffic>. The
+I<Filter string> entry is the text that actually describes the filtering
+action to take, as described above.The dialog buttons perform the
+following actions:
=over 6
=item New
-If there is text in the two entry boxes, it creates a new associated list
+If there is text in the two entry boxes, creates a new associated list
item.
=item Change
=item Add Expression...
-Pops up a dialog box to allow you to construct a filter expression to
-test a particular field; it offers lists of field names, and, when
-appropriate, lists from which to select tests to perform on the field
-and values with which to compare it.
+For display filter expressions, pops up a dialog box to allow you to
+construct a filter expression to test a particular field; it offers
+lists of field names, and, when appropriate, lists from which to select
+tests to perform on the field and values with which to compare it. In
+that dialog box, the OK button will cause the filter expression you
+constructed to be entered into the I<Filter string> entry at the current
+cursor position.
=item OK
-Sets the filter in the I<Filter string> entry as the active filter. If
-nothing is selected, turns filtering off.
+In the I<Edit Capture Filter List> and I<Edit Display Filter List>
+dialogs, closes the dialog box. In the I<Capture Filter> dialog, closes
+the dialog box and makes the filter in the I<Filter string> entry the
+filter in the I<Capture Preferences> dialog. In the I<Display Filter>
+dialog, closes the dialog box and makes the filter in the I<Filter
+string> entry the current display filter, and applies it to the current
+capture. In the I<Read Filter> dialog, closes the dialog box and makes
+the filter in the I<Filter string> entry the filter in the I<Open
+Capture File> dialog. In the I<Search Filter> dialog, closes the dialog
+box and makes the filter in the I<Filter string> entry the filter in the
+I<Find Frame> dialog.
=item Apply
-Sets the filter in the I<Filter string> entry as the active filter, and
-applies it to the current capture, if any. (The currently selected list
-item must be a display filter, not a capture filter.) If nothing is
-selected, turns filtering off.
+Makes the filter in the I<Filter string> entry the current display
+filter, and applies it to the current capture.
=item Save
-Saves the current filter list in F<$HOME/.ethereal/filters>.
+Saves the current filter list in F<$HOME/.ethereal/cfilters> if the list
+of filters being edited is the list of capture filters or in
+F<$HOME/.ethereal/dfilters> if the list of filters being edited is the
+list of display filters.
=item Cancel
/* filters.c
* Code for reading and writing the filters file.
*
- * $Id: filters.c,v 1.2 2001/01/28 04:52:28 guy Exp $
+ * $Id: filters.c,v 1.3 2001/01/28 09:13:07 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
+#include <errno.h>
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#include "filters.h"
#include "util.h"
+/*
+ * Old filter file name.
+ */
+#define FILTER_FILE_NAME "filters"
+
+/*
+ * Capture filter file name.
+ */
+#define CFILTER_FILE_NAME "cfilters"
+
+/*
+ * Display filter file name.
+ */
+#define DFILTER_FILE_NAME "dfilters"
+
#define FILTER_LINE_SIZE 2048
/*
- * List of filters.
+ * List of capture filters.
+ */
+static GList *capture_filters = NULL;
+
+/*
+ * List of display filters.
*/
-GList *fl = NULL;
+static GList *display_filters = NULL;
+/*
+ * Read in a list of filters.
+ *
+ * On success, "*pref_path_return" is set to NULL.
+ * On error, "*pref_path_return" is set to point to the pathname of
+ * the file we tried to read - it should be freed by our caller -
+ * and "*errno_return" is set to the error.
+ */
void
-get_filter_list(void)
+read_filter_list(filter_list_type_t list, char **pref_path_return,
+ int *errno_return)
{
- GList *flp;
- filter_def *filt;
+ char *ff_path, *ff_dir = PF_DIR, *ff_name;
FILE *ff;
- gchar *ff_path, *ff_name = PF_DIR "/filters", f_buf[FILTER_LINE_SIZE];
- gchar *name_begin, *name_end, *filt_begin;
+ GList **flp;
+ GList *fl_ent;
+ filter_def *filt;
+ char f_buf[FILTER_LINE_SIZE];
+ char *name_begin, *name_end, *filt_begin;
int len, line = 0;
- /* If we already have a list of filters, discard it. */
- if (fl != NULL) {
- flp = g_list_first(fl);
- while (flp) {
- filt = (filter_def *) flp->data;
- g_free(filt->name);
- g_free(filt->strval);
- g_free(filt);
- flp = flp->next;
- }
- g_list_free(fl);
- fl = NULL;
+ *pref_path_return = NULL; /* assume no error */
+
+ switch (list) {
+
+ case CFILTER_LIST:
+ ff_name = CFILTER_FILE_NAME;
+ flp = &capture_filters;
+ break;
+
+ case DFILTER_LIST:
+ ff_name = DFILTER_FILE_NAME;
+ flp = &display_filters;
+ break;
+
+ default:
+ g_assert_not_reached();
+ return;
}
/* To do: generalize this */
- ff_path = (gchar *) g_malloc(strlen(get_home_dir()) + strlen(ff_name) + 4);
- sprintf(ff_path, "%s/%s", get_home_dir(), ff_name);
+ ff_path = (gchar *) g_malloc(strlen(get_home_dir()) + strlen(ff_dir) +
+ strlen(ff_name) + 4);
+ sprintf(ff_path, "%s/%s/%s", get_home_dir(), ff_dir, ff_name);
if ((ff = fopen(ff_path, "r")) == NULL) {
- g_free(ff_path);
- return;
+ /*
+ * Did that fail because we the file didn't exist?
+ */
+ if (errno != ENOENT) {
+ /*
+ * No. Just give up.
+ */
+ *pref_path_return = ff_path;
+ *errno_return = errno;
+ return;
+ }
+
+ /*
+ * Yes. See if there's a "filters" file; if so, read it.
+ * This means that a user will start out with their capture and
+ * display filter lists being identical; each list may contain
+ * filters that don't belong in that list. The user can edit
+ * the filter lists, and delete the ones that don't belong in
+ * a particular list.
+ */
+ sprintf(ff_path, "%s/%s/%s", get_home_dir(), ff_dir, FILTER_FILE_NAME);
+ if ((ff = fopen(ff_path, "r")) == NULL) {
+ /*
+ * Well, that didn't work, either. Just give up.
+ * Return an error if the file existed but we couldn't open it.
+ */
+ if (errno != ENOENT) {
+ *pref_path_return = ff_path;
+ *errno_return = errno;
+ }
+ return;
+ }
+ }
+
+ /* If we already have a list of filters, discard it. */
+ if (*flp != NULL) {
+ fl_ent = g_list_first(*flp);
+ while (fl_ent != NULL) {
+ filt = (filter_def *) fl_ent->data;
+ g_free(filt->name);
+ g_free(filt->strval);
+ g_free(filt);
+ fl_ent = fl_ent->next;
+ }
+ g_list_free(*flp);
+ *flp = NULL;
}
while (fgets(f_buf, FILTER_LINE_SIZE, ff)) {
filt = (filter_def *) g_malloc(sizeof(filter_def));
filt->name = g_strdup(name_begin);
filt->strval = g_strdup(filt_begin);
- fl = g_list_append(fl, filt);
+ *flp = g_list_append(*flp, filt);
}
+ if (ferror(ff)) {
+ *pref_path_return = ff_path;
+ *errno_return = errno;
+ } else
+ g_free(ff_path);
fclose(ff);
- g_free(ff_path);
}
+/*
+ * Get a pointer to a list of filters.
+ */
+static GList **
+get_filter_list(filter_list_type_t list)
+{
+ GList **flp;
+
+ switch (list) {
+
+ case CFILTER_LIST:
+ flp = &capture_filters;
+ break;
+
+ case DFILTER_LIST:
+ flp = &display_filters;
+ break;
+
+ default:
+ g_assert_not_reached();
+ flp = NULL;
+ }
+ return flp;
+}
+
+/*
+ * Get a pointer to the first entry in a filter list.
+ */
+GList *
+get_filter_list_first(filter_list_type_t list)
+{
+ GList **flp;
+
+ flp = get_filter_list(list);
+ return g_list_first(*flp);
+}
+
+/*
+ * Add a new filter to the end of a list.
+ * Returns a pointer to the newly-added entry.
+ */
+GList *
+add_to_filter_list(filter_list_type_t list, char *name, char *expression)
+{
+ GList **flp;
+ filter_def *filt;
+
+ flp = get_filter_list(list);
+ filt = (filter_def *) g_malloc(sizeof(filter_def));
+ filt->name = g_strdup(name);
+ filt->strval = g_strdup(expression);
+ *flp = g_list_append(*flp, filt);
+ return g_list_last(*flp);
+}
+
+/*
+ * Remove a filter from a list.
+ */
+void
+remove_from_filter_list(filter_list_type_t list, GList *fl_entry)
+{
+ GList **flp;
+ filter_def *filt;
+
+ flp = get_filter_list(list);
+ filt = (filter_def *) fl_entry->data;
+ g_free(filt->name);
+ g_free(filt->strval);
+ g_free(filt);
+ *flp = g_list_remove_link(*flp, fl_entry);
+}
+
+/*
+ * Write out a list of filters.
+ *
+ * On success, "*pref_path_return" is set to NULL.
+ * On error, "*pref_path_return" is set to point to the pathname of
+ * the file we tried to read - it should be freed by our caller -
+ * and "*errno_return" is set to the error.
+ */
void
-save_filter_list(void)
+save_filter_list(filter_list_type_t list, char **pref_path_return,
+ int *errno_return)
{
+ gchar *ff_path, *ff_path_new, *ff_dir = PF_DIR, *ff_name;
+ int path_length;
+ GList *fl;
GList *flp;
filter_def *filt;
- gchar *ff_path, *ff_dir = PF_DIR, *ff_name = "filters";
FILE *ff;
struct stat s_buf;
- ff_path = (gchar *) g_malloc(strlen(get_home_dir()) + strlen(ff_dir) +
- strlen(ff_name) + 4);
+ *pref_path_return = NULL; /* assume no error */
+
+ switch (list) {
+
+ case CFILTER_LIST:
+ ff_name = CFILTER_FILE_NAME;
+ fl = capture_filters;
+ break;
+
+ case DFILTER_LIST:
+ ff_name = DFILTER_FILE_NAME;
+ fl = display_filters;
+ break;
+
+ default:
+ g_assert_not_reached();
+ return;
+ }
+
+ path_length = strlen(get_home_dir()) + strlen(ff_dir) + strlen(ff_name)
+ + 4 + 4;
+ ff_path = (gchar *) g_malloc(path_length);
sprintf(ff_path, "%s/%s", get_home_dir(), ff_dir);
if (stat(ff_path, &s_buf) != 0)
sprintf(ff_path, "%s/%s/%s", get_home_dir(), ff_dir, ff_name);
- if ((ff = fopen(ff_path, "w")) != NULL) {
- flp = g_list_first(fl);
- while (flp) {
- filt = (filter_def *) flp->data;
- fprintf(ff, "\"%s\" %s\n", filt->name, filt->strval);
- flp = flp->next;
+ /* Write to "XXX.new", and rename if that succeeds.
+ That means we don't trash the file if we fail to write it out
+ completely. */
+ ff_path_new = (gchar *) g_malloc(path_length);
+ sprintf(ff_path_new, "%s/%s/%s.new", get_home_dir(), ff_dir, ff_name);
+
+ if ((ff = fopen(ff_path_new, "w")) == NULL) {
+ *pref_path_return = ff_path;
+ *errno_return = errno;
+ g_free(ff_path_new);
+ return;
+ }
+ flp = g_list_first(fl);
+ while (flp) {
+ filt = (filter_def *) flp->data;
+ fprintf(ff, "\"%s\" %s\n", filt->name, filt->strval);
+ if (ferror(ff)) {
+ *pref_path_return = ff_path;
+ *errno_return = errno;
+ fclose(ff);
+ unlink(ff_path_new);
+ g_free(ff_path_new);
+ return;
}
- fclose(ff);
+ flp = flp->next;
+ }
+ if (fclose(ff) == EOF) {
+ *pref_path_return = ff_path;
+ *errno_return = errno;
+ unlink(ff_path_new);
+ g_free(ff_path_new);
+ return;
}
+ /* XXX - does "rename()" exist on Win32? If so, does it remove the
+ target first? If so, does that mean it's not atomic? */
+ if (rename(ff_path_new, ff_path) < 0) {
+ *pref_path_return = ff_path;
+ *errno_return = errno;
+ unlink(ff_path_new);
+ g_free(ff_path);
+ g_free(ff_path_new);
+ return;
+ }
+ g_free(ff_path_new);
g_free(ff_path);
}
/* filters.c
* Declarations of routines for reading and writing the filters file.
*
- * $Id: filters.h,v 1.1 2001/01/28 04:43:24 guy Exp $
+ * $Id: filters.h,v 1.2 2001/01/28 09:13:07 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
*/
/*
- * List of filters.
+ * Filter lists.
*/
-extern GList *fl;
+typedef enum {
+ CFILTER_LIST, /* capture filter list */
+ DFILTER_LIST /* display filter list */
+} filter_list_type_t;
/*
* Item in a list of filters.
char *strval; /* filter expression */
} filter_def;
-void get_filter_list(void);
+/*
+ * Read in a list of filters.
+ *
+ * On success, "*pref_path_return" is set to NULL.
+ * On error, "*pref_path_return" is set to point to the pathname of
+ * the file we tried to read - it should be freed by our caller -
+ * and "*errno_return" is set to the error.
+ */
+void read_filter_list(filter_list_type_t list, char **pref_path_return,
+ int *errno_return);
+
+/*
+ * Get a pointer to the first entry in a filter list.
+ */
+GList *get_filter_list_first(filter_list_type_t list);
-void save_filter_list(void);
+/*
+ * Add a new filter to the end of a list.
+ * Returns a pointer to the newly-added entry.
+ */
+GList *add_to_filter_list(filter_list_type_t list, char *name,
+ char *expression);
+
+/*
+ * Remove a filter from a list.
+ */
+void remove_from_filter_list(filter_list_type_t list, GList *fl_entry);
+
+/*
+ * Write out a list of filters.
+ *
+ * On success, "*pref_path_return" is set to NULL.
+ * On error, "*pref_path_return" is set to point to the pathname of
+ * the file we tried to read - it should be freed by our caller -
+ * and "*errno_return" is set to the error.
+ */
+void save_filter_list(filter_list_type_t list, char **pref_path_return,
+ int *errno_return);
* (This used to be a notebook page under "Preferences", hence the
* "prefs" in the file name.)
*
- * $Id: filter_prefs.c,v 1.25 2001/01/28 04:52:29 guy Exp $
+ * $Id: filter_prefs.c,v 1.26 2001/01/28 09:13:09 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
# include "config.h"
#endif
+#include <string.h>
+
#include <gtk/gtk.h>
#include <epan.h>
#include "filter_prefs.h"
#include "dlg_utils.h"
#include "ui_util.h"
+#include "simple_dialog.h"
#include "prefs_dlg.h"
#include "dfilter_expr_dlg.h"
} filter_cb_data;
static GtkWidget *filter_dialog_new(GtkWidget *caller, GtkWidget *filter_te,
- construct_args_t *construct_args, gboolean wants_add_expression_button);
+ filter_list_type_t list, construct_args_t *construct_args);
static void filter_dlg_dclick(GtkWidget *dummy, gpointer main_w_arg);
static void filter_dlg_ok_cb(GtkWidget *ok_bt, gpointer dummy);
static void filter_dlg_apply_cb(GtkWidget *apply_bt, gpointer dummy);
parent_filter_te = gtk_object_get_data(GTK_OBJECT(w), E_FILT_TE_PTR_KEY);
/* Now create a new dialog, without an "Add Expression..." button. */
- filter_browse_w = filter_dialog_new(caller, parent_filter_te, &args,
- FALSE);
+ filter_browse_w = filter_dialog_new(caller, parent_filter_te,
+ CFILTER_LIST, &args);
/* Set the E_FILT_CALLER_PTR_KEY for the new dialog to point to
our caller. */
/* Now create a new dialog, possibly with an "Apply" button, and
definitely with an "Add Expression..." button. */
filter_browse_w = filter_dialog_new(caller, parent_filter_te,
- construct_args, TRUE);
+ DFILTER_LIST, construct_args);
/* Set the E_FILT_CALLER_PTR_KEY for the new dialog to point to
our caller. */
filter_browse_w);
}
-static GtkWidget *global_filter_w;
+static GtkWidget *global_cfilter_w;
+
+/* Create a filter dialog for editing capture filters; this is to be used
+ as a callback for menu items, toolbars, etc.. */
+void
+cfilter_dialog_cb(GtkWidget *w)
+{
+ /* No Apply button, and there's no text widget to set, much less
+ activate, on "OK". */
+ static construct_args_t args = {
+ "Ethereal: Edit Capture Filter List",
+ FALSE,
+ FALSE
+ };
+
+ /* Has a filter dialog box already been opened for editing
+ capture filters? */
+ if (global_cfilter_w != NULL) {
+ /* Yes. Just reactivate it. */
+ reactivate_window(global_cfilter_w);
+ return;
+ }
+
+ /*
+ * No. Create one; we didn't pop this up as a result of pressing
+ * a button next to some text entry field, so don't associate it
+ * with a text entry field.
+ */
+ global_cfilter_w = filter_dialog_new(NULL, NULL, CFILTER_LIST, &args);
+}
+
+static GtkWidget *global_dfilter_w;
-/* Create a filter dialog for editing; this is to be used as a callback
- for menu items, toolbars, etc.. */
+/* Create a filter dialog for editing display filters; this is to be used
+ as a callback for menu items, toolbars, etc.. */
void
-filter_dialog_cb(GtkWidget *w)
+dfilter_dialog_cb(GtkWidget *w)
{
/* No Apply button, and there's no text widget to set, much less
activate, on "OK". */
static construct_args_t args = {
- "Ethereal: Edit Filter List",
+ "Ethereal: Edit Display Filter List",
FALSE,
FALSE
};
- /* Has a filter dialog box already been opened for editing? */
- if (global_filter_w != NULL) {
+ /* Has a filter dialog box already been opened for editing
+ display filters? */
+ if (global_dfilter_w != NULL) {
/* Yes. Just reactivate it. */
- reactivate_window(global_filter_w);
+ reactivate_window(global_dfilter_w);
return;
}
* a button next to some text entry field, so don't associate it
* with a text entry field.
*/
- global_filter_w = filter_dialog_new(NULL, NULL, &args, TRUE);
+ global_dfilter_w = filter_dialog_new(NULL, NULL, DFILTER_LIST, &args);
}
-/* List of filter dialogs, so that if the list of filters changes (the
- model, if you will), we can update all of their lists displaying
+/* List of capture filter dialogs, so that if the list of filters changes
+ (the model, if you will), we can update all of their lists displaying
+ the filters (the views). */
+static GList *cfilter_dialogs;
+
+/* List of display filter dialogs, so that if the list of filters changes
+ (the model, if you will), we can update all of their lists displaying
the filters (the views). */
-static GList *filter_dialogs;
+static GList *dfilter_dialogs;
static void
-remember_filter_dialog(GtkWidget *main_w)
+remember_filter_dialog(GtkWidget *main_w, GList **filter_dialogs)
{
- filter_dialogs = g_list_append(filter_dialogs, main_w);
+ *filter_dialogs = g_list_append(*filter_dialogs, main_w);
}
-/* Remove a filter dialog from the list of filter_dialogss. */
+/* Remove a filter dialog from the specified list of filter_dialogs. */
static void
-forget_filter_dialog(GtkWidget *main_w)
+forget_filter_dialog(GtkWidget *main_w, filter_list_type_t list)
+{
+ switch (list) {
+
+ case CFILTER_LIST:
+ cfilter_dialogs = g_list_remove(cfilter_dialogs, main_w);
+ break;
+
+ case DFILTER_LIST:
+ dfilter_dialogs = g_list_remove(dfilter_dialogs, main_w);
+ break;
+
+ default:
+ g_assert_not_reached();
+ break;
+ }
+}
+
+/* Get the dialog list corresponding to a particular filter list. */
+static GList *
+get_filter_dialog_list(filter_list_type_t list)
{
- filter_dialogs = g_list_remove(filter_dialogs, main_w);
+ switch (list) {
+
+ case CFILTER_LIST:
+ return cfilter_dialogs;
+
+ case DFILTER_LIST:
+ return dfilter_dialogs;
+
+ default:
+ g_assert_not_reached();
+ return NULL;
+ }
}
static GtkWidget *
filter_dialog_new(GtkWidget *caller, GtkWidget *parent_filter_te,
- construct_args_t *construct_args, gboolean wants_add_expression_button)
+ filter_list_type_t list, construct_args_t *construct_args)
{
GtkWidget *main_w, /* main window */
*main_vb, /* main container */
*filter_te,
*add_expression_bt;
GtkWidget *l_select = NULL;
- GList *flp = NULL;
+ GList *fl_entry;
filter_def *filt;
gchar *filter_te_str = NULL;
+ GList **filter_dialogs;
+ static filter_list_type_t cfilter_list = CFILTER_LIST;
+ static filter_list_type_t dfilter_list = DFILTER_LIST;
+ filter_list_type_t *filter_list_p;
+
+ /* Get a pointer to a static variable holding the type of filter on
+ which we're working, so we can pass that pointer to callback
+ routines. */
+ switch (list) {
+
+ case CFILTER_LIST:
+ filter_dialogs = &cfilter_dialogs;
+ filter_list_p = &cfilter_list;
+ break;
+
+ case DFILTER_LIST:
+ filter_dialogs = &dfilter_dialogs;
+ filter_list_p = &dfilter_list;
+ break;
+
+ default:
+ g_assert_not_reached();
+ filter_dialogs = NULL;
+ filter_list_p = NULL;
+ break;
+ }
main_w = dlg_window_new(construct_args->title);
gtk_object_set_data(GTK_OBJECT(main_w), E_FILT_CONSTRUCT_ARGS_KEY,
/* Call a handler when we're destroyed, so we can inform
our caller, if any, that we've been destroyed. */
gtk_signal_connect(GTK_OBJECT(main_w), "destroy",
- GTK_SIGNAL_FUNC(filter_dlg_destroy), NULL);
+ GTK_SIGNAL_FUNC(filter_dlg_destroy), filter_list_p);
main_vb = gtk_vbox_new(FALSE, 5);
gtk_container_border_width(GTK_CONTAINER(main_vb), 5);
new_bt = gtk_button_new_with_label ("New");
gtk_signal_connect(GTK_OBJECT(new_bt), "clicked",
- GTK_SIGNAL_FUNC(filter_new_bt_clicked_cb), NULL);
+ GTK_SIGNAL_FUNC(filter_new_bt_clicked_cb), filter_list_p);
gtk_container_add(GTK_CONTAINER(list_bb), new_bt);
gtk_widget_show(new_bt);
chg_bt = gtk_button_new_with_label ("Change");
gtk_widget_set_sensitive(chg_bt, FALSE);
gtk_signal_connect(GTK_OBJECT(chg_bt), "clicked",
- GTK_SIGNAL_FUNC(filter_chg_bt_clicked_cb), NULL);
+ GTK_SIGNAL_FUNC(filter_chg_bt_clicked_cb), filter_list_p);
gtk_object_set_data(GTK_OBJECT(main_w), E_FILT_CHG_BT_KEY, chg_bt);
gtk_signal_connect(GTK_OBJECT(chg_bt), "destroy",
GTK_SIGNAL_FUNC(filter_chg_bt_destroy_cb), NULL);
copy_bt = gtk_button_new_with_label ("Copy");
gtk_widget_set_sensitive(copy_bt, FALSE);
gtk_signal_connect(GTK_OBJECT(copy_bt), "clicked",
- GTK_SIGNAL_FUNC(filter_copy_bt_clicked_cb), NULL);
+ GTK_SIGNAL_FUNC(filter_copy_bt_clicked_cb), filter_list_p);
gtk_object_set_data(GTK_OBJECT(main_w), E_FILT_COPY_BT_KEY, copy_bt);
gtk_signal_connect(GTK_OBJECT(copy_bt), "destroy",
GTK_SIGNAL_FUNC(filter_copy_bt_destroy_cb), NULL);
del_bt = gtk_button_new_with_label ("Delete");
gtk_widget_set_sensitive(del_bt, FALSE);
gtk_signal_connect(GTK_OBJECT(del_bt), "clicked",
- GTK_SIGNAL_FUNC(filter_del_bt_clicked_cb), NULL);
+ GTK_SIGNAL_FUNC(filter_del_bt_clicked_cb), filter_list_p);
gtk_object_set_data(GTK_OBJECT(main_w), E_FILT_DEL_BT_KEY, del_bt);
gtk_signal_connect(GTK_OBJECT(del_bt), "destroy",
GTK_SIGNAL_FUNC(filter_del_bt_destroy_cb), NULL);
gtk_container_add(GTK_CONTAINER(list_bb), del_bt);
gtk_widget_show(del_bt);
- if (wants_add_expression_button) {
+ if (list == DFILTER_LIST) {
/* Create the "Add Expression..." button, to pop up a dialog
for constructing filter comparison expressions. */
add_expression_bt = gtk_button_new_with_label("Add Expression...");
gtk_object_set_data(GTK_OBJECT(filter_l), E_FILT_DBLFUNC_KEY, filter_dlg_dclick);
gtk_object_set_data(GTK_OBJECT(filter_l), E_FILT_DBLARG_KEY, main_w);
- flp = g_list_first(fl);
- while (flp) {
- filt = (filter_def *) flp->data;
+ fl_entry = get_filter_list_first(list);
+ while (fl_entry != NULL) {
+ filt = (filter_def *) fl_entry->data;
nl_lb = gtk_label_new(filt->name);
nl_item = gtk_list_item_new();
gtk_container_add(GTK_CONTAINER(filter_l), nl_item);
gtk_widget_show(nl_item);
gtk_object_set_data(GTK_OBJECT(nl_item), E_FILT_LBL_KEY, nl_lb);
- gtk_object_set_data(GTK_OBJECT(nl_item), E_FILT_LIST_ITEM_MODEL_KEY, flp);
+ gtk_object_set_data(GTK_OBJECT(nl_item), E_FILT_LIST_ITEM_MODEL_KEY,
+ fl_entry);
if (filter_te_str && filt->strval) {
if (strcmp(filter_te_str, filt->strval) == 0)
l_select = nl_item;
}
- flp = flp->next;
+ fl_entry = fl_entry->next;
}
/* Middle row: Filter name entry */
save_bt = gtk_button_new_with_label ("Save");
gtk_signal_connect(GTK_OBJECT(save_bt), "clicked",
- GTK_SIGNAL_FUNC(filter_dlg_save_cb), GTK_OBJECT(main_w));
+ GTK_SIGNAL_FUNC(filter_dlg_save_cb), filter_list_p);
GTK_WIDGET_SET_FLAGS(save_bt, GTK_CAN_DEFAULT);
gtk_box_pack_start(GTK_BOX(bbox), save_bt, TRUE, TRUE, 0);
gtk_widget_show(save_bt);
dlg_set_cancel(main_w, cancel_bt);
- remember_filter_dialog(main_w);
+ remember_filter_dialog(main_w, filter_dialogs);
gtk_widget_show(main_w);
}
static void
-filter_dlg_save_cb(GtkWidget *save_bt, gpointer parent_w)
+filter_dlg_save_cb(GtkWidget *save_bt, gpointer data)
{
- save_filter_list();
+ filter_list_type_t list = *(filter_list_type_t *)data;
+ char *f_path;
+ int f_save_errno;
+ char *filter_type;
+
+ save_filter_list(list, &f_path, &f_save_errno);
+ if (f_path != NULL) {
+ /* We had an error saving the filter. */
+ switch (list) {
+
+ case CFILTER_LIST:
+ filter_type = "capture";
+ break;
+
+ case DFILTER_LIST:
+ filter_type = "display";
+ break;
+
+ default:
+ g_assert_not_reached();
+ filter_type = NULL;
+ break;
+ }
+ simple_dialog(ESD_TYPE_CRIT, NULL,
+ "Could not save to your %s filter file\n\"%s\": %s.",
+ filter_type, f_path, strerror(f_save_errno));
+ g_free(f_path);
+ }
}
static void
static void
filter_dlg_destroy(GtkWidget *win, gpointer data)
{
+ filter_list_type_t list = *(filter_list_type_t *)data;
GtkWidget *caller;
/* Get the widget that requested that we be popped up, if any.
} else {
/* This is an editing dialog popped up from, for example,
a menu item; note that we no longer have one. */
- g_assert(win == global_filter_w);
- global_filter_w = NULL;
+ switch (list) {
+
+ case CFILTER_LIST:
+ g_assert(win == global_cfilter_w);
+ global_cfilter_w = NULL;
+ break;
+
+ case DFILTER_LIST:
+ g_assert(win == global_dfilter_w);
+ global_dfilter_w = NULL;
+ break;
+
+ default:
+ g_assert_not_reached();
+ break;
+ }
}
/* Remove this from the list of filter dialog windows. */
- forget_filter_dialog(win);
+ forget_filter_dialog(win, list);
/* Now nuke this window. */
gtk_grab_remove(GTK_WIDGET(win));
GtkWidget *name_te = gtk_object_get_data(GTK_OBJECT(main_w), E_FILT_NAME_TE_KEY);
GtkWidget *filter_te = gtk_object_get_data(GTK_OBJECT(main_w), E_FILT_FILTER_TE_KEY);
GtkWidget *filter_l = gtk_object_get_data(GTK_OBJECT(main_w), E_FILT_FILTER_L_KEY);
- filter_def *filt;
+ filter_list_type_t list = *(filter_list_type_t *)data;
+ GList *fl_entry;
gchar *name, *strval;
new_filter_cb_args_t args;
strval = gtk_entry_get_text(GTK_ENTRY(filter_te));
if (strlen(name) > 0 && strlen(strval) > 0) {
- filt = (filter_def *) g_malloc(sizeof(filter_def));
- filt->name = g_strdup(name);
- filt->strval = g_strdup(strval);
- fl = g_list_append(fl, filt);
+ /* Add a new entry to the filter list. */
+ fl_entry = add_to_filter_list(list, name, strval);
/* Update all the filter list widgets, not just the one in
the dialog box in which we clicked on "Copy". */
args.active_filter_l = filter_l;
- args.nflp = g_list_last(fl);
- g_list_foreach(filter_dialogs, new_filter_cb, &args);
+ args.nflp = fl_entry;
+ g_list_foreach(get_filter_dialog_list(list), new_filter_cb, &args);
}
}
GtkWidget *filter_l = gtk_object_get_data(GTK_OBJECT(main_w), E_FILT_FILTER_L_KEY);
filter_def *filt;
gchar *name = "", *strval = "";
- GList *sl, *flp;
+ GList *sl, *fl_entry;
GtkObject *l_item;
GtkLabel *nl_lb;
+ filter_list_type_t list = *(filter_list_type_t *)data;
sl = GTK_LIST(filter_l)->selection;
name = gtk_entry_get_text(GTK_ENTRY(name_te));
if (sl) { /* Something was selected */
l_item = GTK_OBJECT(sl->data);
- flp = (GList *) gtk_object_get_data(l_item, E_FILT_LIST_ITEM_MODEL_KEY);
- nl_lb = (GtkLabel *) gtk_object_get_data(l_item, E_FILT_LBL_KEY);
- if (flp && nl_lb) {
- filt = (filter_def *) flp->data;
+ fl_entry = (GList *) gtk_object_get_data(l_item, E_FILT_LIST_ITEM_MODEL_KEY);
+ nl_lb = (GtkLabel *) gtk_object_get_data(l_item, E_FILT_LBL_KEY);
+ if (fl_entry != NULL && nl_lb != NULL) {
+ filt = (filter_def *) fl_entry->data;
if (strlen(name) > 0 && strlen(strval) > 0 && filt) {
g_free(filt->name);
/* Update all the filter list widgets, not just the one in
the dialog box in which we clicked on "Copy". */
- g_list_foreach(filter_dialogs, chg_filter_cb, flp);
+ g_list_foreach(get_filter_dialog_list(list), chg_filter_cb, fl_entry);
}
}
}
{
GtkWidget *main_w = gtk_widget_get_toplevel(w);
GtkWidget *filter_l = gtk_object_get_data(GTK_OBJECT(main_w), E_FILT_FILTER_L_KEY);
- GList *sl, *flp;
- filter_def *filt, *nfilt;
- gchar *prefix = "Copy of ";
+ GList *sl, *fl_entry, *nfl_entry;
+ gchar *prefix = "Copy of ", *name;
GtkObject *l_item;
+ filter_def *filt;
+ filter_list_type_t list = *(filter_list_type_t *)data;
new_filter_cb_args_t args;
sl = GTK_LIST(filter_l)->selection;
if (sl) { /* Something was selected */
l_item = GTK_OBJECT(sl->data);
- flp = (GList *) gtk_object_get_data(l_item, E_FILT_LIST_ITEM_MODEL_KEY);
- if (flp) {
- filt = (filter_def *) flp->data;
- nfilt = (filter_def *) g_malloc(sizeof(filter_def));
- nfilt->name = g_malloc(strlen(prefix) + strlen(filt->name) + 1);
- sprintf(nfilt->name, "%s%s", prefix, filt->name);
- nfilt->strval = g_strdup(filt->strval);
- fl = g_list_append(fl, nfilt);
+ fl_entry = (GList *) gtk_object_get_data(l_item, E_FILT_LIST_ITEM_MODEL_KEY);
+ if (fl_entry != NULL) {
+ /* Add a new entry, copying the existing entry, to the filter list. */
+ filt = (filter_def *) fl_entry->data;
+ name = g_malloc(strlen(prefix) + strlen(filt->name) + 1);
+ sprintf(name, "%s%s", prefix, filt->name);
+ nfl_entry = add_to_filter_list(list, name, filt->strval);
+ g_free(name);
/* Update all the filter list widgets, not just the one in
the dialog box in which we clicked on "Copy". */
args.active_filter_l = filter_l;
- args.nflp = g_list_last(fl);
- g_list_foreach(filter_dialogs, new_filter_cb, &args);
+ args.nflp = nfl_entry;
+ g_list_foreach(get_filter_dialog_list(list), new_filter_cb, &args);
}
}
}
{
GtkWidget *main_w = gtk_widget_get_toplevel(w);
GtkWidget *filter_l = gtk_object_get_data(GTK_OBJECT(main_w), E_FILT_FILTER_L_KEY);
- GList *sl, *flp;
- filter_def *filt;
+ filter_list_type_t list = *(filter_list_type_t *)data;
+ GList *sl, *fl_entry;
GtkObject *l_item;
gint pos;
-
+
sl = GTK_LIST(filter_l)->selection;
if (sl) { /* Something was selected */
l_item = GTK_OBJECT(sl->data);
pos = gtk_list_child_position(GTK_LIST(filter_l),
GTK_WIDGET(l_item));
- flp = (GList *) gtk_object_get_data(l_item, E_FILT_LIST_ITEM_MODEL_KEY);
- if (flp) {
- filt = (filter_def *) flp->data;
- g_free(filt->name);
- g_free(filt->strval);
- g_free(filt);
- fl = g_list_remove_link(fl, flp);
+ fl_entry = (GList *) gtk_object_get_data(l_item, E_FILT_LIST_ITEM_MODEL_KEY);
+ if (fl_entry != NULL) {
+ /* Remove the entry from the filter list. */
+ remove_from_filter_list(list, fl_entry);
/* Update all the filter list widgets, not just the one in
the dialog box in which we clicked on "Delete". */
- g_list_foreach(filter_dialogs, delete_filter_cb, &pos);
+ g_list_foreach(get_filter_dialog_list(list), delete_filter_cb, &pos);
}
}
}
* (This used to be a notebook page under "Preferences", hence the
* "prefs" in the file name.)
*
- * $Id: filter_prefs.h,v 1.9 2001/01/21 02:27:24 guy Exp $
+ * $Id: filter_prefs.h,v 1.10 2001/01/28 09:13:10 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
void capture_filter_construct_cb(GtkWidget *w, gpointer user_data);
void display_filter_construct_cb(GtkWidget *w, gpointer construct_args_ptr);
-void filter_dialog_cb(GtkWidget *);
+void cfilter_dialog_cb(GtkWidget *w);
+void dfilter_dialog_cb(GtkWidget *w);
#define E_FILT_TE_KEY "filter_te"
#define E_FILT_TE_PTR_KEY "filter_te_ptr"
/* main.c
*
- * $Id: main.c,v 1.174 2001/01/28 04:52:29 guy Exp $
+ * $Id: main.c,v 1.175 2001/01/28 09:13:10 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
WSADATA wsaData;
#endif
- char *gpf_path, *pf_path;
- int gpf_open_errno, pf_open_errno;
+ char *gpf_path, *pf_path, *cf_path, *df_path;
+ int gpf_open_errno, pf_open_errno, cf_open_errno, df_open_errno;
int err;
#ifdef HAVE_LIBPCAP
gboolean start_capture = FALSE;
/* Read the preference files. */
prefs = read_prefs(&gpf_open_errno, &gpf_path, &pf_open_errno, &pf_path);
- /* Read the filter file. */
- get_filter_list();
+ /* Read the capture filter file. */
+ read_filter_list(CFILTER_LIST, &cf_path, &cf_open_errno);
+
+ /* Read the display filter file. */
+ read_filter_list(DFILTER_LIST, &df_path, &df_open_errno);
/* Initialize the capture file struct */
cfile.plist = NULL;
strerror(pf_open_errno));
}
+ /* If the user's capture filter file exists but we failed to open it,
+ pop up an alert box; we defer that until now, so that the alert
+ box is more likely to come up on top of the main window. */
+ if (cf_path != NULL) {
+ simple_dialog(ESD_TYPE_WARN, NULL,
+ "Could not open your capture filter file\n\"%s\": %s.", cf_path,
+ strerror(cf_open_errno));
+ g_free(cf_path);
+ }
+
+ /* If the user's display filter file exists but we failed to open it,
+ pop up an alert box; we defer that until now, so that the alert
+ box is more likely to come up on top of the main window. */
+ if (df_path != NULL) {
+ simple_dialog(ESD_TYPE_WARN, NULL,
+ "Could not open your display filter file\n\"%s\": %s.", df_path,
+ strerror(df_open_errno));
+ g_free(df_path);
+ }
+
#ifdef HAVE_LIBPCAP
if (capture_child) {
/* This is the child process for a sync mode or fork mode capture,
/* menu.c
* Menu routines
*
- * $Id: menu.c,v 1.46 2000/10/19 22:59:24 guy Exp $
+ * $Id: menu.c,v 1.47 2001/01/28 09:13:10 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
{"/Edit/_Unmark All Frames", NULL, GTK_MENU_FUNC(unmark_all_frames_cb), 0, NULL},
{"/Edit/<separator>", NULL, NULL, 0, "<Separator>"},
{"/Edit/_Preferences...", NULL, GTK_MENU_FUNC(prefs_cb), 0, NULL},
- {"/Edit/_Filters...", NULL, GTK_MENU_FUNC(filter_dialog_cb), 0, NULL},
+ {"/Edit/_Capture Filters...", NULL, GTK_MENU_FUNC(cfilter_dialog_cb), 0, NULL},
+ {"/Edit/_Display Filters...", NULL, GTK_MENU_FUNC(dfilter_dialog_cb), 0, NULL},
{"/Edit/P_rotocols...", NULL, GTK_MENU_FUNC(proto_cb), 0, NULL},
#ifdef HAVE_LIBPCAP
{"/_Capture", NULL, NULL, 0, "<Branch>" },
static GtkItemFactoryEntry packet_list_menu_items[] =
{
{"/Follow TCP Stream", NULL, GTK_MENU_FUNC(follow_stream_cb), 0, NULL},
- {"/Filters...", NULL, GTK_MENU_FUNC(filter_dialog_cb), 0, NULL},
+ {"/Display Filters...", NULL, GTK_MENU_FUNC(dfilter_dialog_cb), 0, NULL},
{"/<separator>", NULL, NULL, 0, "<Separator>"},
{"/Colorize Display...", NULL, GTK_MENU_FUNC(color_display_cb), 0, NULL},
{"/Print...", NULL, GTK_MENU_FUNC(file_print_cmd_cb), 0, NULL},
static GtkItemFactoryEntry tree_view_menu_items[] =
{
{"/Follow TCP Stream", NULL, GTK_MENU_FUNC(follow_stream_cb), 0, NULL},
- {"/Filters...", NULL, GTK_MENU_FUNC(filter_dialog_cb), 0, NULL},
+ {"/Display Filters...", NULL, GTK_MENU_FUNC(dfilter_dialog_cb), 0, NULL},
{"/<separator>", NULL, NULL, 0, "<Separator>"},
{"/Resolve Name", NULL, GTK_MENU_FUNC(resolve_name_cb), 0, NULL},
{"/Protocol Properties...", NULL, GTK_MENU_FUNC(properties_cb), 0, NULL},
static GtkItemFactoryEntry hexdump_menu_items[] =
{
{"/Follow TCP Stream", NULL, GTK_MENU_FUNC(follow_stream_cb), 0, NULL},
- {"/Filters...", NULL, GTK_MENU_FUNC(filter_dialog_cb), 0, NULL}
+ {"/Display Filters...", NULL, GTK_MENU_FUNC(dfilter_dialog_cb), 0, NULL}
};
static int initialize = TRUE;