From 37e0b8ffe44f4d6e2d2de2e9265ccbad024907ca Mon Sep 17 00:00:00 2001 From: Thomas Becker Date: Thu, 26 Jul 2012 13:10:08 +0200 Subject: [PATCH 01/15] spdy: StandardSession format toString method --- .../src/main/java/org/eclipse/jetty/spdy/StandardSession.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StandardSession.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StandardSession.java index d5524e2f617..b4dbc817715 100644 --- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StandardSession.java +++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StandardSession.java @@ -1295,7 +1295,7 @@ public class StandardSession implements ISession, Parser.Listener, Handler Date: Fri, 27 Jul 2012 15:31:34 +1000 Subject: [PATCH 02/15] JETTY-1529 Ensure new session that has just been authenticated does not get renewed --- .../jetty/security/SecurityHandler.java | 30 ++++++++++++++++ .../authentication/BasicAuthenticator.java | 2 +- .../ClientCertAuthenticator.java | 2 +- .../authentication/DigestAuthenticator.java | 2 +- .../authentication/FormAuthenticator.java | 2 +- .../authentication/LoginAuthenticator.java | 35 +++++++------------ .../authentication/SessionAuthentication.java | 3 +- .../session/AbstractSessionManager.java | 24 +++++++++++++ 8 files changed, 73 insertions(+), 27 deletions(-) diff --git a/jetty-security/src/main/java/org/eclipse/jetty/security/SecurityHandler.java b/jetty-security/src/main/java/org/eclipse/jetty/security/SecurityHandler.java index d6f69bbb91c..6d8794e8ebf 100644 --- a/jetty-security/src/main/java/org/eclipse/jetty/security/SecurityHandler.java +++ b/jetty-security/src/main/java/org/eclipse/jetty/security/SecurityHandler.java @@ -24,8 +24,11 @@ import java.util.Set; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSessionEvent; +import javax.servlet.http.HttpSessionListener; import org.eclipse.jetty.security.authentication.DeferredAuthentication; +import org.eclipse.jetty.server.AbstractHttpConnection; import org.eclipse.jetty.server.Authentication; import org.eclipse.jetty.server.Handler; import org.eclipse.jetty.server.Request; @@ -34,6 +37,7 @@ import org.eclipse.jetty.server.UserIdentity; import org.eclipse.jetty.server.handler.ContextHandler; import org.eclipse.jetty.server.handler.ContextHandler.Context; import org.eclipse.jetty.server.handler.HandlerWrapper; +import org.eclipse.jetty.server.session.AbstractSessionManager; import org.eclipse.jetty.util.component.LifeCycle; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; @@ -286,6 +290,32 @@ public abstract class SecurityHandler extends HandlerWrapper implements Authenti getInitParameter(name)==null) setInitParameter(name,context.getInitParameter(name)); } + + //register a session listener to handle securing sessions when authentication is performed + context.getContextHandler().addEventListener(new HttpSessionListener() + { + + public void sessionDestroyed(HttpSessionEvent se) + { + + } + + public void sessionCreated(HttpSessionEvent se) + { + //if current request is authenticated, then as we have just created the session, mark it as secure, as it has not yet been returned to a user + AbstractHttpConnection connection = AbstractHttpConnection.getCurrentConnection(); + if (connection == null) + return; + Request request = connection.getRequest(); + if (request == null) + return; + + if (request.isSecure()) + { + se.getSession().setAttribute(AbstractSessionManager.SESSION_KNOWN_ONLY_TO_AUTHENTICATED, Boolean.TRUE); + } + } + }); } // complicated resolution of login and identity service to handle diff --git a/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/BasicAuthenticator.java b/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/BasicAuthenticator.java index 7857b4d46ae..28be2d7a8cb 100644 --- a/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/BasicAuthenticator.java +++ b/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/BasicAuthenticator.java @@ -83,7 +83,7 @@ public class BasicAuthenticator extends LoginAuthenticator UserIdentity user = _loginService.login(username,password); if (user!=null) { - renewSessionOnAuthentication(request,response); + renewSession(request,response); return new UserAuthentication(getAuthMethod(),user); } } diff --git a/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/ClientCertAuthenticator.java b/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/ClientCertAuthenticator.java index 25220375506..67eba6034b8 100644 --- a/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/ClientCertAuthenticator.java +++ b/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/ClientCertAuthenticator.java @@ -119,7 +119,7 @@ public class ClientCertAuthenticator extends LoginAuthenticator UserIdentity user = _loginService.login(username,credential); if (user!=null) { - renewSessionOnAuthentication(request,response); + renewSession(request,response); return new UserAuthentication(getAuthMethod(),user); } } diff --git a/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/DigestAuthenticator.java b/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/DigestAuthenticator.java index d762ebefbcf..488c4a8b2b0 100644 --- a/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/DigestAuthenticator.java +++ b/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/DigestAuthenticator.java @@ -183,7 +183,7 @@ public class DigestAuthenticator extends LoginAuthenticator UserIdentity user = _loginService.login(digest.username,digest); if (user!=null) { - renewSessionOnAuthentication(request,response); + renewSession(request,response); return new UserAuthentication(getAuthMethod(),user); } } diff --git a/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/FormAuthenticator.java b/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/FormAuthenticator.java index dcd91498f36..17fbdc3f561 100644 --- a/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/FormAuthenticator.java +++ b/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/FormAuthenticator.java @@ -204,7 +204,7 @@ public class FormAuthenticator extends LoginAuthenticator UserIdentity user = _loginService.login(username,password); if (user!=null) { - session=renewSessionOnAuthentication(request,response); + session=renewSession(request,response); // Redirect to original request String nuri; diff --git a/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/LoginAuthenticator.java b/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/LoginAuthenticator.java index c730a9bab5c..8bed85f9b3e 100644 --- a/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/LoginAuthenticator.java +++ b/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/LoginAuthenticator.java @@ -13,10 +13,6 @@ package org.eclipse.jetty.security.authentication; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.Map; - import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; @@ -24,10 +20,10 @@ import javax.servlet.http.HttpSession; import org.eclipse.jetty.security.Authenticator; import org.eclipse.jetty.security.IdentityService; import org.eclipse.jetty.security.LoginService; +import org.eclipse.jetty.server.session.AbstractSessionManager; public abstract class LoginAuthenticator implements Authenticator { - public final static String SESSION_SECURED="org.eclipse.jetty.security.secured"; protected final DeferredAuthentication _deferred=new DeferredAuthentication(this); protected LoginService _loginService; protected IdentityService _identityService; @@ -53,34 +49,29 @@ public abstract class LoginAuthenticator implements Authenticator return _loginService; } - /* ------------------------------------------------------------ */ - /** Change the session when the request is authenticated for the first time + /** Change the session id. + * The session is changed to a new instance with a new ID if and only if: * @param request * @param response * @return The new session. */ - protected HttpSession renewSessionOnAuthentication(HttpServletRequest request, HttpServletResponse response) + protected HttpSession renewSession(HttpServletRequest request, HttpServletResponse response) { HttpSession httpSession = request.getSession(false); - if (_renewSession && httpSession!=null && httpSession.getAttribute(SESSION_SECURED)==null) + + //if we should renew sessions, and there is an existing session that may have been seen by non-authenticated users + //(indicated by SESSION_SECURED not being set on the session) then we should change id + if (_renewSession && httpSession!=null && httpSession.getAttribute(AbstractSessionManager.SESSION_KNOWN_ONLY_TO_AUTHENTICATED)!=Boolean.TRUE) { synchronized (this) { - Map attributes = new HashMap(); - for (Enumeration e=httpSession.getAttributeNames();e.hasMoreElements();) - { - String name=e.nextElement(); - attributes.put(name,httpSession.getAttribute(name)); - httpSession.removeAttribute(name); - } - httpSession.invalidate(); - httpSession = request.getSession(true); - httpSession.setAttribute(SESSION_SECURED,Boolean.TRUE); - for (Map.Entry entry: attributes.entrySet()) - httpSession.setAttribute(entry.getKey(),entry.getValue()); + httpSession = AbstractSessionManager.renewSession(request, httpSession,true); } } - return httpSession; } } diff --git a/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/SessionAuthentication.java b/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/SessionAuthentication.java index e63e597ccae..368c1d6193e 100644 --- a/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/SessionAuthentication.java +++ b/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/SessionAuthentication.java @@ -29,6 +29,7 @@ import org.eclipse.jetty.security.SecurityHandler; import org.eclipse.jetty.server.Authentication; import org.eclipse.jetty.server.UserIdentity; import org.eclipse.jetty.server.UserIdentity.Scope; +import org.eclipse.jetty.server.session.AbstractSessionManager; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; @@ -102,7 +103,7 @@ public class SessionAuthentication implements Authentication.User, Serializable, if (security!=null) security.logout(this); if (_session!=null) - _session.removeAttribute(LoginAuthenticator.SESSION_SECURED); + _session.removeAttribute(AbstractSessionManager.SESSION_KNOWN_ONLY_TO_AUTHENTICATED); } @Override diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/session/AbstractSessionManager.java b/jetty-server/src/main/java/org/eclipse/jetty/server/session/AbstractSessionManager.java index b6c1a381668..a0749601482 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/session/AbstractSessionManager.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/session/AbstractSessionManager.java @@ -18,6 +18,7 @@ import static java.lang.Math.round; import java.util.Collections; import java.util.Enumeration; import java.util.EventListener; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.CopyOnWriteArrayList; @@ -57,6 +58,7 @@ import org.eclipse.jetty.util.statistic.SampleStatistic; public abstract class AbstractSessionManager extends AbstractLifeCycle implements SessionManager { final static Logger __log = SessionHandler.LOG; + public final static String SESSION_KNOWN_ONLY_TO_AUTHENTICATED="org.eclipse.jetty.security.sessionKnownOnlytoAuthenticated"; /* ------------------------------------------------------------ */ public final static int __distantFuture=60*60*24*7*52*20; @@ -103,6 +105,28 @@ public abstract class AbstractSessionManager extends AbstractLifeCycle implement protected final CounterStatistic _sessionsStats = new CounterStatistic(); protected final SampleStatistic _sessionTimeStats = new SampleStatistic(); + + /* ------------------------------------------------------------ */ + public static HttpSession renewSession (HttpServletRequest request, HttpSession httpSession, boolean authenticated) + { + Map attributes = new HashMap(); + + for (Enumeration e=httpSession.getAttributeNames();e.hasMoreElements();) + { + String name=e.nextElement(); + attributes.put(name,httpSession.getAttribute(name)); + httpSession.removeAttribute(name); + } + + httpSession.invalidate(); + httpSession = request.getSession(true); + if (authenticated) + httpSession.setAttribute(SESSION_KNOWN_ONLY_TO_AUTHENTICATED, Boolean.TRUE); + for (Map.Entry entry: attributes.entrySet()) + httpSession.setAttribute(entry.getKey(),entry.getValue()); + return httpSession; + } + /* ------------------------------------------------------------ */ public AbstractSessionManager() { From c7c4c6e13b4856d1ea0740384d750341c9397a5e Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Fri, 27 Jul 2012 09:24:25 +1000 Subject: [PATCH 03/15] 379207 backported fixes from jetty-9 to make hierarchy work --- .../java/org/eclipse/jetty/util/log/StdErrLog.java | 10 +++++++--- .../org/eclipse/jetty/util/log/StdErrLogTest.java | 14 ++++++++++++-- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/log/StdErrLog.java b/jetty-util/src/main/java/org/eclipse/jetty/util/log/StdErrLog.java index 7636bd870dc..51d248d6a05 100644 --- a/jetty-util/src/main/java/org/eclipse/jetty/util/log/StdErrLog.java +++ b/jetty-util/src/main/java/org/eclipse/jetty/util/log/StdErrLog.java @@ -331,8 +331,8 @@ public class StdErrLog extends AbstractLogger this._level = LEVEL_DEBUG; for (Logger log : Log.getLoggers().values()) - { - if (log instanceof StdErrLog) + { + if (log.getName().startsWith(getName()) && log instanceof StdErrLog) ((StdErrLog)log).setLevel(LEVEL_DEBUG); } } @@ -342,7 +342,7 @@ public class StdErrLog extends AbstractLogger for (Logger log : Log.getLoggers().values()) { - if (log instanceof StdErrLog) + if (log.getName().startsWith(getName()) && log instanceof StdErrLog) ((StdErrLog)log).setLevel(((StdErrLog)log)._configuredLevel); } } @@ -572,6 +572,10 @@ public class StdErrLog extends AbstractLogger // Let Level come from configured Properties instead - sel.setLevel(_level); logger.setSource(_source); logger._stderr = this._stderr; + + // Force the child to have any programmatic configuration + if (_level!=_configuredLevel) + logger._level=_level; return logger; } diff --git a/jetty-util/src/test/java/org/eclipse/jetty/util/log/StdErrLogTest.java b/jetty-util/src/test/java/org/eclipse/jetty/util/log/StdErrLogTest.java index c902f10cea9..c34745a5c07 100644 --- a/jetty-util/src/test/java/org/eclipse/jetty/util/log/StdErrLogTest.java +++ b/jetty-util/src/test/java/org/eclipse/jetty/util/log/StdErrLogTest.java @@ -69,18 +69,28 @@ public class StdErrLogTest log.debug("YOU SHOULD NOT SEE THIS!",null,null); // Test for backward compat with old (now deprecated) method + Logger before = log.getLogger("before"); log.setDebugEnabled(true); + Logger after = log.getLogger("after"); + before.debug("testing {} {}","test","debug-before"); log.debug("testing {} {}","test","debug-deprecated"); + after.debug("testing {} {}","test","debug-after"); log.setDebugEnabled(false); + before.debug("testing {} {}","test","debug-before-false"); log.debug("testing {} {}","test","debug-deprecated-false"); - + after.debug("testing {} {}","test","debug-after-false"); + output.assertContains("DBUG:xxx:testing test debug"); output.assertContains("INFO:xxx:testing test info"); output.assertContains("WARN:xxx:testing test warn"); output.assertNotContains("YOU SHOULD NOT SEE THIS!"); + output.assertContains("DBUG:x.before:testing test debug-before"); output.assertContains("DBUG:xxx:testing test debug-deprecated"); - output.assertNotContains("DBUG:xxx:testing test debug-depdeprecated-false"); + output.assertContains("DBUG:x.after:testing test debug-after"); + output.assertNotContains("DBUG:x.before:testing test debug-before-false"); + output.assertNotContains("DBUG:xxx:testing test debug-deprecated-false"); + output.assertNotContains("DBUG:x.after:testing test debug-after-false"); } @Test From 4d889de159dbda6b00c162fd70cc7ad7eaf68c6f Mon Sep 17 00:00:00 2001 From: Jan Bartel Date: Tue, 31 Jul 2012 18:31:53 +1000 Subject: [PATCH 04/15] 347130 Empty getResourcePaths due to ZipFileClosedException --- .../jetty/util/resource/JarFileResource.java | 144 +++++++++++------- 1 file changed, 89 insertions(+), 55 deletions(-) diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/resource/JarFileResource.java b/jetty-util/src/main/java/org/eclipse/jetty/util/resource/JarFileResource.java index 95cfaabbf97..5b46a140d8b 100644 --- a/jetty-util/src/main/java/org/eclipse/jetty/util/resource/JarFileResource.java +++ b/jetty-util/src/main/java/org/eclipse/jetty/util/resource/JarFileResource.java @@ -19,6 +19,7 @@ import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; import java.util.Enumeration; +import java.util.List; import java.util.jar.JarEntry; import java.util.jar.JarFile; @@ -108,7 +109,7 @@ class JarFileResource extends JarResource /* ------------------------------------------------------------ */ /** - * Returns true if the respresenetd resource exists. + * Returns true if the represented resource exists. */ @Override public boolean exists() @@ -240,67 +241,100 @@ class JarFileResource extends JarResource @Override public synchronized String[] list() { - - if(isDirectory() && _list==null) + if (isDirectory() && _list==null) { - ArrayList list = new ArrayList(32); + List list = null; + try + { + list = listEntries(); + } + catch (Exception e) + { + //Sun's JarURLConnection impl for jar: protocol will close a JarFile in its connect() method if + //useCaches == false (eg someone called URLConnection with defaultUseCaches==true). + //As their sun.net.www.protocol.jar package caches JarFiles and/or connections, we can wind up in + //the situation where the JarFile we have remembered in our _jarFile member has actually been closed + //by other code. + //So, do one retry to drop a connection and get a fresh JarFile + LOG.warn("Retrying list:"+e); + LOG.debug(e); + release(); + list = listEntries(); + } - checkConnection(); - - JarFile jarFile=_jarFile; - if(jarFile==null) + if (list != null) { - try - { - JarURLConnection jc=(JarURLConnection)((new URL(_jarUrl)).openConnection()); - jc.setUseCaches(getUseCaches()); - jarFile=jc.getJarFile(); - } - catch(Exception e) - { - LOG.ignore(e); - } - } - - Enumeration e=jarFile.entries(); - String dir=_urlString.substring(_urlString.indexOf("!/")+2); - while(e.hasMoreElements()) - { - - JarEntry entry = (JarEntry) e.nextElement(); - String name=entry.getName().replace('\\','/'); - if(!name.startsWith(dir) || name.length()==dir.length()) - { - continue; - } - String listName=name.substring(dir.length()); - int dash=listName.indexOf('/'); - if (dash>=0) - { - //when listing jar:file urls, you get back one - //entry for the dir itself, which we ignore - if (dash==0 && listName.length()==1) - continue; - //when listing jar:file urls, all files and - //subdirs have a leading /, which we remove - if (dash==0) - listName=listName.substring(dash+1, listName.length()); - else - listName=listName.substring(0,dash+1); - - if (list.contains(listName)) - continue; - } - - list.add(listName); - } - - _list=new String[list.size()]; - list.toArray(_list); + _list=new String[list.size()]; + list.toArray(_list); + } } return _list; } + + /* ------------------------------------------------------------ */ + private List listEntries () + { + checkConnection(); + + ArrayList list = new ArrayList(32); + JarFile jarFile=_jarFile; + if(jarFile==null) + { + try + { + JarURLConnection jc=(JarURLConnection)((new URL(_jarUrl)).openConnection()); + jc.setUseCaches(getUseCaches()); + jarFile=jc.getJarFile(); + } + catch(Exception e) + { + + e.printStackTrace(); + LOG.ignore(e); + } + } + + Enumeration e=jarFile.entries(); + String dir=_urlString.substring(_urlString.indexOf("!/")+2); + while(e.hasMoreElements()) + { + + JarEntry entry = (JarEntry) e.nextElement(); + String name=entry.getName().replace('\\','/'); + if(!name.startsWith(dir) || name.length()==dir.length()) + { + continue; + } + String listName=name.substring(dir.length()); + int dash=listName.indexOf('/'); + if (dash>=0) + { + //when listing jar:file urls, you get back one + //entry for the dir itself, which we ignore + if (dash==0 && listName.length()==1) + continue; + //when listing jar:file urls, all files and + //subdirs have a leading /, which we remove + if (dash==0) + listName=listName.substring(dash+1, listName.length()); + else + listName=listName.substring(0,dash+1); + + if (list.contains(listName)) + continue; + } + + list.add(listName); + } + + return list; + } + + + + + /* ------------------------------------------------------------ */ /** * Return the length of the resource From c998abc8bcb248bbf9535aa48a9f74ba46fe0099 Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Thu, 2 Aug 2012 19:03:40 +1000 Subject: [PATCH 05/15] JETTY-1527 handle requests with URIs like http://host (ie no / ) --- .../jetty/server/AbstractHttpConnection.java | 7 ++++++- .../eclipse/jetty/server/HttpConnectionTest.java | 13 +++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/AbstractHttpConnection.java b/jetty-server/src/main/java/org/eclipse/jetty/server/AbstractHttpConnection.java index e1aeefef13b..e4acf78ed24 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/AbstractHttpConnection.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/AbstractHttpConnection.java @@ -439,7 +439,12 @@ public abstract class AbstractHttpConnection extends AbstractConnection _uri.getPort(); info=URIUtil.canonicalPath(_uri.getDecodedPath()); if (info==null && !_request.getMethod().equals(HttpMethods.CONNECT)) - throw new HttpException(400); + { + if (_uri.getScheme()!=null && _uri.getHost()!=null) + info="/"; + else + throw new HttpException(400); + } _request.setPathInfo(info); if (_out!=null) diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/HttpConnectionTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/HttpConnectionTest.java index 1e258f33a9b..ef6b5ae4328 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/HttpConnectionTest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/HttpConnectionTest.java @@ -110,6 +110,19 @@ public class HttpConnectionTest System.err.println(response); } } + + @Test + public void testNoPath() throws Exception + { + String response=connector.getResponses("GET http://localhost:80 HTTP/1.1\n"+ + "Host: localhost:80\n"+ + "\n"); + + int offset=0; + offset = checkContains(response,offset,"HTTP/1.1 200"); + checkContains(response,offset,"pathInfo=/"); + } + @Test public void testEmpty() throws Exception From 3f0756427438dabf481a48a62a94ad4d41b47e79 Mon Sep 17 00:00:00 2001 From: Jan Bartel Date: Fri, 3 Aug 2012 17:20:58 +1000 Subject: [PATCH 06/15] 379423 Jetty URL Decoding fails for certain international characters --- .../java/org/eclipse/jetty/http/HttpURI.java | 49 +++++++++++++++++++ .../jetty/server/AbstractHttpConnection.java | 15 +++++- .../jetty/server/HttpConnectionTest.java | 4 +- .../org/eclipse/jetty/server/HttpURITest.java | 11 +++-- 4 files changed, 71 insertions(+), 8 deletions(-) diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java index 1acad63d88b..64f981651e8 100644 --- a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java +++ b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java @@ -581,6 +581,55 @@ public class HttpURI _utf8b.append(bytes,0,n); return _utf8b.toString(); } + + + public String getDecodedPath(String encoding) + { + if (_path==_param) + return null; + + int length = _param-_path; + byte[] bytes=null; + int n=0; + + for (int i=_path;i<_param;i++) + { + byte b = _raw[i]; + + if (b=='%') + { + if ((i+2)>=_param) + throw new IllegalArgumentException("Bad % encoding: "+this); + b=(byte)(0xff&TypeUtil.parseInt(_raw,i+1,2,16)); + i+=2; + } + else if (bytes==null) + { + n++; + continue; + } + + if (bytes==null) + { + bytes=new byte[length]; + System.arraycopy(_raw,_path,bytes,0,n); + } + + bytes[n++]=b; + } + + + if (bytes==null) + return StringUtil.toString(_raw,_path,_param-_path,encoding); + + return StringUtil.toString(bytes,0,n,encoding); + } + + + + + + public String getPathAndParam() { diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/AbstractHttpConnection.java b/jetty-server/src/main/java/org/eclipse/jetty/server/AbstractHttpConnection.java index e4acf78ed24..c86c8b7d18c 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/AbstractHttpConnection.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/AbstractHttpConnection.java @@ -437,7 +437,20 @@ public abstract class AbstractHttpConnection extends AbstractConnection try { _uri.getPort(); - info=URIUtil.canonicalPath(_uri.getDecodedPath()); + String path = null; + + try + { + path = _uri.getDecodedPath(); + } + catch (Exception e) + { + LOG.warn("Failed UTF-8 decode for request path, trying ISO-8859-1"); + LOG.ignore(e); + path = _uri.getDecodedPath(StringUtil.__ISO_8859_1); + } + + info=URIUtil.canonicalPath(path); if (info==null && !_request.getMethod().equals(HttpMethods.CONNECT)) { if (_uri.getScheme()!=null && _uri.getHost()!=null) diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/HttpConnectionTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/HttpConnectionTest.java index ef6b5ae4328..5af969d85fe 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/HttpConnectionTest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/HttpConnectionTest.java @@ -189,12 +189,12 @@ public class HttpConnectionTest response=connector.getResponses("GET /foo/bar%c0%00 HTTP/1.1\n"+ "Host: localhost\n"+ "\015\012"); - checkContains(response,0,"HTTP/1.1 400"); + checkContains(response,0,"HTTP/1.1 200"); //now fallback to iso-8859-1 response=connector.getResponses("GET /bad/utf8%c1 HTTP/1.1\n"+ "Host: localhost\n"+ "\015\012"); - checkContains(response,0,"HTTP/1.1 400"); + checkContains(response,0,"HTTP/1.1 200"); //now fallback to iso-8859-1 } finally { diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/HttpURITest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/HttpURITest.java index d75235d40e0..fb6d1eff981 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/HttpURITest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/HttpURITest.java @@ -181,10 +181,11 @@ public class HttpURITest private final String[][] encoding_tests= { - /* 0*/ {"/path/info","/path/info"}, - /* 1*/ {"/path/%69nfo","/path/info"}, - /* 2*/ {"http://host/path/%69nfo","/path/info"}, - /* 3*/ {"http://host/path/%69nf%c2%a4","/path/inf\u00a4"}, + /* 0*/ {"/path/info","/path/info", "UTF-8"}, + /* 1*/ {"/path/%69nfo","/path/info", "UTF-8"}, + /* 2*/ {"http://host/path/%69nfo","/path/info", "UTF-8"}, + /* 3*/ {"http://host/path/%69nf%c2%a4","/path/inf\u00a4", "UTF-8"}, + /* 4*/ {"http://host/path/%E5", "/path/\u00e5", "ISO-8859-1"} }; @Test @@ -195,7 +196,7 @@ public class HttpURITest for (int t=0;t Date: Fri, 3 Aug 2012 19:22:58 +1000 Subject: [PATCH 07/15] JETTY-1501 Setting custom error response message changes page title --- .../jetty/server/handler/ErrorHandler.java | 27 ++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ErrorHandler.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ErrorHandler.java index b43e34b9cef..efd64967248 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ErrorHandler.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ErrorHandler.java @@ -37,6 +37,7 @@ import org.eclipse.jetty.util.ByteArrayISO8859Writer; public class ErrorHandler extends AbstractHandler { boolean _showStacks=true; + boolean _showMessageInTitle=true; String _cacheControl="must-revalidate,no-cache,no-store"; /* ------------------------------------------------------------ */ @@ -85,12 +86,16 @@ public class ErrorHandler extends AbstractHandler /* ------------------------------------------------------------ */ protected void writeErrorPageHead(HttpServletRequest request, Writer writer, int code, String message) throws IOException - { + { writer.write("\n"); writer.write("Error "); writer.write(Integer.toString(code)); - writer.write(' '); - write(writer,message); + + if (_showMessageInTitle) + { + writer.write(' '); + write(writer,message); + } writer.write("\n"); } @@ -176,6 +181,22 @@ public class ErrorHandler extends AbstractHandler { _showStacks = showStacks; } + + /* ------------------------------------------------------------ */ + /** + * @param showMessageInTitle if true, the error message appears in page title + */ + public void setShowMessageInTitle(boolean showMessageInTitle) + { + _showMessageInTitle = showMessageInTitle; + } + + + /* ------------------------------------------------------------ */ + public boolean getShowMessageInTitle() + { + return _showMessageInTitle; + } /* ------------------------------------------------------------ */ protected void write(Writer writer,String string) From ab40dee06f0047089027d8662dee925378096ce5 Mon Sep 17 00:00:00 2001 From: Simone Bordet Date: Mon, 6 Aug 2012 18:13:16 +0200 Subject: [PATCH 08/15] 367591 - Support Env variables in XmlConfiguration. The 7.6 DTD was erroneously committed without the relevant change, which was committed to the 6.0 DTD. --- .../org/eclipse/jetty/xml/configure_6_0.dtd | 20 +----------------- .../org/eclipse/jetty/xml/configure_7_6.dtd | 21 ++++++++++++++++++- 2 files changed, 21 insertions(+), 20 deletions(-) diff --git a/jetty-xml/src/main/resources/org/eclipse/jetty/xml/configure_6_0.dtd b/jetty-xml/src/main/resources/org/eclipse/jetty/xml/configure_6_0.dtd index e2139c162ed..f79d4b7f003 100644 --- a/jetty-xml/src/main/resources/org/eclipse/jetty/xml/configure_6_0.dtd +++ b/jetty-xml/src/main/resources/org/eclipse/jetty/xml/configure_6_0.dtd @@ -19,7 +19,7 @@ my be specified if a match is not achieved. --> - + @@ -245,24 +245,6 @@ This is equivalent to: - - - - - + @@ -246,6 +246,25 @@ This is equivalent to: + + + + +