<commit_before>/*
 * Winstone Servlet Container
 * Copyright (C) 2003 <NAME>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * Version 2 as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License Version 2 for more details.
 *
 * You should have received a copy of the GNU General Public License
 * Version 2 along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */
package winstone;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.StringWriter;
import java.io.Writer;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.StringTokenizer;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Servlet to handle static resources. Simply finds and sends them, or
 * dispatches to the error servlet.
 * 
 * @author <a href="mailto:<EMAIL>"><NAME></a>
 * @version $Id: StaticResourceServlet.java,v 1.17 2004/12/31 07:21:00
 *          rickknowles Exp $
 */
public class StaticResourceServlet extends HttpServlet {
    // final String JSP_FILE = "org.apache.catalina.jsp_file";
    final static String FORWARD_PATH_INFO = "javax.servlet.forward.path_info";
    final static String INCLUDE_PATH_INFO = "javax.servlet.include.path_info";
    final static String CACHED_RESOURCE_DATE_HEADER = "If-Modified-Since";
    final static String LAST_MODIFIED_DATE_HEADER = "Last-Modified";
    final static String RANGE_HEADER = "Range";
    final static String ACCEPT_RANGES_HEADER = "Accept-Ranges";
    final static String CONTENT_RANGE_HEADER = "Content-Range";
    final static String RESOURCE_FILE = "winstone.LocalStrings";
    private DateFormat sdfFileDate = new SimpleDateFormat("dd-MM-yyyy HH:mm");
    private File webRoot;
    private String prefix;
    private boolean directoryList;
    private WinstoneResourceBundle resources;

