From Dick Gooris (and me :-)

more ways to choose which packets can be saved,
in the save(as) dialog box

svn path=/trunk/; revision=9476
This commit is contained in:
Ulf Lamping 2003-12-29 20:05:59 +00:00
parent 4b37928246
commit 14e2a790f9
8 changed files with 782 additions and 101 deletions

85
file.c
View File

@ -1,7 +1,7 @@
/* file.c
* File I/O routines
*
* $Id: file.c,v 1.331 2003/12/19 23:39:53 guy Exp $
* $Id: file.c,v 1.332 2003/12/29 20:03:38 ulfl Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
@ -116,7 +116,7 @@ static gboolean find_packet(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);
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
@ -2242,8 +2242,7 @@ unmark_frame(capture_file *cf, frame_data *frame)
* up a message box for the failure.
*/
gboolean
cf_save(char *fname, capture_file *cf, gboolean save_filtered,
gboolean save_marked, guint save_format)
cf_save(char *fname, capture_file *cf, packet_range_t *range, guint save_format)
{
gchar *from_filename;
gchar *name_ptr, *save_msg, *save_fmt = " Saving: %s...";
@ -2256,6 +2255,7 @@ cf_save(char *fname, capture_file *cf, gboolean save_filtered,
union wtap_pseudo_header pseudo_header;
guint8 pd[65536];
struct stat infile, outfile;
range_process_e process_this;
name_ptr = get_basename(fname);
msg_len = strlen(name_ptr) + strlen(save_fmt) + 2;
@ -2282,7 +2282,12 @@ cf_save(char *fname, capture_file *cf, gboolean save_filtered,
goto fail;
}
if (!save_filtered && !save_marked && save_format == cf->cd_t) {
/* Used to be :
* if (!save_filtered && !save_marked && !save_manual_range &&
* !save_marked_range && !save_curr && save_format == cf->cd_t) {
*/
if (packet_range_process_all(range) && 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. */
@ -2349,49 +2354,53 @@ cf_save(char *fname, capture_file *cf, gboolean save_filtered,
NetMon do? */
for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
/* XXX - do a progress bar */
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;
hdr.len = fdata->pkt_len;
hdr.pkt_encap = fdata->lnk_t;
if (!wtap_seek_read(cf->wth, fdata->file_off, &pseudo_header,
pd, fdata->cap_len, &err)) {
simple_dialog(ESD_TYPE_CRIT, NULL,
file_read_error_message(err), cf->filename);
wtap_dump_close(pdh, &err);
goto fail;
}
process_this = packet_range_process(range, fdata);
if (!wtap_dump(pdh, &hdr, &pseudo_header, pd, &err)) {
simple_dialog(ESD_TYPE_CRIT, NULL,
file_write_error_message(err), fname);
wtap_dump_close(pdh, &err);
goto fail;
}
}
}
if (process_this == range_process_next) {
continue;
} else if (process_this == range_processing_finished) {
break;
} else {
/* init the wtap header for saving */
hdr.ts.tv_sec = fdata->abs_secs;
hdr.ts.tv_usec = fdata->abs_usecs;
hdr.caplen = fdata->cap_len;
hdr.len = fdata->pkt_len;
hdr.pkt_encap = fdata->lnk_t;
/* Get the packet */
if (!wtap_seek_read(cf->wth, fdata->file_off, &pseudo_header,
pd, fdata->cap_len, &err)) {
simple_dialog(ESD_TYPE_CRIT, NULL,
file_read_error_message(err), cf->filename);
wtap_dump_close(pdh, &err);
goto fail;
}
/* and save the packet */
if (!wtap_dump(pdh, &hdr, &pseudo_header, pd, &err)) {
simple_dialog(ESD_TYPE_CRIT, NULL,
file_write_error_message(err), fname);
wtap_dump_close(pdh, &err);
goto fail;
}
}
} /* for */
if (!wtap_dump_close(pdh, &err)) {
simple_dialog(ESD_TYPE_WARN, NULL,
file_close_error_message(err), fname);
goto fail;
}
}
} /* save_all */
/* Pop the "Saving:" message off the status bar. */
statusbar_pop_file_msg();
if (!save_filtered && !save_marked) {
/* XXX: I'm not sure how this should look like! */
if (packet_range_process_all(range)) {
/*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.

5
file.h
View File

@ -1,7 +1,7 @@
/* file.h
* Definitions for file structures and routines
*
* $Id: file.h,v 1.108 2003/09/24 00:47:36 guy Exp $
* $Id: file.h,v 1.109 2003/12/29 20:03:38 ulfl Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
@ -25,6 +25,7 @@
#ifndef __FILE_H__
#define __FILE_H__
#include "range.h"
#include "wiretap/wtap.h"
#include <epan/dfilter/dfilter.h>
#include "print.h"
@ -48,7 +49,7 @@ int cf_start_tail(char *, gboolean, capture_file *);
read_status_t cf_continue_tail(capture_file *, int, int *);
read_status_t cf_finish_tail(capture_file *, int *);
/* size_t read_frame_header(capture_file *); */
gboolean cf_save(char *, capture_file *, gboolean, gboolean, guint);
gboolean cf_save(char *fname, capture_file * cf, packet_range_t *range, guint save_format);
gchar *cf_get_display_name(capture_file *);
int filter_packets(capture_file *cf, gchar *dfilter);

View File

@ -1,7 +1,7 @@
# Makefile.am
# Automake file for the GTK interface routines for Ethereal
#
# $Id: Makefile.am,v 1.81 2003/12/17 22:13:05 guy Exp $
# $Id: Makefile.am,v 1.82 2003/12/29 20:05:59 ulfl Exp $
#
# Ethereal - Network traffic analyzer
# By Gerald Combs <gerald@ethereal.com>
@ -131,6 +131,7 @@ libui_a_SOURCES = \
proto_draw.h \
proto_hier_stats_dlg.h \
proto_hier_stats_dlg.c \
range.c \
rtp_analysis.h \
rtp_stream.c \
rtp_stream.h \
@ -225,6 +226,8 @@ libui_a_SOURCES = \
proto_draw.h \
proto_hier_stats_dlg.h \
proto_hier_stats_dlg.c \
range.c \
range.h \
rtp_analysis.h \
rtp_stream.c \
rtp_stream.h \

View File

@ -1,7 +1,7 @@
## Makefile for building ethereal.exe with Microsoft C and nmake
## Use: $(MAKE) /$(MAKEFLAGS) -f makefile.nmake
#
# $Id: Makefile.nmake,v 1.66 2003/12/17 22:13:05 guy Exp $
# $Id: Makefile.nmake,v 1.67 2003/12/29 20:05:59 ulfl Exp $
include ..\config.nmake
@ -95,6 +95,7 @@ OBJECTS = \
proto_dlg.obj \
proto_draw.obj \
proto_hier_stats_dlg.obj \
range.obj \
rtp_stream.obj \
service_response_time_table.obj \
simple_dialog.obj \

View File

@ -1,7 +1,7 @@
/* file_dlg.c
* Dialog boxes for handling files
*
* $Id: file_dlg.c,v 1.66 2003/12/01 02:01:55 guy Exp $
* $Id: file_dlg.c,v 1.67 2003/12/29 20:05:59 ulfl Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
@ -28,6 +28,7 @@
#include <gtk/gtk.h>
#include "range.h"
#include <epan/filesystem.h>
#include "globals.h"
@ -66,6 +67,14 @@ static void file_select_destroy_cb(GtkWidget *win, GtkWidget* file_te);
#define ARGUMENT_CL "argument_cl"
/*
* Keep a static pointer to the current "Save Capture File As" window, if
* any, so that if somebody tries to do "File:Save" or "File:Save As"
* while there's already a "Save Capture File As" window up, we just pop
* up the existing one, rather than creating a new one.
*/
static GtkWidget *file_save_as_w;
/*
* A generic select_file_cb routine that is intended to be connected to
* a Browse button on other dialog boxes. This allows the user to browse
@ -450,12 +459,16 @@ file_save_cmd_cb(GtkWidget *w, gpointer data) {
}
/* XXX - can we make these not be static? */
static gboolean filtered;
static gboolean marked;
static packet_range_t range;
static gboolean color_marked;
static int filetype;
static GtkWidget *filter_cb;
static GtkWidget *mark_cb;
static GtkWidget *select_all;
static GtkWidget *select_curr;
static GtkWidget *select_marked_only;
static GtkWidget *select_marked_range;
static GtkWidget *select_manual_range;
static GtkWidget *range_specs;
static GtkWidget *cfmark_cb;
static GtkWidget *ft_om;
@ -480,8 +493,7 @@ can_save_with_wiretap(int ft)
and FALSE if we're to save the entire file (in which case, if we're
saving it in the type it has already, we can just copy it).
"marked" is TRUE if we have to save only the marked packets,
the same remark as "filtered" applies.
The same applies for sel_curr, sel_all, sel_m_only, sel_m_range and sel_man_range
*/
static void
set_file_type_list(GtkWidget *option_menu)
@ -500,8 +512,8 @@ set_file_type_list(GtkWidget *option_menu)
/* Check all file types. */
index = 0;
for (ft = 0; ft < WTAP_NUM_FILE_TYPES; ft++) {
if (filtered || marked || ft != cfile.cd_t) {
/* Filtered, marked or a different file type. We have to use Wiretap. */
if (!packet_range_process_all(&range) || ft != cfile.cd_t) {
/* not all unfiltered packets or a different file type. We have to use Wiretap. */
if (!can_save_with_wiretap(ft))
continue; /* We can't. */
}
@ -541,43 +553,114 @@ static void
toggle_filtered_cb(GtkWidget *widget, gpointer data _U_)
{
gboolean new_filtered;
new_filtered = GTK_TOGGLE_BUTTON (widget)->active;
if (filtered != new_filtered) {
if (range.process_filtered != new_filtered) {
/* They changed the state of the "filtered" button. */
filtered = new_filtered;
range.process_filtered = new_filtered;
set_file_type_list(ft_om);
}
}
static void
toggle_marked_cb(GtkWidget *widget, gpointer data _U_)
toggle_select_all(GtkWidget *widget, gpointer data _U_)
{
gboolean new_all;
new_all = GTK_TOGGLE_BUTTON (widget)->active;
if (range.process_all != new_all) {
/* They changed the state of the "select-all" button. */
range.process_all = new_all;
set_file_type_list(ft_om);
}
}
static void
toggle_select_curr(GtkWidget *widget, gpointer data _U_)
{
gboolean new_curr;
new_curr = GTK_TOGGLE_BUTTON (widget)->active;
if (range.process_curr != new_curr) {
/* They changed the state of the "select-current" button. */
range.process_curr = new_curr;
set_file_type_list(ft_om);
}
}
static void
toggle_select_marked_only(GtkWidget *widget, gpointer data _U_)
{
gboolean new_marked;
new_marked = GTK_TOGGLE_BUTTON (widget)->active;
if (marked != new_marked) {
/* They changed the state of the "marked" button. */
marked = new_marked;
if (range.process_marked != new_marked) {
/* They changed the state of the "marked-only" button. */
range.process_marked = new_marked;
set_file_type_list(ft_om);
}
}
/*
* Keep a static pointer to the current "Save Capture File As" window, if
* any, so that if somebody tries to do "File:Save" or "File:Save As"
* while there's already a "Save Capture File As" window up, we just pop
* up the existing one, rather than creating a new one.
*/
static GtkWidget *file_save_as_w;
static void
toggle_select_marked_range(GtkWidget *widget, gpointer data _U_)
{
gboolean new_marked_range;
new_marked_range = GTK_TOGGLE_BUTTON (widget)->active;
if (range.process_marked_range != new_marked_range) {
/* They changed the state of the "marked-range" button. */
range.process_marked_range = new_marked_range;
set_file_type_list(ft_om);
}
}
static void
toggle_select_manual_range(GtkWidget *widget, gpointer data _U_)
{
gboolean new_manual_range;
new_manual_range = GTK_TOGGLE_BUTTON (widget)->active;
if (range.process_manual_range != new_manual_range) {
/* They changed the state of the "manual-range" button. */
range.process_manual_range = new_manual_range;
set_file_type_list(ft_om);
}
/* Make the entry widget sensitive or insensitive */
gtk_widget_set_sensitive(range_specs, range.process_manual_range);
/* When selecting manual range, then focus on the entry */
if (range.process_manual_range)
gtk_widget_grab_focus(range_specs);
}
static void
range_entry(GtkWidget *entry)
{
gchar *entry_text;
entry_text = gtk_entry_get_text (GTK_ENTRY (entry));
packet_range_convert_str(entry_text);
}
void
file_save_as_cmd_cb(GtkWidget *w _U_, gpointer data _U_)
{
GtkWidget *ok_bt, *main_vb, *ft_hb, *ft_lb;
GtkWidget *ok_bt, *main_vb, *ft_hb, *ft_lb, *range_fr, *range_vb, *range_tb;
GtkTooltips *tooltips;
gchar label_text[100];
frame_data *packet;
#if GTK_MAJOR_VERSION < 2
GtkAccelGroup *accel_group;
#endif
if (file_save_as_w != NULL) {
/* There's already an "Save Capture File As" dialog box; reactivate it. */
reactivate_window(file_save_as_w);
@ -585,13 +668,28 @@ file_save_as_cmd_cb(GtkWidget *w _U_, gpointer data _U_)
}
/* Default to saving all packets, in the file's current format. */
filtered = FALSE;
marked = FALSE;
filetype = cfile.cd_t;
range.process_all = TRUE;
range.process_curr = FALSE;
range.process_marked = FALSE;
range.process_marked_range = FALSE;
range.process_manual_range = FALSE;
range.process_filtered = FALSE;
filetype = cfile.cd_t;
/* init the packet range */
packet_range_init(&range);
/* Enable tooltips */
tooltips = gtk_tooltips_new();
file_save_as_w = file_selection_new ("Ethereal: Save Capture File As");
SIGNAL_CONNECT(file_save_as_w, "destroy", file_save_as_destroy_cb, NULL);
#if GTK_MAJOR_VERSION < 2
accel_group = gtk_accel_group_new();
gtk_window_add_accel_group(GTK_WINDOW(file_save_as_w), accel_group);
#endif
/* If we've opened a file, start out by showing the files in the directory
in which that file resided. */
if (last_open_dir)
@ -603,11 +701,123 @@ file_save_as_cmd_cb(GtkWidget *w _U_, gpointer data _U_)
SIGNAL_CONNECT(ok_bt, "clicked", file_save_as_ok_cb, file_save_as_w);
/* Container for each row of widgets */
main_vb = gtk_vbox_new(FALSE, 3);
main_vb = gtk_vbox_new(FALSE, 5);
gtk_container_border_width(GTK_CONTAINER(main_vb), 5);
gtk_box_pack_start(GTK_BOX(GTK_FILE_SELECTION(file_save_as_w)->action_area),
main_vb, FALSE, FALSE, 0);
gtk_widget_show(main_vb);
gtk_widget_show(main_vb);
/*** Save Range frame ***/
range_fr = gtk_frame_new("Save Range");
gtk_box_pack_start(GTK_BOX(main_vb), range_fr, FALSE, FALSE, 0);
gtk_widget_show(range_fr);
range_vb = gtk_vbox_new(FALSE,6);
gtk_container_border_width(GTK_CONTAINER(range_vb), 5);
gtk_container_add(GTK_CONTAINER(range_fr), range_vb);
gtk_widget_show(range_vb);
/*
* The argument above could, I guess, be applied to the marked packets,
* except that you can't easily tell whether there are any marked
* packets, so I could imagine users doing "Save only marked packets"
* when there aren't any marked packets, not knowing that they'd
* failed to mark them, so I'm more inclined to have the "Save only
* marked packets" toggle button enabled only if there are marked
* packets to save.
*/
/* Save all packets */
g_snprintf(label_text, sizeof(label_text), "All _captured %s (%u %s)",
plurality(cfile.count, "packet", "packets"), cfile.count, plurality(cfile.count, "packet", "packets"));
#if GTK_MAJOR_VERSION < 2
select_all = dlg_radio_button_new_with_label_with_mnemonic(NULL, label_text ,accel_group);
#else
select_all = gtk_radio_button_new_with_mnemonic(NULL, label_text);
#endif
gtk_container_add(GTK_CONTAINER(range_vb), select_all);
gtk_tooltips_set_tip (tooltips,select_all,("Save all captured packets"), NULL);
gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(select_all), FALSE);
SIGNAL_CONNECT(select_all, "toggled", toggle_select_all, NULL);
gtk_widget_show(select_all);
/* Save currently selected */
g_snprintf(label_text, sizeof(label_text), "_Selected packet #%u only", cfile.current_frame->num);
#if GTK_MAJOR_VERSION < 2
select_curr = dlg_radio_button_new_with_label_with_mnemonic(gtk_radio_button_group (GTK_RADIO_BUTTON (select_all)),
label_text,accel_group);
#else
select_curr = gtk_radio_button_new_with_mnemonic(gtk_radio_button_group (GTK_RADIO_BUTTON (select_all)),
label_text);
#endif
gtk_container_add(GTK_CONTAINER(range_vb), select_curr);
gtk_tooltips_set_tip (tooltips,select_curr,("Save the currently selected packet only"), NULL);
gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(select_curr), FALSE);
SIGNAL_CONNECT(select_curr, "toggled", toggle_select_curr, NULL);
gtk_widget_show(select_curr);
/* Save marked packets */
g_snprintf(label_text, sizeof(label_text), "_Marked %s only (%u %s)",
plurality(cfile.marked_count, "packet", "packets"), cfile.marked_count, plurality(cfile.marked_count, "packet", "packets"));
#if GTK_MAJOR_VERSION < 2
select_marked_only = dlg_radio_button_new_with_label_with_mnemonic(gtk_radio_button_group (GTK_RADIO_BUTTON (select_all)),
label_text,accel_group);
#else
select_marked_only = gtk_radio_button_new_with_mnemonic(gtk_radio_button_group (GTK_RADIO_BUTTON (select_all)),
label_text);
#endif
gtk_container_add(GTK_CONTAINER(range_vb), select_marked_only);
gtk_tooltips_set_tip (tooltips,select_marked_only,("Save marked packets only"), NULL);
gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(select_marked_only), FALSE);
SIGNAL_CONNECT(select_marked_only, "toggled", toggle_select_marked_only, NULL);
gtk_widget_show(select_marked_only);
/* Save packet range between first and last packet */
g_snprintf(label_text, sizeof(label_text), "From first _to last marked packet (%u %s)",
range.mark_range, plurality(range.mark_range, "packet", "packets"));
#if GTK_MAJOR_VERSION < 2
select_marked_range = dlg_radio_button_new_with_label_with_mnemonic(gtk_radio_button_group (GTK_RADIO_BUTTON (select_all)),
label_text,accel_group);
#else
select_marked_range = gtk_radio_button_new_with_mnemonic(gtk_radio_button_group (GTK_RADIO_BUTTON (select_all)),
label_text);
#endif
gtk_container_add(GTK_CONTAINER(range_vb), select_marked_range);
gtk_tooltips_set_tip (tooltips,select_marked_range,("Save all packets between the first and last marker"), NULL);
gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(select_marked_range), FALSE);
SIGNAL_CONNECT(select_marked_range, "toggled", toggle_select_marked_range, NULL);
gtk_widget_show(select_marked_range);
/* Range table */
range_tb = gtk_table_new(2, 2, FALSE);
gtk_box_pack_start(GTK_BOX(range_vb), range_tb, FALSE, FALSE, 0);
gtk_widget_show(range_tb);
/* Save a manually provided packet range : -10,30,40-70,80- */
g_snprintf(label_text, sizeof(label_text), "Specify a packet _range :");
#if GTK_MAJOR_VERSION < 2
select_manual_range = dlg_radio_button_new_with_label_with_mnemonic(gtk_radio_button_group (GTK_RADIO_BUTTON (select_all)),
label_text,accel_group);
#else
select_manual_range = gtk_radio_button_new_with_mnemonic(gtk_radio_button_group (GTK_RADIO_BUTTON (select_all)),
label_text);
#endif
gtk_table_attach_defaults(GTK_TABLE(range_tb), select_manual_range, 0, 1, 1, 2);
gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(select_manual_range), FALSE);
gtk_tooltips_set_tip (tooltips,select_manual_range,("Save a specified packet range"), NULL);
SIGNAL_CONNECT(select_manual_range, "toggled", toggle_select_manual_range, NULL);
gtk_widget_show(select_manual_range);
/* The entry part */
range_specs = gtk_entry_new();
gtk_entry_set_max_length (GTK_ENTRY (range_specs), 254);
gtk_table_attach_defaults(GTK_TABLE(range_tb), range_specs, 1, 2, 1, 2);
gtk_tooltips_set_tip (tooltips,range_specs,
("Specify a range of packet numbers : \nExample : 1-10,18,25-100,332-"), NULL);
SIGNAL_CONNECT(range_specs,"activate", range_entry, range_specs);
gtk_widget_set_sensitive(range_specs, FALSE);
gtk_widget_show(range_specs);
/*
* XXX - should this be sensitive only if the current display filter
@ -619,29 +829,18 @@ file_save_as_cmd_cb(GtkWidget *w _U_, gpointer data _U_)
* I guess, argue that the user may want to "save all the displayed
* packets" even if there aren't any, i.e. save an empty file.
*/
filter_cb = gtk_check_button_new_with_label("Save only packets currently being displayed");
gtk_container_add(GTK_CONTAINER(main_vb), filter_cb);
#if GTK_MAJOR_VERSION < 2
filter_cb = dlg_check_button_new_with_label_with_mnemonic("Apply _display filter",accel_group);
#else
filter_cb = gtk_check_button_new_with_mnemonic("Apply _display filter");
#endif
gtk_container_add(GTK_CONTAINER(range_vb), filter_cb);
gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(filter_cb), FALSE);
SIGNAL_CONNECT(filter_cb, "toggled", toggle_filtered_cb, NULL);
gtk_widget_set_sensitive(filter_cb, can_save_with_wiretap(filetype));
gtk_widget_show(filter_cb);
/*
* The argument above could, I guess, be applied to the marked packets,
* except that you can't easily tell whether there are any marked
* packets, so I could imagine users doing "Save only marked packets"
* when there aren't any marked packets, not knowing that they'd
* failed to mark them, so I'm more inclined to have the "Save only
* marked packets" toggle button enabled only if there are marked
* packets to save.
*/
mark_cb = gtk_check_button_new_with_label("Save only marked packets");
gtk_container_add(GTK_CONTAINER(main_vb), mark_cb);
marked = FALSE;
gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(mark_cb), FALSE);
SIGNAL_CONNECT(mark_cb, "toggled", toggle_marked_cb, NULL);
gtk_widget_show(mark_cb);
gtk_widget_show(filter_cb);
/* File type row */
ft_hb = gtk_hbox_new(FALSE, 3);
gtk_container_add(GTK_CONTAINER(main_vb), ft_hb);
@ -666,7 +865,7 @@ file_save_as_cmd_cb(GtkWidget *w _U_, gpointer data _U_)
* as the routine that sets it also sets that menu.
*/
file_set_save_marked_sensitive();
/* Connect the cancel_button to destroy the widget */
SIGNAL_CONNECT_OBJECT(GTK_FILE_SELECTION(file_save_as_w)->cancel_button,
"clicked", (GtkSignalFunc)gtk_widget_destroy,
@ -696,19 +895,23 @@ file_set_save_marked_sensitive(void)
/* We don't currently have a "Save As..." dialog box up. */
return;
}
/* We can request that only the marked packets be saved only if we
can use Wiretap to save the file and if there *are* marked packets. */
if (can_save_with_wiretap(filetype) && cfile.marked_count != 0)
gtk_widget_set_sensitive(mark_cb, TRUE);
if (can_save_with_wiretap(filetype) && cfile.marked_count != 0) {
gtk_widget_set_sensitive(select_marked_only, TRUE);
gtk_widget_set_sensitive(select_marked_range, TRUE);
}
else {
/* Force the "Save only marked packets" toggle to "false", turn
off the flag it controls, and update the list of types we can
save the file as. */
marked = FALSE;
gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(mark_cb), FALSE);
range.process_marked = FALSE;
gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(select_marked_only), FALSE);
gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(select_marked_range), FALSE);
set_file_type_list(ft_om);
gtk_widget_set_sensitive(mark_cb, FALSE);
gtk_widget_set_sensitive(select_marked_only, FALSE);
gtk_widget_set_sensitive(select_marked_range, FALSE);
}
}
@ -717,6 +920,11 @@ file_save_as_ok_cb(GtkWidget *w _U_, GtkFileSelection *fs) {
gchar *cf_name;
gchar *dirname;
/* obtain the range specifications in case we selected manual range */
if (range.process_manual_range) {
range_entry(range_specs);
}
cf_name = g_strdup(gtk_file_selection_get_filename(GTK_FILE_SELECTION(fs)));
/* Perhaps the user specified a directory instead of a file.
@ -733,7 +941,7 @@ file_save_as_ok_cb(GtkWidget *w _U_, GtkFileSelection *fs) {
/* Write out the packets (all, or only the ones that are currently
displayed or marked) to the file with the specified name. */
if (! cf_save(cf_name, &cfile, filtered, marked, filetype)) {
if (! cf_save(cf_name, &cfile, &range, filetype)) {
/* The write failed; don't dismiss the open dialog box,
just leave it around so that the user can, after they
dismiss the alert box popped up for the error, try again. */
@ -1002,7 +1210,6 @@ file_color_export_cmd_cb(GtkWidget *w _U_, gpointer data _U_)
}
/* Default to saving all packets, in the file's current format. */
filtered = FALSE;
color_marked = FALSE;
filetype = cfile.cd_t;

View File

@ -1,6 +1,6 @@
/* main.c
*
* $Id: main.c,v 1.346 2003/12/21 12:17:59 ulfl Exp $
* $Id: main.c,v 1.347 2003/12/29 20:05:59 ulfl Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
@ -1022,6 +1022,8 @@ void mark_frame_cb(GtkWidget *w _U_, gpointer data _U_) {
static void mark_all_frames(gboolean set) {
frame_data *fdata;
cfile.marked_count = 0;
for (fdata = cfile.plist; fdata != NULL; fdata = fdata->next) {
set_frame_mark(set,
fdata,

385
gtk/range.c Normal file
View File

@ -0,0 +1,385 @@
/* range.c
* Packet range routines (save, print, ...)
*
* Dick Gooris <gooris@lucent.com>
* Ulf Lamping <ulf.lamping@web.de>
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
* Copyright 1998 Gerald Combs
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <glib.h>
#include <epan/frame_data.h>
#include "range.h"
#include "globals.h"
static gboolean packet_is_in_range(guint32 val);
/* Range parser variables */
#define MaxRange 30
struct range_admin {
guint32 low;
guint32 high;
};
static guint GLnrange=0;
struct range_admin GLrange[MaxRange];
static guint32 max_packets;
void packet_range_init(packet_range_t *range) {
guint32 current_count;
guint32 displayed_count;
guint32 mark_low;
guint32 mark_high;
frame_data *packet;
/* This is needed to calculate the number of packets for each variation
* like the total amount of packets, the number of marked packets, and
* the number between the packets. This is for information only
*/
/* "enumeration" values */
range->markers = cfile.marked_count;
range->range_active = FALSE;
range->process_curr_done = FALSE;
displayed_count = 0L;
mark_low = 0L;
mark_high = 0L;
range->mark_range = 0L;
current_count = 0;
for(packet = cfile.plist; packet != NULL; packet = packet->next) {
current_count++;
if (cfile.current_frame == packet) {
range->selected_packet = current_count;
}
if (packet->flags.passed_dfilter) {
displayed_count++;
}
if (packet->flags.marked) {
if (mark_low == 0) {
mark_low = current_count;
}
if (current_count > mark_high) {
mark_high = current_count;
}
}
}
/* in case we marked just one packet, we add 1. */
if (cfile.marked_count != 0) {
range->mark_range = mark_high - mark_low + 1;
}
/* make this global, to be used in function conv_str_range() */
max_packets = cfile.count;
}
/* do we have to process all packets? */
gboolean packet_range_process_all(packet_range_t *range) {
return range->process_all && !range->process_filtered;
}
/* do we have to process this packet? */
range_process_e packet_range_process(packet_range_t *range, frame_data *fdata) {
/* do we have to process this packet at all? */
if (
(!range->process_filtered && !range->process_marked) ||
(range->process_filtered && fdata->flags.passed_dfilter && !range->process_marked) ||
(range->process_marked && fdata->flags.marked && !range->process_filtered) ||
(range->process_filtered && range->process_marked && fdata->flags.passed_dfilter && fdata->flags.marked) ||
(range->process_curr) ||
(range->process_marked_range) ||
(range->process_manual_range) ||
(range->range_active)
) {
/* yes, we have to */
} else {
return range_process_next;
}
/* In case we process a manual range, we check the packet number
* with the range as defined in the array GLrange, see file_dlg.c
* If a match is found, we process it, otherwise we simply go to check
* the next packet.
*/
if (range->process_manual_range) {
if (range->process_filtered) {
if (fdata->flags.passed_dfilter == FALSE) {
return range_process_next;
}
}
if (packet_is_in_range(fdata->num) == FALSE) {
return range_process_next;
}
}
/* For processing a marked range, skip the frames not marked in the first place
* until the first marked frame comes by. Then continue processing until we found the
* last marked frame. We set the range_active to FALSE in the first place until
* a marked frame is found (fdata->flags.marked == TRUE) From now on range_active
* is TRUE, and the large 'if' statement will pass by any frame. It will stop doing
* so once the markers count got 0. process_marked_range got set in gtk/file_dlg.c
*/
if (range->process_marked_range) {
if (range->markers == 0) {
return range_processing_finished;
}
if (fdata->flags.marked == TRUE) {
range->range_active = TRUE;
range->markers--;
}
if (range->process_filtered) {
if (fdata->flags.passed_dfilter == FALSE) {
return range_process_next;
}
}
if (range->range_active == FALSE ) {
return range_process_next;
}
}
/* Only process the selected frame. If accomplished, finish */
if (range->process_curr) {
if (range->process_curr_done) {
return range_processing_finished;
}
if (fdata->num != cfile.current_frame->num) {
return range_process_next;
}
range->process_curr_done = TRUE;
}
return range_process_this;
}
/******************** Range Entry Parser *********************************/
/* Convert the entry range string in a fast comparable array of ranges.
* In the first place get rid of spaces, and any other characters than
* commas, digits, and hyphens. The parameter es points to the string to be processed
*
* This function is only called once when a range string is provided in the Save/Print As
* widget. This function fills an array of low and high values indexed by a global
* varaiable GLnrange. After having called this function, the function isin(val)
* determines whether the value is with the range or not.
*/
void packet_range_convert_str(gchar *es)
{
gchar EntryStr[255], OrgStr[255], value[255], p;
guint i, j=0;
guint32 tmp, val;
gboolean hyphenseen;
/* Reset the number of ranges we are going to find */
GLnrange = 0;
GLrange[GLnrange].low = 0L;
GLrange[GLnrange].high = 0L;
/* Make a copy of the string, and check the validity of the input */
strcpy(OrgStr,es);
if (strlen(OrgStr) == 0 ) {
return;
}
/* only keep digits, comma's, and hyphens. */
for (i=0; i<=strlen(OrgStr); i++) {
if ( isdigit(OrgStr[i]) || OrgStr[i] == '-' || OrgStr[i] == ',' ) {
EntryStr[j++] = OrgStr[i];
}
}
EntryStr[j] = '\0';
/* remove any starting commas */
strcpy(OrgStr,EntryStr);
i = 0;
while (OrgStr[i] == ',') {
i++;
}
strcpy(EntryStr,OrgStr+i);
/* remove any double commas within the entry string */
strcpy(OrgStr,EntryStr);
p = ',';
j = 0;
for (i=0; i<=strlen(OrgStr); i++) {
if ( OrgStr[i] != ',' || p != ',') {
EntryStr[j++] = OrgStr[i];
}
p = OrgStr[i];
}
EntryStr[j] = '\0';
/* remove any double hyphens within the entry string */
strcpy(OrgStr,EntryStr);
p = '-';
j = 0;
for (i=0; i<=strlen(OrgStr); i++) {
if (OrgStr[i] != '-' || p != '-' || i == 0) {
EntryStr[j++] = OrgStr[i];
}
p = OrgStr[i];
}
EntryStr[j] = '\0';
/* remove any trailing commas */
i = strlen(EntryStr) - 1;
while (EntryStr[i] == ',') {
EntryStr[i] = '\0';
i--;
}
/* The entry string is now filtered, and ready for further parsing */
/* printf("str=%s\n",EntryStr); */
/* Now we are going to process the ranges separately until we get a comma,
* or end of string. The following input are interpreted all right :
*
* 0-20,30-40 -=> Range from 0 to 20, and packets 30 to 40
* -20,30 -=> Range from 0 to 20, and packet 30
* 20,30,40- -=> Packet number 20, 30, and the range from 40 to the end
* 20-10,30-25 -=> Range from 10 to 20, and from 25 to 30
* - -=> All packets
*
* We build a structure array called GLrange of high and low values. After the
* following loop, we have the GLnrange variable which tells how many ranges
* are found.
* The number of different ranges is limited to 'MaxRanges'
*/
j = 0;
hyphenseen = FALSE;
for (i=0; i<=strlen(EntryStr);i++) {
/* copy the digit string until a no-digit character is seen */
if (isdigit(EntryStr[i])) {
value[j++] = EntryStr[i];
continue;
}
/* Terminate the digit string, and convert it */
value[j] = '\0';
val=atol(value);
j=0;
/* treatment in case we see a hyphen */
if (EntryStr[i] == '-') {
/* if this is a trailer hyphen, then treat it in a different
* way, then the high value is the maximum number of packets counted
* and we are ready */
if (i == strlen(EntryStr)-1) {
GLrange[GLnrange].low = val;
GLrange[GLnrange].high = max_packets;
GLnrange++;
break;
} else {
/* if no digits were actually seen, the outcome of
* a zeroed string conversion to interger is also 0. */
GLrange[GLnrange].low = val;
}
hyphenseen=TRUE;
continue;
}
/* treatment in case we see a comma, or end of string */
if (EntryStr[i] == ',' || i == strlen(EntryStr)) {
if (hyphenseen) {
GLrange[GLnrange].high = val;
} else {
/* in this case we got a single packet number */
GLrange[GLnrange].low = val;
GLrange[GLnrange].high = val;
}
hyphenseen=FALSE;
}
/* Increase the index for ranges found, and protect
* against wildly outside array bounds */
GLnrange++;
if (GLnrange > MaxRange) {
GLnrange--;
}
}
GLnrange--;
/* Now we are going through the low and high values, and check
* whether they are in a proper order. Low should be equal or lower
* than high. So, go through the loop and swap if needed
*/
for (i=0; i <= GLnrange; i++) {
if (GLrange[i].low > GLrange[i].high) {
tmp = GLrange[i].low;
GLrange[i].low = GLrange[i].high;
GLrange[i].high = tmp;
}
}
/* In case we want to know what the result ranges are :
*
* for (i=0; i <= GLnrange; i++) {
* printf("L=%u\tH=%u\n",GLrange[i].low,GLrange[i].high);
* }
*
*/
/* End of conv_str_range() */
return;
}
/* This function returns TRUE is the given value is within the range
* of the input range entered via (Save/Print As). This is supposed to
* be a tiny and quick procedure since this is called for every packet
* to be potentially saved.
*/
static gboolean packet_is_in_range(guint32 val)
{
guint i;
for (i=0; i <= GLnrange; i++) {
if (val >= GLrange[i].low && val <= GLrange[i].high)
return TRUE;
}
return(FALSE);
}
static void packet_is_in_range_check(guint32 val)
{
printf("Checking %d\t",val);
if (packet_is_in_range(val)) {
printf("TRUE\n");
} else {
printf("FALSE\n");
}
}

73
range.h Normal file
View File

@ -0,0 +1,73 @@
/* range.h
* Packet range routines (save, print, ...)
*
* Dick Gooris <gooris@lucent.com>
* Ulf Lamping <ulf.lamping@web.de>
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
* Copyright 1998 Gerald Combs
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __PRINT_RANGE_H__
#define __PRINT_RANGE_H__
#include <glib.h>
#include <epan/frame_data.h>
extern guint32 curr_selected_frame;
typedef struct packet_range_tag {
/* values coming from the UI */
/* XXX: use an enum instead? */
gboolean process_all;
gboolean process_curr;
gboolean process_marked;
gboolean process_marked_range;
gboolean process_manual_range;
gboolean process_filtered;
/* calculated values */
guint32 mark_range;
guint32 selected_packet;
/* "enumeration" values */
gboolean range_active;
guint32 markers;
gboolean process_curr_done;
} packet_range_t;
typedef enum {
range_process_next,
range_processing_finished,
range_process_this
} range_process_e;
/* init the range structure */
extern void packet_range_init(packet_range_t *range);
/* do we have to process all packets? */
extern gboolean packet_range_process_all(packet_range_t *range);
/* do we have to process this packet? */
extern range_process_e packet_range_process(packet_range_t *range, frame_data *fdata);
extern void packet_range_convert_str(gchar *es);
#endif /* __PRINT_RANGE_H__ */