diff options
-rw-r--r-- | epan/follow.c | 26 | ||||
-rw-r--r-- | epan/follow.h | 33 | ||||
-rw-r--r-- | ui/gtk/follow_ssl.c | 2 | ||||
-rw-r--r-- | ui/gtk/follow_tcp.c | 2 | ||||
-rw-r--r-- | ui/gtk/follow_udp.c | 2 | ||||
-rw-r--r-- | ui/qt/follow_stream_dialog.cpp | 501 | ||||
-rw-r--r-- | ui/qt/follow_stream_dialog.h | 85 | ||||
-rw-r--r-- | ui/qt/follow_stream_dialog.ui | 31 | ||||
-rw-r--r-- | ui/qt/main_window.cpp | 1 | ||||
-rw-r--r-- | ui/qt/main_window.h | 3 | ||||
-rw-r--r-- | ui/qt/main_window_slots.cpp | 53 | ||||
-rw-r--r-- | ui/qt/sequence_dialog.cpp | 13 | ||||
-rw-r--r-- | wsutil/tempfile.h | 4 |
13 files changed, 428 insertions, 328 deletions
diff --git a/epan/follow.c b/epan/follow.c index 4e26a5bad7..ed930c12b4 100644 --- a/epan/follow.c +++ b/epan/follow.c @@ -58,7 +58,7 @@ FILE* data_out_file = NULL; gboolean empty_tcp_stream; gboolean incomplete_tcp_stream; -static guint32 tcp_stream_to_follow; +static guint32 tcp_stream_to_follow = 0; static guint8 ip_address[2][MAX_IPADDR_LEN]; static guint port[2]; static guint bytes_written[2]; @@ -80,12 +80,12 @@ follow_stats(follow_stats_t* stats) } } -/* this will build libpcap filter text that will only +/* This will build a display filter text that will only pass the packets related to the stream. There is a chance that two streams could intersect, but not a very good one */ -char* -build_follow_filter( packet_info *pi ) { +gchar* +build_follow_conv_filter( packet_info *pi ) { char* buf; int len; conversation_t *conv=NULL; @@ -148,6 +148,15 @@ static gboolean find_tcp_addr; static address tcp_addr[2]; static gboolean find_tcp_index; +gchar* +build_follow_index_filter(void) { + gchar *buf; + + find_tcp_addr = TRUE; + buf = g_strdup_printf("tcp.stream eq %d", tcp_stream_to_follow); + return buf; +} + /* select a tcp stream to follow via it's address/port pairs */ gboolean follow_tcp_addr(const address *addr0, guint port0, @@ -192,6 +201,10 @@ follow_tcp_index(guint32 indx) return FALSE; } + if (indx > get_tcp_stream_count()) { + return FALSE; + } + find_tcp_addr = TRUE; tcp_stream_to_follow = indx; memset(ip_address, 0, sizeof ip_address); @@ -200,6 +213,11 @@ follow_tcp_index(guint32 indx) return TRUE; } +guint32 +get_follow_tcp_index(void) { + return tcp_stream_to_follow; +} + /* here we are going to try and reconstruct the data portion of a TCP session. We will try and handle duplicates, TCP fragments, and out of order packets in a smart way. */ diff --git a/epan/follow.h b/epan/follow.h index cd92221aa5..b1e02dbcad 100644 --- a/epan/follow.h +++ b/epan/follow.h @@ -46,12 +46,43 @@ typedef struct _tcp_stream_chunk { guint32 dlen; } tcp_stream_chunk; +/** Build a follow filter based on the current packet's conversation. + * + * @param packet_info[in] The current packet. + * @return A filter that specifies the conversation. Must be g_free()d + * the caller. + */ +WS_DLL_PUBLIC +gchar* build_follow_conv_filter( packet_info * ); + +/** Build a follow filter based on the current TCP stream index. + * follow_tcp_index() must be called prior to calling this. + * + * @return A filter that specifies the current stream. Must be g_free()d + * the caller. + */ WS_DLL_PUBLIC -char* build_follow_filter( packet_info * ); +gchar* build_follow_index_filter(void); + WS_DLL_PUBLIC gboolean follow_tcp_addr( const address *, guint, const address *, guint ); + +/** Select a TCP stream to follow via its index. + * + * @param addr[in] The stream index to follow. + * @return TRUE on success, FALSE on failure. + */ WS_DLL_PUBLIC gboolean follow_tcp_index( guint32 ); + +/** Get the current TCP index being followed. + * + * @return The current TCP index. The behavior is undefined + * if no TCP stream is being followed. + */ +WS_DLL_PUBLIC +guint32 get_follow_tcp_index(void); + void reassemble_tcp( guint32, guint32, guint32, guint32, const char*, guint32, int, address *, address *, guint, guint ); WS_DLL_PUBLIC diff --git a/ui/gtk/follow_ssl.c b/ui/gtk/follow_ssl.c index 8ef803bc70..7e826e9211 100644 --- a/ui/gtk/follow_ssl.c +++ b/ui/gtk/follow_ssl.c @@ -167,7 +167,7 @@ follow_ssl_stream_cb(GtkWidget * w _U_, gpointer data _U_) /* Create a new filter that matches all packets in the SSL stream, and set the display filter entry accordingly */ reset_tcp_reassembly(); - follow_filter = build_follow_filter(&cfile.edt->pi); + follow_filter = build_follow_conv_filter(&cfile.edt->pi); if (!follow_filter) { simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, diff --git a/ui/gtk/follow_tcp.c b/ui/gtk/follow_tcp.c index 14651d68d9..9325309994 100644 --- a/ui/gtk/follow_tcp.c +++ b/ui/gtk/follow_tcp.c @@ -121,7 +121,7 @@ follow_tcp_stream_cb(GtkWidget * w _U_, gpointer data _U_) /* 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); + follow_filter = build_follow_conv_filter(&cfile.edt->pi); if (!follow_filter) { simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Error creating filter for this stream.\n" diff --git a/ui/gtk/follow_udp.c b/ui/gtk/follow_udp.c index 93a5106b7e..3980d3c9c2 100644 --- a/ui/gtk/follow_udp.c +++ b/ui/gtk/follow_udp.c @@ -109,7 +109,7 @@ follow_udp_stream_cb(GtkWidget *w _U_, gpointer data _U_) /* Create a new filter that matches all packets in the UDP stream, and set the display filter entry accordingly */ - follow_filter = build_follow_filter(&cfile.edt->pi); + follow_filter = build_follow_conv_filter(&cfile.edt->pi); if (!follow_filter) { simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, diff --git a/ui/qt/follow_stream_dialog.cpp b/ui/qt/follow_stream_dialog.cpp index 4407c0b266..a06dd63b70 100644 --- a/ui/qt/follow_stream_dialog.cpp +++ b/ui/qt/follow_stream_dialog.cpp @@ -29,25 +29,27 @@ #include "epan/follow.h" #include "epan/dissectors/packet-ipv6.h" +#include "epan/dissectors/packet-tcp.h" #include "epan/prefs.h" #include "epan/charsets.h" #include "epan/epan_dissect.h" #include "epan/ipproto.h" #include "epan/tap.h" -#include "file.h" #include "ui/alert_box.h" #include "ui/simple_dialog.h" #include "ui/utf8_entities.h" + #include "wsutil/tempfile.h" #include "wsutil/file_util.h" +#include "wsutil/str_util.h" + #include "ws_symbol_export.h" #include "color_utils.h" #include "qt_ui_utils.h" #include "wireshark_application.h" -#include "globals.h" #include "file.h" #include "version_info.h" @@ -65,30 +67,40 @@ #include <QTextEdit> #include <QTextStream> -FollowStreamDialog::FollowStreamDialog(QWidget *parent) : +FollowStreamDialog::FollowStreamDialog(QWidget *parent, follow_type_t type, capture_file *cf) : QDialog(parent), - ui(new Ui::FollowStreamDialog) + ui(new Ui::FollowStreamDialog), + cap_file_(cf), + follow_type_(type), + save_as_(false) { - follow_info = NULL; ui->setupUi(this); + setAttribute(Qt::WA_DeleteOnClose, true); + memset(&follow_info_, 0, sizeof(follow_info_)); + ui->teStreamContent->installEventFilter(this); - connect(ui->buttonBox, SIGNAL(helpRequested()), this, SLOT(HelpButton())); + connect(ui->buttonBox, SIGNAL(helpRequested()), this, SLOT(helpButton())); - bFilterOut = ui->buttonBox->addButton(tr("Hide this stream"), QDialogButtonBox::ActionRole); - connect(bFilterOut, SIGNAL(clicked()), this, SLOT(FilterOut())); + b_filter_out_ = ui->buttonBox->addButton(tr("Hide this stream"), QDialogButtonBox::ActionRole); + connect(b_filter_out_, SIGNAL(clicked()), this, SLOT(filterOut())); - bPrint = ui->buttonBox->addButton(tr("Print"), QDialogButtonBox::ActionRole); - connect(bPrint, SIGNAL(clicked()), this, SLOT(Print())); + b_print_ = ui->buttonBox->addButton(tr("Print"), QDialogButtonBox::ActionRole); + connect(b_print_, SIGNAL(clicked()), this, SLOT(printStream())); - bSave = ui->buttonBox->addButton(tr("Save as..."), QDialogButtonBox::ActionRole); - connect(bSave, SIGNAL(clicked()), this, SLOT(SaveAs())); + b_save_ = ui->buttonBox->addButton(tr("Save as..."), QDialogButtonBox::ActionRole); + connect(b_save_, SIGNAL(clicked()), this, SLOT(saveAs())); - save_as = false; } -void FollowStreamDialog::Print() +FollowStreamDialog::~FollowStreamDialog() +{ + delete ui; + resetStream(); // Frees payload +} + +void FollowStreamDialog::printStream() { #ifndef QT_NO_PRINTER QPrinter printer(QPrinter::HighResolution); @@ -98,7 +110,7 @@ void FollowStreamDialog::Print() #endif } -void FollowStreamDialog::FindText(bool go_back) +void FollowStreamDialog::findText(bool go_back) { if (ui->leFind->text().isEmpty()) return; @@ -108,60 +120,56 @@ void FollowStreamDialog::FindText(bool go_back) ui->teStreamContent->setFocus(); } else if (go_back) { ui->teStreamContent->moveCursor(QTextCursor::Start); - FindText(false); + findText(false); } } -void FollowStreamDialog::SaveAs() +void FollowStreamDialog::saveAs() { QString file_name = QFileDialog::getSaveFileName(this, "Wireshark: Save stream content as"); - file.setFileName(file_name); - file.open( QIODevice::WriteOnly ); - QTextStream out(&file); + file_.setFileName(file_name); + file_.open( QIODevice::WriteOnly ); + QTextStream out(&file_); - save_as = true; + save_as_ = true; follow_read_stream(); - if (follow_info->show_type != SHOW_RAW) + if (follow_info_.show_type != SHOW_RAW) { out << ui->teStreamContent->toPlainText(); } - save_as = false; + save_as_ = false; - file.close(); + file_.close(); } -void FollowStreamDialog::HelpButton() +void FollowStreamDialog::helpButton() { wsApp->helpTopicAction(HELP_FOLLOW_STREAM_DIALOG); } -void FollowStreamDialog::FilterOut() +void FollowStreamDialog::filterOut() { - QString filter = QString(follow_info->filter_out_filter); - emit updateFilter(filter, TRUE); + emit updateFilter(filter_out_filter_, TRUE); this->close(); } void FollowStreamDialog::on_cbDirections_currentIndexChanged(int index) { - if (!follow_info) - return; - switch(index) { case 0 : - follow_info->show_stream = BOTH_HOSTS; + follow_info_.show_stream = BOTH_HOSTS; break; case 1 : - follow_info->show_stream = FROM_SERVER; + follow_info_.show_stream = FROM_SERVER; break; case 2 : - follow_info->show_stream = FROM_CLIENT; + follow_info_.show_stream = FROM_CLIENT; break; default: return; @@ -175,23 +183,23 @@ void FollowStreamDialog::on_cbCharset_currentIndexChanged(int index) switch (index) { case 0: - follow_info->show_type = SHOW_ASCII; + follow_info_.show_type = SHOW_ASCII; break; case 1: - follow_info->show_type = SHOW_EBCDIC; + follow_info_.show_type = SHOW_EBCDIC; break; case 2: - follow_info->show_type = SHOW_CARRAY; + follow_info_.show_type = SHOW_CARRAY; break; case 3: - follow_info->show_type = SHOW_HEXDUMP; + follow_info_.show_type = SHOW_HEXDUMP; break; case 4: - follow_info->show_type = SHOW_RAW; + follow_info_.show_type = SHOW_RAW; break; default: @@ -203,17 +211,46 @@ void FollowStreamDialog::on_cbCharset_currentIndexChanged(int index) void FollowStreamDialog::on_bFind_clicked() { - FindText(); + findText(); } void FollowStreamDialog::on_leFind_returnPressed() { - FindText(); + findText(); +} + +void FollowStreamDialog::on_streamNumberSpinBox_valueChanged(int stream_num) +{ + if (stream_num >= 0) { + follow_tcp_index(stream_num); + follow(QString(), true); + } } +// Not sure why we have to do this manually. void FollowStreamDialog::on_buttonBox_rejected() { - hide(); + reject(); +} + +void FollowStreamDialog::removeStreamControls() +{ + ui->horizontalLayout->removeItem(ui->streamNumberSpacer); + ui->streamNumberLabel->setVisible(false); + ui->streamNumberSpinBox->setVisible(false); +} + +void FollowStreamDialog::resetStream() +{ + GList *cur; + + filter_out_filter_.clear(); + if (!data_out_filename_.isEmpty()) ws_unlink(data_out_filename_.toUtf8().constData()); + for (cur = follow_info_.payload; cur; cur = g_list_next(cur)) { + g_free(cur->data); + } + g_list_free(follow_info_.payload); + follow_info_.payload = NULL; } frs_return_t @@ -221,7 +258,7 @@ FollowStreamDialog::follow_read_stream() { ui->teStreamContent->clear(); - switch(follow_info->follow_type) { + switch(follow_type_) { case FOLLOW_TCP : return follow_read_tcp_stream(); @@ -243,7 +280,7 @@ static int udp_queue_packet_data(void *tapdata, packet_info *pinfo, epan_dissect_t *edt, const void *data) { - Q_UNUSED(edt) + Q_UNUSED(edt); follow_record_t *follow_record; follow_info_t *follow_info = (follow_info_t *)tapdata; @@ -277,7 +314,7 @@ udp_queue_packet_data(void *tapdata, packet_info *pinfo, static int ssl_queue_packet_data(void *tapdata, packet_info *pinfo, epan_dissect_t *edt, const void *ssl) { - Q_UNUSED(edt) + Q_UNUSED(edt); follow_info_t * follow_info = (follow_info_t*) tapdata; SslDecryptedRecord * rec = NULL; @@ -363,18 +400,18 @@ FollowStreamDialog::follow_read_ssl_stream() GList * cur; frs_return_t frs_return; - for (cur = follow_info->payload; cur; cur = g_list_next(cur)) { + for (cur = follow_info_.payload; cur; cur = g_list_next(cur)) { SslDecryptedRecord * rec = (SslDecryptedRecord*) cur->data; gboolean include_rec = FALSE; if (rec->is_from_server) { global_pos = &global_server_pos; - include_rec = (follow_info->show_stream == BOTH_HOSTS) || - (follow_info->show_stream == FROM_SERVER); + include_rec = (follow_info_.show_stream == BOTH_HOSTS) || + (follow_info_.show_stream == FROM_SERVER); } else { global_pos = &global_client_pos; - include_rec = (follow_info->show_stream == BOTH_HOSTS) || - (follow_info->show_stream == FROM_CLIENT); + include_rec = (follow_info_.show_stream == BOTH_HOSTS) || + (follow_info_.show_stream == FROM_CLIENT); } if (include_rec) { @@ -398,13 +435,13 @@ FollowStreamDialog::follow_stream() { follow_stats_t stats; - follow_info->show_type = SHOW_RAW; - follow_info->show_stream = BOTH_HOSTS; + follow_info_.show_type = SHOW_RAW; + follow_info_.show_stream = BOTH_HOSTS; /* Stream to show */ follow_stats(&stats); - follow_info->is_ipv6 = stats.is_ipv6; + follow_info_.is_ipv6 = stats.is_ipv6; follow_read_stream(); ui->teStreamContent->moveCursor(QTextCursor::Start); @@ -419,11 +456,11 @@ void FollowStreamDialog::add_text(char *buffer, size_t nchars, gboolean is_from_ QString buf; gchar *str; - if (save_as == true) + if (save_as_ == true) { //FILE *fh = (FILE *)arg; size_t nwritten; - int FileDescriptor = file.handle(); + int FileDescriptor = file_.handle(); FILE* fh = fdopen(dup(FileDescriptor), "wb"); nwritten = fwrite(buffer, 1, nchars, fh); fclose(fh); @@ -469,6 +506,14 @@ void FollowStreamDialog::add_text(char *buffer, size_t nchars, gboolean is_from_ } } +void FollowStreamDialog::setCaptureFile(capture_file *cf) +{ + if (!cf) { // We only want to know when the file closes. + cap_file_ = NULL; + ui->streamNumberSpinBox->setEnabled(false); + } +} + // The following keyboard shortcuts should work (although // they may not work consistently depending on focus): // / (slash), Ctrl-F - Focus and highlight the search box @@ -476,14 +521,14 @@ void FollowStreamDialog::add_text(char *buffer, size_t nchars, gboolean is_from_ // Should we make it so that typing any text starts searching? bool FollowStreamDialog::eventFilter(QObject *obj, QEvent *event) { - Q_UNUSED(obj) + Q_UNUSED(obj); if (ui->teStreamContent->hasFocus() && event->type() == QEvent::KeyPress) { ui->leFind->setFocus(); QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event); if (keyEvent->matches(QKeySequence::Find)) { return true; } else if (keyEvent->matches(QKeySequence::FindNext)) { - FindText(); + findText(); return true; } } @@ -495,7 +540,7 @@ void FollowStreamDialog::keyPressEvent(QKeyEvent *event) { if (ui->leFind->hasFocus()) { if (event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return) { - FindText(); + findText(); return; } } else { @@ -507,20 +552,13 @@ void FollowStreamDialog::keyPressEvent(QKeyEvent *event) } if (event->key() == Qt::Key_F3 || (event->key() == Qt::Key_N && event->modifiers() & Qt::ControlModifier)) { - FindText(); + findText(); return; } QDialog::keyPressEvent(event); } -void FollowStreamDialog::closeEvent(QCloseEvent *event) -{ - Q_UNUSED(event) - hide(); -} - - frs_return_t FollowStreamDialog::follow_show(char *buffer, size_t nchars, gboolean is_from_server, guint32 *global_pos, guint32 *server_packet_count, @@ -530,7 +568,7 @@ FollowStreamDialog::follow_show(char *buffer, size_t nchars, gboolean is_from_se guint32 current_pos; static const gchar hexchars[16] = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'}; - switch (follow_info->show_type) { + switch (follow_info_.show_type) { case SHOW_EBCDIC: /* If our native arch is ASCII, call: */ @@ -562,7 +600,7 @@ FollowStreamDialog::follow_show(char *buffer, size_t nchars, gboolean is_from_se /* is_from_server indentation : put 4 spaces at the * beginning of the string */ /* XXX - We might want to prepend each line with "C" or "S" instead. */ - if (is_from_server && follow_info->show_stream == BOTH_HOSTS) { + if (is_from_server && follow_info_.show_stream == BOTH_HOSTS) { memset(cur, ' ', 4); cur += 4; } @@ -646,48 +684,53 @@ FollowStreamDialog::follow_show(char *buffer, size_t nchars, gboolean is_from_se return FRS_OK; } - - -bool FollowStreamDialog::Follow(QString previous_filter_, follow_type_t type) +bool FollowStreamDialog::follow(QString previous_filter, bool use_tcp_index) { int tmp_fd; - gchar *follow_filter; - const gchar *previous_filter = previous_filter_.toStdString().c_str(); - int filter_out_filter_len, previous_filter_len; + QString follow_filter; const char *hostname0 = NULL, *hostname1 = NULL; char *port0 = NULL, *port1 = NULL; - gchar *server_to_client_string = NULL; - gchar *client_to_server_string = NULL; - gchar *both_directions_string = NULL; + QString server_to_client_string; + QString client_to_server_string; + QString both_directions_string; follow_stats_t stats; tcp_stream_chunk sc; size_t nchars; - gchar *data_out_filename; GString * msg; - if (cfile.edt == NULL) + resetStream(); + + if (cap_file_ == NULL) + { + QMessageBox::warning(this, tr("No capture file."), tr("Please make sure you have a capture file opened.")); + return false; + } + + if (cap_file_->edt == NULL) { QMessageBox::warning(this, tr("Error following stream."), tr("Capture file invalid.")); return false; } - switch (type) + switch (follow_type_) { case FOLLOW_TCP: - if (cfile.edt->pi.ipproto != IP_PROTO_TCP) { + if (cap_file_->edt->pi.ipproto != IP_PROTO_TCP) { QMessageBox::warning(this, tr("Error following stream."), tr("Please make sure you have a TCP packet selected.")); return false; } break; case FOLLOW_UDP: - if (cfile.edt->pi.ipproto != IP_PROTO_UDP) { + removeStreamControls(); + if (cap_file_->edt->pi.ipproto != IP_PROTO_UDP) { QMessageBox::warning(this, tr("Error following stream."), tr("Please make sure you have a UDP packet selected.")); return false; } break; case FOLLOW_SSL: /* we got ssl so we can follow */ - if (!epan_dissect_packet_contains_field(cfile.edt, "ssl")) { + removeStreamControls(); + if (!epan_dissect_packet_contains_field(cap_file_->edt, "ssl")) { QMessageBox::critical(this, tr("Error following stream"), tr("Please make sure you have an SSL packet selected.")); return false; @@ -695,26 +738,26 @@ bool FollowStreamDialog::Follow(QString previous_filter_, follow_type_t type) break; } - follow_info = g_new0(follow_info_t, 1); - follow_info->follow_type = type; - - if (type == FOLLOW_TCP || type == FOLLOW_SSL) + if (follow_type_ == FOLLOW_TCP || follow_type_ == FOLLOW_SSL) { /* 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) { + if (use_tcp_index) { + follow_filter = gchar_free_to_qstring(build_follow_index_filter()); + } else { + follow_filter = gchar_free_to_qstring(build_follow_conv_filter(&cap_file_->edt->pi)); + } + if (follow_filter.isEmpty()) { QMessageBox::warning(this, tr("Error creating filter for this stream."), tr("A transport or network layer header is needed.")); - g_free(follow_info); return false; } - if (type == FOLLOW_TCP || type == FOLLOW_SSL) + if (follow_type_ == FOLLOW_TCP || follow_type_ == FOLLOW_SSL) { /* 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 @@ -724,16 +767,15 @@ bool FollowStreamDialog::Follow(QString previous_filter_, follow_type_t type) 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. */ + gchar *data_out_filename; tmp_fd = create_tempfile(&data_out_filename, "follow"); - follow_info->data_out_filename = g_strdup(data_out_filename); + data_out_filename_ = data_out_filename; if (tmp_fd == -1) { QMessageBox::warning(this, "Error", "Could not create temporary file %1: %2", - follow_info->data_out_filename, g_strerror(errno)); - g_free(follow_info->data_out_filename); - g_free(follow_info); - g_free(follow_filter); + data_out_filename_, g_strerror(errno)); + data_out_filename_.clear(); return false; } @@ -741,101 +783,88 @@ bool FollowStreamDialog::Follow(QString previous_filter_, follow_type_t type) if (data_out_file == NULL) { QMessageBox::warning(this, "Error", "Could not create temporary file %1: %2", - follow_info->data_out_filename, g_strerror(errno)); + data_out_filename_, g_strerror(errno)); //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); + ws_unlink(data_out_filename_.toUtf8().constData()); + data_out_filename_.clear(); return false; } } - /* 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 ? */ - previous_filter_len = previous_filter?(int)strlen(previous_filter):0; - filter_out_filter_len = (int)(strlen(follow_filter) + strlen(previous_filter) + 16); - follow_info->filter_out_filter = (gchar *)g_malloc(filter_out_filter_len); + /* Allocate our new filter. */ /* append the negation */ - if(previous_filter_len) { - g_snprintf(follow_info->filter_out_filter, filter_out_filter_len, - "%s and !(%s)", previous_filter, follow_filter); + if(!previous_filter.isEmpty()) { + filter_out_filter_ = QString("%1 and !(%2)") + .arg(previous_filter).arg(follow_filter); } else { - g_snprintf(follow_info->filter_out_filter, filter_out_filter_len, - "!(%s)", follow_filter); + filter_out_filter_ = QString("!(%1)").arg(follow_filter); } - switch (type) + switch (follow_type_) { case FOLLOW_TCP: + ui->streamNumberSpinBox->blockSignals(true); + ui->streamNumberSpinBox->setMaximum(get_tcp_stream_count() - 1); + ui->streamNumberSpinBox->setValue(get_follow_tcp_index()); + ui->streamNumberSpinBox->blockSignals(false); break; case FOLLOW_UDP: /* data will be passed via tap callback*/ - msg = register_tap_listener("udp_follow", follow_info, follow_filter, + msg = register_tap_listener("udp_follow", &follow_info_, + follow_filter.toUtf8().constData(), 0, NULL, udp_queue_packet_data, NULL); if (msg) { QMessageBox::critical(this, "Error", "Can't register udp_follow tap: %1", msg->str); - g_free(follow_info->filter_out_filter); - g_free(follow_info); - g_free(follow_filter); return false; } break; case FOLLOW_SSL: /* we got ssl so we can follow */ - msg = register_tap_listener("ssl", follow_info, follow_filter, 0, + msg = register_tap_listener("ssl", &follow_info_, + follow_filter.toUtf8().constData(), 0, NULL, ssl_queue_packet_data, NULL); if (msg) { QMessageBox::critical(this, "Error", "Can't register ssl tap: %1", msg->str); - g_free(follow_info->filter_out_filter); - g_free(follow_info); - g_free(follow_filter); return false; } break; } - - /* Run the display filter so it goes in effect - even if it's the same as the previous display filter. */ - QString filter = QString(follow_filter); - emit updateFilter(filter, TRUE); + emit updateFilter(follow_filter, TRUE); - switch (type) + switch (follow_type_) { case FOLLOW_TCP: break; case FOLLOW_UDP: - remove_tap_listener(follow_info); + remove_tap_listener(&follow_info_); break; case FOLLOW_SSL: - remove_tap_listener(follow_info); + remove_tap_listener(&follow_info_); break; } - - if (type == FOLLOW_TCP) + if (follow_type_ == FOLLOW_TCP) { /* Check whether we got any data written to the file. */ if (empty_tcp_stream) { QMessageBox::warning(this, "Error", "The packets in the capture file for that stream have no data."); //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); + ws_unlink(data_out_filename_.toUtf8().constData()); + data_out_filename_.clear(); return false; } @@ -845,24 +874,23 @@ bool FollowStreamDialog::Follow(QString previous_filter_, follow_type_t type) if (ferror(data_out_file)) { QMessageBox::warning(this, "Error", QString(tr("Could not read from temporary file %1: %2")) - .arg(follow_info->data_out_filename) + .arg(data_out_filename_) .arg(g_strerror(errno))); } else { QMessageBox::warning(this, "Error", QString(tr("Short read from temporary file %1: expected %2, got %3")) - .arg(follow_info->data_out_filename) + .arg(data_out_filename_) .arg((unsigned long)sizeof(sc)) .arg((unsigned long)nchars)); } //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); + ws_unlink(data_out_filename_.toUtf8().constData()); + data_out_filename_.clear(); return false; } fclose(data_out_file); + data_out_file = NULL; } /* Stream to show */ @@ -872,7 +900,7 @@ bool FollowStreamDialog::Follow(QString previous_filter_, follow_type_t type) struct e_in6_addr ipaddr; memcpy(&ipaddr, stats.ip_address[0], 16); hostname0 = get_hostname6(&ipaddr); - memcpy(&ipaddr, (type == FOLLOW_TCP) ? stats.ip_address[1] : stats.ip_address[0], 16); + memcpy(&ipaddr, (follow_type_ == FOLLOW_TCP) ? stats.ip_address[1] : stats.ip_address[0], 16); hostname1 = get_hostname6(&ipaddr); } else { guint32 ipaddr; @@ -882,7 +910,7 @@ bool FollowStreamDialog::Follow(QString previous_filter_, follow_type_t type) hostname1 = get_hostname(ipaddr); } - switch (type) + switch (follow_type_) { case FOLLOW_TCP: port0 = get_tcp_port(stats.port[0]); @@ -898,99 +926,129 @@ bool FollowStreamDialog::Follow(QString previous_filter_, follow_type_t type) break; } - follow_info->is_ipv6 = stats.is_ipv6; + follow_info_.is_ipv6 = stats.is_ipv6; - if (type == FOLLOW_TCP) + if (follow_type_ == FOLLOW_TCP) { /* Host 0 --> Host 1 */ if(sc.src_port == stats.port[0]) { server_to_client_string = - g_strdup_printf("%s:%s " UTF8_RIGHTWARDS_ARROW " %s:%s (%u bytes)", - hostname0, port0, - hostname1, port1, - stats.bytes_written[0]); + QString("%1:%2 %3 %4:%5 (%6)") + .arg(hostname0).arg(port0) + .arg(UTF8_RIGHTWARDS_ARROW) + .arg(hostname1).arg(port1) + .arg(gchar_free_to_qstring(format_size( + stats.bytes_written[0], + format_size_unit_bytes|format_size_prefix_si))); } else { server_to_client_string = - g_strdup_printf("%s:%s " UTF8_RIGHTWARDS_ARROW " %s:%s (%u bytes)", - hostname1, port1, - hostname0,port0, - stats.bytes_written[0]); + QString("%1:%2 %3 %4:%5 (%6)") + .arg(hostname1).arg(port1) + .arg(UTF8_RIGHTWARDS_ARROW) + .arg(hostname0).arg(port0) + .arg(gchar_free_to_qstring(format_size( + stats.bytes_written[0], + format_size_unit_bytes|format_size_prefix_si))); } /* Host 1 --> Host 0 */ if(sc.src_port == stats.port[1]) { client_to_server_string = - g_strdup_printf("%s:%s " UTF8_RIGHTWARDS_ARROW " %s:%s (%u bytes)", - hostname0, port0, - hostname1, port1, - stats.bytes_written[1]); + QString("%1:%2 %3 %4:%5 (%6)") + .arg(hostname0).arg(port0) + .arg(UTF8_RIGHTWARDS_ARROW) + .arg(hostname1).arg(port1) + .arg(gchar_free_to_qstring(format_size( + stats.bytes_written[1], + format_size_unit_bytes|format_size_prefix_si))); } else { client_to_server_string = - g_strdup_printf("%s:%s " UTF8_RIGHTWARDS_ARROW " %s:%s (%u bytes)", - hostname1, port1, - hostname0, port0, - stats.bytes_written[1]); + QString("%1:%2 %3 %4:%5 (%6)") + .arg(hostname1).arg(port1) + .arg(UTF8_RIGHTWARDS_ARROW) + .arg(hostname0).arg(port0) + .arg(gchar_free_to_qstring(format_size( + stats.bytes_written[1], + format_size_unit_bytes|format_size_prefix_si))); } } else { - if(follow_info->client_port == stats.port[0]) { + if(follow_info_.client_port == stats.port[0]) { server_to_client_string = - g_strdup_printf("%s:%s " UTF8_RIGHTWARDS_ARROW " %s:%s (%u bytes)", - hostname0, port0, - hostname1, port1, - follow_info->bytes_written[0]); + QString("%1:%2 %3 %4:%5 (%6)") + .arg(hostname0).arg(port0) + .arg(UTF8_RIGHTWARDS_ARROW) + .arg(hostname1).arg(port1) + .arg(gchar_free_to_qstring(format_size( + follow_info_.bytes_written[0], + format_size_unit_bytes|format_size_prefix_si))); client_to_server_string = - g_strdup_printf("%s:%s " UTF8_RIGHTWARDS_ARROW " %s:%s (%u bytes)", - hostname1, port1, - hostname0, port0, - follow_info->bytes_written[1]); + QString("%1:%2 %3 %4:%5 (%6)") + .arg(hostname0).arg(port0) + .arg(UTF8_RIGHTWARDS_ARROW) + .arg(hostname1).arg(port1) + .arg(gchar_free_to_qstring(format_size( + follow_info_.bytes_written[1], + format_size_unit_bytes|format_size_prefix_si))); } else { server_to_client_string = - g_strdup_printf("%s:%s " UTF8_RIGHTWARDS_ARROW " %s:%s (%u bytes)", - hostname1, port1, - hostname0, port0, - follow_info->bytes_written[0]); + QString("%1:%2 %3 %4:%5 (%6)") + .arg(hostname1).arg(port1) + .arg(UTF8_RIGHTWARDS_ARROW) + .arg(hostname0).arg(port0) + .arg(gchar_free_to_qstring(format_size( + follow_info_.bytes_written[0], + format_size_unit_bytes|format_size_prefix_si))); client_to_server_string = - g_strdup_printf("%s:%s " UTF8_RIGHTWARDS_ARROW " %s:%s (%u bytes)", - hostname0, port0, - hostname1, port1, - follow_info->bytes_written[1]); + QString("%1:%2 %3 %4:%5 (%6)") + .arg(hostname1).arg(port1) + .arg(UTF8_RIGHTWARDS_ARROW) + .arg(hostname0).arg(port0) + .arg(gchar_free_to_qstring(format_size( + follow_info_.bytes_written[1], + format_size_unit_bytes|format_size_prefix_si))); } } /* Both Stream Directions */ - switch (type) + switch (follow_type_) { case FOLLOW_TCP: - both_directions_string = g_strdup_printf("Entire conversation (%u bytes)", stats.bytes_written[0] + stats.bytes_written[1]); + both_directions_string = QString("Entire conversation (%1)") + .arg(gchar_free_to_qstring(format_size( + stats.bytes_written[0] + stats.bytes_written[1], + format_size_unit_bytes|format_size_prefix_si))); this->setWindowTitle(QString("Follow TCP Stream (%1)").arg(follow_filter)); break; case FOLLOW_UDP: - both_directions_string = g_strdup_printf("Entire conversation (%u bytes)", follow_info->bytes_written[0] + follow_info->bytes_written[1]); + both_directions_string = QString("Entire conversation (%1)") + .arg(gchar_free_to_qstring(format_size( + follow_info_.bytes_written[0] + follow_info_.bytes_written[1], + format_size_unit_bytes|format_size_prefix_si))); this->setWindowTitle(QString("Follow UDP Stream (%1)").arg(follow_filter)); break; case FOLLOW_SSL: - both_directions_string = g_strdup_printf("Entire conversation (%u bytes)", follow_info->bytes_written[0] + follow_info->bytes_written[1]); + both_directions_string = QString("Entire conversation (%1)") + .arg(gchar_free_to_qstring(format_size( + follow_info_.bytes_written[0] + follow_info_.bytes_written[1], + format_size_unit_bytes|format_size_prefix_si))); this->setWindowTitle(QString("Follow SSL Stream (%1)").arg(follow_filter)); break; } ui->cbDirections->clear(); - this->ui->cbDirections->addItem(QString(both_directions_string)); - this->ui->cbDirections->addItem(QString(client_to_server_string)); - this->ui->cbDirections->addItem(QString(server_to_client_string)); + this->ui->cbDirections->addItem(both_directions_string); + this->ui->cbDirections->addItem(client_to_server_string); + this->ui->cbDirections->addItem(server_to_client_string); follow_stream(); - /* Free the filter string, as we're done with it. */ - g_free(follow_filter); - data_out_file = NULL; return true; @@ -1019,7 +1077,7 @@ bool FollowStreamDialog::Follow(QString previous_filter_, follow_type_t type) frs_return_t FollowStreamDialog::follow_read_tcp_stream() { - FILE *data_out_file; + FILE *data_out_fp; tcp_stream_chunk sc; size_t bcount; size_t bytes_read; @@ -1043,25 +1101,25 @@ FollowStreamDialog::follow_read_tcp_stream() #endif - iplen = (follow_info->is_ipv6) ? 16 : 4; + iplen = (follow_info_.is_ipv6) ? 16 : 4; - data_out_file = ws_fopen(follow_info->data_out_filename, "rb"); - if (data_out_file == NULL) { + data_out_fp = ws_fopen(data_out_filename_.toUtf8().constData(), "rb"); + if (data_out_fp == NULL) { QMessageBox::critical(this, "Error", - "Could not open temporary file %1: %2", follow_info->data_out_filename, + "Could not open temporary file %1: %2", data_out_filename_, g_strerror(errno)); return FRS_OPEN_ERROR; } - while ((nchars=fread(&sc, 1, sizeof(sc), data_out_file))) { + while ((nchars=fread(&sc, 1, sizeof(sc), data_out_fp))) { if (nchars != sizeof(sc)) { QMessageBox::critical(this, "Error", QString(tr("Short read from temporary file %1: expected %2, got %3")) - .arg(follow_info->data_out_filename) + .arg(data_out_filename_) .arg(sizeof(sc)) .arg(nchars)); - fclose(data_out_file); - data_out_file = NULL; + fclose(data_out_fp); + data_out_fp = NULL; return FRS_READ_ERROR; } if (client_port == 0) { @@ -1073,14 +1131,14 @@ FollowStreamDialog::follow_read_tcp_stream() client_port == sc.src_port) { is_server = FALSE; global_pos = &global_client_pos; - if (follow_info->show_stream == FROM_SERVER) { + if (follow_info_.show_stream == FROM_SERVER) { skip = TRUE; } } else { is_server = TRUE; global_pos = &global_server_pos; - if (follow_info->show_stream == FROM_CLIENT) { + if (follow_info_.show_stream == FROM_CLIENT) { skip = TRUE; } } @@ -1088,7 +1146,7 @@ FollowStreamDialog::follow_read_tcp_stream() bytes_read = 0; while (bytes_read < sc.dlen) { bcount = ((sc.dlen-bytes_read) < FLT_BUF_SIZE) ? (sc.dlen-bytes_read) : FLT_BUF_SIZE; - nchars = fread(buffer, 1, bcount, data_out_file); + nchars = fread(buffer, 1, bcount, data_out_fp); if (nchars == 0) break; /* XXX - if we don't get "bcount" bytes, is that an error? */ @@ -1107,8 +1165,8 @@ FollowStreamDialog::follow_read_tcp_stream() header_len, is_server, global_pos, &server_packet_count, &client_packet_count); if (frs_return == FRS_PRINT_ERROR) { - fclose(data_out_file); - data_out_file = NULL; + fclose(data_out_fp); + data_out_fp = NULL; return frs_return; } @@ -1122,8 +1180,8 @@ FollowStreamDialog::follow_read_tcp_stream() strm.opaque = Z_NULL; ret = inflateInit2(&strm, MAX_WBITS+16); if (ret != Z_OK) { - fclose(data_out_file); - data_out_file = NULL; + fclose(data_out_fp); + data_out_fp = NULL; return FRS_READ_ERROR; } @@ -1143,8 +1201,8 @@ FollowStreamDialog::follow_read_tcp_stream() ret = inflate(&strm, Z_NO_FLUSH); if (ret < 0 || ret == Z_NEED_DICT) { inflateEnd(&strm); - fclose(data_out_file); - data_out_file = NULL; + fclose(data_out_fp); + data_out_fp = NULL; return FRS_READ_ERROR; } else if (ret == Z_STREAM_END) { inflateEnd(&strm); @@ -1157,8 +1215,8 @@ FollowStreamDialog::follow_read_tcp_stream() &client_packet_count); if(frs_return == FRS_PRINT_ERROR) { inflateEnd(&strm); - fclose(data_out_file); - data_out_file = NULL; + fclose(data_out_fp); + data_out_fp = NULL; return frs_return; } } while (strm.avail_out == 0); @@ -1172,8 +1230,8 @@ FollowStreamDialog::follow_read_tcp_stream() &server_packet_count, &client_packet_count); if(frs_return == FRS_PRINT_ERROR) { - fclose(data_out_file); - data_out_file = NULL; + fclose(data_out_fp); + data_out_fp = NULL; return frs_return; } @@ -1181,17 +1239,16 @@ FollowStreamDialog::follow_read_tcp_stream() } } - if (ferror(data_out_file)) { - simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, - "Error reading temporary file %s: %s", follow_info->data_out_filename, - g_strerror(errno)); - fclose(data_out_file); - data_out_file = NULL; + if (ferror(data_out_fp)) { + QMessageBox::critical(this, tr("Error reading temporary file"), + QString("%1: %2").arg(data_out_filename_).arg(g_strerror(errno))); + fclose(data_out_fp); + data_out_fp = NULL; return FRS_READ_ERROR; } - fclose(data_out_file); - data_out_file = NULL; + fclose(data_out_fp); + data_out_fp = NULL; return FRS_OK; } @@ -1229,17 +1286,17 @@ FollowStreamDialog::follow_read_udp_stream() char *buffer; - for (cur = follow_info->payload; cur; cur = g_list_next(cur)) { + for (cur = follow_info_.payload; cur; cur = g_list_next(cur)) { follow_record = (follow_record_t *)cur->data; skip = FALSE; if (!follow_record->is_server) { global_pos = &global_client_pos; - if(follow_info->show_stream == FROM_SERVER) { + if(follow_info_.show_stream == FROM_SERVER) { skip = TRUE; } } else { global_pos = &global_server_pos; - if (follow_info->show_stream == FROM_CLIENT) { + if (follow_info_.show_stream == FROM_CLIENT) { skip = TRUE; } } @@ -1264,12 +1321,6 @@ FollowStreamDialog::follow_read_udp_stream() return FRS_OK; } - -FollowStreamDialog::~FollowStreamDialog() -{ - delete ui; -} - /* * Editor modelines * diff --git a/ui/qt/follow_stream_dialog.h b/ui/qt/follow_stream_dialog.h index 5f8ec74714..ffa3817cb8 100644 --- a/ui/qt/follow_stream_dialog.h +++ b/ui/qt/follow_stream_dialog.h @@ -34,6 +34,8 @@ #include <unistd.h> #endif +#include "file.h" + #include "ui/follow.h" #include <QDialog> @@ -44,13 +46,11 @@ extern "C" { WS_DLL_PUBLIC FILE *data_out_file; } +// Shouldn't these be member variables? typedef struct { - follow_type_t follow_type; show_stream_t show_stream; show_type_t show_type; - char *data_out_filename; gboolean is_ipv6; - char *filter_out_filter; GList *payload; guint bytes_written[2]; /* Index with FROM_CLIENT or FROM_SERVER for readability. */ guint client_port; @@ -66,69 +66,70 @@ class FollowStreamDialog : public QDialog Q_OBJECT public: - explicit FollowStreamDialog(QWidget *parent = 0); + explicit FollowStreamDialog(QWidget *parent = 0, follow_type_t type = FOLLOW_TCP, capture_file *cf = NULL); ~FollowStreamDialog(); - bool Follow(QString previous_filter_, follow_type_t type); - - frs_return_t - follow_show(char *buffer, size_t nchars, gboolean is_from_server, - guint32 *global_pos, guint32 *server_packet_count, - guint32 *client_packet_count); - - frs_return_t - follow_read_stream(); - - frs_return_t - follow_read_tcp_stream(); - - frs_return_t - follow_read_udp_stream(); - - frs_return_t - follow_read_ssl_stream(); - - void - follow_stream(); + bool follow(QString previous_filter = QString(), bool use_tcp_index = false); - void add_text(char *buffer, size_t nchars, gboolean is_from_server); +public slots: + void setCaptureFile(capture_file *cf); protected: bool eventFilter(QObject *obj, QEvent *event); void keyPressEvent(QKeyEvent *event); - void closeEvent (QCloseEvent *event); private slots: void on_cbCharset_currentIndexChanged(int index); void on_cbDirections_currentIndexChanged(int index); void on_bFind_clicked(); void on_leFind_returnPressed(); - void on_buttonBox_rejected(); - void HelpButton(); - void FilterOut(); - void FindText(bool go_back = true); - void SaveAs(); - void Print(); + void helpButton(); + void filterOut(); + void findText(bool go_back = true); + void saveAs(); + void printStream(); + + void on_streamNumberSpinBox_valueChanged(int stream_num); + + void on_buttonBox_rejected(); signals: void updateFilter(QString &filter, bool force); private: - Ui::FollowStreamDialog *ui; + void removeStreamControls(); + void resetStream(void); + frs_return_t + follow_show(char *buffer, size_t nchars, gboolean is_from_server, + guint32 *global_pos, guint32 *server_packet_count, + guint32 *client_packet_count); - QPushButton *bFilterOut; - QPushButton *bFind; - QPushButton *bPrint; - QPushButton *bSave; + frs_return_t follow_read_stream(); + frs_return_t follow_read_tcp_stream(); + frs_return_t follow_read_udp_stream(); + frs_return_t follow_read_ssl_stream(); - follow_info_t *follow_info; + void follow_stream(); - bool save_as; - QFile file; -}; + void add_text(char *buffer, size_t nchars, gboolean is_from_server); + Ui::FollowStreamDialog *ui; + capture_file *cap_file_; + QPushButton *b_filter_out_; + QPushButton *b_find_; + QPushButton *b_print_; + QPushButton *b_save_; + + follow_type_t follow_type_; + follow_info_t follow_info_; + QString data_out_filename_; + QString filter_out_filter_; + + bool save_as_; + QFile file_; +}; #endif // FOLLOW_STREAM_DIALOG_H diff --git a/ui/qt/follow_stream_dialog.ui b/ui/qt/follow_stream_dialog.ui index 43c7042c2f..4dd0cd850b 100644 --- a/ui/qt/follow_stream_dialog.ui +++ b/ui/qt/follow_stream_dialog.ui @@ -6,8 +6,8 @@ <rect> <x>0</x> <y>0</y> - <width>667</width> - <height>639</height> + <width>750</width> + <height>620</height> </rect> </property> <property name="sizePolicy"> @@ -31,7 +31,7 @@ </widget> </item> <item> - <layout class="QHBoxLayout" name="horizontalLayout"> + <layout class="QHBoxLayout" name="horizontalLayout" stretch="0,0,0,0,1,0,0"> <item> <widget class="QComboBox" name="cbDirections"/> </item> @@ -87,6 +87,29 @@ </item> </widget> </item> + <item> + <spacer name="streamNumberSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QLabel" name="streamNumberLabel"> + <property name="text"> + <string>Stream</string> + </property> + </widget> + </item> + <item> + <widget class="QSpinBox" name="streamNumberSpinBox"/> + </item> </layout> </item> <item> @@ -113,7 +136,7 @@ <item> <widget class="QDialogButtonBox" name="buttonBox"> <property name="standardButtons"> - <set>QDialogButtonBox::Cancel|QDialogButtonBox::Help</set> + <set>QDialogButtonBox::Close|QDialogButtonBox::Help</set> </property> </widget> </item> diff --git a/ui/qt/main_window.cpp b/ui/qt/main_window.cpp index 27d854a5ec..0dcbbea564 100644 --- a/ui/qt/main_window.cpp +++ b/ui/qt/main_window.cpp @@ -119,7 +119,6 @@ MainWindow::MainWindow(QWidget *parent) : updateRecentFiles(); connect(&summary_dialog_, SIGNAL(captureCommentChanged()), this, SLOT(updateForUnsavedChanges())); - connect(&follow_stream_dialog_, SIGNAL(updateFilter(QString&, bool)), this, SLOT(filterPackets(QString&, bool))); const DisplayFilterEdit *df_edit = dynamic_cast<DisplayFilterEdit *>(df_combo_box_->lineEdit()); connect(df_edit, SIGNAL(pushFilterSyntaxStatus(QString&)), main_ui_->statusBar, SLOT(pushFilterStatus(QString&))); diff --git a/ui/qt/main_window.h b/ui/qt/main_window.h index a5ea5269a4..ff42c0a6a9 100644 --- a/ui/qt/main_window.h +++ b/ui/qt/main_window.h @@ -113,7 +113,6 @@ private: SummaryDialog summary_dialog_; ByteViewTab *byte_view_tab_; QWidget empty_pane_; - FollowStreamDialog follow_stream_dialog_; bool capture_stopping_; bool capture_filter_valid_; @@ -277,6 +276,8 @@ private slots: void on_actionAnalyzePAFOrSelected_triggered(); void on_actionAnalyzePAFAndNotSelected_triggered(); void on_actionAnalyzePAFOrNotSelected_triggered(); + + void openFollowStreamDialog(follow_type_t type); void on_actionAnalyzeFollowTCPStream_triggered(); void on_actionAnalyzeFollowUDPStream_triggered(); void on_actionAnalyzeFollowSSLStream_triggered(); diff --git a/ui/qt/main_window_slots.cpp b/ui/qt/main_window_slots.cpp index dd69526b23..2dffc01e8e 100644 --- a/ui/qt/main_window_slots.cpp +++ b/ui/qt/main_window_slots.cpp @@ -1702,58 +1702,27 @@ void MainWindow::on_actionAnalyzePAFOrNotSelected_triggered() matchSelectedFilter(MatchSelectedOrNot, false, false); } -void MainWindow::on_actionAnalyzeFollowTCPStream_triggered() -{ - // XXX Keeping a window or dialog in memory is common in the GTK+ - // code but not in the Qt code. Should we just create a new - // dialog and exec() it instead? - follow_stream_dialog_.Follow(getFilter(), FOLLOW_TCP); +void MainWindow::openFollowStreamDialog(follow_type_t type) { + FollowStreamDialog *fsd = new FollowStreamDialog(this, type, cap_file_); + connect(fsd, SIGNAL(updateFilter(QString&, bool)), this, SLOT(filterPackets(QString&, bool))); - if (follow_stream_dialog_.isMinimized() == true) - { - follow_stream_dialog_.showNormal(); - } - else - { - follow_stream_dialog_.show(); - } + fsd->follow(getFilter()); + fsd->show(); +} - follow_stream_dialog_.raise(); - follow_stream_dialog_.activateWindow(); +void MainWindow::on_actionAnalyzeFollowTCPStream_triggered() +{ + openFollowStreamDialog(FOLLOW_TCP); } void MainWindow::on_actionAnalyzeFollowUDPStream_triggered() { - follow_stream_dialog_.Follow(getFilter(), FOLLOW_UDP); - - if (follow_stream_dialog_.isMinimized() == true) - { - follow_stream_dialog_.showNormal(); - } - else - { - follow_stream_dialog_.show(); - } - - follow_stream_dialog_.raise(); - follow_stream_dialog_.activateWindow(); + openFollowStreamDialog(FOLLOW_UDP); } void MainWindow::on_actionAnalyzeFollowSSLStream_triggered() { - follow_stream_dialog_.Follow(getFilter(), FOLLOW_SSL); - - if (follow_stream_dialog_.isMinimized() == true) - { - follow_stream_dialog_.showNormal(); - } - else - { - follow_stream_dialog_.show(); - } - - follow_stream_dialog_.raise(); - follow_stream_dialog_.activateWindow(); + openFollowStreamDialog(FOLLOW_SSL); } // Next / previous / first / last slots in packet_list diff --git a/ui/qt/sequence_dialog.cpp b/ui/qt/sequence_dialog.cpp index 759b12dcf9..e861b62837 100644 --- a/ui/qt/sequence_dialog.cpp +++ b/ui/qt/sequence_dialog.cpp @@ -46,6 +46,7 @@ // - Incorporate packet comments? // - Change line_style to seq_type (i.e. draw ACKs dashed) // - Create WSGraph subclasses with common behavior. +// - Help button and text SequenceDialog::SequenceDialog(QWidget *parent, capture_file *cf, SequenceType type) : QDialog(parent), @@ -93,13 +94,18 @@ SequenceDialog::SequenceDialog(QWidget *parent, capture_file *cf, SequenceType t memset (&seq_analysis_, 0, sizeof(seq_analysis_)); + ui->showComboBox->blockSignals(true); ui->showComboBox->setCurrentIndex(0); + ui->showComboBox->blockSignals(false); + ui->addressComboBox->blockSignals(true); ui->addressComboBox->setCurrentIndex(0); + ui->addressComboBox->blockSignals(false); QComboBox *fcb = ui->flowComboBox; fcb->addItem(ui->actionFlowAny->text(), SEQ_ANALYSIS_ANY); fcb->addItem(ui->actionFlowTcp->text(), SEQ_ANALYSIS_TCP); + ui->flowComboBox->blockSignals(true); switch (type) { case any: seq_analysis_.type = SEQ_ANALYSIS_ANY; @@ -115,6 +121,7 @@ SequenceDialog::SequenceDialog(QWidget *parent, capture_file *cf, SequenceType t ui->flowLabel->hide(); break; } + ui->flowComboBox->blockSignals(false); seq_analysis_.all_packets = TRUE; QPushButton *save_bt = ui->buttonBox->button(QDialogButtonBox::Save); @@ -425,14 +432,14 @@ void SequenceDialog::on_showComboBox_currentIndexChanged(int index) } else { seq_analysis_.all_packets = FALSE; } - if (isVisible()) fillDiagram(); + fillDiagram(); } void SequenceDialog::on_flowComboBox_currentIndexChanged(int index) { if (index < 0) return; seq_analysis_.type = static_cast<seq_analysis_type>(ui->flowComboBox->itemData(index).toInt()); - if (isVisible()) fillDiagram(); + fillDiagram(); } void SequenceDialog::on_addressComboBox_currentIndexChanged(int index) @@ -442,7 +449,7 @@ void SequenceDialog::on_addressComboBox_currentIndexChanged(int index) } else { seq_analysis_.any_addr = FALSE; } - if (isVisible()) fillDiagram(); + fillDiagram(); } void SequenceDialog::on_actionReset_triggered() diff --git a/wsutil/tempfile.h b/wsutil/tempfile.h index 65746704dd..4f9492ed87 100644 --- a/wsutil/tempfile.h +++ b/wsutil/tempfile.h @@ -40,9 +40,9 @@ extern "C" { * Create a tempfile with the given prefix (e.g. "wireshark"). The path * is created using g_get_tmp_dir and mkstemp. * - * @param namebuf If not NULL, receives the full path of the temp file. + * @param namebuf[in,out] If not NULL, receives the full path of the temp file. * Must NOT be freed. - * @param pfx A prefix for the temporary file. + * @param pfx[in] A prefix for the temporary file. * @return The file descriptor of the new tempfile, from mkstemp(). */ WS_DLL_PUBLIC int create_tempfile(char **namebuf, const char *pfx); |