[PATCH 5/5] Escape text inserted into markup strings

David Shea dshea at redhat.com
Wed Oct 16 17:27:23 UTC 2013


---
 pyanaconda/ui/gui/hubs/__init__.py              |  6 +++---
 pyanaconda/ui/gui/spokes/advstorage/iscsi.glade |  2 +-
 pyanaconda/ui/gui/spokes/advstorage/iscsi.py    | 12 ++++++++++--
 pyanaconda/ui/gui/spokes/keyboard.py            |  4 ++--
 pyanaconda/ui/gui/spokes/langsupport.py         |  8 ++++++--
 pyanaconda/ui/gui/spokes/lib/accordion.py       |  7 +++++--
 pyanaconda/ui/gui/spokes/lib/cart.py            |  5 ++++-
 pyanaconda/ui/gui/spokes/lib/resize.py          | 15 ++++++++++-----
 pyanaconda/ui/gui/spokes/lib/summary.py         |  7 +++++--
 pyanaconda/ui/gui/spokes/network.py             | 16 +++++++++-------
 pyanaconda/ui/gui/spokes/software.py            |  8 +++++---
 pyanaconda/ui/gui/spokes/storage.py             | 19 +++++++++++--------
 pyanaconda/ui/gui/spokes/welcome.py             | 10 +++++++---
 pyanaconda/ui/gui/utils.py                      |  9 +++++++++
 14 files changed, 87 insertions(+), 41 deletions(-)

diff --git a/pyanaconda/ui/gui/hubs/__init__.py b/pyanaconda/ui/gui/hubs/__init__.py
index f142a18..f889e92 100644
--- a/pyanaconda/ui/gui/hubs/__init__.py
+++ b/pyanaconda/ui/gui/hubs/__init__.py
@@ -31,7 +31,7 @@ from pyanaconda.ui import common
 from pyanaconda.ui.gui import GUIObject
 from pyanaconda.ui.gui.categories import collect_categories
 from pyanaconda.ui.gui.spokes import StandaloneSpoke, collect_spokes
-from pyanaconda.ui.gui.utils import gtk_call_once
+from pyanaconda.ui.gui.utils import gtk_call_once, escape_markup
 from pyanaconda.constants import ANACONDA_ENVIRON
 
 import logging
@@ -225,7 +225,7 @@ class Hub(GUIObject, common.Hub):
             if not selectors:
                 continue
 
-            label = Gtk.Label("<span font-desc=\"Sans 14\">%s</span>" % _(obj.title))
+            label = Gtk.Label("<span font-desc=\"Sans 14\">%s</span>" % escape_markup(_(obj.title)))
             label.set_use_markup(True)
             label.set_halign(Gtk.Align.START)
             label.set_margin_top(12)
@@ -257,7 +257,7 @@ class Hub(GUIObject, common.Hub):
     def _updateCompleteness(self, spoke):
         spoke.selector.set_sensitive(spoke.ready)
         spoke.selector.set_property("status", spoke.status)
-        spoke.selector.set_tooltip_markup(GLib.markup_escape_text(spoke.status))
+        spoke.selector.set_tooltip_markup(escape_markup(spoke.status))
         spoke.selector.set_incomplete(not spoke.completed and spoke.mandatory)
         self._handleCompleteness(spoke)
 
diff --git a/pyanaconda/ui/gui/spokes/advstorage/iscsi.glade b/pyanaconda/ui/gui/spokes/advstorage/iscsi.glade
index 8050e06..2e3ad63 100644
--- a/pyanaconda/ui/gui/spokes/advstorage/iscsi.glade
+++ b/pyanaconda/ui/gui/spokes/advstorage/iscsi.glade
@@ -682,7 +682,7 @@
                         <property name="visible">True</property>
                         <property name="can_focus">False</property>
                         <property name="xalign">0</property>
-                        <property name="label" translatable="yes">The following nodes were discovered using the iSCSI initiator &lt;b&gt;%(initiatorName)s&lt;/b&gt; using the target IP address &lt;b&gt;%(targetAddress)s&lt;/b&gt;.  Please select which nodes you wish to log into:</property>
+                        <property name="label">The following nodes were discovered using the iSCSI initiator &lt;b&gt;%(initiatorName)s&lt;/b&gt; using the target IP address &lt;b&gt;%(targetAddress)s&lt;/b&gt;.  Please select which nodes you wish to log into:</property>
                         <property name="use_markup">True</property>
                         <property name="wrap">True</property>
                       </object>
