package it.yup.xml; // #debug //@import it.yup.util.Logger; import it.yup.util.Utils; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.DataInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; public class BProcessor { // private static int TAG_BElement = 0x00; private static int TAG_NS = 0x01; private static int TAG_TEXT = 0x02; public static Element parse(byte data[]) { ByteArrayInputStream bais = new ByteArrayInputStream(data); return (Element) parse(bais, "jabber:client"); } private static Object parse(InputStream is, String ns) { DataInputStream dis = new DataInputStream(is); int n; byte buf[]; String uri = ns; try { int ctag[] = untag(is); if (ctag[0] == BProcessor.TAG_NS) { buf = new byte[ctag[1]]; //is.read(buf, 0, buf.length); dis.readFully( buf, 0, buf.length); uri = Utils.getStringUTF8(buf); ctag = untag(is); } buf = new byte[ctag[1]]; //is.read(buf, 0, buf.length); dis.readFully( buf, 0, buf.length); if (ctag[0] == BProcessor.TAG_TEXT) { return Utils.getStringUTF8(buf); } else { String name; String attrs[][] = null; Object children[] = null; name = Utils.getStringUTF8(buf); // number of attributes n = is.read(); if (n == -1) throw new IOException(); if ((n & 0x80) == 0x80) { int n1 = is.read(); if (n1 == -1) throw new IOException(); n = ((n & 0x7f) << 8) + n1; } if (n == -1) throw new IOException(); attrs = new String[n][3]; int len; for (int i = 0; i < n; i++) { int[] atag = untag(is); if (atag[0] == 0x01) { buf = new byte[atag[1]]; dis.readFully(buf, 0, buf.length); //is.read(buf, 0, buf.length); uri = Utils.getStringUTF8(buf); attrs[i][0] = uri; atag = untag(is); } buf = new byte[atag[1]]; //is.read(buf, 0, buf.length); dis.readFully(buf, 0, buf.length); attrs[i][1] = Utils.getStringUTF8(buf); len = unlen(is); buf = new byte[len]; //is.read(buf, 0, buf.length); dis.readFully( buf, 0, buf.length); attrs[i][2] = Utils.getStringUTF8(buf); } // number of children n = is.read(); if ((n & 0x80) == 0x80) { int n1 = is.read(); if (n1 == -1) throw new IOException(); n = ((n & 0x7f) << 8) + n1; } if (n == -1) throw new IOException(); children = new Object[n]; for (int i = 0; i < n; i++) { children[i] = parse(is, uri); } return new Element(uri, name, children, attrs); } } catch (IOException e) { // #mdebug //@ e.printStackTrace(); //@ Logger.log("In BProcessor parsing "); // #enddebug } return null; } private static int[] untag(InputStream is) throws IOException { int ctag[] = new int[2]; // {type, len} int b = is.read(); if (b == -1) throw new IOException(); ctag[0] = (b & 0x60) >> 5; if ((b & 0x80) == 0x80) { ctag[1] = (b & 0x1f) << 8; b = is.read(); if (b == -1) throw new IOException(); // unexpected end of stream ctag[1] += b; } else { ctag[1] = b & 0x1f; } return ctag; } private static int unlen(InputStream is) throws IOException { int len; int b = is.read(); if (b == -1) throw new IOException(); if ((b & 0x80) == 0x80) { len = (b & 0x7f) << 8; b = is.read(); if (b == -1) throw new IOException(); // unexpected end of stream len += b; } else { len = b; } return len; } public static byte[] toBinary(Element el) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); try { writeBinary(el, null, baos); } catch (IOException e) { // #debug //@ Logger.log("[BElement:toXml] IOException" + e.getMessage()); } return baos.toByteArray(); } private static void writeTag(byte type, String data, OutputStream os) throws IOException { byte bdata[] = Utils.getBytesUtf8(data); type = (byte) (type << 5); if (bdata.length < 32) { os.write(type | ((byte) bdata.length)); } else { os.write(0x80 | type | (bdata.length >> 8)); os.write(bdata.length & 0xff); } os.write(bdata); }; private static void writeLength(int l, OutputStream os) throws IOException { if (l < 128) { os.write(l); } else { os.write(0x80 | (l >> 8)); os.write(l & 0xff); } }; private static void writeBinary(Element el, String ns, OutputStream os) throws IOException { if (ns == null || !ns.equals(el.uri)) { ns = el.uri; writeTag((byte) 0x01, ns, os); } writeTag((byte) 0x00, el.name, os); writeLength(el.nattributes, os); for (int i = 0; i < el.nattributes; i++) { String attNs = el.attributes[i][0]; String k = el.attributes[i][1]; byte v[] = Utils.getBytesUtf8(el.attributes[i][2]); if (attNs != null && attNs.length() > 0 && !attNs.equals(el.uri)) writeTag( (byte) 0x01, attNs, os); writeTag((byte) 0x00, k, os); writeLength(v.length, os); os.write(v); } writeLength(el.nchildren, os); for (int i = 0; i < el.nchildren; i++) { Object c = el.children[i]; if (c.getClass() == String.class) writeTag((byte) 0x02, (String) c, os); else writeBinary((Element) c, ns, os); } } }