1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.xmlfield.core.impl.dom.cleanup;
17
18 import java.io.IOException;
19 import java.io.InputStream;
20
21
22
23
24
25
26
27
28
29
30
31
32 public class EntitySanitizingInputStream extends InputStream {
33
34
35
36 static int MAX_ENTITY_SIZE = 15;
37
38
39
40 static int[] readHeadUndefined = new int[] { '&', '#', '6', '5', '5', '3',
41 '3', ';' };
42
43
44
45
46
47 int[] readAheadBuffer = null;
48 int readAheadCount = 0;
49 int readAheadPosition = 0;
50
51 private InputStream wrappedInputstream;
52
53
54
55
56
57
58
59 public EntitySanitizingInputStream(InputStream xmlStream) {
60 this.wrappedInputstream = xmlStream;
61 }
62
63 @Override
64 public int available() throws IOException {
65 if (readAheadCount == 0) {
66 return super.available();
67 }
68
69 return readAheadCount - readAheadPosition + super.available();
70 }
71
72 @Override
73 public void close() throws IOException {
74 wrappedInputstream.close();
75 }
76
77 @Override
78 public int read() throws IOException {
79
80
81 if (readAheadCount > 0) {
82 int current = readAheadBuffer[readAheadPosition];
83 readAheadPosition++;
84
85
86 if (readAheadPosition == readAheadCount) {
87 readAheadCount = 0;
88 readAheadPosition = 0;
89 readAheadBuffer = null;
90 }
91 return current;
92 }
93
94 int current = wrappedInputstream.read();
95
96
97 if (current == '&') {
98 readAheadBuffer = new int[MAX_ENTITY_SIZE];
99 readAheadBuffer[0] = current;
100 current = 0;
101 readAheadCount++;
102
103
104
105 while (readAheadCount < MAX_ENTITY_SIZE && current != -1
106 && current != ';') {
107 current = wrappedInputstream.read();
108 readAheadBuffer[readAheadCount] = current;
109 readAheadCount++;
110
111
112 if (!(readAheadBuffer[1] == '#')) {
113 break;
114 }
115
116
117 if (readAheadCount > 3 && current == ';') {
118
119 StringBuilder number = new StringBuilder();
120 for (int i = 2; i < readAheadCount - 1; i++) {
121 number.append((char) readAheadBuffer[i]);
122 }
123
124 try {
125 int entity = Integer.parseInt(number.toString());
126
127
128
129 if (!(entity == 9 || entity == 10 || entity == 13
130 || entity >= 32 && entity <= 55295
131 || entity >= 57344 && entity <= 65533
132 || entity == 55296 || entity >= 56320
133 && entity <= 56319 || entity == 57343)) {
134 readAheadBuffer = readHeadUndefined;
135 readAheadCount = readAheadBuffer.length;
136
137 }
138
139 } catch (NumberFormatException e) {
140
141
142 }
143 }
144
145 }
146
147 current = readAheadBuffer[0];
148 readAheadPosition++;
149 }
150 return current;
151 }
152
153 @Override
154 public synchronized void reset() throws IOException {
155 wrappedInputstream.reset();
156 }
157
158 }