diff options
-rw-r--r-- | cfile.h | 6 | ||||
-rw-r--r-- | file.c | 39 | ||||
-rw-r--r-- | ui/gtk/find_dlg.c | 29 | ||||
-rw-r--r-- | ui/qt/CMakeLists.txt | 3 | ||||
-rw-r--r-- | ui/qt/Makefile.am | 6 | ||||
-rw-r--r-- | ui/qt/Makefile.common | 3 | ||||
-rw-r--r-- | ui/qt/QtShark.pro | 9 | ||||
-rw-r--r-- | ui/qt/display_filter_edit.cpp | 4 | ||||
-rw-r--r-- | ui/qt/display_filter_edit.h | 2 | ||||
-rw-r--r-- | ui/qt/label_stack.cpp | 9 | ||||
-rw-r--r-- | ui/qt/main_status_bar.cpp | 10 | ||||
-rw-r--r-- | ui/qt/main_window.cpp | 35 | ||||
-rw-r--r-- | ui/qt/main_window.h | 3 | ||||
-rw-r--r-- | ui/qt/main_window.ui | 44 | ||||
-rw-r--r-- | ui/qt/main_window_slots.cpp | 34 | ||||
-rw-r--r-- | ui/qt/search_frame.cpp | 373 | ||||
-rw-r--r-- | ui/qt/search_frame.h | 74 | ||||
-rw-r--r-- | ui/qt/search_frame.ui | 166 |
18 files changed, 781 insertions, 68 deletions
@@ -43,9 +43,9 @@ typedef enum { /* Character set for text search. */ typedef enum { - SCS_ASCII_AND_UNICODE, - SCS_ASCII, - SCS_UNICODE + SCS_NARROW_AND_WIDE, + SCS_NARROW, + SCS_WIDE /* add EBCDIC when it's implemented */ } search_charset_t; @@ -103,11 +103,11 @@ static match_result match_protocol_tree(capture_file *cf, frame_data *fdata, static void match_subtree_text(proto_node *node, gpointer data); static match_result match_summary_line(capture_file *cf, frame_data *fdata, void *criterion); -static match_result match_ascii_and_unicode(capture_file *cf, frame_data *fdata, +static match_result match_narrow_and_wide(capture_file *cf, frame_data *fdata, void *criterion); -static match_result match_ascii(capture_file *cf, frame_data *fdata, +static match_result match_narrow(capture_file *cf, frame_data *fdata, void *criterion); -static match_result match_unicode(capture_file *cf, frame_data *fdata, +static match_result match_wide(capture_file *cf, frame_data *fdata, void *criterion); static match_result match_binary(capture_file *cf, frame_data *fdata, void *criterion); @@ -626,7 +626,7 @@ cf_read(capture_file *cf, gboolean reloading) break; } read_packet(cf, dfcode, create_proto_tree, cinfo, data_offset); - } + } } CATCH(OutOfMemoryError) { simple_message_box(ESD_TYPE_ERROR, NULL, @@ -3111,6 +3111,17 @@ typedef struct { size_t data_len; } cbs_t; /* "Counted byte string" */ + +/* + * The current match_* routines only support ASCII case insensitivity and don't + * convert UTF-8 inputs to UTF-16 for matching. + * + * We could modify them to use the GLib Unicode routines or the International + * Components for Unicode library but it's not apparent that we could do so + * without consuming a lot more CPU and memory or that searching would be + * significantly better. + */ + gboolean cf_find_packet_data(capture_file *cf, const guint8 *string, size_t string_size, search_direction dir) @@ -3125,14 +3136,14 @@ cf_find_packet_data(capture_file *cf, const guint8 *string, size_t string_size, /* String search - what type of string? */ switch (cf->scs_type) { - case SCS_ASCII_AND_UNICODE: - return find_packet(cf, match_ascii_and_unicode, &info, dir); + case SCS_NARROW_AND_WIDE: + return find_packet(cf, match_narrow_and_wide, &info, dir); - case SCS_ASCII: - return find_packet(cf, match_ascii, &info, dir); + case SCS_NARROW: + return find_packet(cf, match_narrow, &info, dir); - case SCS_UNICODE: - return find_packet(cf, match_unicode, &info, dir); + case SCS_WIDE: + return find_packet(cf, match_wide, &info, dir); default: g_assert_not_reached(); @@ -3143,7 +3154,7 @@ cf_find_packet_data(capture_file *cf, const guint8 *string, size_t string_size, } static match_result -match_ascii_and_unicode(capture_file *cf, frame_data *fdata, void *criterion) +match_narrow_and_wide(capture_file *cf, frame_data *fdata, void *criterion) { cbs_t *info = criterion; const guint8 *ascii_text = info->data; @@ -3189,7 +3200,7 @@ match_ascii_and_unicode(capture_file *cf, frame_data *fdata, void *criterion) } static match_result -match_ascii(capture_file *cf, frame_data *fdata, void *criterion) +match_narrow(capture_file *cf, frame_data *fdata, void *criterion) { cbs_t *info = criterion; const guint8 *ascii_text = info->data; @@ -3234,7 +3245,7 @@ match_ascii(capture_file *cf, frame_data *fdata, void *criterion) } static match_result -match_unicode(capture_file *cf, frame_data *fdata, void *criterion) +match_wide(capture_file *cf, frame_data *fdata, void *criterion) { cbs_t *info = criterion; const guint8 *ascii_text = info->data; @@ -3699,7 +3710,7 @@ cf_select_packet(capture_file *cf, int row) cf->edt = epan_dissect_new(TRUE, TRUE); tap_build_interesting(cf->edt); - epan_dissect_run(cf->edt, &cf->phdr, cf->pd, cf->current_frame, + epan_dissect_run(cf->edt, &cf->phdr, cf->pd, cf->current_frame, NULL); dfilter_macro_build_ftv_cache(cf->edt->tree); diff --git a/ui/gtk/find_dlg.c b/ui/gtk/find_dlg.c index e8085ed65c..b0c61a02dd 100644 --- a/ui/gtk/find_dlg.c +++ b/ui/gtk/find_dlg.c @@ -276,7 +276,7 @@ find_frame_cb(GtkWidget *w _U_, gpointer d _U_) gtk_widget_set_tooltip_text(case_cb, "Search by mixed upper/lower case?"); gtk_widget_show(case_cb); - combo_lb = gtk_label_new("Character set:"); + combo_lb = gtk_label_new("Character width:"); gtk_box_pack_start(GTK_BOX (string_opt_vb), combo_lb, TRUE, TRUE, 0); gtk_misc_set_alignment(GTK_MISC(combo_lb), 0.0f, 0.5f); gtk_widget_show(combo_lb); @@ -287,9 +287,10 @@ find_frame_cb(GtkWidget *w _U_, gpointer d _U_) combo_cb = gtk_combo_box_text_new(); - gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT(combo_cb), "ASCII Unicode & Non-Unicode"); - gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT(combo_cb), "ASCII Non-Unicode"); - gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT(combo_cb), "ASCII Unicode"); + gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT(combo_cb), "Narrow & wide"); + gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT(combo_cb), "Narrow (UTF-8 / ASCII)"); + /* UCS-2 might be more accurate but then we'd have to explain why we don't support UTF-16 */ + gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT(combo_cb), "Wide (UTF-16)"); gtk_combo_box_set_active(GTK_COMBO_BOX(combo_cb),0); gtk_box_pack_start(GTK_BOX (string_opt_vb), combo_cb, TRUE, TRUE, 0); @@ -545,7 +546,7 @@ find_frame_ok_cb(GtkWidget *ok_bt _U_, gpointer parent_w) GtkWidget *filter_te, *up_rb, *hex_rb, *string_rb, *combo_cb, *case_cb, *packet_data_rb, *decode_data_rb, *summary_data_rb; const gchar *filter_text; - search_charset_t scs_type = SCS_ASCII_AND_UNICODE; + search_charset_t scs_type = SCS_NARROW_AND_WIDE; guint8 *bytes = NULL; size_t nbytes = 0; char *string = NULL; @@ -570,9 +571,9 @@ find_frame_ok_cb(GtkWidget *ok_bt _U_, gpointer parent_w) /* Corresponds to the enum in file.c * Character set for text search. * typedef enum { - * SCS_ASCII_AND_UNICODE, - * SCS_ASCII, - * SCS_UNICODE + * SCS_NARROW_AND_WIDE, + * SCS_NARROW, + * SCS_WIDE * / * add EBCDIC when it's implemented * / * } search_charset_t; */ @@ -610,12 +611,12 @@ find_frame_ok_cb(GtkWidget *ok_bt _U_, gpointer parent_w) /* * We are - get the character set type. */ - if (string_type == SCS_ASCII_AND_UNICODE) - scs_type = SCS_ASCII_AND_UNICODE; - else if (string_type == SCS_ASCII) - scs_type = SCS_ASCII; - else if (string_type == SCS_UNICODE) - scs_type = SCS_UNICODE; + if (string_type == SCS_NARROW_AND_WIDE) + scs_type = SCS_NARROW_AND_WIDE; + else if (string_type == SCS_NARROW) + scs_type = SCS_NARROW; + else if (string_type == SCS_WIDE) + scs_type = SCS_WIDE; else { statusbar_push_temporary_msg("You didn't choose a valid character set."); return; diff --git a/ui/qt/CMakeLists.txt b/ui/qt/CMakeLists.txt index 09ccaf633a..76b8b484d4 100644 --- a/ui/qt/CMakeLists.txt +++ b/ui/qt/CMakeLists.txt @@ -52,6 +52,7 @@ set(QTSHARK_H_SRC proto_tree.h recent_file_status.h simple_dialog_qt.h + search_frame.h splash_overlay.h syntax_line_edit.h wireshark_application.h @@ -95,6 +96,7 @@ set(QTSHARK_CPP_SRC recent_file_status.cpp simple_dialog_qt.cpp sparkline_delegate.cpp + search_frame.cpp splash_overlay.cpp syntax_line_edit.cpp wireshark_application.cpp @@ -113,6 +115,7 @@ set(QTSHARK_UI packet_format_group_box.ui packet_range_group_box.ui print_dialog.ui + search_frame.ui splash_overlay.ui ) diff --git a/ui/qt/Makefile.am b/ui/qt/Makefile.am index f806a56cb5..b7c1e28a18 100644 --- a/ui/qt/Makefile.am +++ b/ui/qt/Makefile.am @@ -116,6 +116,11 @@ print_dialog.h: ui_print_dialog.h ui_print_dialog.h: print_dialog.ui uic $< -o $@ +search_frame.h: ui_search_frame.h + +ui_search_frame.h: search_frame.ui + uic $< -o $@ + splash_overlay.h: ui_splash_overlay.h ui_splash_overlay.h: splash_overlay.ui @@ -183,6 +188,7 @@ EXTRA_DIST = \ packet_range_group_box.ui \ print_dialog.ui \ QtShark.pro \ + search_frame.ui \ splash_overlay.ui \ display_filter_16.svg \ gpl-template.txt diff --git a/ui/qt/Makefile.common b/ui/qt/Makefile.common index 148c5361b7..fa268d090d 100644 --- a/ui/qt/Makefile.common +++ b/ui/qt/Makefile.common @@ -39,6 +39,7 @@ GENERATED_NODIST_HEADER_FILES = \ ui_packet_format_group_box.h \ ui_packet_range_group_box.h \ ui_print_dialog.h \ + ui_search_frame.h ui_splash_overlay.h # Generated C source files that we want in the distribution. @@ -103,6 +104,7 @@ MOC_HDRS = \ recent_file_status.h \ simple_dialog_qt.h \ sparkline_delegate.h \ + search_frame.h \ splash_overlay.h \ syntax_line_edit.h \ wireshark_application.h @@ -182,6 +184,7 @@ WIRESHARK_QT_SRC = \ recent_file_status.cpp \ simple_dialog_qt.cpp \ sparkline_delegate.cpp \ + search_frame.cpp \ splash_overlay.cpp \ syntax_line_edit.cpp \ wireshark_application.cpp diff --git a/ui/qt/QtShark.pro b/ui/qt/QtShark.pro index 6ad7729be7..afa1f9692d 100644 --- a/ui/qt/QtShark.pro +++ b/ui/qt/QtShark.pro @@ -187,7 +187,8 @@ FORMS += main_window.ui \ packet_format_group_box.ui \ export_object_dialog.ui \ print_dialog.ui \ - splash_overlay.ui + splash_overlay.ui \ + search_frame.ui win32 { ## These should be in config.pri ?? !isEmpty(PORTAUDIO_DIR) { @@ -215,7 +216,8 @@ HEADERS += $$HEADERS_WS_C \ packet_format_group_box.h \ export_object_dialog.h \ print_dialog.h \ - splash_overlay.h + splash_overlay.h \ + search_frame.h win32 { OBJECTS_WS_C = $$SOURCES_WS_C @@ -427,4 +429,5 @@ SOURCES += \ sparkline_delegate.cpp \ splash_overlay.cpp \ syntax_line_edit.cpp \ - wireshark_application.cpp + wireshark_application.cpp \ + search_frame.cpp diff --git a/ui/qt/display_filter_edit.cpp b/ui/qt/display_filter_edit.cpp index ae13d6dc9a..3afd543f38 100644 --- a/ui/qt/display_filter_edit.cpp +++ b/ui/qt/display_filter_edit.cpp @@ -23,8 +23,6 @@ #include "config.h" -#include "globals.h" - #include <glib.h> #include <epan/proto.h> @@ -268,7 +266,7 @@ void DisplayFilterEdit::checkFilter(const QString& text) if (dfp != NULL) { depr = dfilter_deprecated_tokens(dfp); } - if (text.length() < 1) { + if (text.isEmpty()) { setSyntaxState(Empty); } else if (depr) { /* You keep using that word. I do not think it means what you think it means. */ diff --git a/ui/qt/display_filter_edit.h b/ui/qt/display_filter_edit.h index efe69e28b0..e43c91b5d5 100644 --- a/ui/qt/display_filter_edit.h +++ b/ui/qt/display_filter_edit.h @@ -61,8 +61,6 @@ signals: void pushFilterSyntaxWarning(QString&); void filterPackets(QString& new_filter, bool force); -public slots: - }; #endif // DISPLAYFILTEREDIT_H diff --git a/ui/qt/label_stack.cpp b/ui/qt/label_stack.cpp index 142d097716..8480a3eb5e 100644 --- a/ui/qt/label_stack.cpp +++ b/ui/qt/label_stack.cpp @@ -79,16 +79,19 @@ void LabelStack::fillLabel() { void LabelStack::pushText(QString &text, int ctx) { StackItem *si = new StackItem; - si->text = text; - si->ctx = ctx; - labels_.prepend(si); if (ctx == temporary_ctx_) { + temporary_timer_.stop(); + popText(temporary_ctx_); + temporary_epoch_.start(); temporary_timer_.start(temporary_flash_timeout_); emit toggleTemporaryFlash(true); } + si->text = text; + si->ctx = ctx; + labels_.prepend(si); fillLabel(); } diff --git a/ui/qt/main_status_bar.cpp b/ui/qt/main_status_bar.cpp index 894c2ccb51..deaa1829af 100644 --- a/ui/qt/main_status_bar.cpp +++ b/ui/qt/main_status_bar.cpp @@ -64,19 +64,15 @@ void statusbar_push_temporary_msg(const gchar *msg_format, ...) { va_list ap; - gchar *msg; - QString pushMsg; + QString push_msg; if (!cur_main_status_bar_) return; va_start(ap, msg_format); - msg = g_strdup_vprintf(msg_format, ap); + push_msg.vsprintf(msg_format, ap); va_end(ap); - pushMsg.fromUtf8(msg); - g_free(msg); - - cur_main_status_bar_->pushTemporaryStatus(pushMsg); + cur_main_status_bar_->pushTemporaryStatus(push_msg); } /* diff --git a/ui/qt/main_window.cpp b/ui/qt/main_window.cpp index 6101e52fe8..eec9f720ff 100644 --- a/ui/qt/main_window.cpp +++ b/ui/qt/main_window.cpp @@ -81,8 +81,6 @@ MainWindow::MainWindow(QWidget *parent) : pipe_notifier_(NULL) #endif { - QMargins go_to_margins; - gbl_cur_main_window = this; main_ui_->setupUi(this); setMenusForCaptureFile(); @@ -116,24 +114,26 @@ MainWindow::MainWindow(QWidget *parent) : // This property is obsolete in Qt5 so this issue may be fixed in that version. main_ui_->displayFilterToolBar->addWidget(df_combo_box_); - main_ui_->goToFrame->hide(); - go_to_margins = main_ui_->goToHB->contentsMargins(); -// go_to_margins.setTop(0); -// go_to_margins.setBottom(0); - main_ui_->goToHB->setContentsMargins(go_to_margins); - // XXX For some reason the cursor is drawn funny with an input mask set - // https://bugreports.qt-project.org/browse/QTBUG-7174 - main_ui_->goToFrame->setStyleSheet( - "QFrame {" + QString subframe_style( + ".QFrame {" " background: palette(window);" " padding-top: 0.1em;" " padding-bottom: 0.1em;" " border-bottom: 1px solid palette(shadow);" "}" - "QLineEdit {" + "QLineEdit#goToLineEdit {" " max-width: 5em;" "}" ); + main_ui_->goToFrame->hide(); + // XXX For some reason the cursor is drawn funny with an input mask set + // https://bugreports.qt-project.org/browse/QTBUG-7174 + main_ui_->goToFrame->setStyleSheet(subframe_style); + + main_ui_->searchFrame->hide(); + main_ui_->searchFrame->setStyleSheet(subframe_style); + connect(main_ui_->searchFrame, SIGNAL(pushFilterSyntaxStatus(QString&)), + main_ui_->statusBar, SLOT(pushTemporaryStatus(QString&))); #if defined(Q_WS_MAC) foreach (QMenu *menu, main_ui_->menuBar->findChildren<QMenu*>()) { @@ -206,6 +206,8 @@ MainWindow::MainWindow(QWidget *parent) : this, SLOT(openCaptureFile(QString&))); connect(this, SIGNAL(setCaptureFile(capture_file*)), + main_ui_->searchFrame, SLOT(setCaptureFile(capture_file*))); + connect(this, SIGNAL(setCaptureFile(capture_file*)), main_ui_->statusBar, SLOT(setCaptureFile(capture_file*))); connect(this, SIGNAL(setCaptureFile(capture_file*)), packet_list_, SLOT(setCaptureFile(capture_file*))); @@ -1208,12 +1210,9 @@ void MainWindow::setForCapturedPackets(bool have_captured_packets) // set_menu_sensitivity(ui_manager_packet_list_menu, "/PacketListMenuPopup/Print", // have_captured_packets); -// set_menu_sensitivity(ui_manager_main_menubar, "/Menubar/EditMenu/FindPacket", -// have_captured_packets); -// set_menu_sensitivity(ui_manager_main_menubar, "/Menubar/EditMenu/FindNext", -// have_captured_packets); -// set_menu_sensitivity(ui_manager_main_menubar, "/Menubar/EditMenu/FindPrevious", -// have_captured_packets); + main_ui_->actionEditFindPacket->setEnabled(have_captured_packets); + main_ui_->actionEditFindNext->setEnabled(have_captured_packets); + main_ui_->actionEditFindPrevious->setEnabled(have_captured_packets); // set_menu_sensitivity(ui_manager_main_menubar, "/Menubar/ViewMenu/ZoomIn", // have_captured_packets); // set_menu_sensitivity(ui_manager_main_menubar, "/Menubar/ViewMenu/ZoomOut", diff --git a/ui/qt/main_window.h b/ui/qt/main_window.h index 0dba4513df..e7c8bb52c0 100644 --- a/ui/qt/main_window.h +++ b/ui/qt/main_window.h @@ -200,6 +200,9 @@ private slots: void on_actionEditCopyFieldName_triggered(); void on_actionEditCopyValue_triggered(); void on_actionEditCopyAsFilter_triggered(); + void on_actionEditFindPacket_triggered(); + void on_actionEditFindNext_triggered(); + void on_actionEditFindPrevious_triggered(); void on_actionGoGoToPacket_triggered(); void resetPreviousFocus(); diff --git a/ui/qt/main_window.ui b/ui/qt/main_window.ui index ab8d9c364e..5c40f891d0 100644 --- a/ui/qt/main_window.ui +++ b/ui/qt/main_window.ui @@ -77,6 +77,9 @@ </widget> </item> <item row="1" column="0"> + <widget class="SearchFrame" name="searchFrame" native="true"/> + </item> + <item row="2" column="0"> <widget class="QStackedWidget" name="mainStack"> <widget class="MainWelcome" name="welcomePage"/> <widget class="QWidget" name="packetPage"/> @@ -166,6 +169,9 @@ <addaction name="actionEditCopyAsFilter"/> </widget> <addaction name="menuEditCopy"/> + <addaction name="actionEditFindPacket"/> + <addaction name="actionEditFindNext"/> + <addaction name="actionEditFindPrevious"/> </widget> <widget class="QMenu" name="menuCapture"> <property name="title"> @@ -928,6 +934,39 @@ <string>Apply as Column</string> </property> </action> + <action name="actionEditFindPacket"> + <property name="text"> + <string>&Find Packet...</string> + </property> + <property name="toolTip"> + <string>Find a packet</string> + </property> + <property name="shortcut"> + <string>Ctrl+F</string> + </property> + </action> + <action name="actionEditFindNext"> + <property name="text"> + <string>Find Ne&xt...</string> + </property> + <property name="toolTip"> + <string>Find the next packet</string> + </property> + <property name="shortcut"> + <string>Ctrl+N</string> + </property> + </action> + <action name="actionEditFindPrevious"> + <property name="text"> + <string>Find Pre&vious...</string> + </property> + <property name="toolTip"> + <string>Find the previous packet</string> + </property> + <property name="shortcut"> + <string>Ctrl+B</string> + </property> + </action> </widget> <layoutdefault spacing="6" margin="11"/> <customwidgets> @@ -942,6 +981,11 @@ <header>main_welcome.h</header> <container>1</container> </customwidget> + <customwidget> + <class>SearchFrame</class> + <extends>QWidget</extends> + <header>search_frame.h</header> + </customwidget> </customwidgets> <resources> <include location="../../image/toolbar.qrc"/> diff --git a/ui/qt/main_window_slots.cpp b/ui/qt/main_window_slots.cpp index bc221b133e..aca621c743 100644 --- a/ui/qt/main_window_slots.cpp +++ b/ui/qt/main_window_slots.cpp @@ -320,6 +320,7 @@ void MainWindow::captureFileClosing(const capture_file *cf) { // Reset expert info indicator main_ui_->statusBar->hideExpert(); + main_ui_->searchFrame->hide(); // gtk_widget_show(expert_info_none); emit setCaptureFile(NULL); } @@ -945,6 +946,31 @@ void MainWindow::on_actionEditCopyAsFilter_triggered() matchSelectedFilter(MatchSelectedReplace, false, true); } +void MainWindow::on_actionEditFindPacket_triggered() +{ + if (packet_list_->model()->rowCount() < 1) { + return; + } + previous_focus_ = wsApp->focusWidget(); + connect(previous_focus_, SIGNAL(destroyed()), this, SLOT(resetPreviousFocus())); + main_ui_->goToFrame->hide(); + if (main_ui_->searchFrame->isVisible()) { + main_ui_->searchFrame->hide(); + } else { + main_ui_->searchFrame->show(); + } +} + +void MainWindow::on_actionEditFindNext_triggered() +{ + main_ui_->searchFrame->findNext(); +} + +void MainWindow::on_actionEditFindPrevious_triggered() +{ + main_ui_->searchFrame->findPrevious(); +} + // View Menu // Expand / collapse slots in proto_tree @@ -1172,7 +1198,13 @@ void MainWindow::on_actionGoGoToPacket_triggered() { } previous_focus_ = wsApp->focusWidget(); connect(previous_focus_, SIGNAL(destroyed()), this, SLOT(resetPreviousFocus())); - main_ui_->goToFrame->show(); + + main_ui_->searchFrame->hide(); + if (main_ui_->goToFrame->isVisible()) { + main_ui_->goToFrame->hide(); + } else { + main_ui_->goToFrame->show(); + } main_ui_->goToLineEdit->setFocus(); } diff --git a/ui/qt/search_frame.cpp b/ui/qt/search_frame.cpp new file mode 100644 index 0000000000..a2b9e138ea --- /dev/null +++ b/ui/qt/search_frame.cpp @@ -0,0 +1,373 @@ +/* search_frame.cpp + * + * $Id: splash_overlay.cpp 45941 2012-11-05 22:43:15Z gerald $ + * + * 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. + */ + +#include "search_frame.h" +#include "ui_search_frame.h" + +#include <epan/proto.h> +#include <epan/strutil.h> + +#include "wireshark_application.h" +#include <QKeyEvent> +#include <QCheckBox> + +const int in_packet_list = 0; +const int in_proto_tree = 1; +const int in_bytes = 2; + +const int df_search = 0; +const int hex_search = 1; +const int string_search = 2; + +const int narrow_and_wide_chars = 0; +const int narrow_chars = 1; +const int wide_chars = 2; + +SearchFrame::SearchFrame(QWidget *parent) : + QFrame(parent), + sf_ui_(new Ui::SearchFrame), + cap_file_(NULL) +{ + sf_ui_->setupUi(this); + +#ifdef Q_WS_MAC + foreach (QWidget *w, findChildren<QWidget *>()) { + w->setAttribute(Qt::WA_MacSmallSize, true); + } +#endif + sf_ui_->searchTypeComboBox->setCurrentIndex(0); + enableWidgets(); +} + +SearchFrame::~SearchFrame() +{ + delete sf_ui_; +} + +void SearchFrame::show() +{ + sf_ui_->searchLineEdit->setFocus(); + QFrame::show(); +} + +void SearchFrame::findNext() +{ + if (!cap_file_) return; + + cap_file_->dir = SD_FORWARD; + if (isHidden()) { + show(); + return; + } + on_findButton_clicked(); +} + +void SearchFrame::findPrevious() +{ + if (!cap_file_) return; + + cap_file_->dir = SD_BACKWARD; + if (isHidden()) { + show(); + return; + } + on_findButton_clicked(); +} + +void SearchFrame::setCaptureFile(capture_file *cf) +{ + cap_file_ = cf; + if (!cf && isVisible()) { + hide(); + } + enableWidgets(); +} + +void SearchFrame::findFrameWithFilter(QString &filter) +{ + show(); + sf_ui_->searchLineEdit->setText(filter); + sf_ui_->searchTypeComboBox->setCurrentIndex(0); + enableWidgets(); +} + +void SearchFrame::keyPressEvent(QKeyEvent *event) +{ + if (wsApp->focusWidget() == sf_ui_->searchLineEdit) { + if (event->modifiers() == Qt::NoModifier) { + if (event->key() == Qt::Key_Escape) { + on_cancelButton_clicked(); + } else if (event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return) { + on_findButton_clicked(); + } + } + return; // searchLineEdit didn't want it and we don't either. + } +} + +void SearchFrame::enableWidgets() +{ + if (cap_file_) { + setEnabled(true); + } else { + setEnabled(false); + return; + } + + dfilter_t *dfp = NULL; + bool enable = sf_ui_->searchTypeComboBox->currentIndex() == string_search; + sf_ui_->searchInComboBox->setEnabled(enable); + sf_ui_->caseCheckBox->setEnabled(enable); + sf_ui_->charEncodingComboBox->setEnabled(enable); + + switch (sf_ui_->searchTypeComboBox->currentIndex()) { + case df_search: + // XXX - Merge this with DisplayFitlerEdit::checkFilter + if (dfilter_compile(sf_ui_->searchLineEdit->text().toUtf8().constData(), &dfp)) { + GPtrArray *depr = NULL; + if (dfp != NULL) { + depr = dfilter_deprecated_tokens(dfp); + } + if (sf_ui_->searchLineEdit->text().isEmpty()) { + sf_ui_->searchLineEdit->setSyntaxState(SyntaxLineEdit::Empty); + } else if (depr) { + /* You keep using that word. I do not think it means what you think it means. */ + sf_ui_->searchLineEdit->setSyntaxState(SyntaxLineEdit::Deprecated); + } else { + sf_ui_->searchLineEdit->setSyntaxState(SyntaxLineEdit::Valid); + } + dfilter_free(dfp); + } else { + sf_ui_->searchLineEdit->setSyntaxState(SyntaxLineEdit::Invalid); + } + break; + case hex_search: + if (sf_ui_->searchLineEdit->text().isEmpty()) { + sf_ui_->searchLineEdit->setSyntaxState(SyntaxLineEdit::Invalid); + } else { + guint8 *bytes = NULL; + size_t nbytes; + bytes = convert_string_to_hex(sf_ui_->searchLineEdit->text().toUtf8().constData(), &nbytes); + if (bytes == NULL) + sf_ui_->searchLineEdit->setSyntaxState(SyntaxLineEdit::Invalid); + else { + g_free(bytes); + sf_ui_->searchLineEdit->setSyntaxState(SyntaxLineEdit::Valid); + } + } + break; + case string_search: + if (sf_ui_->searchLineEdit->text().isEmpty()) { + sf_ui_->searchLineEdit->setSyntaxState(SyntaxLineEdit::Invalid); + } else { + sf_ui_->searchLineEdit->setSyntaxState(SyntaxLineEdit::Valid); + } + break; + default: + QString err_string = tr("No valid search type selected. Please report this to the development team."); + emit pushFilterSyntaxStatus(err_string); + return; + } + + if (sf_ui_->searchLineEdit->text().isEmpty() || sf_ui_->searchLineEdit->syntaxState() == SyntaxLineEdit::Invalid) { + sf_ui_->findButton->setEnabled(false); + } else { + sf_ui_->findButton->setEnabled(true); + } +} + +void SearchFrame::on_searchTypeComboBox_currentIndexChanged(int index) +{ + Q_UNUSED(index); + enableWidgets(); +} + +void SearchFrame::on_searchLineEdit_textChanged(const QString &search_string) +{ + Q_UNUSED(search_string); + enableWidgets(); +} + +void SearchFrame::on_findButton_clicked() +{ + guint8 *bytes = NULL; + size_t nbytes; + char *string = NULL; + dfilter_t *dfp; + gboolean found_packet = FALSE; + QString err_string; + + if (!cap_file_) { + return; + } + + cap_file_->hex = FALSE; + cap_file_->string = FALSE; + cap_file_->case_type = FALSE; + cap_file_->packet_data = FALSE; + cap_file_->decode_data = FALSE; + cap_file_->summary_data = FALSE; + cap_file_->scs_type = SCS_NARROW_AND_WIDE; + + switch (sf_ui_->searchTypeComboBox->currentIndex()) { + case df_search: + if (!dfilter_compile(sf_ui_->searchLineEdit->text().toUtf8().constData(), &dfp)) { + err_string = tr("Invalid filter."); + emit pushFilterSyntaxStatus(err_string); + return; + } + + if (dfp == NULL) { + err_string = tr("That filter doesn't test anything."); + emit pushFilterSyntaxStatus(err_string); + return; + } + break; + case hex_search: + bytes = convert_string_to_hex(sf_ui_->searchLineEdit->text().toUtf8().constData(), &nbytes); + if (bytes == NULL) { + err_string = tr("That's not a valid hex string."); + emit pushFilterSyntaxStatus(err_string); + return; + } + cap_file_->hex = TRUE; + break; + case string_search: + if (sf_ui_->searchLineEdit->text().isEmpty()) { + err_string = tr("You didn't specify any text for which to search."); + emit pushFilterSyntaxStatus(err_string); + return; + } + cap_file_->string = TRUE; + cap_file_->case_type = sf_ui_->caseCheckBox->isChecked() ? FALSE : TRUE; + switch (sf_ui_->charEncodingComboBox->currentIndex()) { + case narrow_and_wide_chars: + cap_file_->scs_type = SCS_NARROW_AND_WIDE; + break; + case narrow_chars: + cap_file_->scs_type = SCS_NARROW; + break; + case wide_chars: + cap_file_->scs_type = SCS_WIDE; + break; + default: + err_string = tr("No valid character set selected. Please report this to the development team."); + emit pushFilterSyntaxStatus(err_string); + return; + } + string = convert_string_case(sf_ui_->searchLineEdit->text().toUtf8().constData(), cap_file_->case_type); + break; + default: + err_string = tr("No valid search type selected. Please report this to the development team."); + emit pushFilterSyntaxStatus(err_string); + return; + } + + switch (sf_ui_->searchInComboBox->currentIndex()) { + case in_packet_list: + cap_file_->summary_data = TRUE; + break; + case in_proto_tree: + cap_file_->decode_data = TRUE; + break; + case in_bytes: + cap_file_->packet_data = TRUE; + break; + default: + err_string = tr("No valid search area selected. Please report this to the development team."); + emit pushFilterSyntaxStatus(err_string); + return; + } + + g_free(cap_file_->sfilter); + cap_file_->sfilter = g_strdup(sf_ui_->searchLineEdit->text().toUtf8().constData()); + + if (cap_file_->hex) { + /* Hex value in packet data */ + found_packet = cf_find_packet_data(cap_file_, bytes, nbytes, cap_file_->dir); + g_free(bytes); + if (!found_packet) { + /* We didn't find a packet */ + err_string = tr("No packet contained those bytes."); + emit pushFilterSyntaxStatus(err_string); + return; + } + } else if (cap_file_->string) { + if (cap_file_->summary_data) { + /* String in the Info column of the summary line */ + found_packet = cf_find_packet_summary_line(cap_file_, string, cap_file_->dir); + g_free(string); + if (!found_packet) { + err_string = tr("No packet contained that string in its Info column."); + emit pushFilterSyntaxStatus(err_string); + return; + } + } else if (cap_file_->decode_data) { + /* String in the protocol tree headings */ + found_packet = cf_find_packet_protocol_tree(cap_file_, string, cap_file_->dir); + g_free(string); + if (!found_packet) { + err_string = tr("No packet contained that string in its dissected display."); + emit pushFilterSyntaxStatus(err_string); + return; + } + } else if (cap_file_->packet_data && string) { + /* String in the ASCII-converted packet data */ + found_packet = cf_find_packet_data(cap_file_, (guint8 *) string, strlen(string), cap_file_->dir); + g_free(string); + if (!found_packet) { + err_string = tr("No packet contained that string in its converted data."); + emit pushFilterSyntaxStatus(err_string); + return; + } + } + } else { + /* Search via display filter */ + found_packet = cf_find_packet_dfilter(cap_file_, dfp, cap_file_->dir); + dfilter_free(dfp); + if (!found_packet) { + err_string = tr("No packet matched that filter."); + emit pushFilterSyntaxStatus(err_string); + g_free(bytes); + return; + } + } +} + +void SearchFrame::on_cancelButton_clicked() +{ + hide(); +} + +/* + * Editor modelines + * + * Local Variables: + * c-basic-offset: 4 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * ex: set shiftwidth=4 tabstop=8 expandtab: + * :indentSize=4:tabSize=8:noTabs=true: + */ diff --git a/ui/qt/search_frame.h b/ui/qt/search_frame.h new file mode 100644 index 0000000000..c7297250da --- /dev/null +++ b/ui/qt/search_frame.h @@ -0,0 +1,74 @@ +/* search_frame.h + * + * $Id: splash_overlay.cpp 45941 2012-11-05 22:43:15Z gerald $ + * + * 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. + */ + +#ifndef SEARCH_FRAME_H +#define SEARCH_FRAME_H + +#include <config.h> + +#include <QFrame> + +#include "cfile.h" + +namespace Ui { +class SearchFrame; +} + +class SearchFrame : public QFrame +{ + Q_OBJECT + +public: + explicit SearchFrame(QWidget *parent = 0); + ~SearchFrame(); + void show(); + void findNext(); + void findPrevious(); + +public slots: + void setCaptureFile(capture_file *cf); + void findFrameWithFilter(QString &filter); + +signals: + void pushFilterSyntaxStatus(QString&); + +protected: + void keyPressEvent(QKeyEvent *event); + +private: + void enableWidgets(); + + Ui::SearchFrame *sf_ui_; + capture_file *cap_file_; + +private slots: + void on_searchTypeComboBox_currentIndexChanged(int index); + + void on_searchLineEdit_textChanged(const QString &search_string); + + void on_findButton_clicked(); + + void on_cancelButton_clicked(); +}; + +#endif // SEARCH_FRAME_H diff --git a/ui/qt/search_frame.ui b/ui/qt/search_frame.ui new file mode 100644 index 0000000000..d82c62a6c3 --- /dev/null +++ b/ui/qt/search_frame.ui @@ -0,0 +1,166 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>SearchFrame</class> + <widget class="QFrame" name="SearchFrame"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>1026</width> + <height>30</height> + </rect> + </property> + <property name="windowTitle"> + <string>Frame</string> + </property> + <property name="frameShape"> + <enum>QFrame::NoFrame</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Plain</enum> + </property> + <property name="lineWidth"> + <number>0</number> + </property> + <layout class="QHBoxLayout" name="horizontalLayout"> + <property name="topMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item> + <widget class="QComboBox" name="searchInComboBox"> + <property name="toolTip"> + <string><html><head/><body><p>Search the Info column of the packet list (summary pane), decoded packet display labels (tree view pane) or the ASCII-converted packet data (hex view pane).</p></body></html></string> + </property> + <item> + <property name="text"> + <string>Packet list</string> + </property> + </item> + <item> + <property name="text"> + <string>Packet details</string> + </property> + </item> + <item> + <property name="text"> + <string>Packet bytes</string> + </property> + </item> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_2"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>5</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QComboBox" name="charEncodingComboBox"> + <property name="toolTip"> + <string><html><head/><body><p>Search for strings containing narrow (UTF-8 and ASCII) or wide (UTF-16) characters.</p></body></html></string> + </property> + <item> + <property name="text"> + <string>Narrow & Wide</string> + </property> + </item> + <item> + <property name="text"> + <string>Narrow (UTF-8 / ASCII)</string> + </property> + </item> + <item> + <property name="text"> + <string>Wide (UTF-16)</string> + </property> + </item> + </widget> + </item> + <item> + <widget class="QCheckBox" name="caseCheckBox"> + <property name="text"> + <string>Case sensitive</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>5</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QComboBox" name="searchTypeComboBox"> + <property name="toolTip"> + <string><html><head/><body><p>Search for data using display filter syntax (e.g. ip.addr==10.1.1.1), a hexadecimal string (e.g. fffffda5) or a plain string (e.g. My String).</p></body></html></string> + </property> + <item> + <property name="text"> + <string>Display filter</string> + </property> + </item> + <item> + <property name="text"> + <string>Hex value</string> + </property> + </item> + <item> + <property name="text"> + <string>String</string> + </property> + </item> + </widget> + </item> + <item> + <widget class="SyntaxLineEdit" name="searchLineEdit"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>1</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + </widget> + </item> + <item> + <widget class="QToolButton" name="findButton"> + <property name="text"> + <string>Find</string> + </property> + </widget> + </item> + <item> + <widget class="QToolButton" name="cancelButton"> + <property name="text"> + <string>Cancel</string> + </property> + </widget> + </item> + </layout> + </widget> + <customwidgets> + <customwidget> + <class>SyntaxLineEdit</class> + <extends>QLineEdit</extends> + <header>syntax_line_edit.h</header> + </customwidget> + </customwidgets> + <resources/> + <connections/> +</ui> |