From 211cd04459abe318e384a227393c14f674058602 Mon Sep 17 00:00:00 2001 From: Martin Vidner Date: Wed, 19 May 2021 15:25:02 +0200 Subject: [PATCH 1/4] When finding table items by cell value, ignore BiDi control chars (bsc#1128091) --- libyui-rest-api/src/CMakeLists.txt | 1 + libyui-rest-api/src/YTableActionHandler.cc | 2 +- libyui-rest-api/src/YWidgetActionHandler.cc | 42 +++++++++++++++++++++ libyui-rest-api/src/YWidgetActionHandler.h | 5 +++ 4 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 libyui-rest-api/src/YWidgetActionHandler.cc diff --git a/libyui-rest-api/src/CMakeLists.txt b/libyui-rest-api/src/CMakeLists.txt index 20162a1bd..30281b34f 100644 --- a/libyui-rest-api/src/CMakeLists.txt +++ b/libyui-rest-api/src/CMakeLists.txt @@ -45,6 +45,7 @@ set( SOURCES YJsonSerializer.cc YMenuWidgetActionHandler.cc YTableActionHandler.cc + YWidgetActionHandler.cc YWidgetFinder.cc ) diff --git a/libyui-rest-api/src/YTableActionHandler.cc b/libyui-rest-api/src/YTableActionHandler.cc index 80bcdf849..163439e3b 100644 --- a/libyui-rest-api/src/YTableActionHandler.cc +++ b/libyui-rest-api/src/YTableActionHandler.cc @@ -90,7 +90,7 @@ YTableActionHandler::table_findItem( std::vector::const_iterator pa if ( ! item ) return nullptr; - if ( item->label(column_id) == *path_begin ) + if ( normalize_label ( item->label(column_id) ) == *path_begin ) { if ( std::next( path_begin ) == path_end ) return item; diff --git a/libyui-rest-api/src/YWidgetActionHandler.cc b/libyui-rest-api/src/YWidgetActionHandler.cc new file mode 100644 index 000000000..7ad6023ff --- /dev/null +++ b/libyui-rest-api/src/YWidgetActionHandler.cc @@ -0,0 +1,42 @@ +/* + Copyright (C) 2021 SUSE LLC + + This library is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) version 3.0 of the License. This library + 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 Lesser General Public + License for more details. You should have received a copy of the GNU + Lesser General Public License along with this library; if not, write + to the Free Software Foundation, Inc., 51 Franklin Street, Fifth + Floor, Boston, MA 02110-1301 USA +*/ + +#include +#include + +#include "YWidgetActionHandler.h" + +static +std::string normalize_label_bidi(const std::string& label) +{ + static std::wstring_convert> conv; + + //static const std::wstring bidi_controls(L"\u202a\u202b\u202c\u202d\u202e\u2066\u2067\u2068\u2069"); + static wchar_t bidi_controls[] { L'\u202a', L'\u202b', L'\u202c', L'\u202d', L'\u202e', L'\u2066', L'\u2067', L'\u2068', L'\u2069' }; + + std::wstring wlabel(conv.from_bytes(label)); + wlabel.erase(boost::remove_if(wlabel, boost::is_any_of(bidi_controls)), wlabel.end()); + std::string cleaned(conv.to_bytes(wlabel)); + + return cleaned; +} + + +std::string YWidgetActionHandler::normalize_label(const std::string & label) +{ + // FIXME: also ampersand + return normalize_label_bidi(label); +} \ No newline at end of file diff --git a/libyui-rest-api/src/YWidgetActionHandler.h b/libyui-rest-api/src/YWidgetActionHandler.h index 0aba85000..1597c9f28 100644 --- a/libyui-rest-api/src/YWidgetActionHandler.h +++ b/libyui-rest-api/src/YWidgetActionHandler.h @@ -111,6 +111,11 @@ class YWidgetActionHandler } }; } + + // Normalize a label before comparing it for equality: + // - remove shortcut characters (&) + // - remove BiDi control characters (added to certain table cells to render pathnames correctly) + static std::string normalize_label(const std::string & label); }; #endif //YWidgetActionHandler_h From 6b80836e699f4854f9505a8ea8d19455fcca436d Mon Sep 17 00:00:00 2001 From: Martin Vidner Date: Fri, 4 Jun 2021 09:47:09 +0200 Subject: [PATCH 2/4] Unify ampersand and BiDi normalization (bsc#1128091, bsc#1139747) --- libyui-rest-api/src/YDumbTabActionHandler.cc | 4 ++-- libyui-rest-api/src/YMenuWidgetActionHandler.cc | 2 +- libyui-rest-api/src/YMenuWidgetActionHandler.h | 2 +- libyui-rest-api/src/YWidgetActionHandler.cc | 8 ++++++-- libyui-rest-api/src/YWidgetActionHandler.h | 8 ++++++++ libyui-rest-api/src/YWidgetFinder.cc | 5 ++--- libyui-rest-api/src/YWidgetFinder.h | 2 -- 7 files changed, 20 insertions(+), 11 deletions(-) diff --git a/libyui-rest-api/src/YDumbTabActionHandler.cc b/libyui-rest-api/src/YDumbTabActionHandler.cc index ecae0c87d..7a4417168 100644 --- a/libyui-rest-api/src/YDumbTabActionHandler.cc +++ b/libyui-rest-api/src/YDumbTabActionHandler.cc @@ -49,12 +49,12 @@ YDumbTabActionHandler::findItem( const std::string &item_label, YItemConstIterator begin, YItemConstIterator end ) const { - std::string item_label_sanitized = boost::erase_all_copy(item_label, ShortcutChar); + std::string item_label_sanitized = normalize_label(item_label); for ( YItemConstIterator it = begin; it != end; ++it ) { YItem * item = *it; - if ( boost::erase_all_copy(item->label(), ShortcutChar) == item_label_sanitized ) + if ( normalize_label(item->label()) == item_label_sanitized ) { return item; } diff --git a/libyui-rest-api/src/YMenuWidgetActionHandler.cc b/libyui-rest-api/src/YMenuWidgetActionHandler.cc index 9034bf60b..29103e8d1 100644 --- a/libyui-rest-api/src/YMenuWidgetActionHandler.cc +++ b/libyui-rest-api/src/YMenuWidgetActionHandler.cc @@ -34,7 +34,7 @@ YMenuWidgetActionHandler::findItem( std::vector::iterator path_begi if ( !item ) return nullptr; - if ( boost::erase_all_copy( item->label(), ShortcutChar ) == *path_begin ) + if ( normalize_label( item->label() ) == *path_begin ) { if ( std::next( path_begin ) == path_end ) { diff --git a/libyui-rest-api/src/YMenuWidgetActionHandler.h b/libyui-rest-api/src/YMenuWidgetActionHandler.h index c61422945..1ed4e2f10 100644 --- a/libyui-rest-api/src/YMenuWidgetActionHandler.h +++ b/libyui-rest-api/src/YMenuWidgetActionHandler.h @@ -30,7 +30,7 @@ class YMenuWidgetActionHandler : public YWidgetActionHandler template std::function get_handler( T *widget, const std::string &value ) { return [&] ( T *menu_selector ) { - std::string value_sanitized = boost::erase_all_copy( value, ShortcutChar ); + std::string value_sanitized = normalize_label( value ); // Vector of string to store path to the tree item std::vector path; boost::split( path, value_sanitized, boost::is_any_of( TreePathDelimiter ) ); diff --git a/libyui-rest-api/src/YWidgetActionHandler.cc b/libyui-rest-api/src/YWidgetActionHandler.cc index 7ad6023ff..6f6ca7304 100644 --- a/libyui-rest-api/src/YWidgetActionHandler.cc +++ b/libyui-rest-api/src/YWidgetActionHandler.cc @@ -34,9 +34,13 @@ std::string normalize_label_bidi(const std::string& label) return cleaned; } +static +std::string normalize_label_shortcut(const std::string& label) +{ + return boost::erase_all_copy(label, ShortcutChar); +} std::string YWidgetActionHandler::normalize_label(const std::string & label) { - // FIXME: also ampersand - return normalize_label_bidi(label); + return normalize_label_shortcut(normalize_label_bidi(label)); } \ No newline at end of file diff --git a/libyui-rest-api/src/YWidgetActionHandler.h b/libyui-rest-api/src/YWidgetActionHandler.h index 1597c9f28..c5626d8c4 100644 --- a/libyui-rest-api/src/YWidgetActionHandler.h +++ b/libyui-rest-api/src/YWidgetActionHandler.h @@ -116,6 +116,14 @@ class YWidgetActionHandler // - remove shortcut characters (&) // - remove BiDi control characters (added to certain table cells to render pathnames correctly) static std::string normalize_label(const std::string & label); + + // Apply normalize_label to both arguments and compare the result with ==. + static bool normalized_labels_equal(const std::string & a, const std::string & b) + { + std::string na = normalize_label(a); + std::string nb = normalize_label(b); + return na == nb; + } }; #endif //YWidgetActionHandler_h diff --git a/libyui-rest-api/src/YWidgetFinder.cc b/libyui-rest-api/src/YWidgetFinder.cc index 9a873c9ca..7bef0363b 100644 --- a/libyui-rest-api/src/YWidgetFinder.cc +++ b/libyui-rest-api/src/YWidgetFinder.cc @@ -23,6 +23,7 @@ #include #include "YWidgetFinder.h" +#include "YWidgetActionHandler.h" // internal helper methods @@ -94,14 +95,12 @@ void find_widgets(YWidget *w, WidgetArray &array, std::function static bool filter_by_label_rec(YWidget *w, const std::string &label) { - std::string label_sanitized = boost::erase_all_copy( label, ShortcutChar ); // check the widget label if it is defined if ( w->propertySet().contains("Label") ) { std::string widget_label = w->getProperty("Label").stringVal(); - boost::erase_all( widget_label, ShortcutChar ); - if ( widget_label == label_sanitized ) + if ( YWidgetActionHandler::normalized_labels_equal( widget_label, label ) ) return true; } return false; diff --git a/libyui-rest-api/src/YWidgetFinder.h b/libyui-rest-api/src/YWidgetFinder.h index 6cd6ea0cb..8f4d6f345 100644 --- a/libyui-rest-api/src/YWidgetFinder.h +++ b/libyui-rest-api/src/YWidgetFinder.h @@ -20,8 +20,6 @@ #include #include -#define ShortcutChar "&" - class YWidget; typedef std::vector WidgetArray; From ed6e2d46f40b1877e8f4c1844490d97ca1f194e3 Mon Sep 17 00:00:00 2001 From: Martin Vidner Date: Fri, 4 Jun 2021 10:28:58 +0200 Subject: [PATCH 3/4] version + changelog --- VERSION.cmake | 2 +- package/libyui-bindings.spec | 2 +- package/libyui-ncurses-pkg.spec | 2 +- package/libyui-ncurses-rest-api.spec | 2 +- package/libyui-ncurses.spec | 2 +- package/libyui-qt-graph.spec | 2 +- package/libyui-qt-pkg.spec | 2 +- package/libyui-qt-rest-api.spec | 2 +- package/libyui-qt.spec | 2 +- package/libyui-rest-api.spec | 2 +- package/libyui.changes | 7 +++++++ package/libyui.spec | 2 +- 12 files changed, 18 insertions(+), 11 deletions(-) diff --git a/VERSION.cmake b/VERSION.cmake index f05dedffd..4bd08cba8 100644 --- a/VERSION.cmake +++ b/VERSION.cmake @@ -1,6 +1,6 @@ SET( VERSION_MAJOR "4") SET( VERSION_MINOR "2" ) -SET( VERSION_PATCH "13" ) +SET( VERSION_PATCH "14" ) SET( VERSION "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}" ) SET( SONAME_MAJOR "15" ) diff --git a/package/libyui-bindings.spec b/package/libyui-bindings.spec index ecacbc198..9c786aa58 100644 --- a/package/libyui-bindings.spec +++ b/package/libyui-bindings.spec @@ -20,7 +20,7 @@ Name: libyui-bindings # DO NOT manually bump the version here; instead, use rake version:bump -Version: 4.2.13 +Version: 4.2.14 Release: 0 Summary: Bindings for libyui License: LGPL-2.1-only OR LGPL-3.0-only diff --git a/package/libyui-ncurses-pkg.spec b/package/libyui-ncurses-pkg.spec index 759290c63..0e9cc56cb 100644 --- a/package/libyui-ncurses-pkg.spec +++ b/package/libyui-ncurses-pkg.spec @@ -19,7 +19,7 @@ Name: libyui-ncurses-pkg # DO NOT manually bump the version here; instead, use rake version:bump -Version: 4.2.13 +Version: 4.2.14 Release: 0 %define so_version 15 diff --git a/package/libyui-ncurses-rest-api.spec b/package/libyui-ncurses-rest-api.spec index 0ed0bb99e..b7675ca4f 100644 --- a/package/libyui-ncurses-rest-api.spec +++ b/package/libyui-ncurses-rest-api.spec @@ -19,7 +19,7 @@ Name: libyui-ncurses-rest-api # DO NOT manually bump the version here; instead, use rake version:bump -Version: 4.2.13 +Version: 4.2.14 Release: 0 %define so_version 15 diff --git a/package/libyui-ncurses.spec b/package/libyui-ncurses.spec index 37b1f7a05..04a48023c 100644 --- a/package/libyui-ncurses.spec +++ b/package/libyui-ncurses.spec @@ -19,7 +19,7 @@ Name: libyui-ncurses # DO NOT manually bump the version here; instead, use rake version:bump -Version: 4.2.13 +Version: 4.2.14 Release: 0 %define so_version 15 diff --git a/package/libyui-qt-graph.spec b/package/libyui-qt-graph.spec index 57ff2b672..2fca6d563 100644 --- a/package/libyui-qt-graph.spec +++ b/package/libyui-qt-graph.spec @@ -19,7 +19,7 @@ Name: libyui-qt-graph # DO NOT manually bump the version here; instead, use rake version:bump -Version: 4.2.13 +Version: 4.2.14 Release: 0 %define so_version 15 diff --git a/package/libyui-qt-pkg.spec b/package/libyui-qt-pkg.spec index 625861098..907b3bb59 100644 --- a/package/libyui-qt-pkg.spec +++ b/package/libyui-qt-pkg.spec @@ -19,7 +19,7 @@ Name: libyui-qt-pkg # DO NOT manually bump the version here; instead, use rake version:bump -Version: 4.2.13 +Version: 4.2.14 Release: 0 %define so_version 15 diff --git a/package/libyui-qt-rest-api.spec b/package/libyui-qt-rest-api.spec index e2b9dc629..c455f18c1 100644 --- a/package/libyui-qt-rest-api.spec +++ b/package/libyui-qt-rest-api.spec @@ -19,7 +19,7 @@ Name: libyui-qt-rest-api # DO NOT manually bump the version here; instead, use rake version:bump -Version: 4.2.13 +Version: 4.2.14 Release: 0 %define so_version 15 diff --git a/package/libyui-qt.spec b/package/libyui-qt.spec index 7381e8dd4..e79fa6592 100644 --- a/package/libyui-qt.spec +++ b/package/libyui-qt.spec @@ -19,7 +19,7 @@ Name: libyui-qt # DO NOT manually bump the version here; instead, use rake version:bump -Version: 4.2.13 +Version: 4.2.14 Release: 0 %define so_version 15 diff --git a/package/libyui-rest-api.spec b/package/libyui-rest-api.spec index 95b95ad22..837dc8694 100644 --- a/package/libyui-rest-api.spec +++ b/package/libyui-rest-api.spec @@ -19,7 +19,7 @@ Name: libyui-rest-api # DO NOT manually bump the version here; instead, use rake version:bump -Version: 4.2.13 +Version: 4.2.14 Release: 0 %define so_version 15 diff --git a/package/libyui.changes b/package/libyui.changes index a6a3fffc4..eabaf13f7 100644 --- a/package/libyui.changes +++ b/package/libyui.changes @@ -1,3 +1,10 @@ +------------------------------------------------------------------- +Fri Jun 4 08:27:03 UTC 2021 - Martin Vidner + +- rest-api: When finding table items by cell value, + ignore BiDi control chars (bsc#1128091) +- 4.2.14 + ------------------------------------------------------------------- Wed Jun 2 11:18:42 UTC 2021 - Stefan Hundhammer diff --git a/package/libyui.spec b/package/libyui.spec index 6c5740b20..139afebf9 100644 --- a/package/libyui.spec +++ b/package/libyui.spec @@ -19,7 +19,7 @@ Name: libyui # DO NOT manually bump the version here; instead, use rake version:bump -Version: 4.2.13 +Version: 4.2.14 Release: 0 %define so_version 15 From 3030d7cb646173738cca5fcdf6f6c7d15f9f1bea Mon Sep 17 00:00:00 2001 From: Martin Vidner Date: Mon, 7 Jun 2021 11:19:52 +0200 Subject: [PATCH 4/4] Explain boost::remove_if --- libyui-rest-api/src/YWidgetActionHandler.cc | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/libyui-rest-api/src/YWidgetActionHandler.cc b/libyui-rest-api/src/YWidgetActionHandler.cc index 6f6ca7304..5cff4a436 100644 --- a/libyui-rest-api/src/YWidgetActionHandler.cc +++ b/libyui-rest-api/src/YWidgetActionHandler.cc @@ -24,11 +24,14 @@ std::string normalize_label_bidi(const std::string& label) { static std::wstring_convert> conv; - //static const std::wstring bidi_controls(L"\u202a\u202b\u202c\u202d\u202e\u2066\u2067\u2068\u2069"); static wchar_t bidi_controls[] { L'\u202a', L'\u202b', L'\u202c', L'\u202d', L'\u202e', L'\u2066', L'\u2067', L'\u2068', L'\u2069' }; std::wstring wlabel(conv.from_bytes(label)); - wlabel.erase(boost::remove_if(wlabel, boost::is_any_of(bidi_controls)), wlabel.end()); + auto new_end = boost::remove_if(wlabel, boost::is_any_of(bidi_controls)); + // for s == "hello", + // remove_if(s, is_consonant) leaves s == "eollo" and returns new_end + // pointing at the first 'l', so an additional erase is needed: + wlabel.erase(new_end, wlabel.end()); std::string cleaned(conv.to_bytes(wlabel)); return cleaned; @@ -43,4 +46,4 @@ std::string normalize_label_shortcut(const std::string& label) std::string YWidgetActionHandler::normalize_label(const std::string & label) { return normalize_label_shortcut(normalize_label_bidi(label)); -} \ No newline at end of file +}