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
This commit is contained in:
Greg Wilkins 2010-09-15 23:01:56 +00:00
parent a4b693a271
commit bb91faac89
3 changed files with 43 additions and 223 deletions

View File

@ -81,11 +81,6 @@
<artifactId>servlet-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>test-jetty-servlet</artifactId>

View File

@ -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++];
}
}
}

View File

@ -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")))));
}
}
}