1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36 package org.jboss.netty.handler.codec.http.websocketx;
37
38 import org.jboss.netty.handler.codec.frame.CorruptedFrameException;
39
40
41
42
43 final class Utf8Validator {
44 private static final int UTF8_ACCEPT = 0;
45 private static final int UTF8_REJECT = 12;
46
47 private static final byte[] TYPES = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
48 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
49 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
50 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
51 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1,
52 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 7, 7, 7, 7,
53 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8,
54 8, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
55 2, 2, 10, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 3, 3, 11, 6, 6, 6, 5, 8, 8, 8, 8, 8,
56 8, 8, 8, 8, 8, 8 };
57
58 private static final byte[] STATES = { 0, 12, 24, 36, 60, 96, 84, 12, 12, 12, 48, 72, 12, 12,
59 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 0, 12, 12, 12, 12, 12, 0, 12, 0, 12, 12,
60 12, 24, 12, 12, 12, 12, 12, 24, 12, 24, 12, 12, 12, 12, 12, 12, 12, 12, 12, 24, 12, 12,
61 12, 12, 12, 24, 12, 12, 12, 12, 12, 12, 12, 24, 12, 12, 12, 12, 12, 12, 12, 12, 12, 36,
62 12, 36, 12, 12, 12, 36, 12, 12, 12, 12, 12, 36, 12, 36, 12, 12, 12, 36, 12, 12, 12, 12,
63 12, 12, 12, 12, 12, 12 };
64
65 @SuppressWarnings("RedundantFieldInitialization")
66 private int state = UTF8_ACCEPT;
67 private int codep;
68 private boolean checking;
69
70 public void check(byte[] bytes) throws CorruptedFrameException {
71 checking = true;
72 for (byte b : bytes) {
73 write(b);
74 }
75 }
76
77 private void write(int b) throws CorruptedFrameException {
78 byte type = TYPES[b & 0xFF];
79
80 codep = state != UTF8_ACCEPT ? b & 0x3f | codep << 6 : 0xff >> type & b;
81
82 state = STATES[state + type];
83
84 if (state == UTF8_REJECT) {
85 throw new CorruptedFrameException("bytes are not UTF-8");
86 }
87 }
88
89 public void finish() throws CorruptedFrameException {
90 checking = false;
91 codep = 0;
92 if (state != UTF8_ACCEPT) {
93 state = UTF8_ACCEPT;
94 throw new CorruptedFrameException("bytes are not UTF-8");
95 }
96 }
97
98 public boolean isChecking() {
99 return checking;
100 }
101 }