You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by ma...@apache.org on 2019/12/07 22:30:32 UTC

[tomcat] branch 7.0.x updated (1d43f40 -> f47bc32)

This is an automated email from the ASF dual-hosted git repository.

markt pushed a change to branch 7.0.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git.


    from 1d43f40  BZ 63982: CombinedRealm makes assumptions about principal implementation
     new 7f9e8b1  Merge in BCEL changes to ff6941e (2019-12-06, 6.4.2-dev)
     new cefae34  Merge in Codec changes to 9637dd4 (2019-12-06, 1.14-SNAPSHOT)
     new be8f0e3  Merge in FileUpload changes to 2317552 (2019-12-06, 2.0-SNAPSHOT)
     new 2e4536b  Fix Findbugs warnings
     new fea2445  Remove unused code reported by SpotBugs
     new f4322c6  Fix FileUpload
     new aa6e0f0  Clean-up. No functional change.
     new d2a40f2  Clean-up prior to some refactoring.
     new c31917d  Refactor change of session ID to reduce duplicate code
     new ab72a10  Refactor so Principal is never cached in session with cache==false
     new be6b473  Harden the FORM authentication process
     new 11ed237  Align with 8.5.x to aid back-ports
     new c06674e  Add an atomic method to rotate session ID and return new value.
     new f47bc32  Update changelog

The 14 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 java/org/apache/catalina/Manager.java              |  43 +-
 .../catalina/authenticator/AuthenticatorBase.java  |  36 +-
 .../apache/catalina/authenticator/Constants.java   |  47 +-
 .../catalina/authenticator/FormAuthenticator.java  | 101 ++-
 java/org/apache/catalina/connector/Request.java    |  33 +-
 .../catalina/session/LocalStrings.properties       |   1 +
 .../catalina/session/LocalStrings_fr.properties    |   1 +
 .../catalina/session/LocalStrings_ja.properties    |   1 +
 .../catalina/session/LocalStrings_ko.properties    |   1 +
 .../catalina/session/LocalStrings_zh_CN.properties |   1 +
 java/org/apache/catalina/session/ManagerBase.java  | 184 +++---
 java/org/apache/tomcat/util/bcel/Const.java        |  14 +-
 .../tomcat/util/bcel/classfile/ConstantClass.java  |   2 +-
 .../tomcat/util/bcel/classfile/ConstantDouble.java |   2 +-
 .../tomcat/util/bcel/classfile/ConstantFloat.java  |   2 +-
 .../util/bcel/classfile/ConstantInteger.java       |   2 +-
 .../tomcat/util/bcel/classfile/ConstantLong.java   |   2 +-
 .../apache/tomcat/util/codec/binary/Base64.java    |  28 +-
 .../tomcat/util/codec/binary/BaseNCodec.java       | 112 +++-
 .../util/http/fileupload/FileItemIterator.java     |  49 +-
 .../util/http/fileupload/FileUploadBase.java       | 708 +--------------------
 .../util/http/fileupload/MultipartStream.java      |  10 +-
 .../util/http/fileupload/disk/DiskFileItem.java    |   3 +-
 .../http/fileupload/impl/FileItemIteratorImpl.java | 339 ++++++++++
 .../http/fileupload/impl/FileItemStreamImpl.java   | 213 +++++++
 .../impl/FileSizeLimitExceededException.java       |  94 +++
 .../fileupload/impl/FileUploadIOException.java     |  62 ++
 .../fileupload/impl/IOFileUploadException.java     |  61 ++
 .../impl/InvalidContentTypeException.java          |  62 ++
 .../util/http/fileupload/impl/SizeException.java   |  75 +++
 .../impl/SizeLimitExceededException.java}          |  37 +-
 .../org/apache/catalina/session/FileStoreTest.java |  12 +-
 webapps/docs/changelog.xml                         |  17 +
 33 files changed, 1378 insertions(+), 977 deletions(-)
 create mode 100644 java/org/apache/tomcat/util/http/fileupload/impl/FileItemIteratorImpl.java
 create mode 100644 java/org/apache/tomcat/util/http/fileupload/impl/FileItemStreamImpl.java
 create mode 100644 java/org/apache/tomcat/util/http/fileupload/impl/FileSizeLimitExceededException.java
 create mode 100644 java/org/apache/tomcat/util/http/fileupload/impl/FileUploadIOException.java
 create mode 100644 java/org/apache/tomcat/util/http/fileupload/impl/IOFileUploadException.java
 create mode 100644 java/org/apache/tomcat/util/http/fileupload/impl/InvalidContentTypeException.java
 create mode 100644 java/org/apache/tomcat/util/http/fileupload/impl/SizeException.java
 copy java/org/apache/{naming/ResourceEnvRef.java => tomcat/util/http/fileupload/impl/SizeLimitExceededException.java} (53%)


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


[tomcat] 08/14: Clean-up prior to some refactoring.

Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

markt pushed a commit to branch 7.0.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git

commit d2a40f238d0ab6b6e60d643b208812aa6b655ca6
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Thu Dec 5 20:00:02 2019 +0000

    Clean-up prior to some refactoring.
---
 .../catalina/authenticator/FormAuthenticator.java  | 51 ++++++++--------------
 1 file changed, 17 insertions(+), 34 deletions(-)

diff --git a/java/org/apache/catalina/authenticator/FormAuthenticator.java b/java/org/apache/catalina/authenticator/FormAuthenticator.java
index 5b55664..d8551c4 100644
--- a/java/org/apache/catalina/authenticator/FormAuthenticator.java
+++ b/java/org/apache/catalina/authenticator/FormAuthenticator.java
@@ -168,22 +168,17 @@ public class FormAuthenticator
             if (log.isDebugEnabled()) {
                 log.debug("Checking for reauthenticate in session " + session);
             }
