X-Git-Url: https://code.wpia.club/?p=gigi.git;a=blobdiff_plain;f=lib%2Fjetty%2Forg%2Feclipse%2Fjetty%2Fserver%2FRequest.java;fp=lib%2Fjetty%2Forg%2Feclipse%2Fjetty%2Fserver%2FRequest.java;h=77c80abc2930f0b8474d69a227b638ff9f8eb23e;hp=0000000000000000000000000000000000000000;hb=73ef54a38e3930a1a789cdc6b5fa23cdd4c9d086;hpb=515007c7c1351045420669d65b59c08fa46850f2 diff --git a/lib/jetty/org/eclipse/jetty/server/Request.java b/lib/jetty/org/eclipse/jetty/server/Request.java new file mode 100644 index 00000000..77c80abc --- /dev/null +++ b/lib/jetty/org/eclipse/jetty/server/Request.java @@ -0,0 +1,2265 @@ +// +// ======================================================================== +// Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd. +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// +// The Apache License v2.0 is available at +// http://www.opensource.org/licenses/apache2.0.php +// +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +// + +package org.eclipse.jetty.server; + +import java.io.BufferedReader; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.UnsupportedEncodingException; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.nio.charset.UnsupportedCharsetException; +import java.security.Principal; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Enumeration; +import java.util.EventListener; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import javax.servlet.AsyncContext; +import javax.servlet.AsyncListener; +import javax.servlet.DispatcherType; +import javax.servlet.MultipartConfigElement; +import javax.servlet.RequestDispatcher; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.servlet.ServletInputStream; +import javax.servlet.ServletRequest; +import javax.servlet.ServletRequestAttributeEvent; +import javax.servlet.ServletRequestAttributeListener; +import javax.servlet.ServletRequestEvent; +import javax.servlet.ServletRequestListener; +import javax.servlet.ServletResponse; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; +import javax.servlet.http.HttpUpgradeHandler; +import javax.servlet.http.Part; + +import org.eclipse.jetty.http.HttpCookie; +import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpHeader; +import org.eclipse.jetty.http.HttpMethod; +import org.eclipse.jetty.http.HttpStatus; +import org.eclipse.jetty.http.HttpURI; +import org.eclipse.jetty.http.HttpVersion; +import org.eclipse.jetty.http.MimeTypes; +import org.eclipse.jetty.server.handler.ContextHandler; +import org.eclipse.jetty.server.handler.ContextHandler.Context; +import org.eclipse.jetty.server.session.AbstractSession; +import org.eclipse.jetty.util.Attributes; +import org.eclipse.jetty.util.AttributesMap; +import org.eclipse.jetty.util.IO; +import org.eclipse.jetty.util.MultiException; +import org.eclipse.jetty.util.MultiMap; +import org.eclipse.jetty.util.MultiPartInputStreamParser; +import org.eclipse.jetty.util.StringUtil; +import org.eclipse.jetty.util.URIUtil; +import org.eclipse.jetty.util.UrlEncoded; +import org.eclipse.jetty.util.log.Log; +import org.eclipse.jetty.util.log.Logger; + +/* ------------------------------------------------------------ */ +/** + * Jetty Request. + *

+ * Implements {@link javax.servlet.http.HttpServletRequest} from the javax.servlet.http package. + *

+ *

+ * The standard interface of mostly getters, is extended with setters so that the request is mutable by the handlers that it is passed to. This allows the + * request object to be as lightweight as possible and not actually implement any significant behavior. For example + *

+ * + * A request instance is created for each connection accepted by the server and recycled for each HTTP request received via that connection. + * An effort is made to avoid reparsing headers and cookies that are likely to be the same for requests from the same connection. + * + *

