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).
This commit is contained in:
parent
db0b00557a
commit
87871fabca
2 changed files with 52 additions and 2 deletions
|
|
@ -26,6 +26,7 @@ log = getLogger(__name__)
|
|||
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 @@ class TextSyntaxes(object):
|
|||
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
|
||||
|
|
|
|||
|
|
@ -41,6 +41,10 @@ SAT_PARAM_SEPARATOR = "_XMLUI_PARAM_" # used to have unique elements names
|
|||
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 @@ def _dataFormField2XMLUIData(field, read_only=False):
|
|||
"""
|
||||
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 @@ class TextBoxWidget(StringWidget):
|
|||
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 @@ def deferConfirm(*args, **kwargs):
|
|||
|
||||
# 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"""
|
||||
|
|
|
|||
Loading…
Reference in a new issue