From bb91faac8913fdb37d93bf0ed50a3ce29a07893f Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Wed, 15 Sep 2010 23:01:56 +0000 Subject: [PATCH] JETTY-1252 Handle more multipart transfer encodings git-svn-id: svn+ssh://dev.eclipse.org/svnroot/rt/org.eclipse.jetty/jetty/trunk@2280 7e9141cc-0065-0410-87d8-b60c137991c4 --- jetty-servlets/pom.xml | 5 - .../jetty/servlets/MultiPartFilter.java | 46 +++- .../servlets/MultipartFilterTest.java.orig | 215 ------------------ 3 files changed, 43 insertions(+), 223 deletions(-) delete mode 100644 jetty-servlets/src/test/java/org/eclipse/jetty/servlets/MultipartFilterTest.java.orig diff --git a/jetty-servlets/pom.xml b/jetty-servlets/pom.xml index e079d593c8a..3a21db179bf 100644 --- a/jetty-servlets/pom.xml +++ b/jetty-servlets/pom.xml @@ -81,11 +81,6 @@ servlet-api provided - - commons-codec - commons-codec - 1.4 - org.eclipse.jetty test-jetty-servlet 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 9ea65889065..eff9de767bf 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 @@ -14,12 +14,14 @@ package org.eclipse.jetty.servlets; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; +import java.io.BufferedReader; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.FilterInputStream; import java.io.IOException; import java.io.InputStream; +import java.io.InputStreamReader; import java.io.OutputStream; import java.io.UnsupportedEncodingException; import java.util.ArrayList; @@ -40,7 +42,7 @@ import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; -import org.apache.commons.codec.binary.Base64InputStream; +import org.eclipse.jetty.http.security.B64Code; import org.eclipse.jetty.util.LazyList; import org.eclipse.jetty.util.MultiMap; import org.eclipse.jetty.util.StringUtil; @@ -221,10 +223,15 @@ public class MultiPartFilter implements Filter } } else + { out=new ByteArrayOutputStream(); - + } + + if ("base64".equalsIgnoreCase(content_transfer_encoding)) - in = new Base64InputStream(in); + { + in = new Base64InputStream(in); + } else if ("quoted-printable".equalsIgnoreCase(content_transfer_encoding)) { in = new FilterInputStream(in) @@ -503,4 +510,37 @@ public class MultiPartFilter implements Filter _encoding=enc; } } + + private static class Base64InputStream extends InputStream + { + BufferedReader _in; + String _line; + byte[] _buffer; + int _pos; + + public Base64InputStream (InputStream in) + { + _in = new BufferedReader(new InputStreamReader(in)); + } + + @Override + public int read() throws IOException + { + if (_buffer==null || _pos>= _buffer.length) + { + _line = _in.readLine(); + if (_line==null) + return -1; + if (_line.startsWith("--")) + _buffer=(_line+"\r\n").getBytes(); + else if (_line.length()==0) + _buffer="\r\n".getBytes(); + else + _buffer=B64Code.decode(_line); + + _pos=0; + } + return _buffer[_pos++]; + } + } } diff --git a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/MultipartFilterTest.java.orig b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/MultipartFilterTest.java.orig deleted file mode 100644 index 11f3534305a..00000000000 --- a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/MultipartFilterTest.java.orig +++ /dev/null @@ -1,215 +0,0 @@ -// ======================================================================== -// Copyright (c) 2004-2009 Mort Bay Consulting Pty. Ltd. -// ------------------------------------------------------------------------ -// All rights reserved. This program and the accompanying materials -// are made available under the terms of the Eclipse Public License v1.0 -// and Apache License v2.0 which accompanies this distribution. -// The Eclipse Public License is available at -// http://www.eclipse.org/legal/epl-v10.html -// The Apache License v2.0 is available at -// http://www.opensource.org/licenses/apache2.0.php -// You may elect to redistribute this code under either of these licenses. -// ======================================================================== - -package org.eclipse.jetty.servlets; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.net.Socket; -import java.net.URL; -import java.util.Enumeration; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.eclipse.jetty.servlet.FilterHolder; -import org.eclipse.jetty.servlet.FilterMapping; -import org.eclipse.jetty.testing.HttpTester; -import org.eclipse.jetty.testing.ServletTester; -import org.eclipse.jetty.util.IO; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -public class MultipartFilterTest -{ - private File _dir; - private ServletTester tester; - - @Before - public void setUp() throws Exception - { - _dir = File.createTempFile("testmultupart",null); - assertTrue(_dir.delete()); - assertTrue(_dir.mkdir()); - _dir.deleteOnExit(); - assertTrue(_dir.isDirectory()); - - tester=new ServletTester(); - tester.setContextPath("/context"); - tester.setResourceBase(_dir.getCanonicalPath()); - tester.addServlet(DumpServlet.class, "/"); - tester.addFilter(MultiPartFilter.class,"/*",FilterMapping.DEFAULT); - tester.start(); - } - - @After - public void tearDown() throws Exception - { - tester.stop(); - } - - @Test - public void testBadPost() throws Exception - { - // generated and parsed test - HttpTester request = new HttpTester(); - HttpTester response = new HttpTester(); - - // test GET - request.setMethod("POST"); - request.setVersion("HTTP/1.0"); - request.setHeader("Host","tester"); - request.setURI("/context/dump"); - - String boundary="XyXyXy"; - request.setHeader("Content-Type","multipart/form-data; boundary="+boundary); - - - String content = "--" + boundary + "\r\n"+ - "Content-Disposition: form-data; name=\"fileup\"; filename=\"test.upload\"\r\n"+ - "Content-Type: application/octet-stream\r\n\r\n"+ - "How now brown cow."+ - "\r\n--" + boundary + "-\r\n\r\n"; - - request.setContent(content); - - - response.parse(tester.getResponses(request.generate())); - assertTrue(response.getMethod()==null); - assertEquals(HttpServletResponse.SC_OK,response.getStatus()); - } - - @Test - public void testPost() throws Exception - { - // generated and parsed test - HttpTester request = new HttpTester(); - HttpTester response = new HttpTester(); - - // test GET - request.setMethod("POST"); - request.setVersion("HTTP/1.0"); - request.setHeader("Host","tester"); - request.setURI("/context/dump"); - - String boundary="XyXyXy"; - request.setHeader("Content-Type","multipart/form-data; boundary="+boundary); - - - String content = "--" + boundary + "\r\n"+ - "Content-Disposition: form-data; name=\"fileup\"; filename=\"test.upload\"\r\n"+ - "Content-Type: application/octet-stream\r\n\r\n"+ - "How now brown cow."+ - "\r\n--" + boundary + "--\r\n\r\n"; - - request.setContent(content); - - response.parse(tester.getResponses(request.generate())); - assertTrue(response.getMethod()==null); - assertEquals(HttpServletResponse.SC_OK,response.getStatus()); - assertTrue(response.getContent().indexOf("brown cow")>=0); - } - - /* - * Test multipart with parts encoded in base64 (RFC1521 section 5) - */ - @Test - public void testPostWithContentTransferEncodingBase64() throws Exception { - // generated and parsed test - HttpTester request = new HttpTester(); - HttpTester response = new HttpTester(); - - // test GET - request.setMethod("POST"); - request.setVersion("HTTP/1.0"); - request.setHeader("Host","tester"); - request.setURI("/context/dump"); - - String boundary="XyXyXy"; - request.setHeader("Content-Type","multipart/form-data; boundary="+boundary); - - // part content is "How now brown cow." run through a base64 encoder - String content = "--" + boundary + "\r\n"+ - "Content-Disposition: form-data; name=\"fileup\"; filename=\"test.upload\"\r\n"+ - "Content-Transfer-Encoding: base64\r\n"+ - "Content-Type: application/octet-stream\r\n\r\n"+ - "SG93IG5vdyBicm93biBjb3cuCg=="+ - "\r\n--" + boundary + "--\r\n\r\n"; - - request.setContent(content); - - response.parse(tester.getResponses(request.generate())); - assertTrue(response.getMethod()==null); - assertEquals(HttpServletResponse.SC_OK,response.getStatus()); - assertTrue(response.getContent().indexOf("brown cow")>=0); - } - - /* - * Test multipart with parts encoded in quoted-printable (RFC1521 section 5) - */ - @Test - public void testPostWithContentTransferEncodingQuotedPrintable() throws Exception { - // generated and parsed test - HttpTester request = new HttpTester(); - HttpTester response = new HttpTester(); - - // test GET - request.setMethod("POST"); - request.setVersion("HTTP/1.0"); - request.setHeader("Host","tester"); - request.setURI("/context/dump"); - - String boundary="XyXyXy"; - request.setHeader("Content-Type","multipart/form-data; boundary="+boundary); - - /* - * Part content is "How now brown cow." run through Apache Commons Codec - * quoted printable encoding. - */ - String content = "--" + boundary + "\r\n"+ - "Content-Disposition: form-data; name=\"fileup\"; filename=\"test.upload\"\r\n"+ - "Content-Transfer-Encoding: quoted-printable\r\n"+ - "Content-Type: application/octet-stream\r\n\r\n"+ - "=48=6F=77=20=6E=6F=77=20=62=72=6F=77=6E=20=63=6F=77=2E"+ - "\r\n--" + boundary + "--\r\n\r\n"; - - request.setContent(content); - - response.parse(tester.getResponses(request.generate())); - assertTrue(response.getMethod()==null); - assertEquals(HttpServletResponse.SC_OK,response.getStatus()); - assertTrue(response.getContent().indexOf("brown cow")>=0); - } - - public static class DumpServlet extends HttpServlet - { - /* ------------------------------------------------------------ */ - /** - * @see javax.servlet.http.HttpServlet#doPost(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) - */ - @Override - protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException - { - resp.getWriter().println((IO.toString(new FileInputStream((File)req.getAttribute("fileup"))))); - } - - } -}