1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 | package Torello.HTML; import java.util.regex.*; /** * This {@code Exception} is generated, usually, when a quote-within-quote problem has occurred * inside HTML Attributes. * * <BR /><BR />Attribute-<B STYLE="color: red;">values</B> cannot contain quotes, unless the * inner-quotes do not match the outer-quotes. Generally, there are not many HTML Inner-Tags that * use quotes, other than the occasional {@code ALT="..."} text (in an image element), or possibly * a Java-Script listener attribute. * * <BR /><BR />However, this package performs quite a bit of {@code String}-operations, so * {@code String's} are checked when any method or constructor which builds instances of class * {@link TagNode} containing any Inner-Tag <B STYLE="color: red;">Key-Value Pairs</B>. * * <BR /><BR />In addition to checking for double-within-double-quotation mark problems (or * single-quote inside of a singly-quoted string), this {@code Exception} is also thrown if a user * attempts to assign an attribute <B STYLE="color: red;">value</B> that uses the * 'no-quotation-marks' version of attribute-<B STYLE="color: red;">value</B> pairs <I>when the * value he is passing has any white-space, inside the * <B STYLE="color: red;">value</B>-{@code String} at all.</I> */ public class QuotesException extends IllegalArgumentException { /** <EMBED CLASS='external-html' DATA-FILE-ID=SVUIDEX> */ public static final long serialVersionUID = 1; /** Constructs a {@code QuotesException} with no detail message. */ public QuotesException() { super(); } /** * Constructs a {@code QuotesException} with the specified detail message. * @param message the detail message. */ public QuotesException(String message) { super(message); } /** * Constructs a new exception with the specified detail message and cause. * * <BR /><BR /><B CLASS=JDDescLabel>NOTE:</B> * * <BR /><BR />The detail message associated with cause is not automatically incorporated into * this exception's detail message. * * @param message The detail message (which is saved for later retrieval by the * {@code Throwable.getMessage()} method). * * @param cause the cause (which is saved for later retrieval by the * {@code Throwable.getCause()} method). (A null value is permitted, and indicates that the * cause is nonexistent or unknown.) */ public QuotesException(String message, Throwable cause) { super(message, cause); } /** * Constructs a new exception with the specified cause and a detail message of * {@code (cause==null ? null : cause.toString())} (which typically contains the class and * detail message of cause). This constructor is useful for exceptions that are little more * than wrappers for other throwables. * * @param cause the cause (which is saved for later retrieval by the * {@code Throwable.getCause()} method). (A null value is permitted, and indicates that the * cause is nonexistent or unknown.) */ public QuotesException(Throwable cause) { super(cause); } /** * This Regular-Expression {@code Pattern} is used internally for one particular scenario * involving a null quotes specifier. It states that a {@code String} must conform to either * single-quotes, double-quotes or no-quotes. * * <DIV CLASS="LOC">{@code * // Throws Exception - No surrounding-quotes, has spaces * check("This is an Attribute Value", null, "No Message"); * * // Passes Inspection - No surrounding-quotes, but has no spaces. * check("This-is-an-Attribute-Value", null, "No Message"); * * // Throws Exception - Has surrounding-quotes, but has quote-within-quote * check("This is an\"Attribute\" Value", null, "No Message"); * * // Passes Inspection - Has surrounding-quotes, no quote-within-quote * check("'This is an attribute value'", null, "No Message"); * }</DIV> */ protected static final Pattern QUOTES_CHECKER = Pattern.compile("^(\"[^\"]*\"|'[^']*'|[^'\"\\s]*)$"); /** * The primary purpose of this {@code static} function is to generate a uniformly formatted * error message when a "Quote within Quote" problem is identified. If parameter * {@code 'quotes'} is set to {@code SD.SingleQuotes}, then finding a single-quote within the * input {@code String} will cause this {@code Exception} throw. If quotes is set to * {@code SD.DoubleQuotes}, then finding a double-quote in the input {@code String} will cause * this {@code Exception} throw. If parameter {@code 'quotes'} is null, then finding either * will generate a {@code QuotesException}. * * @param s The {@code String}-token to check * * @param quotes The surrounding quotes used, or null if no quotes are being used. If this * value is null, then finding either quote in the {@code 's'} parameter will cause this * {@code QuotesException} throw. * * @param message A brief error message to report to the programmer. If this is null, then it * is not included. * * @throws QuotesException If there is a "Quote within Quote" problem identified, as explained * above. */ public static void check(String s, SD quotes, String message) { if (quotes == null) { if (! QUOTES_CHECKER.matcher(s).find()) throw new QuotesException( ((message == null) ? "" : (message.endsWith("\n") ? message : (message + "\n"))) + "\nString: [" + s + "]\nis not being properly quoted." ); } else if (s.indexOf(quotes.quote) != -1) throw new QuotesException( ((message == null) ? "" : (message.endsWith("\n") ? message : (message + "\n"))) + "\nString: [" + s + "]\n" + "contains a quote that matches the surrounding quotes: " + quotes.quote ); } } |