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:
parent
4b37928246
commit
14e2a790f9
85
file.c
85
file.c
|
@ -1,7 +1,7 @@
|
||||||
/* file.c
|
/* file.c
|
||||||
* File I/O routines
|
* 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
|
* Ethereal - Network traffic analyzer
|
||||||
* By Gerald Combs <gerald@ethereal.com>
|
* 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_rename_error_message(int err);
|
||||||
static char *file_close_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. */
|
/* Update the progress bar this many times when reading a file. */
|
||||||
#define N_PROGBAR_UPDATES 100
|
#define N_PROGBAR_UPDATES 100
|
||||||
|
@ -2242,8 +2242,7 @@ unmark_frame(capture_file *cf, frame_data *frame)
|
||||||
* up a message box for the failure.
|
* up a message box for the failure.
|
||||||
*/
|
*/
|
||||||
gboolean
|
gboolean
|
||||||
cf_save(char *fname, capture_file *cf, gboolean save_filtered,
|
cf_save(char *fname, capture_file *cf, packet_range_t *range, guint save_format)
|
||||||
gboolean save_marked, guint save_format)
|
|
||||||
{
|
{
|
||||||
gchar *from_filename;
|
gchar *from_filename;
|
||||||
gchar *name_ptr, *save_msg, *save_fmt = " Saving: %s...";
|
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;
|
union wtap_pseudo_header pseudo_header;
|
||||||
guint8 pd[65536];
|
guint8 pd[65536];
|
||||||
struct stat infile, outfile;
|
struct stat infile, outfile;
|
||||||
|
range_process_e process_this;
|
||||||
|
|
||||||
name_ptr = get_basename(fname);
|
name_ptr = get_basename(fname);
|
||||||
msg_len = strlen(name_ptr) + strlen(save_fmt) + 2;
|
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;
|
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
|
/* 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. */
|
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? */
|
NetMon do? */
|
||||||
for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
|
for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
|
||||||
/* XXX - do a progress bar */
|
/* XXX - do a progress bar */
|
||||||
if ((!save_filtered && !save_marked) ||
|
process_this = packet_range_process(range, fdata);
|
||||||
(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;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!wtap_dump(pdh, &hdr, &pseudo_header, pd, &err)) {
|
if (process_this == range_process_next) {
|
||||||
simple_dialog(ESD_TYPE_CRIT, NULL,
|
continue;
|
||||||
file_write_error_message(err), fname);
|
} else if (process_this == range_processing_finished) {
|
||||||
wtap_dump_close(pdh, &err);
|
break;
|
||||||
goto fail;
|
} 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)) {
|
if (!wtap_dump_close(pdh, &err)) {
|
||||||
simple_dialog(ESD_TYPE_WARN, NULL,
|
simple_dialog(ESD_TYPE_WARN, NULL,
|
||||||
file_close_error_message(err), fname);
|
file_close_error_message(err), fname);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
}
|
} /* save_all */
|
||||||
|
|
||||||
/* Pop the "Saving:" message off the status bar. */
|
/* Pop the "Saving:" message off the status bar. */
|
||||||
statusbar_pop_file_msg();
|
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.
|
/* We saved the entire capture, not just some packets from it.
|
||||||
Open and read the file we saved it to.
|
Open and read the file we saved it to.
|
||||||
|
|
||||||
|
|
5
file.h
5
file.h
|
@ -1,7 +1,7 @@
|
||||||
/* file.h
|
/* file.h
|
||||||
* Definitions for file structures and routines
|
* 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
|
* Ethereal - Network traffic analyzer
|
||||||
* By Gerald Combs <gerald@ethereal.com>
|
* By Gerald Combs <gerald@ethereal.com>
|
||||||
|
@ -25,6 +25,7 @@
|
||||||
#ifndef __FILE_H__
|
#ifndef __FILE_H__
|
||||||
#define __FILE_H__
|
#define __FILE_H__
|
||||||
|
|
||||||
|
#include "range.h"
|
||||||
#include "wiretap/wtap.h"
|
#include "wiretap/wtap.h"
|
||||||
#include <epan/dfilter/dfilter.h>
|
#include <epan/dfilter/dfilter.h>
|
||||||
#include "print.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_continue_tail(capture_file *, int, int *);
|
||||||
read_status_t cf_finish_tail(capture_file *, int *);
|
read_status_t cf_finish_tail(capture_file *, int *);
|
||||||
/* size_t read_frame_header(capture_file *); */
|
/* 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 *);
|
gchar *cf_get_display_name(capture_file *);
|
||||||
|
|
||||||
int filter_packets(capture_file *cf, gchar *dfilter);
|
int filter_packets(capture_file *cf, gchar *dfilter);
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
# Makefile.am
|
# Makefile.am
|
||||||
# Automake file for the GTK interface routines for Ethereal
|
# 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
|
# Ethereal - Network traffic analyzer
|
||||||
# By Gerald Combs <gerald@ethereal.com>
|
# By Gerald Combs <gerald@ethereal.com>
|
||||||
|
@ -131,6 +131,7 @@ libui_a_SOURCES = \
|
||||||
proto_draw.h \
|
proto_draw.h \
|
||||||
proto_hier_stats_dlg.h \
|
proto_hier_stats_dlg.h \
|
||||||
proto_hier_stats_dlg.c \
|
proto_hier_stats_dlg.c \
|
||||||
|
range.c \
|
||||||
rtp_analysis.h \
|
rtp_analysis.h \
|
||||||
rtp_stream.c \
|
rtp_stream.c \
|
||||||
rtp_stream.h \
|
rtp_stream.h \
|
||||||
|
@ -225,6 +226,8 @@ libui_a_SOURCES = \
|
||||||
proto_draw.h \
|
proto_draw.h \
|
||||||
proto_hier_stats_dlg.h \
|
proto_hier_stats_dlg.h \
|
||||||
proto_hier_stats_dlg.c \
|
proto_hier_stats_dlg.c \
|
||||||
|
range.c \
|
||||||
|
range.h \
|
||||||
rtp_analysis.h \
|
rtp_analysis.h \
|
||||||
rtp_stream.c \
|
rtp_stream.c \
|
||||||
rtp_stream.h \
|
rtp_stream.h \
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
## Makefile for building ethereal.exe with Microsoft C and nmake
|
## Makefile for building ethereal.exe with Microsoft C and nmake
|
||||||
## Use: $(MAKE) /$(MAKEFLAGS) -f makefile.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
|
include ..\config.nmake
|
||||||
|
|
||||||
|
@ -95,6 +95,7 @@ OBJECTS = \
|
||||||
proto_dlg.obj \
|
proto_dlg.obj \
|
||||||
proto_draw.obj \
|
proto_draw.obj \
|
||||||
proto_hier_stats_dlg.obj \
|
proto_hier_stats_dlg.obj \
|
||||||
|
range.obj \
|
||||||
rtp_stream.obj \
|
rtp_stream.obj \
|
||||||
service_response_time_table.obj \
|
service_response_time_table.obj \
|
||||||
simple_dialog.obj \
|
simple_dialog.obj \
|
||||||
|
|
323
gtk/file_dlg.c
323
gtk/file_dlg.c
|
@ -1,7 +1,7 @@
|
||||||
/* file_dlg.c
|
/* file_dlg.c
|
||||||
* Dialog boxes for handling files
|
* 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
|
* Ethereal - Network traffic analyzer
|
||||||
* By Gerald Combs <gerald@ethereal.com>
|
* By Gerald Combs <gerald@ethereal.com>
|
||||||
|
@ -28,6 +28,7 @@
|
||||||
|
|
||||||
#include <gtk/gtk.h>
|
#include <gtk/gtk.h>
|
||||||
|
|
||||||
|
#include "range.h"
|
||||||
#include <epan/filesystem.h>
|
#include <epan/filesystem.h>
|
||||||
|
|
||||||
#include "globals.h"
|
#include "globals.h"
|
||||||
|
@ -66,6 +67,14 @@ static void file_select_destroy_cb(GtkWidget *win, GtkWidget* file_te);
|
||||||
|
|
||||||
#define ARGUMENT_CL "argument_cl"
|
#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 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
|
* 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? */
|
/* XXX - can we make these not be static? */
|
||||||
static gboolean filtered;
|
static packet_range_t range;
|
||||||
static gboolean marked;
|
|
||||||
static gboolean color_marked;
|
static gboolean color_marked;
|
||||||
static int filetype;
|
static int filetype;
|
||||||
static GtkWidget *filter_cb;
|
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 *cfmark_cb;
|
||||||
static GtkWidget *ft_om;
|
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
|
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).
|
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 applies for sel_curr, sel_all, sel_m_only, sel_m_range and sel_man_range
|
||||||
the same remark as "filtered" applies.
|
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
set_file_type_list(GtkWidget *option_menu)
|
set_file_type_list(GtkWidget *option_menu)
|
||||||
|
@ -500,8 +512,8 @@ set_file_type_list(GtkWidget *option_menu)
|
||||||
/* Check all file types. */
|
/* Check all file types. */
|
||||||
index = 0;
|
index = 0;
|
||||||
for (ft = 0; ft < WTAP_NUM_FILE_TYPES; ft++) {
|
for (ft = 0; ft < WTAP_NUM_FILE_TYPES; ft++) {
|
||||||
if (filtered || marked || ft != cfile.cd_t) {
|
if (!packet_range_process_all(&range) || ft != cfile.cd_t) {
|
||||||
/* Filtered, marked or a different file type. We have to use Wiretap. */
|
/* not all unfiltered packets or a different file type. We have to use Wiretap. */
|
||||||
if (!can_save_with_wiretap(ft))
|
if (!can_save_with_wiretap(ft))
|
||||||
continue; /* We can't. */
|
continue; /* We can't. */
|
||||||
}
|
}
|
||||||
|
@ -541,43 +553,114 @@ static void
|
||||||
toggle_filtered_cb(GtkWidget *widget, gpointer data _U_)
|
toggle_filtered_cb(GtkWidget *widget, gpointer data _U_)
|
||||||
{
|
{
|
||||||
gboolean new_filtered;
|
gboolean new_filtered;
|
||||||
|
|
||||||
new_filtered = GTK_TOGGLE_BUTTON (widget)->active;
|
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. */
|
/* They changed the state of the "filtered" button. */
|
||||||
filtered = new_filtered;
|
range.process_filtered = new_filtered;
|
||||||
set_file_type_list(ft_om);
|
set_file_type_list(ft_om);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
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;
|
gboolean new_marked;
|
||||||
|
|
||||||
new_marked = GTK_TOGGLE_BUTTON (widget)->active;
|
new_marked = GTK_TOGGLE_BUTTON (widget)->active;
|
||||||
|
|
||||||
if (marked != new_marked) {
|
if (range.process_marked != new_marked) {
|
||||||
/* They changed the state of the "marked" button. */
|
/* They changed the state of the "marked-only" button. */
|
||||||
marked = new_marked;
|
range.process_marked = new_marked;
|
||||||
set_file_type_list(ft_om);
|
set_file_type_list(ft_om);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
static void
|
||||||
* Keep a static pointer to the current "Save Capture File As" window, if
|
toggle_select_marked_range(GtkWidget *widget, gpointer data _U_)
|
||||||
* 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
|
gboolean new_marked_range;
|
||||||
* up the existing one, rather than creating a new one.
|
|
||||||
*/
|
new_marked_range = GTK_TOGGLE_BUTTON (widget)->active;
|
||||||
static GtkWidget *file_save_as_w;
|
|
||||||
|
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
|
void
|
||||||
file_save_as_cmd_cb(GtkWidget *w _U_, gpointer data _U_)
|
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) {
|
if (file_save_as_w != NULL) {
|
||||||
/* There's already an "Save Capture File As" dialog box; reactivate it. */
|
/* There's already an "Save Capture File As" dialog box; reactivate it. */
|
||||||
reactivate_window(file_save_as_w);
|
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. */
|
/* Default to saving all packets, in the file's current format. */
|
||||||
filtered = FALSE;
|
range.process_all = TRUE;
|
||||||
marked = FALSE;
|
range.process_curr = FALSE;
|
||||||
filetype = cfile.cd_t;
|
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");
|
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);
|
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
|
/* If we've opened a file, start out by showing the files in the directory
|
||||||
in which that file resided. */
|
in which that file resided. */
|
||||||
if (last_open_dir)
|
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);
|
SIGNAL_CONNECT(ok_bt, "clicked", file_save_as_ok_cb, file_save_as_w);
|
||||||
|
|
||||||
/* Container for each row of widgets */
|
/* 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_container_border_width(GTK_CONTAINER(main_vb), 5);
|
||||||
gtk_box_pack_start(GTK_BOX(GTK_FILE_SELECTION(file_save_as_w)->action_area),
|
gtk_box_pack_start(GTK_BOX(GTK_FILE_SELECTION(file_save_as_w)->action_area),
|
||||||
main_vb, FALSE, FALSE, 0);
|
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
|
* 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
|
* 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.
|
* 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");
|
#if GTK_MAJOR_VERSION < 2
|
||||||
gtk_container_add(GTK_CONTAINER(main_vb), filter_cb);
|
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);
|
gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(filter_cb), FALSE);
|
||||||
SIGNAL_CONNECT(filter_cb, "toggled", toggle_filtered_cb, NULL);
|
SIGNAL_CONNECT(filter_cb, "toggled", toggle_filtered_cb, NULL);
|
||||||
gtk_widget_set_sensitive(filter_cb, can_save_with_wiretap(filetype));
|
gtk_widget_set_sensitive(filter_cb, can_save_with_wiretap(filetype));
|
||||||
gtk_widget_show(filter_cb);
|
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);
|
|
||||||
|
|
||||||
|
|
||||||
/* File type row */
|
/* File type row */
|
||||||
ft_hb = gtk_hbox_new(FALSE, 3);
|
ft_hb = gtk_hbox_new(FALSE, 3);
|
||||||
gtk_container_add(GTK_CONTAINER(main_vb), ft_hb);
|
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.
|
* as the routine that sets it also sets that menu.
|
||||||
*/
|
*/
|
||||||
file_set_save_marked_sensitive();
|
file_set_save_marked_sensitive();
|
||||||
|
|
||||||
/* Connect the cancel_button to destroy the widget */
|
/* Connect the cancel_button to destroy the widget */
|
||||||
SIGNAL_CONNECT_OBJECT(GTK_FILE_SELECTION(file_save_as_w)->cancel_button,
|
SIGNAL_CONNECT_OBJECT(GTK_FILE_SELECTION(file_save_as_w)->cancel_button,
|
||||||
"clicked", (GtkSignalFunc)gtk_widget_destroy,
|
"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. */
|
/* We don't currently have a "Save As..." dialog box up. */
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We can request that only the marked packets be saved only if we
|
/* 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. */
|
can use Wiretap to save the file and if there *are* marked packets. */
|
||||||
if (can_save_with_wiretap(filetype) && cfile.marked_count != 0)
|
if (can_save_with_wiretap(filetype) && cfile.marked_count != 0) {
|
||||||
gtk_widget_set_sensitive(mark_cb, TRUE);
|
gtk_widget_set_sensitive(select_marked_only, TRUE);
|
||||||
|
gtk_widget_set_sensitive(select_marked_range, TRUE);
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
/* Force the "Save only marked packets" toggle to "false", turn
|
/* Force the "Save only marked packets" toggle to "false", turn
|
||||||
off the flag it controls, and update the list of types we can
|
off the flag it controls, and update the list of types we can
|
||||||
save the file as. */
|
save the file as. */
|
||||||
marked = FALSE;
|
range.process_marked = FALSE;
|
||||||
gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(mark_cb), 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);
|
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 *cf_name;
|
||||||
gchar *dirname;
|
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)));
|
cf_name = g_strdup(gtk_file_selection_get_filename(GTK_FILE_SELECTION(fs)));
|
||||||
|
|
||||||
/* Perhaps the user specified a directory instead of a file.
|
/* 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
|
/* Write out the packets (all, or only the ones that are currently
|
||||||
displayed or marked) to the file with the specified name. */
|
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,
|
/* The write failed; don't dismiss the open dialog box,
|
||||||
just leave it around so that the user can, after they
|
just leave it around so that the user can, after they
|
||||||
dismiss the alert box popped up for the error, try again. */
|
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. */
|
/* Default to saving all packets, in the file's current format. */
|
||||||
filtered = FALSE;
|
|
||||||
color_marked = FALSE;
|
color_marked = FALSE;
|
||||||
filetype = cfile.cd_t;
|
filetype = cfile.cd_t;
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* main.c
|
/* 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
|
* Ethereal - Network traffic analyzer
|
||||||
* By Gerald Combs <gerald@ethereal.com>
|
* 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) {
|
static void mark_all_frames(gboolean set) {
|
||||||
frame_data *fdata;
|
frame_data *fdata;
|
||||||
|
|
||||||
|
cfile.marked_count = 0;
|
||||||
for (fdata = cfile.plist; fdata != NULL; fdata = fdata->next) {
|
for (fdata = cfile.plist; fdata != NULL; fdata = fdata->next) {
|
||||||
set_frame_mark(set,
|
set_frame_mark(set,
|
||||||
fdata,
|
fdata,
|
||||||
|
|
|
@ -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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -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__ */
|
Loading…
Reference in New Issue