diff --git a/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/MultiPartFilter.java b/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/MultiPartFilter.java index 4111a1de6ff..049f37072b1 100644 --- a/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/MultiPartFilter.java +++ b/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/MultiPartFilter.java @@ -63,6 +63,7 @@ import org.eclipse.jetty.util.TypeUtil; */ public class MultiPartFilter implements Filter { + public final static String CONTENT_TYPE_SUFFIX=".org.eclipse.jetty.servlet.contentType"; private final static String FILES ="org.eclipse.jetty.servlet.MultiPartFilter.files"; private File tempdir; private boolean _deleteFiles; @@ -132,8 +133,11 @@ public class MultiPartFilter implements Filter String content_disposition=null; String content_transfer_encoding=null; + outer:while(!lastPart) { + String type_content=null; + while(true) { // read a line @@ -155,7 +159,9 @@ public class MultiPartFilter implements Filter if(key.equals("content-disposition")) content_disposition=value; else if(key.equals("content-transfer-encoding")) - content_transfer_encoding=value; + content_transfer_encoding=value; + else if (key.equals("content-type")) + type_content = value; } } // Extract content-disposition @@ -207,6 +213,8 @@ public class MultiPartFilter implements Filter out = new BufferedOutputStream(out, _fileOutputBuffer); request.setAttribute(name,file); params.add(name, filename); + if (type_content != null) + params.add(name+CONTENT_TYPE_SUFFIX, type_content); if (_deleteFiles) { @@ -330,6 +338,8 @@ public class MultiPartFilter implements Filter { bytes = ((ByteArrayOutputStream)out).toByteArray(); params.add(name,bytes); + if (type_content != null) + params.add(name+CONTENT_TYPE_SUFFIX, type_content); } } diff --git a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/MultipartFilterTest.java b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/MultipartFilterTest.java index 2dc3048024c..0dfd6f17bf8 100644 --- a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/MultipartFilterTest.java +++ b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/MultipartFilterTest.java @@ -15,6 +15,7 @@ package org.eclipse.jetty.servlets; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; +import static org.junit.Assert.assertNotNull; import java.io.File; import java.io.FileInputStream; @@ -39,6 +40,21 @@ public class MultipartFilterTest private File _dir; private ServletTester tester; + + public static class TestServlet extends DumpServlet + { + + @Override + protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException + { + assertNotNull(req.getParameter("fileup")); + assertNotNull(req.getParameter("fileup"+MultiPartFilter.CONTENT_TYPE_SUFFIX)); + assertEquals(req.getParameter("fileup"+MultiPartFilter.CONTENT_TYPE_SUFFIX), "application/octet-stream"); + + super.doPost(req, resp); + } + + } @Before public void setUp() throws Exception { @@ -51,7 +67,7 @@ public class MultipartFilterTest tester=new ServletTester(); tester.setContextPath("/context"); tester.setResourceBase(_dir.getCanonicalPath()); - tester.addServlet(DumpServlet.class, "/"); + tester.addServlet(TestServlet.class, "/"); FilterHolder multipartFilter = tester.addFilter(MultiPartFilter.class,"/*",FilterMapping.DEFAULT); multipartFilter.setInitParameter("deleteFiles", "true"); tester.start(); @@ -93,6 +109,7 @@ public class MultipartFilterTest assertTrue(response.getMethod()==null); assertEquals(HttpServletResponse.SC_OK,response.getStatus()); } + @Test public void testPost() throws Exception @@ -124,6 +141,7 @@ public class MultipartFilterTest assertEquals(HttpServletResponse.SC_OK,response.getStatus()); assertTrue(response.getContent().indexOf("brown cow")>=0); } + @Test public void testEncodedPost() throws Exception diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/log/StdErrLog.java b/jetty-util/src/main/java/org/eclipse/jetty/util/log/StdErrLog.java index 7dc87b4f3e4..72192728e0d 100644 --- a/jetty-util/src/main/java/org/eclipse/jetty/util/log/StdErrLog.java +++ b/jetty-util/src/main/java/org/eclipse/jetty/util/log/StdErrLog.java @@ -37,9 +37,10 @@ import org.eclipse.jetty.util.DateCache; */ public class StdErrLog implements Logger { + private static final String EOL = System.getProperty("line.separator"); private static DateCache _dateCache; private static Properties __props = Log.__props; - + private final static boolean __source = Boolean.parseBoolean(Log.__props.getProperty("org.eclipse.jetty.util.log.SOURCE", Log.__props.getProperty("org.eclipse.jetty.util.log.stderr.SOURCE","false"))); private final static boolean __long = Boolean.parseBoolean(Log.__props.getProperty("org.eclipse.jetty.util.log.stderr.LONG","false")); @@ -122,7 +123,7 @@ public class StdErrLog implements Logger /** * Get the Logging Level for the provided log name. Using the FQCN first, then each package segment from longest to * shortest. - * + * * @param props * the properties to check * @param name @@ -193,13 +194,13 @@ public class StdErrLog implements Logger * Condenses a classname by stripping down the package name to just the first character of each package name * segment.Configured *
- * + * *
* Examples: * "org.eclipse.jetty.test.FooTest" = "oejt.FooTest" * "org.eclipse.jetty.server.logging.LogTest" = "orjsl.LogTest" *- * + * * @param classname * the fully qualified class name * @return the condensed name @@ -248,7 +249,7 @@ public class StdErrLog implements Logger /* ------------------------------------------------------------ */ /** * Is the source of a log, logged - * + * * @return true if the class, method, file and line number of a log is logged. */ public boolean isSource() @@ -259,7 +260,7 @@ public class StdErrLog implements Logger /* ------------------------------------------------------------ */ /** * Set if a log source is logged. - * + * * @param source * true if the class, method, file and line number of a log is logged. */ @@ -334,9 +335,9 @@ public class StdErrLog implements Logger synchronized (__loggers) { this._level = LEVEL_DEBUG; - + // Boot stomp all cached log levels to DEBUG - for(StdErrLog log: __loggers.values()) + for(StdErrLog log: __loggers.values()) { log._level = LEVEL_DEBUG; } @@ -347,9 +348,9 @@ public class StdErrLog implements Logger synchronized (__loggers) { this._level = this._configuredLevel; - + // restore all cached log configured levels - for(StdErrLog log: __loggers.values()) + for(StdErrLog log: __loggers.values()) { log._level = log._configuredLevel; } @@ -367,7 +368,7 @@ public class StdErrLog implements Logger *
* Available values ({@link StdErrLog#LEVEL_ALL}, {@link StdErrLog#LEVEL_DEBUG}, {@link StdErrLog#LEVEL_INFO}, * {@link StdErrLog#LEVEL_WARN}) - * + * * @param level * the level to set the logger to */ @@ -551,19 +552,19 @@ public class StdErrLog implements Logger } else { - buffer.append('\n'); + buffer.append(EOL); format(buffer,thrown.toString()); StackTraceElement[] elements = thrown.getStackTrace(); for (int i = 0; elements != null && i < elements.length; i++) { - buffer.append("\n\tat "); + buffer.append(EOL).append("\tat "); format(buffer,elements[i].toString()); } Throwable cause = thrown.getCause(); if (cause != null && cause != thrown) { - buffer.append("\nCaused by: "); + buffer.append(EOL).append("Caused by: "); format(buffer,cause); } } @@ -571,7 +572,7 @@ public class StdErrLog implements Logger /** * A more robust form of name blank test. Will return true for null names, and names that have only whitespace - * + * * @param name * the name to test * @return true for null or blank name, false if any non-whitespace character is found. @@ -597,7 +598,7 @@ public class StdErrLog implements Logger /** * Get a Child Logger relative to this Logger. - * + * * @param name * the child name * @return the appropriate child logger (if name specified results in a new unique child) @@ -661,7 +662,7 @@ public class StdErrLog implements Logger } return s.toString(); } - + public static void setProperties(Properties props) { __props = props;