Search in sources :

Example 1 with ProtocolDecoderException

use of org.apache.mina.filter.codec.ProtocolDecoderException in project Openfire by igniterealtime.

the class XMLLightweightParser method read.

/*
    * Main reading method
    */
public void read(IoBuffer byteBuffer) throws Exception {
    if (buffer == null) {
        // exception was thrown before, avoid duplicate exception(s)
        // "read" and discard remaining data
        byteBuffer.position(byteBuffer.limit());
        return;
    }
    invalidateBuffer();
    // we will abort parsing when 1 Mega of queued chars was found.
    if (buffer.length() > maxBufferSize) {
        // purge the local buffer / free memory
        buffer = null;
        // processing the exception takes quite long
        final ProtocolDecoderException ex = new ProtocolDecoderException("Stopped parsing never ending stanza");
        ex.setHexdump("(redacted hex dump of never ending stanza)");
        throw ex;
    }
    CharBuffer charBuffer = CharBuffer.allocate(byteBuffer.capacity());
    encoder.reset();
    encoder.decode(byteBuffer.buf(), charBuffer, false);
    char[] buf = new char[charBuffer.position()];
    charBuffer.flip();
    charBuffer.get(buf);
    int readChar = buf.length;
    // Just return if nothing was read
    if (readChar == 0) {
        return;
    }
    buffer.append(buf);
    // Robot.
    char ch;
    boolean isHighSurrogate = false;
    for (int i = 0; i < readChar; i++) {
        ch = buf[i];
        if (ch < 0x20 && ch != 0x9 && ch != 0xA && ch != 0xD && ch != 0x0) {
            //Unicode characters in the range 0x0000-0x001F other than 9, A, and D are not allowed in XML
            //We need to allow the NULL character, however, for Flash XMLSocket clients to work.
            buffer = null;
            throw new XMLNotWellFormedException("Character is invalid in: " + ch);
        }
        if (isHighSurrogate) {
            if (Character.isLowSurrogate(ch)) {
                // Everything is fine. Clean up traces for surrogates
                isHighSurrogate = false;
            } else {
                // Trigger error. Found high surrogate not followed by low surrogate
                buffer = null;
                throw new Exception("Found high surrogate not followed by low surrogate");
            }
        } else if (Character.isHighSurrogate(ch)) {
            isHighSurrogate = true;
        } else if (Character.isLowSurrogate(ch)) {
            // Trigger error. Found low surrogate char without a preceding high surrogate
            buffer = null;
            throw new Exception("Found low surrogate char without a preceding high surrogate");
        }
        if (status == XMLLightweightParser.TAIL) {
            // Looking for the close tag
            if (depth < 1 && ch == head.charAt(tailCount)) {
                tailCount++;
                if (tailCount == head.length()) {
                    // Close stanza found!
                    // Calculate the correct start,end position of the message into the buffer
                    int end = buffer.length() - readChar + (i + 1);
                    String msg = buffer.substring(startLastMsg, end);
                    // Add message to the list
                    foundMsg(msg);
                    startLastMsg = end;
                }
            } else {
                tailCount = 0;
                status = XMLLightweightParser.INSIDE;
            }
        } else if (status == XMLLightweightParser.PRETAIL) {
            if (ch == XMLLightweightParser.CDATA_START[cdataOffset]) {
                cdataOffset++;
                if (cdataOffset == XMLLightweightParser.CDATA_START.length) {
                    status = XMLLightweightParser.INSIDE_CDATA;
                    cdataOffset = 0;
                    continue;
                }
            } else {
                cdataOffset = 0;
                status = XMLLightweightParser.INSIDE;
            }
            if (ch == '/') {
                status = XMLLightweightParser.TAIL;
                depth--;
            } else if (ch == '!') {
                // This is a <! (comment) so ignore it
                status = XMLLightweightParser.INSIDE;
            } else {
                depth++;
            }
        } else if (status == XMLLightweightParser.VERIFY_CLOSE_TAG) {
            if (ch == '>') {
                depth--;
                status = XMLLightweightParser.OUTSIDE;
                if (depth < 1) {
                    // Found a tag in the form <tag />
                    int end = buffer.length() - readChar + (i + 1);
                    String msg = buffer.substring(startLastMsg, end);
                    // Add message to the list
                    foundMsg(msg);
                    startLastMsg = end;
                }
            } else if (ch == '<') {
                status = XMLLightweightParser.PRETAIL;
                insideChildrenTag = true;
            } else {
                status = XMLLightweightParser.INSIDE;
            }
        } else if (status == XMLLightweightParser.INSIDE_PARAM_VALUE) {
            if (ch == '"') {
                status = XMLLightweightParser.INSIDE;
            }
        } else if (status == XMLLightweightParser.INSIDE_CDATA) {
            if (ch == XMLLightweightParser.CDATA_END[cdataOffset]) {
                cdataOffset++;
                if (cdataOffset == XMLLightweightParser.CDATA_END.length) {
                    status = XMLLightweightParser.OUTSIDE;
                    cdataOffset = 0;
                }
            } else if (cdataOffset == XMLLightweightParser.CDATA_END.length - 1 && ch == XMLLightweightParser.CDATA_END[cdataOffset - 1]) {
            // if we are looking for the last CDATA_END char, and we instead found an extra ']' 
            // char, leave cdataOffset as is and proceed to the next char. This could be a case 
            // where the XML character data ends with multiple square braces. For Example ]]]>
            } else {
                cdataOffset = 0;
            }
        } else if (status == XMLLightweightParser.INSIDE) {
            if (ch == XMLLightweightParser.CDATA_START[cdataOffset]) {
                cdataOffset++;
                if (cdataOffset == XMLLightweightParser.CDATA_START.length) {
                    status = XMLLightweightParser.INSIDE_CDATA;
                    cdataOffset = 0;
                    continue;
                }
            } else {
                cdataOffset = 0;
                status = XMLLightweightParser.INSIDE;
            }
            if (ch == '"') {
                status = XMLLightweightParser.INSIDE_PARAM_VALUE;
            } else if (ch == '>') {
                status = XMLLightweightParser.OUTSIDE;
                if (insideRootTag && ("stream:stream>".equals(head.toString()) || ("?xml>".equals(head.toString())) || ("flash:stream>".equals(head.toString())))) {
                    // Found closing stream:stream
                    int end = buffer.length() - readChar + (i + 1);
                    // Skip LF, CR and other "weird" characters that could appear
                    while (startLastMsg < end && '<' != buffer.charAt(startLastMsg)) {
                        startLastMsg++;
                    }
                    String msg = buffer.substring(startLastMsg, end);
                    foundMsg(msg);
                    startLastMsg = end;
                }
                insideRootTag = false;
            } else if (ch == '/') {
                status = XMLLightweightParser.VERIFY_CLOSE_TAG;
            }
        } else if (status == XMLLightweightParser.HEAD) {
            if (ch == ' ' || ch == '>') {
                // Append > to head to allow searching </tag>
                head.append('>');
                if (ch == '>')
                    status = XMLLightweightParser.OUTSIDE;
                else
                    status = XMLLightweightParser.INSIDE;
                insideRootTag = true;
                insideChildrenTag = false;
                continue;
            } else if (ch == '/' && head.length() > 0) {
                status = XMLLightweightParser.VERIFY_CLOSE_TAG;
                depth--;
            }
            head.append(ch);
        } else if (status == XMLLightweightParser.INIT) {
            if (ch == '<') {
                status = XMLLightweightParser.HEAD;
                depth = 1;
            } else {
                startLastMsg++;
            }
        } else if (status == XMLLightweightParser.OUTSIDE) {
            if (ch == '<') {
                status = XMLLightweightParser.PRETAIL;
                cdataOffset = 1;
                insideChildrenTag = true;
            }
        }
    }
    if (head.length() > 0 && ("/stream:stream>".equals(head.toString()) || ("/flash:stream>".equals(head.toString())))) {
        // Found closing stream:stream
        foundMsg("</stream:stream>");
    }
}
Also used : ProtocolDecoderException(org.apache.mina.filter.codec.ProtocolDecoderException) CharBuffer(java.nio.CharBuffer) ProtocolDecoderException(org.apache.mina.filter.codec.ProtocolDecoderException)

Aggregations

CharBuffer (java.nio.CharBuffer)1 ProtocolDecoderException (org.apache.mina.filter.codec.ProtocolDecoderException)1