Add text import capability, like text2pcap, directly into the GUI.
[obnox/wireshark/wip.git] / gtk / follow_tcp.c
index 18a708840575fd7e042eca2ed4fec1d08e787c77..f20b02dd8c08e323401d6dbfbd15c655a6f83866 100644 (file)
 # include "config.h"
 #endif
 
-#include <gtk/gtk.h>
-
 #include <stdio.h>
 #include <string.h>
 
-
 #ifdef HAVE_UNISTD_H
 #include <unistd.h>
 #endif
 
 #include <ctype.h>
 
-#include "isprint.h"
+#include <gtk/gtk.h>
 
-#include "file_util.h"
-#include "color.h"
-#include "colors.h"
-#include "file.h"
-#include "follow_tcp.h"
 #include <epan/follow.h>
-#include "dlg_utils.h"
-#include "file_dlg.h"
-#include "keys.h"
-#include "globals.h"
-#include "main.h"
-#include "alert_box.h"
-#include "simple_dialog.h"
 #include <epan/dissectors/packet-ipv6.h>
 #include <epan/prefs.h>
 #include <epan/addr_resolv.h>
 #include <epan/charsets.h>
-#include "tempfile.h"
-#include "gui_utils.h"
 #include <epan/epan_dissect.h>
 #include <epan/filesystem.h>
-#include "compat_macros.h"
 #include <epan/ipproto.h>
-#include "print_mswin.h"
-#include "font_utils.h"
-#include "help_dlg.h"
 #include <epan/charsets.h>
 
-#include "follow_stream.h"
-
-/* This is backwards-compatibility code for old versions of GTK+ (2.2.1 and
- * earlier).  It defines the new wrap behavior (unknown in earlier versions)
- * as the old (slightly buggy) wrap behavior.
- */
-#ifndef GTK_WRAP_WORD_CHAR
-#define GTK_WRAP_WORD_CHAR GTK_WRAP_WORD
-#endif
+#include "../isprint.h"
+#include "../color.h"
+#include "../file.h"
+#include "../alert_box.h"
+#include "../simple_dialog.h"
+#include "../tempfile.h"
+#include <wsutil/file_util.h>
+
+#include "gtkglobals.h"
+#include "gtk/color_utils.h"
+#include "gtk/follow_tcp.h"
+#include "gtk/dlg_utils.h"
+#include "gtk/file_dlg.h"
+#include "gtk/keys.h"
+#include "gtk/main.h"
+#include "gtk/gui_utils.h"
+#include "gtk/print_win32.h"
+#include "gtk/font_utils.h"
+#include "gtk/help_dlg.h"
+#include "gtk/follow_stream.h"
+#include "gtk/utf8_entities.h"
 
 /* With MSVC and a libwireshark.dll, we need a special declaration. */
 WS_VAR_IMPORT FILE *data_out_file;
@@ -99,8 +90,9 @@ follow_tcp_redraw_all(void)
    a dissection routine on belongs (this might be the most recently
    selected packet, or it might be the last packet in the file). */
 void
-follow_tcp_stream_cb(GtkWidget * w, gpointer data _U_)
+follow_tcp_stream_cb(GtkWidget * w _U_, gpointer data _U_)
 {
+       GtkWidget *filter_cm;
        GtkWidget       *filter_te;
        int             tmp_fd;
        gchar           *follow_filter;
@@ -115,6 +107,7 @@ follow_tcp_stream_cb(GtkWidget * w, gpointer data _U_)
        follow_info_t   *follow_info;
        tcp_stream_chunk sc;
        size_t              nchars;
+       gchar           *data_out_filename;
 
        /* we got tcp so we can follow */
        if (cfile.edt->pi.ipproto != IP_PROTO_TCP) {
@@ -127,6 +120,18 @@ follow_tcp_stream_cb(GtkWidget * w, gpointer data _U_)
        follow_info = g_new0(follow_info_t, 1);
        follow_info->follow_type = FOLLOW_TCP;
 
+       /* Create a new filter that matches all packets in the TCP stream,
+          and set the display filter entry accordingly */
+       reset_tcp_reassembly();
+       follow_filter = build_follow_filter(&cfile.edt->pi);
+       if (!follow_filter) {
+               simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
+                             "Error creating filter for this stream.\n"
+                             "A transport or network layer header is needed");
+               g_free(follow_info);
+               return;
+       }
+
        /* Create a temporary file into which to dump the reassembled data
           from the TCP stream, and set "data_out_file" to refer to it, so
           that the TCP code will write to it.
@@ -135,14 +140,16 @@ follow_tcp_stream_cb(GtkWidget * w, gpointer data _U_)
           append stuff to the text widget for the TCP stream window,
           if we can arrange that said window not pop up until we're
           done. */
-       tmp_fd = create_tempfile(follow_info->data_out_filename,
-                       sizeof follow_info->data_out_filename, "follow");
+       tmp_fd = create_tempfile(&data_out_filename, "follow");
+       follow_info->data_out_filename = g_strdup(data_out_filename);
 
        if (tmp_fd == -1) {
            simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
                          "Could not create temporary file %s: %s",
                          follow_info->data_out_filename, strerror(errno));
+           g_free(follow_info->data_out_filename);
            g_free(follow_info);
+           g_free(follow_filter);
            return;
        }
 