+ * The form content that a request can process is limited to protect from Denial of Service attacks. The size in bytes is limited by + * {@link ContextHandler#getMaxFormContentSize()} or if there is no context then the "org.eclipse.jetty.server.Request.maxFormContentSize" {@link Server} + * attribute. The number of parameters keys is limited by {@link ContextHandler#getMaxFormKeys()} or if there is no context then the + * "org.eclipse.jetty.server.Request.maxFormKeys" {@link Server} attribute. + * + * + */ +public class Request implements HttpServletRequest +{ + public static final String __MULTIPART_CONFIG_ELEMENT = "org.eclipse.jetty.multipartConfig"; + public static final String __MULTIPART_INPUT_STREAM = "org.eclipse.jetty.multiPartInputStream"; + public static final String __MULTIPART_CONTEXT = "org.eclipse.jetty.multiPartContext"; + + private static final Logger LOG = Log.getLogger(Request.class); + private static final Collection __defaultLocale = Collections.singleton(Locale.getDefault()); + private static final int __NONE = 0, _STREAM = 1, __READER = 2; + + private final HttpChannel _channel; + private final HttpFields _fields=new HttpFields(); + private final List _requestAttributeListeners=new ArrayList<>(); + private final HttpInput _input; + + public static class MultiPartCleanerListener implements ServletRequestListener + { + @Override + public void requestDestroyed(ServletRequestEvent sre) + { + //Clean up any tmp files created by MultiPartInputStream + MultiPartInputStreamParser mpis = (MultiPartInputStreamParser)sre.getServletRequest().getAttribute(__MULTIPART_INPUT_STREAM); + if (mpis != null) + { + ContextHandler.Context context = (ContextHandler.Context)sre.getServletRequest().getAttribute(__MULTIPART_CONTEXT); + + //Only do the cleanup if we are exiting from the context in which a servlet parsed the multipart files + if (context == sre.getServletContext()) + { + try + { + mpis.deleteParts(); + } + catch (MultiException e) + { + sre.getServletContext().log("Errors deleting multipart tmp files", e); + } + } + } + } + + @Override + public void requestInitialized(ServletRequestEvent sre) + { + //nothing to do, multipart config set up by ServletHolder.handle() + } + + } + + + + private boolean _secure; + private boolean _asyncSupported = true; + private boolean _newContext; + private boolean _cookiesExtracted = false; + private boolean _handled = false; + private boolean _paramsExtracted; + private boolean _requestedSessionIdFromCookie = false; + private volatile Attributes _attributes; + private Authentication _authentication; + private String _characterEncoding; + private ContextHandler.Context _context; + private String _contextPath; + private CookieCutter _cookies; + private DispatcherType _dispatcherType; + private int _inputState = __NONE; + private HttpMethod _httpMethod; + private String _httpMethodString; + private MultiMap _queryParameters; + private MultiMap _contentParameters; + private MultiMap _parameters; + private String _pathInfo; + private int _port; + private HttpVersion _httpVersion = HttpVersion.HTTP_1_1; + private String _queryEncoding; + private String _queryString; + private BufferedReader _reader; + private String _readerEncoding; + private InetSocketAddress _remote; + private String _requestedSessionId; + private String _requestURI; + private Map _savedNewSessions; + private String _scheme = URIUtil.HTTP; + private UserIdentity.Scope _scope; + private String _serverName; + private String _servletPath; + private HttpSession _session; + private SessionManager _sessionManager; + private long _timeStamp; + private HttpURI _uri; + private MultiPartInputStreamParser _multiPartInputStream; //if the request is a multi-part mime + private AsyncContextState _async; + + /* ------------------------------------------------------------ */ + public Request(HttpChannel channel, HttpInput input) + { + _channel = channel; + _input = input; + } + + /* ------------------------------------------------------------ */ + public HttpFields getHttpFields() + { + return _fields; + } + + /* ------------------------------------------------------------ */ + public HttpInput getHttpInput() + { + return _input; + } + + /* ------------------------------------------------------------ */ + public void addEventListener(final EventListener listener) + { + if (listener instanceof ServletRequestAttributeListener) + _requestAttributeListeners.add((ServletRequestAttributeListener)listener); + if (listener instanceof AsyncListener) + throw new IllegalArgumentException(listener.getClass().toString()); + } + + public void extractParameters() + { + if (_paramsExtracted) + return; + + _paramsExtracted = true; + + // Extract query string parameters; these may be replaced by a forward() + // and may have already been extracted by mergeQueryParameters(). + if (_queryParameters == null) + _queryParameters = extractQueryParameters(); + + // Extract content parameters; these cannot be replaced by a forward() + // once extracted and may have already been extracted by getParts() or + // by a processing happening after a form-based authentication. + if (_contentParameters == null) + _contentParameters = extractContentParameters(); + + _parameters = restoreParameters(); + } + + private MultiMap extractQueryParameters() + { + MultiMap result = new MultiMap<>(); + if (_uri != null && _uri.hasQuery()) + { + if (_queryEncoding == null) + { + _uri.decodeQueryTo(result); + } + else + { + try + { + _uri.decodeQueryTo(result, _queryEncoding); + } + catch (UnsupportedEncodingException e) + { + if (LOG.isDebugEnabled()) + LOG.warn(e); + else + LOG.warn(e.toString()); + } + } + } + return result; + } + + private MultiMap extractContentParameters() + { + MultiMap result = new MultiMap<>(); + + String contentType = getContentType(); + if (contentType != null && !contentType.isEmpty()) + { + contentType = HttpFields.valueParameters(contentType, null); + int contentLength = getContentLength(); + if (contentLength != 0) + { + if (MimeTypes.Type.FORM_ENCODED.is(contentType) && _inputState == __NONE && + (HttpMethod.POST.is(getMethod()) || HttpMethod.PUT.is(getMethod()))) + { + extractFormParameters(result); + } + else if (contentType.startsWith("multipart/form-data") && + getAttribute(__MULTIPART_CONFIG_ELEMENT) != null && + _multiPartInputStream == null) + { + extractMultipartParameters(result); + } + } + } + + return result; + } + + public void extractFormParameters(MultiMap params) + { + try + { + int maxFormContentSize = -1; + int maxFormKeys = -1; + + if (_context != null) + { + maxFormContentSize = _context.getContextHandler().getMaxFormContentSize(); + maxFormKeys = _context.getContextHandler().getMaxFormKeys(); + } + + if (maxFormContentSize < 0) + { + Object obj = _channel.getServer().getAttribute("org.eclipse.jetty.server.Request.maxFormContentSize"); + if (obj == null) + maxFormContentSize = 200000; + else if (obj instanceof Number) + { + Number size = (Number)obj; + maxFormContentSize = size.intValue(); + } + else if (obj instanceof String) + { + maxFormContentSize = Integer.valueOf((String)obj); + } + } + + if (maxFormKeys < 0) + { + Object obj = _channel.getServer().getAttribute("org.eclipse.jetty.server.Request.maxFormKeys"); + if (obj == null) + maxFormKeys = 1000; + else if (obj instanceof Number) + { + Number keys = (Number)obj; + maxFormKeys = keys.intValue(); + } + else if (obj instanceof String) + { + maxFormKeys = Integer.valueOf((String)obj); + } + } + + int contentLength = getContentLength(); + if (contentLength > maxFormContentSize && maxFormContentSize > 0) + { + throw new IllegalStateException("Form too large: " + contentLength + " > " + maxFormContentSize); + } + InputStream in = getInputStream(); + if (_input.isAsync()) + throw new IllegalStateException("Cannot extract parameters with async IO"); + + UrlEncoded.decodeTo(in,params,getCharacterEncoding(),contentLength<0?maxFormContentSize:-1,maxFormKeys); + } + catch (IOException e) + { + if (LOG.isDebugEnabled()) + LOG.warn(e); + else + LOG.warn(e.toString()); + } + } + + private void extractMultipartParameters(MultiMap result) + { + try + { + getParts(result); + } + catch (IOException | ServletException e) + { + if (LOG.isDebugEnabled()) + LOG.warn(e); + else + LOG.warn(e.toString()); + } + } + + /* ------------------------------------------------------------ */ + @Override + public AsyncContext getAsyncContext() + { + HttpChannelState state = getHttpChannelState(); + if (_async==null || state.isInitial() && !state.isAsync()) + throw new IllegalStateException(state.getStatusString()); + + return _async; + } + + /* ------------------------------------------------------------ */ + public HttpChannelState getHttpChannelState() + { + return _channel.getState(); + } + + /* ------------------------------------------------------------ */ + /** + * Get Request Attribute. + *

Also supports jetty specific attributes to gain access to Jetty APIs: + *

+ *
org.eclipse.jetty.server.Server
The Jetty Server instance
+ *
org.eclipse.jetty.server.HttpChannel
The HttpChannel for this request
+ *
org.eclipse.jetty.server.HttpConnection
The HttpConnection or null if another transport is used
+ *
+ * While these attributes may look like security problems, they are exposing nothing that is not already + * available via reflection from a Request instance. + *

+ * @see javax.servlet.ServletRequest#getAttribute(java.lang.String) + */ + @Override + public Object getAttribute(String name) + { + if (name.startsWith("org.eclipse.jetty")) + { + if ("org.eclipse.jetty.server.Server".equals(name)) + return _channel.getServer(); + if ("org.eclipse.jetty.server.HttpChannel".equals(name)) + return _channel; + if ("org.eclipse.jetty.server.HttpConnection".equals(name) && + _channel.getHttpTransport() instanceof HttpConnection) + return _channel.getHttpTransport(); + } + return (_attributes == null)?null:_attributes.getAttribute(name); + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.ServletRequest#getAttributeNames() + */ + @Override + public Enumeration getAttributeNames() + { + if (_attributes == null) + return Collections.enumeration(Collections.emptyList()); + + return AttributesMap.getAttributeNamesCopy(_attributes); + } + + /* ------------------------------------------------------------ */ + /* + */ + public Attributes getAttributes() + { + if (_attributes == null) + _attributes = new AttributesMap(); + return _attributes; + } + + /* ------------------------------------------------------------ */ + /** + * Get the authentication. + * + * @return the authentication + */ + public Authentication getAuthentication() + { + return _authentication; + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.http.HttpServletRequest#getAuthType() + */ + @Override + public String getAuthType() + { + if (_authentication instanceof Authentication.Deferred) + setAuthentication(((Authentication.Deferred)_authentication).authenticate(this)); + + if (_authentication instanceof Authentication.User) + return ((Authentication.User)_authentication).getAuthMethod(); + return null; + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.ServletRequest#getCharacterEncoding() + */ + @Override + public String getCharacterEncoding() + { + return _characterEncoding; + } + + /* ------------------------------------------------------------ */ + /** + * @return Returns the connection. + */ + public HttpChannel getHttpChannel() + { + return _channel; + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.ServletRequest#getContentLength() + */ + @Override + public int getContentLength() + { + return (int)_fields.getLongField(HttpHeader.CONTENT_LENGTH.toString()); + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.ServletRequest.getContentLengthLong() + */ + @Override + public long getContentLengthLong() + { + return _fields.getLongField(HttpHeader.CONTENT_LENGTH.toString()); + } + + /* ------------------------------------------------------------ */ + public long getContentRead() + { + return _input.getContentRead(); + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.ServletRequest#getContentType() + */ + @Override + public String getContentType() + { + return _fields.getStringField(HttpHeader.CONTENT_TYPE); + } + + /* ------------------------------------------------------------ */ + /** + * @return The current {@link Context context} used for this request, or null if {@link #setContext} has not yet been called. + */ + public Context getContext() + { + return _context; + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.http.HttpServletRequest#getContextPath() + */ + @Override + public String getContextPath() + { + return _contextPath; + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.http.HttpServletRequest#getCookies() + */ + @Override + public Cookie[] getCookies() + { + if (_cookiesExtracted) + { + if (_cookies == null || _cookies.getCookies().length == 0) + return null; + + return _cookies.getCookies(); + } + + _cookiesExtracted = true; + + Enumeration enm = _fields.getValues(HttpHeader.COOKIE.toString()); + + // Handle no cookies + if (enm != null) + { + if (_cookies == null) + _cookies = new CookieCutter(); + + while (enm.hasMoreElements()) + { + String c = (String)enm.nextElement(); + _cookies.addCookieField(c); + } + } + + //Javadoc for Request.getCookies() stipulates null for no cookies + if (_cookies == null || _cookies.getCookies().length == 0) + return null; + + return _cookies.getCookies(); + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.http.HttpServletRequest#getDateHeader(java.lang.String) + */ + @Override + public long getDateHeader(String name) + { + return _fields.getDateField(name); + } + + /* ------------------------------------------------------------ */ + @Override + public DispatcherType getDispatcherType() + { + return _dispatcherType; + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.http.HttpServletRequest#getHeader(java.lang.String) + */ + @Override + public String getHeader(String name) + { + return _fields.getStringField(name); + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.http.HttpServletRequest#getHeaderNames() + */ + @Override + public Enumeration getHeaderNames() + { + return _fields.getFieldNames(); + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.http.HttpServletRequest#getHeaders(java.lang.String) + */ + @Override + public Enumeration getHeaders(String name) + { + Enumeration e = _fields.getValues(name); + if (e == null) + return Collections.enumeration(Collections.emptyList()); + return e; + } + + /* ------------------------------------------------------------ */ + /** + * @return Returns the inputState. + */ + public int getInputState() + { + return _inputState; + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.ServletRequest#getInputStream() + */ + @Override + public ServletInputStream getInputStream() throws IOException + { + if (_inputState != __NONE && _inputState != _STREAM) + throw new IllegalStateException("READER"); + _inputState = _STREAM; + + if (_channel.isExpecting100Continue()) + _channel.continue100(_input.available()); + + return _input; + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.http.HttpServletRequest#getIntHeader(java.lang.String) + */ + @Override + public int getIntHeader(String name) + { + return (int)_fields.getLongField(name); + } + + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.ServletRequest#getLocale() + */ + @Override + public Locale getLocale() + { + Enumeration enm = _fields.getValues(HttpHeader.ACCEPT_LANGUAGE.toString(),HttpFields.__separators); + + // handle no locale + if (enm == null || !enm.hasMoreElements()) + return Locale.getDefault(); + + // sort the list in quality order + List acceptLanguage = HttpFields.qualityList(enm); + if (acceptLanguage.size() == 0) + return Locale.getDefault(); + + int size = acceptLanguage.size(); + + if (size > 0) + { + String language = (String)acceptLanguage.get(0); + language = HttpFields.valueParameters(language,null); + String country = ""; + int dash = language.indexOf('-'); + if (dash > -1) + { + country = language.substring(dash + 1).trim(); + language = language.substring(0,dash).trim(); + } + return new Locale(language,country); + } + + return Locale.getDefault(); + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.ServletRequest#getLocales() + */ + @Override + public Enumeration getLocales() + { + + Enumeration enm = _fields.getValues(HttpHeader.ACCEPT_LANGUAGE.toString(),HttpFields.__separators); + + // handle no locale + if (enm == null || !enm.hasMoreElements()) + return Collections.enumeration(__defaultLocale); + + // sort the list in quality order + List acceptLanguage = HttpFields.qualityList(enm); + + if (acceptLanguage.size() == 0) + return Collections.enumeration(__defaultLocale); + + List langs = new ArrayList<>(); + + // convert to locals + for (String language : acceptLanguage) + { + language = HttpFields.valueParameters(language, null); + String country = ""; + int dash = language.indexOf('-'); + if (dash > -1) + { + country = language.substring(dash + 1).trim(); + language = language.substring(0, dash).trim(); + } + langs.add(new Locale(language, country)); + } + + if (langs.size() == 0) + return Collections.enumeration(__defaultLocale); + + return Collections.enumeration(langs); + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.ServletRequest#getLocalAddr() + */ + @Override + public String getLocalAddr() + { + InetSocketAddress local=_channel.getLocalAddress(); + if (local==null) + return ""; + InetAddress address = local.getAddress(); + if (address==null) + return local.getHostString(); + return address.getHostAddress(); + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.ServletRequest#getLocalName() + */ + @Override + public String getLocalName() + { + InetSocketAddress local=_channel.getLocalAddress(); + return local.getHostString(); + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.ServletRequest#getLocalPort() + */ + @Override + public int getLocalPort() + { + InetSocketAddress local=_channel.getLocalAddress(); + return local.getPort(); + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.http.HttpServletRequest#getMethod() + */ + @Override + public String getMethod() + { + return _httpMethodString; + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.ServletRequest#getParameter(java.lang.String) + */ + @Override + public String getParameter(String name) + { + if (!_paramsExtracted) + extractParameters(); + if (_parameters == null) + _parameters = restoreParameters(); + return _parameters.getValue(name,0); + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.ServletRequest#getParameterMap() + */ + @Override + public Map getParameterMap() + { + if (!_paramsExtracted) + extractParameters(); + if (_parameters == null) + _parameters = restoreParameters(); + return Collections.unmodifiableMap(_parameters.toStringArrayMap()); + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.ServletRequest#getParameterNames() + */ + @Override + public Enumeration getParameterNames() + { + if (!_paramsExtracted) + extractParameters(); + if (_parameters == null) + _parameters = restoreParameters(); + return Collections.enumeration(_parameters.keySet()); + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.ServletRequest#getParameterValues(java.lang.String) + */ + @Override + public String[] getParameterValues(String name) + { + if (!_paramsExtracted) + extractParameters(); + if (_parameters == null) + _parameters = restoreParameters(); + List vals = _parameters.getValues(name); + if (vals == null) + return null; + return vals.toArray(new String[vals.size()]); + } + + private MultiMap restoreParameters() + { + MultiMap result = new MultiMap<>(); + if (_queryParameters == null) + _queryParameters = extractQueryParameters(); + result.addAllValues(_queryParameters); + result.addAllValues(_contentParameters); + return result; + } + + public MultiMap getQueryParameters() + { + return _queryParameters; + } + + public void setQueryParameters(MultiMap queryParameters) + { + _queryParameters = queryParameters; + } + + public void setContentParameters(MultiMap contentParameters) + { + _contentParameters = contentParameters; + } + + public void resetParameters() + { + _parameters = null; + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.http.HttpServletRequest#getPathInfo() + */ + @Override + public String getPathInfo() + { + return _pathInfo; + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.http.HttpServletRequest#getPathTranslated() + */ + @Override + public String getPathTranslated() + { + if (_pathInfo == null || _context == null) + return null; + return _context.getRealPath(_pathInfo); + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.ServletRequest#getProtocol() + */ + @Override + public String getProtocol() + { + return _httpVersion.toString(); + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.ServletRequest#getProtocol() + */ + public HttpVersion getHttpVersion() + { + return _httpVersion; + } + + /* ------------------------------------------------------------ */ + public String getQueryEncoding() + { + return _queryEncoding; + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.http.HttpServletRequest#getQueryString() + */ + @Override + public String getQueryString() + { + if (_queryString == null && _uri != null) + { + if (_queryEncoding == null) + _queryString = _uri.getQuery(); + else + _queryString = _uri.getQuery(_queryEncoding); + } + return _queryString; + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.ServletRequest#getReader() + */ + @Override + public BufferedReader getReader() throws IOException + { + if (_inputState != __NONE && _inputState != __READER) + throw new IllegalStateException("STREAMED"); + + if (_inputState == __READER) + return _reader; + + String encoding = getCharacterEncoding(); + if (encoding == null) + encoding = StringUtil.__ISO_8859_1; + + if (_reader == null || !encoding.equalsIgnoreCase(_readerEncoding)) + { + final ServletInputStream in = getInputStream(); + _readerEncoding = encoding; + _reader = new BufferedReader(new InputStreamReader(in,encoding)) + { + @Override + public void close() throws IOException + { + in.close(); + } + }; + } + _inputState = __READER; + return _reader; + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.ServletRequest#getRealPath(java.lang.String) + */ + @Override + public String getRealPath(String path) + { + if (_context == null) + return null; + return _context.getRealPath(path); + } + + /* ------------------------------------------------------------ */ + /** + * Access the underlying Remote {@link InetSocketAddress} for this request. + * + * @return the remote {@link InetSocketAddress} for this request, or null if the request has no remote (see {@link ServletRequest#getRemoteAddr()} for + * conditions that result in no remote address) + */ + public InetSocketAddress getRemoteInetSocketAddress() + { + InetSocketAddress remote = _remote; + if (remote == null) + remote = _channel.getRemoteAddress(); + + return remote; + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.ServletRequest#getRemoteAddr() + */ + @Override + public String getRemoteAddr() + { + InetSocketAddress remote=_remote; + if (remote==null) + remote=_channel.getRemoteAddress(); + + if (remote==null) + return ""; + + InetAddress address = remote.getAddress(); + if (address==null) + return remote.getHostString(); + + return address.getHostAddress(); + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.ServletRequest#getRemoteHost() + */ + @Override + public String getRemoteHost() + { + InetSocketAddress remote=_remote; + if (remote==null) + remote=_channel.getRemoteAddress(); + return remote==null?"":remote.getHostString(); + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.ServletRequest#getRemotePort() + */ + @Override + public int getRemotePort() + { + InetSocketAddress remote=_remote; + if (remote==null) + remote=_channel.getRemoteAddress(); + return remote==null?0:remote.getPort(); + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.http.HttpServletRequest#getRemoteUser() + */ + @Override + public String getRemoteUser() + { + Principal p = getUserPrincipal(); + if (p == null) + return null; + return p.getName(); + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.ServletRequest#getRequestDispatcher(java.lang.String) + */ + @Override + public RequestDispatcher getRequestDispatcher(String path) + { + if (path == null || _context == null) + return null; + + // handle relative path + if (!path.startsWith("/")) + { + String relTo = URIUtil.addPaths(_servletPath,_pathInfo); + int slash = relTo.lastIndexOf("/"); + if (slash > 1) + relTo = relTo.substring(0,slash + 1); + else + relTo = "/"; + path = URIUtil.addPaths(relTo,path); + } + + return _context.getRequestDispatcher(path); + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.http.HttpServletRequest#getRequestedSessionId() + */ + @Override + public String getRequestedSessionId() + { + return _requestedSessionId; + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.http.HttpServletRequest#getRequestURI() + */ + @Override + public String getRequestURI() + { + if (_requestURI == null && _uri != null) + _requestURI = _uri.getPathAndParam(); + return _requestURI; + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.http.HttpServletRequest#getRequestURL() + */ + @Override + public StringBuffer getRequestURL() + { + final StringBuffer url = new StringBuffer(128); + URIUtil.appendSchemeHostPort(url,getScheme(),getServerName(),getServerPort()); + url.append(getRequestURI()); + return url; + } + + /* ------------------------------------------------------------ */ + public Response getResponse() + { + return _channel.getResponse(); + } + + /* ------------------------------------------------------------ */ + /** + * Reconstructs the URL the client used to make the request. The returned URL contains a protocol, server name, port number, and, but it does not include a + * path. + *

+ * Because this method returns a StringBuffer, not a string, you can modify the URL easily, for example, to append path and query parameters. + * + * This method is useful for creating redirect messages and for reporting errors. + * + * @return "scheme://host:port" + */ + public StringBuilder getRootURL() + { + StringBuilder url = new StringBuilder(128); + URIUtil.appendSchemeHostPort(url,getScheme(),getServerName(),getServerPort()); + return url; + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.ServletRequest#getScheme() + */ + @Override + public String getScheme() + { + return _scheme; + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.ServletRequest#getServerName() + */ + @Override + public String getServerName() + { + // Return already determined host + if (_serverName != null) + return _serverName; + + if (_uri == null) + throw new IllegalStateException("No uri"); + + // Return host from absolute URI + _serverName = _uri.getHost(); + if (_serverName != null) + { + _port = _uri.getPort(); + return _serverName; + } + + // Return host from header field + String hostPort = _fields.getStringField(HttpHeader.HOST); + + _port=0; + if (hostPort != null) + { + int len=hostPort.length(); + loop: for (int i = len; i-- > 0;) + { + char c2 = (char)(0xff & hostPort.charAt(i)); + switch (c2) + { + case ']': + break loop; + + case ':': + try + { + len=i; + _port = StringUtil.toInt(hostPort.substring(i+1)); + } + catch (NumberFormatException e) + { + LOG.warn(e); + _serverName=hostPort; + _port=0; + return _serverName; + } + break loop; + } + } + if (hostPort.charAt(0)=='[') + { + if (hostPort.charAt(len-1)!=']') + { + LOG.warn("Bad IPv6 "+hostPort); + _serverName=hostPort; + _port=0; + return _serverName; + } + _serverName = hostPort.substring(1,len-1); + } + else if (len==hostPort.length()) + _serverName=hostPort; + else + _serverName = hostPort.substring(0,len); + + return _serverName; + } + + // Return host from connection + if (_channel != null) + { + _serverName = getLocalName(); + _port = getLocalPort(); + if (_serverName != null && !StringUtil.ALL_INTERFACES.equals(_serverName)) + return _serverName; + } + + // Return the local host + try + { + _serverName = InetAddress.getLocalHost().getHostAddress(); + } + catch (java.net.UnknownHostException e) + { + LOG.ignore(e); + } + return _serverName; + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.ServletRequest#getServerPort() + */ + @Override + public int getServerPort() + { + if (_port <= 0) + { + if (_serverName == null) + getServerName(); + + if (_port <= 0) + { + if (_serverName != null && _uri != null) + _port = _uri.getPort(); + else + { + InetSocketAddress local = _channel.getLocalAddress(); + _port = local == null?0:local.getPort(); + } + } + } + + if (_port <= 0) + { + if (getScheme().equalsIgnoreCase(URIUtil.HTTPS)) + return 443; + return 80; + } + return _port; + } + + /* ------------------------------------------------------------ */ + @Override + public ServletContext getServletContext() + { + return _context; + } + + /* ------------------------------------------------------------ */ + /* + */ + public String getServletName() + { + if (_scope != null) + return _scope.getName(); + return null; + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.http.HttpServletRequest#getServletPath() + */ + @Override + public String getServletPath() + { + if (_servletPath == null) + _servletPath = ""; + return _servletPath; + } + + /* ------------------------------------------------------------ */ + public ServletResponse getServletResponse() + { + return _channel.getResponse(); + } + + /* ------------------------------------------------------------ */ + /* + * Add @override when 3.1 api is available + */ + public String changeSessionId() + { + HttpSession session = getSession(false); + if (session == null) + throw new IllegalStateException("No session"); + + if (session instanceof AbstractSession) + { + AbstractSession abstractSession = ((AbstractSession)session); + abstractSession.renewId(this); + if (getRemoteUser() != null) + abstractSession.setAttribute(AbstractSession.SESSION_KNOWN_ONLY_TO_AUTHENTICATED, Boolean.TRUE); + if (abstractSession.isIdChanged()) + _channel.getResponse().addCookie(_sessionManager.getSessionCookie(abstractSession, getContextPath(), isSecure())); + } + + return session.getId(); + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.http.HttpServletRequest#getSession() + */ + @Override + public HttpSession getSession() + { + return getSession(true); + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.http.HttpServletRequest#getSession(boolean) + */ + @Override + public HttpSession getSession(boolean create) + { + if (_session != null) + { + if (_sessionManager != null && !_sessionManager.isValid(_session)) + _session = null; + else + return _session; + } + + if (!create) + return null; + + if (getResponse().isCommitted()) + throw new IllegalStateException("Response is committed"); + + if (_sessionManager == null) + throw new IllegalStateException("No SessionManager"); + + _session = _sessionManager.newHttpSession(this); + HttpCookie cookie = _sessionManager.getSessionCookie(_session,getContextPath(),isSecure()); + if (cookie != null) + _channel.getResponse().addCookie(cookie); + + return _session; + } + + /* ------------------------------------------------------------ */ + /** + * @return Returns the sessionManager. + */ + public SessionManager getSessionManager() + { + return _sessionManager; + } + + /* ------------------------------------------------------------ */ + /** + * Get Request TimeStamp + * + * @return The time that the request was received. + */ + public long getTimeStamp() + { + return _timeStamp; + } + + /* ------------------------------------------------------------ */ + /** + * @return Returns the uri. + */ + public HttpURI getUri() + { + return _uri; + } + + /* ------------------------------------------------------------ */ + public UserIdentity getUserIdentity() + { + if (_authentication instanceof Authentication.Deferred) + setAuthentication(((Authentication.Deferred)_authentication).authenticate(this)); + + if (_authentication instanceof Authentication.User) + return ((Authentication.User)_authentication).getUserIdentity(); + return null; + } + + /* ------------------------------------------------------------ */ + /** + * @return The resolved user Identity, which may be null if the {@link Authentication} is not {@link Authentication.User} (eg. + * {@link Authentication.Deferred}). + */ + public UserIdentity getResolvedUserIdentity() + { + if (_authentication instanceof Authentication.User) + return ((Authentication.User)_authentication).getUserIdentity(); + return null; + } + + /* ------------------------------------------------------------ */ + public UserIdentity.Scope getUserIdentityScope() + { + return _scope; + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.http.HttpServletRequest#getUserPrincipal() + */ + @Override + public Principal getUserPrincipal() + { + if (_authentication instanceof Authentication.Deferred) + setAuthentication(((Authentication.Deferred)_authentication).authenticate(this)); + + if (_authentication instanceof Authentication.User) + { + UserIdentity user = ((Authentication.User)_authentication).getUserIdentity(); + return user.getUserPrincipal(); + } + + return null; + } + + + /* ------------------------------------------------------------ */ + public boolean isHandled() + { + return _handled; + } + + @Override + public boolean isAsyncStarted() + { + return getHttpChannelState().isAsyncStarted(); + } + + + /* ------------------------------------------------------------ */ + @Override + public boolean isAsyncSupported() + { + return _asyncSupported; + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.http.HttpServletRequest#isRequestedSessionIdFromCookie() + */ + @Override + public boolean isRequestedSessionIdFromCookie() + { + return _requestedSessionId != null && _requestedSessionIdFromCookie; + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.http.HttpServletRequest#isRequestedSessionIdFromUrl() + */ + @Override + public boolean isRequestedSessionIdFromUrl() + { + return _requestedSessionId != null && !_requestedSessionIdFromCookie; + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.http.HttpServletRequest#isRequestedSessionIdFromURL() + */ + @Override + public boolean isRequestedSessionIdFromURL() + { + return _requestedSessionId != null && !_requestedSessionIdFromCookie; + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.http.HttpServletRequest#isRequestedSessionIdValid() + */ + @Override + public boolean isRequestedSessionIdValid() + { + if (_requestedSessionId == null) + return false; + + HttpSession session = getSession(false); + return (session != null && _sessionManager.getSessionIdManager().getClusterId(_requestedSessionId).equals(_sessionManager.getClusterId(session))); + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.ServletRequest#isSecure() + */ + @Override + public boolean isSecure() + { + return _secure; + } + + /* ------------------------------------------------------------ */ + public void setSecure(boolean secure) + { + _secure=secure; + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.http.HttpServletRequest#isUserInRole(java.lang.String) + */ + @Override + public boolean isUserInRole(String role) + { + if (_authentication instanceof Authentication.Deferred) + setAuthentication(((Authentication.Deferred)_authentication).authenticate(this)); + + if (_authentication instanceof Authentication.User) + return ((Authentication.User)_authentication).isUserInRole(_scope,role); + return false; + } + + /* ------------------------------------------------------------ */ + public HttpSession recoverNewSession(Object key) + { + if (_savedNewSessions == null) + return null; + return _savedNewSessions.get(key); + } + + /* ------------------------------------------------------------ */ + protected void recycle() + { + if (_context != null) + throw new IllegalStateException("Request in context!"); + + if (_inputState == __READER) + { + try + { + int r = _reader.read(); + while (r != -1) + r = _reader.read(); + } + catch (Exception e) + { + LOG.ignore(e); + _reader = null; + } + } + + _dispatcherType=null; + setAuthentication(Authentication.NOT_CHECKED); + getHttpChannelState().recycle(); + if (_async!=null) + _async.reset(); + _async=null; + _asyncSupported = true; + _handled = false; + if (_attributes != null) + _attributes.clearAttributes(); + _characterEncoding = null; + _contextPath = null; + if (_cookies != null) + _cookies.reset(); + _cookiesExtracted = false; + _context = null; + _newContext=false; + _serverName = null; + _httpMethod=null; + _httpMethodString = null; + _pathInfo = null; + _port = 0; + _httpVersion = HttpVersion.HTTP_1_1; + _queryEncoding = null; + _queryString = null; + _requestedSessionId = null; + _requestedSessionIdFromCookie = false; + _secure=false; + _session = null; + _sessionManager = null; + _requestURI = null; + _scope = null; + _scheme = URIUtil.HTTP; + _servletPath = null; + _timeStamp = 0; + _uri = null; + _queryParameters = null; + _contentParameters = null; + _parameters = null; + _paramsExtracted = false; + _inputState = __NONE; + + if (_savedNewSessions != null) + _savedNewSessions.clear(); + _savedNewSessions=null; + _multiPartInputStream = null; + _remote=null; + _fields.clear(); + _input.recycle(); + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.ServletRequest#removeAttribute(java.lang.String) + */ + @Override + public void removeAttribute(String name) + { + Object old_value = _attributes == null?null:_attributes.getAttribute(name); + + if (_attributes != null) + _attributes.removeAttribute(name); + + if (old_value != null && !_requestAttributeListeners.isEmpty()) + { + final ServletRequestAttributeEvent event = new ServletRequestAttributeEvent(_context,this,name,old_value); + for (ServletRequestAttributeListener listener : _requestAttributeListeners) + listener.attributeRemoved(event); + } + } + + /* ------------------------------------------------------------ */ + public void removeEventListener(final EventListener listener) + { + _requestAttributeListeners.remove(listener); + } + + /* ------------------------------------------------------------ */ + public void saveNewSession(Object key, HttpSession session) + { + if (_savedNewSessions == null) + _savedNewSessions = new HashMap<>(); + _savedNewSessions.put(key,session); + } + + /* ------------------------------------------------------------ */ + public void setAsyncSupported(boolean supported) + { + _asyncSupported = supported; + } + + /* ------------------------------------------------------------ */ + /* + * Set a request attribute. if the attribute name is "org.eclipse.jetty.server.server.Request.queryEncoding" then the value is also passed in a call to + * {@link #setQueryEncoding}. + * + * @see javax.servlet.ServletRequest#setAttribute(java.lang.String, java.lang.Object) + */ + @Override + public void setAttribute(String name, Object value) + { + Object old_value = _attributes == null?null:_attributes.getAttribute(name); + + if ("org.eclipse.jetty.server.Request.queryEncoding".equals(name)) + setQueryEncoding(value == null?null:value.toString()); + else if ("org.eclipse.jetty.server.sendContent".equals(name)) + LOG.warn("Deprecated: org.eclipse.jetty.server.sendContent"); + + if (_attributes == null) + _attributes = new AttributesMap(); + _attributes.setAttribute(name,value); + + if (!_requestAttributeListeners.isEmpty()) + { + final ServletRequestAttributeEvent event = new ServletRequestAttributeEvent(_context,this,name,old_value == null?value:old_value); + for (ServletRequestAttributeListener l : _requestAttributeListeners) + { + if (old_value == null) + l.attributeAdded(event); + else if (value == null) + l.attributeRemoved(event); + else + l.attributeReplaced(event); + } + } + } + + /* ------------------------------------------------------------ */ + /* + */ + public void setAttributes(Attributes attributes) + { + _attributes = attributes; + } + + /* ------------------------------------------------------------ */ + + /* ------------------------------------------------------------ */ + /** + * Set the authentication. + * + * @param authentication + * the authentication to set + */ + public void setAuthentication(Authentication authentication) + { + _authentication = authentication; + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.ServletRequest#setCharacterEncoding(java.lang.String) + */ + @Override + public void setCharacterEncoding(String encoding) throws UnsupportedEncodingException + { + if (_inputState != __NONE) + return; + + _characterEncoding = encoding; + + // check encoding is supported + if (!StringUtil.isUTF8(encoding)) + { + try + { + Charset.forName(encoding); + } + catch (UnsupportedCharsetException e) + { + throw new UnsupportedEncodingException(e.getMessage()); + } + } + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.ServletRequest#setCharacterEncoding(java.lang.String) + */ + public void setCharacterEncodingUnchecked(String encoding) + { + _characterEncoding = encoding; + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.ServletRequest#getContentType() + */ + public void setContentType(String contentType) + { + _fields.put(HttpHeader.CONTENT_TYPE,contentType); + + } + + /* ------------------------------------------------------------ */ + /** + * Set request context + * + * @param context + * context object + */ + public void setContext(Context context) + { + _newContext = _context != context; + _context = context; + } + + /* ------------------------------------------------------------ */ + /** + * @return True if this is the first call of {@link #takeNewContext()} since the last + * {@link #setContext(org.eclipse.jetty.server.handler.ContextHandler.Context)} call. + */ + public boolean takeNewContext() + { + boolean nc = _newContext; + _newContext = false; + return nc; + } + + /* ------------------------------------------------------------ */ + /** + * Sets the "context path" for this request + * + * @see HttpServletRequest#getContextPath() + */ + public void setContextPath(String contextPath) + { + _contextPath = contextPath; + } + + /* ------------------------------------------------------------ */ + /** + * @param cookies + * The cookies to set. + */ + public void setCookies(Cookie[] cookies) + { + if (_cookies == null) + _cookies = new CookieCutter(); + _cookies.setCookies(cookies); + } + + /* ------------------------------------------------------------ */ + public void setDispatcherType(DispatcherType type) + { + _dispatcherType = type; + } + + /* ------------------------------------------------------------ */ + public void setHandled(boolean h) + { + _handled = h; + Response r=getResponse(); + if (_handled && r.getStatus()==0) + r.setStatus(200); + } + + /* ------------------------------------------------------------ */ + /** + * @param method + * The method to set. + */ + public void setMethod(HttpMethod httpMethod, String method) + { + _httpMethod=httpMethod; + _httpMethodString = method; + } + + /* ------------------------------------------------------------ */ + public boolean isHead() + { + return HttpMethod.HEAD==_httpMethod; + } + + /* ------------------------------------------------------------ */ + /** + * @param pathInfo + * The pathInfo to set. + */ + public void setPathInfo(String pathInfo) + { + _pathInfo = pathInfo; + } + + /* ------------------------------------------------------------ */ + /** + * @param version + * The protocol to set. + */ + public void setHttpVersion(HttpVersion version) + { + _httpVersion = version; + } + + /* ------------------------------------------------------------ */ + /** + * Set the character encoding used for the query string. This call will effect the return of getQueryString and getParamaters. It must be called before any + * getParameter methods. + * + * The request attribute "org.eclipse.jetty.server.server.Request.queryEncoding" may be set as an alternate method of calling setQueryEncoding. + * + * @param queryEncoding + */ + public void setQueryEncoding(String queryEncoding) + { + _queryEncoding = queryEncoding; + _queryString = null; + } + + /* ------------------------------------------------------------ */ + /** + * @param queryString + * The queryString to set. + */ + public void setQueryString(String queryString) + { + _queryString = queryString; + _queryEncoding = null; //assume utf-8 + } + + /* ------------------------------------------------------------ */ + /** + * @param addr + * The address to set. + */ + public void setRemoteAddr(InetSocketAddress addr) + { + _remote = addr; + } + + /* ------------------------------------------------------------ */ + /** + * @param requestedSessionId + * The requestedSessionId to set. + */ + public void setRequestedSessionId(String requestedSessionId) + { + _requestedSessionId = requestedSessionId; + } + + /* ------------------------------------------------------------ */ + /** + * @param requestedSessionIdCookie + * The requestedSessionIdCookie to set. + */ + public void setRequestedSessionIdFromCookie(boolean requestedSessionIdCookie) + { + _requestedSessionIdFromCookie = requestedSessionIdCookie; + } + + /* ------------------------------------------------------------ */ + /** + * @param requestURI + * The requestURI to set. + */ + public void setRequestURI(String requestURI) + { + _requestURI = requestURI; + } + + /* ------------------------------------------------------------ */ + /** + * @param scheme + * The scheme to set. + */ + public void setScheme(String scheme) + { + _scheme = scheme; + } + + /* ------------------------------------------------------------ */ + /** + * @param host + * The host to set. + */ + public void setServerName(String host) + { + _serverName = host; + } + + /* ------------------------------------------------------------ */ + /** + * @param port + * The port to set. + */ + public void setServerPort(int port) + { + _port = port; + } + + /* ------------------------------------------------------------ */ + /** + * @param servletPath + * The servletPath to set. + */ + public void setServletPath(String servletPath) + { + _servletPath = servletPath; + } + + /* ------------------------------------------------------------ */ + /** + * @param session + * The session to set. + */ + public void setSession(HttpSession session) + { + _session = session; + } + + /* ------------------------------------------------------------ */ + /** + * @param sessionManager + * The sessionManager to set. + */ + public void setSessionManager(SessionManager sessionManager) + { + _sessionManager = sessionManager; + } + + /* ------------------------------------------------------------ */ + public void setTimeStamp(long ts) + { + _timeStamp = ts; + } + + /* ------------------------------------------------------------ */ + /** + * @param uri + * The uri to set. + */ + public void setUri(HttpURI uri) + { + _uri = uri; + } + + /* ------------------------------------------------------------ */ + public void setUserIdentityScope(UserIdentity.Scope scope) + { + _scope = scope; + } + + /* ------------------------------------------------------------ */ + @Override + public AsyncContext startAsync() throws IllegalStateException + { + if (!_asyncSupported) + throw new IllegalStateException("!asyncSupported"); + HttpChannelState state = getHttpChannelState(); + if (_async==null) + _async=new AsyncContextState(state); + AsyncContextEvent event = new AsyncContextEvent(_context,_async,state,this,this,getResponse()); + state.startAsync(event); + return _async; + } + + /* ------------------------------------------------------------ */ + @Override + public AsyncContext startAsync(ServletRequest servletRequest, ServletResponse servletResponse) throws IllegalStateException + { + if (!_asyncSupported) + throw new IllegalStateException("!asyncSupported"); + HttpChannelState state = getHttpChannelState(); + if (_async==null) + _async=new AsyncContextState(state); + AsyncContextEvent event = new AsyncContextEvent(_context,_async,state,this,servletRequest,servletResponse); + event.setDispatchContext(getServletContext()); + event.setDispatchPath(URIUtil.addPaths(getServletPath(),getPathInfo())); + state.startAsync(event); + return _async; + } + + /* ------------------------------------------------------------ */ + @Override + public String toString() + { + return (_handled?"[":"(") + getMethod() + " " + _uri + (_handled?"]@":")@") + hashCode() + " " + super.toString(); + } + + /* ------------------------------------------------------------ */ + @Override + public boolean authenticate(HttpServletResponse response) throws IOException, ServletException + { + if (_authentication instanceof Authentication.Deferred) + { + setAuthentication(((Authentication.Deferred)_authentication).authenticate(this,response)); + return !(_authentication instanceof Authentication.ResponseSent); + } + response.sendError(HttpStatus.UNAUTHORIZED_401); + return false; + } + + /* ------------------------------------------------------------ */ + @Override + public Part getPart(String name) throws IOException, ServletException + { + getParts(); + + return _multiPartInputStream.getPart(name); + } + + /* ------------------------------------------------------------ */ + @Override + public Collection getParts() throws IOException, ServletException + { + if (getContentType() == null || !getContentType().startsWith("multipart/form-data")) + throw new ServletException("Content-Type != multipart/form-data"); + return getParts(null); + } + + private Collection getParts(MultiMap params) throws IOException, ServletException + { + if (_multiPartInputStream == null) + _multiPartInputStream = (MultiPartInputStreamParser)getAttribute(__MULTIPART_INPUT_STREAM); + + if (_multiPartInputStream == null) + { + MultipartConfigElement config = (MultipartConfigElement)getAttribute(__MULTIPART_CONFIG_ELEMENT); + + if (config == null) + throw new IllegalStateException("No multipart config for servlet"); + + _multiPartInputStream = new MultiPartInputStreamParser(getInputStream(), + getContentType(), config, + (_context != null?(File)_context.getAttribute("javax.servlet.context.tempdir"):null)); + + setAttribute(__MULTIPART_INPUT_STREAM, _multiPartInputStream); + setAttribute(__MULTIPART_CONTEXT, _context); + Collection parts = _multiPartInputStream.getParts(); //causes parsing + ByteArrayOutputStream os = null; + for (Part p:parts) + { + MultiPartInputStreamParser.MultiPart mp = (MultiPartInputStreamParser.MultiPart)p; + if (mp.getContentDispositionFilename() == null) + { + // Servlet Spec 3.0 pg 23, parts without filename must be put into params. + String charset = null; + if (mp.getContentType() != null) + charset = MimeTypes.getCharsetFromContentType(mp.getContentType()); + + try (InputStream is = mp.getInputStream()) + { + if (os == null) + os = new ByteArrayOutputStream(); + IO.copy(is, os); + String content=new String(os.toByteArray(),charset==null?StandardCharsets.UTF_8:Charset.forName(charset)); + if (_contentParameters == null) + _contentParameters = params == null ? new MultiMap() : params; + _contentParameters.add(mp.getName(), content); + } + os.reset(); + } + } + } + + return _multiPartInputStream.getParts(); + } + + /* ------------------------------------------------------------ */ + @Override + public void login(String username, String password) throws ServletException + { + if (_authentication instanceof Authentication.Deferred) + { + _authentication=((Authentication.Deferred)_authentication).login(username,password,this); + if (_authentication == null) + throw new Authentication.Failed("Authentication failed for username '"+username+"'"); + } + else + { + throw new Authentication.Failed("Authenticated failed for username '"+username+"'. Already authenticated as "+_authentication); + } + } + + /* ------------------------------------------------------------ */ + @Override + public void logout() throws ServletException + { + if (_authentication instanceof Authentication.User) + ((Authentication.User)_authentication).logout(); + _authentication=Authentication.UNAUTHENTICATED; + } + + public void mergeQueryParameters(String newQuery, boolean updateQueryString) + { + MultiMap newQueryParams = new MultiMap<>(); + // Have to assume ENCODING because we can't know otherwise. + UrlEncoded.decodeTo(newQuery, newQueryParams, UrlEncoded.ENCODING, -1); + + MultiMap oldQueryParams = _queryParameters; + if (oldQueryParams == null && _queryString != null) + { + oldQueryParams = new MultiMap<>(); + UrlEncoded.decodeTo(_queryString, oldQueryParams, getQueryEncoding(), -1); + } + + MultiMap mergedQueryParams = newQueryParams; + if (oldQueryParams != null) + { + // Parameters values are accumulated. + mergedQueryParams = new MultiMap<>(newQueryParams); + mergedQueryParams.addAllValues(oldQueryParams); + } + + setQueryParameters(mergedQueryParams); + resetParameters(); + + if (updateQueryString) + { + // Build the new merged query string, parameters in the + // new query string hide parameters in the old query string. + StringBuilder mergedQuery = new StringBuilder(newQuery); + for (Map.Entry> entry : mergedQueryParams.entrySet()) + { + if (newQueryParams.containsKey(entry.getKey())) + continue; + for (String value : entry.getValue()) + mergedQuery.append("&").append(entry.getKey()).append("=").append(value); + } + + setQueryString(mergedQuery.toString()); + } + } + + /** + * @see javax.servlet.http.HttpServletRequest#upgrade(java.lang.Class) + */ + @Override + public T upgrade(Class handlerClass) throws IOException, ServletException + { + if (getContext() == null) + throw new ServletException ("Unable to instantiate "+handlerClass); + + try + { + //Instantiate an instance and inject it + T h = getContext().createInstance(handlerClass); + + //TODO handle the rest of the upgrade process + + return h; + } + catch (Exception e) + { + if (e instanceof ServletException) + throw (ServletException)e; + throw new ServletException(e); + } + } +}