001    /**
002     * Copyright (c) 2000-present Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.security.xml;
016    
017    import com.liferay.portal.kernel.util.ArrayUtil;
018    
019    import java.io.IOException;
020    import java.io.InputStream;
021    import java.io.Reader;
022    
023    /**
024     * @author Tomas Polesovsky
025     */
026    public class StripDoctypeFilter {
027    
028            public StripDoctypeFilter(InputStream inputStream) {
029                    _inputStream = inputStream;
030            }
031    
032            public StripDoctypeFilter(Reader reader) {
033                    _reader = reader;
034            }
035    
036            public int read() throws IOException {
037                    if (_bufferLength > 0) {
038                            return readFromBuffer();
039                    }
040    
041                    int c = readFromSource();
042    
043                    if (_documentStarted) {
044                            return c;
045                    }
046    
047                    if (c == '<') {
048                            int[] buffer = new int[2];
049    
050                            buffer[0] = readFromSource();
051                            buffer[1] = readFromSource();
052    
053                            if (buffer[0] == '?') {
054                                    setBuffer(buffer);
055    
056                                    return c;
057                            }
058    
059                            if ((buffer[0] == '!') && (buffer[1] == '-')) {
060                                    setBuffer(buffer);
061    
062                                    return c;
063                            }
064    
065                            if ((buffer[0] == '!') && (buffer[1] == 'D')) {
066                                    while (true) {
067                                            int doctypeContent = readFromSource();
068    
069                                            if (doctypeContent == '[') {
070                                                    entityDeclaration = true;
071                                            }
072                                            else if (doctypeContent == ']') {
073                                                    entityDeclaration = false;
074                                            }
075                                            else if (doctypeContent == '>') {
076                                                    if (!entityDeclaration) {
077                                                            _documentStarted = true;
078    
079                                                            return readFromSource();
080                                                    }
081                                            }
082                                    }
083                            }
084    
085                            setBuffer(buffer);
086    
087                            _documentStarted = true;
088                    }
089    
090                    return c;
091            }
092    
093            public int read(byte[] bytes, int offset, int length) throws IOException {
094                    if (_documentStarted && (length > _bufferLength)) {
095                            int bufferLength = _bufferLength;
096    
097                            for (int i = 0; i < bufferLength; i++) {
098                                    bytes[offset++] = (byte) (readFromBuffer() & 0xFF);
099                            }
100    
101                            return _inputStream.read(bytes, offset, length - bufferLength) +
102                                    bufferLength;
103                    }
104    
105                    int read = 0;
106    
107                    for (read = 0; read < length; read++) {
108                            int c = read();
109    
110                            if (c == -1) {
111                                    if (read == 0) {
112                                            return -1;
113                                    }
114    
115                                    return read;
116                            }
117    
118                            bytes[offset + read] = (byte) (c & 0xFF);
119                    }
120    
121                    return read;
122            }
123    
124            public int read(char[] chars, int offset, int length) throws IOException {
125                    if (_documentStarted && (length > _bufferLength)) {
126                            int bufferLength = _bufferLength;
127    
128                            for (int i = 0; i < bufferLength; i++) {
129                                    chars[offset++] = (char)readFromBuffer();
130                            }
131    
132                            return _reader.read(chars, offset, length - bufferLength) +
133                                    bufferLength;
134                    }
135    
136                    int read = 0;
137    
138                    for (read = 0; read < length; read++) {
139                            int c = read();
140    
141                            if (c == -1) {
142                                    if (read == 0) {
143                                            return -1;
144                                    }
145    
146                                    return read;
147                            }
148    
149                            chars[offset + read] = (char)c;
150                    }
151    
152                    return read;
153            }
154    
155            protected int readFromBuffer() {
156                    _bufferLength--;
157    
158                    return _buffer[_bufferLength];
159            }
160    
161            protected int readFromSource() throws IOException {
162                    if (_inputStream != null) {
163                            return _inputStream.read();
164                    }
165    
166                    if (_reader != null) {
167                            return _reader.read();
168                    }
169    
170                    throw new IllegalStateException("No underlying source available");
171            }
172    
173            protected void setBuffer(int[] buffer) {
174                    _buffer = buffer;
175    
176                    ArrayUtil.reverse(_buffer);
177    
178                    _bufferLength = _buffer.length;
179            }
180    
181            private int[] _buffer;
182            private int _bufferLength;
183            private boolean _documentStarted;
184            private InputStream _inputStream;
185            private Reader _reader;
186            private boolean entityDeclaration;
187    
188    }