Seam SVN: r8318 - trunk/ui/src/main/java/org/jboss/seam/ui/validator.
by seam-commits@lists.jboss.org
Author: christian.bauer(a)jboss.com
Date: 2008-06-02 07:54:08 -0400 (Mon, 02 Jun 2008)
New Revision: 8318
Modified:
trunk/ui/src/main/java/org/jboss/seam/ui/validator/FormattedTextValidator.java
Log:
JBSEAM-3061, better customizable FormattedTextValidator
Modified: trunk/ui/src/main/java/org/jboss/seam/ui/validator/FormattedTextValidator.java
===================================================================
--- trunk/ui/src/main/java/org/jboss/seam/ui/validator/FormattedTextValidator.java 2008-06-02 11:47:36 UTC (rev 8317)
+++ trunk/ui/src/main/java/org/jboss/seam/ui/validator/FormattedTextValidator.java 2008-06-02 11:54:08 UTC (rev 8318)
@@ -12,8 +12,7 @@
import org.jboss.seam.text.SeamTextLexer;
import org.jboss.seam.text.SeamTextParser;
-import antlr.RecognitionException;
-import antlr.TokenStreamException;
+import antlr.*;
/**
* Formatted Text validator
@@ -27,19 +26,24 @@
* and call the static convenience method
* <tt>FormattedTextValidator.getErrorMessage(originalText, recognitionException)</tt>
* if you want to display or log a nice error message.
- *
+ * </p>
+ * <p>
+ * Uses an instance of <tt>SeamTextParser</tt> by default, override if you require
+ * validation with your customized instance of <tt>SeamTextParser</tt>.
+ * </p>
+ *
* @author matthew.drees
* @author Christian Bauer
*/
-public class FormattedTextValidator implements javax.faces.validator.Validator,
- Serializable {
+public class FormattedTextValidator implements javax.faces.validator.Validator, Serializable {
+
private static final long serialVersionUID = 1L;
-
private static final int NUMBER_OF_CONTEXT_CHARS_AFTER = 10;
private static final int NUMBER_OF_CONTEXT_CHARS_BEFORE = 10;
+ private static final String END_OF_TEXT = "END OF TEXT";
+ String firstError;
+ String firstErrorDetail;
- String firstError;
-
/**
* Validate the given value as well-formed Seam Text. If there are parse
* errors, throw a ValidatorException including the first parse error.
@@ -47,6 +51,7 @@
public void validate(FacesContext context, UIComponent component,
Object value) throws ValidatorException {
firstError = null;
+ firstErrorDetail = null;
if (value == null) {
return;
}
@@ -56,9 +61,7 @@
+ value);
}
String text = (String) value;
- Reader r = new StringReader(text);
- SeamTextLexer lexer = new SeamTextLexer(r);
- SeamTextParser parser = new SeamTextParser(lexer);
+ SeamTextParser parser = getSeamTextParser(text);
try {
parser.startRule();
}
@@ -68,40 +71,146 @@
// Problem with the token input stream
throw new RuntimeException(tse);
} catch (RecognitionException re) {
- // A parser error, just log and swallow
+ // A parser error
if (firstError == null) {
- firstError = getErrorMessage(text, re);
+ firstError = getParserErrorMessage(text, re);
+ firstErrorDetail = re.getMessage().replace("\uFFFF",END_OF_TEXT);
}
}
if (firstError != null) {
- throw new ValidatorException(new FacesMessage("Invalid markup: "
- + firstError));
+ throw new ValidatorException(new FacesMessage(firstError, firstErrorDetail));
}
}
/**
+ * Override to instantiate a custom <tt>SeamTextLexer</tt> and <tt>SeamTextParser</tt>.
+ *
+ * @param text the raw markup text
+ * @return an instance of <tt>SeamTextParser</tt>
+ */
+ public SeamTextParser getSeamTextParser(String text) {
+ Reader r = new StringReader(text);
+ SeamTextLexer lexer = new SeamTextLexer(r);
+ return new SeamTextParser(lexer);
+ }
+
+ public String getParserErrorMessage(String originalText, RecognitionException re) {
+ String parserErrorMsg;
+ if (NoViableAltException.class.isAssignableFrom(re.getClass())) {
+ parserErrorMsg = getNoViableAltErrorMessage(
+ re.getMessage(),
+ getErrorLocation(originalText, re, getNumberOfCharsBeforeErrorLocation(), getNumberOfCharsAfterErrorLocation())
+ );
+ } else if (MismatchedTokenException.class.isAssignableFrom(re.getClass())) {
+ parserErrorMsg = getMismatchedTokenErrorMessage(
+ re.getMessage(),
+ getErrorLocation(originalText, re, getNumberOfCharsBeforeErrorLocation(), getNumberOfCharsAfterErrorLocation())
+ );
+ } else if (SemanticException.class.isAssignableFrom(re.getClass())) {
+ parserErrorMsg = getSemanticErrorMessage(re.getMessage());
+ } else {
+ parserErrorMsg = re.getMessage();
+ }
+ return parserErrorMsg;
+ }
+
+ public int getNumberOfCharsBeforeErrorLocation() {
+ return NUMBER_OF_CONTEXT_CHARS_BEFORE;
+ }
+
+ public int getNumberOfCharsAfterErrorLocation() {
+ return NUMBER_OF_CONTEXT_CHARS_AFTER;
+ }
+
+ /**
+ * Override (e.g. for i18n) ANTLR parser error messages.
+ *
+ * @param originalMessage the ANTLR parser error message of the RecognitionException
+ * @param location a snippet that indicates the location in the original markup, might be null
+ * @return a message that is thrown by this validator
+ */
+ public String getNoViableAltErrorMessage(String originalMessage, String location) {
+ return location != null
+ ? "Text parsing error at '..." + location.trim() + "...'."
+ : "Text parsing error, " + originalMessage.replace("\uFFFF",END_OF_TEXT);
+ }
+
+ /**
+ * Override (e.g. for i18n) ANTLR parser error messages.
+ *
+ * @param originalMessage the ANTLR parser error message of the RecognitionException
+ * @param location a snippet that indicates the location in the original markup, might be null
+ * @return a message that is thrown by this validator
+ */
+ public String getMismatchedTokenErrorMessage(String originalMessage, String location) {
+ return location != null
+ ? "Text parsing error at '..." + location.trim() + "...'."
+ : "Text parsing error, " + originalMessage.replace("\uFFFF",END_OF_TEXT);
+ }
+
+ /**
+ * Override (e.g. for i18n) ANTLR parser error messages.
+ *
+ * @param originalMessage the ANTLR parser error message of the RecognitionException
+ * @return a message that is thrown by this validator
+ */
+ public String getSemanticErrorMessage(String originalMessage) {
+ return "Text parsing error, " + originalMessage.replace("\uFFFF",END_OF_TEXT) + ".";
+ }
+
+ /**
* Extracts the error from the <tt>RecognitionException</tt> and generates
- * a message with some helpful context.
+ * a location of the error by extracting the original text at the exceptions
+ * line and column.
*
* @param originalText
* the original Seam Text markup as fed into the parser
* @param re
* an ANTLR <tt>RecognitionException</tt> thrown by the parser
+ * @param charsBefore
+ * characters before error location included in message
+ * @param charsAfter
+ * characters after error location included in message
* @return an error message with some helpful context about where the error
* occured
*/
- public static String getErrorMessage(String originalText,
- RecognitionException re) {
+ public static String getErrorLocation(String originalText, RecognitionException re, int charsBefore, int charsAfter) {
+ int beginIndex = Math.max(re.getColumn() - 1 - charsBefore, 0);
+ int endIndex = Math.min(re.getColumn() + charsAfter, originalText.length());
+
+ String location = null;
+
// Avoid IOOBE even if what we show is wrong, we need to figure out why the indexes are off sometimes
- int beginIndex = Math.max(re.getColumn() - 1 - NUMBER_OF_CONTEXT_CHARS_BEFORE, 0);
- int endIndex = Math.min(re.getColumn() + NUMBER_OF_CONTEXT_CHARS_AFTER, originalText.length());
- String snippet = originalText.length() > 50 ? originalText.substring(0, 50) : originalText;
if (beginIndex > 0 && beginIndex < endIndex && endIndex > 0 && endIndex < originalText.length())
- snippet = "..." + originalText.substring(beginIndex, endIndex) + "...";
+ location = originalText.substring(beginIndex, endIndex);
- String msg = re.getMessage() + " at '" + snippet + "'";
- return msg.replace("\n", " ").replace("\r", " ").replace("\uFFFF","END OF TEXT").replace("#{", "# {");
+ if (location == null) return location;
+
+ // Filter some dangerous characters we do not want in error messages
+ return location.replace("\n", " ").replace("\r", " ").replace("#{", "# {");
}
+
+ /**
+ * Extracts the error from the <tt>RecognitionException</tt> and generates
+ * a message including the location of the error.
+ *
+ * @param originalText
+ * the original Seam Text markup as fed into the parser
+ * @param re
+ * an ANTLR <tt>RecognitionException</tt> thrown by the parser
+ * @return an error message with some helpful context about where the error
+ * occured
+ */
+ public static String getErrorMessage(String originalText, RecognitionException re) {
+ return re.getMessage().replace("\uFFFF",END_OF_TEXT)
+ + " at '"
+ + getErrorLocation(
+ originalText, re,
+ NUMBER_OF_CONTEXT_CHARS_BEFORE, NUMBER_OF_CONTEXT_CHARS_AFTER
+ )
+ + "'";
+
+ }
}
16 years, 5 months
Seam SVN: r8317 - trunk.
by seam-commits@lists.jboss.org
Author: christian.bauer(a)jboss.com
Date: 2008-06-02 07:47:36 -0400 (Mon, 02 Jun 2008)
New Revision: 8317
Modified:
trunk/seam-text.g
Log:
JBSEAM-3058, customizable HTML/CSS sanitization for SeamTextParser
Modified: trunk/seam-text.g
===================================================================
--- trunk/seam-text.g 2008-06-02 10:50:09 UTC (rev 8316)
+++ trunk/seam-text.g 2008-06-02 11:47:36 UTC (rev 8317)
@@ -6,24 +6,359 @@
class SeamTextParser extends Parser;
options
{
- k=4;
- defaultErrorHandler=false;
+ k=4;
+ defaultErrorHandler=false;
}
{
- private java.util.Set htmlElements = new java.util.HashSet( java.util.Arrays.asList( new String[] { "a", "p", "q", "blockquote", "code", "pre", "table", "tr", "td", "th", "ul", "ol", "li", "b", "i", "u", "tt", "del", "em", "hr", "br", "div", "span", "h1", "h2", "h3", "h4", "img"} ) );
- private java.util.Set htmlAttributes = new java.util.HashSet( java.util.Arrays.asList( new String[] { "src", "href", "lang", "class", "id", "style", "width", "height", "name", "value", "type", "cellpadding", "cellspacing", "border" } ) );
+ public class Macro {
+ public String name;
+ public java.util.SortedMap<String,String> params = new java.util.TreeMap<String,String>();
- public class Macro {
- public String name;
- public java.util.SortedMap<String,String> params = new java.util.TreeMap<String,String>();
+ public Macro(String name) {
+ this.name = name;
+ }
+ }
- public Macro(String name) {
- this.name = name;
- }
- }
+ /**
+ * Sanitization of user input, used to clean links and plain HTML.
+ */
+ public interface Sanitizer {
- private Macro currentMacro;
-
+ /**
+ * Called by the SeamTextParser when a link tag is parsed, i.e. [=>some URI].
+ *
+ * @param uri the user-entered link text
+ * @throws SemanticException thrown if the URI is not syntactically or semantically valid
+ */
+ public void validateLinkTagURI(String uri) throws SemanticException;
+
+ /**
+ * Called by the SeamTextParser when a plain HTML element is parsed.
+ *
+ * @param element the token of the parse tree, call <tt>getText()</tt> to access the HTML tag name
+ * @throws SemanticException thrown when the HTML tag is not valid
+ */
+ public void validateHtmlElement(Token element) throws SemanticException;
+
+ /**
+ * Called by the SeamTextParser when a plain HTML attribute is parsed.
+ *
+ * @param element the token of the parse tree that represents the HTML tag
+ * @param attribute the token of the parse tree that represents the HTML attribute
+ * @throws SemanticException thrown if the attribute is not valid for the given HTML tag
+ */
+ public void validateHtmlAttribute(Token element, Token attribute) throws SemanticException;
+
+ /**
+ * Called by the SeamTextParser when a plain HTML attribute value is parsed.
+ *
+ * @param element the token of the parse tree that represents the HTML tag
+ * @param attribute the token of the parse tree that represents the HTML attribute
+ * @param attributeValue the plain string value of the HTML attribute
+ * @throws SemanticException thrown if the attribute value is not valid for the given HTML attribute and element
+ */
+ public void validateHtmlAttributeValue(Token element, Token attribute, String attributeValue) throws SemanticException;
+
+ public String getInvalidURIMessage(String uri);
+ public String getInvalidElementMessage(String elementName);
+ public String getInvalidAttributeMessage(String elementName, String attributeName);
+ public String getInvalidAttributeValueMessage(String elementName, String attributeName, String value);
+ }
+
+ /**
+ * Implementation of the rules in http://wiki.whatwg.org/wiki/Sanitization_rules
+ *
+ * Changes and additions:
+ *
+ * 1. Expanded all -* wildcard values to their full CSS property name (e.g. border-*).
+ *
+ * 2. Added dash as allowed characater to REGEX_VALID_CSS_STRING1.
+ *
+ * 3. Improved REGEX_VALID_CSS_VALUE with range {n,m} checks for color values and negative units.
+ *
+ * 4. Added more options (mostly of vertical-align property, e.g. "middle", "text-top") as allowed CSS values.
+ *
+ * 5. Added "max-height", "max-width", "min-height", "min-width" to CSS properties.
+ *
+ * 6. Removed 'data' URI scheme.
+ *
+ * 7. Not implemented filtering of CSS url() - it's an invalid value always.
+ *
+ */
+ public static class DefaultSanitizer implements SeamTextParser.Sanitizer {
+
+ public final java.util.regex.Pattern REGEX_VALID_CSS_STRING1 = java.util.regex.Pattern.compile(
+ "^([-:,;#%.\\sa-zA-Z0-9!]|\\w-\\w|'[\\s\\w]+'|\"[\\s\\w]+\"|\\([\\d,\\s]+\\))*$"
+ );
+
+ public final java.util.regex.Pattern REGEX_VALID_CSS_STRING2 = java.util.regex.Pattern.compile(
+ "^(\\s*[-\\w]+\\s*:\\s*[^:;]*(;|$))*$"
+ );
+
+ public final java.util.regex.Pattern REGEX_VALID_CSS_VALUE = java.util.regex.Pattern.compile(
+ "^(#[0-9a-f]{3,6}|rgb\\(\\d{1,3}%?,\\d{1,3}%?,?\\d{1,3}%?\\)?|-?\\d{0,2}\\.?\\d{0,2}(cm|em|ex|in|mm|pc|pt|px|%|,|\\))?)$"
+ );
+
+ public final java.util.regex.Pattern REGEX_INVALID_CSS_URL = java.util.regex.Pattern.compile(
+ "url\\s*\\(\\s*[^\\s)]+?\\s*\\)\\s*"
+ );
+
+ protected java.util.Set<String> acceptableElements = new java.util.HashSet(java.util.Arrays.asList(
+ "a", "abbr", "acronym", "address", "area", "b", "bdo", "big", "blockquote",
+ "br", "button", "caption", "center", "cite", "code", "col", "colgroup", "dd",
+ "del", "dfn", "dir", "div", "dl", "dt", "em", "fieldset", "font", "form",
+ "h1", "h2", "h3", "h4", "h5", "h6", "hr", "i", "img", "input", "ins", "kbd",
+ "label", "legend", "li", "map", "menu", "ol", "optgroup", "option", "p",
+ "pre", "q", "s", "samp", "select", "small", "span", "strike", "strong",
+ "sub", "sup", "table", "tbody", "td", "textarea", "tfoot", "th", "thead",
+ "tr", "tt", "u", "ul", "var", "wbr"
+ ));
+
+ protected java.util.Set<String> mathmlElements = new java.util.HashSet(java.util.Arrays.asList(
+ "maction", "math", "merror", "mfrac", "mi", "mmultiscripts", "mn", "mo",
+ "mover", "mpadded", "mphantom", "mprescripts", "mroot", "mrow", "mspace",
+ "msqrt", "mstyle", "msub", "msubsup", "msup", "mtable", "mtd", "mtext",
+ "mtr", "munder", "munderover", "none"
+ ));
+
+ protected java.util.Set<String> svgElements = new java.util.HashSet(java.util.Arrays.asList(
+ "a", "animate", "animateColor", "animateMotion", "animateTransform",
+ "circle", "defs", "desc", "ellipse", "font-face", "font-face-name",
+ "font-face-src", "g", "glyph", "hkern", "image", "line", "linearGradient",
+ "marker", "metadata", "missing-glyph", "mpath", "path", "polygon",
+ "polyline", "radialGradient", "rect", "set", "stop", "svg", "switch", "text",
+ "title", "tspan", "use"
+ ));
+
+ protected java.util.Set<String> acceptableAttributes = new java.util.HashSet(java.util.Arrays.asList(
+ "abbr", "accept", "accept-charset", "accesskey", "action", "align", "alt",
+ "axis", "border", "cellpadding", "cellspacing", "char", "charoff", "charset",
+ "checked", "cite", "class", "clear", "color", "cols", "colspan", "compact",
+ "coords", "datetime", "dir", "disabled", "enctype", "for", "frame",
+ "headers", "height", "href", "hreflang", "hspace", "id", "ismap", "label",
+ "lang", "longdesc", "maxlength", "media", "method", "multiple", "name",
+ "nohref", "noshade", "nowrap", "prompt", "readonly", "rel", "rev", "rows",
+ "rowspan", "rules", "scope", "selected", "shape", "size", "span", "src",
+ "start", "style", "summary", "tabindex", "target", "title", "type", "usemap",
+ "valign", "value", "vspace", "width", "xml:lang"
+ ));
+
+ protected java.util.Set<String> mathmlAttributes = new java.util.HashSet(java.util.Arrays.asList(
+ "actiontype", "align", "columnalign", "columnalign", "columnalign",
+ "columnlines", "columnspacing", "columnspan", "depth", "display",
+ "displaystyle", "equalcolumns", "equalrows", "fence", "fontstyle",
+ "fontweight", "frame", "height", "linethickness", "lspace", "mathbackground",
+ "mathcolor", "mathvariant", "mathvariant", "maxsize", "minsize", "other",
+ "rowalign", "rowalign", "rowalign", "rowlines", "rowspacing", "rowspan",
+ "rspace", "scriptlevel", "selection", "separator", "stretchy", "width",
+ "width", "xlink:href", "xlink:show", "xlink:type", "xmlns", "xmlns:xlink"
+ ));
+
+ protected java.util.Set<String> svgAttributes = new java.util.HashSet(java.util.Arrays.asList(
+ "accent-height", "accumulate", "additive", "alphabetic", "arabic-form",
+ "ascent", "attributeName", "attributeType", "baseProfile", "bbox", "begin",
+ "by", "calcMode", "cap-height", "class", "color", "color-rendering",
+ "content", "cx", "cy", "d", "descent", "display", "dur", "dx", "dy", "end",
+ "fill", "fill-rule", "font-family", "font-size", "font-stretch",
+ "font-style", "font-variant", "font-weight", "from", "fx", "fy", "g1", "g2",
+ "glyph-name", "gradientUnits", "hanging", "height", "horiz-adv-x",
+ "horiz-origin-x", "id", "ideographic", "k", "keyPoints", "keySplines",
+ "keyTimes", "lang", "marker-end", "marker-mid", "marker-start",
+ "markerHeight", "markerUnits", "markerWidth", "mathematical", "max", "min",
+ "name", "offset", "opacity", "orient", "origin", "overline-position",
+ "overline-thickness", "panose-1", "path", "pathLength", "points",
+ "preserveAspectRatio", "r", "refX", "refY", "repeatCount", "repeatDur",
+ "requiredExtensions", "requiredFeatures", "restart", "rotate", "rx", "ry",
+ "slope", "stemh", "stemv", "stop-color", "stop-opacity",
+ "strikethrough-position", "strikethrough-thickness", "stroke",
+ "stroke-dasharray", "stroke-dashoffset", "stroke-linecap", "stroke-linejoin",
+ "stroke-miterlimit", "stroke-opacity", "stroke-width", "systemLanguage",
+ "target", "text-anchor", "to", "transform", "type", "u1", "u2",
+ "underline-position", "underline-thickness", "unicode", "unicode-range",
+ "units-per-em", "values", "version", "viewBox", "visibility", "width",
+ "widths", "x", "x-height", "x1", "x2", "xlink:actuate", "xlink:arcrole",
+ "xlink:href", "xlink:role", "xlink:show", "xlink:title", "xlink:type",
+ "xml:base", "xml:lang", "xml:space", "xmlns", "xmlns:xlink", "y", "y1", "y2",
+ "zoomAndPan"
+ ));
+
+ protected java.util.Set<String> styleProperties = new java.util.HashSet(java.util.Arrays.asList(
+ "azimuth",
+ "background", "background-attachment", "background-color", "background-image",
+ "background-position", "background-repeat",
+ "border", "border-bottom", "border-bottom-color", "border-bottom-style",
+ "border-bottom-width", "border-collapse", "border-color", "border-left",
+ "border-left-color", "border-left-style", "border-left-width", "border-right",
+ "border-right-color", "border-right-style", "border-right-width", "border-spacing",
+ "border-style", "border-top", "border-top-color", "border-top-style",
+ "border-top-width", "border-width",
+ "clear", "color",
+ "cursor", "direction", "display", "elevation", "float", "font",
+ "font-family", "font-size", "font-style", "font-variant", "font-weight",
+ "height", "letter-spacing", "line-height",
+ "margin", "margin-bottom", "margin-left", "margin-right", "margin-top",
+ "max-height", "max-width", "min-height", "min-width",
+ "overflow",
+ "padding", "padding-bottom", "padding-left", "padding-right", "padding-top",
+ "pause", "pause-after", "pause-before", "pitch",
+ "pitch-range", "richness", "speak", "speak-header", "speak-numeral",
+ "speak-punctuation", "speech-rate", "stress", "text-align",
+ "text-decoration", "text-indent", "unicode-bidi", "vertical-align",
+ "voice-family", "volume", "white-space", "width"
+ ));
+
+ protected java.util.Set<String> stylePropertiesValues = new java.util.HashSet(java.util.Arrays.asList(
+ "aqua", "auto", "baseline", "black", "block", "blue", "bold", "both", "bottom", "brown",
+ "center", "collapse", "dashed", "dotted", "fuchsia", "gray", "green",
+ "inherit", "italic", "left", "length", "lime", "maroon", "medium", "middle", "navy", "none", "normal",
+ "nowrap", "olive", "percentage", "pointer", "purple", "red", "right", "silver", "solid", "sub", "super",
+ "teal", "text-bottom", "text-top", "top", "transparent", "underline", "white", "yellow"
+ ));
+
+ protected java.util.Set<String> svgStyleProperties = new java.util.HashSet(java.util.Arrays.asList(
+ "fill", "fill-opacity", "fill-rule", "stroke", "stroke-linecap",
+ "stroke-linejoin", "stroke-opacity", "stroke-width"
+ ));
+
+ protected java.util.Set<String> attributesWhoseValueIsAURI = new java.util.HashSet(java.util.Arrays.asList(
+ "action", "cite", "href", "longdesc", "src", "xlink:href", "xml:base"
+ ));
+
+ protected java.util.Set<String> uriSchemes = new java.util.HashSet(java.util.Arrays.asList(
+ "afs", "aim", "callto", "ed2k", "feed", "ftp", "gopher", "http", "https",
+ "irc", "mailto", "news", "nntp", "rsync", "rtsp", "sftp", "ssh", "tag",
+ "tel", "telnet", "urn", "webcal", "wtai", "xmpp"
+ ));
+
+ public void validateLinkTagURI(String uri) throws SemanticException {
+ if (!validateURI(uri)) {
+ throw new SemanticException("Invalid URI");
+ }
+ }
+
+ public void validateHtmlElement(Token element) throws SemanticException {
+ String elementName = element.getText().toLowerCase();
+
+ if (!acceptableElements.contains(elementName) &&
+ !svgElements.contains(elementName) &&
+ !mathmlElements.contains(elementName)) {
+ throw new SemanticException(getInvalidElementMessage(elementName));
+ }
+ }
+
+ public void validateHtmlAttribute(Token element, Token attribute) throws SemanticException {
+ String elementName = element.getText().toLowerCase();
+ String attributeName = attribute.getText().toLowerCase();
+ if (!acceptableAttributes.contains(attributeName) &&
+ !svgAttributes.contains(attributeName) &&
+ !mathmlAttributes.contains(attributeName)) {
+ throw new SemanticException(getInvalidAttributeMessage(elementName, attributeName));
+ }
+ }
+
+ public void validateHtmlAttributeValue(Token element,
+ Token attribute,
+ String attributeValue) throws SemanticException {
+
+ String elementName = element.getText().toLowerCase();
+ String attributeName = attribute.getText().toLowerCase();
+
+ // Check element with attribute that has URI value (href, src, etc.)
+ if (attributesWhoseValueIsAURI.contains(attributeName) && !validateURI(attributeValue)) {
+ throw new SemanticException(getInvalidURIMessage(attributeValue));
+ }
+
+ // Check attribute value of style (CSS filtering)
+ if (attributeName.equals("style")) {
+ if (!REGEX_VALID_CSS_STRING1.matcher(attributeValue).matches() ||
+ !REGEX_VALID_CSS_STRING2.matcher(attributeValue).matches()) {
+ throw new SemanticException(getInvalidAttributeValueMessage(elementName, attributeName, attributeValue));
+ }
+
+ String[] cssProperties = attributeValue.split(";");
+ for (String cssProperty : cssProperties) {
+ if (!cssProperty.contains(":")) {
+ throw new SemanticException(getInvalidAttributeValueMessage(elementName, attributeName, attributeValue));
+ }
+ String[] property = cssProperty.split(":");
+ String propertyName = property[0].trim();
+ String propertyValue = property.length == 2 ? property[1].trim() : null;
+
+ // CSS property name
+ if (!styleProperties.contains(propertyName) &&
+ !svgStyleProperties.contains(propertyName)) {
+ throw new SemanticException(getInvalidAttributeValueMessage(elementName, attributeName, attributeValue));
+ }
+
+ // CSS property value
+ if (!stylePropertiesValues.contains(propertyValue)) {
+ // Not in list, now check the regex
+ if (!REGEX_VALID_CSS_VALUE.matcher(propertyValue).matches()) {
+ throw new SemanticException(getInvalidAttributeValueMessage(elementName, attributeName, attributeValue));
+ }
+ }
+ }
+ }
+
+ // TODO: Implement SVG style checking?! Who cares...
+ }
+
+ /**
+ * Validate a URI string.
+ * <p>
+ * The default implementation accepts any URI string that starts with a slash,
+ * this is considered a relative URL. Any absolute URI is parsed by the JDK with
+ * the <tt>java.net.URI</tt> constructor. Finally, the scheme of the parsed
+ * absolute URI is checked with a list of valid schemes.
+ * </p>
+ *
+ * @param uri the URI string
+ * @return return true if the String represents a safe and valid URI
+ */
+ protected boolean validateURI(String uri) {
+
+ // Relative URI starts with a slash
+ if (uri.startsWith("/")) return true;
+
+ java.net.URI parsedURI;
+ try {
+ parsedURI = new java.net.URI(uri);
+ } catch (java.net.URISyntaxException ex) {
+ return false;
+ }
+
+ if (!uriSchemes.contains(parsedURI.getScheme())) {
+ return false;
+ }
+ return true;
+ }
+
+ public String getInvalidURIMessage(String uri) {
+ return "invalid URI";
+ }
+
+ public String getInvalidElementMessage(String elementName) {
+ return "invalid element '" + elementName + "'";
+ }
+
+ public String getInvalidAttributeMessage(String elementName, String attributeName) {
+ return "invalid attribute '" + attributeName + "' for element '" + elementName + "'";
+ }
+
+ public String getInvalidAttributeValueMessage(String elementName, String attributeName, String value) {
+ return "invalid value of attribute '" + attributeName + "' for element '" + elementName + "'";
+ };
+
+ }
+
+ private Sanitizer sanitizer = new DefaultSanitizer();
+ public void setSanitizer(Sanitizer sanitizer) {
+ this.sanitizer = sanitizer;
+ }
+
+ private Macro currentMacro;
+ private java.util.Stack<Token> htmlElementStack = new java.util.Stack<Token>();
+
private StringBuilder mainBuilder = new StringBuilder();
private StringBuilder builder = mainBuilder;
@@ -38,19 +373,7 @@
private static boolean hasMultiple(String string, char c) {
return string.indexOf(c)!=string.lastIndexOf(c);
}
-
- private void validateElement(Token t) throws NoViableAltException {
- if ( !htmlElements.contains( t.getText().toLowerCase() ) ) {
- throw new NoViableAltException(t, null);
- }
- }
- private void validateAttribute(Token t) throws NoViableAltException {
- if ( !htmlAttributes.contains( t.getText().toLowerCase() ) ) {
- throw new NoViableAltException(t, null);
- }
- }
-
private void beginCapture() {
builder = new StringBuilder();
}
@@ -200,7 +523,11 @@
EQ GT
{ beginCapture(); }
attributeValue
- { String link = endCapture(); append(linkTag(text, link)); }
+ {
+ String link = endCapture();
+ sanitizer.validateLinkTagURI(link);
+ append(linkTag(text, link));
+ }
CLOSE
;
@@ -342,22 +669,54 @@
body: (plain|formatted|preformatted|quoted|html|list|newline)*
;
-openTag: LT name:ALPHANUMERICWORD { validateElement(name); append("<"); append(name.getText()); }
+openTag:
+ LT name:ALPHANUMERICWORD
+ {
+ htmlElementStack.push(name);
+ sanitizer.validateHtmlElement(name);
+ append("<");
+ append(name.getText());
+ }
;
-
+
beforeBody: GT { append(">"); }
;
-closeTagWithBody: LT SLASH name:ALPHANUMERICWORD GT { append("</"); append(name.getText()); append(">"); }
+closeTagWithBody:
+ LT SLASH name:ALPHANUMERICWORD GT
+ {
+ append("</");
+ append(name.getText());
+ append(">");
+ htmlElementStack.pop();
+ }
;
-closeTagWithNoBody: SLASH GT { append("/>"); }
+closeTagWithNoBody:
+ SLASH GT
+ {
+ append("/>");
+ htmlElementStack.pop();
+ }
;
attribute: att:ALPHANUMERICWORD (space)* EQ (space)*
- DOUBLEQUOTE { validateAttribute(att); append(att.getText()); append("=\""); }
- attributeValue
- DOUBLEQUOTE { append("\""); }
+ DOUBLEQUOTE
+ {
+ sanitizer.validateHtmlAttribute(htmlElementStack.peek(), att);
+ append(att.getText());
+ append("=\"");
+ }
+ {
+ beginCapture();
+ }
+ attributeValue
+ {
+ String attValue = endCapture();
+ sanitizer.validateHtmlAttributeValue(htmlElementStack.peek(), att, attValue);
+ append(attValue);
+ }
+ DOUBLEQUOTE { append("\""); }
;
attributeValue: ( AMPERSAND { append("&"); } |
16 years, 5 months
Seam SVN: r8316 - in trunk/ui/src/main/java/org/jboss/seam/ui: component/html and 1 other directories.
by seam-commits@lists.jboss.org
Author: pete.muir(a)jboss.org
Date: 2008-06-02 06:50:09 -0400 (Mon, 02 Jun 2008)
New Revision: 8316
Removed:
trunk/ui/src/main/java/org/jboss/seam/ui/component/UILoadStyle.java
trunk/ui/src/main/java/org/jboss/seam/ui/component/html/HtmlLoadStyle.java
trunk/ui/src/main/java/org/jboss/seam/ui/resource/SafeStyleResources.java
trunk/ui/src/main/java/org/jboss/seam/ui/resource/StyleResource.java
Log:
JBSEAM-2496
Deleted: trunk/ui/src/main/java/org/jboss/seam/ui/component/UILoadStyle.java
===================================================================
--- trunk/ui/src/main/java/org/jboss/seam/ui/component/UILoadStyle.java 2008-06-02 10:47:51 UTC (rev 8315)
+++ trunk/ui/src/main/java/org/jboss/seam/ui/component/UILoadStyle.java 2008-06-02 10:50:09 UTC (rev 8316)
@@ -1,84 +0,0 @@
-package org.jboss.seam.ui.component;
-
-import java.io.UnsupportedEncodingException;
-
-import javax.faces.component.NamingContainer;
-import javax.faces.component.UIComponent;
-import javax.faces.component.UIParameter;
-import javax.faces.context.FacesContext;
-
-import org.ajax4jsf.component.html.HtmlLoadStyle;
-import org.jboss.seam.navigation.Pages;
-import org.jboss.seam.ui.resource.SafeStyleResources;
-import org.jboss.seam.ui.resource.StyleResource;
-import org.jboss.seam.ui.util.UrlBuilder;
-import org.jboss.seam.util.Reflections;
-
-public abstract class UILoadStyle extends HtmlLoadStyle
-{
-
- @Override
- public Object getSrc()
- {
-
- UIConversationId uiConversationId = UIConversationId.newInstance();
- uiConversationId.setViewId(Pages.getViewId(getFacesContext()));
- String src = super.getSrc() != null ? super.getSrc().toString() : null;
- SafeStyleResources.instance().addSafeStyleResource(src);
- try
- {
- UrlBuilder urlBuilder = new UrlBuilder(StyleResource.WEB_RESOURCE_PATH + src, null, FacesContext.getCurrentInstance().getResponseWriter().getCharacterEncoding());
- urlBuilder.addParameter(uiConversationId);
- if (isIsolated())
- {
- UIComponent namingContainer = getParentNamingContainer(this);
- if (namingContainer != null)
- {
- UIParameter idPrefix = new UIParameter();
- idPrefix.setName("idPrefix");
- urlBuilder.addParameter("idPrefix", namingContainer.getClientId(getFacesContext()));
- }
- }
- return urlBuilder.getEncodedUrl();
- }
- catch (UnsupportedEncodingException e)
- {
- throw new RuntimeException(e);
- }
- }
-
- public abstract boolean isIsolated();
-
-
- public abstract void setIsolated(boolean isolated);
-
-
- private UIComponent getParentNamingContainer(UIComponent cmp)
- {
- if (cmp == null)
- {
- return null;
- }
- else if (cmp instanceof NamingContainer)
- {
- return cmp;
- }
- else
- {
- return getParentNamingContainer(cmp.getParent());
- }
- }
-
- public static UILoadStyle newInstance() {
- // Avoid runtime dep on a4j
- try
- {
- return (UILoadStyle) Reflections.classForName("org.jboss.seam.ui.component.html.HtmlLoadStyle").newInstance();
- }
- catch (Exception e)
- {
- throw new RuntimeException("Error loading UILoadStyle");
- }
- }
-
-}
\ No newline at end of file
Deleted: trunk/ui/src/main/java/org/jboss/seam/ui/component/html/HtmlLoadStyle.java
===================================================================
--- trunk/ui/src/main/java/org/jboss/seam/ui/component/html/HtmlLoadStyle.java 2008-06-02 10:47:51 UTC (rev 8315)
+++ trunk/ui/src/main/java/org/jboss/seam/ui/component/html/HtmlLoadStyle.java 2008-06-02 10:50:09 UTC (rev 8316)
@@ -1,108 +0,0 @@
-/**
- * GENERATED FILE - DO NOT EDIT
- *
- */
-
-package org.jboss.seam.ui.component.html;
-
-import javax.faces.context.FacesContext;
-import javax.faces.el.ValueBinding;
-
-/**
- * Component-Type org.jboss.seam.ui.LoadStyle
- * Component-Family org.ajax4jsf.LoadStyle
- * Add a stylesheet to the &lt;head&gt; of the page. Any EL in the CSS will be resolved.
- */
- public class HtmlLoadStyle extends org.jboss.seam.ui.component.UILoadStyle {
-
- public static final String COMPONENT_TYPE = "org.jboss.seam.ui.LoadStyle";
-
- /**
- * Constructor to init default renderers
- */
- public HtmlLoadStyle (){
- }
-
-// Component properties fields
- /**
- * isolated
- * If isolated, any references to html ids will be resolved only within
- this naming container
- */
- private boolean _isolated = false;
- /**
- * Flag indicated what isolated is set.
- */
- private boolean _isolatedSet = false;
-
-// Getters-setters
- /**
- * If isolated, any references to html ids will be resolved only within
- this naming container
- * Setter for isolated
- * @param __isolated - new value
- */
- @Override
- public void setIsolated( boolean __isolated ){
- this._isolated = __isolated;
- this._isolatedSet = true;
- }
-
-
- /**
- * If isolated, any references to html ids will be resolved only within
- this naming container
- * Getter for isolated
- * @return isolated value from local variable or value bindings
- */
- @Override
- public boolean isIsolated( ){
- if(this._isolatedSet){
- return this._isolated;
- }
- ValueBinding vb = getValueBinding("isolated");
- if (vb != null) {
- Boolean value = (Boolean) vb.getValue(getFacesContext());
- if (null == value) {
- return this._isolated;
- }
- return (value.booleanValue());
- } else {
- return (this._isolated);
- }
- }
-
-// Component family.
- public static final String COMPONENT_FAMILY = "org.ajax4jsf.LoadStyle";
-
- @Override
- public String getFamily() {
- return COMPONENT_FAMILY;
- }
-
-// Save state
-// ----------------------------------------------------- StateHolder Methods
-
- @Override
- public Object saveState(FacesContext context) {
- Object values[] = new Object[3];
- values[0] = super.saveState(context);
- values[1] = new Boolean(_isolated);
- values[2] = Boolean.valueOf(_isolatedSet);
-
- return values;
- }
-
- @Override
- public void restoreState(FacesContext context, Object state) {
- Object values[] = (Object[]) state;
- super.restoreState(context, values[0]);
- _isolated = ((Boolean)values[1]).booleanValue();
- _isolatedSet = ((Boolean)values[2]).booleanValue();
-
-
-
- }
-// Utilites
-
-}
\ No newline at end of file
Deleted: trunk/ui/src/main/java/org/jboss/seam/ui/resource/SafeStyleResources.java
===================================================================
--- trunk/ui/src/main/java/org/jboss/seam/ui/resource/SafeStyleResources.java 2008-06-02 10:47:51 UTC (rev 8315)
+++ trunk/ui/src/main/java/org/jboss/seam/ui/resource/SafeStyleResources.java 2008-06-02 10:50:09 UTC (rev 8316)
@@ -1,51 +0,0 @@
-package org.jboss.seam.ui.resource;
-
-import static org.jboss.seam.ScopeType.APPLICATION;
-import static org.jboss.seam.annotations.Install.BUILT_IN;
-
-import java.util.HashSet;
-import java.util.Set;
-
-import org.jboss.seam.Component;
-import org.jboss.seam.annotations.Install;
-import org.jboss.seam.annotations.Name;
-import org.jboss.seam.annotations.Scope;
-import org.jboss.seam.annotations.intercept.BypassInterceptors;
-import org.jboss.seam.contexts.Contexts;
-
-@Scope(APPLICATION)
-@Name("org.jboss.seam.ui.resource.safeStyleResources")
-@BypassInterceptors
-@Install(precedence = BUILT_IN)
-public class SafeStyleResources
-{
-
- private Set<String> safeStyleResources = new HashSet<String>();
-
- public void addSafeStyleResource(String path)
- {
- this.safeStyleResources.add(path);
- }
-
- public boolean isStyleResourceSafe(String path)
- {
- if (safeStyleResources.contains(path))
- {
- return true;
- }
- else
- {
- return false;
- }
- }
-
- public static SafeStyleResources instance()
- {
- if ( !Contexts.isApplicationContextActive() )
- {
- throw new IllegalStateException("No active application context");
- }
- return (SafeStyleResources) (Component.getInstance(SafeStyleResources.class));
- }
-
-}
Deleted: trunk/ui/src/main/java/org/jboss/seam/ui/resource/StyleResource.java
===================================================================
--- trunk/ui/src/main/java/org/jboss/seam/ui/resource/StyleResource.java 2008-06-02 10:47:51 UTC (rev 8315)
+++ trunk/ui/src/main/java/org/jboss/seam/ui/resource/StyleResource.java 2008-06-02 10:50:09 UTC (rev 8316)
@@ -1,160 +0,0 @@
-package org.jboss.seam.ui.resource;
-
-import static org.jboss.seam.ScopeType.APPLICATION;
-import static org.jboss.seam.annotations.Install.BUILT_IN;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.jboss.seam.annotations.Install;
-import org.jboss.seam.annotations.Name;
-import org.jboss.seam.annotations.Scope;
-import org.jboss.seam.annotations.intercept.BypassInterceptors;
-import org.jboss.seam.core.Expressions;
-import org.jboss.seam.log.Log;
-import org.jboss.seam.log.LogProvider;
-import org.jboss.seam.log.Logging;
-import org.jboss.seam.servlet.ContextualHttpServletRequest;
-import org.jboss.seam.util.Resources;
-import org.jboss.seam.web.AbstractResource;
-
-/**
- * Serve up stylesheets which are have been run through the EL Interpolator.
- *
- * @author pmuir
- *
- */
-@Scope(APPLICATION)
-@Name("org.jboss.seam.ui.resource.styleResource")
-@Install(precedence = BUILT_IN)
-@BypassInterceptors
-public class StyleResource extends AbstractResource
-{
-
- private LogProvider log = Logging.getLogProvider(StyleResource.class);
-
- private static final Pattern EL_PATTERN = Pattern.compile("#" + Pattern.quote("{") + "(.*)"
- + Pattern.quote("}"));
-
- private static final Pattern ID_PATTERN = Pattern.compile("#([A-Za-z][A-Za-z0-9\\-\\_\\:\\.]*)");
-
- public static final String WEB_RESOURCE_PATH = "/seam/resource/style";
-
- private static final String RESOURCE_PATH = "/style";
-
- @Override
- public void getResource(final HttpServletRequest request, final HttpServletResponse response)
- throws ServletException, IOException
- {
-
- new ContextualHttpServletRequest(request)
- {
- @Override
- public void process() throws IOException
- {
- doWork(request, response);
- }
- }.run();
-
- }
-
- public void doWork(HttpServletRequest request, HttpServletResponse response)
- throws IOException
- {
- String pathInfo = request.getPathInfo().substring(getResourcePath().length());
- if (!SafeStyleResources.instance().isStyleResourceSafe(pathInfo))
- {
- log.warn(pathInfo + " isn't recognized as a valid stylesheet");
- response.sendError(HttpServletResponse.SC_NOT_FOUND);
- return;
- }
- InputStream in = Resources.getResourceAsStream( pathInfo, getServletContext() );
-
- if (in != null)
- {
- CharSequence css = readFile(in);
- css = parseEL(css);
- String idPrefix = request.getParameter("idPrefix");
- css = addIdPrefix(idPrefix, css);
- response.getWriter().write(css.toString());
- response.getWriter().flush();
- }
- else
- {
- response.sendError(HttpServletResponse.SC_NOT_FOUND);
- }
-
- }
-
- // Resolve any EL value binding expression present in CSS
- // This should be Interpolator.interpolate, but it seems to break on CSS
- private CharSequence parseEL(CharSequence string)
- {
- StringBuffer parsed = new StringBuffer(string.length());
- Matcher matcher =
- EL_PATTERN.matcher(string);
-
- while (matcher.find())
- {
- String result = Expressions.instance().createValueExpression("#{"+matcher.group(1)+"}", String.class).getValue();
- if (result != null)
- {
- matcher.appendReplacement(parsed, result);
- }
- else
- {
- matcher.appendReplacement(parsed, "");
- }
- }
- matcher.appendTail(parsed);
- return parsed;
- }
-
- private CharSequence readFile(InputStream inputStream) throws IOException
- {
- BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
- StringBuilder css = new StringBuilder();
- String line;
- while ((line = reader.readLine()) != null)
- {
- css.append(line);
- css.append("\n");
- }
- inputStream.close();
- return css;
- }
-
- private CharSequence addIdPrefix(String idPrefix, CharSequence string)
- {
- StringBuffer parsed = new StringBuffer(string.length());
- if (idPrefix != null)
- {
- Matcher matcher = ID_PATTERN.matcher(string);
- while (matcher.find()) {
- String result = "#" + idPrefix + ":" + matcher.group(1);
- matcher.appendReplacement(parsed, result);
- }
- matcher.appendTail(parsed);
- return parsed;
- }
- else
- {
- return string;
- }
- }
-
- @Override
- public String getResourcePath()
- {
- return RESOURCE_PATH;
- }
-
-}
16 years, 5 months
Seam SVN: r8315 - trunk/ui/src/main/java/org/jboss/seam/ui/graphicImage and 1 other directory.
by seam-commits@lists.jboss.org
Author: pete.muir(a)jboss.org
Date: 2008-06-02 06:47:51 -0400 (Mon, 02 Jun 2008)
New Revision: 8315
Modified:
branches/Seam_2_0/ui/src/main/java/org/jboss/seam/ui/graphicImage/GraphicImageRendererBase.java
trunk/ui/src/main/java/org/jboss/seam/ui/graphicImage/GraphicImageRendererBase.java
Log:
Oops, wrong branch for JBSEAM-2517
Modified: branches/Seam_2_0/ui/src/main/java/org/jboss/seam/ui/graphicImage/GraphicImageRendererBase.java
===================================================================
--- branches/Seam_2_0/ui/src/main/java/org/jboss/seam/ui/graphicImage/GraphicImageRendererBase.java 2008-06-02 10:35:00 UTC (rev 8314)
+++ branches/Seam_2_0/ui/src/main/java/org/jboss/seam/ui/graphicImage/GraphicImageRendererBase.java 2008-06-02 10:47:51 UTC (rev 8315)
@@ -46,14 +46,10 @@
extension = image.getContentType().getExtension();
writer.startElement(HTML.IMG_ELEM, graphicImage);
- if (graphicImage.getId() != null)
- {
- writer.writeAttribute(HTML.ID_ATTR, graphicImage.getClientId(context), HTML.ID_ATTR);
- }
-
String url = context.getExternalContext().getRequestContextPath()
+ GraphicImageResource.GRAPHIC_IMAGE_RESOURCE_PATH + "/" + key + extension;
writer.writeAttribute(HTML.SRC_ATTR, url, HTML.SRC_ATTR);
+
HTML.renderHTMLAttributes(writer, component, HTML.IMG_PASSTHROUGH_ATTRIBUTES);
writer.endElement(HTML.IMG_ELEM);
}
Modified: trunk/ui/src/main/java/org/jboss/seam/ui/graphicImage/GraphicImageRendererBase.java
===================================================================
--- trunk/ui/src/main/java/org/jboss/seam/ui/graphicImage/GraphicImageRendererBase.java 2008-06-02 10:35:00 UTC (rev 8314)
+++ trunk/ui/src/main/java/org/jboss/seam/ui/graphicImage/GraphicImageRendererBase.java 2008-06-02 10:47:51 UTC (rev 8315)
@@ -46,10 +46,14 @@
extension = image.getContentType().getExtension();
writer.startElement(HTML.IMG_ELEM, graphicImage);
+ if (graphicImage.getId() != null)
+ {
+ writer.writeAttribute(HTML.ID_ATTR, graphicImage.getClientId(context), HTML.ID_ATTR);
+ }
+
String url = context.getExternalContext().getRequestContextPath()
+ GraphicImageResource.GRAPHIC_IMAGE_RESOURCE_PATH + "/" + key + extension;
writer.writeAttribute(HTML.SRC_ATTR, url, HTML.SRC_ATTR);
-
HTML.renderHTMLAttributes(writer, component, HTML.IMG_PASSTHROUGH_ATTRIBUTES);
writer.endElement(HTML.IMG_ELEM);
}
16 years, 5 months
Seam SVN: r8314 - branches/Seam_2_0/ui/src/main/java/org/jboss/seam/ui/graphicImage.
by seam-commits@lists.jboss.org
Author: pete.muir(a)jboss.org
Date: 2008-06-02 06:35:00 -0400 (Mon, 02 Jun 2008)
New Revision: 8314
Modified:
branches/Seam_2_0/ui/src/main/java/org/jboss/seam/ui/graphicImage/GraphicImageRendererBase.java
Log:
JBSEAM-2517 (thanks to Keith Naas!)
Modified: branches/Seam_2_0/ui/src/main/java/org/jboss/seam/ui/graphicImage/GraphicImageRendererBase.java
===================================================================
--- branches/Seam_2_0/ui/src/main/java/org/jboss/seam/ui/graphicImage/GraphicImageRendererBase.java 2008-06-02 01:55:59 UTC (rev 8313)
+++ branches/Seam_2_0/ui/src/main/java/org/jboss/seam/ui/graphicImage/GraphicImageRendererBase.java 2008-06-02 10:35:00 UTC (rev 8314)
@@ -46,10 +46,14 @@
extension = image.getContentType().getExtension();
writer.startElement(HTML.IMG_ELEM, graphicImage);
+ if (graphicImage.getId() != null)
+ {
+ writer.writeAttribute(HTML.ID_ATTR, graphicImage.getClientId(context), HTML.ID_ATTR);
+ }
+
String url = context.getExternalContext().getRequestContextPath()
+ GraphicImageResource.GRAPHIC_IMAGE_RESOURCE_PATH + "/" + key + extension;
writer.writeAttribute(HTML.SRC_ATTR, url, HTML.SRC_ATTR);
-
HTML.renderHTMLAttributes(writer, component, HTML.IMG_PASSTHROUGH_ATTRIBUTES);
writer.endElement(HTML.IMG_ELEM);
}
16 years, 5 months
Seam SVN: r8313 - trunk/src/main/org/jboss/seam/security/permission.
by seam-commits@lists.jboss.org
Author: shane.bryzak(a)jboss.com
Date: 2008-06-01 21:55:59 -0400 (Sun, 01 Jun 2008)
New Revision: 8313
Modified:
trunk/src/main/org/jboss/seam/security/permission/IdentifierPolicy.java
Log:
strings identify themselves
Modified: trunk/src/main/org/jboss/seam/security/permission/IdentifierPolicy.java
===================================================================
--- trunk/src/main/org/jboss/seam/security/permission/IdentifierPolicy.java 2008-05-30 18:39:33 UTC (rev 8312)
+++ trunk/src/main/org/jboss/seam/security/permission/IdentifierPolicy.java 2008-06-02 01:55:59 UTC (rev 8313)
@@ -43,6 +43,11 @@
public String getIdentifier(Object target)
{
+ if (target instanceof String)
+ {
+ return (String) target;
+ }
+
IdentifierStrategy strategy = strategies.get(target.getClass());
if (strategy == null)
@@ -75,7 +80,7 @@
}
}
- return strategy.getIdentifier(target);
+ return strategy != null ? strategy.getIdentifier(target) : null;
}
public Set<IdentifierStrategy> getRegisteredStrategies()
16 years, 5 months