diff --git a/pyanaconda/ui/gui/spokes/advstorage/iscsi.py b/pyanaconda/ui/gui/spokes/advstorage/iscsi.py
index b2abccc..223e1cd 100644
--- a/pyanaconda/ui/gui/spokes/advstorage/iscsi.py
+++ b/pyanaconda/ui/gui/spokes/advstorage/iscsi.py
@@ -26,6 +26,8 @@ from gi.repository import GLib
 from pyanaconda import constants
 from pyanaconda.threads import threadMgr, AnacondaThread
 from pyanaconda.ui.gui import GUIObject
+from pyanaconda.ui.gui.utils import escape_markup
+from pyanaconda.i18n import _
 from pyanaconda import nm
 
 __all__ = ["ISCSIDialog"]
@@ -264,9 +266,15 @@ class ISCSIDialog(GUIObject):
         # Now get the node discovery credentials.
         credentials = discoverMap[self._authNotebook.get_current_page()](self.builder)
 
+        discoveredLabelText = _("The following nodes were discovered using the iSCSI initiator "\
+                                "<b>%(initiatorName)s</b> using the target IP address "\
+                                "<b>%(targetAddress)s</b>.  Please select which nodes you "\
+                                "wish to log into:") % \
+                                {"initiatorName": escape_markup(credentials.initiator),
+                                 "targetAddress": escape_markup(credentials.targetIP)}
+
         discoveredLabel = self.builder.get_object("discoveredLabel")
-        discoveredLabel.set_markup(discoveredLabel.get_label() % {"initiatorName": credentials.initiator,
-                                                                  "targetAddress": credentials.targetIP})
+        discoveredLabel.set_markup(discoveredLabelText)
 
         bind = self._bindCheckbox.get_active()
 
diff --git a/pyanaconda/ui/gui/spokes/keyboard.py b/pyanaconda/ui/gui/spokes/keyboard.py
index f7c8c99..b5d3af0 100644
--- a/pyanaconda/ui/gui/spokes/keyboard.py
+++ b/pyanaconda/ui/gui/spokes/keyboard.py
@@ -25,7 +25,7 @@ from gi.repository import Gkbd, Gdk, Gtk
 from pyanaconda.ui.gui import GUIObject
 from pyanaconda.ui.gui.spokes import NormalSpoke
 from pyanaconda.ui.gui.categories.localization import LocalizationCategory
-from pyanaconda.ui.gui.utils import enlightbox, gtk_call_once
+from pyanaconda.ui.gui.utils import enlightbox, gtk_call_once, escape_markup
 from pyanaconda import keyboard
 from pyanaconda import flags
 from pyanaconda.i18n import _, N_
@@ -46,7 +46,7 @@ def _show_layout(column, renderer, model, itr, wrapper):
 def _show_description(column, renderer, model, itr, wrapper):
     value = wrapper.get_switch_opt_description(model[itr][0])
     if model[itr][1]:
-        value = "<b>%s</b>" % value
+        value = "<b>%s</b>" % escape_markup(value)
     renderer.set_property("markup", value)
 
 class AddLayoutDialog(GUIObject):
diff --git a/pyanaconda/ui/gui/spokes/langsupport.py b/pyanaconda/ui/gui/spokes/langsupport.py
index 776791e..9c37895 100644
--- a/pyanaconda/ui/gui/spokes/langsupport.py
+++ b/pyanaconda/ui/gui/spokes/langsupport.py
@@ -24,6 +24,7 @@ from gi.repository import Pango
 from pyanaconda.flags import flags
 from pyanaconda.i18n import N_
 from pyanaconda.ui.gui.spokes import NormalSpoke
+from pyanaconda.ui.gui.utils import escape_markup
 from pyanaconda.ui.gui.categories.localization import LocalizationCategory
 from pyanaconda.ui.gui.spokes.lib.lang_locale_handler import LangLocaleHandler
 from pyanaconda import localization
@@ -108,11 +109,14 @@ class LangsupportSpoke(LangLocaleHandler, NormalSpoke):
         return True
 
     def _add_language(self, store, native, english, lang):
-        native_span = '<span lang="%s">%s</span>' % (lang, native)
+        native_span = '<span lang="%s">%s</span>' % \
+                (escape_markup(lang), escape_markup(native))
         store.append([native_span, english, lang])
 
     def _add_locale(self, store, native, locale):
