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>");
}
}
Aggregations