    public void init(ServletConfig config) throws ServletException {
        super.init(config);
        this.resources = new WinstoneResourceBundle(RESOURCE_FILE);
        this.webRoot = new File(config.getInitParameter("webRoot"));
        this.prefix = config.getInitParameter("prefix");
        String dirList = config.getInitParameter("directoryList");
        this.directoryList = (dirList == null)
                || dirList.equalsIgnoreCase("true")
                || dirList.equalsIgnoreCase("yes");
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        boolean isInclude = (request.getAttribute(INCLUDE_PATH_INFO) != null);
        boolean isForward = (request.getAttribute(FORWARD_PATH_INFO) != null);
        String path = null;

        if (isInclude)
            path = (String) request.getAttribute(INCLUDE_PATH_INFO);
        else if (request.getPathInfo() != null)
            path = request.getPathInfo();
        else
            path = "";

        // URL decode path
        path = WinstoneRequest.decodeURLToken(path, resources);

        long cachedResDate = request.getDateHeader(CACHED_RESOURCE_DATE_HEADER);
        Logger.log(Logger.DEBUG, this.resources,
                "StaticResourceServlet.PathRequested", new String[] {
                        getServletConfig().getServletName(), path });

        // Check for the resource
        File res = path.equals("") ? this.webRoot : new File(
                this.webRoot, path);

        // Send a 404 if not found
        if (!res.exists())
            response.sendError(HttpServletResponse.SC_NOT_FOUND, this.resources
                    .getString("StaticResourceServlet.PathNotFound", path));

        // Check we are below the webroot
        else if (!isDescendant(this.webRoot, res, this.webRoot)) {
            Logger.log(Logger.FULL_DEBUG, resources, "StaticResourceServlet.OutsideWebroot",
                    new String[] {res.getCanonicalPath(), this.webRoot.toString()});
            response.sendError(HttpServletResponse.SC_FORBIDDEN, this.resources
                    .getString("StaticResourceServlet.PathInvalid", path));
        }

        // Check we are not below the web-inf
        else if (!isInclude && !isForward && isDescendant(new File(this.webRoot, "WEB-INF"), res, this.webRoot)) 
            response.sendError(HttpServletResponse.SC_NOT_FOUND, this.resources
                    .getString("StaticResourceServlet.PathInvalid", path));

        // Check we are not below the meta-inf
        else if (!isInclude && !isForward && isDescendant(new File(this.webRoot, "META-INF"), res, this.webRoot)) 
            response.sendError(HttpServletResponse.SC_NOT_FOUND, this.resources
                    .getString("StaticResourceServlet.PathInvalid", path));

        // check for the directory case
        else if (res.isDirectory()) {
            if (path.endsWith("/")) {
                // Try to match each of the welcome files
                // String matchedWelcome = matchWelcomeFiles(path, res);
                // if (matchedWelcome != null)
                // response.sendRedirect(this.prefix + path + matchedWelcome);
                // else
                if (this.directoryList)
                    generateDirectoryList(request, response, path);
                else
                    response.sendError(HttpServletResponse.SC_FORBIDDEN,
                            this.resources.getString("StaticResourceServlet.AccessDenied"));
            } else
                response.sendRedirect(this.prefix + path + "/");
        }

        // Send a 304 if not modified
        else if ((cachedResDate != -1)
                && (cachedResDate < System.currentTimeMillis())
                && (cachedResDate >= res.lastModified())) {
            String mimeType = getServletContext().getMimeType(
                    res.getName().toLowerCase());
            if (mimeType != null)
                response.setContentType(mimeType);
            response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
            response.setContentLength(0);
            response.getOutputStream().close();
        }

        // Write out the resource if not range
        else if (request.getHeader(RANGE_HEADER) == null) {
            String mimeType = getServletContext().getMimeType(
                    res.getName().toLowerCase());
            if (mimeType != null)
                response.setContentType(mimeType);
            InputStream resStream = new FileInputStream(res);

            response.setStatus(HttpServletResponse.SC_OK);
            response.setContentLength((int) res.length());
            response.addHeader(ACCEPT_RANGES_HEADER, "bytes");
            response.addDateHeader(LAST_MODIFIED_DATE_HEADER, res
                    .lastModified());
            OutputStream out = null;
            Writer outWriter = null;
            try {
                out = response.getOutputStream();
            } catch (IOException err) {
                outWriter = response.getWriter();
            }<commit_msg>fixed exception catching on getOutputStream<commit_after>/*
 * Winstone Servlet Container
 * Copyright (C) 2003 <NAME>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * Version 2 as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License Version 2 for more details.
 *
 * You should have received a copy of the GNU General Public License
 * Version 2 along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */
package winstone;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.StringWriter;
import java.io.Writer;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.StringTokenizer;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Servlet to handle static resources. Simply finds and sends them, or
 * dispatches to the error servlet.
 * 
 * @author <a href="mailto:<EMAIL>"><NAME></a>
 * @version $Id: StaticResourceServlet.java,v 1.17 2004/12/31 07:21:00
 *          rickknowles Exp $
 */
public class StaticResourceServlet extends HttpServlet {
    // final String JSP_FILE = "org.apache.catalina.jsp_file";
    final static String FORWARD_PATH_INFO = "javax.servlet.forward.path_info";
    final static String INCLUDE_PATH_INFO = "javax.servlet.include.path_info";
    final static String CACHED_RESOURCE_DATE_HEADER = "If-Modified-Since";
    final static String LAST_MODIFIED_DATE_HEADER = "Last-Modified";
    final static String RANGE_HEADER = "Range";
    final static String ACCEPT_RANGES_HEADER = "Accept-Ranges";
    final static String CONTENT_RANGE_HEADER = "Content-Range";
    final static String RESOURCE_FILE = "winstone.LocalStrings";
    private DateFormat sdfFileDate = new SimpleDateFormat("dd-MM-yyyy HH:mm");
    private File webRoot;
    private String prefix;
    private boolean directoryList;
    private WinstoneResourceBundle resources;

    public void init(ServletConfig config) throws ServletException {
        super.init(config);
        this.resources = new WinstoneResourceBundle(RESOURCE_FILE);
        this.webRoot = new File(config.getInitParameter("webRoot"));
        this.prefix = config.getInitParameter("prefix");
        String dirList = config.getInitParameter("directoryList");
        this.directoryList = (dirList == null)
                || dirList.equalsIgnoreCase("true")
                || dirList.equalsIgnoreCase("yes");
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        boolean isInclude = (request.getAttribute(INCLUDE_PATH_INFO) != null);
        boolean isForward = (request.getAttribute(FORWARD_PATH_INFO) != null);
        String path = null;

        if (isInclude)
            path = (String) request.getAttribute(INCLUDE_PATH_INFO);
        else if (request.getPathInfo() != null)
            path = request.getPathInfo();
        else
            path = "";

        // URL decode path
        path = WinstoneRequest.decodeURLToken(path, resources);

        long cachedResDate = request.getDateHeader(CACHED_RESOURCE_DATE_HEADER);
        Logger.log(Logger.DEBUG, this.resources,
                "StaticResourceServlet.PathRequested", new String[] {
                        getServletConfig().getServletName(), path });

        // Check for the resource
        File res = path.equals("") ? this.webRoot : new File(
                this.webRoot, path);

        // Send a 404 if not found
        if (!res.exists())
            response.sendError(HttpServletResponse.SC_NOT_FOUND, this.resources
                    .getString("StaticResourceServlet.PathNotFound", path));

        // Check we are below the webroot
        else if (!isDescendant(this.webRoot, res, this.webRoot)) {
            Logger.log(Logger.FULL_DEBUG, resources, "StaticResourceServlet.OutsideWebroot",
                    new String[] {res.getCanonicalPath(), this.webRoot.toString()});
            response.sendError(HttpServletResponse.SC_FORBIDDEN, this.resources
                    .getString("StaticResourceServlet.PathInvalid", path));
        }

        // Check we are not below the web-inf
        else if (!isInclude && !isForward && isDescendant(new File(this.webRoot, "WEB-INF"), res, this.webRoot)) 
            response.sendError(HttpServletResponse.SC_NOT_FOUND, this.resources
                    .getString("StaticResourceServlet.PathInvalid", path));

        // Check we are not below the meta-inf
        else if (!isInclude && !isForward && isDescendant(new File(this.webRoot, "META-INF"), res, this.webRoot)) 
            response.sendError(HttpServletResponse.SC_NOT_FOUND, this.resources
                    .getString("StaticResourceServlet.PathInvalid", path));

        // check for the directory case
        else if (res.isDirectory()) {
            if (path.endsWith("/")) {
                // Try to match each of the welcome files
                // String matchedWelcome = matchWelcomeFiles(path, res);
                // if (matchedWelcome != null)
                // response.sendRedirect(this.prefix + path + matchedWelcome);
                // else
                if (this.directoryList)
                    generateDirectoryList(request, response, path);
                else
                    response.sendError(HttpServletResponse.SC_FORBIDDEN,
                            this.resources.getString("StaticResourceServlet.AccessDenied"));
            } else
                response.sendRedirect(this.prefix + path + "/");
        }

        // Send a 304 if not modified
        else if ((cachedResDate != -1)
                && (cachedResDate < System.currentTimeMillis())
                && (cachedResDate >= res.lastModified())) {
            String mimeType = getServletContext().getMimeType(
                    res.getName().toLowerCase());
            if (mimeType != null)
                response.setContentType(mimeType);
            response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
            response.setContentLength(0);
            response.getOutputStream().close();
        }

        // Write out the resource if not range
        else if (request.getHeader(RANGE_HEADER) == null) {
            String mimeType = getServletContext().getMimeType(
                    res.getName().toLowerCase());
            if (mimeType != null)
                response.setContentType(mimeType);
            InputStream resStream = new FileInputStream(res);

            response.setStatus(HttpServletResponse.SC_OK);
            response.setContentLength((int) res.length());
            response.addHeader(ACCEPT_RANGES_HEADER, "bytes");
            response.addDateHeader(LAST_MODIFIED_DATE_HEADER, res
                    .lastModified());
            OutputStream out = null;
            Writer outWriter = null;
            try {
                out = response.getOutputStream();
            } catch (Throwable err) {
                outWriter = response.getWriter();
            }
{'fraction_non_alphanumeric': 0.09614160193556602, 'fraction_numerical': 0.005857634025213295, 'mean_word_length': 2.6199585157870477, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6097795', 'n_tokens_mistral': 4141, 'n_tokens_neox': 3963, 'n_words': 1062}