-            String username =
-                (String) session.getNote(Constants.SESS_USERNAME_NOTE);
-            String password =
-                (String) session.getNote(Constants.SESS_PASSWORD_NOTE);
-            if ((username != null) && (password != null)) {
+            String username = (String) session.getNote(Constants.SESS_USERNAME_NOTE);
+            String password = (String) session.getNote(Constants.SESS_PASSWORD_NOTE);
+            if (username != null && password != null) {
                 if (log.isDebugEnabled()) {
                     log.debug("Reauthenticating username '" + username + "'");
                 }
-                principal =
-                    context.getRealm().authenticate(username, password);
+                principal = context.getRealm().authenticate(username, password);
                 if (principal != null) {
                     session.setNote(Constants.FORM_PRINCIPAL_NOTE, principal);
                     if (!matchRequest(request)) {
-                        register(request, response, principal,
-                                HttpServletRequest.FORM_AUTH,
-                                username, password);
+                        register(request, response, principal, HttpServletRequest.FORM_AUTH, username, password);
                         return true;
                     }
                 }
@@ -198,16 +193,13 @@ public class FormAuthenticator
         if (matchRequest(request)) {
             session = request.getSessionInternal(true);
             if (log.isDebugEnabled()) {
-                log.debug("Restore request from session '"
-                          + session.getIdInternal()
-                          + "'");
+                log.debug("Restore request from session '" + session.getIdInternal() + "'");
             }
-            principal = (Principal)
-                session.getNote(Constants.FORM_PRINCIPAL_NOTE);
+            principal = (Principal) session.getNote(Constants.FORM_PRINCIPAL_NOTE);
             register(request, response, principal, HttpServletRequest.FORM_AUTH,
                      (String) session.getNote(Constants.SESS_USERNAME_NOTE),
                      (String) session.getNote(Constants.SESS_PASSWORD_NOTE));
-            // If we're caching principals we no longer need the username
+            // If we're caching principals we no longer need the user name
             // and password in the session, so remove them
             if (cache) {
                 session.removeNote(Constants.SESS_USERNAME_NOTE);
@@ -232,9 +224,7 @@ public class FormAuthenticator
         String requestURI = request.getDecodedRequestURI();
 
         // Is this the action request from the login page?
-        boolean loginAction =
-            requestURI.startsWith(contextPath) &&
-            requestURI.endsWith(Constants.FORM_ACTION);
+        boolean loginAction = requestURI.startsWith(contextPath) && requestURI.endsWith(Constants.FORM_ACTION);
 
         // No -- Save this request and redirect to the form login page
         if (!loginAction) {
@@ -260,8 +250,7 @@ public class FormAuthenticator
                 saveRequest(request, session);
             } catch (IOException ioe) {
                 log.debug("Request body too big to save during authentication");
-                response.sendError(HttpServletResponse.SC_FORBIDDEN,
-                        sm.getString("authenticator.requestBodyTooBig"));
+                response.sendError(HttpServletResponse.SC_FORBIDDEN, sm.getString("authenticator.requestBodyTooBig"));
                 return false;
             }
             forwardToLoginPage(request, response, config);
@@ -295,12 +284,11 @@ public class FormAuthenticator
         }
         if (session == null) {
             if (containerLog.isDebugEnabled()) {
-                containerLog.debug
-                    ("User took so long to log on the session expired");
+                containerLog.debug("User took so long to log on the session expired");
             }
             if (landingPage == null) {
-                response.sendError(HttpServletResponse.SC_REQUEST_TIMEOUT,
-                        sm.getString("authenticator.sessionExpired"));
+                response.sendError(
+                        HttpServletResponse.SC_REQUEST_TIMEOUT, sm.getString("authenticator.sessionExpired"));
             } else {
                 // Make the authenticator think the user originally requested
                 // the landing page
@@ -309,8 +297,7 @@ public class FormAuthenticator
                 saved.setMethod("GET");
                 saved.setRequestURI(uri);
                 saved.setDecodedRequestURI(uri);
-                request.getSessionInternal(true).setNote(
-                        Constants.FORM_REQUEST_NOTE, saved);
+                request.getSessionInternal(true).setNote(Constants.FORM_REQUEST_NOTE, saved);
                 response.sendRedirect(response.encodeRedirectURL(uri));
             }
             return false;
@@ -331,8 +318,7 @@ public class FormAuthenticator
         }
         if (requestURI == null) {
             if (landingPage == null) {
-                response.sendError(HttpServletResponse.SC_BAD_REQUEST,
-                        sm.getString("authenticator.formlogin"));
+                response.sendError(HttpServletResponse.SC_BAD_REQUEST, sm.getString("authenticator.formlogin"));
             } else {
                 // Make the authenticator think the user originally requested
                 // the landing page
@@ -348,7 +334,6 @@ public class FormAuthenticator
             response.sendRedirect(response.encodeRedirectURL(requestURI));
         }
         return false;
-
     }
 
 
@@ -514,8 +499,7 @@ public class FormAuthenticator
         }
 
         // Is there a saved request?
-        SavedRequest sreq =
-                (SavedRequest) session.getNote(Constants.FORM_REQUEST_NOTE);
+        SavedRequest sreq = (SavedRequest) session.getNote(Constants.FORM_REQUEST_NOTE);
         if (sreq == null) {
             return false;
         }
@@ -549,8 +533,7 @@ public class FormAuthenticator
             throws IOException {
 
         // Retrieve and remove the SavedRequest object from our session
-        SavedRequest saved = (SavedRequest)
-            session.getNote(Constants.FORM_REQUEST_NOTE);
+        SavedRequest saved = (SavedRequest) session.getNote(Constants.FORM_REQUEST_NOTE);
         session.removeNote(Constants.FORM_REQUEST_NOTE);
         session.removeNote(Constants.FORM_PRINCIPAL_NOTE);
         if (saved == null) {


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


[tomcat] 14/14: Update changelog

Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

markt pushed a commit to branch 7.0.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git

commit f47bc323bd62db6cdece75c004d405e00d76a703
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Fri Dec 6 21:14:06 2019 +0000

    Update changelog
---
 webapps/docs/changelog.xml | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index ce55169..997d773 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -94,6 +94,11 @@
         and refactor loops in <code>FileStore</code> to use the ForEach style.
         Pull request provided by Govinda Sakhare. (markt)
       </scode>
+      <fix>
+        Refactor FORM authentication to reduce duplicate code and to ensure that
+        the authenticated Principal is not cached in the session when caching is
+        disabled. (markt)
+      </fix>
     </changelog>
   </subsection>
   <subsection name="Coyote">


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


[tomcat] 01/14: Merge in BCEL changes to ff6941e (2019-12-06, 6.4.2-dev)

Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

markt pushed a commit to branch 7.0.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git

commit 7f9e8b1aa348f206d390c48bcc700662fe979818
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Fri Dec 6 14:18:15 2019 +0000

    Merge in BCEL changes to ff6941e (2019-12-06, 6.4.2-dev)
---
 java/org/apache/tomcat/util/bcel/Const.java                | 14 ++++++++------
 .../apache/tomcat/util/bcel/classfile/ConstantClass.java   |  2 +-
 .../apache/tomcat/util/bcel/classfile/ConstantDouble.java  |  2 +-
 .../apache/tomcat/util/bcel/classfile/ConstantFloat.java   |  2 +-
 .../apache/tomcat/util/bcel/classfile/ConstantInteger.java |  2 +-
 .../apache/tomcat/util/bcel/classfile/ConstantLong.java    |  2 +-
 webapps/docs/changelog.xml                                 |  4 ++++
 7 files changed, 17 insertions(+), 11 deletions(-)

diff --git a/java/org/apache/tomcat/util/bcel/Const.java b/java/org/apache/tomcat/util/bcel/Const.java
index 402b304..bfaeb42 100644
--- a/java/org/apache/tomcat/util/bcel/Const.java
+++ b/java/org/apache/tomcat/util/bcel/Const.java
@@ -23,12 +23,14 @@ package org.apache.tomcat.util.bcel;
 public final class Const {
 
     /** One of the access flags for fields, methods, or classes.
-     *  @see <a href="http://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.5">
-     *  Flag definitions for Fields in the Java Virtual Machine Specification (Java SE 8 Edition).</a>
-     *  @see <a href="http://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.6">
-     *  Flag definitions for Methods in the Java Virtual Machine Specification (Java SE 8 Edition).</a>
-     *  @see <a href="http://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.7.6-300-D.1-D.1">
-     *  Flag definitions for Classes in the Java Virtual Machine Specification (Java SE 8 Edition).</a>
+     *  @see <a href="http://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.1-200-E.1">
+     *  Flag definitions for Classes in the Java Virtual Machine Specification (Java SE 9 Edition).</a>
+     *  @see <a href="http://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.5">
+     *  Flag definitions for Fields in the Java Virtual Machine Specification (Java SE 9 Edition).</a>
+     *  @see <a href="http://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.6">
+     *  Flag definitions for Methods in the Java Virtual Machine Specification (Java SE 9 Edition).</a>
+     *  @see <a href="http://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.6-300-D.1-D.1">
+     *  Flag definitions for Inner Classes in the Java Virtual Machine Specification (Java SE 9 Edition).</a>
      */
     public static final short ACC_FINAL      = 0x0010;
 
diff --git a/java/org/apache/tomcat/util/bcel/classfile/ConstantClass.java b/java/org/apache/tomcat/util/bcel/classfile/ConstantClass.java
index 86e7262..4bce5cc 100644
--- a/java/org/apache/tomcat/util/bcel/classfile/ConstantClass.java
+++ b/java/org/apache/tomcat/util/bcel/classfile/ConstantClass.java
@@ -48,7 +48,7 @@ public final class ConstantClass extends Constant {
     /**
      * @return Name index in constant pool of class name.
      */
-    public final int getNameIndex() {
+    public int getNameIndex() {
         return name_index;
     }
 }
diff --git a/java/org/apache/tomcat/util/bcel/classfile/ConstantDouble.java b/java/org/apache/tomcat/util/bcel/classfile/ConstantDouble.java
index 5ba7fcc..1152dbd 100644
--- a/java/org/apache/tomcat/util/bcel/classfile/ConstantDouble.java
+++ b/java/org/apache/tomcat/util/bcel/classfile/ConstantDouble.java
@@ -48,7 +48,7 @@ public final class ConstantDouble extends Constant {
     /**
      * @return data, i.e., 8 bytes.
      */
-    public final double getBytes() {
+    public double getBytes() {
         return bytes;
     }
 }
diff --git a/java/org/apache/tomcat/util/bcel/classfile/ConstantFloat.java b/java/org/apache/tomcat/util/bcel/classfile/ConstantFloat.java
index f372bb9..1fd2450 100644
--- a/java/org/apache/tomcat/util/bcel/classfile/ConstantFloat.java
+++ b/java/org/apache/tomcat/util/bcel/classfile/ConstantFloat.java
@@ -48,7 +48,7 @@ public final class ConstantFloat extends Constant {
     /**
      * @return data, i.e., 4 bytes.
      */
-    public final float getBytes() {
+    public float getBytes() {
         return bytes;
     }
 }
diff --git a/java/org/apache/tomcat/util/bcel/classfile/ConstantInteger.java b/java/org/apache/tomcat/util/bcel/classfile/ConstantInteger.java
index f2c1ba8..0d95983 100644
--- a/java/org/apache/tomcat/util/bcel/classfile/ConstantInteger.java
+++ b/java/org/apache/tomcat/util/bcel/classfile/ConstantInteger.java
@@ -48,7 +48,7 @@ public final class ConstantInteger extends Constant {
     /**
      * @return data, i.e., 4 bytes.
      */
-    public final int getBytes() {
+    public int getBytes() {
         return bytes;
     }
 }
diff --git a/java/org/apache/tomcat/util/bcel/classfile/ConstantLong.java b/java/org/apache/tomcat/util/bcel/classfile/ConstantLong.java
index d7b245c..d7affef 100644
--- a/java/org/apache/tomcat/util/bcel/classfile/ConstantLong.java
+++ b/java/org/apache/tomcat/util/bcel/classfile/ConstantLong.java
@@ -48,7 +48,7 @@ public final class ConstantLong extends Constant {
     /**
      * @return data, i.e., 8 bytes.
      */
-    public final long getBytes() {
+    public long getBytes() {
         return bytes;
     }
 }
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index b09bd6c..2e9cce6 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -157,6 +157,10 @@
         Expand the coverage of the Chinese translations provided with Apache
         Tomcat. Contributions provided by lins and 磊. (markt)
       </add>
+      <add>
+        Update the internal fork of Apache Commons BCEL to ff6941e (2019-12-06,
+        6.4.2-dev). Code clean-up only. (markt)
+      </add>
     </changelog>
   </subsection>
 </section>


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


[tomcat] 04/14: Fix Findbugs warnings

Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

markt pushed a commit to branch 7.0.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git

commit 2e4536b0b42db1a1ce84fc507adb4524de93cb11
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Fri Dec 6 16:42:32 2019 +0000

    Fix Findbugs warnings
---
 test/org/apache/catalina/session/FileStoreTest.java | 12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/test/org/apache/catalina/session/FileStoreTest.java b/test/org/apache/catalina/session/FileStoreTest.java
index e46a308..8ace616 100644
--- a/test/org/apache/catalina/session/FileStoreTest.java
+++ b/test/org/apache/catalina/session/FileStoreTest.java
@@ -60,9 +60,15 @@ public class FileStoreTest {
     @Before
     public void beforeEachTest() throws IOException {
         fileStore.setDirectory(SESS_TEMPPATH);
-        dir.mkdir();
-        file1.createNewFile();
-        file2.createNewFile();
+        if (!dir.mkdir()) {
+            Assert.fail();
+        }
+        if (!file1.createNewFile()) {
+            Assert.fail();
+        }
+        if (!file2.createNewFile()) {
+            Assert.fail();
+        }
     }
 
 


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


[tomcat] 10/14: Refactor so Principal is never cached in session with cache==false

Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

markt pushed a commit to branch 7.0.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git

commit ab72a106fe5d992abddda954e30849d7cf8cc583
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Thu Dec 5 23:25:37 2019 +0000

    Refactor so Principal is never cached in session with cache==false
---
 .../catalina/authenticator/AuthenticatorBase.java  |  5 ++--
 .../apache/catalina/authenticator/Constants.java   |  3 ++
 .../catalina/authenticator/FormAuthenticator.java  | 33 ++++++----------------
 3 files changed, 15 insertions(+), 26 deletions(-)

diff --git a/java/org/apache/catalina/authenticator/AuthenticatorBase.java b/java/org/apache/catalina/authenticator/AuthenticatorBase.java
index 5a00864..6d5232e 100644
--- a/java/org/apache/catalina/authenticator/AuthenticatorBase.java
+++ b/java/org/apache/catalina/authenticator/AuthenticatorBase.java
@@ -914,10 +914,11 @@ public abstract class AuthenticatorBase extends ValveBase
         }
 
         // Cache the authentication information in our session, if any
-        if (cache) {
-            if (session != null) {
+        if (session != null) {
+            if (cache) {
                 session.setAuthType(authType);
                 session.setPrincipal(principal);
+            } else {
                 if (username != null) {
                     session.setNote(Constants.SESS_USERNAME_NOTE, username);
                 } else {
diff --git a/java/org/apache/catalina/authenticator/Constants.java b/java/org/apache/catalina/authenticator/Constants.java
index b8e03cd..e13dc55 100644
--- a/java/org/apache/catalina/authenticator/Constants.java
+++ b/java/org/apache/catalina/authenticator/Constants.java
@@ -108,7 +108,10 @@ public class Constants {
 
     /**
      * The previously authenticated principal (if caching is disabled).
+     *
+     * @deprecated Unused. Will be removed in Tomcat 10.
      */
+    @Deprecated
     public static final String FORM_PRINCIPAL_NOTE = "org.apache.catalina.authenticator.PRINCIPAL";
 
     /**
diff --git a/java/org/apache/catalina/authenticator/FormAuthenticator.java b/java/org/apache/catalina/authenticator/FormAuthenticator.java
index 863fd77..1354ce2 100644
--- a/java/org/apache/catalina/authenticator/FormAuthenticator.java
+++ b/java/org/apache/catalina/authenticator/FormAuthenticator.java
@@ -153,10 +153,6 @@ public class FormAuthenticator
                                 LoginConfig config)
         throws IOException {
 
-        if (checkForCachedAuthentication(request, response, true)) {
-            return true;
-        }
-
         // References to objects we will need later
         Session session = null;
         Principal principal = null;
@@ -175,9 +171,8 @@ public class FormAuthenticator
                 }
                 principal = context.getRealm().authenticate(username, password);
                 if (principal != null) {
-                    session.setNote(Constants.FORM_PRINCIPAL_NOTE, principal);
+                    register(request, response, principal, HttpServletRequest.FORM_AUTH, username, password);
                     if (!matchRequest(request)) {
-                        register(request, response, principal, HttpServletRequest.FORM_AUTH, username, password);
                         return true;
                     }
                 }
@@ -194,16 +189,6 @@ public class FormAuthenticator
             if (log.isDebugEnabled()) {
                 log.debug("Restore request from session '" + session.getIdInternal() + "'");
             }
-            principal = (Principal) session.getNote(Constants.FORM_PRINCIPAL_NOTE);
-            register(request, response, principal, HttpServletRequest.FORM_AUTH,
-                     (String) session.getNote(Constants.SESS_USERNAME_NOTE),
-                     (String) session.getNote(Constants.SESS_PASSWORD_NOTE));
-            // If we're caching principals we no longer need the user name
-            // and password in the session, so remove them
-            if (cache) {
-                session.removeNote(Constants.SESS_USERNAME_NOTE);
-                session.removeNote(Constants.SESS_PASSWORD_NOTE);
-            }
             if (restoreRequest(request, session)) {
                 if (log.isDebugEnabled()) {
                     log.debug("Proceed to restored request");
@@ -218,6 +203,12 @@ public class FormAuthenticator
             }
         }
 
+        // This check has to be after the previous check for a matching request
+        // because that matching request may also include a cached Principal.
+        if (checkForCachedAuthentication(request, response, true)) {
+            return true;
+        }
+
         // Acquire references to objects we will need to evaluate
         String contextPath = request.getContextPath();
         String requestURI = request.getDecodedRequestURI();
@@ -302,12 +293,7 @@ public class FormAuthenticator
             return false;
         }
 
-        // Save the authenticated Principal in our session
-        session.setNote(Constants.FORM_PRINCIPAL_NOTE, principal);
-
-        // Save the username and password as well
-        session.setNote(Constants.SESS_USERNAME_NOTE, username);
-        session.setNote(Constants.SESS_PASSWORD_NOTE, password);
+        register(request, response, principal, HttpServletRequest.FORM_AUTH, username, password);
 
         // Redirect the user to the original request URI (which will cause
         // the original request to be restored)
@@ -502,7 +488,7 @@ public class FormAuthenticator
         }
 
         // Is there a saved principal?
-        if (session.getNote(Constants.FORM_PRINCIPAL_NOTE) == null) {
+        if (cache && session.getPrincipal() == null || !cache && request.getPrincipal() == null) {
             return false;
         }
 
@@ -532,7 +518,6 @@ public class FormAuthenticator
         // Retrieve and remove the SavedRequest object from our session
         SavedRequest saved = (SavedRequest) session.getNote(Constants.FORM_REQUEST_NOTE);
         session.removeNote(Constants.FORM_REQUEST_NOTE);
-        session.removeNote(Constants.FORM_PRINCIPAL_NOTE);
         if (saved == null) {
             return false;
         }


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


[tomcat] 03/14: Merge in FileUpload changes to 2317552 (2019-12-06, 2.0-SNAPSHOT)

Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

markt pushed a commit to branch 7.0.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git

commit be8f0e3a1417cce57d42d9727d4fea4619db6fd9
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Fri Dec 6 15:30:48 2019 +0000

    Merge in FileUpload changes to 2317552 (2019-12-06, 2.0-SNAPSHOT)
---
 java/org/apache/catalina/connector/Request.java    |   6 +-
 .../util/http/fileupload/FileItemIterator.java     |  49 +-
 .../util/http/fileupload/FileUploadBase.java       | 708 +--------------------
 .../util/http/fileupload/MultipartStream.java      |  10 +-
 .../util/http/fileupload/disk/DiskFileItem.java    |   3 +-
 .../http/fileupload/impl/FileItemIteratorImpl.java | 339 ++++++++++
 .../http/fileupload/impl/FileItemStreamImpl.java   | 222 +++++++
 .../impl/FileSizeLimitExceededException.java       |  94 +++
 .../fileupload/impl/FileUploadIOException.java     |  62 ++
 .../fileupload/impl/IOFileUploadException.java     |  61 ++
 .../impl/InvalidContentTypeException.java          |  62 ++
 .../util/http/fileupload/impl/SizeException.java   |  75 +++
 .../impl/SizeLimitExceededException.java           |  43 ++
 webapps/docs/changelog.xml                         |   4 +
 14 files changed, 1029 insertions(+), 709 deletions(-)

diff --git a/java/org/apache/catalina/connector/Request.java b/java/org/apache/catalina/connector/Request.java
index f916ad7..954c0a2 100644
--- a/java/org/apache/catalina/connector/Request.java
+++ b/java/org/apache/catalina/connector/Request.java
@@ -94,10 +94,10 @@ import org.apache.tomcat.util.http.Parameters;
 import org.apache.tomcat.util.http.Parameters.FailReason;
 import org.apache.tomcat.util.http.ServerCookie;
 import org.apache.tomcat.util.http.fileupload.FileItem;
-import org.apache.tomcat.util.http.fileupload.FileUploadBase;
-import org.apache.tomcat.util.http.fileupload.FileUploadBase.InvalidContentTypeException;
 import org.apache.tomcat.util.http.fileupload.FileUploadException;
 import org.apache.tomcat.util.http.fileupload.disk.DiskFileItemFactory;
+import org.apache.tomcat.util.http.fileupload.impl.InvalidContentTypeException;
+import org.apache.tomcat.util.http.fileupload.impl.SizeLimitExceededException;
 import org.apache.tomcat.util.http.fileupload.servlet.ServletFileUpload;
 import org.apache.tomcat.util.http.fileupload.servlet.ServletRequestContext;
 import org.apache.tomcat.util.http.mapper.MappingData;
@@ -2996,7 +2996,7 @@ public class Request implements HttpServletRequest {
             } catch (InvalidContentTypeException e) {
                 parameters.setParseFailedReason(FailReason.INVALID_CONTENT_TYPE);
                 partsParseException = new ServletException(e);
-            } catch (FileUploadBase.SizeException e) {
+            } catch (SizeLimitExceededException e) {
                 parameters.setParseFailedReason(FailReason.POST_TOO_LARGE);
                 checkSwallowInput();
                 partsParseException = new IllegalStateException(e);
diff --git a/java/org/apache/tomcat/util/http/fileupload/FileItemIterator.java b/java/org/apache/tomcat/util/http/fileupload/FileItemIterator.java
index 4f331ad..9665312 100644
--- a/java/org/apache/tomcat/util/http/fileupload/FileItemIterator.java
+++ b/java/org/apache/tomcat/util/http/fileupload/FileItemIterator.java
@@ -17,12 +17,56 @@
 package org.apache.tomcat.util.http.fileupload;
 
 import java.io.IOException;
+import java.util.List;
+
+import org.apache.tomcat.util.http.fileupload.impl.FileSizeLimitExceededException;
+import org.apache.tomcat.util.http.fileupload.impl.SizeLimitExceededException;
 
 /**
  * An iterator, as returned by
  * {@link FileUploadBase#getItemIterator(RequestContext)}.
  */
 public interface FileItemIterator {
+    /** Returns the maximum size of a single file. An {@link FileSizeLimitExceededException}
+     * will be thrown, if there is an uploaded file, which is exceeding this value.
+     * By default, this value will be copied from the {@link FileUploadBase#getFileSizeMax()
+     * FileUploadBase} object, however, the user may replace the default value with a
+     * request specific value by invoking {@link #setFileSizeMax(long)} on this object.
+     * @return The maximum size of a single, uploaded file. The value -1 indicates "unlimited".
+     */
+    public long getFileSizeMax();
+
+    /** Sets the maximum size of a single file. An {@link FileSizeLimitExceededException}
+     * will be thrown, if there is an uploaded file, which is exceeding this value.
+     * By default, this value will be copied from the {@link FileUploadBase#getFileSizeMax()
+     * FileUploadBase} object, however, the user may replace the default value with a
+     * request specific value by invoking {@link #setFileSizeMax(long)} on this object, so
+     * there is no need to configure it here.
+     * <em>Note:</em>Changing this value doesn't affect files, that have already been uploaded.
+     * @param pFileSizeMax The maximum size of a single, uploaded file. The value -1 indicates "unlimited".
+     */
+    public void setFileSizeMax(long pFileSizeMax);
+
+    /** Returns the maximum size of the complete HTTP request. A {@link SizeLimitExceededException}
+     * will be thrown, if the HTTP request will exceed this value.
+     * By default, this value will be copied from the {@link FileUploadBase#getSizeMax()
+     * FileUploadBase} object, however, the user may replace the default value with a
+     * request specific value by invoking {@link #setSizeMax(long)} on this object.
+     * @return The maximum size of the complete HTTP requqest. The value -1 indicates "unlimited".
+     */
+    public long getSizeMax();
+
+    /** Returns the maximum size of the complete HTTP request. A {@link SizeLimitExceededException}
+     * will be thrown, if the HTTP request will exceed this value.
+     * By default, this value will be copied from the {@link FileUploadBase#getSizeMax()
+     * FileUploadBase} object, however, the user may replace the default value with a
+     * request specific value by invoking {@link #setSizeMax(long)} on this object.
+     * <em>Note:</em> Setting the maximum size on this object will work only, if the iterator is not
+     * yet initialized. In other words: If the methods {@link #hasNext()}, {@link #next()} have not
+     * yet been invoked.
+     * @param pSizeMax The maximum size of the complete HTTP request. The value -1 indicates "unlimited".
+     */
+    public void setSizeMax(long pSizeMax);
 
     /**
      * Returns, whether another instance of {@link FileItemStream}
@@ -34,7 +78,7 @@ public interface FileItemIterator {
      * @return True, if one or more additional file items
      *   are available, otherwise false.
      */
-    boolean hasNext() throws FileUploadException, IOException;
+    public boolean hasNext() throws FileUploadException, IOException;
 
     /**
      * Returns the next available {@link FileItemStream}.
@@ -47,6 +91,7 @@ public interface FileItemIterator {
      * @return FileItemStream instance, which provides
      *   access to the next file item.
      */
-    FileItemStream next() throws FileUploadException, IOException;
+    public FileItemStream next() throws FileUploadException, IOException;
 
+    public List<FileItem> getFileItems() throws FileUploadException, IOException;
 }
diff --git a/java/org/apache/tomcat/util/http/fileupload/FileUploadBase.java b/java/org/apache/tomcat/util/http/fileupload/FileUploadBase.java
index 5480a33..8869b9e 100644
--- a/java/org/apache/tomcat/util/http/fileupload/FileUploadBase.java
+++ b/java/org/apache/tomcat/util/http/fileupload/FileUploadBase.java
@@ -17,19 +17,18 @@
 package org.apache.tomcat.util.http.fileupload;
 
 import java.io.IOException;
-import java.io.InputStream;
 import java.nio.charset.Charset;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
-import java.util.NoSuchElementException;
 
-import org.apache.tomcat.util.http.fileupload.MultipartStream.ItemInputStream;
-import org.apache.tomcat.util.http.fileupload.util.Closeable;
+import org.apache.tomcat.util.http.fileupload.impl.FileItemIteratorImpl;
+import org.apache.tomcat.util.http.fileupload.impl.FileItemStreamImpl;
+import org.apache.tomcat.util.http.fileupload.impl.FileUploadIOException;
+import org.apache.tomcat.util.http.fileupload.impl.IOFileUploadException;
 import org.apache.tomcat.util.http.fileupload.util.FileItemHeadersImpl;
-import org.apache.tomcat.util.http.fileupload.util.LimitedInputStream;
 import org.apache.tomcat.util.http.fileupload.util.Streams;
 
 
@@ -256,7 +255,7 @@ public abstract class FileUploadBase {
     public FileItemIterator getItemIterator(RequestContext ctx)
     throws FileUploadException, IOException {
         try {
-            return new FileItemIteratorImpl(ctx);
+            return new FileItemIteratorImpl(this, ctx);
         } catch (FileUploadIOException e) {
             // unwrap encapsulated SizeException
             throw (FileUploadException) e.getCause();
@@ -288,7 +287,7 @@ public abstract class FileUploadBase {
             while (iter.hasNext()) {
                 final FileItemStream item = iter.next();
                 // Don't use getName() here to prevent an InvalidFileNameException.
-                final String fileName = ((FileItemIteratorImpl.FileItemStreamImpl) item).name;
+                final String fileName = ((FileItemStreamImpl) item).getName();
                 FileItem fileItem = fac.createItem(item.getFieldName(), item.getContentType(),
                                                    item.isFormField(), fileName);
                 items.add(fileItem);
@@ -366,7 +365,7 @@ public abstract class FileUploadBase {
      *
      * @return The boundary, as a byte array.
      */
-    protected byte[] getBoundary(String contentType) {
+    public byte[] getBoundary(String contentType) {
         ParameterParser parser = new ParameterParser();
         parser.setLowerCaseNames(true);
         // Parameter parser can handle null input
@@ -390,7 +389,7 @@ public abstract class FileUploadBase {
      *
      * @return The file name for the current <code>encapsulation</code>.
      */
-    protected String getFileName(FileItemHeaders headers) {
+    public String getFileName(FileItemHeaders headers) {
         return getFileName(headers.getHeader(CONTENT_DISPOSITION));
     }
 
@@ -433,7 +432,7 @@ public abstract class FileUploadBase {
      *
      * @return The field name for the current <code>encapsulation</code>.
      */
-    protected String getFieldName(FileItemHeaders headers) {
+    public String getFieldName(FileItemHeaders headers) {
         return getFieldName(headers.getHeader(CONTENT_DISPOSITION));
     }
 
@@ -471,7 +470,7 @@ public abstract class FileUploadBase {
      *
      * @return A <code>Map</code> containing the parsed HTTP request headers.
      */
-    protected FileItemHeaders getParsedHeaders(String headerPart) {
+    public FileItemHeaders getParsedHeaders(String headerPart) {
         final int len = headerPart.length();
         FileItemHeadersImpl headers = newFileItemHeaders();
         int start = 0;
@@ -553,693 +552,6 @@ public abstract class FileUploadBase {
     }
 
     /**
-     * The iterator, which is returned by
-     * {@link FileUploadBase#getItemIterator(RequestContext)}.
-     */
-    private class FileItemIteratorImpl implements FileItemIterator {
-
-        /**
-         * Default implementation of {@link FileItemStream}.
-         */
-        class FileItemStreamImpl implements FileItemStream {
-
-            /**
-             * The file items content type.
-             */
-            private final String contentType;
-
-            /**
-             * The file items field name.
-             */
-            private final String fieldName;
-
-            /**
-             * The file items file name.
-             */
-            private final String name;
-
-            /**
-             * Whether the file item is a form field.
-             */
-            private final boolean formField;
-
-            /**
-             * The file items input stream.
-             */
-            private final InputStream stream;
-
-            /**
-             * Whether the file item was already opened.
-             */
-            private boolean opened;
-
-            /**
-             * The headers, if any.
-             */
-            private FileItemHeaders headers;
-
-            /**
-             * Creates a new instance.
-             *
-             * @param pName The items file name, or null.
-             * @param pFieldName The items field name.
-             * @param pContentType The items content type, or null.
-             * @param pFormField Whether the item is a form field.
-             * @param pContentLength The items content length, if known, or -1
-             * @throws IOException Creating the file item failed.
-             */
-            FileItemStreamImpl(String pName, String pFieldName,
-                    String pContentType, boolean pFormField,
-                    long pContentLength) throws IOException {
-                name = pName;
-                fieldName = pFieldName;
-                contentType = pContentType;
-                formField = pFormField;
-                final ItemInputStream itemStream = multi.newInputStream();
-                InputStream istream = itemStream;
-                if (fileSizeMax != -1) {
-                    if (pContentLength != -1
-                            &&  pContentLength > fileSizeMax) {
-                        FileSizeLimitExceededException e =
-                            new FileSizeLimitExceededException(
-                                String.format("The field %s exceeds its maximum permitted size of %s bytes.",
-                                        fieldName, Long.valueOf(fileSizeMax)),
-                                pContentLength, fileSizeMax);
-                        e.setFileName(pName);
-                        e.setFieldName(pFieldName);
-                        throw new FileUploadIOException(e);
-                    }
-                    istream = new LimitedInputStream(istream, fileSizeMax) {
-                        @Override
-                        protected void raiseError(long pSizeMax, long pCount)
-                                throws IOException {
-                            itemStream.close(true);
-                            FileSizeLimitExceededException e =
-                                new FileSizeLimitExceededException(
-                                    String.format("The field %s exceeds its maximum permitted size of %s bytes.",
-                                           fieldName, Long.valueOf(pSizeMax)),
-                                    pCount, pSizeMax);
-                            e.setFieldName(fieldName);
-                            e.setFileName(name);
-                            throw new FileUploadIOException(e);
-                        }
-                    };
-                }
-                stream = istream;
-            }
-
-            /**
-             * Returns the items content type, or null.
-             *
-             * @return Content type, if known, or null.
-             */
-            @Override
-            public String getContentType() {
-                return contentType;
-            }
-
-            /**
-             * Returns the items field name.
-             *
-             * @return Field name.
-             */
-            @Override
-            public String getFieldName() {
-                return fieldName;
-            }
-
-            /**
-             * Returns the items file name.
-             *
-             * @return File name, if known, or null.
-             * @throws InvalidFileNameException The file name contains a NUL character,
-             *   which might be an indicator of a security attack. If you intend to
-             *   use the file name anyways, catch the exception and use
-             *   InvalidFileNameException#getName().
-             */
-            @Override
-            public String getName() {
-                return Streams.checkFileName(name);
-            }
-
-            /**
-             * Returns, whether this is a form field.
-             *
-             * @return True, if the item is a form field,
-             *   otherwise false.
-             */
-            @Override
-            public boolean isFormField() {
-                return formField;
-            }
-
-            /**
-             * Returns an input stream, which may be used to
-             * read the items contents.
-             *
-             * @return Opened input stream.
-             * @throws IOException An I/O error occurred.
-             */
-            @Override
-            public InputStream openStream() throws IOException {
-                if (opened) {
-                    throw new IllegalStateException(
-                            "The stream was already opened.");
-                }
-                if (((Closeable) stream).isClosed()) {
-                    throw new FileItemStream.ItemSkippedException();
-                }
-                return stream;
-            }
-
-            /**
-             * Closes the file item.
-             *
-             * @throws IOException An I/O error occurred.
-             */
-            void close() throws IOException {
-                stream.close();
-            }
-
-            /**
-             * Returns the file item headers.
-             *
-             * @return The items header object
-             */
-            @Override
-            public FileItemHeaders getHeaders() {
-                return headers;
-            }
-
-            /**
-             * Sets the file item headers.
-             *
-             * @param pHeaders The items header object
-             */
-            @Override
-            public void setHeaders(FileItemHeaders pHeaders) {
-                headers = pHeaders;
-            }
-
-        }
-
-        /**
-         * The multi part stream to process.
-         */
-        private final MultipartStream multi;
-
-        /**
-         * The notifier, which used for triggering the
-         * {@link ProgressListener}.
-         */
-        private final MultipartStream.ProgressNotifier notifier;
-
-        /**
-         * The boundary, which separates the various parts.
-         */
-        private final byte[] boundary;
-
-        /**
-         * The item, which we currently process.
-         */
-        private FileItemStreamImpl currentItem;
-
-        /**
-         * The current items field name.
-         */
-        private String currentFieldName;
-
-        /**
-         * Whether we are currently skipping the preamble.
-         */
-        private boolean skipPreamble;
-
-        /**
-         * Whether the current item may still be read.
-         */
-        private boolean itemValid;
-
-        /**
-         * Whether we have seen the end of the file.
-         */
-        private boolean eof;
-
-        /**
-         * Creates a new instance.
-         *
-         * @param ctx The request context.
-         * @throws FileUploadException An error occurred while
-         *   parsing the request.
-         * @throws IOException An I/O error occurred.
-         */
-        FileItemIteratorImpl(RequestContext ctx)
-                throws FileUploadException, IOException {
-            if (ctx == null) {
-                throw new NullPointerException("ctx parameter");
-            }
-
-            String contentType = ctx.getContentType();
-            if ((null == contentType)
-                    || (!contentType.toLowerCase(Locale.ENGLISH).startsWith(MULTIPART))) {
-                throw new InvalidContentTypeException(String.format(
-                        "the request doesn't contain a %s or %s stream, content type header is %s",
-                        MULTIPART_FORM_DATA, MULTIPART_MIXED, contentType));
-            }
-
-
-            final long requestSize = ((UploadContext) ctx).contentLength();
-
-            InputStream input; // N.B. this is eventually closed in MultipartStream processing
-            if (sizeMax >= 0) {
-                if (requestSize != -1 && requestSize > sizeMax) {
-                    throw new SizeLimitExceededException(String.format(
-                            "the request was rejected because its size (%s) exceeds the configured maximum (%s)",
-                            Long.valueOf(requestSize), Long.valueOf(sizeMax)),
-                            requestSize, sizeMax);
-                }
-                // N.B. this is eventually closed in MultipartStream processing
-                input = new LimitedInputStream(ctx.getInputStream(), sizeMax) {
-                    @Override
-                    protected void raiseError(long pSizeMax, long pCount)
-                            throws IOException {
-                        FileUploadException ex = new SizeLimitExceededException(
-                        String.format("the request was rejected because its size (%s) exceeds the configured maximum (%s)",
-                               Long.valueOf(pCount), Long.valueOf(pSizeMax)),
-                               pCount, pSizeMax);
-                        throw new FileUploadIOException(ex);
-                    }
-                };
-            } else {
-                input = ctx.getInputStream();
-            }
-
-            String charEncoding = headerEncoding;
-            if (charEncoding == null) {
-                charEncoding = ctx.getCharacterEncoding();
-            }
-
-            boundary = getBoundary(contentType);
-            if (boundary == null) {
-                IOUtils.closeQuietly(input); // avoid possible resource leak
-                throw new FileUploadException("the request was rejected because no multipart boundary was found");
-            }
-
-            notifier = new MultipartStream.ProgressNotifier(listener, requestSize);
-            try {
-                multi = new MultipartStream(input, boundary, notifier);
-            } catch (IllegalArgumentException iae) {
-                IOUtils.closeQuietly(input); // avoid possible resource leak
-                throw new InvalidContentTypeException(
-                        String.format("The boundary specified in the %s header is too long", CONTENT_TYPE), iae);
-            }
-            multi.setHeaderEncoding(charEncoding);
-
-            skipPreamble = true;
-            findNextItem();
-        }
-
-        /**
-         * Called for finding the next item, if any.
-         *
-         * @return True, if an next item was found, otherwise false.
-         * @throws IOException An I/O error occurred.
-         */
-        private boolean findNextItem() throws IOException {
-            if (eof) {
-                return false;
-            }
-            if (currentItem != null) {
-                currentItem.close();
-                currentItem = null;
-            }
-            for (;;) {
-                boolean nextPart;
-                if (skipPreamble) {
-                    nextPart = multi.skipPreamble();
-                } else {
-                    nextPart = multi.readBoundary();
-                }
-                if (!nextPart) {
-                    if (currentFieldName == null) {
-                        // Outer multipart terminated -> No more data
-                        eof = true;
-                        return false;
-                    }
-                    // Inner multipart terminated -> Return to parsing the outer
-                    multi.setBoundary(boundary);
-                    currentFieldName = null;
-                    continue;
-                }
-                FileItemHeaders headers = getParsedHeaders(multi.readHeaders());
-                if (currentFieldName == null) {
-                    // We're parsing the outer multipart
-                    String fieldName = getFieldName(headers);
-                    if (fieldName != null) {
-                        String subContentType = headers.getHeader(CONTENT_TYPE);
-                        if (subContentType != null
-                                &&  subContentType.toLowerCase(Locale.ENGLISH)
-                                        .startsWith(MULTIPART_MIXED)) {
-                            currentFieldName = fieldName;
-                            // Multiple files associated with this field name
-                            byte[] subBoundary = getBoundary(subContentType);
-                            multi.setBoundary(subBoundary);
-                            skipPreamble = true;
-                            continue;
-                        }
-                        String fileName = getFileName(headers);
-                        currentItem = new FileItemStreamImpl(fileName,
-                                fieldName, headers.getHeader(CONTENT_TYPE),
-                                fileName == null, getContentLength(headers));
-                        currentItem.setHeaders(headers);
-                        notifier.noteItem();
-                        itemValid = true;
-                        return true;
-                    }
-                } else {
-                    String fileName = getFileName(headers);
-                    if (fileName != null) {
-                        currentItem = new FileItemStreamImpl(fileName,
-                                currentFieldName,
-                                headers.getHeader(CONTENT_TYPE),
-                                false, getContentLength(headers));
-                        currentItem.setHeaders(headers);
-                        notifier.noteItem();
-                        itemValid = true;
-                        return true;
-                    }
-                }
-                multi.discardBodyData();
-            }
-        }
-
-        private long getContentLength(FileItemHeaders pHeaders) {
-            try {
-                return Long.parseLong(pHeaders.getHeader(CONTENT_LENGTH));
-            } catch (Exception e) {
-                return -1;
-            }
-        }
-
-        /**
-         * Returns, whether another instance of {@link FileItemStream}
-         * is available.
-         *
-         * @throws FileUploadException Parsing or processing the
-         *   file item failed.
-         * @throws IOException Reading the file item failed.
-         * @return True, if one or more additional file items
-         *   are available, otherwise false.
-         */
-        @Override
-        public boolean hasNext() throws FileUploadException, IOException {
-            if (eof) {
-                return false;
-            }
-            if (itemValid) {
-                return true;
-            }
-            try {
-                return findNextItem();
-            } catch (FileUploadIOException e) {
-                // unwrap encapsulated SizeException
-                throw (FileUploadException) e.getCause();
-            }
-        }
-
-        /**
-         * Returns the next available {@link FileItemStream}.
-         *
-         * @throws java.util.NoSuchElementException No more items are
-         *   available. Use {@link #hasNext()} to prevent this exception.
-         * @throws FileUploadException Parsing or processing the
-         *   file item failed.
-         * @throws IOException Reading the file item failed.
-         * @return FileItemStream instance, which provides
-         *   access to the next file item.
-         */
-        @Override
-        public FileItemStream next() throws FileUploadException, IOException {
-            if (eof  ||  (!itemValid && !hasNext())) {
-                throw new NoSuchElementException();
-            }
-            itemValid = false;
-            return currentItem;
-        }
-
-    }
-
-    /**
-     * This exception is thrown for hiding an inner
-     * {@link FileUploadException} in an {@link IOException}.
-     */
-    public static class FileUploadIOException extends IOException {
-
-        private static final long serialVersionUID = -3082868232248803474L;
-
-        public FileUploadIOException() {
-            super();
-        }
-
-        public FileUploadIOException(String message, Throwable cause) {
-            super(message, cause);
-        }
-
-        public FileUploadIOException(String message) {
-            super(message);
-        }
-
-        public FileUploadIOException(Throwable cause) {
-            super(cause);
-        }
-    }
-
-    /**
-     * Thrown to indicate that the request is not a multipart request.
-     */
-    public static class InvalidContentTypeException
-            extends FileUploadException {
-
-        /**
-         * The exceptions UID, for serializing an instance.
-         */
-        private static final long serialVersionUID = -9073026332015646668L;
-
-        /**
-         * Constructs a <code>InvalidContentTypeException</code> with no
-         * detail message.
-         */
-        public InvalidContentTypeException() {
-            super();
-        }
-
-        /**
-         * Constructs an <code>InvalidContentTypeException</code> with
-         * the specified detail message.
-         *
-         * @param message The detail message.
-         */
-        public InvalidContentTypeException(String message) {
-            super(message);
-        }
-
-        /**
-         * Constructs an <code>InvalidContentTypeException</code> with
-         * the specified detail message and cause.
-         *
-         * @param msg The detail message.
-         * @param cause the original cause
-         *
-         * @since 1.3.1
-         */
-        public InvalidContentTypeException(String msg, Throwable cause) {
-            super(msg, cause);
-        }
-    }
-
-    /**
-     * Thrown to indicate an IOException.
-     */
-    public static class IOFileUploadException extends FileUploadException {
-
-        private static final long serialVersionUID = -5858565745868986701L;
-
-        public IOFileUploadException() {
-            super();
-        }
-
-        public IOFileUploadException(String message, Throwable cause) {
-            super(message, cause);
-        }
-
-        public IOFileUploadException(String message) {
-            super(message);
-        }
-
-        public IOFileUploadException(Throwable cause) {
-            super(cause);
-        }
-    }
-
-    /**
-     * This exception is thrown, if a requests permitted size
-     * is exceeded.
-     */
-    public abstract static class SizeException extends FileUploadException {
-
-        /**
-         * Serial version UID, being used, if serialized.
-         */
-        private static final long serialVersionUID = -8776225574705254126L;
-
-        /**
-         * The actual size of the request.
-         */
-        private final long actual;
-
-        /**
-         * The maximum permitted size of the request.
-         */
-        private final long permitted;
-
-        /**
-         * Creates a new instance.
-         *
-         * @param message The detail message.
-         * @param actual The actual number of bytes in the request.
-         * @param permitted The requests size limit, in bytes.
-         */
-        protected SizeException(String message, long actual, long permitted) {
-            super(message);
-            this.actual = actual;
-            this.permitted = permitted;
-        }
-
-        /**
-         * Retrieves the actual size of the request.
-         *
-         * @return The actual size of the request.
-         * @since 1.3
-         */
-        public long getActualSize() {
-            return actual;
-        }
-
-        /**
-         * Retrieves the permitted size of the request.
-         *
-         * @return The permitted size of the request.
-         * @since 1.3
-         */
-        public long getPermittedSize() {
-            return permitted;
-        }
-
-    }
-
-    /**
-     * Thrown to indicate that the request size exceeds the configured maximum.
-     */
-    public static class SizeLimitExceededException
-            extends SizeException {
-
-        /**
-         * The exceptions UID, for serializing an instance.
-         */
-        private static final long serialVersionUID = -2474893167098052828L;
-
-        /**
-         * Constructs a <code>SizeExceededException</code> with
-         * the specified detail message, and actual and permitted sizes.
-         *
-         * @param message   The detail message.
-         * @param actual    The actual request size.
-         * @param permitted The maximum permitted request size.
-         */
-        public SizeLimitExceededException(String message, long actual,
-                long permitted) {
-            super(message, actual, permitted);
-        }
-
-    }
-
-    /**
-     * Thrown to indicate that A files size exceeds the configured maximum.
-     */
-    public static class FileSizeLimitExceededException
-            extends SizeException {
-
-        /**
-         * The exceptions UID, for serializing an instance.
-         */
-        private static final long serialVersionUID = 8150776562029630058L;
-
-        /**
-         * File name of the item, which caused the exception.
-         */
-        private String fileName;
-
-        /**
-         * Field name of the item, which caused the exception.
-         */
-        private String fieldName;
-
-        /**
-         * Constructs a <code>SizeExceededException</code> with
-         * the specified detail message, and actual and permitted sizes.
-         *
-         * @param message   The detail message.
-         * @param actual    The actual request size.
-         * @param permitted The maximum permitted request size.
-         */
-        public FileSizeLimitExceededException(String message, long actual,
-                long permitted) {
-            super(message, actual, permitted);
-        }
-
-        /**
-         * Returns the file name of the item, which caused the
-         * exception.
-         *
-         * @return File name, if known, or null.
-         */
-        public String getFileName() {
-            return fileName;
-        }
-
-        /**
-         * Sets the file name of the item, which caused the
-         * exception.
-         *
-         * @param pFileName the file name of the item, which caused the exception.
-         */
-        public void setFileName(String pFileName) {
-            fileName = pFileName;
-        }
-
-        /**
-         * Returns the field name of the item, which caused the
-         * exception.
-         *
-         * @return Field name, if known, or null.
-         */
-        public String getFieldName() {
-            return fieldName;
-        }
-
-        /**
-         * Sets the field name of the item, which caused the
-         * exception.
-         *
-         * @param pFieldName the field name of the item,
-         *        which caused the exception.
-         */
-        public void setFieldName(String pFieldName) {
-            fieldName = pFieldName;
-        }
-
-    }
-
-    /**
      * Returns the progress listener.
      *
      * @return The progress listener, if any, or null.
diff --git a/java/org/apache/tomcat/util/http/fileupload/MultipartStream.java b/java/org/apache/tomcat/util/http/fileupload/MultipartStream.java
index 351fa02..c3616c3 100644
--- a/java/org/apache/tomcat/util/http/fileupload/MultipartStream.java
+++ b/java/org/apache/tomcat/util/http/fileupload/MultipartStream.java
@@ -22,7 +22,7 @@ import java.io.InputStream;
 import java.io.OutputStream;
 import java.io.UnsupportedEncodingException;
 
-import org.apache.tomcat.util.http.fileupload.FileUploadBase.FileUploadIOException;
+import org.apache.tomcat.util.http.fileupload.impl.FileUploadIOException;
 import org.apache.tomcat.util.http.fileupload.util.Closeable;
 import org.apache.tomcat.util.http.fileupload.util.Streams;
 
@@ -115,7 +115,7 @@ public class MultipartStream {
          * @param pListener The listener to invoke.
          * @param pContentLength The expected content length.
          */
-        ProgressNotifier(ProgressListener pListener, long pContentLength) {
+        public ProgressNotifier(ProgressListener pListener, long pContentLength) {
             listener = pListener;
             contentLength = pContentLength;
         }
@@ -136,7 +136,7 @@ public class MultipartStream {
         /**
          * Called to indicate, that a new file item has been detected.
          */
-        void noteItem() {
+        public void noteItem() {
             ++items;
             notifyListener();
         }
@@ -332,7 +332,7 @@ public class MultipartStream {
      *
      * @see #MultipartStream(InputStream, byte[], int, ProgressNotifier)
      */
-    MultipartStream(InputStream input,
+    public MultipartStream(InputStream input,
             byte[] boundary,
             ProgressNotifier pNotifier) {
         this(input, boundary, DEFAULT_BUFSIZE, pNotifier);
@@ -576,7 +576,7 @@ public class MultipartStream {
      * Creates a new {@link ItemInputStream}.
      * @return A new instance of {@link ItemInputStream}.
      */
-    ItemInputStream newInputStream() {
+    public ItemInputStream newInputStream() {
         return new ItemInputStream();
     }
 
diff --git a/java/org/apache/tomcat/util/http/fileupload/disk/DiskFileItem.java b/java/org/apache/tomcat/util/http/fileupload/disk/DiskFileItem.java
index e899ef3..ac2eb25 100644
--- a/java/org/apache/tomcat/util/http/fileupload/disk/DiskFileItem.java
+++ b/java/org/apache/tomcat/util/http/fileupload/disk/DiskFileItem.java
@@ -540,7 +540,7 @@ public class DiskFileItem
      * Removes the file contents from the temporary storage.
      */
     @Override
-    protected void finalize() {
+    protected void finalize() throws Throwable {
         if (dfos == null || dfos.isInMemory()) {
             return;
         }
@@ -549,6 +549,7 @@ public class DiskFileItem
         if (outputFile != null && outputFile.exists()) {
             outputFile.delete();
         }
+        super.finalize();
     }
 
     /**
diff --git a/java/org/apache/tomcat/util/http/fileupload/impl/FileItemIteratorImpl.java b/java/org/apache/tomcat/util/http/fileupload/impl/FileItemIteratorImpl.java
new file mode 100644
index 0000000..58b46ca
--- /dev/null
+++ b/java/org/apache/tomcat/util/http/fileupload/impl/FileItemIteratorImpl.java
@@ -0,0 +1,339 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.tomcat.util.http.fileupload.impl;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+import java.util.NoSuchElementException;
+
+import org.apache.tomcat.util.http.fileupload.FileItem;
+import org.apache.tomcat.util.http.fileupload.FileItemHeaders;
+import org.apache.tomcat.util.http.fileupload.FileItemIterator;
+import org.apache.tomcat.util.http.fileupload.FileItemStream;
+import org.apache.tomcat.util.http.fileupload.FileUploadBase;
+import org.apache.tomcat.util.http.fileupload.FileUploadException;
+import org.apache.tomcat.util.http.fileupload.IOUtils;
+import org.apache.tomcat.util.http.fileupload.MultipartStream;
+import org.apache.tomcat.util.http.fileupload.ProgressListener;
+import org.apache.tomcat.util.http.fileupload.RequestContext;
+import org.apache.tomcat.util.http.fileupload.UploadContext;
+import org.apache.tomcat.util.http.fileupload.util.LimitedInputStream;
+
+/**
+ * The iterator, which is returned by
+ * {@link FileUploadBase#getItemIterator(RequestContext)}.
+ */
+public class FileItemIteratorImpl implements FileItemIterator {
+    private final FileUploadBase fileUploadBase;
+    private final RequestContext ctx;
+    private long sizeMax, fileSizeMax;
+
+
+    @Override
+    public long getSizeMax() {
+        return sizeMax;
+    }
+
+    @Override
+    public void setSizeMax(long sizeMax) {
+        this.sizeMax = sizeMax;
+    }
+
+    @Override
+    public long getFileSizeMax() {
+        return fileSizeMax;
+    }
+
+    @Override
+    public void setFileSizeMax(long fileSizeMax) {
+        this.fileSizeMax = fileSizeMax;
+    }
+
+    /**
+     * The multi part stream to process.
+     */
+    private MultipartStream multiPartStream;
+
+    /**
+     * The notifier, which used for triggering the
+     * {@link ProgressListener}.
+     */
+    private MultipartStream.ProgressNotifier progressNotifier;
+
+    /**
+     * The boundary, which separates the various parts.
+     */
+    private byte[] multiPartBoundary;
+
+    /**
+     * The item, which we currently process.
+     */
+    private FileItemStreamImpl currentItem;
+
+    /**
+     * The current items field name.
+     */
+    private String currentFieldName;
+
+    /**
+     * Whether we are currently skipping the preamble.
+     */
+    private boolean skipPreamble;
+
+    /**
+     * Whether the current item may still be read.
+     */
+    private boolean itemValid;
+
+    /**
+     * Whether we have seen the end of the file.
+     */
+    private boolean eof;
+
+    /**
+     * Creates a new instance.
+     *
+     * @param pFileUploadBase Upload instance
+     * @param pRequestContext The request context.
+     * @throws FileUploadException An error occurred while
+     *   parsing the request.
+     * @throws IOException An I/O error occurred.
+     */
+    public FileItemIteratorImpl(FileUploadBase pFileUploadBase, RequestContext pRequestContext)
+            throws FileUploadException, IOException {
+        fileUploadBase = pFileUploadBase;
+        sizeMax = fileUploadBase.getSizeMax();
+        fileSizeMax = fileUploadBase.getFileSizeMax();
+        ctx = pRequestContext;
+        if (ctx == null) {
+            throw new NullPointerException("ctx parameter");
+        }
+
+
+        skipPreamble = true;
+        findNextItem();
+    }
+
+    protected void init(FileUploadBase fileUploadBase, @SuppressWarnings("unused") RequestContext pRequestContext)
+            throws FileUploadException, IOException {
+        String contentType = ctx.getContentType();
+        if ((null == contentType)
+                || (!contentType.toLowerCase(Locale.ENGLISH).startsWith(FileUploadBase.MULTIPART))) {
+            throw new InvalidContentTypeException(
+                    String.format("the request doesn't contain a %s or %s stream, content type header is %s",
+                           FileUploadBase.MULTIPART_FORM_DATA, FileUploadBase.MULTIPART_MIXED, contentType));
+        }
+
+        final long requestSize = ((UploadContext) ctx).contentLength();
+
+        InputStream input; // N.B. this is eventually closed in MultipartStream processing
+        if (sizeMax >= 0) {
+            if (requestSize != -1 && requestSize > sizeMax) {
+                throw new SizeLimitExceededException(
+                    String.format("the request was rejected because its size (%s) exceeds the configured maximum (%s)",
+                            Long.valueOf(requestSize), Long.valueOf(sizeMax)),
+                           requestSize, sizeMax);
+            }
+            // N.B. this is eventually closed in MultipartStream processing
+            input = new LimitedInputStream(ctx.getInputStream(), sizeMax) {
+                @Override
+                protected void raiseError(long pSizeMax, long pCount)
+                        throws IOException {
+                    FileUploadException ex = new SizeLimitExceededException(
+                    String.format("the request was rejected because its size (%s) exceeds the configured maximum (%s)",
+                            Long.valueOf(pCount), Long.valueOf(pSizeMax)),
+                           pCount, pSizeMax);
+                    throw new FileUploadIOException(ex);
+                }
+            };
+        } else {
+            input = ctx.getInputStream();
+        }
+
+        String charEncoding = fileUploadBase.getHeaderEncoding();
+        if (charEncoding == null) {
+            charEncoding = ctx.getCharacterEncoding();
+        }
+
+        multiPartBoundary = fileUploadBase.getBoundary(contentType);
+        if (multiPartBoundary == null) {
+            IOUtils.closeQuietly(input); // avoid possible resource leak
+            throw new FileUploadException("the request was rejected because no multipart boundary was found");
+        }
+
+        progressNotifier = new MultipartStream.ProgressNotifier(fileUploadBase.getProgressListener(), requestSize);
+        try {
+            multiPartStream = new MultipartStream(input, multiPartBoundary, progressNotifier);
+        } catch (IllegalArgumentException iae) {
+            IOUtils.closeQuietly(input); // avoid possible resource leak
+            throw new InvalidContentTypeException(
+                    String.format("The boundary specified in the %s header is too long", FileUploadBase.CONTENT_TYPE), iae);
+        }
+        multiPartStream.setHeaderEncoding(charEncoding);
+    }
+
+    public MultipartStream getMultiPartStream() throws FileUploadException, IOException {
+        if (multiPartStream == null) {
+            init(fileUploadBase, ctx);
+        }
+        return multiPartStream;
+    }
+
+    /**
+     * Called for finding the next item, if any.
+     *
+     * @return True, if an next item was found, otherwise false.
+     * @throws IOException An I/O error occurred.
+     */
+    private boolean findNextItem() throws FileUploadException, IOException {
+        if (eof) {
+            return false;
+        }
+        if (currentItem != null) {
+            currentItem.close();
+            currentItem = null;
+        }
+        final MultipartStream multi = getMultiPartStream();
+        for (;;) {
+            boolean nextPart;
+            if (skipPreamble) {
+                nextPart = multi.skipPreamble();
+            } else {
+                nextPart = multi.readBoundary();
+            }
+            if (!nextPart) {
+                if (currentFieldName == null) {
+                    // Outer multipart terminated -> No more data
+                    eof = true;
+                    return false;
+                }
+                // Inner multipart terminated -> Return to parsing the outer
+                multi.setBoundary(multiPartBoundary);
+                currentFieldName = null;
+                continue;
+            }
+            FileItemHeaders headers = fileUploadBase.getParsedHeaders(multi.readHeaders());
+            if (currentFieldName == null) {
+                // We're parsing the outer multipart
+                String fieldName = fileUploadBase.getFieldName(headers);
+                if (fieldName != null) {
+                    String subContentType = headers.getHeader(FileUploadBase.CONTENT_TYPE);
+                    if (subContentType != null
+                            &&  subContentType.toLowerCase(Locale.ENGLISH)
+                                    .startsWith(FileUploadBase.MULTIPART_MIXED)) {
+                        currentFieldName = fieldName;
+                        // Multiple files associated with this field name
+                        byte[] subBoundary = fileUploadBase.getBoundary(subContentType);
+                        multi.setBoundary(subBoundary);
+                        skipPreamble = true;
+                        continue;
+                    }
+                    String fileName = fileUploadBase.getFileName(headers);
+                    currentItem = new FileItemStreamImpl(this, fileName,
+                            fieldName, headers.getHeader(FileUploadBase.CONTENT_TYPE),
+                            fileName == null, getContentLength(headers));
+                    currentItem.setHeaders(headers);
+                    progressNotifier.noteItem();
+                    itemValid = true;
+                    return true;
+                }
+            } else {
+                String fileName = fileUploadBase.getFileName(headers);
+                if (fileName != null) {
+                    currentItem = new FileItemStreamImpl(this, fileName,
+                            currentFieldName,
+                            headers.getHeader(FileUploadBase.CONTENT_TYPE),
+                            false, getContentLength(headers));
+                    currentItem.setHeaders(headers);
+                    progressNotifier.noteItem();
+                    itemValid = true;
+                    return true;
+                }
+            }
+            multi.discardBodyData();
+        }
+    }
+
+    private long getContentLength(FileItemHeaders pHeaders) {
+        try {
+            return Long.parseLong(pHeaders.getHeader(FileUploadBase.CONTENT_LENGTH));
+        } catch (Exception e) {
+            return -1;
+        }
+    }
+
+    /**
+     * Returns, whether another instance of {@link FileItemStream}
+     * is available.
+     *
+     * @throws FileUploadException Parsing or processing the
+     *   file item failed.
+     * @throws IOException Reading the file item failed.
+     * @return True, if one or more additional file items
+     *   are available, otherwise false.
+     */
+    @Override
+    public boolean hasNext() throws FileUploadException, IOException {
+        if (eof) {
+            return false;
+        }
+        if (itemValid) {
+            return true;
+        }
+        try {
+            return findNextItem();
+        } catch (FileUploadIOException e) {
+            // unwrap encapsulated SizeException
+            throw (FileUploadException) e.getCause();
+        }
+    }
+
+    /**
+     * Returns the next available {@link FileItemStream}.
+     *
+     * @throws java.util.NoSuchElementException No more items are
+     *   available. Use {@link #hasNext()} to prevent this exception.
+     * @throws FileUploadException Parsing or processing the
+     *   file item failed.
+     * @throws IOException Reading the file item failed.
+     * @return FileItemStream instance, which provides
+     *   access to the next file item.
+     */
+    @Override
+    public FileItemStream next() throws FileUploadException, IOException {
+        if (eof  ||  (!itemValid && !hasNext())) {
+            throw new NoSuchElementException();
+        }
+        itemValid = false;
+        return currentItem;
+    }
+
+    @Override
+    public List<FileItem> getFileItems() throws FileUploadException, IOException {
+        final List<FileItem> items = new ArrayList<FileItem>();
+        while (hasNext()) {
+            final FileItemStream fis = next();
+            final FileItem fi = fileUploadBase.getFileItemFactory().createItem(fis.getFieldName(), fis.getContentType(), fis.isFormField(), fis.getName());
+            items.add(fi);
+        }
+        return items;
+    }
+
+}
\ No newline at end of file
diff --git a/java/org/apache/tomcat/util/http/fileupload/impl/FileItemStreamImpl.java b/java/org/apache/tomcat/util/http/fileupload/impl/FileItemStreamImpl.java
new file mode 100644
index 0000000..29427e6
--- /dev/null
+++ b/java/org/apache/tomcat/util/http/fileupload/impl/FileItemStreamImpl.java
@@ -0,0 +1,222 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.tomcat.util.http.fileupload.impl;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.apache.tomcat.util.http.fileupload.FileItemHeaders;
+import org.apache.tomcat.util.http.fileupload.FileItemStream;
+import org.apache.tomcat.util.http.fileupload.FileUploadException;
+import org.apache.tomcat.util.http.fileupload.InvalidFileNameException;
+import org.apache.tomcat.util.http.fileupload.MultipartStream.ItemInputStream;
+import org.apache.tomcat.util.http.fileupload.util.Closeable;
+import org.apache.tomcat.util.http.fileupload.util.LimitedInputStream;
+import org.apache.tomcat.util.http.fileupload.util.Streams;
+
+
+/**
+ * Default implementation of {@link FileItemStream}.
+ */
+public class FileItemStreamImpl implements FileItemStream {
+    private final FileItemIteratorImpl fileItemIteratorImpl;
+
+    /**
+     * The file items content type.
+     */
+    private final String contentType;
+
+    /**
+     * The file items field name.
+     */
+    private final String fieldName;
+
+    /**
+     * The file items file name.
+     */
+    final String name;
+
+    /**
+     * Whether the file item is a form field.
+     */
+    private final boolean formField;
+
+    /**
+     * The file items input stream.
+     */
+    private final InputStream stream;
+
+    /**
+     * Whether the file item was already opened.
+     */
+    private boolean opened;
+
+    /**
+     * The headers, if any.
+     */
+    private FileItemHeaders headers;
+
+    /**
+     * Creates a new instance.
+     * @param pFileItemIterator Iterator for all files in this upload
+     * @param pName The items file name, or null.
+     * @param pFieldName The items field name.
+     * @param pContentType The items content type, or null.
+     * @param pFormField Whether the item is a form field.
+     * @param pContentLength The items content length, if known, or -1
+     * @throws FileUploadException If an error is encountered processing the request
+     * @throws IOException Creating the file item failed.
+     */
+    public FileItemStreamImpl(FileItemIteratorImpl pFileItemIterator, String pName, String pFieldName,
+            String pContentType, boolean pFormField,
+            long pContentLength) throws FileUploadException, IOException {
+        fileItemIteratorImpl = pFileItemIterator;
+        name = pName;
+        fieldName = pFieldName;
+        contentType = pContentType;
+        formField = pFormField;
+        final long fileSizeMax = fileItemIteratorImpl.getFileSizeMax();
+        if (fileSizeMax != -1) { // Check if limit is already exceeded
+            if (pContentLength != -1
+                    && pContentLength > fileSizeMax) {
+                FileSizeLimitExceededException e =
+                        new FileSizeLimitExceededException(
+                                String.format("The field %s exceeds its maximum permitted size of %s bytes.",
+                                        fieldName, Long.valueOf(fileSizeMax)),
+                                pContentLength, fileSizeMax);
+                e.setFileName(pName);
+                e.setFieldName(pFieldName);
+                throw new FileUploadIOException(e);
+            }
+        }
+        // OK to construct stream now
+        final ItemInputStream itemStream = fileItemIteratorImpl.getMultiPartStream().newInputStream();
+        InputStream istream = itemStream;
+        if (fileSizeMax != -1) {
+            istream = new LimitedInputStream(istream, fileSizeMax) {
+                @Override
+                protected void raiseError(long pSizeMax, long pCount)
+                        throws IOException {
+                    itemStream.close(true);
+                    FileSizeLimitExceededException e =
+                        new FileSizeLimitExceededException(
+                            String.format("The field %s exceeds its maximum permitted size of %s bytes.",
+                                   fieldName, Long.valueOf(pSizeMax)),
+                            pCount, pSizeMax);
+                    e.setFieldName(fieldName);
+                    e.setFileName(name);
+                    throw new FileUploadIOException(e);
+                }
+            };
+        }
+        stream = istream;
+    }
+
+    /**
+     * Returns the items content type, or null.
+     *
+     * @return Content type, if known, or null.
+     */
+    @Override
+    public String getContentType() {
+        return contentType;
+    }
+
+    /**
+     * Returns the items field name.
+     *
+     * @return Field name.
+     */
+    @Override
+    public String getFieldName() {
+        return fieldName;
+    }
+
+    /**
+     * Returns the items file name.
+     *
+     * @return File name, if known, or null.
+     * @throws InvalidFileNameException The file name contains a NUL character,
+     *   which might be an indicator of a security attack. If you intend to
+     *   use the file name anyways, catch the exception and use
+     *   InvalidFileNameException#getName().
+     */
+    @Override
+    public String getName() {
+        return Streams.checkFileName(name);
+    }
+
+    /**
+     * Returns, whether this is a form field.
+     *
+     * @return True, if the item is a form field,
+     *   otherwise false.
+     */
+    @Override
+    public boolean isFormField() {
+        return formField;
+    }
+
+    /**
+     * Returns an input stream, which may be used to
+     * read the items contents.
+     *
+     * @return Opened input stream.
+     * @throws IOException An I/O error occurred.
+     */
+    @Override
+    public InputStream openStream() throws IOException {
+        if (opened) {
+            throw new IllegalStateException(
+                    "The stream was already opened.");
+        }
+        if (((Closeable) stream).isClosed()) {
+            throw new FileItemStream.ItemSkippedException();
+        }
+        return stream;
+    }
+
+    /**
+     * Closes the file item.
+     *
+     * @throws IOException An I/O error occurred.
+     */
+    public void close() throws IOException {
+        stream.close();
+    }
+
+    /**
+     * Returns the file item headers.
+     *
+     * @return The items header object
+     */
+    @Override
+    public FileItemHeaders getHeaders() {
+        return headers;
+    }
+
+    /**
+     * Sets the file item headers.
+     *
+     * @param pHeaders The items header object
+     */
+    @Override
+    public void setHeaders(FileItemHeaders pHeaders) {
+        headers = pHeaders;
+    }
+
+}
\ No newline at end of file
diff --git a/java/org/apache/tomcat/util/http/fileupload/impl/FileSizeLimitExceededException.java b/java/org/apache/tomcat/util/http/fileupload/impl/FileSizeLimitExceededException.java
new file mode 100644
index 0000000..3eaa9d8
--- /dev/null
+++ b/java/org/apache/tomcat/util/http/fileupload/impl/FileSizeLimitExceededException.java
@@ -0,0 +1,94 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.tomcat.util.http.fileupload.impl;
+
+/**
+ * Thrown to indicate that A files size exceeds the configured maximum.
+ */
+public class FileSizeLimitExceededException
+        extends SizeException {
+
+    /**
+     * The exceptions UID, for serializing an instance.
+     */
+    private static final long serialVersionUID = 8150776562029630058L;
+
+    /**
+     * File name of the item, which caused the exception.
+     */
+    private String fileName;
+
+    /**
+     * Field name of the item, which caused the exception.
+     */
+    private String fieldName;
+
+    /**
+     * Constructs a <code>SizeExceededException</code> with
+     * the specified detail message, and actual and permitted sizes.
+     *
+     * @param message   The detail message.
+     * @param actual    The actual request size.
+     * @param permitted The maximum permitted request size.
+     */
+    public FileSizeLimitExceededException(String message, long actual,
+            long permitted) {
+        super(message, actual, permitted);
+    }
+
+    /**
+     * Returns the file name of the item, which caused the
+     * exception.
+     *
+     * @return File name, if known, or null.
+     */
+    public String getFileName() {
+        return fileName;
+    }
+
+    /**
+     * Sets the file name of the item, which caused the
+     * exception.
+     *
+     * @param pFileName the file name of the item, which caused the exception.
+     */
+    public void setFileName(String pFileName) {
+        fileName = pFileName;
+    }
+
+    /**
+     * Returns the field name of the item, which caused the
+     * exception.
+     *
+     * @return Field name, if known, or null.
+     */
+    public String getFieldName() {
+        return fieldName;
+    }
+
+    /**
+     * Sets the field name of the item, which caused the
+     * exception.
+     *
+     * @param pFieldName the field name of the item,
+     *        which caused the exception.
+     */
+    public void setFieldName(String pFieldName) {
+        fieldName = pFieldName;
+    }
+
+}
\ No newline at end of file
diff --git a/java/org/apache/tomcat/util/http/fileupload/impl/FileUploadIOException.java b/java/org/apache/tomcat/util/http/fileupload/impl/FileUploadIOException.java
new file mode 100644
index 0000000..8a4066a
--- /dev/null
+++ b/java/org/apache/tomcat/util/http/fileupload/impl/FileUploadIOException.java
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.tomcat.util.http.fileupload.impl;
+
+import java.io.IOException;
+
+import org.apache.tomcat.util.http.fileupload.FileUploadException;
+
+/**
+ * This exception is thrown for hiding an inner
+ * {@link FileUploadException} in an {@link IOException}.
+ */
+public class FileUploadIOException extends IOException {
+
+    /**
+     * The exceptions UID, for serializing an instance.
+     */
+    private static final long serialVersionUID = -7047616958165584154L;
+
+    /**
+     * The exceptions cause; we overwrite the parent
+     * classes field, which is available since Java
+     * 1.4 only.
+     */
+    private final FileUploadException cause;
+
+    /**
+     * Creates a <code>FileUploadIOException</code> with the
+     * given cause.
+     *
+     * @param pCause The exceptions cause, if any, or null.
+     */
+    public FileUploadIOException(FileUploadException pCause) {
+        // We're not doing super(pCause) cause of 1.3 compatibility.
+        cause = pCause;
+    }
+
+    /**
+     * Returns the exceptions cause.
+     *
+     * @return The exceptions cause, if any, or null.
+     */
+    @Override
+    public Throwable getCause() {
+        return cause;
+    }
+
+}
\ No newline at end of file
diff --git a/java/org/apache/tomcat/util/http/fileupload/impl/IOFileUploadException.java b/java/org/apache/tomcat/util/http/fileupload/impl/IOFileUploadException.java
new file mode 100644
index 0000000..e1049c7
--- /dev/null
+++ b/java/org/apache/tomcat/util/http/fileupload/impl/IOFileUploadException.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.tomcat.util.http.fileupload.impl;
+
+import java.io.IOException;
+
+import org.apache.tomcat.util.http.fileupload.FileUploadException;
+
+/**
+ * Thrown to indicate an IOException.
+ */
+public class IOFileUploadException extends FileUploadException {
+
+    /**
+     * The exceptions UID, for serializing an instance.
+     */
+    private static final long serialVersionUID = 1749796615868477269L;
+
+    /**
+     * The exceptions cause; we overwrite the parent
+     * classes field, which is available since Java
+     * 1.4 only.
+     */
+    private final IOException cause;
+
+    /**
+     * Creates a new instance with the given cause.
+     *
+     * @param pMsg The detail message.
+     * @param pException The exceptions cause.
+     */
+    public IOFileUploadException(String pMsg, IOException pException) {
+        super(pMsg);
+        cause = pException;
+    }
+
+    /**
+     * Returns the exceptions cause.
+     *
+     * @return The exceptions cause, if any, or null.
+     */
+    @Override
+    public Throwable getCause() {
+        return cause;
+    }
+
+}
\ No newline at end of file
diff --git a/java/org/apache/tomcat/util/http/fileupload/impl/InvalidContentTypeException.java b/java/org/apache/tomcat/util/http/fileupload/impl/InvalidContentTypeException.java
new file mode 100644
index 0000000..295597b
--- /dev/null
+++ b/java/org/apache/tomcat/util/http/fileupload/impl/InvalidContentTypeException.java
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.tomcat.util.http.fileupload.impl;
+
+import org.apache.tomcat.util.http.fileupload.FileUploadException;
+
+/**
+ * Thrown to indicate that the request is not a multipart request.
+ */
+public class InvalidContentTypeException
+        extends FileUploadException {
+
+    /**
+     * The exceptions UID, for serializing an instance.
+     */
+    private static final long serialVersionUID = -9073026332015646668L;
+
+    /**
+     * Constructs a <code>InvalidContentTypeException</code> with no
+     * detail message.
+     */
+    public InvalidContentTypeException() {
+        super();
+    }
+
+    /**
+     * Constructs an <code>InvalidContentTypeException</code> with
+     * the specified detail message.
+     *
+     * @param message The detail message.
+     */
+    public InvalidContentTypeException(String message) {
+        super(message);
+    }
+
+    /**
+     * Constructs an <code>InvalidContentTypeException</code> with
+     * the specified detail message and cause.
+     *
+     * @param msg The detail message.
+     * @param cause the original cause
+     *
+     * @since 1.3.1
+     */
+    public InvalidContentTypeException(String msg, Throwable cause) {
+        super(msg, cause);
+    }
+}
\ No newline at end of file
diff --git a/java/org/apache/tomcat/util/http/fileupload/impl/SizeException.java b/java/org/apache/tomcat/util/http/fileupload/impl/SizeException.java
new file mode 100644
index 0000000..4852795
--- /dev/null
+++ b/java/org/apache/tomcat/util/http/fileupload/impl/SizeException.java
@@ -0,0 +1,75 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.tomcat.util.http.fileupload.impl;
+
+import org.apache.tomcat.util.http.fileupload.FileUploadException;
+
+/**
+ * This exception is thrown, if a requests permitted size
+ * is exceeded.
+ */
+abstract class SizeException extends FileUploadException {
+
+    /**
+     * Serial version UID, being used, if serialized.
+     */
+    private static final long serialVersionUID = -8776225574705254126L;
+
+    /**
+     * The actual size of the request.
+     */
+    private final long actual;
+
+    /**
+     * The maximum permitted size of the request.
+     */
+    private final long permitted;
+
+    /**
+     * Creates a new instance.
+     *
+     * @param message The detail message.
+     * @param actual The actual number of bytes in the request.
+     * @param permitted The requests size limit, in bytes.
+     */
+    protected SizeException(String message, long actual, long permitted) {
+        super(message);
+        this.actual = actual;
+        this.permitted = permitted;
+    }
+
+    /**
+     * Retrieves the actual size of the request.
+     *
+     * @return The actual size of the request.
+     * @since 1.3
+     */
+    public long getActualSize() {
+        return actual;
+    }
+
+    /**
+     * Retrieves the permitted size of the request.
+     *
+     * @return The permitted size of the request.
+     * @since 1.3
+     */
+    public long getPermittedSize() {
+        return permitted;
+    }
+
+}
\ No newline at end of file
diff --git a/java/org/apache/tomcat/util/http/fileupload/impl/SizeLimitExceededException.java b/java/org/apache/tomcat/util/http/fileupload/impl/SizeLimitExceededException.java
new file mode 100644
index 0000000..668e99b
--- /dev/null
+++ b/java/org/apache/tomcat/util/http/fileupload/impl/SizeLimitExceededException.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.tomcat.util.http.fileupload.impl;
+
+/**
+ * Thrown to indicate that the request size exceeds the configured maximum.
+ */
+public class SizeLimitExceededException
+        extends SizeException {
+
+    /**
+     * The exceptions UID, for serializing an instance.
+     */
+    private static final long serialVersionUID = -2474893167098052828L;
+
+    /**
+     * Constructs a <code>SizeExceededException</code> with
+     * the specified detail message, and actual and permitted sizes.
+     *
+     * @param message   The detail message.
+     * @param actual    The actual request size.
+     * @param permitted The maximum permitted request size.
+     */
+    public SizeLimitExceededException(String message, long actual,
+            long permitted) {
+        super(message, actual, permitted);
+    }
+
+}
\ No newline at end of file
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index 1dad7fe..ce55169 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -165,6 +165,10 @@
         Update the internal fork of Apache Commons Codec to 9637dd4 (2019-12-06,
         1.14-SNAPSHOT). Code clean-up and a fix for CODEC-265. (markt)
       </add>
+      <add>
+        Update the internal fork of Apache Commons FileUpload to 2317552
+        (2019-12-06, 2.0-SNAPSHOT). Refactoring. (markt)
+      </add>
     </changelog>
   </subsection>
 </section>


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


[tomcat] 07/14: Clean-up. No functional change.

Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

markt pushed a commit to branch 7.0.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git

commit aa6e0f053cd44225bfad5dc555c6e2b276034e2a
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Thu Dec 5 19:59:47 2019 +0000

    Clean-up. No functional change.
---
 .../apache/catalina/authenticator/Constants.java   | 40 ++++++----------------
 1 file changed, 10 insertions(+), 30 deletions(-)

diff --git a/java/org/apache/catalina/authenticator/Constants.java b/java/org/apache/catalina/authenticator/Constants.java
index 48329c5..b8e03cd 100644
--- a/java/org/apache/catalina/authenticator/Constants.java
+++ b/java/org/apache/catalina/authenticator/Constants.java
@@ -14,11 +14,8 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
-
 package org.apache.catalina.authenticator;
 
-
 public class Constants {
 
     public static final String Package = "org.apache.catalina.authenticator";
@@ -61,23 +58,18 @@ public class Constants {
     // SPNEGO authentication constants
     public static final String KRB5_CONF_PROPERTY = "java.security.krb5.conf";
     public static final String DEFAULT_KRB5_CONF = "conf/krb5.ini";
-    public static final String JAAS_CONF_PROPERTY =
-            "java.security.auth.login.config";
+    public static final String JAAS_CONF_PROPERTY = "java.security.auth.login.config";
     public static final String DEFAULT_JAAS_CONF = "conf/jaas.conf";
-    public static final String DEFAULT_LOGIN_MODULE_NAME =
-        "com.sun.security.jgss.krb5.accept";
+    public static final String DEFAULT_LOGIN_MODULE_NAME = "com.sun.security.jgss.krb5.accept";
     /**
      * @deprecated Unused. Will be removed in Tomcat 9.
      */
     @Deprecated
-    public static final String USE_SUBJECT_CREDS_ONLY_PROPERTY =
-            "javax.security.auth.useSubjectCredsOnly";
+    public static final String USE_SUBJECT_CREDS_ONLY_PROPERTY = "javax.security.auth.useSubjectCredsOnly";
 
     // Cookie name for single sign on support
-    public static final String SINGLE_SIGN_ON_COOKIE =
-        System.getProperty(
-                "org.apache.catalina.authenticator.Constants.SSO_SESSION_COOKIE_NAME",
-                "JSESSIONIDSSO");
+    public static final String SINGLE_SIGN_ON_COOKIE = System.getProperty(
+            "org.apache.catalina.authenticator.Constants.SSO_SESSION_COOKIE_NAME", "JSESSIONIDSSO");
 
 
     // --------------------------------------------------------- Request Notes
@@ -86,13 +78,11 @@ public class Constants {
      * The notes key to track the single-sign-on identity with which this
      * request is associated.
      */
-    public static final String REQ_SSOID_NOTE =
-            "org.apache.catalina.request.SSOID";
+    public static final String REQ_SSOID_NOTE = "org.apache.catalina.request.SSOID";
 
 
     // ---------------------------------------------------------- Session Notes
 
-
     /**
      * If the <code>cache</code> property of our authenticator is set, and
      * the current request is part of a session, authentication information
@@ -100,19 +90,15 @@ public class Constants {
      * <code>Realm.authenticate()</code>, under the following keys:
      */
 
-
     /**
      * The notes key for the password used to authenticate this user.
      */
-    public static final String SESS_PASSWORD_NOTE =
-      "org.apache.catalina.session.PASSWORD";
-
+    public static final String SESS_PASSWORD_NOTE = "org.apache.catalina.session.PASSWORD";
 
     /**
      * The notes key for the username used to authenticate this user.
      */
-    public static final String SESS_USERNAME_NOTE =
-      "org.apache.catalina.session.USERNAME";
+    public static final String SESS_USERNAME_NOTE = "org.apache.catalina.session.USERNAME";
 
 
     /**
@@ -120,20 +106,14 @@ public class Constants {
      * cache required information prior to the completion of authentication.
      */
 
-
     /**
      * The previously authenticated principal (if caching is disabled).
      */
-    public static final String FORM_PRINCIPAL_NOTE =
-        "org.apache.catalina.authenticator.PRINCIPAL";
-
+    public static final String FORM_PRINCIPAL_NOTE = "org.apache.catalina.authenticator.PRINCIPAL";
 
     /**
      * The original request information, to which the user will be
      * redirected if authentication succeeds.
      */
-    public static final String FORM_REQUEST_NOTE =
-        "org.apache.catalina.authenticator.REQUEST";
-
-
+    public static final String FORM_REQUEST_NOTE = "org.apache.catalina.authenticator.REQUEST";
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


[tomcat] 11/14: Harden the FORM authentication process

Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

markt pushed a commit to branch 7.0.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git

commit be6b4731c287d1e340f1ecc8d76d3d26e8c2a529
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Thu Dec 5 23:01:42 2019 +0000

    Harden the FORM authentication process
    
    When the session ID is configured to change on authentication, track the
    expected session ID through the authentication process and ensure that
    the expected value is seen at each stage.
---
 .../catalina/authenticator/AuthenticatorBase.java    |  6 +++++-
 .../org/apache/catalina/authenticator/Constants.java |  6 ++++++
 .../catalina/authenticator/FormAuthenticator.java    | 20 +++++++++++++++++++-
 3 files changed, 30 insertions(+), 2 deletions(-)

diff --git a/java/org/apache/catalina/authenticator/AuthenticatorBase.java b/java/org/apache/catalina/authenticator/AuthenticatorBase.java
index 6d5232e..52bff92 100644
--- a/java/org/apache/catalina/authenticator/AuthenticatorBase.java
+++ b/java/org/apache/catalina/authenticator/AuthenticatorBase.java
@@ -907,7 +907,11 @@ public abstract class AuthenticatorBase extends ValveBase
             // If the principal is null then this is a logout. No need to change
             // the session ID. See BZ 59043.
             if (getChangeSessionIdOnAuthentication() && principal != null) {
-                changeSessionID(request, session);
+                String newSessionId = changeSessionID(request, session);
+                // If the current session ID is being tracked, update it.
+                if (session.getNote(Constants.SESSION_ID_NOTE) != null) {
+                    session.setNote(Constants.SESSION_ID_NOTE, newSessionId);
+                }
             }
         } else if (alwaysUseSession) {
             session = request.getSessionInternal(true);
diff --git a/java/org/apache/catalina/authenticator/Constants.java b/java/org/apache/catalina/authenticator/Constants.java
index e13dc55..3f8fca4 100644
--- a/java/org/apache/catalina/authenticator/Constants.java
+++ b/java/org/apache/catalina/authenticator/Constants.java
@@ -84,6 +84,12 @@ public class Constants {
     // ---------------------------------------------------------- Session Notes
 
     /**
+     * The session id used as a CSRF marker when redirecting a user's request.
+     */
+    public static final String SESSION_ID_NOTE = "org.apache.catalina.authenticator.SESSION_ID";
+
+
+    /**
      * If the <code>cache</code> property of our authenticator is set, and
      * the current request is part of a session, authentication information
      * will be cached to avoid the need for repeated calls to
diff --git a/java/org/apache/catalina/authenticator/FormAuthenticator.java b/java/org/apache/catalina/authenticator/FormAuthenticator.java
index 1354ce2..1204d4c 100644
--- a/java/org/apache/catalina/authenticator/FormAuthenticator.java
+++ b/java/org/apache/catalina/authenticator/FormAuthenticator.java
@@ -272,6 +272,14 @@ public class FormAuthenticator
         if (session == null) {
             session = request.getSessionInternal(false);
         }
+        if (session != null && getChangeSessionIdOnAuthentication()) {
+            // Does session id match?
+            String expectedSessionId = (String) session.getNote(Constants.SESSION_ID_NOTE);
+            if (expectedSessionId == null || !expectedSessionId.equals(request.getRequestedSessionId())) {
+                session.expire();
+                session = null;
+            }
+        }
         if (session == null) {
             if (containerLog.isDebugEnabled()) {
                 containerLog.debug("User took so long to log on the session expired");
@@ -395,7 +403,8 @@ public class FormAuthenticator
         if (getChangeSessionIdOnAuthentication()) {
             Session session = request.getSessionInternal(false);
             if (session != null) {
-                changeSessionID(request, session);
+                String newSessionId = changeSessionID(request, session);
+                session.setNote(Constants.SESSION_ID_NOTE, newSessionId);
             }
         }
 
@@ -492,6 +501,14 @@ public class FormAuthenticator
             return false;
         }
 
+        // Does session id match?
+        if (getChangeSessionIdOnAuthentication()) {
+            String expectedSessionId = (String) session.getNote(Constants.SESSION_ID_NOTE);
+            if (expectedSessionId == null || !expectedSessionId.equals(request.getRequestedSessionId())) {
+                return false;
+            }
+        }
+
         // Does the request URI match?
         String decodedRequestURI = request.getDecodedRequestURI();
         if (decodedRequestURI == null) {
@@ -518,6 +535,7 @@ public class FormAuthenticator
         // Retrieve and remove the SavedRequest object from our session
         SavedRequest saved = (SavedRequest) session.getNote(Constants.FORM_REQUEST_NOTE);
         session.removeNote(Constants.FORM_REQUEST_NOTE);
+        session.removeNote(Constants.SESSION_ID_NOTE);
         if (saved == null) {
             return false;
         }


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


[tomcat] 06/14: Fix FileUpload

Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

markt pushed a commit to branch 7.0.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git

commit f4322c63f501bd6cd3ae31ae84309bf561ae9794
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Fri Dec 6 18:59:59 2019 +0000

    Fix FileUpload
---
 java/org/apache/catalina/connector/Request.java                     | 4 ++--
 java/org/apache/tomcat/util/http/fileupload/impl/SizeException.java | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/java/org/apache/catalina/connector/Request.java b/java/org/apache/catalina/connector/Request.java
index 954c0a2..a0726ee 100644
--- a/java/org/apache/catalina/connector/Request.java
+++ b/java/org/apache/catalina/connector/Request.java
@@ -97,7 +97,7 @@ import org.apache.tomcat.util.http.fileupload.FileItem;
 import org.apache.tomcat.util.http.fileupload.FileUploadException;
 import org.apache.tomcat.util.http.fileupload.disk.DiskFileItemFactory;
 import org.apache.tomcat.util.http.fileupload.impl.InvalidContentTypeException;
-import org.apache.tomcat.util.http.fileupload.impl.SizeLimitExceededException;
+import org.apache.tomcat.util.http.fileupload.impl.SizeException;
 import org.apache.tomcat.util.http.fileupload.servlet.ServletFileUpload;
 import org.apache.tomcat.util.http.fileupload.servlet.ServletRequestContext;
 import org.apache.tomcat.util.http.mapper.MappingData;
@@ -2996,7 +2996,7 @@ public class Request implements HttpServletRequest {
             } catch (InvalidContentTypeException e) {
                 parameters.setParseFailedReason(FailReason.INVALID_CONTENT_TYPE);
                 partsParseException = new ServletException(e);
-            } catch (SizeLimitExceededException e) {
+            } catch (SizeException e) {
                 parameters.setParseFailedReason(FailReason.POST_TOO_LARGE);
                 checkSwallowInput();
                 partsParseException = new IllegalStateException(e);
diff --git a/java/org/apache/tomcat/util/http/fileupload/impl/SizeException.java b/java/org/apache/tomcat/util/http/fileupload/impl/SizeException.java
index 4852795..7928f2d 100644
--- a/java/org/apache/tomcat/util/http/fileupload/impl/SizeException.java
+++ b/java/org/apache/tomcat/util/http/fileupload/impl/SizeException.java
@@ -22,7 +22,7 @@ import org.apache.tomcat.util.http.fileupload.FileUploadException;
  * This exception is thrown, if a requests permitted size
  * is exceeded.
  */
-abstract class SizeException extends FileUploadException {
+public abstract class SizeException extends FileUploadException {
 
     /**
      * Serial version UID, being used, if serialized.


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


[tomcat] 02/14: Merge in Codec changes to 9637dd4 (2019-12-06, 1.14-SNAPSHOT)

Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

markt pushed a commit to branch 7.0.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git

commit cefae342c15b18868dbbd24a17bb91fe0c37b5db
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Fri Dec 6 14:29:01 2019 +0000

    Merge in Codec changes to 9637dd4 (2019-12-06, 1.14-SNAPSHOT)
---
 .../apache/tomcat/util/codec/binary/Base64.java    |  28 ++++--
 .../tomcat/util/codec/binary/BaseNCodec.java       | 112 ++++++++++++++++++---
 webapps/docs/changelog.xml                         |   4 +
 3 files changed, 119 insertions(+), 25 deletions(-)

diff --git a/java/org/apache/tomcat/util/codec/binary/Base64.java b/java/org/apache/tomcat/util/codec/binary/Base64.java
index 3d40748..ce6311c 100644
--- a/java/org/apache/tomcat/util/codec/binary/Base64.java
+++ b/java/org/apache/tomcat/util/codec/binary/Base64.java
@@ -126,6 +126,10 @@ public class Base64 extends BaseNCodec {
      */
     /** Mask used to extract 6 bits, used when encoding */
     private static final int MASK_6BITS = 0x3f;
+    /** Mask used to extract 4 bits, used when decoding final trailing character. */
+    private static final int MASK_4BITS = 0xf;
+    /** Mask used to extract 2 bits, used when decoding final trailing character. */
+    private static final int MASK_2BITS = 0x3;
 
     // The static final fields above are used for the original static byte[] methods on Base64.
     // The private member fields below are used with the new streaming approach, which requires
@@ -468,12 +472,12 @@ public class Base64 extends BaseNCodec {
                     // TODO not currently tested; perhaps it is impossible?
                     break;
                 case 2 : // 12 bits = 8 + 4
-                    validateCharacter(4, context);
+                    validateCharacter(MASK_4BITS, context);
                     context.ibitWorkArea = context.ibitWorkArea >> 4; // dump the extra 4 bits
                     buffer[context.pos++] = (byte) ((context.ibitWorkArea) & MASK_8BITS);
                     break;
                 case 3 : // 18 bits = 8 + 8 + 2
-                    validateCharacter(2, context);
+                    validateCharacter(MASK_2BITS, context);
                     context.ibitWorkArea = context.ibitWorkArea >> 2; // dump 2 bits
                     buffer[context.pos++] = (byte) ((context.ibitWorkArea >> 8) & MASK_8BITS);
                     buffer[context.pos++] = (byte) ((context.ibitWorkArea) & MASK_8BITS);
@@ -789,20 +793,22 @@ public class Base64 extends BaseNCodec {
 
 
     /**
-     * <p>
-     * Validates whether the character is possible in the context of the set of possible base 64 values.
-     * </p>
+     * Validates whether decoding the final trailing character is possible in the context
+     * of the set of possible base 64 values.
+     *
+     * <p>The character is valid if the lower bits within the provided mask are zero. This
+     * is used to test the final trailing base-64 digit is zero in the bits that will be discarded.
      *
-     * @param numBitsToDrop number of least significant bits to check
+     * @param emptyBitsMask The mask of the lower bits that should be empty
      * @param context the context to be used
      *
      * @throws IllegalArgumentException if the bits being checked contain any non-zero value
      */
-    private long validateCharacter(final int numBitsToDrop, final Context context) {
-        if ((context.ibitWorkArea & numBitsToDrop) != 0) {
-        throw new IllegalArgumentException(
-            "Last encoded character (before the paddings if any) is a valid base 64 alphabet but not a possible value");
+    private static void validateCharacter(final int emptyBitsMask, final Context context) {
+        if ((context.ibitWorkArea & emptyBitsMask) != 0) {
+            throw new IllegalArgumentException(
+                "Last encoded character (before the paddings if any) is a valid base 64 alphabet but not a possible value. " +
+                "Expected the discarded bits to be zero.");
         }
-        return context.ibitWorkArea >> numBitsToDrop;
     }
 }
diff --git a/java/org/apache/tomcat/util/codec/binary/BaseNCodec.java b/java/org/apache/tomcat/util/codec/binary/BaseNCodec.java
index ecc761d..0245942 100644
--- a/java/org/apache/tomcat/util/codec/binary/BaseNCodec.java
+++ b/java/org/apache/tomcat/util/codec/binary/BaseNCodec.java
@@ -143,6 +143,18 @@ public abstract class BaseNCodec implements BinaryEncoder, BinaryDecoder {
      */
     private static final int DEFAULT_BUFFER_SIZE = 128;
 
+    /**
+     * The maximum size buffer to allocate.
+     *
+     * <p>This is set to the same size used in the JDK {@code java.util.ArrayList}:</p>
+     * <blockquote>
+     * Some VMs reserve some header words in an array.
+     * Attempts to allocate larger arrays may result in
+     * OutOfMemoryError: Requested array size exceeds VM limit.
+     * </blockquote>
+     */
+    private static final int MAX_BUFFER_SIZE = Integer.MAX_VALUE - 8;
+
     /** Mask used to extract 8 bits, used in decoding bytes */
     protected static final int MASK_8BITS = 0xff;
 
@@ -172,7 +184,7 @@ public abstract class BaseNCodec implements BinaryEncoder, BinaryDecoder {
     private final int chunkSeparatorLength;
 
     /**
-     * Note <code>lineLength</code> is rounded down to the nearest multiple of {@link #encodedBlockSize}
+     * Note <code>lineLength</code> is rounded down to the nearest multiple of the encoded block size.
      * If <code>chunkSeparatorLength</code> is zero, then chunking is disabled.
      * @param unencodedBlockSize the size of an unencoded block (e.g. Base64 = 3)
      * @param encodedBlockSize the size of an encoded block (e.g. Base64 = 4)
@@ -181,6 +193,20 @@ public abstract class BaseNCodec implements BinaryEncoder, BinaryDecoder {
      */
     protected BaseNCodec(final int unencodedBlockSize, final int encodedBlockSize,
                          final int lineLength, final int chunkSeparatorLength) {
+        this(unencodedBlockSize, encodedBlockSize, lineLength, chunkSeparatorLength, PAD_DEFAULT);
+    }
+
+    /**
+     * Note <code>lineLength</code> is rounded down to the nearest multiple of the encoded block size.
+     * If <code>chunkSeparatorLength</code> is zero, then chunking is disabled.
+     * @param unencodedBlockSize the size of an unencoded block (e.g. Base64 = 3)
+     * @param encodedBlockSize the size of an encoded block (e.g. Base64 = 4)
+     * @param lineLength if &gt; 0, use chunking with a length <code>lineLength</code>
+     * @param chunkSeparatorLength the chunk separator length, if relevant
+     * @param pad byte used as padding byte.
+     */
+    protected BaseNCodec(final int unencodedBlockSize, final int encodedBlockSize,
+                         final int lineLength, final int chunkSeparatorLength, final byte pad) {
         this.unencodedBlockSize = unencodedBlockSize;
         this.encodedBlockSize = encodedBlockSize;
         final boolean useChunking = lineLength > 0 && chunkSeparatorLength > 0;
@@ -211,7 +237,7 @@ public abstract class BaseNCodec implements BinaryEncoder, BinaryDecoder {
     /**
      * Get the default buffer size. Can be overridden.
      *
-     * @return {@link #DEFAULT_BUFFER_SIZE}
+     * @return the default buffer size.
      */
     protected int getDefaultBufferSize() {
         return DEFAULT_BUFFER_SIZE;
@@ -220,18 +246,69 @@ public abstract class BaseNCodec implements BinaryEncoder, BinaryDecoder {
     /**
      * Increases our buffer by the {@link #DEFAULT_BUFFER_RESIZE_FACTOR}.
      * @param context the context to be used
+     * @param minCapacity the minimum required capacity
+     * @return the resized byte[] buffer
+     * @throws OutOfMemoryError if the {@code minCapacity} is negative
      */
-    private byte[] resizeBuffer(final Context context) {
-        if (context.buffer == null) {
-            context.buffer = new byte[getDefaultBufferSize()];
-            context.pos = 0;
-            context.readPos = 0;
-        } else {
-            final byte[] b = new byte[context.buffer.length * DEFAULT_BUFFER_RESIZE_FACTOR];
-            System.arraycopy(context.buffer, 0, b, 0, context.buffer.length);
-            context.buffer = b;
+    private static byte[] resizeBuffer(final Context context, final int minCapacity) {
+        // Overflow-conscious code treats the min and new capacity as unsigned.
+        final int oldCapacity = context.buffer.length;
+        int newCapacity = oldCapacity * DEFAULT_BUFFER_RESIZE_FACTOR;
+        if (compareUnsigned(newCapacity, minCapacity) < 0) {
+            newCapacity = minCapacity;
         }
-        return context.buffer;
+        if (compareUnsigned(newCapacity, MAX_BUFFER_SIZE) > 0) {
+            newCapacity = createPositiveCapacity(minCapacity);
+        }
+
+        final byte[] b = new byte[newCapacity];
+        System.arraycopy(context.buffer, 0, b, 0, context.buffer.length);
+        context.buffer = b;
+        return b;
+    }
+
+    /**
+     * Compares two {@code int} values numerically treating the values
+     * as unsigned. Taken from JDK 1.8.
+     *
+     * <p>TODO: Replace with JDK 1.8 Integer::compareUnsigned(int, int).</p>
+     *
+     * @param  x the first {@code int} to compare
+     * @param  y the second {@code int} to compare
+     * @return the value {@code 0} if {@code x == y}; a value less
+     *         than {@code 0} if {@code x < y} as unsigned values; and
+     *         a value greater than {@code 0} if {@code x > y} as
+     *         unsigned values
+     */
+    private static int compareUnsigned(int x, int y) {
+        return Integer.valueOf(x + Integer.MIN_VALUE).compareTo(Integer.valueOf(y + Integer.MIN_VALUE));
+    }
+
+    /**
+     * Create a positive capacity at least as large the minimum required capacity.
+     * If the minimum capacity is negative then this throws an OutOfMemoryError as no array
+     * can be allocated.
+     *
+     * @param minCapacity the minimum capacity
+     * @return the capacity
+     * @throws OutOfMemoryError if the {@code minCapacity} is negative
+     */
+    private static int createPositiveCapacity(int minCapacity) {
+        if (minCapacity < 0) {
+            // overflow
+            throw new OutOfMemoryError("Unable to allocate array size: " + (minCapacity & 0xffffffffL));
+        }
+        // This is called when we require buffer expansion to a very big array.
+        // Use the conservative maximum buffer size if possible, otherwise the biggest required.
+        //
+        // Note: In this situation JDK 1.8 java.util.ArrayList returns Integer.MAX_VALUE.
+        // This excludes some VMs that can exceed MAX_BUFFER_SIZE but not allocate a full
+        // Integer.MAX_VALUE length array.
+        // The result is that we may have to allocate an array of this size more than once if
+        // the capacity must be expanded again.
+        return (minCapacity > MAX_BUFFER_SIZE) ?
+            minCapacity :
+            MAX_BUFFER_SIZE;
     }
 
     /**
@@ -242,8 +319,15 @@ public abstract class BaseNCodec implements BinaryEncoder, BinaryDecoder {
      * @return the buffer
      */
     protected byte[] ensureBufferSize(final int size, final Context context){
-        if ((context.buffer == null) || (context.buffer.length < context.pos + size)){
-            return resizeBuffer(context);
+        if (context.buffer == null) {
+            context.buffer = new byte[getDefaultBufferSize()];
+            context.pos = 0;
+            context.readPos = 0;
+
+            // Overflow-conscious:
+            // x + y > z  ==  x + y - z > 0
+        } else if (context.pos + size - context.buffer.length > 0) {
+            return resizeBuffer(context, context.pos + size);
         }
         return context.buffer;
     }
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index 2e9cce6..1dad7fe 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -161,6 +161,10 @@
         Update the internal fork of Apache Commons BCEL to ff6941e (2019-12-06,
         6.4.2-dev). Code clean-up only. (markt)
       </add>
+      <add>
+        Update the internal fork of Apache Commons Codec to 9637dd4 (2019-12-06,
+        1.14-SNAPSHOT). Code clean-up and a fix for CODEC-265. (markt)
+      </add>
     </changelog>
   </subsection>
 </section>


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


[tomcat] 05/14: Remove unused code reported by SpotBugs

Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

markt pushed a commit to branch 7.0.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git

commit fea244563927c980c4881d8ae1530dc6f825a09f
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Fri Dec 6 16:49:52 2019 +0000

    Remove unused code reported by SpotBugs
---
 .../tomcat/util/http/fileupload/impl/FileItemStreamImpl.java     | 9 ---------
 1 file changed, 9 deletions(-)

diff --git a/java/org/apache/tomcat/util/http/fileupload/impl/FileItemStreamImpl.java b/java/org/apache/tomcat/util/http/fileupload/impl/FileItemStreamImpl.java
index 29427e6..06bf33e 100644
--- a/java/org/apache/tomcat/util/http/fileupload/impl/FileItemStreamImpl.java
+++ b/java/org/apache/tomcat/util/http/fileupload/impl/FileItemStreamImpl.java
@@ -61,11 +61,6 @@ public class FileItemStreamImpl implements FileItemStream {
     private final InputStream stream;
 
     /**
-     * Whether the file item was already opened.
-     */
-    private boolean opened;
-
-    /**
      * The headers, if any.
      */
     private FileItemHeaders headers;
@@ -180,10 +175,6 @@ public class FileItemStreamImpl implements FileItemStream {
      */
     @Override
     public InputStream openStream() throws IOException {
-        if (opened) {
-            throw new IllegalStateException(
-                    "The stream was already opened.");
-        }
         if (((Closeable) stream).isClosed()) {
             throw new FileItemStream.ItemSkippedException();
         }


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


Re: [tomcat] 13/14: Add an atomic method to rotate session ID and return new value.

Posted by Christopher Schultz <ch...@christopherschultz.net>.
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256

Mark,

On 12/11/19 12:52, Mark Thomas wrote:
> On 11/12/2019 17:46, Christopher Schultz wrote: Mark,
> 
> On 12/7/19 17:30, markt@apache.org wrote:
>>>> This is an automated email from the ASF dual-hosted git 
>>>> repository.
>>>> 
>>>> markt pushed a commit to branch 7.0.x in repository 
>>>> https://gitbox.apache.org/repos/asf/tomcat.git
>>>> 
>>>> commit c06674e09e9f3f43dc0e5c022dc8c311a4285cfd Author: Mark
>>>> Thomas <ma...@apache.org> AuthorDate: Fri Dec 6 12:13:15 2019
>>>> +0000
>>>> 
>>>> Add an atomic method to rotate session ID and return new
>>>> value.
>>>> 
>>>> Use it where possible.
> 
> Shouldn't there be a "synchronized" keyword somewhere in there?
> 
>> Not to solve the problem the commit was intended to solve.
> 
>> Maybe the commit message wasn't worded in the best way to
>> describe what was going on.
> 
>> The key thing here is that the new session ID that was created as
>> a result of this call is the one that is returned to the caller.

Ack.

Thanks,
- -chris

>>>> --- java/org/apache/catalina/connector/Request.java   | 27 
>>>> +++++++++++++++++++++++ 
>>>> java/org/apache/catalina/session/ManagerBase.java | 15 
>>>> +++++++++++-- 2 files changed, 40 insertions(+), 2
>>>> deletions(-)
>>>> 
>>>> diff --git a/java/org/apache/catalina/connector/Request.java 
>>>> b/java/org/apache/catalina/connector/Request.java index 
>>>> a0726ee..ab4e5f0 100644 --- 
>>>> a/java/org/apache/catalina/connector/Request.java +++ 
>>>> b/java/org/apache/catalina/connector/Request.java @@ -74,6
>>>> +74,7 @@ import org.apache.catalina.core.ApplicationPart;
>>>> import 
>>>> org.apache.catalina.core.ApplicationSessionCookieConfig;
>>>> import org.apache.catalina.core.AsyncContextImpl; import 
>>>> org.apache.catalina.realm.GenericPrincipal; +import 
>>>> org.apache.catalina.session.ManagerBase; import 
>>>> org.apache.catalina.util.ParameterMap; import 
>>>> org.apache.catalina.util.RequestUtil; import 
>>>> org.apache.catalina.util.StringParser; @@ -2702,6 +2703,32
>>>> @@ public class Request implements HttpServletRequest { }
>>>> 
>>>> 
>>>> +    public String changeSessionId() { + +        Session
>>>> session = this.getSessionInternal(false); +        if
>>>> (session == null) { + throw new IllegalStateException( + 
>>>> sm.getString("coyoteRequest.changeSessionId")); +        } +
>>>> + Manager manager = this.getContext().getManager(); + +
>>>> String newSessionId = rotateSessionId(manager, session); + 
>>>> this.changeSessionId(newSessionId); + +        return 
>>>> newSessionId; +    } + +    private String
>>>> rotateSessionId(Manager manager, Session session) { +
>>>> if (manager instanceof ManagerBase) { +            return
>>>> ((ManagerBase) manager).rotateSessionId(session); +        }
>>>> else { + // Best we do with the current interface + 
>>>> manager.changeSessionId(session); +            return 
>>>> session.getId(); +        } +    } + /** * @return the
>>>> session associated with this Request, creating one * if
>>>> necessary and requested. diff --git 
>>>> a/java/org/apache/catalina/session/ManagerBase.java 
>>>> b/java/org/apache/catalina/session/ManagerBase.java index 
>>>> e4121a6..8022d08 100644 --- 
>>>> a/java/org/apache/catalina/session/ManagerBase.java +++ 
>>>> b/java/org/apache/catalina/session/ManagerBase.java @@
>>>> -851,9 +851,20 @@ public abstract class ManagerBase extends 
>>>> LifecycleMBeanBase implements Manager
>>>> 
>>>> @Override public void changeSessionId(Session session) { + 
>>>> rotateSessionId(session); +    } + + +    public String 
>>>> rotateSessionId(Session session) { +        String newId = 
>>>> generateSessionId(); +        changeSessionId(session,
>>>> newId); + return newId; +    } + + +    public void
>>>> changeSessionId(Session session, String newId) { String oldId
>>>> = session.getIdInternal(); - 
>>>> session.setId(generateSessionId(), false); -        String
>>>> newId = session.getIdInternal(); +
>>>> session.setId(newId, false); 
>>>> container.fireContainerEvent(Context.CHANGE_SESSION_ID_EVENT,
>>>> new String[] {oldId, newId}); }
>>>> 
>>>> 
>>>> -------------------------------------------------------------------
- --
>>>>
>>>>
>
>>>> 
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
>>>> For additional commands, e-mail: dev-help@tomcat.apache.org
>>>> 
>> 
>> ---------------------------------------------------------------------
>>
>> 
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
>> For additional commands, e-mail: dev-help@tomcat.apache.org
>> 
> 
> ---------------------------------------------------------------------
>
> 
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
> For additional commands, e-mail: dev-help@tomcat.apache.org
> 
-----BEGIN PGP SIGNATURE-----
Comment: Using GnuPG with Thunderbird - https://www.enigmail.net/

iQIzBAEBCAAdFiEEMmKgYcQvxMe7tcJcHPApP6U8pFgFAl3xQToACgkQHPApP6U8
pFg/5BAApLUOHwQXbBxEkEshvmLw/slDMXihnR/ZP5tQuujjnwcjMmGNCTEgdxtI
cMDfRLYBiXhF3T+lOGrdFCnnTHEvXFg3Pbspy5FZobK8vvgR4JOqZa5liYGPG6iq
62b9U2zrMPDihwBQ/qOCD5TwP+r6MeOC1MrLEwWZfCAM+TZlTSZqg6A+M2HMWdj9
X0BR+H2vaUy8m9MrC0TQXYDfYKsJXTOWLHNG7+WviWNN6LJXywxVeaie7X4x687g
hQOvZIu5wU4dcsHUbcH+8Eo1G2HeG9Y61YL2EvzWtDwJ9CF3sX68EV12wDl1oV5M
hEljbWrMuoZrt4/WDIW4QndUUsVJNxTJDnhYxGjocD3o58CI2QcUbhjN7qT3rAWN
4MJtOIGr4HoPDhKbPskibi+yJvK7DLSp5C0xwE+mJFC7vwng3NTchvkhjls7YMs5
MAEUgDOgSP+Nipa6h89WCtzxO557D10dLhdVuqfCeiXcDMOMR8cHz9zel2hfmtHI
4d4WSY+laNnJOxlB1oXMkgmnGicFWz09Hk5jvth+0gkge9+32z9AQ16kcCUGvT5M
i61Vat/tAy9FLf32TFXRVubYLprsRFJRYy/GypBKMIA3Ob3JJ9392bDkcT9F8t9o
6ob43RjrYz1rU7TN13yBz5lyfmkml5BdQiXSm1jm7lgy+gaA9k8=
=zJ3K
-----END PGP SIGNATURE-----

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


Re: [tomcat] 13/14: Add an atomic method to rotate session ID and return new value.

Posted by Mark Thomas <ma...@apache.org>.
On 11/12/2019 17:46, Christopher Schultz wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA256
> 
> Mark,
> 
> On 12/7/19 17:30, markt@apache.org wrote:
>> This is an automated email from the ASF dual-hosted git
>> repository.
>>
>> markt pushed a commit to branch 7.0.x in repository
>> https://gitbox.apache.org/repos/asf/tomcat.git
>>
>> commit c06674e09e9f3f43dc0e5c022dc8c311a4285cfd Author: Mark Thomas
>> <ma...@apache.org> AuthorDate: Fri Dec 6 12:13:15 2019 +0000
>>
>> Add an atomic method to rotate session ID and return new value.
>>
>> Use it where possible.
> 
> Shouldn't there be a "synchronized" keyword somewhere in there?

Not to solve the problem the commit was intended to solve.

Maybe the commit message wasn't worded in the best way to describe what
was going on.

The key thing here is that the new session ID that was created as a
result of this call is the one that is returned to the caller.

Mark


> 
> - -chris
> 
>> --- java/org/apache/catalina/connector/Request.java   | 27
>> +++++++++++++++++++++++ 
>> java/org/apache/catalina/session/ManagerBase.java | 15
>> +++++++++++-- 2 files changed, 40 insertions(+), 2 deletions(-)
>>
>> diff --git a/java/org/apache/catalina/connector/Request.java
>> b/java/org/apache/catalina/connector/Request.java index
>> a0726ee..ab4e5f0 100644 ---
>> a/java/org/apache/catalina/connector/Request.java +++
>> b/java/org/apache/catalina/connector/Request.java @@ -74,6 +74,7 @@
>> import org.apache.catalina.core.ApplicationPart; import
>> org.apache.catalina.core.ApplicationSessionCookieConfig; import
>> org.apache.catalina.core.AsyncContextImpl; import
>> org.apache.catalina.realm.GenericPrincipal; +import
>> org.apache.catalina.session.ManagerBase; import
>> org.apache.catalina.util.ParameterMap; import
>> org.apache.catalina.util.RequestUtil; import
>> org.apache.catalina.util.StringParser; @@ -2702,6 +2703,32 @@
>> public class Request implements HttpServletRequest { }
>>
>>
>> +    public String changeSessionId() { + +        Session session =
>> this.getSessionInternal(false); +        if (session == null) { +
>> throw new IllegalStateException( +
>> sm.getString("coyoteRequest.changeSessionId")); +        } + +
>> Manager manager = this.getContext().getManager(); + +        String
>> newSessionId = rotateSessionId(manager, session); +
>> this.changeSessionId(newSessionId); + +        return
>> newSessionId; +    } + +    private String rotateSessionId(Manager
>> manager, Session session) { +        if (manager instanceof
>> ManagerBase) { +            return ((ManagerBase)
>> manager).rotateSessionId(session); +        } else { +
>> // Best we do with the current interface +
>> manager.changeSessionId(session); +            return
>> session.getId(); +        } +    } + /** * @return the session
>> associated with this Request, creating one * if necessary and
>> requested. diff --git
>> a/java/org/apache/catalina/session/ManagerBase.java
>> b/java/org/apache/catalina/session/ManagerBase.java index
>> e4121a6..8022d08 100644 ---
>> a/java/org/apache/catalina/session/ManagerBase.java +++
>> b/java/org/apache/catalina/session/ManagerBase.java @@ -851,9
>> +851,20 @@ public abstract class ManagerBase extends
>> LifecycleMBeanBase implements Manager
>>
>> @Override public void changeSessionId(Session session) { +
>> rotateSessionId(session); +    } + + +    public String
>> rotateSessionId(Session session) { +        String newId =
>> generateSessionId(); +        changeSessionId(session, newId); +
>> return newId; +    } + + +    public void changeSessionId(Session
>> session, String newId) { String oldId = session.getIdInternal(); -
>> session.setId(generateSessionId(), false); -        String newId =
>> session.getIdInternal(); +        session.setId(newId, false); 
>> container.fireContainerEvent(Context.CHANGE_SESSION_ID_EVENT, new
>> String[] {oldId, newId}); }
>>
>>
>> ---------------------------------------------------------------------
>>
>>
> To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
>> For additional commands, e-mail: dev-help@tomcat.apache.org
>>
> -----BEGIN PGP SIGNATURE-----
> Comment: Using GnuPG with Thunderbird - https://www.enigmail.net/
> 
> iQIzBAEBCAAdFiEEMmKgYcQvxMe7tcJcHPApP6U8pFgFAl3xK2kACgkQHPApP6U8
> pFgyKxAAs1tW1HjrlofSFAD1hPFG8iWITjAF7zuFzH3+gTCyuaQT/V6mD6Ad6xwR
> qrwdM1X4pZLkGYmIz1QOQtpzjAdZyuFRjlLLIlIVOdEj+d2vth3O0GgwSfRcU0PZ
> o4ars/2xeLyK3BD7iU79FfqtzrWlHuzXNtoBoBvy7YSJPvHqJh0Jd7faiiNZtUQ9
> H4zDlKQdBCyuehf5LOCV18iL0FhvwFZBzs09P8BXAwdKjuI5SEj9Tc3DYTAMM6yS
> yc7EztgAg/YXDtV6dDfwHZ5T32apMxqOqH1iTZl6cjUcKlKSvTMoH6EeakyF+DDJ
> W0edlmP9rUTj8Gwu13L5I8T/3G4qu6dV3RGV7BxQmha7gJoafte/TL64v20RkXYw
> qidZ0asGu96d4/VQsCSTmBVIpBDMhxUpmm62dPQpO4aD6bWLOCrAChSvouk0uDCO
> 6eBZhSfFWRo/I3SmPrLpy4/bO8L/JlBWEGr2Oen84iNSBX3K1xqWY35/weOPZhaN
> uoU0xJzICU9umbnSwSECUmNFIfdhhfQ80rc4RWFovCAfcvfbH9V7TU+LQk4WGuhU
> oaezHcAarYvfYXRAtl7ypxwDjeOT0oNonDi8WHkaPdkFo1ZNS2aXxm7fh5jxDIbF
> QSLyDjm35hX2+pJkdgNoKCfVnlWOm2QJUQhhc+i3EiNdksuET8U=
> =qerJ
> -----END PGP SIGNATURE-----
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
> For additional commands, e-mail: dev-help@tomcat.apache.org
> 

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


Re: [tomcat] 13/14: Add an atomic method to rotate session ID and return new value.

Posted by Christopher Schultz <ch...@christopherschultz.net>.
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256

Mark,

On 12/7/19 17:30, markt@apache.org wrote:
> This is an automated email from the ASF dual-hosted git
> repository.
> 
> markt pushed a commit to branch 7.0.x in repository
> https://gitbox.apache.org/repos/asf/tomcat.git
> 
> commit c06674e09e9f3f43dc0e5c022dc8c311a4285cfd Author: Mark Thomas
> <ma...@apache.org> AuthorDate: Fri Dec 6 12:13:15 2019 +0000
> 
> Add an atomic method to rotate session ID and return new value.
> 
> Use it where possible.

Shouldn't there be a "synchronized" keyword somewhere in there?

- -chris

> --- java/org/apache/catalina/connector/Request.java   | 27
> +++++++++++++++++++++++ 
> java/org/apache/catalina/session/ManagerBase.java | 15
> +++++++++++-- 2 files changed, 40 insertions(+), 2 deletions(-)
> 
> diff --git a/java/org/apache/catalina/connector/Request.java
> b/java/org/apache/catalina/connector/Request.java index
> a0726ee..ab4e5f0 100644 ---
> a/java/org/apache/catalina/connector/Request.java +++
> b/java/org/apache/catalina/connector/Request.java @@ -74,6 +74,7 @@
> import org.apache.catalina.core.ApplicationPart; import
> org.apache.catalina.core.ApplicationSessionCookieConfig; import
> org.apache.catalina.core.AsyncContextImpl; import
> org.apache.catalina.realm.GenericPrincipal; +import
> org.apache.catalina.session.ManagerBase; import
> org.apache.catalina.util.ParameterMap; import
> org.apache.catalina.util.RequestUtil; import
> org.apache.catalina.util.StringParser; @@ -2702,6 +2703,32 @@
> public class Request implements HttpServletRequest { }
> 
> 
> +    public String changeSessionId() { + +        Session session =
> this.getSessionInternal(false); +        if (session == null) { +
> throw new IllegalStateException( +
> sm.getString("coyoteRequest.changeSessionId")); +        } + +
> Manager manager = this.getContext().getManager(); + +        String
> newSessionId = rotateSessionId(manager, session); +
> this.changeSessionId(newSessionId); + +        return
> newSessionId; +    } + +    private String rotateSessionId(Manager
> manager, Session session) { +        if (manager instanceof
> ManagerBase) { +            return ((ManagerBase)
> manager).rotateSessionId(session); +        } else { +
> // Best we do with the current interface +
> manager.changeSessionId(session); +            return
> session.getId(); +        } +    } + /** * @return the session
> associated with this Request, creating one * if necessary and
> requested. diff --git
> a/java/org/apache/catalina/session/ManagerBase.java
> b/java/org/apache/catalina/session/ManagerBase.java index
> e4121a6..8022d08 100644 ---
> a/java/org/apache/catalina/session/ManagerBase.java +++
> b/java/org/apache/catalina/session/ManagerBase.java @@ -851,9
> +851,20 @@ public abstract class ManagerBase extends
> LifecycleMBeanBase implements Manager
> 
> @Override public void changeSessionId(Session session) { +
> rotateSessionId(session); +    } + + +    public String
> rotateSessionId(Session session) { +        String newId =
> generateSessionId(); +        changeSessionId(session, newId); +
> return newId; +    } + + +    public void changeSessionId(Session
> session, String newId) { String oldId = session.getIdInternal(); -
> session.setId(generateSessionId(), false); -        String newId =
> session.getIdInternal(); +        session.setId(newId, false); 
> container.fireContainerEvent(Context.CHANGE_SESSION_ID_EVENT, new
> String[] {oldId, newId}); }
> 
> 
> ---------------------------------------------------------------------
>
> 
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
> For additional commands, e-mail: dev-help@tomcat.apache.org
> 
-----BEGIN PGP SIGNATURE-----
Comment: Using GnuPG with Thunderbird - https://www.enigmail.net/

iQIzBAEBCAAdFiEEMmKgYcQvxMe7tcJcHPApP6U8pFgFAl3xK2kACgkQHPApP6U8
pFgyKxAAs1tW1HjrlofSFAD1hPFG8iWITjAF7zuFzH3+gTCyuaQT/V6mD6Ad6xwR
qrwdM1X4pZLkGYmIz1QOQtpzjAdZyuFRjlLLIlIVOdEj+d2vth3O0GgwSfRcU0PZ
o4ars/2xeLyK3BD7iU79FfqtzrWlHuzXNtoBoBvy7YSJPvHqJh0Jd7faiiNZtUQ9
H4zDlKQdBCyuehf5LOCV18iL0FhvwFZBzs09P8BXAwdKjuI5SEj9Tc3DYTAMM6yS
yc7EztgAg/YXDtV6dDfwHZ5T32apMxqOqH1iTZl6cjUcKlKSvTMoH6EeakyF+DDJ
W0edlmP9rUTj8Gwu13L5I8T/3G4qu6dV3RGV7BxQmha7gJoafte/TL64v20RkXYw
qidZ0asGu96d4/VQsCSTmBVIpBDMhxUpmm62dPQpO4aD6bWLOCrAChSvouk0uDCO
6eBZhSfFWRo/I3SmPrLpy4/bO8L/JlBWEGr2Oen84iNSBX3K1xqWY35/weOPZhaN
uoU0xJzICU9umbnSwSECUmNFIfdhhfQ80rc4RWFovCAfcvfbH9V7TU+LQk4WGuhU
oaezHcAarYvfYXRAtl7ypxwDjeOT0oNonDi8WHkaPdkFo1ZNS2aXxm7fh5jxDIbF
QSLyDjm35hX2+pJkdgNoKCfVnlWOm2QJUQhhc+i3EiNdksuET8U=
=qerJ
-----END PGP SIGNATURE-----

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


[tomcat] 13/14: Add an atomic method to rotate session ID and return new value.

Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

markt pushed a commit to branch 7.0.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git

commit c06674e09e9f3f43dc0e5c022dc8c311a4285cfd
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Fri Dec 6 12:13:15 2019 +0000

    Add an atomic method to rotate session ID and return new value.
    
    Use it where possible.
---
 java/org/apache/catalina/connector/Request.java   | 27 +++++++++++++++++++++++
 java/org/apache/catalina/session/ManagerBase.java | 15 +++++++++++--
 2 files changed, 40 insertions(+), 2 deletions(-)

diff --git a/java/org/apache/catalina/connector/Request.java b/java/org/apache/catalina/connector/Request.java
index a0726ee..ab4e5f0 100644
--- a/java/org/apache/catalina/connector/Request.java
+++ b/java/org/apache/catalina/connector/Request.java
@@ -74,6 +74,7 @@ import org.apache.catalina.core.ApplicationPart;
 import org.apache.catalina.core.ApplicationSessionCookieConfig;
 import org.apache.catalina.core.AsyncContextImpl;
 import org.apache.catalina.realm.GenericPrincipal;
+import org.apache.catalina.session.ManagerBase;
 import org.apache.catalina.util.ParameterMap;
 import org.apache.catalina.util.RequestUtil;
 import org.apache.catalina.util.StringParser;
@@ -2702,6 +2703,32 @@ public class Request implements HttpServletRequest {
     }
 
 
+    public String changeSessionId() {
+
+        Session session = this.getSessionInternal(false);
+        if (session == null) {
+            throw new IllegalStateException(
+                sm.getString("coyoteRequest.changeSessionId"));
+        }
+
+        Manager manager = this.getContext().getManager();
+
+        String newSessionId = rotateSessionId(manager, session);
+        this.changeSessionId(newSessionId);
+
+        return newSessionId;
+    }
+
+    private String rotateSessionId(Manager manager, Session session) {
+        if (manager instanceof ManagerBase) {
+            return ((ManagerBase) manager).rotateSessionId(session);
+        } else {
+            // Best we do with the current interface
+            manager.changeSessionId(session);
+            return session.getId();
+        }
+    }
+
     /**
      * @return the session associated with this Request, creating one
      * if necessary and requested.
diff --git a/java/org/apache/catalina/session/ManagerBase.java b/java/org/apache/catalina/session/ManagerBase.java
index e4121a6..8022d08 100644
--- a/java/org/apache/catalina/session/ManagerBase.java
+++ b/java/org/apache/catalina/session/ManagerBase.java
@@ -851,9 +851,20 @@ public abstract class ManagerBase extends LifecycleMBeanBase implements Manager
 
     @Override
     public void changeSessionId(Session session) {
+        rotateSessionId(session);
+    }
+
+
+    public String rotateSessionId(Session session) {
+        String newId = generateSessionId();
+        changeSessionId(session, newId);
+        return newId;
+    }
+
+
+    public void changeSessionId(Session session, String newId) {
         String oldId = session.getIdInternal();
-        session.setId(generateSessionId(), false);
-        String newId = session.getIdInternal();
+        session.setId(newId, false);
         container.fireContainerEvent(Context.CHANGE_SESSION_ID_EVENT,
                 new String[] {oldId, newId});
     }


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


[tomcat] 09/14: Refactor change of session ID to reduce duplicate code

Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

markt pushed a commit to branch 7.0.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git

commit c31917da2d2338731b7406bb52561c3721816b18
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Thu Dec 5 23:11:03 2019 +0000

    Refactor change of session ID to reduce duplicate code
---
 .../catalina/authenticator/AuthenticatorBase.java  | 29 ++++++++++++----------
 .../catalina/authenticator/FormAuthenticator.java  |  5 +---
 2 files changed, 17 insertions(+), 17 deletions(-)

diff --git a/java/org/apache/catalina/authenticator/AuthenticatorBase.java b/java/org/apache/catalina/authenticator/AuthenticatorBase.java
index 6c9e121..5a00864 100644
--- a/java/org/apache/catalina/authenticator/AuthenticatorBase.java
+++ b/java/org/apache/catalina/authenticator/AuthenticatorBase.java
@@ -32,7 +32,6 @@ import org.apache.catalina.Container;
 import org.apache.catalina.Context;
 import org.apache.catalina.Globals;
 import org.apache.catalina.LifecycleException;
-import org.apache.catalina.Manager;
 import org.apache.catalina.Realm;
 import org.apache.catalina.Session;
 import org.apache.catalina.Valve;
@@ -907,18 +906,8 @@ public abstract class AuthenticatorBase extends ValveBase
         if (session != null) {
             // If the principal is null then this is a logout. No need to change
             // the session ID. See BZ 59043.
-            if (changeSessionIdOnAuthentication && principal != null) {
-                String oldId = null;
-                if (log.isDebugEnabled()) {
-                    oldId = session.getId();
-                }
-                Manager manager = request.getContext().getManager();
-                manager.changeSessionId(session);
-                request.changeSessionId(session.getId());
-                if (log.isDebugEnabled()) {
-                    log.debug(sm.getString("authenticator.changeSessionId",
-                            oldId, session.getId()));
-                }
+            if (getChangeSessionIdOnAuthentication() && principal != null) {
+                changeSessionID(request, session);
             }
         } else if (alwaysUseSession) {
             session = request.getSessionInternal(true);
@@ -1005,6 +994,20 @@ public abstract class AuthenticatorBase extends ValveBase
 
     }
 
+
+    protected String changeSessionID(Request request, Session session) {
+        String oldId = null;
+        if (log.isDebugEnabled()) {
+            oldId = session.getId();
+        }
+        String newId = request.changeSessionId();
+        if (log.isDebugEnabled()) {
+            log.debug(sm.getString("authenticator.changeSessionId", oldId, newId));
+        }
+        return newId;
+    }
+
+
     @Override
     public void login(String username, String password, Request request) throws ServletException {
         Principal principal = doLogin(request, username, password);
diff --git a/java/org/apache/catalina/authenticator/FormAuthenticator.java b/java/org/apache/catalina/authenticator/FormAuthenticator.java
index d8551c4..863fd77 100644
--- a/java/org/apache/catalina/authenticator/FormAuthenticator.java
+++ b/java/org/apache/catalina/authenticator/FormAuthenticator.java
@@ -28,7 +28,6 @@ import javax.servlet.http.Cookie;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
-import org.apache.catalina.Manager;
 import org.apache.catalina.Realm;
 import org.apache.catalina.Session;
 import org.apache.catalina.connector.Request;
@@ -410,9 +409,7 @@ public class FormAuthenticator
         if (getChangeSessionIdOnAuthentication()) {
             Session session = request.getSessionInternal(false);
             if (session != null) {
-                Manager manager = request.getContext().getManager();
-                manager.changeSessionId(session);
-                request.changeSessionId(session.getId());
+                changeSessionID(request, session);
             }
         }
 


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


[tomcat] 12/14: Align with 8.5.x to aid back-ports

Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

markt pushed a commit to branch 7.0.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git

commit 11ed237be6c27e035c00cd38c55e398789f2c7ac
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Sat Dec 7 20:58:03 2019 +0000

    Align with 8.5.x to aid back-ports
---
 java/org/apache/catalina/Manager.java              |  43 +++---
 .../catalina/session/LocalStrings.properties       |   1 +
 .../catalina/session/LocalStrings_fr.properties    |   1 +
 .../catalina/session/LocalStrings_ja.properties    |   1 +
 .../catalina/session/LocalStrings_ko.properties    |   1 +
 .../catalina/session/LocalStrings_zh_CN.properties |   1 +
 java/org/apache/catalina/session/ManagerBase.java  | 169 ++++++++++-----------
 7 files changed, 114 insertions(+), 103 deletions(-)

diff --git a/java/org/apache/catalina/Manager.java b/java/org/apache/catalina/Manager.java
index 8322f25..3f02f6e 100644
--- a/java/org/apache/catalina/Manager.java
+++ b/java/org/apache/catalina/Manager.java
@@ -14,15 +14,11 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
-
 package org.apache.catalina;
 
-
 import java.beans.PropertyChangeListener;
 import java.io.IOException;
 
-
 /**
  * A <b>Manager</b> manages the pool of Sessions that are associated with a
  * particular Container.  Different Manager implementations may support
@@ -43,12 +39,12 @@ import java.io.IOException;
  */
 public interface Manager {
 
-
     // ------------------------------------------------------------- Properties
 
-
     /**
-     * Return the Container with which this Manager is associated.
+     * Get the Container with which this Manager is associated.
+     *
+     * @return The associated Container
      */
     public Container getContainer();
 
@@ -71,7 +67,7 @@ public interface Manager {
      * this Manager.
      *
      * @deprecated Ignored. {@link Context#getDistributable()} always takes
-     *             precedence. Will be removed in Tomcat 9.0.x.
+     *             precedence. Will be removed in Tomcat 8.5.x.
      */
     @Deprecated
     public boolean getDistributable();
@@ -85,7 +81,7 @@ public interface Manager {
      * @param distributable The new distributable flag
      *
      * @deprecated Ignored. {@link Context#getDistributable()} always takes
-     *             precedence. Will be removed in Tomcat 9.0.x.
+     *             precedence. Will be removed in Tomcat 8.5.x.
      */
     @Deprecated
     public void setDistributable(boolean distributable);
@@ -104,7 +100,7 @@ public interface Manager {
      * for Sessions created by this Manager.
      *
      * @deprecated Ignored. {@link Context#getSessionTimeout()} always takes
-     *             precedence. Will be removed in Tomcat 9.0.x.
+     *             precedence. Will be removed in Tomcat 8.5.x.
      */
     @Deprecated
     public int getMaxInactiveInterval();
@@ -117,7 +113,7 @@ public interface Manager {
      * @param interval The new default value
      *
      * @deprecated Ignored. {@link Context#getSessionTimeout()} always takes
-     *             precedence. Will be removed in Tomcat 9.0.x.
+     *             precedence. Will be removed in Tomcat 8.5.x.
      */
     @Deprecated
     public void setMaxInactiveInterval(int interval);
@@ -256,9 +252,10 @@ public interface Manager {
      * @return  The current rate (in sessions per minute) of session expiration
      */
     public int getSessionExpireRate();
-    // --------------------------------------------------------- Public Methods
 
 
+    // --------------------------------------------------------- Public Methods
+
     /**
      * Add this Session to the set of active Sessions for this Manager.
      *
@@ -288,6 +285,8 @@ public interface Manager {
      * Get a session from the recycled ones or create a new empty one.
      * The PersistentManager manager does not need to create session data
      * because it reads it from the Store.
+     *
+     * @return An empty Session object
      */
     public Session createEmptySession();
 
@@ -305,6 +304,9 @@ public interface Manager {
      *  method of the returned session.
      * @exception IllegalStateException if a new session cannot be
      *  instantiated for any reason
+     *
+     * @return An empty Session object with the given ID or a newly created
+     *         session ID if none was specified
      */
     public Session createSession(String sessionId);
 
@@ -319,6 +321,9 @@ public interface Manager {
      *  instantiated for any reason
      * @exception IOException if an input/output error occurs while
      *  processing this request
+     *
+     * @return the request session or {@code null} if a session with the
+     *         requested ID could not be found
      */
     public Session findSession(String id) throws IOException;
 
@@ -326,6 +331,8 @@ public interface Manager {
     /**
      * Return the set of active Sessions associated with this Manager.
      * If this Manager has no active Sessions, a zero-length array is returned.
+     *
+     * @return All the currently active sessions managed by this manager
      */
     public Session[] findSessions();
 
@@ -376,13 +383,13 @@ public interface Manager {
      */
     public void unload() throws IOException;
 
-     /**
-      * This method will be invoked by the context/container on a periodic
-      * basis and allows the manager to implement
-      * a method that executes periodic tasks, such as expiring sessions etc.
-      */
-     public void backgroundProcess();
 
+    /**
+     * This method will be invoked by the context/container on a periodic
+     * basis and allows the manager to implement
+     * a method that executes periodic tasks, such as expiring sessions etc.
+     */
+    public void backgroundProcess();
 
 
     /**
diff --git a/java/org/apache/catalina/session/LocalStrings.properties b/java/org/apache/catalina/session/LocalStrings.properties
index 1b55ca9..2429627 100644
--- a/java/org/apache/catalina/session/LocalStrings.properties
+++ b/java/org/apache/catalina/session/LocalStrings.properties
@@ -41,6 +41,7 @@ managerBase.createRandom=Created random number generator for session ID generati
 managerBase.createSession.ise=createSession: Too many active sessions
 managerBase.sessionAttributeNameFilter=Skipped session attribute named [{0}] because it did not match the name filter [{1}]
 managerBase.sessionAttributeValueClassNameFilter=Skipped session attribute named [{0}] because the value type [{1}] did not match the filter [{2}]
+managerBase.sessionNotFound=The session [{0}] was not found
 managerBase.sessionTimeout=Invalid session timeout setting [{0}]
 managerBase.setContextNotNew=It is illegal to call setContext() to change the Context associated with a Manager if the Manager is not in the NEW state
 managerBase.setMaxInactiveIntervalUnused=Manager.setMaxInactiveInterval() is deprecated and calls to this method are ignored. Session timeouts should be configured in web.xml or via Context.setSessionTimeout(int timeoutInMinutes)
diff --git a/java/org/apache/catalina/session/LocalStrings_fr.properties b/java/org/apache/catalina/session/LocalStrings_fr.properties
index eed03cd..066360b 100644
--- a/java/org/apache/catalina/session/LocalStrings_fr.properties
+++ b/java/org/apache/catalina/session/LocalStrings_fr.properties
@@ -39,6 +39,7 @@ fileStore.saving=Sauvegarde de la Session [{0}] vers le fichier [{1}]
 managerBase.createSession.ise="createSession": Trop de sessions actives
 managerBase.sessionAttributeNameFilter=L''attribut de session nommé [{0}] sera sauté car il ne correspond pas au filtre sur les noms [{1}]
 managerBase.sessionAttributeValueClassNameFilter=L''attribut de session nommé [{0}] a été passé parce que le type [{1}] de la valeur ne correspond pas au filtre [{2}]
+managerBase.sessionNotFound=La session [{0}] n''a pas été trouvée
 managerBase.sessionTimeout=Réglage du délai d''inactivité (timeout) de session invalide [{0}]
 managerBase.setContextNotNew=Il est illégal d'appeler setContext() pour changer le contexte associé avec un gestionnaire (Manager) si le genstionnaire n'est pas dans l'état nouveau
 
diff --git a/java/org/apache/catalina/session/LocalStrings_ja.properties b/java/org/apache/catalina/session/LocalStrings_ja.properties
index 8f008b7..0cfbbd1 100644
--- a/java/org/apache/catalina/session/LocalStrings_ja.properties
+++ b/java/org/apache/catalina/session/LocalStrings_ja.properties
@@ -39,6 +39,7 @@ fileStore.saving=セッション [{0}] をファイル [{1}] に保存します
 managerBase.createSession.ise=createSession: アクティブセッションが多すぎます
 managerBase.sessionAttributeNameFilter=名前フィルタ[{1}]と一致しなかったため、[{0}]というセッション属性をスキップしました。
 managerBase.sessionAttributeValueClassNameFilter=値タイプ[{1}]がフィルタ[{2}]と一致しなかったため、[{0}]という名前のセッション属性をスキップしました。
+managerBase.sessionNotFound=セッション [{0}] が見つかりません。
 managerBase.sessionTimeout=無効なセッションタイムアウト設定です [{0}]
 managerBase.setContextNotNew=NEW 状態ではないマネージャーに関連付けられた Context を変更するために setContext() を呼び出すことは禁止されています。
 
diff --git a/java/org/apache/catalina/session/LocalStrings_ko.properties b/java/org/apache/catalina/session/LocalStrings_ko.properties
index e8057d5..2d0bacc 100644
--- a/java/org/apache/catalina/session/LocalStrings_ko.properties
+++ b/java/org/apache/catalina/session/LocalStrings_ko.properties
@@ -36,6 +36,7 @@ fileStore.saving=세션 [{0}]을(를) 파일 [{1}]에 저장합니다.
 managerBase.createSession.ise=createSession: 활성화된 세션이 너무 많습니다.
 managerBase.sessionAttributeNameFilter=이름 필터 [{1}]와(과) 부합되지 않기 때문에, [{0}](이)라는 이름의 세션 속성을 건너뛰었습니다.
 managerBase.sessionAttributeValueClassNameFilter=값의 타입 [{1}]이(가) 필터 [{2}]와(과) 부합하지 않기 때문에, [{0}](이)라는 이름의 세션 속성을 건너뛰었습니다.
+managerBase.sessionNotFound=세션 [{0}]을(를) 찾을 수 없었습니다.
 managerBase.sessionTimeout=유효하지 않은, 세션 제한 시간 초과 설정입니다: [{0}]
 managerBase.setContextNotNew=만일 매니저가 NEW 상태에 있지 않다면, 매니저와 연관된 컨텍스트를 변경하기 위해 setContext()를 호출하는 것은 불허됩니다.
 
diff --git a/java/org/apache/catalina/session/LocalStrings_zh_CN.properties b/java/org/apache/catalina/session/LocalStrings_zh_CN.properties
index 30cda59..1b05442 100644
--- a/java/org/apache/catalina/session/LocalStrings_zh_CN.properties
+++ b/java/org/apache/catalina/session/LocalStrings_zh_CN.properties
@@ -26,6 +26,7 @@ fileStore.deleteFailed=无法删除阻止创建会话存储位置的文件 [{0}]
 fileStore.deleteSessionFailed=无法删除不再需要的文件[{0}]
 
 managerBase.createSession.ise=createSession:活跃session过多
+managerBase.sessionNotFound=找不到会话 [{0}]
 managerBase.setContextNotNew=如果Manager未处于NEW状态,则调用setContext()以更改与Manager关联的Context是非法的
 
 persistentManager.deserializeError=错误反序列化会话[{0}]: [{1}]
diff --git a/java/org/apache/catalina/session/ManagerBase.java b/java/org/apache/catalina/session/ManagerBase.java
index bcb94bf..e4121a6 100644
--- a/java/org/apache/catalina/session/ManagerBase.java
+++ b/java/org/apache/catalina/session/ManagerBase.java
@@ -14,20 +14,18 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
-
 package org.apache.catalina.session;
 
 
 import java.beans.PropertyChangeListener;
 import java.beans.PropertyChangeSupport;
 import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
 import java.util.ArrayList;
 import java.util.Date;
 import java.util.Deque;
 import java.util.Enumeration;
 import java.util.HashMap;
-import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
@@ -80,7 +78,7 @@ public abstract class ManagerBase extends LifecycleMBeanBase implements Manager
      * session controlled by this Manager must be Serializable.
      *
      * @deprecated Ignored. {@link Context#getDistributable()} always takes
-     *             precedence. Will be removed in Tomcat 9.0.x.
+     *             precedence. Will be removed in Tomcat 8.5.x.
      */
     @Deprecated
     protected boolean distributable;
@@ -103,7 +101,7 @@ public abstract class ManagerBase extends LifecycleMBeanBase implements Manager
      * this Manager.
      *
      * @deprecated Ignored. {@link Context#getSessionTimeout()} always takes
-     *             precedence. Will be removed in Tomcat 9.0.x.
+     *             precedence. Will be removed in Tomcat 8.5.x.
      */
     @Deprecated
     protected int maxInactiveInterval = 30 * 60;
@@ -278,6 +276,13 @@ public abstract class ManagerBase extends LifecycleMBeanBase implements Manager
     }
 
 
+    /**
+     * Provides {@link #getSessionAttributeNameFilter()} as a pre-compiled
+     * regular expression pattern.
+     *
+     * @return The pre-compiled pattern used to filter session attributes based
+     *         on attribute name. {@code null} means no filter is applied.
+     */
     protected Pattern getSessionAttributeNamePattern() {
         return sessionAttributeNamePattern;
     }
@@ -487,12 +492,20 @@ public abstract class ManagerBase extends LifecycleMBeanBase implements Manager
             return sessionIdGenerator;
         } else if (sessionIdGeneratorClass != null) {
             try {
-                sessionIdGenerator = sessionIdGeneratorClass.newInstance();
+                sessionIdGenerator = sessionIdGeneratorClass.getConstructor().newInstance();
                 return sessionIdGenerator;
             } catch(IllegalAccessException ex) {
                 // Ignore
             } catch(InstantiationException ex) {
                 // Ignore
+            } catch (IllegalArgumentException e) {
+                // Ignore
+            } catch (SecurityException e) {
+                // Ignore
+            } catch (InvocationTargetException e) {
+                // Ignore
+            } catch (NoSuchMethodException e) {
+                // Ignore
             }
         }
         return null;
@@ -509,18 +522,14 @@ public abstract class ManagerBase extends LifecycleMBeanBase implements Manager
      * @return The descriptive short name of this Manager implementation.
      */
     public String getName() {
-
-        return (name);
-
+        return name;
     }
 
     /**
      * @return The secure random number generator class name.
      */
     public String getSecureRandomClass() {
-
-        return (this.secureRandomClass);
-
+        return this.secureRandomClass;
     }
 
 
@@ -608,9 +617,7 @@ public abstract class ManagerBase extends LifecycleMBeanBase implements Manager
      * @return The frequency of manager checks.
      */
     public int getProcessExpiresFrequency() {
-
-        return (this.processExpiresFrequency);
-
+        return this.processExpiresFrequency;
     }
 
     /**
@@ -782,14 +789,13 @@ public abstract class ManagerBase extends LifecycleMBeanBase implements Manager
             sessionCreationTiming.add(timing);
             sessionCreationTiming.poll();
         }
-        return (session);
-
+        return session;
     }
 
 
     @Override
     public Session createEmptySession() {
-        return (getNewSession());
+        return getNewSession();
     }
 
 
@@ -905,6 +911,7 @@ public abstract class ManagerBase extends LifecycleMBeanBase implements Manager
 
     /**
      * Get new session class to be used in the doLoad() method.
+     * @return a new session for use with this manager
      */
     protected StandardSession getNewSession() {
         return new StandardSession(this);
@@ -913,6 +920,7 @@ public abstract class ManagerBase extends LifecycleMBeanBase implements Manager
 
     /**
      * Generate and return a new session identifier.
+     * @return a new session id
      */
     protected String generateSessionId() {
 
@@ -1019,9 +1027,7 @@ public abstract class ManagerBase extends LifecycleMBeanBase implements Manager
      *         limit.
      */
     public int getMaxActiveSessions() {
-
-        return (this.maxActiveSessions);
-
+        return this.maxActiveSessions;
     }
 
 
@@ -1090,11 +1096,9 @@ public abstract class ManagerBase extends LifecycleMBeanBase implements Manager
         // Init
         int counter = 0;
         int result = 0;
-        Iterator<SessionTiming> iter = copy.iterator();
 
         // Calculate average
-        while (iter.hasNext()) {
-            SessionTiming timing = iter.next();
+        for (SessionTiming timing : copy) {
             if (timing != null) {
                 int timeAlive = timing.getDuration();
                 counter++;
@@ -1114,37 +1118,13 @@ public abstract class ManagerBase extends LifecycleMBeanBase implements Manager
      */
     @Override
     public int getSessionCreateRate() {
-        long now = System.currentTimeMillis();
         // Copy current stats
         List<SessionTiming> copy = new ArrayList<SessionTiming>();
         synchronized (sessionCreationTiming) {
             copy.addAll(sessionCreationTiming);
         }
 
-        // Init
-        long oldest = now;
-        int counter = 0;
-        int result = 0;
-        Iterator<SessionTiming> iter = copy.iterator();
-
-        // Calculate rate
-        while (iter.hasNext()) {
-            SessionTiming timing = iter.next();
-            if (timing != null) {
-                counter++;
-                if (timing.getTimestamp() < oldest) {
-                    oldest = timing.getTimestamp();
-                }
-            }
-        }
-        if (counter > 0) {
-            if (oldest < now) {
-                result = (1000*60*counter)/(int) (now - oldest);
-            } else {
-                result = Integer.MAX_VALUE;
-            }
-        }
-        return result;
+        return calculateRate(copy);
     }
 
 
@@ -1158,22 +1138,25 @@ public abstract class ManagerBase extends LifecycleMBeanBase implements Manager
      */
     @Override
     public int getSessionExpireRate() {
-        long now = System.currentTimeMillis();
         // Copy current stats
         List<SessionTiming> copy = new ArrayList<SessionTiming>();
         synchronized (sessionExpirationTiming) {
             copy.addAll(sessionExpirationTiming);
         }
 
+        return calculateRate(copy);
+    }
+
+
+    private static int calculateRate(List<SessionTiming> sessionTiming) {
         // Init
+        long now = System.currentTimeMillis();
         long oldest = now;
         int counter = 0;
         int result = 0;
-        Iterator<SessionTiming> iter = copy.iterator();
 
         // Calculate rate
-        while (iter.hasNext()) {
-            SessionTiming timing = iter.next();
+        for (SessionTiming timing : sessionTiming) {
             if (timing != null) {
                 counter++;
                 if (timing.getTimestamp() < oldest) {
@@ -1200,9 +1183,8 @@ public abstract class ManagerBase extends LifecycleMBeanBase implements Manager
      */
     public String listSessionIds() {
         StringBuilder sb = new StringBuilder();
-        Iterator<String> keys = sessions.keySet().iterator();
-        while (keys.hasNext()) {
-            sb.append(keys.next()).append(" ");
+        for (String s : sessions.keySet()) {
+            sb.append(s).append(" ");
         }
         return sb.toString();
     }
@@ -1219,9 +1201,10 @@ public abstract class ManagerBase extends LifecycleMBeanBase implements Manager
      */
     public String getSessionAttribute( String sessionId, String key ) {
         Session s = sessions.get(sessionId);
-        if( s==null ) {
-            if(log.isInfoEnabled())
-                log.info("Session not found " + sessionId);
+        if (s == null) {
+            if (log.isInfoEnabled()) {
+                log.info(sm.getString("managerBase.sessionNotFound", sessionId));
+            }
             return null;
         }
         Object o=s.getSession().getAttribute(key);
@@ -1246,7 +1229,7 @@ public abstract class ManagerBase extends LifecycleMBeanBase implements Manager
         Session s = sessions.get(sessionId);
         if (s == null) {
             if (log.isInfoEnabled()) {
-                log.info("Session not found " + sessionId);
+                log.info(sm.getString("managerBase.sessionNotFound", sessionId));
             }
             return null;
         }
@@ -1267,63 +1250,79 @@ public abstract class ManagerBase extends LifecycleMBeanBase implements Manager
 
 
     public void expireSession( String sessionId ) {
-        Session s=sessions.get(sessionId);
-        if( s==null ) {
-            if(log.isInfoEnabled())
-                log.info("Session not found " + sessionId);
+        Session s = sessions.get(sessionId);
+        if (s == null) {
+            if (log.isInfoEnabled()) {
+                log.info(sm.getString("managerBase.sessionNotFound", sessionId));
+            }
             return;
         }
         s.expire();
     }
 
     public long getThisAccessedTimestamp( String sessionId ) {
-        Session s=sessions.get(sessionId);
-        if(s== null)
-            return -1 ;
+        Session s = sessions.get(sessionId);
+        if (s == null) {
+            if (log.isInfoEnabled()) {
+                log.info(sm.getString("managerBase.sessionNotFound", sessionId));
+            }
+            return -1;
+        }
         return s.getThisAccessedTime();
     }
 
     public String getThisAccessedTime( String sessionId ) {
-        Session s=sessions.get(sessionId);
-        if( s==null ) {
-            if(log.isInfoEnabled())
-                log.info("Session not found " + sessionId);
+        Session s = sessions.get(sessionId);
+        if (s == null) {
+            if (log.isInfoEnabled()) {
+                log.info(sm.getString("managerBase.sessionNotFound", sessionId));
+            }
             return "";
         }
         return new Date(s.getThisAccessedTime()).toString();
     }
 
     public long getLastAccessedTimestamp( String sessionId ) {
-        Session s=sessions.get(sessionId);
-        if(s== null)
-            return -1 ;
+        Session s = sessions.get(sessionId);
+        if (s == null) {
+            if (log.isInfoEnabled()) {
+                log.info(sm.getString("managerBase.sessionNotFound", sessionId));
+            }
+            return -1;
+        }
         return s.getLastAccessedTime();
     }
 
     public String getLastAccessedTime( String sessionId ) {
-        Session s=sessions.get(sessionId);
-        if( s==null ) {
-            if(log.isInfoEnabled())
-                log.info("Session not found " + sessionId);
+        Session s = sessions.get(sessionId);
+        if (s == null) {
+            if (log.isInfoEnabled()) {
+                log.info(sm.getString("managerBase.sessionNotFound", sessionId));
+            }
             return "";
         }
         return new Date(s.getLastAccessedTime()).toString();
     }
 
     public String getCreationTime( String sessionId ) {
-        Session s=sessions.get(sessionId);
-        if( s==null ) {
-            if(log.isInfoEnabled())
-                log.info("Session not found " + sessionId);
+        Session s = sessions.get(sessionId);
+        if (s == null) {
+            if (log.isInfoEnabled()) {
+                log.info(sm.getString("managerBase.sessionNotFound", sessionId));
+            }
             return "";
         }
         return new Date(s.getCreationTime()).toString();
     }
 
     public long getCreationTimestamp( String sessionId ) {
-        Session s=sessions.get(sessionId);
-        if(s== null)
-            return -1 ;
+        Session s = sessions.get(sessionId);
+        if (s == null) {
+            if (log.isInfoEnabled()) {
+                log.info(sm.getString("managerBase.sessionNotFound", sessionId));
+            }
+            return -1;
+        }
         return s.getCreationTime();
     }
 


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org