package org.jivesoftware.admin; import org.bouncycastle.asn1.*; import javax.servlet.jsp.JspException; import javax.servlet.jsp.tagext.BodyTagSupport; import java.io.IOException; /** * Creates a table that represents an ASN.1 encoded DER value. * * This tag creates a HTML table, that consists of one or two columns and an unspecified number of rows. Each cell * can contain a nested table (of similar format). */ public class ASN1DERTag extends BodyTagSupport { private byte[] value; // ASN.1 DER-encoded value public byte[] getValue() { return value; } public void setValue(byte[] value) { this.value = value; } @Override public int doEndTag() throws JspException { try { final ASN1InputStream decoder = new ASN1InputStream(value); ASN1Primitive primitive = decoder.readObject(); while (primitive != null && !(primitive instanceof ASN1Null)) { pageContext.getOut().write(doPrimitive(primitive)); primitive = decoder.readObject(); } } catch (Exception ex) { throw new JspException(ex.getMessage()); } return super.doEndTag(); } private String doPrimitive(ASN1Primitive primitive) throws IOException { if (primitive == null || primitive instanceof ASN1Null) { return ""; } else if (primitive instanceof ASN1Sequence) { return doCollection(((ASN1Sequence) primitive).toArray()); } else if (primitive instanceof ASN1Set) { return doCollection(((ASN1Set) primitive).toArray()); } else if (primitive instanceof DERTaggedObject) { final DERTaggedObject tagged = ((DERTaggedObject) primitive); return "<table><tr><td>" + /* tagged.getTagNo() + */ "</td><td>" + doPrimitive(tagged.getObject()) + "</td></tr></table>"; } else { return "<table><tr><td colspan='2'>" + asString(primitive) + "</td></tr></table>"; } } private String doCollection(ASN1Encodable[] asn1Encodables) throws IOException { switch (asn1Encodables.length) { case 1: // one row, one column return "<table><tr><td colspan='2'>" + doPrimitive(asn1Encodables[0].toASN1Primitive()) + "</td></tr></table>"; case 2: // one row, two columns return "<table><tr><td>" + doPrimitive(asn1Encodables[0].toASN1Primitive()) + "</td>" + "<td>" + doPrimitive(asn1Encodables[1].toASN1Primitive()) + "</td></tr></table>"; default: // a row per per item final StringBuilder sb = new StringBuilder(); for (ASN1Encodable asn1Encodable : asn1Encodables) { sb.append("<table><tr><td colspan='2'>").append(doPrimitive(asn1Encodable.toASN1Primitive())).append("</td></tr></table>"); } return sb.toString(); } } private String asString(ASN1Primitive primitive) { if (primitive == null || primitive instanceof ASN1Null) { return ""; } if (primitive instanceof ASN1String) { return ((ASN1String) primitive).getString(); } if (primitive instanceof DERUTCTime) { return ((DERUTCTime) primitive).getAdjustedTime(); } if (primitive instanceof DERGeneralizedTime) { return ((DERGeneralizedTime) primitive).getTime(); } if (primitive instanceof ASN1ObjectIdentifier) { switch (((ASN1ObjectIdentifier) primitive).getId()) { case "1.3.6.1.5.5.7.8.5": return "xmppAddr"; default: return primitive.toString(); } } return primitive.toString(); } }