# HG changeset patch # User Goffi # Date 1547894342 -3600 # Node ID b17e6fa1e607f6a236b35e8139109b7d07ba2d08 # Parent 816be0a23877779dc055956811922dfc81fd0a0e core (XMLUI): new XHTMLBox widget: XHTMLBox is a textbox specialised in XHTML, i.e. it renders the XHTML when in read_only, and it allows to edit it. The XHTML is cleaned by default, the cleaning is done by Text Syntaxes plugin (actually there is a cleaning method which can be set by any plugin, but Text Syntaxes is the one which does it). diff -r 816be0a23877 -r b17e6fa1e607 sat/plugins/plugin_misc_text_syntaxes.py --- a/sat/plugins/plugin_misc_text_syntaxes.py Sat Jan 19 11:39:02 2019 +0100 +++ b/sat/plugins/plugin_misc_text_syntaxes.py Sat Jan 19 11:39:02 2019 +0100 @@ -26,6 +26,7 @@ from twisted.internet import defer from twisted.internet.threads import deferToThread from sat.core import exceptions +from sat.tools import xml_tools try: from lxml import html @@ -205,6 +206,9 @@ host.bridge.addMethod( "syntaxGet", ".plugin", in_sign="s", out_sign="s", method=self.getSyntax ) + if xml_tools.cleanXHTML is None: + log.debug(u"Installing cleaning method") + xml_tools.cleanXHTML = self.cleanXHTML def _updateParamOptions(self): data_synt = TextSyntaxes.syntaxes diff -r 816be0a23877 -r b17e6fa1e607 sat/tools/xml_tools.py --- a/sat/tools/xml_tools.py Sat Jan 19 11:39:02 2019 +0100 +++ b/sat/tools/xml_tools.py Sat Jan 19 11:39:02 2019 +0100 @@ -41,6 +41,10 @@ html_entity_re = re.compile(r"&([a-zA-Z]+?);") XML_ENTITIES = ("quot", "amp", "apos", "lt", "gt") +# method to clean XHTML, receive raw unsecure XML or HTML, must return cleaned raw XHTML +# this method must be set during runtime +cleanXHTML = None + # TODO: move XMLUI stuff in a separate module # TODO: rewrite this with lxml or ElementTree or domish.Element: it's complicated and difficult to maintain with current minidom implementation @@ -58,11 +62,28 @@ """ widget_args = [field.value] widget_kwargs = {} - if field.fieldType == "fixed" or field.fieldType is None: + if field.fieldType is None and field.ext_type is not None: + # we have an extended field + if field.ext_type == u"xml": + element = field.value + if element.uri == C.NS_XHTML: + widget_type = "xhtmlbox" + widget_args[0] = element.toXml() + widget_kwargs["read_only"] = read_only + else: + log.warning(u"unknown XML element, falling back to textbox") + widget_type = "textbox" + widget_args[0] = element.toXml() + widget_kwargs["read_only"] = read_only + else: + raise exceptions.DataError(u"unknown extended type {ext_type}".format( + ext_type = field.ext_type)) + + elif field.fieldType == "fixed" or field.fieldType is None: widget_type = "text" if field.value is None: if field.label is None: - log.warning(_("Fixed field has neither value nor label, ignoring it")) + log.warning(_(u"Fixed field has neither value nor label, ignoring it")) field.value = "" else: field.value = field.label @@ -1011,6 +1032,26 @@ type = "textbox" +class XHTMLBoxWidget(StringWidget): + """Specialized textbox to manipulate XHTML""" + type = "xhtmlbox" + + def __init__(self, xmlui, value, name=None, parent=None, read_only=False, clean=True): + """ + @param clean(bool): if True, the XHTML is considered insecure and will be cleaned + Only set to False if you are absolutely sure that the XHTML is safe (in other + word, set to False only if you made the XHTML yourself) + """ + if clean: + if cleanXHTML is None: + raise exceptions.NotFound( + u"No cleaning method set, can't clean the XHTML") + value = cleanXHTML(value) + + super(XHTMLBoxWidget, self).__init__( + xmlui, value=value, name=name, parent=parent, read_only=read_only) + + class JidInputWidget(StringWidget): type = "jid_input" @@ -1623,6 +1664,11 @@ # Misc other funtions +def isXHTMLField(field): + """Check if a data_form.Field is an XHTML one""" + return (field.fieldType is None and field.ext_type == u"xml" and + field.value.uri == C.NS_XHTML) + class ElementParser(object): """callable class to parse XML string into Element"""