NameUtil.java

 1package de.measite.minidns.util;
 2
 3import java.io.ByteArrayOutputStream;
 4import java.io.DataInputStream;
 5import java.io.DataOutputStream;
 6import java.io.IOException;
 7import java.net.IDN;
 8import java.util.HashSet;
 9import java.util.Arrays;
10
11public class NameUtil {
12
13    public static int size(String name) {
14        return name.length() + 2;
15    }
16
17    public static boolean idnEquals(String name1, String name2) {
18        if (name1 == name2) return true; // catches null, null
19        if (name1 == null) return false;
20        if (name2 == null) return false;
21        if (name1.equals(name2)) return true;
22
23        try {
24            return Arrays.equals(toByteArray(name1),toByteArray(name2));
25        } catch (IOException e) {
26            return false; // impossible
27        }
28    }
29
30    public static byte[] toByteArray(String name) throws IOException {
31        ByteArrayOutputStream baos = new ByteArrayOutputStream(64);
32        DataOutputStream dos = new DataOutputStream(baos);
33        for (String s: name.split("[.\u3002\uFF0E\uFF61]")) {
34            byte[] buffer = IDN.toASCII(s).getBytes();
35            dos.writeByte(buffer.length);
36            dos.write(buffer);
37        }
38        dos.writeByte(0);
39        dos.flush();
40        return baos.toByteArray();
41    }   
42
43    public static String parse(DataInputStream dis, byte data[]) 
44        throws IOException
45    {
46        int c = dis.readUnsignedByte();
47        if ((c & 0xc0) == 0xc0) {
48            c = ((c & 0x3f) << 8) + dis.readUnsignedByte();
49            HashSet<Integer> jumps = new HashSet<Integer>();
50            jumps.add(c);
51            return parse(data, c, jumps);
52        }
53        if (c == 0) {
54            return "";
55        }
56        byte b[] = new byte[c];
57        dis.readFully(b);
58        String s = IDN.toUnicode(new String(b));
59        String t = parse(dis, data);
60        if (t.length() > 0) {
61            s = s + "." + t;
62        }
63        return s;
64    }
65
66    public static String parse(
67        byte data[],
68        int offset,
69        HashSet<Integer> jumps
70    ) {
71        int c = data[offset] & 0xff;
72        if ((c & 0xc0) == 0xc0) {
73            c = ((c & 0x3f) << 8) + (data[offset + 1] & 0xff);
74            if (jumps.contains(c)) {
75                throw new IllegalStateException("Cyclic offsets detected.");
76            }
77            jumps.add(c);
78            return parse(data, c, jumps);
79        }
80        if (c == 0) {
81            return "";
82        }
83        String s = new String(data,offset + 1, c);
84        String t = parse(data, offset + 1 + c, jumps);
85        if (t.length() > 0) {
86            s = s + "." + t;
87        }
88        return s;
89    }
90
91}