/** * Write properly escaped text from a character array. If there is an open element that has been * created by a call to <code>startElement()</code>, that element will be closed first. * * <p> * * <p>All angle bracket occurrences in the argument must be escaped using the &gt; &lt; * syntax. * * @param text Text to be written * @param off Starting offset (zero-relative) * @param len Number of characters to be written * @throws IndexOutOfBoundsException if the calculated starting or ending position is outside the * bounds of the character array * @throws IOException if an input/output error occurs * @throws NullPointerException if <code>text</code> is <code>null</code> */ public void writeText(char text[], int off, int len) throws IOException { if (text == null) { throw new NullPointerException( MessageUtils.getExceptionMessageString( MessageUtils.NULL_PARAMETERS_ERROR_MESSAGE_ID, "text")); } if (off < 0 || off > text.length || len < 0 || len > text.length) { throw new IndexOutOfBoundsException(); } closeStartIfNecessary(); if (writingCdata) { // RELEASE_PENDING // Might take a page from the HtmlUtils book and if the content being written // is more than 16 chars, then use an existing buffer and copy the contents // to said buffer. If 16 or less, then just iterate over the string using charAt() char[] cbuf = new char[off + len]; System.arraycopy(text, off, cbuf, 0, len); writer.write(escapeArray(cbuf)); } else if (dontEscape) { writer.write(text, off, len); } else { HtmlUtils.writeText(writer, escapeUnicode, escapeIso, buffer, text, off, len); } }
/** * Write a properly encoded URI attribute name and the corresponding value. The value text will be * converted to a String if necessary). This method may only be called after a call to <code> * startElement()</code>, and before the opened element has been closed. * * @param name Attribute name to be added * @param value Attribute value to be added * @param componentPropertyName The name of the component property to which this attribute * argument applies. This argument may be <code>null</code>. * @throws IllegalStateException if this method is called when there is no currently open element * @throws IOException if an input/output error occurs * @throws NullPointerException if <code>name</code> or <code>value</code> is <code>null</code> */ public void writeURIAttribute(String name, Object value, String componentPropertyName) throws IOException { if (name == null) { throw new NullPointerException( MessageUtils.getExceptionMessageString( MessageUtils.NULL_PARAMETERS_ERROR_MESSAGE_ID, "name")); } if (value == null) { throw new NullPointerException( MessageUtils.getExceptionMessageString( MessageUtils.NULL_PARAMETERS_ERROR_MESSAGE_ID, "value")); } if (isCdata) { return; } if (name.equalsIgnoreCase("src") && isScriptOrStyle()) { scriptOrStyleSrc = true; } attributesBuffer.write(' '); attributesBuffer.write(name); attributesBuffer.write("=\""); String stringValue = value.toString(); ensureTextBufferCapacity(stringValue); // Javascript URLs should not be URL-encoded if (stringValue.startsWith("javascript:")) { HtmlUtils.writeAttribute( attributesBuffer, escapeUnicode, escapeIso, buffer, stringValue, textBuffer, isScriptInAttributeValueEnabled); } else { HtmlUtils.writeURL(attributesBuffer, stringValue, textBuffer, encoding); } attributesBuffer.write('"'); }
/** * Write a properly escaped single character, If there is an open element that has been created by * a call to <code>startElement()</code>, that element will be closed first. * * <p> * * <p>All angle bracket occurrences in the argument must be escaped using the &gt; &lt; * syntax. * * @param text Text to be written * @throws IOException if an input/output error occurs */ public void writeText(char text) throws IOException { closeStartIfNecessary(); if (dontEscape) { writer.write(text); } else { charHolder[0] = text; HtmlUtils.writeText(writer, escapeUnicode, escapeIso, buffer, charHolder); } }
/** * Write a properly escaped attribute name and the corresponding value. The value text will be * converted to a String if necessary. This method may only be called after a call to <code> * startElement()</code>, and before the opened element has been closed. * * @param name Attribute name to be added * @param value Attribute value to be added * @param componentPropertyName The name of the component property to which this attribute * argument applies. This argument may be <code>null</code>. * @throws IllegalStateException if this method is called when there is no currently open element * @throws IOException if an input/output error occurs * @throws NullPointerException if <code>name</code> is <code>null</code> */ public void writeAttribute(String name, Object value, String componentPropertyName) throws IOException { if (name == null) { throw new NullPointerException( MessageUtils.getExceptionMessageString( MessageUtils.NULL_PARAMETERS_ERROR_MESSAGE_ID, "name")); } if (value == null) { return; } if (isCdata) { return; } if (name.equalsIgnoreCase("src") && isScriptOrStyle()) { scriptOrStyleSrc = true; } Class valueClass = value.getClass(); // Output Boolean values specially if (valueClass == Boolean.class) { if (Boolean.TRUE.equals(value)) { // NOTE: HTML 4.01 states that boolean attributes // may legally take a single value which is the // name of the attribute itself or appear using // minimization. // http://www.w3.org/TR/html401/intro/sgmltut.html#h-3.3.4.2 attributesBuffer.write(' '); attributesBuffer.write(name); attributesBuffer.write("=\""); attributesBuffer.write(name); attributesBuffer.write('"'); } } else { attributesBuffer.write(' '); attributesBuffer.write(name); attributesBuffer.write("=\""); // write the attribute value String val = value.toString(); ensureTextBufferCapacity(val); HtmlUtils.writeAttribute( attributesBuffer, escapeUnicode, escapeIso, buffer, val, textBuffer, isScriptInAttributeValueEnabled); attributesBuffer.write('"'); } }
/** * Write properly escaped text from a character array. The output from this command is identical * to the invocation: <code>writeText(c, 0, c.length)</code>. If there is an open element that has * been created by a call to <code>startElement()</code>, that element will be closed first. * * <p> * * <p>All angle bracket occurrences in the argument must be escaped using the &gt; &lt; * syntax. * * @param text Text to be written * @throws IOException if an input/output error occurs * @throws NullPointerException if <code>text</code> is <code>null</code> */ public void writeText(char text[]) throws IOException { if (text == null) { throw new NullPointerException( MessageUtils.getExceptionMessageString( MessageUtils.NULL_PARAMETERS_ERROR_MESSAGE_ID, "text")); } closeStartIfNecessary(); if (dontEscape) { writer.write(text); } else { HtmlUtils.writeText(writer, escapeUnicode, escapeIso, buffer, text); } }
/** * Write a properly escaped object. The object will be converted to a String if necessary. If * there is an open element that has been created by a call to <code>startElement()</code>, that * element will be closed first. * * @param text Text to be written * @param componentPropertyName The name of the component property to which this text argument * applies. This argument may be <code>null</code>. * @throws IOException if an input/output error occurs * @throws NullPointerException if <code>text</code> is <code>null</code> */ public void writeText(Object text, String componentPropertyName) throws IOException { if (text == null) { throw new NullPointerException( MessageUtils.getExceptionMessageString( MessageUtils.NULL_PARAMETERS_ERROR_MESSAGE_ID, "text")); } closeStartIfNecessary(); if (writingCdata) { writer.write(escapeArray(text.toString().toCharArray())); } else if (dontEscape) { writer.write(text.toString()); } else { String val = text.toString(); ensureTextBufferCapacity(val); HtmlUtils.writeText(writer, escapeUnicode, escapeIso, buffer, val, textBuffer); } }
/** * Write the end of an element. This method will first close any open element created by a call to * <code>startElement()</code>. * * @param name Name of the element to be ended * @throws IOException if an input/output error occurs * @throws NullPointerException if <code>name</code> is <code>null</code> */ public void endElement(String name) throws IOException { if (name == null) { throw new NullPointerException( MessageUtils.getExceptionMessageString( MessageUtils.NULL_PARAMETERS_ERROR_MESSAGE_ID, "name")); } if (!writingCdata) { // always turn escaping back on once an element ends unless we're // still writing cdata content dontEscape = false; } isXhtml = getContentType().equals(RIConstants.XHTML_CONTENT_TYPE); if (isScriptOrStyle(name) && !scriptOrStyleSrc && writer instanceof FastStringWriter) { String result = ((FastStringWriter) writer).getBuffer().toString(); writer = origWriter; if (result != null) { String trim = result.trim(); if (isXhtml) { if (isScript) { Matcher cdataStartSlashSlash = CDATA_START_SLASH_SLASH.matcher(trim), cdataEndSlashSlash = CDATA_END_SLASH_SLASH.matcher(trim), cdataStartSlashStar = CDATA_START_SLASH_STAR.matcher(trim), cdataEndSlashStar = CDATA_END_SLASH_STAR.matcher(trim); int trimLen = trim.length(), start, end; // case 1 start is // end is // if (cdataStartSlashSlash.find() && cdataEndSlashSlash.find()) { start = cdataStartSlashSlash.end() - cdataStartSlashSlash.start(); end = trimLen - (cdataEndSlashSlash.end() - cdataEndSlashSlash.start()); writer.write(trim.substring(start, end)); } // case 2 start is // end is /* */ else if ((null != cdataStartSlashSlash.reset() && cdataStartSlashSlash.find()) && cdataEndSlashStar.find()) { start = cdataStartSlashSlash.end() - cdataStartSlashSlash.start(); end = trimLen - (cdataEndSlashStar.end() - cdataEndSlashStar.start()); writer.write(trim.substring(start, end)); } // case 3 start is /* */ end is /* */ else if (cdataStartSlashStar.find() && (null != cdataEndSlashStar.reset() && cdataEndSlashStar.find())) { start = cdataStartSlashStar.end() - cdataStartSlashStar.start(); end = trimLen - (cdataEndSlashStar.end() - cdataEndSlashStar.start()); writer.write(trim.substring(start, end)); } // case 4 start is /* */ end is // else if ((null != cdataStartSlashStar.reset() && cdataStartSlashStar.find()) && (null != cdataEndSlashStar.reset() && cdataEndSlashSlash.find())) { start = cdataStartSlashStar.end() - cdataStartSlashStar.start(); end = trimLen - (cdataEndSlashSlash.end() - cdataEndSlashSlash.start()); writer.write(trim.substring(start, end)); } // case 5 no commented out cdata present. else { writer.write(result); } } else { if (trim.startsWith("<![CDATA[") && trim.endsWith("]]>")) { writer.write(trim.substring(9, trim.length() - 3)); } else { writer.write(result); } } } else { if (trim.startsWith("<!--") && trim.endsWith("//-->")) { writer.write(trim.substring(4, trim.length() - 5)); } else { writer.write(result); } } } if (isXhtml) { if (!writingCdata) { if (isScript) { writer.write("\n//]]>\n"); } else { writer.write("\n]]>\n"); } } } else { if (isScriptHidingEnabled) { writer.write("\n//-->\n"); } } } isScript = false; isStyle = false; if ("cdata".equalsIgnoreCase(name)) { endCDATA(); return; } // See if we need to close the start of the last element if (closeStart) { boolean isEmptyElement = HtmlUtils.isEmptyElement(name); // Tricky: we need to use the writer ivar here, rather than the // one from the FacesContext because we don't want // spurious /> characters to appear in the output. if (isEmptyElement) { flushAttributes(); writer.write(" />"); closeStart = false; return; } flushAttributes(); writer.write('>'); closeStart = false; } writer.write("</"); writer.write(name); writer.write('>'); }
/** * Constructor sets the <code>ResponseWriter</code> and encoding. * * <p>The argument configPrefs is a map of configurable prefs that affect this instance's * behavior. Supported keys are: * * <p>BooleanWebContextInitParameter.EnableJSStyleHiding: <code>true</code> if the writer should * attempt to hide JS from older browsers * * @param writer the <code>ResponseWriter</code> * @param contentType the content type. * @param encoding the character encoding. * @throws javax.faces.FacesException the encoding is not recognized. */ public HtmlResponseWriter( Writer writer, String contentType, String encoding, Boolean isScriptHidingEnabled, Boolean isScriptInAttributeValueEnabled, WebConfiguration.DisableUnicodeEscaping disableUnicodeEscaping) throws FacesException { this.writer = writer; if (null != contentType) { this.contentType = contentType; } this.encoding = encoding; // init those configuration parameters not yet initialized WebConfiguration webConfig = null; if (isScriptHidingEnabled == null) { webConfig = getWebConfiguration(webConfig); isScriptHidingEnabled = (null == webConfig) ? BooleanWebContextInitParameter.EnableJSStyleHiding.getDefaultValue() : webConfig.isOptionEnabled(BooleanWebContextInitParameter.EnableJSStyleHiding); } if (isScriptInAttributeValueEnabled == null) { webConfig = getWebConfiguration(webConfig); isScriptInAttributeValueEnabled = (null == webConfig) ? BooleanWebContextInitParameter.EnableScriptInAttributeValue.getDefaultValue() : webConfig.isOptionEnabled( BooleanWebContextInitParameter.EnableScriptInAttributeValue); } if (disableUnicodeEscaping == null) { webConfig = getWebConfiguration(webConfig); disableUnicodeEscaping = WebConfiguration.DisableUnicodeEscaping.getByValue( (null == webConfig) ? WebConfiguration.WebContextInitParameter.DisableUnicodeEscaping .getDefaultValue() : webConfig.getOptionValue( WebConfiguration.WebContextInitParameter.DisableUnicodeEscaping)); if (disableUnicodeEscaping == null) { disableUnicodeEscaping = WebConfiguration.DisableUnicodeEscaping.False; } } // and store them for later use this.isScriptHidingEnabled = isScriptHidingEnabled; this.isScriptInAttributeValueEnabled = isScriptInAttributeValueEnabled; this.disableUnicodeEscaping = disableUnicodeEscaping; this.attributesBuffer = new FastStringWriter(128); // Check the character encoding if (!HtmlUtils.validateEncoding(encoding)) { throw new IllegalArgumentException( MessageUtils.getExceptionMessageString(MessageUtils.ENCODING_ERROR_MESSAGE_ID)); } String charsetName = encoding.toUpperCase(); switch (disableUnicodeEscaping) { case True: // html escape noting (except the dangerous characters like "<>'" etc escapeUnicode = false; escapeIso = false; break; case False: // html escape any non-ascii character escapeUnicode = true; escapeIso = true; break; case Auto: // is stream capable of rendering unicode, do not escape escapeUnicode = !HtmlUtils.isUTFencoding(charsetName); // is stream capable of rendering unicode or iso-8859-1, do not escape escapeIso = !HtmlUtils.isISO8859_1encoding(charsetName) && !HtmlUtils.isUTFencoding(charsetName); break; } }