001    /**
002     * Copyright (c) 2000-2013 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                    int read = 0;
095    
096                    for (read = 0; read < length; read++) {
097                            int c = read();
098    
099                            if (c == -1) {
100                                    if (read == 0) {
101                                            return -1;
102                                    }
103    
104                                    return read;
105                            }
106    
107                            bytes[offset + read] = (byte) (c & 0xFF);
108                    }
109    
110                    return read;
111            }
112    
113            public int read(char[] chars, int offset, int length) throws IOException {
114                    int read = 0;
115    
116                    for (read = 0; read < length; read++) {
117                            int c = read();
118    
119                            if (c == -1) {
120                                    if (read == 0) {
121                                            return -1;
122                                    }
123    
124                                    return read;
125                            }
126    
127                            chars[offset + read] = (char)c;
128                    }
129    
130                    return read;
131            }
132    
133            protected int readFromBuffer() {
134                    _bufferLength--;
135    
136                    return _buffer[_bufferLength];
137            }
138    
139            protected int readFromSource() throws IOException {
140                    if (_inputStream != null) {
141                            return _inputStream.read();
142                    }
143    
144                    if (_reader != null) {
145                            return _reader.read();
146                    }
147    
148                    throw new IllegalStateException("No underlying source available");
149            }
150    
151            protected void setBuffer(int[] buffer) {
152                    _buffer = buffer;
153    
154                    ArrayUtil.reverse(_buffer);
155    
156                    _bufferLength = _buffer.length;
157            }
158    
159            private int[] _buffer;
160            private int _bufferLength;
161            private boolean _documentStarted;
162            private InputStream _inputStream;
163            private Reader _reader;
164            private boolean entityDeclaration;
165    
166    }