Use local copy of latest bndlib code for pre-release testing purposes

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1347815 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/bundleplugin/src/main/java/aQute/libg/asn1/BER.java b/bundleplugin/src/main/java/aQute/libg/asn1/BER.java
new file mode 100644
index 0000000..4416dd4
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/libg/asn1/BER.java
@@ -0,0 +1,472 @@
+package aQute.libg.asn1;
+
+import java.io.*;
+import java.text.*;
+import java.util.*;
+
+public class BER implements Types {
+    DateFormat df = new SimpleDateFormat("yyyyMMddHHmmss\\Z");
+    
+    final DataInputStream xin;
+    long                  position;
+
+    public BER(InputStream in) {
+        this.xin = new DataInputStream(in);
+    }
+
+    public void dump(PrintStream out) throws Exception {
+        int type = readByte();
+        long length = readLength();
+        if (type == -1 || length == -1)
+            throw new EOFException("Empty file");
+        dump(out, type, length, "");
+    }
+
+    void dump(PrintStream out, int type, long length, String indent)
+            throws Exception {
+        int clss = type >> 6;
+        int nmbr = type & 0x1F;
+        boolean cnst = (type & 0x20) != 0;
+
+        String tag = "[" + nmbr + "]";
+        if (clss == 0)
+            tag = TAGS[nmbr];
+
+        if (cnst) {
+            System.err.printf("%5d %s %s %s%n", length, indent, CLASSES[clss],
+                    tag);
+            while (length > 1) {
+                long atStart = getPosition();
+                int t2 = read();
+                long l2 = readLength();
+                dump(out, t2, l2, indent + "  ");
+                length -= getPosition() - atStart;
+            }
+        } else {
+            assert length < Integer.MAX_VALUE;
+            assert length >= 0;
+            byte[] data = new byte[(int) length];
+            readFully(data);
+            String summary;
+
+            switch (nmbr) {
+            case BOOLEAN:
+                assert length == 1;
+                summary = data[0] != 0 ? "true" : "false";
+                break;
+
+            case INTEGER:
+                long n = toLong(data);
+                summary = n + "";
+                break;
+
+            case UTF8_STRING:
+            case IA5STRING:
+            case VISIBLE_STRING:
+            case UNIVERSAL_STRING:
+            case PRINTABLE_STRING:
+            case UTCTIME:
+                summary = new String(data, "UTF-8");
+                break;
+
+            case OBJECT_IDENTIFIER:
+                summary = readOID(data);
+                break;
+
+            case GENERALIZED_TIME:
+            case GRAPHIC_STRING:
+            case GENERAL_STRING:
+            case CHARACTER_STRING:
+
+            case REAL:
+            case EOC:
+            case BIT_STRING:
+            case OCTET_STRING:
+            case NULL:
+            case OBJECT_DESCRIPTOR:
+            case EXTERNAL:
+            case ENUMERATED:
+            case EMBEDDED_PDV:
+            case RELATIVE_OID:
+            case NUMERIC_STRING:
+            case T61_STRING:
+            case VIDEOTEX_STRING:
+            case BMP_STRING:
+            default:
+                StringBuilder sb = new StringBuilder();
+                for (int i = 0; i < 10 && i < data.length; i++) {
+                    sb.append(Integer.toHexString(data[i]));
+                }
+                if (data.length > 10) {
+                    sb.append("...");
+                }
+                summary = sb.toString();
+                break;
+            }
+            out.printf("%5d %s %s %s %s\n", length, indent, CLASSES[clss], tag,
+                    summary);
+        }
+    }
+
+    long toLong(byte[] data) {
+        if (data[0] < 0) {
+            for (int i = 0; i < data.length; i++)
+                data[i] = (byte) (0xFF ^ data[i]);
+
+            return -(toLong(data) + 1);
+        }
+        long n = 0;
+        for (int i = 0; i < data.length; i++) {
+            n = n * 256 + data[i];
+        }
+        return n;
+    }
+
+    /**
+     * 8.1.3.3 For the definite form, the length octets shall consist of one or
+     * more octets, and shall represent the number of octets in the contents
+     * octets using either the short form (see 8.1.3.4) or the long form (see
+     * 8.1.3.5) as a sender's option. NOTE – The short form can only be used if
+     * the number of octets in the contents octets is less than or equal to 127.
+     * 8.1.3.4 In the short form, the length octets shall consist of a single
+     * octet in which bit 8 is zero and bits 7 to 1 encode the number of octets
+     * in the contents octets (which may be zero), as an unsigned binary integer
+     * with bit 7 as the most significant bit. EXAMPLE L = 38 can be encoded as
+     * 001001102 8.1.3.5 In the long form, the length octets shall consist of an
+     * initial octet and one or more subsequent octets. The initial octet shall
+     * be encoded as follows: a) bit 8 shall be one; b) bits 7 to 1 shall encode
+     * the number of subsequent octets in the length octets, as an unsigned
+     * binary integer with bit 7 as the most significant bit; c) the value
+     * 111111112 shall not be used. ISO/IEC 8825-1:2003 (E) NOTE 1 – This
+     * restriction is introduced for possible future extension. Bits 8 to 1 of
+     * the first subsequent octet, followed by bits 8 to 1 of the second
+     * subsequent octet, followed in turn by bits 8 to 1 of each further octet
+     * up to and including the last subsequent octet, shall be the encoding of
+     * an unsigned binary integer equal to the number of octets in the contents
+     * octets, with bit 8 of the first subsequent octet as the most significant
+     * bit. EXAMPLE L = 201 can be encoded as: 100000012 110010012 NOTE 2 – In
+     * the long form, it is a sender's option whether to use more length octets
+     * than the minimum necessary. 8.1.3.6 For the indefinite form, the length
+     * octets indicate that the contents octets are terminated by
+     * end-of-contents octets (see 8.1.5), and shall consist of a single octet.
+     * 8.1.3.6.1 The single octet shall have bit 8 set to one, and bits 7 to 1
+     * set to zero. 8.1.3.6.2 If this form of length is used, then
+     * end-of-contents octets (see 8.1.5) shall be present in the encoding
+     * following the contents octets. 8.1.4 Contents octets The contents octets
+     * shall consist of zero, one or more octets, and shall encode the data
+     * value as specified in subsequent clauses. NOTE – The contents octets
+     * depend on the type of the data value; subsequent clauses follow the same
+     * sequence as the definition of types in ASN.1. 8.1.5 End-of-contents
+     * octets The end-of-contents octets shall be present if the length is
+     * encoded as specified in 8.1.3.6, otherwise they shall not be present. The
+     * end-of-contents octets shall consist of two zero octets. NOTE – The
+     * end-of-contents octets can be considered as the encoding of a value whose
+     * tag is universal class, whose form is primitive, whose number of the tag
+     * is zero, and whose contents are absent, thus:
+     * 
+     * End-of-contents Length Contents 0016 0016 Absent
+     * 
+     * @return
+     */
+    private long readLength() throws IOException {
+        long n = readByte();
+        if (n > 0) {
+            // short form
+            return n;
+        }
+		// long form
+		int count = (int) (n & 0x7F);
+		if (count == 0) {
+		    // indefinite form
+		    return 0;
+		}
+		n = 0;
+		while (count-- > 0) {
+		    n = n * 256 + read();
+		}
+		return n;
+    }
+
+    private int readByte() throws IOException {
+        position++;
+        return xin.readByte();
+    }
+
+    private void readFully(byte[] data) throws IOException {
+        position += data.length;
+        xin.readFully(data);
+    }
+
+    private long getPosition() {
+        return position;
+    }
+
+    private int read() throws IOException {
+        position++;
+        return xin.read();
+    }
+
+    String readOID(byte[] data) {
+        StringBuilder sb = new StringBuilder();
+        sb.append((0xFF & data[0]) / 40);
+        sb.append(".");
+        sb.append((0xFF & data[0]) % 40);
+
+        int i = 0;
+        while (++i < data.length) {
+            int n = 0;
+            while (data[i] < 0) {
+                n = n * 128 + (0x7F & data[i]);
+                i++;
+            }
+            n = n * 128 + data[i];
+            sb.append(".");
+            sb.append(n);
+        }
+
+        return sb.toString();
+    }
+
+    int getPayloadLength(PDU pdu) throws Exception {
+        switch (pdu.getTag() & 0x1F) {
+        case EOC:
+            return 1;
+
+        case BOOLEAN:
+            return 1;
+
+        case INTEGER:
+            return size(pdu.getInt());
+
+        case UTF8_STRING:
+            String s = pdu.getString();
+            byte[] encoded = s.getBytes("UTF-8");
+            return encoded.length;
+
+        case IA5STRING:
+        case VISIBLE_STRING:
+        case UNIVERSAL_STRING:
+        case PRINTABLE_STRING:
+        case GENERALIZED_TIME:
+        case GRAPHIC_STRING:
+        case GENERAL_STRING:
+        case CHARACTER_STRING:
+        case UTCTIME:
+        case NUMERIC_STRING: {
+            String str = pdu.getString();
+            encoded = str.getBytes("ASCII");
+            return encoded.length;
+        }
+
+        case OBJECT_IDENTIFIER:
+        case REAL:
+        case BIT_STRING:
+            return pdu.getBytes().length;
+
+        case OCTET_STRING:
+        case NULL:
+        case OBJECT_DESCRIPTOR:
+        case EXTERNAL:
+        case ENUMERATED:
+        case EMBEDDED_PDV:
+        case RELATIVE_OID:
+        case T61_STRING:
+        case VIDEOTEX_STRING:
+        case BMP_STRING:
+            return pdu.getBytes().length;
+
+        default:
+            throw new IllegalArgumentException("Invalid type: " + pdu);
+        }
+    }
+
+    int size(long value) {
+        if (value < 128)
+            return 1;
+
+        if (value <= 0xFF)
+            return 2;
+
+        if (value <= 0xFFFF)
+            return 3;
+
+        if (value <= 0xFFFFFF)
+            return 4;
+
+        if (value <= 0xFFFFFFFF)
+            return 5;
+
+        if (value <= 0xFFFFFFFFFFL)
+            return 6;
+
+        if (value <= 0xFFFFFFFFFFFFL)
+            return 7;
+
+        if (value <= 0xFFFFFFFFFFFFFFL)
+            return 8;
+
+        if (value <= 0xFFFFFFFFFFFFFFFFL)
+            return 9;
+
+        throw new IllegalArgumentException("length too long");
+    }
+
+    public void write(OutputStream out, PDU pdu) throws Exception {
+        byte id = 0;
+
+        switch (pdu.getClss()) {
+        case UNIVERSAL:
+            id |= 0;
+            break;
+        case APPLICATION:
+            id |= 0x40;
+            break;
+        case CONTEXT:
+            id |= 0x80;
+            break;
+        case PRIVATE:
+            id |= 0xC0;
+            break;
+        }
+
+        if (pdu.isConstructed())
+            id |= 0x20;
+
+        int tag = pdu.getTag();
+        if (tag >= 0 && tag < 31) {
+            id |= tag;
+        } else {
+            throw new UnsupportedOperationException("Cant do tags > 30");
+        }
+
+        out.write(id);
+
+        int length = getPayloadLength(pdu);
+        int size = size(length);
+        if (size == 1) {
+            out.write(length);
+        } else {
+            out.write(size);
+            while (--size >= 0) {
+                byte data = (byte) ((length >> (size * 8)) & 0xFF);
+                out.write(data);
+            }
+        }
+        writePayload(out, pdu);
+    }
+
+    void writePayload(OutputStream out, PDU pdu) throws Exception {
+        switch (pdu.getTag()) {
+        case EOC:
+            out.write(0);
+            break;
+
+        case BOOLEAN:
+            if (pdu.getBoolean())
+                out.write(-1);
+            else
+                out.write(0);
+            break;
+
+        case ENUMERATED:
+        case INTEGER: {
+            long value = pdu.getInt();
+            int size = size(value);
+            for (int i = size; i >= 0; i--) {
+                byte b = (byte) ((value >> (i * 8)) & 0xFF);
+                out.write(b);
+            }
+        }
+
+        case BIT_STRING: {
+            byte bytes[] = pdu.getBytes();
+            int unused = bytes[0];
+            assert unused <= 7;
+            int[] mask = { 0xFF, 0x7F, 0x3F, 0x1F, 0xF, 0x7, 0x3, 0x1 };
+            bytes[bytes.length - 1] &= (byte) mask[unused];
+            out.write(bytes);
+            break;
+        }
+
+        case RELATIVE_OID:
+        case OBJECT_IDENTIFIER: {
+            int[] oid = pdu.getOID();
+            assert oid.length > 2;
+            assert oid[0] < 4;
+            assert oid[1] < 40;
+            byte top = (byte) (oid[0] * 40 + oid[1]);
+            out.write(top);
+            for (int i = 2; i < oid.length; i++) {
+                putOid(out,oid[i]);
+            }
+            break;
+        }
+
+        case OCTET_STRING: {
+            byte bytes[] = pdu.getBytes();
+            out.write(bytes);
+            break;
+        }
+
+        case NULL:
+            break;
+
+        case BMP_STRING:
+        case GRAPHIC_STRING:
+        case VISIBLE_STRING:
+        case GENERAL_STRING:
+        case UNIVERSAL_STRING:
+        case CHARACTER_STRING:
+        case NUMERIC_STRING:
+        case PRINTABLE_STRING:
+        case VIDEOTEX_STRING:
+        case T61_STRING:
+        case REAL:
+        case EMBEDDED_PDV:
+        case EXTERNAL:
+            throw new UnsupportedEncodingException("dont know real, embedded PDV or external");
+            
+        case UTF8_STRING: {
+            String s = pdu.getString();
+            byte [] data = s.getBytes("UTF-8");
+            out.write(data);
+            break;
+        }
+        
+        case OBJECT_DESCRIPTOR:
+        case IA5STRING:
+            String s = pdu.getString();
+            byte [] data = s.getBytes("ASCII");
+            out.write(data);
+            break;
+            
+            
+        case SEQUENCE:
+        case SET: {
+            PDU pdus[] = pdu.getChildren();
+            for ( PDU p : pdus ) {
+                write(out, p);
+            }
+        }
+            
+        
+        case UTCTIME:
+        case GENERALIZED_TIME:
+            Date date = pdu.getDate();
+            String ss= df.format(date);
+            byte d[] = ss.getBytes("ASCII");
+            out.write(d);
+            break;
+            
+        }
+    }
+    
+
+    private void putOid(OutputStream out, int i) throws IOException {
+        if (i > 127) {
+            putOid(out, i >> 7);
+            out.write(0x80 + (i & 0x7F));
+        } else
+            out.write(i & 0x7F);
+    }
+}
diff --git a/bundleplugin/src/main/java/aQute/libg/asn1/PDU.java b/bundleplugin/src/main/java/aQute/libg/asn1/PDU.java
new file mode 100644
index 0000000..033928c
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/libg/asn1/PDU.java
@@ -0,0 +1,114 @@
+package aQute.libg.asn1;
+
+import java.util.*;
+
+public class PDU implements Types, Iterable<PDU> {
+    final int identifier;
+    final Object  payload;
+    byte data[] = new byte[100];
+
+
+    public PDU(int id, Object payload) {
+        identifier = id;
+        this.payload = payload;
+    }
+
+    public PDU(Date payload) {
+        identifier = UTCTIME;
+        this.payload = payload;
+    }
+
+    public PDU(int n) {
+        this(UNIVERSAL+INTEGER, n);
+    }
+
+    public PDU(boolean value) {
+        this(UNIVERSAL+BOOLEAN, value);
+    }
+
+    public PDU(String s) throws Exception {
+        this(UNIVERSAL+IA5STRING, s);
+    }
+    
+    public PDU(byte[] data) {
+        this(UNIVERSAL+OCTET_STRING, data);
+    }
+    
+    public PDU(BitSet bits) {
+        this(UNIVERSAL+BIT_STRING, bits);
+    }
+
+    public PDU(int top, int l1, int... remainder) {
+        identifier = UNIVERSAL+OBJECT_IDENTIFIER;
+        int[] ids = new int[remainder.length + 2];
+        ids[0] = top;
+        ids[1] = l1;
+        System.arraycopy(remainder, 0, ids, 2, remainder.length);
+        payload = ids;
+    }
+
+    public PDU(int tag, PDU... set) {
+        this(tag,(Object)set);
+    }
+
+    public PDU(PDU... set) {
+        this(SEQUENCE+CONSTRUCTED,set);
+    }
+
+
+    public int getTag() {
+        return identifier & TAGMASK;
+    }
+
+    int getClss() {
+        return identifier & CLASSMASK;
+    }
+
+    public boolean isConstructed() {
+        return (identifier & CONSTRUCTED) != 0;
+    }
+
+    public String getString() {
+        return (String) payload;
+    }
+
+    public Iterator<PDU> iterator() {
+        return Arrays.asList((PDU[]) payload).iterator();
+    }
+
+    
+    public int[] getOID() {
+        assert getTag() == OBJECT_IDENTIFIER;
+        return (int[]) payload;
+    }
+
+    public Boolean getBoolean() {
+        assert getTag() == BOOLEAN;
+        return (Boolean) payload;
+    }
+
+    public BitSet getBits() {
+        assert getTag() == BIT_STRING;
+        return (BitSet) payload;
+    }
+
+    public int getInt() {
+        assert getTag() == INTEGER || getTag() == ENUMERATED;
+        return (Integer) payload;
+    }
+
+    public byte[] getBytes() {
+        return (byte[]) payload;
+    }
+
+    public PDU[] getChildren() {
+        assert isConstructed();
+        return (PDU[]) payload;
+    }
+
+    public Date getDate() {
+        assert getTag() == UTCTIME || getTag() == GENERALIZED_TIME;
+        return (Date) payload;
+    }
+
+}
diff --git a/bundleplugin/src/main/java/aQute/libg/asn1/Types.java b/bundleplugin/src/main/java/aQute/libg/asn1/Types.java
new file mode 100644
index 0000000..630ed1c
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/libg/asn1/Types.java
@@ -0,0 +1,65 @@
+package aQute.libg.asn1;
+
+public interface Types {
+    int      UNIVERSAL         = 0x00000000;
+    int      APPLICATION       = 0x40000000;
+    int      CONTEXT           = 0x80000000;
+    int      PRIVATE           = 0xC0000000;
+    int      CLASSMASK         = 0xC0000000;
+    int      CONSTRUCTED       = 0x20000000;
+    int      TAGMASK           = 0x1FFFFFFF;
+
+    String [] CLASSES = {"U", "A", "C", "P"};
+    
+    // Payload Primitve
+    int      EOC               = 0;                                // null
+    // x
+    int      BOOLEAN           = 1;                                // Boolean
+    // x
+    int      INTEGER           = 2;                                // Long
+    // x
+    int      BIT_STRING        = 3;                                // byte
+    // [] -
+    int      OCTET_STRING      = 4;                                // byte
+    // [] -
+    int      NULL              = 5;                                // null
+    // x
+    int      OBJECT_IDENTIFIER = 6;                                // int[]
+    // x
+    int      OBJECT_DESCRIPTOR = 7;                                // 
+    int      EXTERNAL          = 8;                                //
+    int      REAL              = 9;                                // double
+    // x
+    int      ENUMERATED        = 10;                               // 
+    int      EMBEDDED_PDV      = 11;                               //
+    int      UTF8_STRING       = 12;                               // String
+    int      RELATIVE_OID      = 13;                               // 
+    int      SEQUENCE          = 16;                               // 
+    int      SET               = 17;
+    int      NUMERIC_STRING    = 18;                               // String
+    int      PRINTABLE_STRING  = 19;                               // String
+    int      T61_STRING        = 20;                               // String
+    int      VIDEOTEX_STRING   = 21;                               // String
+    int      IA5STRING         = 22;                               // String
+    int      UTCTIME           = 23;                               // Date
+    int      GENERALIZED_TIME  = 24;                               // Date
+    int      GRAPHIC_STRING    = 25;                               // String
+    int      VISIBLE_STRING    = 26;                               // String
+    int      GENERAL_STRING    = 27;                               // String
+    int      UNIVERSAL_STRING  = 28;                               // String
+    int      CHARACTER_STRING  = 29;                               // String
+    int      BMP_STRING        = 30;                               // byte[]
+
+    String[] TAGS              = { "EOC               ",
+            "BOOLEAN           ", "INTEGER           ", "BIT_STRING        ",
+            "OCTET_STRING      ", "NULL              ", "OBJECT_IDENTIFIER ",
+            "OBJECT_DESCRIPTOR ", "EXTERNAL          ", "REAL              ",
+            "ENUMERATED        ", "EMBEDDED_PDV      ", "UTF8_STRING       ",
+            "RELATIVE_OID      ", "?(14)             ", "?(15)             ",
+            "SEQUENCE          ", "SET               ", "NUMERIC_STRING    ",
+            "PRINTABLE_STRING  ", "T61_STRING        ", "VIDEOTEX_STRING   ",
+            "IA5STRING         ", "UTCTIME           ", "GENERALIZED_TIME  ",
+            "GRAPHIC_STRING    ", "VISIBLE_STRING    ", "GENERAL_STRING    ",
+            "UNIVERSAL_STRING  ", "CHARACTER_STRING  ", "BMP_STRING        ", };
+
+}
diff --git a/bundleplugin/src/main/java/aQute/libg/asn1/algorithms b/bundleplugin/src/main/java/aQute/libg/asn1/algorithms
new file mode 100644
index 0000000..4fb6ab4
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/libg/asn1/algorithms
@@ -0,0 +1,22 @@
+---------------------------------------------------------------------------
+SignatureAlgorithm      digestAlgo        (I)  signatureAlgo (RFC 2630)
+                                          (II) digestEncrAlgo(PKCS#7)
+---------------------------------------------------------------------------
+(A) sha1WithRSA            1.3.14.3.2.26  (Ia)     1.2.840.113549.1.1.5
+   (1.2.840.113549.1.1.5)                 (Ib)     1.2.840.113549.1.1.1
+                                          (II)     1.2.840.113549.1.1.1
+
+
+(B) md5WithRSA           1.2.840.1x9.2.5  (Ia)     1.2.840.113549.1.1.4
+   (1.2.840.113549.1.1.4)                 (Ib)     1.2.840.113549.1.1.1
+                                          (II)     1.2.840.113549.1.1.1
+
+
+(C) ripeMD160WithRsa        1.3.36.3.2.1  (Ia)     1.3.36.3.3.1.2
+   (1.3.36.3.3.1.2)                       (Ib)     1.2.840.113549.1.1.1
+                                          (II)     1.2.840.113549.1.1.1
+
+
+(D) sha1WithDsa            1.3.14.3.2.26  (Ia)     1.2.840.10040.4.3
+   (1.2.840.10040.4.3)                    (Ib)     1.2.840.10040.4.1 (?)
+                                          (II)     1.2.840.10040.4.1
diff --git a/bundleplugin/src/main/java/aQute/libg/asn1/packageinfo b/bundleplugin/src/main/java/aQute/libg/asn1/packageinfo
new file mode 100644
index 0000000..7c8de03
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/libg/asn1/packageinfo
@@ -0,0 +1 @@
+version 1.0