-        native_span = '<span lang="%s">%s</span>' % (re.sub(r'\..*', '', locale), native)
+        native_span = '<span lang="%s">%s</span>' % \
+                (escape_markup(re.sub(r'\..*', '', locale)),
+                 escape_markup(native))
 
         # native, locale, selected, additional
         store.append([native_span, locale, locale in self._selected_locales,
diff --git a/pyanaconda/ui/gui/spokes/lib/accordion.py b/pyanaconda/ui/gui/spokes/lib/accordion.py
index 5990332..b527021 100644
--- a/pyanaconda/ui/gui/spokes/lib/accordion.py
+++ b/pyanaconda/ui/gui/spokes/lib/accordion.py
@@ -24,6 +24,7 @@ from blivet.size import Size
 
 from pyanaconda.i18n import _
 from pyanaconda.product import productName, productVersion
+from pyanaconda.ui.gui.utils import escape_markup
 
 from gi.repository.AnacondaWidgets import MountpointSelector
 from gi.repository import Gtk
@@ -82,7 +83,8 @@ class Accordion(Gtk.Box):
 
     def addPage(self, contents, cb=None):
         label = Gtk.Label()
-        label.set_markup("""<span size='large' weight='bold' fgcolor='black'>%s</span>""" % contents.pageTitle)
+        label.set_markup("""<span size='large' weight='bold' fgcolor='black'>%s</span>""" %
+                escape_markup(contents.pageTitle))
         label.set_alignment(0, 0.5)
         label.set_line_wrap(True)
 
@@ -167,7 +169,8 @@ class Page(Gtk.Box):
 
     def _make_category_label(self, name):
         label = Gtk.Label()
-        label.set_markup("""<span fgcolor='dark grey' size='large' weight='bold'>%s</span>""" % name)
+        label.set_markup("""<span fgcolor='dark grey' size='large' weight='bold'>%s</span>""" %
+                escape_markup(name))
         label.set_halign(Gtk.Align.START)
         label.set_margin_left(24)
         return label
diff --git a/pyanaconda/ui/gui/spokes/lib/cart.py b/pyanaconda/ui/gui/spokes/lib/cart.py
index b3a2ca5..db34a6d 100644
--- a/pyanaconda/ui/gui/spokes/lib/cart.py
+++ b/pyanaconda/ui/gui/spokes/lib/cart.py
@@ -25,6 +25,7 @@ from gi.repository import Gtk
 from pyanaconda.i18n import _, P_
 from pyanaconda.ui.lib.disks import size_str
 from pyanaconda.ui.gui import GUIObject
+from pyanaconda.ui.gui.utils import escape_markup
 from blivet.size import Size
 
 __all__ = ["SelectedDisksDialog"]
@@ -134,7 +135,9 @@ class SelectedDisksDialog(GUIObject):
                    "(unpartitioned and in filesystems)",
                   "<b>%(count)d disks; %(size)s capacity; %(free)s free space</b> "
                    "(unpartitioned and in filesystems)",
-                   count) % {"count" : count, "size" : size, "free" : free}
+                   count) % {"count" : count,
+                             "size" : escape_markup(size),
+                             "free" : escape_markup(free)}
         self._summary_label.set_markup(text)
 
     # signal handlers
diff --git a/pyanaconda/ui/gui/spokes/lib/resize.py b/pyanaconda/ui/gui/spokes/lib/resize.py
index 36ae4b1..755faea 100644
--- a/pyanaconda/ui/gui/spokes/lib/resize.py
+++ b/pyanaconda/ui/gui/spokes/lib/resize.py
@@ -27,6 +27,7 @@ from gi.repository import Gdk, Gtk
 from pyanaconda.i18n import _, N_, P_
 from pyanaconda.ui.lib.disks import size_str
 from pyanaconda.ui.gui import GUIObject
+from pyanaconda.ui.gui.utils import escape_markup
 from blivet.size import Size
 
 __all__ = ["ResizeDialog"]
@@ -74,7 +75,7 @@ class ResizeDialog(GUIObject):
 
         self._required_label = self.builder.get_object("requiredSpaceLabel")
         markup = self._required_label.get_label()
-        self._required_label.set_markup(markup % size_str(self.payload.spaceRequired))
+        self._required_label.set_markup(markup % escape_markup(size_str(self.payload.spaceRequired)))
 
         self._reclaimDescLabel = self.builder.get_object("reclaimDescLabel")
 
