From 16953695d734555a4472bada9d2dec799544d619 Mon Sep 17 00:00:00 2001 From: Peter Wu Date: Tue, 10 Jul 2018 00:33:24 +0200 Subject: [PATCH] Qt: make "Save As" in Follow Streams usable For formats other than "Raw" and "UTF-8", the written file does not match the actual stream data. It would be duplicated in strange ways. Executing the "Save As" action twice while the dialog is open would also write two different files (huh?). As a quick fix, just replace the strange save logic by writing the text field contents. A functional difference is that previously it would write data while parsing the "follow data" list, now it uses the text field contents. That data will now be truncated after 500 MB. Bug: 14933 Change-Id: I498676389d0da3ac070346d6903bd2e6b0fc7674 Fixes: v1.11.0-rc1-2538-g80f9326b2f ("Add TCP/UDP/SSL Follow feature to QtShark") Reviewed-on: https://code.wireshark.org/review/28663 Petri-Dish: Peter Wu Tested-by: Petri Dish Buildbot Reviewed-by: Peter Wu --- ui/qt/follow_stream_dialog.cpp | 76 +++++++++++----------------------- ui/qt/follow_stream_dialog.h | 2 - 2 files changed, 24 insertions(+), 54 deletions(-) diff --git a/ui/qt/follow_stream_dialog.cpp b/ui/qt/follow_stream_dialog.cpp index 3f3f88d411..2b141fbeb1 100644 --- a/ui/qt/follow_stream_dialog.cpp +++ b/ui/qt/follow_stream_dialog.cpp @@ -53,6 +53,8 @@ // - Instead of calling QMessageBox, display the error message in the text // box and disable the appropriate controls. // - Add a progress bar and connect captureCaptureUpdateContinue to it +// - User's Guide documents the "Raw" type as "same as ASCII, but saving binary +// data". However it currently displays hex-encoded data. // Matches SplashOverlay. static int info_update_freq_ = 100; @@ -72,7 +74,6 @@ FollowStreamDialog::FollowStreamDialog(QWidget &parent, CaptureFile &cf, follow_ last_packet_(0), last_from_server_(0), turns_(0), - save_as_(false), use_regex_find_(false), terminating_(false) { @@ -267,28 +268,26 @@ void FollowStreamDialog::findText(bool go_back) void FollowStreamDialog::saveAs() { QString file_name = WiresharkFileDialog::getSaveFileName(this, wsApp->windowTitleString(tr("Save Stream Content As" UTF8_HORIZONTAL_ELLIPSIS))); - if (!file_name.isEmpty()) { - QTextStream out(&file_); - - file_.setFileName(file_name); - if (!file_.open(QIODevice::WriteOnly)) { - open_failure_alert_box(file_name.toUtf8().constData(), errno, TRUE); - return; - } - - save_as_ = true; - - readStream(); - - if ((show_type_ != SHOW_RAW) && (show_type_ != SHOW_UTF8)) - { - out << ui->teStreamContent->toPlainText(); - } - - save_as_ = false; - - file_.close(); + if (file_name.isEmpty()) { + return; } + + QFile file(file_name); + if (!file.open(QIODevice::WriteOnly)) { + open_failure_alert_box(file_name.toUtf8().constData(), errno, TRUE); + return; + } + + // Unconditionally save data as UTF-8 (even if data is decoded as UTF-16). + QByteArray bytes = ui->teStreamContent->toPlainText().toUtf8(); + if (show_type_ == SHOW_RAW) { + // The "Raw" format is currently displayed as hex data and needs to be + // converted to binary data. + bytes = QByteArray::fromHex(bytes); + } + + QDataStream out(&file); + out.writeRawData(bytes.constData(), bytes.size()); } void FollowStreamDialog::helpButton() @@ -438,11 +437,8 @@ frs_return_t FollowStreamDialog::readStream() { - // Only clear the display if we're going to refill it - if (save_as_ == false) { - ui->teStreamContent->clear(); - text_pos_to_packet_.clear(); - } + ui->teStreamContent->clear(); + text_pos_to_packet_.clear(); truncated_ = false; frs_return_t ret; @@ -469,8 +465,7 @@ FollowStreamDialog::readStream() break; } - if (save_as_ == false) - ui->teStreamContent->moveCursor(QTextCursor::Start); + ui->teStreamContent->moveCursor(QTextCursor::Start); return ret; } @@ -484,29 +479,6 @@ FollowStreamDialog::followStream() const int FollowStreamDialog::max_document_length_ = 500 * 1000 * 1000; // Just a guess void FollowStreamDialog::addText(QString text, gboolean is_from_server, guint32 packet_num) { - if (save_as_ == true) - { - size_t nwritten; - int FileDescriptor = file_.handle(); - int fd_new = ws_dup(FileDescriptor); - if (fd_new == -1) - return; - FILE* fh = ws_fdopen(fd_new, "wb"); - if (show_type_ == SHOW_RAW) { - QByteArray binstream = QByteArray::fromHex(text.toUtf8()); - nwritten = fwrite(binstream.constData(), binstream.length(), 1, fh); - } else { - nwritten = fwrite(text.toUtf8().constData(), text.length(), 1, fh); - } - fclose(fh); - if ((int)nwritten != text.length()) { -#if 0 - report_an_error_maybe(); -#endif - } - return; - } - if (truncated_) { return; } diff --git a/ui/qt/follow_stream_dialog.h b/ui/qt/follow_stream_dialog.h index f4b6dd25af..805f46c6ab 100644 --- a/ui/qt/follow_stream_dialog.h +++ b/ui/qt/follow_stream_dialog.h @@ -119,9 +119,7 @@ private: int turns_; QMap text_pos_to_packet_; - bool save_as_; bool use_regex_find_; - QFile file_; bool terminating_; };