/** The safe character set. */ static { urlEncoder = new URLEncoder(); urlEncoder.addSafeCharacter('-'); urlEncoder.addSafeCharacter('_'); urlEncoder.addSafeCharacter('.'); urlEncoder.addSafeCharacter('*'); urlEncoder.addSafeCharacter('/'); }
protected String encode(String value, String encoding) { String retVal = null; if (encoding.equalsIgnoreCase("url")) { retVal = urlEncoder.encode(value); } else if (encoding.equalsIgnoreCase("none")) { retVal = value; } else if (encoding.equalsIgnoreCase("entity")) { retVal = HttpMessages.filter(value); } else { // This shouldn't be possible throw new IllegalArgumentException("Unknown encoding: " + encoding); } return retVal; }
static { // We try to encode only the same characters that apache does urlEncoder = new URLEncoder(); urlEncoder.addSafeCharacter(','); urlEncoder.addSafeCharacter(':'); urlEncoder.addSafeCharacter('-'); urlEncoder.addSafeCharacter('_'); urlEncoder.addSafeCharacter('.'); urlEncoder.addSafeCharacter('*'); urlEncoder.addSafeCharacter('/'); urlEncoder.addSafeCharacter('!'); urlEncoder.addSafeCharacter('~'); urlEncoder.addSafeCharacter('\''); urlEncoder.addSafeCharacter('('); urlEncoder.addSafeCharacter(')'); }
/** Parse additional request parameters. */ protected boolean postParseRequest( org.apache.coyote.Request req, Request request, org.apache.coyote.Response res, Response response) throws Exception { // XXX the processor may have set a correct scheme and port prior to this point, // in ajp13 protocols dont make sense to get the port from the connector... // otherwise, use connector configuration if (!req.scheme().isNull()) { // use processor specified scheme to determine secure state request.setSecure(req.scheme().equals("https")); } else { // use connector scheme and secure configuration, (defaults to // "http" and false respectively) req.scheme().setString(connector.getScheme()); request.setSecure(connector.getSecure()); } // FIXME: the code below doesnt belongs to here, // this is only have sense // in Http11, not in ajp13.. // At this point the Host header has been processed. // Override if the proxyPort/proxyHost are set String proxyName = connector.getProxyName(); int proxyPort = connector.getProxyPort(); if (proxyPort != 0) { req.setServerPort(proxyPort); } if (proxyName != null) { req.serverName().setString(proxyName); } // Copy the raw URI to the decodedURI MessageBytes decodedURI = req.decodedURI(); decodedURI.duplicate(req.requestURI()); // Parse the path parameters. This will: // - strip out the path parameters // - convert the decodedURI to bytes parsePathParameters(req, request); // URI decoding // %xx decoding of the URL try { req.getURLDecoder().convert(decodedURI, false); } catch (IOException ioe) { res.setStatus(400); res.setMessage("Invalid URI: " + ioe.getMessage()); connector.getService().getContainer().logAccess(request, response, 0, true); return false; } // Normalization if (!normalize(req.decodedURI())) { res.setStatus(400); res.setMessage("Invalid URI"); connector.getService().getContainer().logAccess(request, response, 0, true); return false; } // Character decoding convertURI(decodedURI, request); // Check that the URI is still normalized if (!checkNormalize(req.decodedURI())) { res.setStatus(400); res.setMessage("Invalid URI character encoding"); connector.getService().getContainer().logAccess(request, response, 0, true); return false; } // Request mapping. MessageBytes serverName; if (connector.getUseIPVHosts()) { serverName = req.localName(); if (serverName.isNull()) { // well, they did ask for it res.action(ActionCode.REQ_LOCAL_NAME_ATTRIBUTE, null); } } else { serverName = req.serverName(); } if (request.isAsyncStarted()) { // TODO SERVLET3 - async // reset mapping data, should prolly be done elsewhere request.getMappingData().recycle(); } // Version for the second mapping loop and // Context that we expect to get for that version String version = null; Context versionContext = null; boolean mapRequired = true; while (mapRequired) { // This will map the the latest version by default connector.getMapper().map(serverName, decodedURI, version, request.getMappingData()); request.setContext((Context) request.getMappingData().context); request.setWrapper((Wrapper) request.getMappingData().wrapper); // If there is no context at this point, it is likely no ROOT context // has been deployed if (request.getContext() == null) { res.setStatus(404); res.setMessage("Not found"); // No context, so use host Host host = request.getHost(); // Make sure there is a host (might not be during shutdown) if (host != null) { host.logAccess(request, response, 0, true); } return false; } // Now we have the context, we can parse the session ID from the URL // (if any). Need to do this before we redirect in case we need to // include the session id in the redirect String sessionID; if (request .getServletContext() .getEffectiveSessionTrackingModes() .contains(SessionTrackingMode.URL)) { // Get the session ID if there was one sessionID = request.getPathParameter(SessionConfig.getSessionUriParamName(request.getContext())); if (sessionID != null) { request.setRequestedSessionId(sessionID); request.setRequestedSessionURL(true); } } // Look for session ID in cookies and SSL session parseSessionCookiesId(req, request); parseSessionSslId(request); sessionID = request.getRequestedSessionId(); mapRequired = false; if (version != null && request.getContext() == versionContext) { // We got the version that we asked for. That is it. } else { version = null; versionContext = null; Object[] contexts = request.getMappingData().contexts; // Single contextVersion means no need to remap // No session ID means no possibility of remap if (contexts != null && sessionID != null) { // Find the context associated with the session for (int i = (contexts.length); i > 0; i--) { Context ctxt = (Context) contexts[i - 1]; if (ctxt.getManager().findSession(sessionID) != null) { // We found a context. Is it the one that has // already been mapped? if (!ctxt.equals(request.getMappingData().context)) { // Set version so second time through mapping // the correct context is found version = ctxt.getWebappVersion(); versionContext = ctxt; // Reset mapping request.getMappingData().recycle(); mapRequired = true; } break; } } } } if (!mapRequired && request.getContext().getPaused()) { // Found a matching context but it is paused. Mapping data will // be wrong since some Wrappers may not be registered at this // point. try { Thread.sleep(1000); } catch (InterruptedException e) { // Should never happen } // Reset mapping request.getMappingData().recycle(); mapRequired = true; } } // Possible redirect MessageBytes redirectPathMB = request.getMappingData().redirectPath; if (!redirectPathMB.isNull()) { String redirectPath = urlEncoder.encode(redirectPathMB.toString()); String query = request.getQueryString(); if (request.isRequestedSessionIdFromURL()) { // This is not optimal, but as this is not very common, it // shouldn't matter redirectPath = redirectPath + ";" + SessionConfig.getSessionUriParamName(request.getContext()) + "=" + request.getRequestedSessionId(); } if (query != null) { // This is not optimal, but as this is not very common, it // shouldn't matter redirectPath = redirectPath + "?" + query; } response.sendRedirect(redirectPath); request.getContext().logAccess(request, response, 0, true); return false; } // Filter trace method if (!connector.getAllowTrace() && req.method().equalsIgnoreCase("TRACE")) { Wrapper wrapper = request.getWrapper(); String header = null; if (wrapper != null) { String[] methods = wrapper.getServletMethods(); if (methods != null) { for (int i = 0; i < methods.length; i++) { if ("TRACE".equals(methods[i])) { continue; } if (header == null) { header = methods[i]; } else { header += ", " + methods[i]; } } } } res.setStatus(405); res.addHeader("Allow", header); res.setMessage("TRACE method is not allowed"); request.getContext().logAccess(request, response, 0, true); return false; } doConnectorAuthenticationAuthorization(req, request); return true; }