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            @Override
077            public void parse(InputSource inputSource)
078                    throws IOException, SAXException {
079    
080                    if (_disallowDoctypeDecl) {
081                            InputStream inputStream = inputSource.getByteStream();
082    
083                            if (inputStream != null) {
084                                    final StripDoctypeFilter stripDoctypeFilter =
085                                            new StripDoctypeFilter(inputStream);
086    
087                                    inputSource.setByteStream(
088                                            new FilterInputStream(inputStream) {
089    
090                                                    @Override
091                                                    public int read() throws IOException {
092                                                            return stripDoctypeFilter.read();
093                                                    }
094    
095                                                    @Override
096                                                    public int read(byte[] bytes, int offset, int length)
097                                                            throws IOException {
098    
099                                                            return stripDoctypeFilter.read(
100                                                                    bytes, offset, length);
101                                                    }
102    
103                                            });
104                            }
105    
106                            Reader reader = inputSource.getCharacterStream();
107    
108                            if (reader != null) {
109                                    final StripDoctypeFilter stripDoctypeFilter =
110                                            new StripDoctypeFilter(reader);
111    
112                                    inputSource.setCharacterStream(
113                                            new FilterReader(reader) {
114    
115                                                    @Override
116                                                    public int read() throws IOException {
117                                                            return stripDoctypeFilter.read();
118                                                    }
119    
120                                                    @Override
121                                                    public int read(char[] chars, int offset, int length)
122                                                            throws IOException {
123    
124                                                            return stripDoctypeFilter.read(
125                                                                    chars, offset, length);
126                                                    }
127    
128                                            });
129                            }
130                    }
131    
132                    _xmlReader.parse(inputSource);
133            }
134    
135            @Override
136            public void parse(String systemId) throws IOException, SAXException {
137                    _xmlReader.parse(systemId);
138            }
139    
140            @Override
141            public void setContentHandler(ContentHandler contentHandler) {
142                    _xmlReader.setContentHandler(contentHandler);
143            }
144    
145            @Override
146            public void setDTDHandler(DTDHandler dtdHandler) {
147                    _xmlReader.setDTDHandler(dtdHandler);
148            }
149    
150            @Override
151            public void setEntityResolver(EntityResolver entityResolver) {
152                    _xmlReader.setEntityResolver(entityResolver);
153            }
154    
155            @Override
156            public void setErrorHandler(ErrorHandler errorHandler) {
157                    _xmlReader.setErrorHandler(errorHandler);
158            }
159    
160            @Override
161            public void setFeature(String name, boolean value)
162                    throws SAXNotRecognizedException, SAXNotSupportedException {
163    
164                    if (_FEATURES_DISALLOW_DOCTYPE_DECL.equals(name)) {
165                            _disallowDoctypeDecl = value;
166                    }
167    
168                    _xmlReader.setFeature(name, value);
169            }
170    
171            @Override
172            public void setProperty(String name, Object value)
173                    throws SAXNotRecognizedException, SAXNotSupportedException {
174    
175                    _xmlReader.setProperty(name, value);
176            }
177    
178            private static final String _FEATURES_DISALLOW_DOCTYPE_DECL =
179                    "http://apache.org/xml/features/disallow-doctype-decl";
180    
181            private boolean _disallowDoctypeDecl;
182            private final XMLReader _xmlReader;
183    
184    }