From c72b746d0a0675cb2328801d3e2d7c95fe65054e Mon Sep 17 00:00:00 2001 From: Alexander Shaduri Date: Fri, 14 Jan 2022 19:17:15 +0400 Subject: [PATCH] Escape all text wherever it may be interpreted as markup, even if not coming from external source. --- src/applib/ata_storage_property.h | 2 +- src/applib/ata_storage_property_descr.cpp | 6 +-- src/applib/warning_colors.h | 6 +-- src/gsc_info_window.cpp | 52 +++++++++++------------ src/gsc_main_window.cpp | 2 +- src/gsc_main_window_iconview.h | 8 ++-- 6 files changed, 38 insertions(+), 38 deletions(-) diff --git a/src/applib/ata_storage_property.h b/src/applib/ata_storage_property.h index f0f3fbc..578d681 100644 --- a/src/applib/ata_storage_property.h +++ b/src/applib/ata_storage_property.h @@ -300,7 +300,7 @@ class AtaStorageProperty { std::string generic_name; ///< Generic (internal) name. May be same as reported_name, or something more program-identifiable. std::string displayable_name; ///< Readable property name. May be same as reported_name, or something more user-readable. Possibly translatable. - std::string description; ///< Property description (for tooltips, etc...) + std::string description; ///< Property description (for tooltips, etc...). May contain markup. Section section = Section::unknown; ///< Section this property belongs to SubSection subsection = SubSection::unknown; ///< Subsection this property belongs to diff --git a/src/applib/ata_storage_property_descr.cpp b/src/applib/ata_storage_property_descr.cpp index daf1651..4321158 100644 --- a/src/applib/ata_storage_property_descr.cpp +++ b/src/applib/ata_storage_property_descr.cpp @@ -1504,9 +1504,9 @@ namespace { same_names = app_pcre_match("/^" + app_pcre_escape(match) + "$/i", against); } - std::string descr = std::string("") + attr.displayable_name + ""; + std::string descr = std::string("") + Glib::Markup::escape_text(attr.displayable_name) + ""; if (!same_names) { - std::string reported_name_for_descr = hz::string_replace_copy(p.reported_name, '_', ' '); + std::string reported_name_for_descr = Glib::Markup::escape_text(hz::string_replace_copy(p.reported_name, '_', ' ')); descr += "\nReported by smartctl as \"" + reported_name_for_descr + "\"\n"; } descr += "\n"; @@ -1535,7 +1535,7 @@ namespace { sd.description = "No description is available for this attribute."; } else { - std::string descr = std::string("") + displayable_name + "\n"; + std::string descr = std::string("") + Glib::Markup::escape_text(displayable_name) + "\n"; descr += sd.description; if (p.get_value().is_normalized()) { diff --git a/src/applib/warning_colors.h b/src/applib/warning_colors.h index f775ff1..8cbe9be 100644 --- a/src/applib/warning_colors.h +++ b/src/applib/warning_colors.h @@ -76,13 +76,13 @@ inline std::string storage_property_get_warning_reason(const AtaStorageProperty& break; case WarningLevel::notice: /// Translators: %1 and %2 are HTML tags, %3 is a message. - return Glib::ustring::compose(_("%1Notice:%2 %3"), start, stop, p.warning_reason); + return Glib::ustring::compose(_("%1Notice:%2 %3"), start, stop, Glib::Markup::escape_text(p.warning_reason)); case WarningLevel::warning: /// Translators: %1 and %2 are HTML tags, %3 is a message. - return Glib::ustring::compose(_("%1Warning:%2 %3"), start, stop, p.warning_reason); + return Glib::ustring::compose(_("%1Warning:%2 %3"), start, stop, Glib::Markup::escape_text(p.warning_reason)); case WarningLevel::alert: /// Translators: %1 and %2 are HTML tags, %3 is a message. - return Glib::ustring::compose(_("%1ALERT:%2 %3"), start, stop, p.warning_reason); + return Glib::ustring::compose(_("%1ALERT:%2 %3"), start, stop, Glib::Markup::escape_text(p.warning_reason)); } return {}; diff --git a/src/gsc_info_window.cpp b/src/gsc_info_window.cpp index 925888a..dca9ddd 100644 --- a/src/gsc_info_window.cpp +++ b/src/gsc_info_window.cpp @@ -133,7 +133,8 @@ namespace { if (p->is_value_type() && p->get_value().is_header) { crt->property_weight() = Pango::WEIGHT_BOLD; } else { - crt->property_weight() = Pango::WEIGHT_NORMAL; + // Do not use WEIGHT_NORMAL here, it interferes with cell markup + crt->property_weight().reset_value(); } } } @@ -1181,12 +1182,12 @@ void GscInfoWindow::fill_ui_statistics(const std::vector& pr Gtk::TreeRow row = *(list_store->append()); const auto& st = p.get_value(); - row[col_description] = (st.is_header ? p.displayable_name : (" " + p.displayable_name)); - row[col_value] = st.format_value(); - row[col_flags] = st.flags; // it's a string, not int. - row[col_page_offset] = (st.is_header ? std::string() + row[col_description] = Glib::Markup::escape_text(st.is_header ? p.displayable_name : (" " + p.displayable_name)); + row[col_value] = Glib::Markup::escape_text(st.format_value()); + row[col_flags] = Glib::Markup::escape_text(st.flags); // it's a string, not int. + row[col_page_offset] = Glib::Markup::escape_text(st.is_header ? std::string() : hz::string_sprintf("0x%02x, 0x%03x", int(st.page), int(st.offset))); - row[col_tooltip] = p.get_description(); + row[col_tooltip] = p.get_description(); // markup row[col_storage] = &p; if (int(p.warning) > int(max_tab_warning)) @@ -1375,11 +1376,11 @@ void GscInfoWindow::fill_ui_self_test_log(const std::vector& const auto& sse = p.get_value(); row[col_num] = sse.test_num; - row[col_type] = sse.type; - row[col_status] = sse.get_status_str(); - row[col_percent] = hz::number_to_string_locale(100 - sse.remaining_percent) + "%"; - row[col_hours] = sse.format_lifetime_hours(); - row[col_lba] = sse.lba_of_first_error; + row[col_type] = Glib::Markup::escape_text(sse.type); + row[col_status] = Glib::Markup::escape_text(sse.get_status_str()); + row[col_percent] = Glib::Markup::escape_text(hz::number_to_string_locale(100 - sse.remaining_percent) + "%"); + row[col_hours] = Glib::Markup::escape_text(sse.format_lifetime_hours()); + row[col_lba] = Glib::Markup::escape_text(sse.lba_of_first_error); // There are no descriptions in self-test log entries, so don't display // "No description available" for all of them. // row[col_tooltip] = p.get_description(); @@ -1508,13 +1509,11 @@ void GscInfoWindow::fill_ui_error_log(const std::vector& pro Gtk::TreeRow row = *(list_store->append()); row[col_num] = eb.error_num; - row[col_hours] = eb.format_lifetime_hours(); - row[col_state] = eb.device_state; - row[col_type] = AtaStorageErrorBlock::get_displayable_error_types(eb.reported_types); - row[col_details] = (type_details.empty() ? "-" : type_details); // e.g. OBS has no details - // There are no descriptions in self-test log entries, so don't display - // "No description available" for all of them. - row[col_tooltip] = p.get_description(); + row[col_hours] = Glib::Markup::escape_text(eb.format_lifetime_hours()); + row[col_state] = Glib::Markup::escape_text(eb.device_state); + row[col_type] = Glib::Markup::escape_text(AtaStorageErrorBlock::get_displayable_error_types(eb.reported_types)); + row[col_details] = Glib::Markup::escape_text(type_details.empty() ? "-" : type_details); // e.g. OBS has no details + row[col_tooltip] = p.get_description(); // markup row[col_storage] = &p; row[col_mark_name] = Glib::ustring::compose(_("Error %1"), eb.error_num); } @@ -1590,7 +1589,8 @@ void GscInfoWindow::fill_ui_temperature_log(const std::vector" + temperature + ""), &temp_property, true); + label_strings.emplace_back(Glib::ustring::compose(_("Current temperature: %1"), + "" + Glib::Markup::escape_text(temperature) + ""), &temp_property, true); if (int(temp_property.warning) > int(max_tab_warning)) max_tab_warning = temp_property.warning; @@ -1660,7 +1660,6 @@ WarningLevel GscInfoWindow::fill_ui_capabilities(const std::vectorappend()); row[col_index] = index; - row[col_name] = name; - row[col_flag_value] = (flag_value.empty() ? "-" : flag_value); - row[col_str_values] = str_value; - row[col_tooltip] = p.get_description(); + row[col_name] = Glib::Markup::escape_text(p.displayable_name); + row[col_flag_value] = Glib::Markup::escape_text(flag_value.empty() ? "-" : flag_value); + row[col_str_values] = Glib::Markup::escape_text(str_value); + row[col_tooltip] = p.get_description(); // markup row[col_storage] = &p; if (int(p.warning) > int(max_tab_warning)) @@ -1902,7 +1901,7 @@ gboolean GscInfoWindow::test_idle_callback(void* data) if (!self->test_error_msg.empty()) { aborted = true; severity = AtaStorageSelftestEntry::StatusSeverity::error; - result_msg = Glib::ustring::compose(_("Test aborted: %1"), self->test_error_msg); + result_msg = Glib::ustring::compose(_("Test aborted: %1"), Glib::Markup::escape_text(self->test_error_msg)); } else { severity = AtaStorageSelftestEntry::get_status_severity(status); @@ -1911,7 +1910,8 @@ gboolean GscInfoWindow::test_idle_callback(void* data) result_msg = ""s + _("Test was manually aborted.") + ""; // it's a StatusSeverity::none message } else { - result_msg = Glib::ustring::compose(_("Test result: %1."), AtaStorageSelftestEntry::get_status_displayable_name(status)); + result_msg = Glib::ustring::compose(_("Test result: %1."), + Glib::Markup::escape_text(AtaStorageSelftestEntry::get_status_displayable_name(status))); // It may not reach 100% somehow, so do it manually. if (test_completion_progressbar) diff --git a/src/gsc_main_window.cpp b/src/gsc_main_window.cpp index d067535..06e89d2 100644 --- a/src/gsc_main_window.cpp +++ b/src/gsc_main_window.cpp @@ -949,7 +949,7 @@ void GscMainWindow::update_status_widgets() health_label_->set_text(health_prop.format_value()); std::string fg; if (app_property_get_label_highlight_color(health_prop.warning, fg)) { - health_label_->set_markup(""+ health_label_->get_text() + ""); + health_label_->set_markup(""+ Glib::Markup::escape_text(health_label_->get_text()) + ""); } // don't set description tooltip - we already have the basic one. // unless it's failing. diff --git a/src/gsc_main_window_iconview.h b/src/gsc_main_window_iconview.h index 97b9c40..63d208d 100644 --- a/src/gsc_main_window_iconview.h +++ b/src/gsc_main_window_iconview.h @@ -334,9 +334,9 @@ class GscMainWindowIconView : public Gtk::IconView { tooltip_strs.push_back(Glib::ustring::compose(_("Serial number: %1"), "" + Glib::Markup::escape_text(drive->get_serial_number()) + "")); } tooltip_strs.push_back(Glib::ustring::compose(_("SMART status: %1"), - "" + StorageDevice::get_status_displayable_name(drive->get_smart_status()) + "")); + "" + Glib::Markup::escape_text(StorageDevice::get_status_displayable_name(drive->get_smart_status())) + "")); tooltip_strs.push_back(Glib::ustring::compose(_("Automatic Offline Data Collection status: %1"), - "" + StorageDevice::get_status_displayable_name(drive->get_aodc_status()) + "")); + "" + Glib::Markup::escape_text(StorageDevice::get_status_displayable_name(drive->get_aodc_status())) + "")); std::string tooltip_str = hz::string_join(tooltip_strs, '\n'); @@ -385,9 +385,9 @@ class GscMainWindowIconView : public Gtk::IconView { // sometimes leads to screwed up icons in iconview (blame gtk). if (row.get_value(col_name) != name) - row[col_name] = name; + row[col_name] = name; // markup if (row.get_value(col_description) != tooltip_str) - row[col_description] = tooltip_str; + row[col_description] = tooltip_str; // markup if (row.get_value(col_pixbuf) != icon) row[col_pixbuf] = icon;