예제 #1
0
  /**
   * 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 &amp;gt; &amp;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);
    }
  }
예제 #2
0
  /**
   * 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('"');
  }
예제 #3
0
  /**
   * 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 &amp;gt; &amp;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);
    }
  }
예제 #4
0
  /**
   * 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('"');
    }
  }
예제 #5
0
  /**
   * 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 &amp;gt; &amp;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);
    }
  }
예제 #6
0
  /**
   * 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);
    }
  }
예제 #7
0
  /**
   * 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('>');
  }
예제 #8
0
  /**
   * 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;
    }
  }