runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/ee8/ResourceFileServlet.java [109:201]:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  protected void doGet(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
    String servletPath;
    String pathInfo;

    boolean included = request.getAttribute(RequestDispatcher.INCLUDE_REQUEST_URI) != null;
    if (included) {
      servletPath = (String) request.getAttribute(RequestDispatcher.INCLUDE_SERVLET_PATH);
      pathInfo = (String) request.getAttribute(RequestDispatcher.INCLUDE_PATH_INFO);
      if (servletPath == null) {
        servletPath = request.getServletPath();
        pathInfo = request.getPathInfo();
      }
    } else {
      included = Boolean.FALSE;
      servletPath = request.getServletPath();
      pathInfo = request.getPathInfo();
    }

    boolean forwarded = request.getAttribute(RequestDispatcher.FORWARD_REQUEST_URI) != null;
    String pathInContext = URIUtil.addPaths(servletPath, pathInfo);

    // The servlet spec says "No file contained in the WEB-INF
    // directory may be served directly a client by the container.
    // However, ... may be exposed using the RequestDispatcher calls."
    // Thus, we only allow these requests for includes and forwards.
    //
    // TODO: I suspect we should allow error handlers here somehow.
    if (isProtectedPath(pathInContext) && !included && !forwarded) {
      response.sendError(HttpServletResponse.SC_NOT_FOUND);
      return;
    }

    if (maybeServeWelcomeFile(pathInContext, included, request, response)) {
      // We served a welcome file (either via redirecting, forwarding, or including).
      return;
    }

    if (pathInContext.endsWith("/")) {
      // N.B.: Resource.addPath() trims off trailing
      // slashes, which may result in us serving files for strange
      // paths (e.g. "/index.html/").  Since we already took care of
      // welcome files above, we just return a 404 now if the path
      // ends with a slash.
      response.sendError(HttpServletResponse.SC_NOT_FOUND);
      return;
    }

    // RFC 2396 specifies which characters are allowed in URIs:
    //
    // http://tools.ietf.org/html/rfc2396#section-2.4.3
    //
    // See also RFC 3986, which specifically mentions handling %00,
    // which would allow security checks to be bypassed.
    for (int i = 0; i < pathInContext.length(); i++) {
      int c = pathInContext.charAt(i);
      if (c < 0x20 || c == 0x7F) {
        response.sendError(HttpServletResponse.SC_BAD_REQUEST);
        logger.atWarning().log(
            "Attempted to access file containing control character, returning 400.");
        return;
      }
    }

    // Find the resource
    Resource resource = getResource(pathInContext);
    if (resource == null) {
      response.sendError(HttpServletResponse.SC_NOT_FOUND);
      return;
    }

    if (StringUtil.endsWithIgnoreCase(resource.getName(), ".jsp")) {
      // General paranoia: don't ever serve raw .jsp files.
      response.sendError(HttpServletResponse.SC_NOT_FOUND);
      return;
    }

    // Handle resource
    if (resource.isDirectory()) {
      if (included || !fSender.checkIfUnmodified(request, response, resource)) {
        response.sendError(HttpServletResponse.SC_FORBIDDEN);
      }
    } else {
      if (!resource.exists() || !aliasCheck.checkAlias(pathInContext, resource)) {
        logger.atWarning().log("Non existent resource: %s = %s", pathInContext, resource);
        response.sendError(HttpServletResponse.SC_NOT_FOUND);
      } else {
        if (included || !fSender.checkIfUnmodified(request, response, resource)) {
          fSender.sendData(context, response, included, resource, request.getRequestURI());
        }
      }
    }
  }
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -



runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/ee10/ResourceFileServlet.java [108:200]:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  protected void doGet(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
    String servletPath;
    String pathInfo;

    boolean included = request.getAttribute(RequestDispatcher.INCLUDE_REQUEST_URI) != null;
    if (included) {
      servletPath = (String) request.getAttribute(RequestDispatcher.INCLUDE_SERVLET_PATH);
      pathInfo = (String) request.getAttribute(RequestDispatcher.INCLUDE_PATH_INFO);
      if (servletPath == null) {
        servletPath = request.getServletPath();
        pathInfo = request.getPathInfo();
      }
    } else {
      included = Boolean.FALSE;
      servletPath = request.getServletPath();
      pathInfo = request.getPathInfo();
    }

    boolean forwarded = request.getAttribute(RequestDispatcher.FORWARD_REQUEST_URI) != null;
    String pathInContext = URIUtil.addPaths(servletPath, pathInfo);

    // The servlet spec says "No file contained in the WEB-INF
    // directory may be served directly a client by the container.
    // However, ... may be exposed using the RequestDispatcher calls."
    // Thus, we only allow these requests for includes and forwards.
    //
    // TODO: I suspect we should allow error handlers here somehow.
    if (isProtectedPath(pathInContext) && !included && !forwarded) {
      response.sendError(HttpServletResponse.SC_NOT_FOUND);
      return;
    }

    if (maybeServeWelcomeFile(pathInContext, included, request, response)) {
      // We served a welcome file (either via redirecting, forwarding, or including).
      return;
    }

    if (pathInContext.endsWith("/")) {
      // N.B.: Resource.addPath() trims off trailing
      // slashes, which may result in us serving files for strange
      // paths (e.g. "/index.html/").  Since we already took care of
      // welcome files above, we just return a 404 now if the path
      // ends with a slash.
      response.sendError(HttpServletResponse.SC_NOT_FOUND);
      return;
    }

    // RFC 2396 specifies which characters are allowed in URIs:
    //
    // http://tools.ietf.org/html/rfc2396#section-2.4.3
    //
    // See also RFC 3986, which specifically mentions handling %00,
    // which would allow security checks to be bypassed.
    for (int i = 0; i < pathInContext.length(); i++) {
      int c = pathInContext.charAt(i);
      if (c < 0x20 || c == 0x7F) {
        response.sendError(HttpServletResponse.SC_BAD_REQUEST);
        logger.atWarning().log(
            "Attempted to access file containing control character, returning 400.");
        return;
      }
    }

    // Find the resource
    Resource resource = getResource(pathInContext);
    if (resource == null) {
      response.sendError(HttpServletResponse.SC_NOT_FOUND);
      return;
    }

    if (StringUtil.endsWithIgnoreCase(resource.getName(), ".jsp")) {
      // General paranoia: don't ever serve raw .jsp files.
      response.sendError(HttpServletResponse.SC_NOT_FOUND);
      return;
    }

    // Handle resource
    if (resource.isDirectory()) {
      if (included || !fSender.checkIfUnmodified(request, response, resource)) {
        response.sendError(HttpServletResponse.SC_FORBIDDEN);
      }
    } else {
      if (!resource.exists() || !aliasCheck.checkAlias(pathInContext, resource)) {
        logger.atWarning().log("Non existent resource: %s = %s", pathInContext, resource);
        response.sendError(HttpServletResponse.SC_NOT_FOUND);
      } else {
        if (included || !fSender.checkIfUnmodified(request, response, resource)) {
          fSender.sendData(context, response, included, resource, request.getRequestURI());
        }
      }
    }
  }
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -



