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 java.io.FilterInputStream;
018    import java.io.FilterReader;
019    import java.io.IOException;
020    import java.io.InputStream;
021    import java.io.Reader;
022    
023    import org.xml.sax.ContentHandler;
024    import org.xml.sax.DTDHandler;
025    import org.xml.sax.EntityResolver;
026    import org.xml.sax.ErrorHandler;
027    import org.xml.sax.InputSource;
028    import org.xml.sax.SAXException;
029    import org.xml.sax.SAXNotRecognizedException;
030    import org.xml.sax.SAXNotSupportedException;
031    import org.xml.sax.XMLReader;
032    
033    /**
034     * @author Tomas Polesovsky
035     */
036    public class StripDoctypeXMLReader implements XMLReader {
037    
038            public StripDoctypeXMLReader(XMLReader xmlReader) {
039                    _xmlReader = xmlReader;
040            }
041    
042            @Override
043            public ContentHandler getContentHandler() {
044                    return _xmlReader.getContentHandler();
045            }
046    
047            @Override
048            public DTDHandler getDTDHandler() {
049                    return _xmlReader.getDTDHandler();
050            }
051    
052            @Override
053            public EntityResolver getEntityResolver() {
054                    return _xmlReader.getEntityResolver();
055            }
056    
057            @Override
058            public ErrorHandler getErrorHandler() {
059                    return _xmlReader.getErrorHandler();
060            }
061    
062            @Override
063            public boolean getFeature(String name)
064                    throws SAXNotRecognizedException, SAXNotSupportedException {
065    
066                    return _xmlReader.getFeature(name);
067            }
068    
069            @Override
070            public Object getProperty(String name)
071                    throws SAXNotRecognizedException, SAXNotSupportedException {
072    
073                    return _xmlReader.getProperty(name);
074            }
075    
076            public XMLReader getXmlReader() {
077                    return _xmlReader;
078            }
079    
080            @Override
081            public void parse(InputSource inputSource)
082                    throws IOException, SAXException {
083    
084                    if (_disallowDoctypeDecl) {
085                            InputStream inputStream = inputSource.getByteStream();
086    
087                            if (inputStream != null) {
088                                    final StripDoctypeFilter stripDoctypeFilter =
089                                            new StripDoctypeFilter(inputStream);
090    
091                                    inputSource.setByteStream(
092                                            new FilterInputStream(inputStream) {
093    
094                                                    @Override
095                                                    public int read() throws IOException {
096                                                            return stripDoctypeFilter.read();
097                                                    }
098    
099                                                    @Override
100                                                    public int read(byte[] bytes, int offset, int length)
101                                                            throws IOException {
102    
103                                                            return stripDoctypeFilter.read(
104                                                                    bytes, offset, length);
105                                                    }
106    
107                                            });
108                            }
109    
110                            Reader reader = inputSource.getCharacterStream();
111    
112                            if (reader != null) {
113                                    final StripDoctypeFilter stripDoctypeFilter =
114                                            new StripDoctypeFilter(reader);
115    
116                                    inputSource.setCharacterStream(
117                                            new FilterReader(reader) {
118    
119                                                    @Override
120                                                    public int read() throws IOException {
121                                                            return stripDoctypeFilter.read();
122                                                    }
123    
124                                                    @Override
125                                                    public int read(char[] chars, int offset, int length)
126                                                            throws IOException {
127    
128                                                            return stripDoctypeFilter.read(
129                                                                    chars, offset, length);
130                                                    }
131    
132                                            });
133                            }
134                    }
135    
136                    _xmlReader.parse(inputSource);
137            }
138    
139            @Override
140            public void parse(String systemId) throws IOException, SAXException {
141                    _xmlReader.parse(systemId);
142            }
143    
144            @Override
145            public void setContentHandler(ContentHandler contentHandler) {
146                    _xmlReader.setContentHandler(contentHandler);
147            }
148    
149            @Override
150            public void setDTDHandler(DTDHandler dtdHandler) {
151                    _xmlReader.setDTDHandler(dtdHandler);
152            }
153    
154            @Override
155            public void setEntityResolver(EntityResolver entityResolver) {
156                    _xmlReader.setEntityResolver(entityResolver);
157            }
158    
159            @Override
160            public void setErrorHandler(ErrorHandler errorHandler) {
161                    _xmlReader.setErrorHandler(errorHandler);
162            }
163    
164            @Override
165            public void setFeature(String name, boolean value)
166                    throws SAXNotRecognizedException, SAXNotSupportedException {
167    
168                    if (_FEATURES_DISALLOW_DOCTYPE_DECL.equals(name)) {
169                            _disallowDoctypeDecl = value;
170                    }
171    
172                    _xmlReader.setFeature(name, value);
173            }
174    
175            @Override
176            public void setProperty(String name, Object value)
177                    throws SAXNotRecognizedException, SAXNotSupportedException {
178    
179                    _xmlReader.setProperty(name, value);
180            }
181    
182            private static final String _FEATURES_DISALLOW_DOCTYPE_DECL =
183                    "http://apache.org/xml/features/disallow-doctype-decl";
184    
185            private boolean _disallowDoctypeDecl;
186            private final XMLReader _xmlReader;
187    
188    }