@@ -151,19 +158,17 @@ follow_tcp_stream_cb(GtkWidget * w, gpointer data _U_)
            simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
                          "Could not create temporary file %s: %s",
                          follow_info->data_out_filename, strerror(errno));
-           eth_close(tmp_fd);
-           eth_unlink(follow_info->data_out_filename);
+           ws_close(tmp_fd);
+           ws_unlink(follow_info->data_out_filename);
+           g_free(follow_info->data_out_filename);
            g_free(follow_info);
+           g_free(follow_filter);
            return;
        }
 
-       /* Create a new filter that matches all packets in the TCP stream,
-          and set the display filter entry accordingly */
-       reset_tcp_reassembly();
-       follow_filter = build_follow_filter(&cfile.edt->pi);
-
        /* Set the display filter entry accordingly */
-       filter_te = OBJECT_GET_DATA(w, E_DFILTER_TE_KEY);
+       filter_cm = g_object_get_data(G_OBJECT(top_level), E_DFILTER_CM_KEY);
+       filter_te = gtk_bin_get_child(GTK_BIN(filter_cm));
 
        /* needed in follow_filter_out_stream(), is there a better way? */
        follow_info->filter_te = filter_te;
@@ -174,7 +179,7 @@ follow_tcp_stream_cb(GtkWidget * w, gpointer data _U_)
 
        /* allocate our new filter. API claims g_malloc terminates program on failure */
        /* my calc for max alloc needed is really +10 but when did a few extra bytes hurt ? */
-       filter_out_filter_len = strlen(follow_filter) + strlen(previous_filter) + 16;
+       filter_out_filter_len = (int)(strlen(follow_filter) + strlen(previous_filter) + 16);
        follow_info->filter_out_filter = (gchar *)g_malloc(filter_out_filter_len);
 
        /* append the negation */
@@ -199,8 +204,10 @@ follow_tcp_stream_cb(GtkWidget * w, gpointer data _U_)
        if (empty_tcp_stream) {
            simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
                          "The packets in the capture file for that stream have no data.");
-           eth_close(tmp_fd);
-           eth_unlink(follow_info->data_out_filename);
+           ws_close(tmp_fd);
+           ws_unlink(follow_info->data_out_filename);
+           g_free(follow_info->data_out_filename);
+           g_free(follow_info->filter_out_filter);
            g_free(follow_info);
            return;
        }
@@ -229,8 +236,10 @@ follow_tcp_stream_cb(GtkWidget * w, gpointer data _U_)
                              (unsigned long)sizeof(sc),
                              (unsigned long)nchars);
            }
-           eth_close(tmp_fd);
-           eth_unlink(follow_info->data_out_filename);
+           ws_close(tmp_fd);
+           ws_unlink(follow_info->data_out_filename);
+           g_free(follow_info->data_out_filename);
+           g_free(follow_info->filter_out_filter);
            g_free(follow_info);
            return;
        }
@@ -262,33 +271,32 @@ follow_tcp_stream_cb(GtkWidget * w, gpointer data _U_)
        port1 = get_tcp_port(stats.port[1]);
 
        /* Host 0 --> Host 1 */