@@ -156,7 +157,8 @@ class ResizeDialog(GUIObject):
                             canShrinkSomething = True
                     else:
                         freeSize = dev.size
-                        resizeString = "<span foreground='grey'>%s</span>" % _("Not resizeable")
+                        resizeString = "<span foreground='grey'>%s</span>" % \
+                                escape_markup(_("Not resizeable"))
 
                     self._diskStore.append(itr, [dev.id,
                                                  self._description(dev),
@@ -174,7 +176,8 @@ class ResizeDialog(GUIObject):
             diskFree = free_space[disk.name][0]
             converted = diskFree.convertTo(spec="mb")
             if int(converted):
-                freeSpaceString = "<span foreground='grey' style='italic'>%s</span>" % _("Free space")
+                freeSpaceString = "<span foreground='grey' style='italic'>%s</span>" % \
+                        escape_markup(_("Free space"))
                 self._diskStore.append(itr, [disk.id,
                                              freeSpaceString,
                                              "",
@@ -212,11 +215,13 @@ class ResizeDialog(GUIObject):
         if nDisks is not None and totalReclaimable is not None:
             text = P_("<b>%(count)s disk; %(size)s reclaimable space</b> (in filesystems)",
                       "<b>%(count)s disks; %(size)s reclaimable space</b> (in filesystems)",
-                      nDisks) % {"count" : nDisks, "size" : size_str(totalReclaimable)}
+                      nDisks) % {"count" : escape_markup(str(nDisks)),
+                                 "size" : escape_markup(size_str(totalReclaimable))}
             self._reclaimable_label.set_markup(text)
 
         if selectedReclaimable is not None:
-            text = _("Total selected space to reclaim: <b>%s</b>") % size_str(selectedReclaimable)
+            text = _("Total selected space to reclaim: <b>%s</b>") % \
+                    escape_markup(size_str(selectedReclaimable))
             self._selected_label.set_markup(text)
 
     def _setup_slider(self, device, value):
diff --git a/pyanaconda/ui/gui/spokes/lib/summary.py b/pyanaconda/ui/gui/spokes/lib/summary.py
index 8d320cc..2b3eb86 100644
--- a/pyanaconda/ui/gui/spokes/lib/summary.py
+++ b/pyanaconda/ui/gui/spokes/lib/summary.py
@@ -20,6 +20,7 @@
 #
 
 from pyanaconda.ui.gui import GUIObject
+from pyanaconda.ui.gui.utils import escape_markup
 
 from blivet.deviceaction import ACTION_TYPE_DESTROY, ACTION_TYPE_RESIZE, ACTION_OBJECT_FORMAT
 
@@ -40,9 +41,11 @@ class ActionSummaryDialog(GUIObject):
             mountpoint = ""
 
             if action.type in [ACTION_TYPE_DESTROY, ACTION_TYPE_RESIZE]:
-                typeString = """<span foreground='red'>%s</span>""" % action.typeDesc.title()
+                typeString = """<span foreground='red'>%s</span>""" % \
+                        escape_markup(action.typeDesc.title())
             else:
-                typeString = """<span foreground='green'>%s</span>""" % action.typeDesc.title()
+                typeString = """<span foreground='green'>%s</span>""" % \
+                        escape_markup(action.typeDesc.title())
                 if action.obj == ACTION_OBJECT_FORMAT:
                     mountpoint = getattr(action.device.format, "mountpoint", "")
 
diff --git a/pyanaconda/ui/gui/spokes/network.py b/pyanaconda/ui/gui/spokes/network.py
index d4d1803..559e999 100644
--- a/pyanaconda/ui/gui/spokes/network.py
+++ b/pyanaconda/ui/gui/spokes/network.py
@@ -39,7 +39,7 @@ from pyanaconda.ui.gui import GUIObject
 from pyanaconda.ui.gui.spokes import NormalSpoke, StandaloneSpoke
 from pyanaconda.ui.gui.categories.system import SystemCategory
 from pyanaconda.ui.gui.hubs.summary import SummaryHub
-from pyanaconda.ui.gui.utils import gtk_call_once, enlightbox
+from pyanaconda.ui.gui.utils import gtk_call_once, enlightbox, escape_markup
 from pyanaconda.ui.common import FirstbootSpokeMixIn
 
 from pyanaconda import network
@@ -626,12 +626,14 @@ class NetworkControlBox(object):
             and device.get_device_type() == NetworkManager.DeviceType.ETHERNET
             and not device.get_carrier()):
             # Translators: ethernet cable is unplugged
-            unplugged = ', <i>%s</i>' % _("unplugged")
-        title = '<span size="large">%s (%s%s)</span>' % (self._dev_type_str(device),
-                                                         device.get_iface(),
-                                                         unplugged)
-        title += '\n<span size="small">%s %s</span>' % (device.get_vendor() or "",
-                                                        device.get_product() or "")
+            unplugged = ', <i>%s</i>' % escape_markup(_("unplugged"))
+        title = '<span size="large">%s (%s%s)</span>' % \
+                (escape_markup(self._dev_type_str(device)),
+                 escape_markup(device.get_iface()),
+                 unplugged)
+        title += '\n<span size="small">%s %s</span>' % \
+                (escape_markup(device.get_vendor()) or "",
+                 escape_markup(device.get_product()) or "")
         return title
 
     def _dev_type_str(self, device):
diff --git a/pyanaconda/ui/gui/spokes/software.py b/pyanaconda/ui/gui/spokes/software.py
index f4b7995..285e857 100644
--- a/pyanaconda/ui/gui/spokes/software.py
+++ b/pyanaconda/ui/gui/spokes/software.py
@@ -30,7 +30,7 @@ from pyanaconda import constants
 from pyanaconda.ui.communication import hubQ
 from pyanaconda.ui.gui.spokes import NormalSpoke
 from pyanaconda.ui.gui.spokes.lib.detailederror import DetailedErrorDialog
-from pyanaconda.ui.gui.utils import enlightbox, gtk_action_wait
+from pyanaconda.ui.gui.utils import enlightbox, gtk_action_wait, escape_markup
 from pyanaconda.ui.gui.categories.software import SoftwareCategory
 
 import sys
@@ -248,7 +248,8 @@ class SoftwareSelectionSpoke(NormalSpoke):
         for environment in self.payload.environments:
             (name, desc) = self.payload.environmentDescription(environment)
 
-            itr = self._environmentStore.append([environment == self.environment, "<b>%s</b>\n%s" % (name, desc), environment])
+            itr = self._environmentStore.append([environment == self.environment, "<b>%s</b>\n%s" % \
+                    (escape_markup(name), escape_markup(desc)), environment])
             # Either:
             # (1) Select the environment given by kickstart or selected last
             #     time this spoke was displayed; or
@@ -276,7 +277,8 @@ class SoftwareSelectionSpoke(NormalSpoke):
         else:
             selected = grp in self.selectedGroups
 
-        self._addonStore.append([selected, "<b>%s</b>\n%s" % (name, desc), grp, False])
+        self._addonStore.append([selected, "<b>%s</b>\n%s" % \
+                (escape_markup(name), escape_markup(desc)), grp, False])
 
     def refreshAddons(self):
         self._addonStore.clear()
diff --git a/pyanaconda/ui/gui/spokes/storage.py b/pyanaconda/ui/gui/spokes/storage.py
index 99450b9..5b83e7f 100644
--- a/pyanaconda/ui/gui/spokes/storage.py
+++ b/pyanaconda/ui/gui/spokes/storage.py
@@ -49,7 +49,7 @@ from pyanaconda.ui.gui.spokes.lib.passphrase import PassphraseDialog
 from pyanaconda.ui.gui.spokes.lib.detailederror import DetailedErrorDialog
 from pyanaconda.ui.gui.spokes.lib.resize import ResizeDialog
 from pyanaconda.ui.gui.categories.system import SystemCategory
-from pyanaconda.ui.gui.utils import enlightbox
+from pyanaconda.ui.gui.utils import enlightbox, escape_markup
 
 from pyanaconda.kickstart import doKickstartStorage, getAvailableDiskSpace
 from blivet import empty_device
@@ -126,7 +126,8 @@ class InstallOptions1Dialog(GUIObject):
         options_text = _("<span font-desc=\"Cantarell 11\">You have <b>%(freeSpace)s</b> "
                          "of free space, which is enough to install %(productName)s.  "
                          "What would you like to do?</span>") %\
-                         {"freeSpace": disk_free, "productName": productName}
+                         {"freeSpace": escape_markup(disk_free),
+                          "productName": escape_markup(productName)}
         options_label.set_markup(options_text)
 
         label = self.builder.get_object("options1_autopart_label")
@@ -171,9 +172,10 @@ class InstallOptions1Dialog(GUIObject):
                      "selection</a> requires <b>%(total)s</b> of available "
                      "space, including <b>%(software)s</b> for software and "
                      "<b>%(swap)s</b> for swap space.")
-                   % {"product": productName,
-                      "total": required_space + auto_swap,
-                      "software": required_space, "swap": auto_swap})
+                   % {"product": escape_markup(productName),
+                      "total": escape_markup(str(required_space + auto_swap)),
+                      "software": escape_markup(str(required_space)),
+                      "swap": escape_markup(str(auto_swap))})
         return sw_text
 
     # Methods to handle sensitivity of the modify button.
