]> git.argeo.org Git - lgpl/argeo-commons.git/blob - org.argeo.cms/src/org/argeo/cms/internal/text/MarkupValidatorCopy.java
- Improve CMS login (HTTP session now supported)
[lgpl/argeo-commons.git] / org.argeo.cms / src / org / argeo / cms / internal / text / MarkupValidatorCopy.java
1 package org.argeo.cms.internal.text;
2
3 import java.io.StringReader;
4 import java.text.MessageFormat;
5 import java.util.Arrays;
6 import java.util.HashMap;
7 import java.util.List;
8 import java.util.Map;
9
10 import javax.xml.parsers.SAXParser;
11 import javax.xml.parsers.SAXParserFactory;
12
13 import org.eclipse.rap.rwt.SingletonUtil;
14 import org.eclipse.swt.widgets.Widget;
15 import org.xml.sax.Attributes;
16 import org.xml.sax.InputSource;
17 import org.xml.sax.helpers.DefaultHandler;
18
19 /** Copy of RAP v2.3 since it is in an internal package. */
20 class MarkupValidatorCopy {
21
22 // Used by Eclipse Scout project
23 public static final String MARKUP_VALIDATION_DISABLED
24 = "org.eclipse.rap.rwt.markupValidationDisabled";
25
26 private static final String DTD = createDTD();
27 private static final Map<String, String[]> SUPPORTED_ELEMENTS = createSupportedElementsMap();
28 private final SAXParser saxParser;
29
30 public static MarkupValidatorCopy getInstance() {
31 return SingletonUtil.getSessionInstance( MarkupValidatorCopy.class );
32 }
33
34 public MarkupValidatorCopy() {
35 saxParser = createSAXParser();
36 }
37
38 public void validate( String text ) {
39 StringBuilder markup = new StringBuilder();
40 markup.append( DTD );
41 markup.append( "<html>" );
42 markup.append( text );
43 markup.append( "</html>" );
44 InputSource inputSource = new InputSource( new StringReader( markup.toString() ) );
45 try {
46 saxParser.parse( inputSource, new MarkupHandler() );
47 } catch( RuntimeException exception ) {
48 throw exception;
49 } catch( Exception exception ) {
50 throw new IllegalArgumentException( "Failed to parse markup text", exception );
51 }
52 }
53
54 public static boolean isValidationDisabledFor( Widget widget ) {
55 return Boolean.TRUE.equals( widget.getData( MARKUP_VALIDATION_DISABLED ) );
56 }
57
58 private static SAXParser createSAXParser() {
59 SAXParser result = null;
60 SAXParserFactory parserFactory = SAXParserFactory.newInstance();
61 try {
62 result = parserFactory.newSAXParser();
63 } catch( Exception exception ) {
64 throw new RuntimeException( "Failed to create SAX parser", exception );
65 }
66 return result;
67 }
68
69 private static String createDTD() {
70 StringBuilder result = new StringBuilder();
71 result.append( "<!DOCTYPE html [" );
72 result.append( "<!ENTITY quot \"&#34;\">" );
73 result.append( "<!ENTITY amp \"&#38;\">" );
74 result.append( "<!ENTITY apos \"&#39;\">" );
75 result.append( "<!ENTITY lt \"&#60;\">" );
76 result.append( "<!ENTITY gt \"&#62;\">" );
77 result.append( "<!ENTITY nbsp \"&#160;\">" );
78 result.append( "<!ENTITY ensp \"&#8194;\">" );
79 result.append( "<!ENTITY emsp \"&#8195;\">" );
80 result.append( "<!ENTITY ndash \"&#8211;\">" );
81 result.append( "<!ENTITY mdash \"&#8212;\">" );
82 result.append( "]>" );
83 return result.toString();
84 }
85
86 private static Map<String, String[]> createSupportedElementsMap() {
87 Map<String, String[]> result = new HashMap<String, String[]>();
88 result.put( "html", new String[ 0 ] );
89 result.put( "br", new String[ 0 ] );
90 result.put( "b", new String[] { "style" } );
91 result.put( "strong", new String[] { "style" } );
92 result.put( "i", new String[] { "style" } );
93 result.put( "em", new String[] { "style" } );
94 result.put( "sub", new String[] { "style" } );
95 result.put( "sup", new String[] { "style" } );
96 result.put( "big", new String[] { "style" } );
97 result.put( "small", new String[] { "style" } );
98 result.put( "del", new String[] { "style" } );
99 result.put( "ins", new String[] { "style" } );
100 result.put( "code", new String[] { "style" } );
101 result.put( "samp", new String[] { "style" } );
102 result.put( "kbd", new String[] { "style" } );
103 result.put( "var", new String[] { "style" } );
104 result.put( "cite", new String[] { "style" } );
105 result.put( "dfn", new String[] { "style" } );
106 result.put( "q", new String[] { "style" } );
107 result.put( "abbr", new String[] { "style", "title" } );
108 result.put( "span", new String[] { "style" } );
109 result.put( "img", new String[] { "style", "src", "width", "height", "title", "alt" } );
110 result.put( "a", new String[] { "style", "href", "target", "title" } );
111 return result;
112 }
113
114 private static class MarkupHandler extends DefaultHandler {
115
116 @Override
117 public void startElement( String uri, String localName, String name, Attributes attributes ) {
118 checkSupportedElements( name, attributes );
119 checkSupportedAttributes( name, attributes );
120 checkMandatoryAttributes( name, attributes );
121 }
122
123 private static void checkSupportedElements( String elementName, Attributes attributes ) {
124 if( !SUPPORTED_ELEMENTS.containsKey( elementName ) ) {
125 throw new IllegalArgumentException( "Unsupported element in markup text: " + elementName );
126 }
127 }
128
129 private static void checkSupportedAttributes( String elementName, Attributes attributes ) {
130 if( attributes.getLength() > 0 ) {
131 List<String> supportedAttributes = Arrays.asList( SUPPORTED_ELEMENTS.get( elementName ) );
132 int index = 0;
133 String attributeName = attributes.getQName( index );
134 while( attributeName != null ) {
135 if( !supportedAttributes.contains( attributeName ) ) {
136 String message = "Unsupported attribute \"{0}\" for element \"{1}\" in markup text";
137 message = MessageFormat.format( message, new Object[] { attributeName, elementName } );
138 throw new IllegalArgumentException( message );
139 }
140 index++;
141 attributeName = attributes.getQName( index );
142 }
143 }
144 }
145
146 private static void checkMandatoryAttributes( String elementName, Attributes attributes ) {
147 checkIntAttribute( elementName, attributes, "img", "width" );
148 checkIntAttribute( elementName, attributes, "img", "height" );
149 }
150
151 private static void checkIntAttribute( String elementName,
152 Attributes attributes,
153 String checkedElementName,
154 String checkedAttributeName )
155 {
156 if( checkedElementName.equals( elementName ) ) {
157 String attribute = attributes.getValue( checkedAttributeName );
158 try {
159 Integer.parseInt( attribute );
160 } catch( NumberFormatException exception ) {
161 String message
162 = "Mandatory attribute \"{0}\" for element \"{1}\" is missing or not a valid integer";
163 Object[] arguments = new Object[] { checkedAttributeName, checkedElementName };
164 message = MessageFormat.format( message, arguments );
165 throw new IllegalArgumentException( message );
166 }
167 }
168 }
169
170 }
171
172 }