-       if(sc.src_port == strtol(port0, NULL, 10)) {
+       if(sc.src_port == stats.port[0]) {
                server_to_client_string =
-                       g_strdup_printf("%s:%s --> %s:%s (%u bytes)",
+                       g_strdup_printf("%s:%s " UTF8_RIGHTWARDS_ARROW " %s:%s (%u bytes)",
                                        hostname0, port0,
                                        hostname1, port1,
                                        stats.bytes_written[0]);
        } else {
                server_to_client_string =
-                       g_strdup_printf("%s:%s --> %s:%s (%u bytes)",
+                       g_strdup_printf("%s:%s " UTF8_RIGHTWARDS_ARROW " %s:%s (%u bytes)",
                                        hostname1, port1,
                                        hostname0,port0,
                                        stats.bytes_written[0]);
        }
 
        /* Host 1 --> Host 0 */
-       if(sc.src_port == strtol(port0, NULL, 10)) {
+       if(sc.src_port == stats.port[1]) {
                client_to_server_string =
-                       g_strdup_printf("%s:%s --> %s:%s (%u bytes)",
-                                       hostname1, port1,
+                       g_strdup_printf("%s:%s " UTF8_RIGHTWARDS_ARROW " %s:%s (%u bytes)",
                                        hostname0, port0,
+                                       hostname1, port1,
                                        stats.bytes_written[1]);
-
        } else {
                client_to_server_string =
-                       g_strdup_printf("%s:%s --> %s:%s (%u bytes)",
-                                       hostname0, port0,
+                       g_strdup_printf("%s:%s " UTF8_RIGHTWARDS_ARROW " %s:%s (%u bytes)",
                                        hostname1, port1,
+                                       hostname0, port0,
                                        stats.bytes_written[1]);
        }
 
@@ -308,7 +316,7 @@ follow_tcp_stream_cb(GtkWidget * w, gpointer data _U_)
 #define FLT_BUF_SIZE 1024
 
 /*
- * XXX - the routine pointed to by "print_line" doesn't get handed lines,
+ * XXX - the routine pointed to by "print_line_fcn_p" doesn't get handed lines,
  * it gets handed bufferfuls.  That's fine for "follow_write_raw()"
  * and "follow_add_to_gtk_text()", but, as "follow_print_text()" calls
  * the "print_line()" routine from "print.c", and as that routine might
@@ -326,7 +334,7 @@ follow_tcp_stream_cb(GtkWidget * w, gpointer data _U_)
  */
 frs_return_t
 follow_read_tcp_stream(follow_info_t *follow_info,
-                      gboolean (*print_line)(char *, size_t, gboolean, void *),
+                      gboolean (*print_line_fcn_p)(char *, size_t, gboolean, void *),
                       void *arg)
 {
     tcp_stream_chunk   sc;
@@ -335,6 +343,8 @@ follow_read_tcp_stream(follow_info_t *follow_info,
     guint16            client_port = 0;
     gboolean           is_server;
     guint32            global_client_pos = 0, global_server_pos = 0;
+    guint32            server_packet_count = 0;
+    guint32            client_packet_count = 0;
     guint32            *global_pos;
     gboolean           skip;
     char                buffer[FLT_BUF_SIZE+1]; /* +1 to fix ws bug 1043 */
@@ -343,7 +353,7 @@ follow_read_tcp_stream(follow_info_t *follow_info,
 
     iplen = (follow_info->is_ipv6) ? 16 : 4;
 
-    data_out_file = eth_fopen(follow_info->data_out_filename, "rb");
+    data_out_file = ws_fopen(follow_info->data_out_filename, "rb");
     if (data_out_file == NULL) {
        simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
                      "Could not open temporary file %s: %s", follow_info->data_out_filename,
@@ -389,17 +399,18 @@ follow_read_tcp_stream(follow_info_t *follow_info,
            if (nchars == 0)
                break;
            /* XXX - if we don't get "bcount" bytes, is that an error? */
-           sc.dlen -= nchars;
+           sc.dlen -= (guint32) nchars;
 
            if (!skip) {
-                   frs_return = follow_show(follow_info, print_line, buffer,
-                                            nchars, is_server, arg,
-                                            global_pos);
+                   frs_return = follow_show(follow_info, print_line_fcn_p, buffer,
+                                            nchars, is_server, arg, global_pos,
+                                            &server_packet_count,
+                                            &client_packet_count);
                    if(frs_return == FRS_PRINT_ERROR) {
                            fclose(data_out_file);
                            data_out_file = NULL;
                            return frs_return;
-               
+
                    }
            }
        }