@@ -248,7 +250,7 @@ class InstallOptions2Dialog(InstallOptions1Dialog):
                        "%s</b>.  You can shrink or remove existing partitions "
                        "via our guided reclaim space tool, or you can adjust your "
                        "partitions on your own in the custom partitioning "
-                       "interface.") % productName
+                       "interface.") % escape_markup(productName)
         self.builder.get_object("options2_label2").set_markup(label_text)
 
         self._add_modify_watcher("options2_label1")
@@ -277,7 +279,8 @@ class InstallOptions3Dialog(InstallOptions1Dialog):
         label_text = (_("%(sw_text)s You don't have enough space available to install "
                         "<b>%(product)s</b>, even if you used all of the free space "
                         "available on the selected disks.")
-                      % {"sw_text": sw_text, "product": productName})
+                      % {"sw_text": escape_markup(sw_text),
+                         "product": escape_markup(productName)})
         label = self.builder.get_object("options3_label1")
         label.set_markup(label_text)
         label.set_tooltip_text(_("Please wait... software metadata still loading."))
@@ -291,7 +294,7 @@ class InstallOptions3Dialog(InstallOptions1Dialog):
                        "disks for additional space, "
                        "modify your software selection to install a smaller "
                        "version of <b>%(productName)s</b>, or quit the installer.") % \
