X-Git-Url: https://git.argeo.org/?a=blobdiff_plain;f=publishing%2Forg.argeo.publishing.ui%2Fsrc%2Forg%2Fargeo%2Fcms%2Ftext%2FMarkupValidatorCopy.java;fp=publishing%2Forg.argeo.publishing.ui%2Fsrc%2Forg%2Fargeo%2Fcms%2Ftext%2FMarkupValidatorCopy.java;h=1aee5d9281a0fcc961941454250872318c707b5c;hb=147ada7da5bf6292569f17a53a77fca04c97f707;hp=0000000000000000000000000000000000000000;hpb=5431f941fd6161e89f495a330c2ecddaf4f6bfb1;p=gpl%2Fargeo-suite.git diff --git a/publishing/org.argeo.publishing.ui/src/org/argeo/cms/text/MarkupValidatorCopy.java b/publishing/org.argeo.publishing.ui/src/org/argeo/cms/text/MarkupValidatorCopy.java new file mode 100644 index 0000000..1aee5d9 --- /dev/null +++ b/publishing/org.argeo.publishing.ui/src/org/argeo/cms/text/MarkupValidatorCopy.java @@ -0,0 +1,169 @@ +package org.argeo.cms.text; + +import java.io.StringReader; +import java.text.MessageFormat; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; + +import org.eclipse.rap.rwt.SingletonUtil; +import org.eclipse.swt.widgets.Widget; +import org.xml.sax.Attributes; +import org.xml.sax.InputSource; +import org.xml.sax.helpers.DefaultHandler; + +/** + * Copy of RAP v2.3 since it is in an internal package. + */ +class MarkupValidatorCopy { + + // Used by Eclipse Scout project + public static final String MARKUP_VALIDATION_DISABLED = "org.eclipse.rap.rwt.markupValidationDisabled"; + + private static final String DTD = createDTD(); + private static final Map SUPPORTED_ELEMENTS = createSupportedElementsMap(); + private final SAXParser saxParser; + + public static MarkupValidatorCopy getInstance() { + return SingletonUtil.getSessionInstance(MarkupValidatorCopy.class); + } + + public MarkupValidatorCopy() { + saxParser = createSAXParser(); + } + + public void validate(String text) { + StringBuilder markup = new StringBuilder(); + markup.append(DTD); + markup.append(""); + markup.append(text); + markup.append(""); + InputSource inputSource = new InputSource(new StringReader(markup.toString())); + try { + saxParser.parse(inputSource, new MarkupHandler()); + } catch (RuntimeException exception) { + throw exception; + } catch (Exception exception) { + throw new IllegalArgumentException("Failed to parse markup text", exception); + } + } + + public static boolean isValidationDisabledFor(Widget widget) { + return Boolean.TRUE.equals(widget.getData(MARKUP_VALIDATION_DISABLED)); + } + + private static SAXParser createSAXParser() { + SAXParser result = null; + SAXParserFactory parserFactory = SAXParserFactory.newInstance(); + try { + result = parserFactory.newSAXParser(); + } catch (Exception exception) { + throw new RuntimeException("Failed to create SAX parser", exception); + } + return result; + } + + private static String createDTD() { + StringBuilder result = new StringBuilder(); + result.append(""); + result.append(""); + result.append(""); + result.append(""); + result.append(""); + result.append(""); + result.append(""); + result.append(""); + result.append(""); + result.append(""); + result.append("]>"); + return result.toString(); + } + + private static Map createSupportedElementsMap() { + Map result = new HashMap(); + result.put("html", new String[0]); + result.put("br", new String[0]); + result.put("b", new String[] { "style" }); + result.put("strong", new String[] { "style" }); + result.put("i", new String[] { "style" }); + result.put("em", new String[] { "style" }); + result.put("sub", new String[] { "style" }); + result.put("sup", new String[] { "style" }); + result.put("big", new String[] { "style" }); + result.put("small", new String[] { "style" }); + result.put("del", new String[] { "style" }); + result.put("ins", new String[] { "style" }); + result.put("code", new String[] { "style" }); + result.put("samp", new String[] { "style" }); + result.put("kbd", new String[] { "style" }); + result.put("var", new String[] { "style" }); + result.put("cite", new String[] { "style" }); + result.put("dfn", new String[] { "style" }); + result.put("q", new String[] { "style" }); + result.put("abbr", new String[] { "style", "title" }); + result.put("span", new String[] { "style" }); + result.put("img", new String[] { "style", "src", "width", "height", "title", "alt" }); + result.put("a", new String[] { "style", "href", "target", "title" }); + return result; + } + + private static class MarkupHandler extends DefaultHandler { + + @Override + public void startElement(String uri, String localName, String name, Attributes attributes) { + checkSupportedElements(name, attributes); + checkSupportedAttributes(name, attributes); + checkMandatoryAttributes(name, attributes); + } + + private static void checkSupportedElements(String elementName, Attributes attributes) { + if (!SUPPORTED_ELEMENTS.containsKey(elementName)) { + throw new IllegalArgumentException("Unsupported element in markup text: " + elementName); + } + } + + private static void checkSupportedAttributes(String elementName, Attributes attributes) { + if (attributes.getLength() > 0) { + List supportedAttributes = Arrays.asList(SUPPORTED_ELEMENTS.get(elementName)); + int index = 0; + String attributeName = attributes.getQName(index); + while (attributeName != null) { + if (!supportedAttributes.contains(attributeName)) { + String message = "Unsupported attribute \"{0}\" for element \"{1}\" in markup text"; + message = MessageFormat.format(message, new Object[] { attributeName, elementName }); + throw new IllegalArgumentException(message); + } + index++; + attributeName = attributes.getQName(index); + } + } + } + + private static void checkMandatoryAttributes(String elementName, Attributes attributes) { + checkIntAttribute(elementName, attributes, "img", "width"); + checkIntAttribute(elementName, attributes, "img", "height"); + } + + private static void checkIntAttribute(String elementName, Attributes attributes, String checkedElementName, + String checkedAttributeName) { + if (checkedElementName.equals(elementName)) { + String attribute = attributes.getValue(checkedAttributeName); + try { + Integer.parseInt(attribute); + } catch (NumberFormatException exception) { + String message = "Mandatory attribute \"{0}\" for element \"{1}\" is missing or not a valid integer"; + Object[] arguments = new Object[] { checkedAttributeName, checkedElementName }; + message = MessageFormat.format(message, arguments); + throw new IllegalArgumentException(message); + } + } + } + + } + +}