2007-08-16 03:36:38 +00:00
/* follow_stream.c
* Common routines for following data streams
*
* $ Id $
*
* Wireshark - Network traffic analyzer
* By Gerald Combs < gerald @ wireshark . org >
* 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 . , 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 ,
* USA .
*/
# ifdef HAVE_CONFIG_H
# include "config.h"
# endif
2008-04-13 01:54:20 +00:00
# ifdef HAVE_UNISTD_H
# include <unistd.h>
# endif
2007-08-16 03:36:38 +00:00
# include <ctype.h>
# include <string.h>
# include <gtk/gtk.h>
2007-09-10 23:50:46 +00:00
# include <epan/addr_resolv.h>
2007-08-16 03:36:38 +00:00
# include <epan/follow.h>
# include <epan/filesystem.h>
# include <epan/prefs.h>
2008-04-13 01:54:20 +00:00
# include <epan/charsets.h>
# include <../alert_box.h>
# include <../isprint.h>
# include <../print.h>
# include <../simple_dialog.h>
2008-05-22 15:46:27 +00:00
# include <wsutil/file_util.h>
2008-04-13 01:54:20 +00:00
2008-04-13 12:41:22 +00:00
# include <gtk/color_utils.h>
2008-04-12 00:49:20 +00:00
# include <gtk/stock_icons.h>
2007-08-16 03:36:38 +00:00
# include <gtk/dlg_utils.h>
# include <gtk/follow_stream.h>
# include <gtk/font_utils.h>
# include <gtk/file_dlg.h>
# include <gtk/gui_utils.h>
2007-09-10 23:50:46 +00:00
# include <gtk/help_dlg.h>
2008-04-13 01:54:20 +00:00
# include "gtk/main.h"
2007-08-16 04:54:30 +00:00
2009-03-09 20:19:36 +00:00
# ifdef _WIN32
# include "../tempfile.h"
# include "gtk/print_win32.h"
# endif
2007-09-10 23:50:46 +00:00
2007-08-16 03:36:38 +00:00
/* static variable declarations to speed up the performance
* of follow_load_text and follow_add_to_gtk_text
*/
static GdkColor server_fg , server_bg ;
static GdkColor client_fg , client_bg ;
static GtkTextTag * server_tag , * client_tag ;
2009-06-01 19:43:58 +00:00
static void follow_find_destroy_cb ( GtkWidget * win _U_ , gpointer data ) ;
static void follow_find_button_cb ( GtkWidget * w , gpointer data ) ;
static gboolean follow_save_as_ok_cb ( GtkWidget * w _U_ , gpointer fs ) ;
2007-09-10 23:50:46 +00:00
static void follow_destroy_cb ( GtkWidget * w , gpointer data _U_ ) ;
2009-06-01 19:43:58 +00:00
static void follow_save_as_destroy_cb ( GtkWidget * win _U_ , gpointer data ) ;
2007-09-10 23:50:46 +00:00
2007-08-23 23:01:20 +00:00
GList * follow_infos = NULL ;
2009-10-05 07:25:33 +00:00
static frs_return_t
2007-08-16 03:36:38 +00:00
follow_read_stream ( follow_info_t * follow_info ,
2010-01-29 16:13:26 +00:00
gboolean ( * print_line_fcn_p ) ( char * , size_t , gboolean , void * ) ,
2007-08-16 03:36:38 +00:00
void * arg )
{
switch ( follow_info - > follow_type ) {
case FOLLOW_TCP :
2010-01-29 16:13:26 +00:00
return follow_read_tcp_stream ( follow_info , print_line_fcn_p , arg ) ;
2007-08-16 03:36:38 +00:00
2007-11-03 04:45:35 +00:00
case FOLLOW_UDP :
2010-01-29 16:13:26 +00:00
return follow_read_udp_stream ( follow_info , print_line_fcn_p , arg ) ;
2007-11-03 04:45:35 +00:00
2007-08-16 03:36:38 +00:00
case FOLLOW_SSL :
2010-01-29 16:13:26 +00:00
return follow_read_ssl_stream ( follow_info , print_line_fcn_p , arg ) ;
2007-08-16 03:36:38 +00:00
default :
g_assert_not_reached ( ) ;
2007-08-23 23:01:20 +00:00
return 0 ;
2007-08-16 03:36:38 +00:00
}
}
2009-04-27 14:56:07 +00:00
gboolean
2007-08-16 03:36:38 +00:00
follow_add_to_gtk_text ( char * buffer , size_t nchars , gboolean is_server ,
void * arg )
{
GtkWidget * text = arg ;
GtkTextBuffer * buf = gtk_text_view_get_buffer ( GTK_TEXT_VIEW ( text ) ) ;
GtkTextIter iter ;
/* While our isprint() hack is in place, we
2009-03-16 19:02:18 +00:00
* have to convert some chars to ' . ' in order
2007-08-16 03:36:38 +00:00
* to be able to see the data we * should * see
* in the GtkText widget .
*/
size_t i ;
for ( i = 0 ; i < nchars ; i + + ) {
if ( buffer [ i ] = = ' \n ' | | buffer [ i ] = = ' \r ' )
continue ;
if ( ! isprint ( ( guchar ) buffer [ i ] ) ) {
buffer [ i ] = ' . ' ;
}
}
gtk_text_buffer_get_end_iter ( buf , & iter ) ;
if ( is_server ) {
2009-04-16 00:45:26 +00:00
gtk_text_buffer_insert_with_tags ( buf , & iter , buffer , ( gint ) nchars ,
2007-08-16 03:36:38 +00:00
server_tag , NULL ) ;
} else {
2009-04-16 00:45:26 +00:00
gtk_text_buffer_insert_with_tags ( buf , & iter , buffer , ( gint ) nchars ,
2007-08-16 03:36:38 +00:00
client_tag , NULL ) ;
}
return TRUE ;
}
/*
* XXX - for text printing , we probably want to wrap lines at 80 characters ;
2007-08-23 23:01:20 +00:00
* ( PostScript printing is doing this already ) , and perhaps put some kind of
* dingbat ( to use the technical term ) to indicate a wrapped line , along the
* lines of what ' s done when displaying this in a window , as per Warren Young ' s
2007-08-16 03:36:38 +00:00
* suggestion .
*/
2009-10-05 07:25:33 +00:00
static gboolean
2007-09-10 23:50:46 +00:00
follow_print_text ( char * buffer , size_t nchars , gboolean is_server _U_ ,
void * arg )
2007-08-16 03:36:38 +00:00
{
print_stream_t * stream = arg ;
size_t i ;
char * str ;
/* convert non printable characters */
for ( i = 0 ; i < nchars ; i + + ) {
if ( buffer [ i ] = = ' \n ' | | buffer [ i ] = = ' \r ' )
continue ;
if ( ! isprint ( ( guchar ) buffer [ i ] ) ) {
buffer [ i ] = ' . ' ;
}
}
/* convert unterminated char array to a zero terminated string */
str = g_malloc ( nchars + 1 ) ;
memcpy ( str , buffer , nchars ) ;
str [ nchars ] = 0 ;
print_line ( stream , /*indent*/ 0 , str ) ;
g_free ( str ) ;
return TRUE ;
}
2009-10-05 07:25:33 +00:00
static gboolean
2007-08-16 03:36:38 +00:00
follow_write_raw ( char * buffer , size_t nchars , gboolean is_server _U_ , void * arg )
{
FILE * fh = arg ;
size_t nwritten ;
nwritten = fwrite ( buffer , 1 , nchars , fh ) ;
if ( nwritten ! = nchars )
return FALSE ;
return TRUE ;
}
/* Handles the display style toggling */
2009-06-01 19:43:58 +00:00
static void
2007-08-16 03:36:38 +00:00
follow_charset_toggle_cb ( GtkWidget * w _U_ , gpointer data )
{
follow_info_t * follow_info = data ;
/*
* A radio button toggles when it goes on and when it goes
* off , so when you click a radio button two signals are
* delivered . We only want to reprocess the display once ,
* so we do it only when the button goes on .
*/
if ( GTK_TOGGLE_BUTTON ( w ) - > active ) {
if ( w = = follow_info - > ebcdic_bt )
follow_info - > show_type = SHOW_EBCDIC ;
else if ( w = = follow_info - > hexdump_bt )
follow_info - > show_type = SHOW_HEXDUMP ;
else if ( w = = follow_info - > carray_bt )
follow_info - > show_type = SHOW_CARRAY ;
else if ( w = = follow_info - > ascii_bt )
follow_info - > show_type = SHOW_ASCII ;
else if ( w = = follow_info - > raw_bt )
follow_info - > show_type = SHOW_RAW ;
follow_load_text ( follow_info ) ;
}
}
void
follow_load_text ( follow_info_t * follow_info )
{
GtkTextBuffer * buf ;
buf = gtk_text_view_get_buffer ( GTK_TEXT_VIEW ( follow_info - > text ) ) ;
/* prepare colors one time for repeated use by follow_add_to_gtk_text */
color_t_to_gdkcolor ( & server_fg , & prefs . st_server_fg ) ;
color_t_to_gdkcolor ( & server_bg , & prefs . st_server_bg ) ;
color_t_to_gdkcolor ( & client_fg , & prefs . st_client_fg ) ;
color_t_to_gdkcolor ( & client_bg , & prefs . st_client_bg ) ;
/* prepare tags one time for repeated use by follow_add_to_gtk_text */
server_tag = gtk_text_buffer_create_tag ( buf , NULL , " foreground-gdk " ,
& server_fg , " background-gdk " ,
& server_bg , " font-desc " ,
user_font_get_regular ( ) , NULL ) ;
client_tag = gtk_text_buffer_create_tag ( buf , NULL , " foreground-gdk " ,
& client_fg , " background-gdk " ,
& client_bg , " font-desc " ,
user_font_get_regular ( ) , NULL ) ;
2008-04-05 00:12:04 +00:00
/* Delete any info already in text box */
2007-08-16 03:36:38 +00:00
gtk_text_buffer_set_text ( buf , " " , - 1 ) ;
2008-04-05 00:12:04 +00:00
2007-08-16 03:36:38 +00:00
follow_read_stream ( follow_info , follow_add_to_gtk_text ,
follow_info - > text ) ;
}
2009-04-27 14:56:07 +00:00
void
2007-08-16 03:36:38 +00:00
follow_filter_out_stream ( GtkWidget * w _U_ , gpointer data )
{
follow_info_t * follow_info = data ;
/* Lock out user from messing with us. (ie. don't free our data!) */
gtk_widget_set_sensitive ( follow_info - > streamwindow , FALSE ) ;
/* Set the display filter. */
2007-09-10 23:50:46 +00:00
gtk_entry_set_text ( GTK_ENTRY ( follow_info - > filter_te ) ,
follow_info - > filter_out_filter ) ;
2007-08-16 03:36:38 +00:00
/* Run the display filter so it goes in effect. */
main_filter_packets ( & cfile , follow_info - > filter_out_filter , FALSE ) ;
/* we force a subsequent close */
window_destroy ( follow_info - > streamwindow ) ;
return ;
}
2009-06-01 19:43:58 +00:00
static void
2007-08-16 03:36:38 +00:00
follow_find_cb ( GtkWidget * w _U_ , gpointer data )
{
follow_info_t * follow_info = data ;
GtkTooltips * tooltips ;
GtkWidget * find_dlg_w , * main_vb , * buttons_row , * find_lb ;
GtkWidget * find_hb , * find_text_box , * find_bt , * cancel_bt ;
tooltips = gtk_tooltips_new ( ) ;
if ( follow_info - > find_dlg_w ! = NULL ) {
/* There's already a dialog box; reactivate it. */
reactivate_window ( follow_info - > find_dlg_w ) ;
return ;
}
/* Create the find box */
find_dlg_w = dlg_window_new ( " Wireshark: Find text " ) ;
gtk_window_set_transient_for ( GTK_WINDOW ( find_dlg_w ) ,
GTK_WINDOW ( follow_info - > streamwindow ) ) ;
gtk_window_set_destroy_with_parent ( GTK_WINDOW ( find_dlg_w ) , TRUE ) ;
follow_info - > find_dlg_w = find_dlg_w ;
2008-04-11 22:10:36 +00:00
g_signal_connect ( find_dlg_w , " destroy " , G_CALLBACK ( follow_find_destroy_cb ) ,
2007-09-10 23:50:46 +00:00
follow_info ) ;
2008-04-11 22:10:36 +00:00
g_signal_connect ( find_dlg_w , " delete_event " , G_CALLBACK ( window_delete_event_cb ) ,
2007-09-10 23:50:46 +00:00
NULL ) ;
2007-08-16 03:36:38 +00:00
/* Main vertical box */
main_vb = gtk_vbox_new ( FALSE , 3 ) ;
2008-06-29 15:51:43 +00:00
gtk_container_set_border_width ( GTK_CONTAINER ( main_vb ) , 5 ) ;
2007-08-16 03:36:38 +00:00
gtk_container_add ( GTK_CONTAINER ( find_dlg_w ) , main_vb ) ;
2007-09-10 23:50:46 +00:00
/* Horizontal box for find label, entry field and up/down radio
buttons */
2007-08-16 03:36:38 +00:00
find_hb = gtk_hbox_new ( FALSE , 3 ) ;
gtk_container_add ( GTK_CONTAINER ( main_vb ) , find_hb ) ;
gtk_widget_show ( find_hb ) ;
/* Find label */
find_lb = gtk_label_new ( " Find text: " ) ;
gtk_box_pack_start ( GTK_BOX ( find_hb ) , find_lb , FALSE , FALSE , 0 ) ;
gtk_widget_show ( find_lb ) ;
/* Find field */
find_text_box = gtk_entry_new ( ) ;
gtk_box_pack_start ( GTK_BOX ( find_hb ) , find_text_box , FALSE , FALSE , 0 ) ;
gtk_tooltips_set_tip ( tooltips , find_text_box , " Text to search for (case sensitive) " , NULL ) ;
gtk_widget_show ( find_text_box ) ;
/* Buttons row */
2007-09-10 23:50:46 +00:00
buttons_row = dlg_button_row_new ( GTK_STOCK_FIND , GTK_STOCK_CANCEL ,
NULL ) ;
2007-08-16 03:36:38 +00:00
gtk_container_add ( GTK_CONTAINER ( main_vb ) , buttons_row ) ;
2008-04-11 16:44:31 +00:00
find_bt = g_object_get_data ( G_OBJECT ( buttons_row ) , GTK_STOCK_FIND ) ;
cancel_bt = g_object_get_data ( G_OBJECT ( buttons_row ) , GTK_STOCK_CANCEL ) ;
2007-08-16 03:36:38 +00:00
2008-04-11 22:10:36 +00:00
g_signal_connect ( find_bt , " clicked " , G_CALLBACK ( follow_find_button_cb ) , follow_info ) ;
2008-04-11 16:44:31 +00:00
g_object_set_data ( G_OBJECT ( find_bt ) , " find_string " , find_text_box ) ;
2007-09-10 23:50:46 +00:00
window_set_cancel_button ( find_dlg_w , cancel_bt ,
window_cancel_button_cb ) ;
2007-08-16 03:36:38 +00:00
/* Hitting return in the find field "clicks" the find button */
dlg_set_activate ( find_text_box , find_bt ) ;
/* Show the dialog */
gtk_widget_show_all ( find_dlg_w ) ;
window_present ( find_dlg_w ) ;
}
2009-06-01 19:43:58 +00:00
static void
2007-08-16 03:36:38 +00:00
follow_find_button_cb ( GtkWidget * w , gpointer data )
{
gboolean found ;
const gchar * find_string ;
follow_info_t * follow_info = data ;
GtkTextBuffer * buffer ;
GtkTextIter iter , match_start , match_end ;
GtkTextMark * last_pos_mark ;
GtkWidget * find_string_w ;
/* Get the text the user typed into the find field */
2008-04-11 16:44:31 +00:00
find_string_w = ( GtkWidget * ) g_object_get_data ( G_OBJECT ( w ) , " find_string " ) ;
2007-08-16 03:36:38 +00:00
find_string = gtk_entry_get_text ( GTK_ENTRY ( find_string_w ) ) ;
/* Get the buffer associated with the follow stream */
buffer = gtk_text_view_get_buffer ( GTK_TEXT_VIEW ( follow_info - > text ) ) ;
gtk_text_buffer_get_start_iter ( buffer , & iter ) ;
/* Look for the search string in the buffer */
last_pos_mark = gtk_text_buffer_get_mark ( buffer , " last_position " ) ;
if ( last_pos_mark )
gtk_text_buffer_get_iter_at_mark ( buffer , & iter , last_pos_mark ) ;
2007-09-10 23:50:46 +00:00
found = gtk_text_iter_forward_search ( & iter , find_string , 0 ,
& match_start ,
2007-08-16 03:36:38 +00:00
& match_end ,
NULL ) ;
if ( found ) {
gtk_text_buffer_select_range ( buffer , & match_start , & match_end ) ;
2007-09-10 23:50:46 +00:00
last_pos_mark = gtk_text_buffer_create_mark ( buffer ,
" last_position " ,
2007-08-16 03:36:38 +00:00
& match_end , FALSE ) ;
gtk_text_view_scroll_mark_onscreen ( GTK_TEXT_VIEW ( follow_info - > text ) , last_pos_mark ) ;
} else {
/* We didn't find a match */
simple_dialog ( ESD_TYPE_INFO , ESD_BTN_OK ,
" %sFind text has reached the end of the followed "
" stream%s \n \n The next search will start from the "
" beginning " , simple_dialog_primary_start ( ) ,
simple_dialog_primary_end ( ) ) ;
if ( last_pos_mark )
gtk_text_buffer_delete_mark ( buffer , last_pos_mark ) ;
}
2007-08-23 23:01:20 +00:00
2007-08-16 03:36:38 +00:00
}
2009-06-01 19:43:58 +00:00
static void
2007-08-16 03:36:38 +00:00
follow_find_destroy_cb ( GtkWidget * win _U_ , gpointer data )
{
follow_info_t * follow_info = data ;
/* Note that we no longer have a dialog box. */
follow_info - > find_dlg_w = NULL ;
}
2009-06-01 19:43:58 +00:00
static void
2007-08-16 03:36:38 +00:00
follow_print_stream ( GtkWidget * w _U_ , gpointer data )
{
print_stream_t * stream ;
2009-03-09 20:19:36 +00:00
gboolean to_file ;
2007-08-16 03:36:38 +00:00
char * print_dest ;
follow_info_t * follow_info = data ;
# ifdef _WIN32
2009-03-09 20:19:36 +00:00
gboolean win_printer = FALSE ;
int tmp_fd ;
2009-07-01 23:36:51 +00:00
char * tmp_namebuf ;
2007-08-16 03:36:38 +00:00
# endif
switch ( prefs . pr_dest ) {
case PR_DEST_CMD :
# ifdef _WIN32
win_printer = TRUE ;
2009-03-09 20:19:36 +00:00
/* (The code for creating a temp filename is adapted from print_dlg.c). */
/* We currently don't have a function in util.h to create just a tempfile */
/* name, so simply create a tempfile using the "official" function, */
/* then delete this file again. After this, the name MUST be available. */
/* */
/* Don't use tmpnam() or such, as this will fail under some ACL */
/* circumstances: http://bugs.wireshark.org/bugzilla/show_bug.cgi?id=358 */
/* Also: tmpnam is "insecure" and should not be used. */
2009-07-02 02:50:24 +00:00
tmp_fd = create_tempfile ( & tmp_namebuf , " wshprint " ) ;
2009-03-09 20:19:36 +00:00
if ( tmp_fd = = - 1 ) {
simple_dialog ( ESD_TYPE_ERROR , ESD_BTN_OK ,
2009-07-01 23:36:51 +00:00
" Couldn't create temporary file for printing: \n %s " , tmp_namebuf ) ;
2009-03-09 20:19:36 +00:00
return ;
}
ws_close ( tmp_fd ) ;
ws_unlink ( tmp_namebuf ) ;
print_dest = tmp_namebuf ;
2007-08-16 03:36:38 +00:00
to_file = TRUE ;
# else
print_dest = prefs . pr_cmd ;
to_file = FALSE ;
# endif
break ;
case PR_DEST_FILE :
print_dest = prefs . pr_file ;
to_file = TRUE ;
break ;
default : /* "Can't happen" */
simple_dialog ( ESD_TYPE_ERROR , ESD_BTN_OK ,
" Couldn't figure out where to send the print "
" job. Check your preferences. " ) ;
return ;
}
switch ( prefs . pr_format ) {
case PR_FMT_TEXT :
stream = print_stream_text_new ( to_file , print_dest ) ;
break ;
case PR_FMT_PS :
stream = print_stream_ps_new ( to_file , print_dest ) ;
break ;
default :
g_assert_not_reached ( ) ;
stream = NULL ;
}
if ( stream = = NULL ) {
if ( to_file ) {
2009-03-09 20:19:36 +00:00
open_failure_alert_box ( print_dest , errno , TRUE ) ;
2007-08-16 03:36:38 +00:00
} else {
simple_dialog ( ESD_TYPE_ERROR , ESD_BTN_OK ,
2007-09-10 23:50:46 +00:00
" Couldn't run print command %s. " ,
prefs . pr_cmd ) ;
2007-08-16 03:36:38 +00:00
}
return ;
}
if ( ! print_preamble ( stream , cfile . filename ) )
goto print_error ;
switch ( follow_read_stream ( follow_info , follow_print_text , stream ) ) {
case FRS_OK :
break ;
case FRS_OPEN_ERROR :
case FRS_READ_ERROR :
/* XXX - cancel printing? */
destroy_print_stream ( stream ) ;
return ;
case FRS_PRINT_ERROR :
goto print_error ;
}
if ( ! print_finale ( stream ) )
goto print_error ;
if ( ! destroy_print_stream ( stream ) ) {
if ( to_file ) {
2009-03-09 20:19:36 +00:00
write_failure_alert_box ( print_dest , errno ) ;
2007-08-16 03:36:38 +00:00
} else {
simple_dialog ( ESD_TYPE_ERROR , ESD_BTN_OK ,
" Error closing print destination. " ) ;
}
}
# ifdef _WIN32
if ( win_printer ) {
print_mswin ( print_dest ) ;
/* trash temp file */
2008-05-22 15:46:27 +00:00
ws_remove ( print_dest ) ;
2007-08-16 03:36:38 +00:00
}
# endif
return ;
print_error :
if ( to_file ) {
2009-03-09 20:19:36 +00:00
write_failure_alert_box ( print_dest , errno ) ;
2007-08-16 03:36:38 +00:00
} else {
simple_dialog ( ESD_TYPE_ERROR , ESD_BTN_OK ,
2007-09-10 23:50:46 +00:00
" Error writing to print command: %s " ,
strerror ( errno ) ) ;
2007-08-16 03:36:38 +00:00
}
/* XXX - cancel printing? */
destroy_print_stream ( stream ) ;
# ifdef _WIN32
if ( win_printer ) {
/* trash temp file */
2008-05-22 15:46:27 +00:00
ws_remove ( print_dest ) ;
2007-08-16 03:36:38 +00:00
}
# endif
}
/*
2008-05-23 02:33:24 +00:00
* Keep a static pointer to the current " Save Follow Stream As " window , if
2007-08-16 03:36:38 +00:00
* any , so that if somebody tries to do " Save "
2008-05-23 02:33:24 +00:00
* while there ' s already a " Save Follow Stream " window up , we just pop
2007-08-16 03:36:38 +00:00
* up the existing one , rather than creating a new one .
*/
2009-06-01 19:43:58 +00:00
static void
2007-08-16 03:36:38 +00:00
follow_save_as_cmd_cb ( GtkWidget * w _U_ , gpointer data )
{
GtkWidget * new_win ;
follow_info_t * follow_info = data ;
2009-06-01 19:43:58 +00:00
#if 0 /* XXX: GtkFileChooserDialog/gtk_dialog_run currently being used is effectively modal so this is not req'd */
2007-08-16 03:36:38 +00:00
if ( follow_info - > follow_save_as_w ! = NULL ) {
/* There's already a dialog box; reactivate it. */
reactivate_window ( follow_info - > follow_save_as_w ) ;
return ;
}
2009-06-01 19:43:58 +00:00
# endif
2007-11-03 04:45:35 +00:00
new_win = file_selection_new ( " Wireshark: Save Follow Stream As " ,
2007-08-16 03:36:38 +00:00
FILE_SELECTION_SAVE ) ;
follow_info - > follow_save_as_w = new_win ;
2009-06-02 15:39:20 +00:00
# if GTK_CHECK_VERSION(2,8,0)
gtk_file_chooser_set_do_overwrite_confirmation ( GTK_FILE_CHOOSER ( new_win ) , TRUE ) ;
# endif
2007-08-16 03:36:38 +00:00
/* Tuck away the follow_info object into the window */
2008-04-11 16:44:31 +00:00
g_object_set_data ( G_OBJECT ( new_win ) , E_FOLLOW_INFO_KEY , follow_info ) ;
2007-08-16 03:36:38 +00:00
2008-04-11 22:10:36 +00:00
g_signal_connect ( new_win , " destroy " , G_CALLBACK ( follow_save_as_destroy_cb ) ,
2007-09-10 23:50:46 +00:00
follow_info ) ;
2007-08-16 03:36:38 +00:00
2009-06-01 19:43:58 +00:00
#if 0
2007-08-16 03:36:38 +00:00
if ( gtk_dialog_run ( GTK_DIALOG ( new_win ) ) = = GTK_RESPONSE_ACCEPT )
{
follow_save_as_ok_cb ( new_win , new_win ) ;
} else {
window_destroy ( new_win ) ;
}
2009-06-01 19:43:58 +00:00
# endif
/* "Run" the GtkFileChooserDialog. */
/* Upon exit: If "Accept" run the OK callback. */
/* If the OK callback returns with a FALSE status, re-run the dialog.*/
/* If not accept (ie: cancel) destroy the window. */
/* XXX: If the OK callback pops up an alert box (eg: for an error) it *must* */
/* return with a TRUE status so that the dialog window will be destroyed. */
/* Trying to re-run the dialog after popping up an alert box will not work */
/* since the user will not be able to dismiss the alert box. */
/* The (somewhat unfriendly) effect: the user must re-invoke the */
/* GtkFileChooserDialog whenever the OK callback pops up an alert box. */
/* */
/* ToDo: use GtkFileChooserWidget in a dialog window instead of */
/* GtkFileChooserDialog. */
while ( gtk_dialog_run ( GTK_DIALOG ( new_win ) ) = = GTK_RESPONSE_ACCEPT ) {
if ( follow_save_as_ok_cb ( NULL , new_win ) ) {
break ; /* we're done */
}
}
window_destroy ( new_win ) ;
2007-08-16 03:36:38 +00:00
}
2009-06-01 19:43:58 +00:00
static gboolean
2007-08-16 03:36:38 +00:00
follow_save_as_ok_cb ( GtkWidget * w _U_ , gpointer fs )
{
gchar * to_name ;
follow_info_t * follow_info ;
FILE * fh ;
print_stream_t * stream = NULL ;
gchar * dirname ;
2009-06-01 19:43:58 +00:00
to_name = gtk_file_chooser_get_filename ( GTK_FILE_CHOOSER ( fs ) ) ;
2007-08-16 03:36:38 +00:00
/* Perhaps the user specified a directory instead of a file.
Check whether they did . */
if ( test_for_directory ( to_name ) = = EISDIR ) {
/* It's a directory - set the file selection box to display that
directory , and leave the selection box displayed . */
set_last_open_dir ( to_name ) ;
g_free ( to_name ) ;
file_selection_set_current_folder ( fs , get_last_open_dir ( ) ) ;
2009-06-01 19:43:58 +00:00
gtk_file_chooser_set_current_name ( fs , " " ) ;
return FALSE ; /* do gtk_dialog_run again */
2007-08-16 03:36:38 +00:00
}
2008-04-11 16:44:31 +00:00
follow_info = g_object_get_data ( G_OBJECT ( fs ) , E_FOLLOW_INFO_KEY ) ;
2009-06-01 19:43:58 +00:00
2007-08-16 03:36:38 +00:00
if ( follow_info - > show_type = = SHOW_RAW ) {
/* Write the data out as raw binary data */
2008-05-22 15:46:27 +00:00
fh = ws_fopen ( to_name , " wb " ) ;
2007-08-16 03:36:38 +00:00
} else {
/* Write it out as text */
2008-05-22 15:46:27 +00:00
fh = ws_fopen ( to_name , " w " ) ;
2007-08-16 03:36:38 +00:00
}
if ( fh = = NULL ) {
open_failure_alert_box ( to_name , errno , TRUE ) ;
g_free ( to_name ) ;
2009-06-01 19:43:58 +00:00
return TRUE ;
2007-08-16 03:36:38 +00:00
}
2009-06-01 19:43:58 +00:00
#if 0 /* handled by caller (for now) .... */
2007-08-16 03:36:38 +00:00
gtk_widget_hide ( GTK_WIDGET ( fs ) ) ;
window_destroy ( GTK_WIDGET ( fs ) ) ;
2009-06-01 19:43:58 +00:00
# endif
2007-08-16 03:36:38 +00:00
if ( follow_info - > show_type = = SHOW_RAW ) {
switch ( follow_read_stream ( follow_info , follow_write_raw , fh ) ) {
case FRS_OK :
if ( fclose ( fh ) = = EOF )
write_failure_alert_box ( to_name , errno ) ;
break ;
case FRS_OPEN_ERROR :
case FRS_READ_ERROR :
fclose ( fh ) ;
break ;
case FRS_PRINT_ERROR :
write_failure_alert_box ( to_name , errno ) ;
fclose ( fh ) ;
break ;
}
} else {
stream = print_stream_text_stdio_new ( fh ) ;
2007-09-10 23:50:46 +00:00
switch ( follow_read_stream ( follow_info , follow_print_text ,
stream ) ) {
2007-08-16 03:36:38 +00:00
case FRS_OK :
if ( ! destroy_print_stream ( stream ) )
write_failure_alert_box ( to_name , errno ) ;
break ;
case FRS_OPEN_ERROR :
case FRS_READ_ERROR :
destroy_print_stream ( stream ) ;
break ;
case FRS_PRINT_ERROR :
write_failure_alert_box ( to_name , errno ) ;
destroy_print_stream ( stream ) ;
break ;
}
}
/* Save the directory name for future file dialogs. */
dirname = get_dirname ( to_name ) ; /* Overwrites to_name */
set_last_open_dir ( dirname ) ;
g_free ( to_name ) ;
2009-06-01 19:43:58 +00:00
return TRUE ;
2007-08-16 03:36:38 +00:00
}
2009-06-01 19:43:58 +00:00
static void
2007-08-16 03:36:38 +00:00
follow_save_as_destroy_cb ( GtkWidget * win _U_ , gpointer data )
{
follow_info_t * follow_info = data ;
/* Note that we no longer have a dialog box. */
follow_info - > follow_save_as_w = NULL ;
}
2009-10-05 07:25:33 +00:00
static void
2008-04-29 18:46:10 +00:00
follow_stream_direction_changed ( GtkWidget * w , gpointer data )
2007-08-16 03:36:38 +00:00
{
2008-04-29 18:46:10 +00:00
follow_info_t * follow_info = data ;
2007-08-16 03:36:38 +00:00
2008-04-29 18:46:10 +00:00
switch ( gtk_combo_box_get_active ( GTK_COMBO_BOX ( w ) ) ) {
2007-08-16 03:36:38 +00:00
2008-04-29 18:46:10 +00:00
case 0 :
follow_info - > show_stream = BOTH_HOSTS ;
follow_load_text ( follow_info ) ;
break ;
case 1 :
follow_info - > show_stream = FROM_CLIENT ;
follow_load_text ( follow_info ) ;
break ;
case 2 :
follow_info - > show_stream = FROM_SERVER ;
follow_load_text ( follow_info ) ;
break ;
}
2007-08-16 03:36:38 +00:00
}
/* Add a "follow_info_t" structure to the list. */
2009-06-01 19:43:58 +00:00
static void
2007-08-16 03:36:38 +00:00
remember_follow_info ( follow_info_t * follow_info )
{
follow_infos = g_list_append ( follow_infos , follow_info ) ;
}
2008-03-26 22:33:56 +00:00
# define IS_SHOW_TYPE(x) (follow_info->show_type == x ? 1 : 0)
2007-08-16 03:36:38 +00:00
/* Remove a "follow_info_t" structure from the list. */
2009-06-01 19:43:58 +00:00
static void
2007-08-16 03:36:38 +00:00
forget_follow_info ( follow_info_t * follow_info )
{
follow_infos = g_list_remove ( follow_infos , follow_info ) ;
}
2007-09-10 23:50:46 +00:00
void
follow_stream ( gchar * title , follow_info_t * follow_info ,
gchar * both_directions_string ,
gchar * server_to_client_string , gchar * client_to_server_string )
{
GtkWidget * streamwindow , * vbox , * txt_scrollw , * text ;
GtkWidget * hbox , * bbox , * button , * radio_bt ;
GtkWidget * stream_fr , * stream_vb ;
2008-04-29 18:46:10 +00:00
GtkWidget * stream_cmb ;
2007-09-10 23:50:46 +00:00
GtkTooltips * tooltips ;
2007-11-03 04:45:35 +00:00
follow_stats_t stats ;
2007-09-10 23:50:46 +00:00
2008-03-26 22:33:56 +00:00
follow_info - > show_type = SHOW_RAW ;
2007-09-10 23:50:46 +00:00
streamwindow = dlg_window_new ( title ) ;
/* needed in follow_filter_out_stream(), is there a better way? */
follow_info - > streamwindow = streamwindow ;
2008-03-26 22:33:56 +00:00
2007-09-10 23:50:46 +00:00
gtk_widget_set_name ( streamwindow , title ) ;
gtk_window_set_default_size ( GTK_WINDOW ( streamwindow ) ,
DEF_WIDTH , DEF_HEIGHT ) ;
2008-06-29 15:51:43 +00:00
gtk_container_set_border_width ( GTK_CONTAINER ( streamwindow ) , 6 ) ;
2008-03-26 22:33:56 +00:00
2007-09-10 23:50:46 +00:00
/* setup the container */
tooltips = gtk_tooltips_new ( ) ;
vbox = gtk_vbox_new ( FALSE , 6 ) ;
gtk_container_add ( GTK_CONTAINER ( streamwindow ) , vbox ) ;
/* content frame */
if ( incomplete_tcp_stream ) {
stream_fr = gtk_frame_new ( " Stream Content (incomplete) " ) ;
} else {
stream_fr = gtk_frame_new ( " Stream Content " ) ;
}
gtk_container_add ( GTK_CONTAINER ( vbox ) , stream_fr ) ;
gtk_widget_show ( stream_fr ) ;
2008-03-26 22:33:56 +00:00
2007-09-10 23:50:46 +00:00
stream_vb = gtk_vbox_new ( FALSE , 6 ) ;
gtk_container_set_border_width ( GTK_CONTAINER ( stream_vb ) , 6 ) ;
gtk_container_add ( GTK_CONTAINER ( stream_fr ) , stream_vb ) ;
/* create a scrolled window for the text */
txt_scrollw = scrolled_window_new ( NULL , NULL ) ;
gtk_scrolled_window_set_shadow_type ( GTK_SCROLLED_WINDOW ( txt_scrollw ) ,
GTK_SHADOW_IN ) ;
gtk_box_pack_start ( GTK_BOX ( stream_vb ) , txt_scrollw , TRUE , TRUE , 0 ) ;
/* create a text box */
text = gtk_text_view_new ( ) ;
gtk_text_view_set_editable ( GTK_TEXT_VIEW ( text ) , FALSE ) ;
2008-03-28 04:42:29 +00:00
gtk_text_view_set_wrap_mode ( GTK_TEXT_VIEW ( text ) , GTK_WRAP_WORD_CHAR ) ;
2008-04-05 00:12:04 +00:00
2007-09-10 23:50:46 +00:00
gtk_container_add ( GTK_CONTAINER ( txt_scrollw ) , text ) ;
follow_info - > text = text ;
/* stream hbox */
hbox = gtk_hbox_new ( FALSE , 1 ) ;
gtk_box_pack_start ( GTK_BOX ( stream_vb ) , hbox , FALSE , FALSE , 0 ) ;
/* Create Find Button */
2008-04-11 18:58:19 +00:00
button = gtk_button_new_from_stock ( GTK_STOCK_FIND ) ;
2008-04-11 22:10:36 +00:00
g_signal_connect ( button , " clicked " , G_CALLBACK ( follow_find_cb ) , follow_info ) ;
2007-09-10 23:50:46 +00:00
gtk_tooltips_set_tip ( tooltips , button , " Find text in the displayed content " , NULL ) ;
gtk_box_pack_start ( GTK_BOX ( hbox ) , button , FALSE , FALSE , 0 ) ;
/* Create Save As Button */
2008-04-11 18:58:19 +00:00
button = gtk_button_new_from_stock ( GTK_STOCK_SAVE_AS ) ;
2008-04-11 22:10:36 +00:00
g_signal_connect ( button , " clicked " , G_CALLBACK ( follow_save_as_cmd_cb ) , follow_info ) ;
2007-09-10 23:50:46 +00:00
gtk_tooltips_set_tip ( tooltips , button , " Save the content as currently displayed " , NULL ) ;
gtk_box_pack_start ( GTK_BOX ( hbox ) , button , FALSE , FALSE , 0 ) ;
/* Create Print Button */
2008-04-11 18:58:19 +00:00
button = gtk_button_new_from_stock ( GTK_STOCK_PRINT ) ;
2008-04-11 22:10:36 +00:00
g_signal_connect ( button , " clicked " , G_CALLBACK ( follow_print_stream ) , follow_info ) ;
2007-09-10 23:50:46 +00:00
gtk_tooltips_set_tip ( tooltips , button , " Print the content as currently displayed " , NULL ) ;
gtk_box_pack_start ( GTK_BOX ( hbox ) , button , FALSE , FALSE , 0 ) ;
2008-03-26 22:33:56 +00:00
2007-09-10 23:50:46 +00:00
/* Stream to show */
2007-11-03 04:45:35 +00:00
follow_stats ( & stats ) ;
2007-09-10 23:50:46 +00:00
follow_info - > is_ipv6 = stats . is_ipv6 ;
2008-04-29 18:46:10 +00:00
stream_cmb = gtk_combo_box_new_text ( ) ;
2007-09-10 23:50:46 +00:00
2008-04-29 18:46:10 +00:00
gtk_combo_box_append_text ( GTK_COMBO_BOX ( stream_cmb ) ,
both_directions_string ) ;
2007-09-10 23:50:46 +00:00
follow_info - > show_stream = BOTH_HOSTS ;
2008-04-29 18:46:10 +00:00
gtk_combo_box_append_text ( GTK_COMBO_BOX ( stream_cmb ) ,
server_to_client_string ) ;
gtk_combo_box_append_text ( GTK_COMBO_BOX ( stream_cmb ) ,
client_to_server_string ) ;
2009-04-27 14:39:10 +00:00
gtk_combo_box_set_active ( GTK_COMBO_BOX ( stream_cmb ) , 0 ) ; /* Do this before signal_connect */
/* so callback not triggered */
2008-04-29 18:46:10 +00:00
g_signal_connect ( stream_cmb , " changed " ,
G_CALLBACK ( follow_stream_direction_changed ) ,
follow_info ) ;
gtk_tooltips_set_tip ( tooltips , stream_cmb ,
2007-09-13 22:11:50 +00:00
" Select the stream direction to display " , NULL ) ;
2008-04-29 18:46:10 +00:00
gtk_box_pack_start ( GTK_BOX ( hbox ) , stream_cmb , FALSE , FALSE , 0 ) ;
2007-09-10 23:50:46 +00:00
/* ASCII radio button */
radio_bt = gtk_radio_button_new_with_label ( NULL , " ASCII " ) ;
gtk_tooltips_set_tip ( tooltips , radio_bt , " Stream data output in \" ASCII \" format " , NULL ) ;
2008-03-26 22:33:56 +00:00
gtk_toggle_button_set_active ( GTK_TOGGLE_BUTTON ( radio_bt ) ,
IS_SHOW_TYPE ( SHOW_ASCII ) ) ;
2007-09-10 23:50:46 +00:00
gtk_box_pack_start ( GTK_BOX ( hbox ) , radio_bt , FALSE , FALSE , 0 ) ;
2008-04-11 22:10:36 +00:00
g_signal_connect ( radio_bt , " toggled " , G_CALLBACK ( follow_charset_toggle_cb ) ,
2007-09-10 23:50:46 +00:00
follow_info ) ;
follow_info - > ascii_bt = radio_bt ;
/* EBCDIC radio button */
2008-06-29 15:51:43 +00:00
radio_bt = gtk_radio_button_new_with_label ( gtk_radio_button_get_group
2007-09-10 23:50:46 +00:00
( GTK_RADIO_BUTTON ( radio_bt ) ) ,
" EBCDIC " ) ;
gtk_tooltips_set_tip ( tooltips , radio_bt , " Stream data output in \" EBCDIC \" format " , NULL ) ;
2008-03-26 22:33:56 +00:00
gtk_toggle_button_set_active ( GTK_TOGGLE_BUTTON ( radio_bt ) ,
IS_SHOW_TYPE ( SHOW_EBCDIC ) ) ;
2007-09-10 23:50:46 +00:00
gtk_box_pack_start ( GTK_BOX ( hbox ) , radio_bt , FALSE , FALSE , 0 ) ;
2008-04-11 22:10:36 +00:00
g_signal_connect ( radio_bt , " toggled " , G_CALLBACK ( follow_charset_toggle_cb ) ,
2007-09-10 23:50:46 +00:00
follow_info ) ;
follow_info - > ebcdic_bt = radio_bt ;
/* HEX DUMP radio button */
2008-06-29 15:51:43 +00:00
radio_bt = gtk_radio_button_new_with_label ( gtk_radio_button_get_group
2007-09-10 23:50:46 +00:00
( GTK_RADIO_BUTTON ( radio_bt ) ) ,
" Hex Dump " ) ;
gtk_tooltips_set_tip ( tooltips , radio_bt , " Stream data output in \" Hexdump \" format " , NULL ) ;
2008-03-26 22:33:56 +00:00
gtk_toggle_button_set_active ( GTK_TOGGLE_BUTTON ( radio_bt ) ,
IS_SHOW_TYPE ( SHOW_HEXDUMP ) ) ;
2007-09-10 23:50:46 +00:00
gtk_box_pack_start ( GTK_BOX ( hbox ) , radio_bt , FALSE , FALSE , 0 ) ;
2008-04-11 22:10:36 +00:00
g_signal_connect ( radio_bt , " toggled " , G_CALLBACK ( follow_charset_toggle_cb ) ,
2007-09-10 23:50:46 +00:00
follow_info ) ;
follow_info - > hexdump_bt = radio_bt ;
/* C Array radio button */
2008-06-29 15:51:43 +00:00
radio_bt = gtk_radio_button_new_with_label ( gtk_radio_button_get_group
2007-09-10 23:50:46 +00:00
( GTK_RADIO_BUTTON ( radio_bt ) ) ,
" C Arrays " ) ;
gtk_tooltips_set_tip ( tooltips , radio_bt , " Stream data output in \" C Array \" format " , NULL ) ;
2008-03-26 22:33:56 +00:00
gtk_toggle_button_set_active ( GTK_TOGGLE_BUTTON ( radio_bt ) ,
IS_SHOW_TYPE ( SHOW_CARRAY ) ) ;
2007-09-10 23:50:46 +00:00
gtk_box_pack_start ( GTK_BOX ( hbox ) , radio_bt , FALSE , FALSE , 0 ) ;
2008-04-11 22:10:36 +00:00
g_signal_connect ( radio_bt , " toggled " , G_CALLBACK ( follow_charset_toggle_cb ) ,
2007-09-10 23:50:46 +00:00
follow_info ) ;
follow_info - > carray_bt = radio_bt ;
/* Raw radio button */
2008-06-29 15:51:43 +00:00
radio_bt = gtk_radio_button_new_with_label ( gtk_radio_button_get_group
2007-09-10 23:50:46 +00:00
( GTK_RADIO_BUTTON ( radio_bt ) ) ,
" Raw " ) ;
gtk_tooltips_set_tip ( tooltips , radio_bt , " Stream data output in \" Raw \" (binary) format. As this contains non printable characters, the screen output will be in ASCII format " , NULL ) ;
2008-03-26 22:33:56 +00:00
gtk_toggle_button_set_active ( GTK_TOGGLE_BUTTON ( radio_bt ) ,
IS_SHOW_TYPE ( SHOW_RAW ) ) ;
2007-09-10 23:50:46 +00:00
gtk_box_pack_start ( GTK_BOX ( hbox ) , radio_bt , FALSE , FALSE , 0 ) ;
2008-04-11 22:10:36 +00:00
g_signal_connect ( radio_bt , " toggled " , G_CALLBACK ( follow_charset_toggle_cb ) ,
2007-09-10 23:50:46 +00:00
follow_info ) ;
follow_info - > raw_bt = radio_bt ;
2008-06-21 13:36:31 +00:00
/* Button row: help, filter out, close button */
bbox = dlg_button_row_new ( WIRESHARK_STOCK_FILTER_OUT_STREAM ,
GTK_STOCK_CLOSE , GTK_STOCK_HELP ,
NULL ) ;
2007-09-10 23:50:46 +00:00
gtk_box_pack_start ( GTK_BOX ( vbox ) , bbox , FALSE , FALSE , 5 ) ;
2008-04-11 16:44:31 +00:00
button = g_object_get_data ( G_OBJECT ( bbox ) , WIRESHARK_STOCK_FILTER_OUT_STREAM ) ;
2007-09-10 23:50:46 +00:00
gtk_tooltips_set_tip ( tooltips , button ,
" Build a display filter which cuts this stream from the capture " , NULL ) ;
2008-04-11 22:10:36 +00:00
g_signal_connect ( button , " clicked " , G_CALLBACK ( follow_filter_out_stream ) ,
2007-09-10 23:50:46 +00:00
follow_info ) ;
2008-04-11 16:44:31 +00:00
button = g_object_get_data ( G_OBJECT ( bbox ) , GTK_STOCK_CLOSE ) ;
2007-09-10 23:50:46 +00:00
window_set_cancel_button ( streamwindow , button , window_cancel_button_cb ) ;
gtk_tooltips_set_tip ( tooltips , button ,
" Close the dialog and keep the current display filter " , NULL ) ;
gtk_widget_grab_default ( button ) ;
2008-06-21 13:36:31 +00:00
button = g_object_get_data ( G_OBJECT ( bbox ) , GTK_STOCK_HELP ) ;
g_signal_connect ( button , " clicked " , G_CALLBACK ( topic_cb ) ,
( gpointer ) HELP_FOLLOW_STREAM_DIALOG ) ;
2007-09-10 23:50:46 +00:00
/* Tuck away the follow_info object into the window */
2008-04-11 16:44:31 +00:00
g_object_set_data ( G_OBJECT ( streamwindow ) , E_FOLLOW_INFO_KEY , follow_info ) ;
2007-09-10 23:50:46 +00:00
follow_load_text ( follow_info ) ;
remember_follow_info ( follow_info ) ;
2008-04-11 22:10:36 +00:00
g_signal_connect ( streamwindow , " delete_event " , G_CALLBACK ( window_delete_event_cb ) , NULL ) ;
g_signal_connect ( streamwindow , " destroy " , G_CALLBACK ( follow_destroy_cb ) , NULL ) ;
2007-09-10 23:50:46 +00:00
/* Make sure this widget gets destroyed if we quit the main loop,
so that if we exit , we clean up any temporary files we have
for " Follow TCP Stream " windows . */
gtk_quit_add_destroy ( gtk_main_level ( ) , GTK_OBJECT ( streamwindow ) ) ;
gtk_widget_show_all ( streamwindow ) ;
window_present ( streamwindow ) ;
}
/* The destroy call back has the responsibility of
* unlinking the temporary file
* and freeing the filter_out_filter */
static void
follow_destroy_cb ( GtkWidget * w , gpointer data _U_ )
{
follow_info_t * follow_info ;
2007-11-03 04:45:35 +00:00
follow_record_t * follow_record ;
2007-09-10 23:50:46 +00:00
GList * cur ;
int i ;
2008-04-11 16:44:31 +00:00
follow_info = g_object_get_data ( G_OBJECT ( w ) , E_FOLLOW_INFO_KEY ) ;
2007-09-10 23:50:46 +00:00
switch ( follow_info - > follow_type ) {
2008-03-26 22:33:56 +00:00
2007-09-10 23:50:46 +00:00
case FOLLOW_TCP :
2008-05-22 15:46:27 +00:00
i = ws_unlink ( follow_info - > data_out_filename ) ;
2007-09-10 23:50:46 +00:00
if ( i ! = 0 ) {
2008-03-26 22:33:56 +00:00
g_warning ( " Follow: Couldn't remove temporary file: \" %s \" , errno: %s (%u) " , follow_info - > data_out_filename , strerror ( errno ) , errno ) ;
2007-09-10 23:50:46 +00:00
}
break ;
2008-03-26 22:33:56 +00:00
2007-11-03 04:45:35 +00:00
case FOLLOW_UDP :
for ( cur = follow_info - > payload ; cur ; cur = g_list_next ( cur ) )
if ( cur - > data ) {
follow_record = cur - > data ;
if ( follow_record - > data )
g_byte_array_free ( follow_record - > data ,
TRUE ) ;
g_free ( follow_record ) ;
}
g_list_free ( follow_info - > payload ) ;
break ;
2007-09-10 23:50:46 +00:00
case FOLLOW_SSL :
/* free decrypted data list*/
2007-11-03 04:45:35 +00:00
for ( cur = follow_info - > payload ; cur ; cur = g_list_next ( cur ) )
2007-09-10 23:50:46 +00:00
if ( cur - > data )
{
g_free ( cur - > data ) ;
cur - > data = NULL ;
}
2007-11-03 04:45:35 +00:00
g_list_free ( follow_info - > payload ) ;
2007-09-10 23:50:46 +00:00
break ;
}
2009-07-01 23:36:51 +00:00
g_free ( follow_info - > data_out_filename ) ;
2007-09-10 23:50:46 +00:00
g_free ( follow_info - > filter_out_filter ) ;
2008-03-22 05:50:19 +00:00
g_free ( ( gpointer ) follow_info - > client_ip . data ) ;
2007-09-10 23:50:46 +00:00
forget_follow_info ( follow_info ) ;
g_free ( follow_info ) ;
}
2007-09-13 22:11:50 +00:00
frs_return_t
2008-03-26 22:33:56 +00:00
follow_show ( follow_info_t * follow_info ,
2010-01-29 16:13:26 +00:00
gboolean ( * print_line_fcn_p ) ( char * , size_t , gboolean , void * ) ,
2007-09-13 22:11:50 +00:00
char * buffer , size_t nchars , gboolean is_server , void * arg ,
2008-03-12 08:50:09 +00:00
guint32 * global_pos , guint32 * server_packet_count ,
guint32 * client_packet_count )
2007-09-13 22:11:50 +00:00
{
gchar initbuf [ 256 ] ;
guint32 current_pos ;
static const gchar hexchars [ 16 ] = " 0123456789abcdef " ;
switch ( follow_info - > show_type ) {
case SHOW_EBCDIC :
/* If our native arch is ASCII, call: */
2009-04-16 00:45:26 +00:00
EBCDIC_to_ASCII ( buffer , ( guint ) nchars ) ;
2010-01-29 16:13:26 +00:00
if ( ! ( * print_line_fcn_p ) ( buffer , nchars , is_server , arg ) )
2007-09-13 22:11:50 +00:00
return FRS_PRINT_ERROR ;
break ;
case SHOW_ASCII :
/* If our native arch is EBCDIC, call:
* ASCII_TO_EBCDIC ( buffer , nchars ) ;
*/
2010-01-29 16:13:26 +00:00
if ( ! ( * print_line_fcn_p ) ( buffer , nchars , is_server , arg ) )
2007-09-13 22:11:50 +00:00
return FRS_PRINT_ERROR ;
break ;
2008-03-26 22:33:56 +00:00
2007-09-13 22:11:50 +00:00
case SHOW_RAW :
/* Don't translate, no matter what the native arch
* is .
*/
2010-01-29 16:13:26 +00:00
if ( ! ( * print_line_fcn_p ) ( buffer , nchars , is_server , arg ) )
2007-09-13 22:11:50 +00:00
return FRS_PRINT_ERROR ;
break ;
2008-03-26 22:33:56 +00:00
2007-09-13 22:11:50 +00:00
case SHOW_HEXDUMP :
current_pos = 0 ;
while ( current_pos < nchars ) {
gchar hexbuf [ 256 ] ;
int i ;
gchar * cur = hexbuf , * ascii_start ;
2008-03-26 22:33:56 +00:00
2009-05-17 19:34:30 +00:00
/* is_server indentation : put 4 spaces at the
2007-09-13 22:11:50 +00:00
* beginning of the string */
2009-05-17 19:34:30 +00:00
/* XXX - We might want to prepend each line with "C" or "S" instead. */
2007-09-13 22:11:50 +00:00
if ( is_server & & follow_info - > show_stream = = BOTH_HOSTS ) {
2009-05-17 19:34:30 +00:00
memset ( cur , ' ' , 4 ) ;
cur + = 4 ;
2007-09-13 22:11:50 +00:00
}
cur + = g_snprintf ( cur , 20 , " %08X " , * global_pos ) ;
/* 49 is space consumed by hex chars */
ascii_start = cur + 49 ;
for ( i = 0 ; i < 16 & & current_pos + i < nchars ; i + + ) {
* cur + + =
hexchars [ ( buffer [ current_pos + i ] & 0xf0 ) > > 4 ] ;
* cur + + =
hexchars [ buffer [ current_pos + i ] & 0x0f ] ;
* cur + + = ' ' ;
if ( i = = 7 )
* cur + + = ' ' ;
}
/* Fill it up if column isn't complete */
2008-03-26 22:33:56 +00:00
while ( cur < ascii_start )
2007-09-13 22:11:50 +00:00
* cur + + = ' ' ;
2008-03-26 22:33:56 +00:00
2007-09-13 22:11:50 +00:00
/* Now dump bytes as text */
for ( i = 0 ; i < 16 & & current_pos + i < nchars ; i + + ) {
* cur + + =
( isprint ( ( guchar ) buffer [ current_pos + i ] ) ?
buffer [ current_pos + i ] : ' . ' ) ;
if ( i = = 7 ) {
* cur + + = ' ' ;
}
}
current_pos + = i ;
( * global_pos ) + = i ;
* cur + + = ' \n ' ;
* cur = 0 ;
2010-01-29 16:13:26 +00:00
if ( ! ( * print_line_fcn_p ) ( hexbuf , strlen ( hexbuf ) , is_server , arg ) )
2007-09-13 22:11:50 +00:00
return FRS_PRINT_ERROR ;
}
break ;
2008-03-26 22:33:56 +00:00
2007-09-13 22:11:50 +00:00
case SHOW_CARRAY :
current_pos = 0 ;
2008-03-26 22:33:56 +00:00
g_snprintf ( initbuf , sizeof ( initbuf ) , " char peer%d_%d[] = { \n " ,
is_server ? 1 : 0 ,
2008-03-12 08:50:09 +00:00
is_server ? ( * server_packet_count ) + + : ( * client_packet_count ) + + ) ;
2010-01-29 16:13:26 +00:00
if ( ! ( * print_line_fcn_p ) ( initbuf , strlen ( initbuf ) , is_server , arg ) )
2007-09-13 22:11:50 +00:00
return FRS_PRINT_ERROR ;
while ( current_pos < nchars ) {
gchar hexbuf [ 256 ] ;
int i , cur ;
2008-03-26 22:33:56 +00:00
2007-09-13 22:11:50 +00:00
cur = 0 ;
for ( i = 0 ; i < 8 & & current_pos + i < nchars ; i + + ) {
/* Prepend entries with "0x" */
hexbuf [ cur + + ] = ' 0 ' ;
hexbuf [ cur + + ] = ' x ' ;
hexbuf [ cur + + ] =
hexchars [ ( buffer [ current_pos + i ] & 0xf0 ) > > 4 ] ;
hexbuf [ cur + + ] =
hexchars [ buffer [ current_pos + i ] & 0x0f ] ;
2008-03-26 22:33:56 +00:00
2007-09-13 22:11:50 +00:00
/* Delimit array entries with a comma */
if ( current_pos + i + 1 < nchars )
hexbuf [ cur + + ] = ' , ' ;
2008-03-26 22:33:56 +00:00
2007-09-13 22:11:50 +00:00
hexbuf [ cur + + ] = ' ' ;
}
2008-03-26 22:33:56 +00:00
2007-09-13 22:11:50 +00:00
/* Terminate the array if we are at the end */
if ( current_pos + i = = nchars ) {
hexbuf [ cur + + ] = ' } ' ;
hexbuf [ cur + + ] = ' ; ' ;
}
2008-03-26 22:33:56 +00:00
2007-09-13 22:11:50 +00:00
current_pos + = i ;
( * global_pos ) + = i ;
hexbuf [ cur + + ] = ' \n ' ;
hexbuf [ cur ] = 0 ;
2010-01-29 16:13:26 +00:00
if ( ! ( * print_line_fcn_p ) ( hexbuf , strlen ( hexbuf ) , is_server , arg ) )
2007-09-13 22:11:50 +00:00
return FRS_PRINT_ERROR ;
}
break ;
}
return FRS_OK ;
}