-                               {"productName": productName}
+                               {"productName": escape_markup(productName)}
         self.builder.get_object("options3_label2").set_markup(label_text)
 
         self._add_modify_watcher("options3_label1")
diff --git a/pyanaconda/ui/gui/spokes/welcome.py b/pyanaconda/ui/gui/spokes/welcome.py
index c6f411d..a986b73 100644
--- a/pyanaconda/ui/gui/spokes/welcome.py
+++ b/pyanaconda/ui/gui/spokes/welcome.py
@@ -26,7 +26,7 @@ import langtable
 
 from pyanaconda.ui.gui.hubs.summary import SummaryHub
 from pyanaconda.ui.gui.spokes import StandaloneSpoke
-from pyanaconda.ui.gui.utils import enlightbox, setup_gtk_direction
+from pyanaconda.ui.gui.utils import enlightbox, setup_gtk_direction, escape_markup
 from pyanaconda.ui.gui.spokes.lib.lang_locale_handler import LangLocaleHandler
 
 from pyanaconda import localization
@@ -268,11 +268,15 @@ class WelcomeLanguageSpoke(LangLocaleHandler, StandaloneSpoke):
         self._languageStoreFilter.refilter()
 
     def _add_language(self, store, native, english, lang):
-        native_span = '<span lang="%s">%s</span>' % (lang, native)
+        native_span = '<span lang="%s">%s</span>' % \
+                (escape_markup(lang),
+                 escape_markup(native))
         store.append([native_span, english, lang, False])
 
     def _add_locale(self, store, native, locale):
-        native_span = '<span lang="%s">%s</span>' % (re.sub(r'\..*', '', locale), native)
+        native_span = '<span lang="%s">%s</span>' % \
+                (escape_markup(re.sub(r'\..*', '', locale)),
+                 escape_markup(native))
         store.append([native_span, locale])
 
     # Signal handlers.
diff --git a/pyanaconda/ui/gui/utils.py b/pyanaconda/ui/gui/utils.py
index f7ad413..5e5095c 100644
--- a/pyanaconda/ui/gui/utils.py
+++ b/pyanaconda/ui/gui/utils.py
@@ -223,3 +223,12 @@ def setup_gtk_direction():
     """
 
     Gtk.Widget.set_default_direction(get_default_widget_direction())
+
+def escape_markup(value):
+    """
+    Escape strings for use within Pango markup.
+
+    This function converts the value to a string before passing markup_escape_text().
+    """
+
+    return GLib.markup_escape_text(str(value))
-- 
1.8.3.1



More information about the anaconda-patches mailing list