Search in sources :

Example 6 with MessageBytes

use of org.apache.tomcat.util.buf.MessageBytes in project tomcat by apache.

the class ApplicationContext method getRequestDispatcher.

@Override
public RequestDispatcher getRequestDispatcher(String path) {
    // Validate the path argument
    if (path == null)
        return (null);
    if (!path.startsWith("/"))
        throw new IllegalArgumentException(sm.getString("applicationContext.requestDispatcher.iae", path));
    // Get query string
    String queryString = null;
    String normalizedPath = path;
    int pos = normalizedPath.indexOf('?');
    if (pos >= 0) {
        queryString = normalizedPath.substring(pos + 1);
        normalizedPath = normalizedPath.substring(0, pos);
    }
    normalizedPath = RequestUtil.normalize(normalizedPath);
    if (normalizedPath == null)
        return (null);
    if (getContext().getDispatchersUseEncodedPaths()) {
        // Decode
        String decodedPath;
        try {
            decodedPath = URLDecoder.decode(normalizedPath, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            // Impossible
            return null;
        }
        // Security check to catch attempts to encode /../ sequences
        normalizedPath = RequestUtil.normalize(decodedPath);
        if (!decodedPath.equals(normalizedPath)) {
            getContext().getLogger().warn(sm.getString("applicationContext.illegalDispatchPath", path), new IllegalArgumentException());
            return null;
        }
    }
    pos = normalizedPath.length();
    // Use the thread local URI and mapping data
    DispatchData dd = dispatchData.get();
    if (dd == null) {
        dd = new DispatchData();
        dispatchData.set(dd);
    }
    MessageBytes uriMB = dd.uriMB;
    uriMB.recycle();
    // Use the thread local mapping data
    MappingData mappingData = dd.mappingData;
    // Map the URI
    CharChunk uriCC = uriMB.getCharChunk();
    try {
        uriCC.append(context.getPath(), 0, context.getPath().length());
        /*
             * Ignore any trailing path params (separated by ';') for mapping
             * purposes
             */
        int semicolon = normalizedPath.indexOf(';');
        if (pos >= 0 && semicolon > pos) {
            semicolon = -1;
        }
        uriCC.append(normalizedPath, 0, semicolon > 0 ? semicolon : pos);
        service.getMapper().map(context, uriMB, mappingData);
        if (mappingData.wrapper == null) {
            return (null);
        }
        /*
             * Append any trailing path params (separated by ';') that were
             * ignored for mapping purposes, so that they're reflected in the
             * RequestDispatcher's requestURI
             */
        if (semicolon > 0) {
            uriCC.append(normalizedPath, semicolon, pos - semicolon);
        }
    } catch (Exception e) {
        // Should never happen
        log(sm.getString("applicationContext.mapping.error"), e);
        return (null);
    }
    Wrapper wrapper = mappingData.wrapper;
    String wrapperPath = mappingData.wrapperPath.toString();
    String pathInfo = mappingData.pathInfo.toString();
    ServletMapping mapping = (new ApplicationMapping(mappingData)).getServletMapping();
    mappingData.recycle();
    String encodedUri = URLEncoder.DEFAULT.encode(uriCC.toString(), "UTF-8");
    // Construct a RequestDispatcher to process this request
    return new ApplicationDispatcher(wrapper, encodedUri, wrapperPath, pathInfo, queryString, mapping, null);
}
Also used : Wrapper(org.apache.catalina.Wrapper) ServletMapping(javax.servlet.http.ServletMapping) UnsupportedEncodingException(java.io.UnsupportedEncodingException) MessageBytes(org.apache.tomcat.util.buf.MessageBytes) ServletException(javax.servlet.ServletException) NamingException(javax.naming.NamingException) InvocationTargetException(java.lang.reflect.InvocationTargetException) UnsupportedEncodingException(java.io.UnsupportedEncodingException) MalformedURLException(java.net.MalformedURLException) MappingData(org.apache.catalina.mapper.MappingData) CharChunk(org.apache.tomcat.util.buf.CharChunk)

Example 7 with MessageBytes

use of org.apache.tomcat.util.buf.MessageBytes in project tomcat by apache.

the class ApplicationContext method getContext.

@Override
public ServletContext getContext(String uri) {
    // Validate the format of the specified argument
    if (uri == null || !uri.startsWith("/")) {
        return null;
    }
    Context child = null;
    try {
        // Look for an exact match
        Container host = context.getParent();
        child = (Context) host.findChild(uri);
        // Non-running contexts should be ignored.
        if (child != null && !child.getState().isAvailable()) {
            child = null;
        }
        // Remove any version information and use the mapper
        if (child == null) {
            int i = uri.indexOf("##");
            if (i > -1) {
                uri = uri.substring(0, i);
            }
            // Note: This could be more efficient with a dedicated Mapper
            //       method but such an implementation would require some
            //       refactoring of the Mapper to avoid copy/paste of
            //       existing code.
            MessageBytes hostMB = MessageBytes.newInstance();
            hostMB.setString(host.getName());
            MessageBytes pathMB = MessageBytes.newInstance();
            pathMB.setString(uri);
            MappingData mappingData = new MappingData();
            ((Engine) host.getParent()).getService().getMapper().map(hostMB, pathMB, null, mappingData);
            child = mappingData.context;
        }
    } catch (Throwable t) {
        ExceptionUtils.handleThrowable(t);
        return null;
    }
    if (child == null) {
        return null;
    }
    if (context.getCrossContext()) {
        // If crossContext is enabled, can always return the context
        return child.getServletContext();
    } else if (child == context) {
        // Can still return the current context
        return context.getServletContext();
    } else {
        // Nothing to return
        return null;
    }
}
Also used : Context(org.apache.catalina.Context) ServletContext(javax.servlet.ServletContext) Container(org.apache.catalina.Container) MessageBytes(org.apache.tomcat.util.buf.MessageBytes) MappingData(org.apache.catalina.mapper.MappingData) Engine(org.apache.catalina.Engine)

Example 8 with MessageBytes

use of org.apache.tomcat.util.buf.MessageBytes in project tomcat by apache.

the class RewriteValve method invoke.

@Override
public void invoke(Request request, Response response) throws IOException, ServletException {
    if (!getEnabled() || rules == null || rules.length == 0) {
        getNext().invoke(request, response);
        return;
    }
    if (Boolean.TRUE.equals(invoked.get())) {
        try {
            getNext().invoke(request, response);
        } finally {
            invoked.set(null);
        }
        return;
    }
    try {
        Resolver resolver = new ResolverImpl(request);
        invoked.set(Boolean.TRUE);
        // As long as MB isn't a char sequence or affiliated, this has to be
        // converted to a string
        String uriEncoding = request.getConnector().getURIEncoding();
        String originalQueryStringEncoded = request.getQueryString();
        MessageBytes urlMB = context ? request.getRequestPathMB() : request.getDecodedRequestURIMB();
        urlMB.toChars();
        CharSequence urlDecoded = urlMB.getCharChunk();
        CharSequence host = request.getServerName();
        boolean rewritten = false;
        boolean done = false;
        boolean qsa = false;
        for (int i = 0; i < rules.length; i++) {
            RewriteRule rule = rules[i];
            CharSequence test = (rule.isHost()) ? host : urlDecoded;
            CharSequence newtest = rule.evaluate(test, resolver);
            if (newtest != null && !test.equals(newtest.toString())) {
                if (containerLog.isDebugEnabled()) {
                    containerLog.debug("Rewrote " + test + " as " + newtest + " with rule pattern " + rule.getPatternString());
                }
                if (rule.isHost()) {
                    host = newtest;
                } else {
                    urlDecoded = newtest;
                }
                rewritten = true;
            }
            // Check QSA before the final reply
            if (!qsa && newtest != null && rule.isQsappend()) {
                // TODO: This logic will need some tweaks if we add QSD
                //       support
                qsa = true;
            }
            // - forbidden
            if (rule.isForbidden() && newtest != null) {
                response.sendError(HttpServletResponse.SC_FORBIDDEN);
                done = true;
                break;
            }
            // - gone
            if (rule.isGone() && newtest != null) {
                response.sendError(HttpServletResponse.SC_GONE);
                done = true;
                break;
            }
            // - redirect (code)
            if (rule.isRedirect() && newtest != null) {
                // Append the query string to the url if there is one and it
                // hasn't been rewritten
                String urlStringDecoded = urlDecoded.toString();
                int index = urlStringDecoded.indexOf("?");
                String rewrittenQueryStringDecoded;
                if (index == -1) {
                    rewrittenQueryStringDecoded = null;
                } else {
                    rewrittenQueryStringDecoded = urlStringDecoded.substring(index + 1);
                    urlStringDecoded = urlStringDecoded.substring(0, index);
                }
                StringBuffer urlStringEncoded = new StringBuffer(ENCODER.encode(urlStringDecoded, uriEncoding));
                if (originalQueryStringEncoded != null && originalQueryStringEncoded.length() > 0) {
                    if (rewrittenQueryStringDecoded == null) {
                        urlStringEncoded.append('?');
                        urlStringEncoded.append(originalQueryStringEncoded);
                    } else {
                        if (qsa) {
                            // if qsa is specified append the query
                            urlStringEncoded.append('?');
                            urlStringEncoded.append(ENCODER.encode(rewrittenQueryStringDecoded, uriEncoding));
                            urlStringEncoded.append('&');
                            urlStringEncoded.append(originalQueryStringEncoded);
                        } else if (index == urlStringEncoded.length() - 1) {
                            // if the ? is the last character delete it, its only purpose was to
                            // prevent the rewrite module from appending the query string
                            urlStringEncoded.deleteCharAt(index);
                        } else {
                            urlStringEncoded.append('?');
                            urlStringEncoded.append(ENCODER.encode(rewrittenQueryStringDecoded, uriEncoding));
                        }
                    }
                } else if (rewrittenQueryStringDecoded != null) {
                    urlStringEncoded.append('?');
                    urlStringEncoded.append(ENCODER.encode(rewrittenQueryStringDecoded, uriEncoding));
                }
                // 3. the url isn't absolute
                if (context && urlStringEncoded.charAt(0) == '/' && !UriUtil.hasScheme(urlStringEncoded)) {
                    urlStringEncoded.insert(0, request.getContext().getEncodedPath());
                }
                if (rule.isNoescape()) {
                    response.sendRedirect(URLDecoder.decode(urlStringEncoded.toString(), uriEncoding));
                } else {
                    response.sendRedirect(urlStringEncoded.toString());
                }
                response.setStatus(rule.getRedirectCode());
                done = true;
                break;
            }
            // - cookie
            if (rule.isCookie() && newtest != null) {
                Cookie cookie = new Cookie(rule.getCookieName(), rule.getCookieResult());
                cookie.setDomain(rule.getCookieDomain());
                cookie.setMaxAge(rule.getCookieLifetime());
                cookie.setPath(rule.getCookiePath());
                cookie.setSecure(rule.isCookieSecure());
                cookie.setHttpOnly(rule.isCookieHttpOnly());
                response.addCookie(cookie);
            }
            // - env (note: this sets a request attribute)
            if (rule.isEnv() && newtest != null) {
                for (int j = 0; j < rule.getEnvSize(); j++) {
                    request.setAttribute(rule.getEnvName(j), rule.getEnvResult(j));
                }
            }
            //   to do that)
            if (rule.isType() && newtest != null) {
                request.setContentType(rule.getTypeValue());
            }
            // - chain (skip remaining chained rules if this one does not match)
            if (rule.isChain() && newtest == null) {
                for (int j = i; j < rules.length; j++) {
                    if (!rules[j].isChain()) {
                        i = j;
                        break;
                    }
                }
                continue;
            }
            // - last (stop rewriting here)
            if (rule.isLast() && newtest != null) {
                break;
            }
            // - next (redo again)
            if (rule.isNext() && newtest != null) {
                i = 0;
                continue;
            }
            // - skip (n rules)
            if (newtest != null) {
                i += rule.getSkip();
            }
        }
        if (rewritten) {
            if (!done) {
                // See if we need to replace the query string
                String urlStringDecoded = urlDecoded.toString();
                String queryStringDecoded = null;
                int queryIndex = urlStringDecoded.indexOf('?');
                if (queryIndex != -1) {
                    queryStringDecoded = urlStringDecoded.substring(queryIndex + 1);
                    urlStringDecoded = urlStringDecoded.substring(0, queryIndex);
                }
                // Save the current context path before re-writing starts
                String contextPath = null;
                if (context) {
                    contextPath = request.getContextPath();
                }
                // Populated the encoded (i.e. undecoded) requestURI
                request.getCoyoteRequest().requestURI().setString(null);
                CharChunk chunk = request.getCoyoteRequest().requestURI().getCharChunk();
                chunk.recycle();
                if (context) {
                    // This is neither decoded nor normalized
                    chunk.append(contextPath);
                }
                chunk.append(ENCODER.encode(urlStringDecoded, uriEncoding));
                request.getCoyoteRequest().requestURI().toChars();
                // Decoded and normalized URI
                // Rewriting may have denormalized the URL
                urlStringDecoded = RequestUtil.normalize(urlStringDecoded);
                request.getCoyoteRequest().decodedURI().setString(null);
                chunk = request.getCoyoteRequest().decodedURI().getCharChunk();
                chunk.recycle();
                if (context) {
                    // This is decoded and normalized
                    chunk.append(request.getServletContext().getContextPath());
                }
                chunk.append(urlStringDecoded);
                request.getCoyoteRequest().decodedURI().toChars();
                // Set the new Query if there is one
                if (queryStringDecoded != null) {
                    request.getCoyoteRequest().queryString().setString(null);
                    chunk = request.getCoyoteRequest().queryString().getCharChunk();
                    chunk.recycle();
                    chunk.append(ENCODER.encode(queryStringDecoded, uriEncoding));
                    if (qsa && originalQueryStringEncoded != null && originalQueryStringEncoded.length() > 0) {
                        chunk.append('&');
                        chunk.append(originalQueryStringEncoded);
                    }
                    if (!chunk.isNull()) {
                        request.getCoyoteRequest().queryString().toChars();
                    }
                }
                // Set the new host if it changed
                if (!host.equals(request.getServerName())) {
                    request.getCoyoteRequest().serverName().setString(null);
                    chunk = request.getCoyoteRequest().serverName().getCharChunk();
                    chunk.recycle();
                    chunk.append(host.toString());
                    request.getCoyoteRequest().serverName().toChars();
                }
                request.getMappingData().recycle();
                // Reinvoke the whole request recursively
                try {
                    Connector connector = request.getConnector();
                    if (!connector.getProtocolHandler().getAdapter().prepare(request.getCoyoteRequest(), response.getCoyoteResponse())) {
                        return;
                    }
                    Pipeline pipeline = connector.getService().getContainer().getPipeline();
                    request.setAsyncSupported(pipeline.isAsyncSupported());
                    pipeline.getFirst().invoke(request, response);
                } catch (Exception e) {
                // This doesn't actually happen in the Catalina adapter implementation
                }
            }
        } else {
            getNext().invoke(request, response);
        }
    } finally {
        invoked.set(null);
    }
}
Also used : Cookie(javax.servlet.http.Cookie) Connector(org.apache.catalina.connector.Connector) MessageBytes(org.apache.tomcat.util.buf.MessageBytes) ServletException(javax.servlet.ServletException) LifecycleException(org.apache.catalina.LifecycleException) IOException(java.io.IOException) Pipeline(org.apache.catalina.Pipeline) CharChunk(org.apache.tomcat.util.buf.CharChunk)

Example 9 with MessageBytes

use of org.apache.tomcat.util.buf.MessageBytes in project tomcat by apache.

the class MimeHeaderField method nextElement.

@Override
public String nextElement() {
    MessageBytes current = next;
    findNext();
    return current.toString();
}
Also used : MessageBytes(org.apache.tomcat.util.buf.MessageBytes)

Example 10 with MessageBytes

use of org.apache.tomcat.util.buf.MessageBytes in project tomcat by apache.

the class MimeHeaderField method findNext.

private void findNext() {
    next = null;
    for (; pos < size; pos++) {
        MessageBytes n1 = headers.getName(pos);
        if (n1.equalsIgnoreCase(name)) {
            next = headers.getValue(pos);
            break;
        }
    }
    pos++;
}
Also used : MessageBytes(org.apache.tomcat.util.buf.MessageBytes)

Aggregations

MessageBytes (org.apache.tomcat.util.buf.MessageBytes)32 ByteChunk (org.apache.tomcat.util.buf.ByteChunk)7 Context (org.apache.catalina.Context)6 MimeHeaders (org.apache.tomcat.util.http.MimeHeaders)6 Test (org.junit.Test)6 IOException (java.io.IOException)4 Host (org.apache.catalina.Host)4 LoggingBaseTest (org.apache.catalina.startup.LoggingBaseTest)4 Pattern (java.util.regex.Pattern)3 ServletException (javax.servlet.ServletException)3 Cookie (javax.servlet.http.Cookie)3 Wrapper (org.apache.catalina.Wrapper)3 StandardContext (org.apache.catalina.core.StandardContext)3 StandardHost (org.apache.catalina.core.StandardHost)3 CharChunk (org.apache.tomcat.util.buf.CharChunk)3 UnsupportedEncodingException (java.io.UnsupportedEncodingException)2 Principal (java.security.Principal)2 MappingData (org.apache.catalina.mapper.MappingData)2 InputStream (java.io.InputStream)1 InvocationTargetException (java.lang.reflect.InvocationTargetException)1