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 }