You are viewing a plain text version of this content. The canonical link for it is here.
Posted to scm@geronimo.apache.org by ri...@apache.org on 2008/04/08 20:01:43 UTC
svn commit: r646017 - in
/geronimo/specs/trunk/geronimo-javamail_1.4_spec/src:
main/java/javax/mail/internet/ test/java/javax/mail/internet/ test/resources/
Author: rickmcguire
Date: Tue Apr 8 11:01:42 2008
New Revision: 646017
URL: http://svn.apache.org/viewvc?rev=646017&view=rev
Log:
GERONIMO-3953 ArrayIndexOutOfBoundsException reading MimeMultipart from a file with multiple attachments.
Added:
geronimo/specs/trunk/geronimo-javamail_1.4_spec/src/test/resources/wmtom.bin (with props)
Modified:
geronimo/specs/trunk/geronimo-javamail_1.4_spec/src/main/java/javax/mail/internet/InternetHeaders.java
geronimo/specs/trunk/geronimo-javamail_1.4_spec/src/main/java/javax/mail/internet/MimeMultipart.java
geronimo/specs/trunk/geronimo-javamail_1.4_spec/src/test/java/javax/mail/internet/MimeMultipartTest.java
Modified: geronimo/specs/trunk/geronimo-javamail_1.4_spec/src/main/java/javax/mail/internet/InternetHeaders.java
URL: http://svn.apache.org/viewvc/geronimo/specs/trunk/geronimo-javamail_1.4_spec/src/main/java/javax/mail/internet/InternetHeaders.java?rev=646017&r1=646016&r2=646017&view=diff
==============================================================================
--- geronimo/specs/trunk/geronimo-javamail_1.4_spec/src/main/java/javax/mail/internet/InternetHeaders.java (original)
+++ geronimo/specs/trunk/geronimo-javamail_1.4_spec/src/main/java/javax/mail/internet/InternetHeaders.java Tue Apr 8 11:01:42 2008
@@ -104,6 +104,7 @@
try {
StringBuffer name = new StringBuffer(32);
StringBuffer value = new StringBuffer(128);
+ boolean foundColon = false;
done: while (true) {
int c = in.read();
char ch = (char) c;
@@ -128,22 +129,34 @@
} else {
// new header
if (name.length() > 0) {
- addHeader(name.toString().trim(), value.toString().trim());
+ if (foundColon) {
+ addHeader(name.toString().trim(), value.toString().trim());
+ }
+ else {
+ addHeader(name.toString().trim(), name.toString().trim());
+ }
}
name.setLength(0);
value.setLength(0);
+ foundColon = false;
while (true) {
name.append((char) c);
c = in.read();
if (c == -1) {
break done;
} else if (c == ':') {
+ foundColon = true;
+ break;
+ } else if (c == 13 || c == 10) {
break;
}
}
- c = in.read();
- if (c == -1) {
- break done;
+ // only read this if we found a separator
+ if (foundColon) {
+ c = in.read();
+ if (c == -1) {
+ break done;
+ }
}
}
@@ -165,7 +178,12 @@
}
}
if (name.length() > 0) {
- addHeader(name.toString().trim(), value.toString().trim());
+ if (foundColon) {
+ addHeader(name.toString().trim(), value.toString().trim());
+ }
+ else {
+ addHeader(name.toString().trim(), name.toString().trim());
+ }
}
} catch (IOException e) {
throw new MessagingException("Error loading headers", e);
Modified: geronimo/specs/trunk/geronimo-javamail_1.4_spec/src/main/java/javax/mail/internet/MimeMultipart.java
URL: http://svn.apache.org/viewvc/geronimo/specs/trunk/geronimo-javamail_1.4_spec/src/main/java/javax/mail/internet/MimeMultipart.java?rev=646017&r1=646016&r2=646017&view=diff
==============================================================================
--- geronimo/specs/trunk/geronimo-javamail_1.4_spec/src/main/java/javax/mail/internet/MimeMultipart.java (original)
+++ geronimo/specs/trunk/geronimo-javamail_1.4_spec/src/main/java/javax/mail/internet/MimeMultipart.java Tue Apr 8 11:01:42 2008
@@ -27,6 +27,8 @@
import java.io.OutputStream;
import java.io.PushbackInputStream;
+import java.util.Arrays;
+
import javax.activation.DataSource;
import javax.mail.BodyPart;
import javax.mail.MessagingException;
@@ -165,11 +167,21 @@
}
try {
ContentType cType = new ContentType(contentType);
- byte[] boundary = ("--" + cType.getParameter("boundary")).getBytes();
InputStream is = new BufferedInputStream(ds.getInputStream());
- PushbackInputStream pushbackInStream = new PushbackInputStream(is,
- (boundary.length + 2));
- readTillFirstBoundary(pushbackInStream, boundary);
+ PushbackInputStream pushbackInStream = null;
+ String boundaryString = cType.getParameter("boundary");
+ byte[] boundary = null;
+ if (boundaryString == null) {
+ pushbackInStream = new PushbackInputStream(is, 128);
+ // read until we find something that looks like a boundary string
+ boundary = readTillFirstBoundary(pushbackInStream);
+ }
+ else {
+ boundary = ("--" + boundaryString).getBytes();
+ pushbackInStream = new PushbackInputStream(is, (boundary.length + 2));
+ readTillFirstBoundary(pushbackInStream, boundary);
+ }
+
while (pushbackInStream.available()>0){
MimeBodyPartInputStream partStream;
partStream = new MimeBodyPartInputStream(pushbackInStream,
@@ -199,49 +211,120 @@
* @param boundary
* @throws MessagingException
*/
- private boolean readTillFirstBoundary(PushbackInputStream pushbackInStream, byte[] boundary) throws MessagingException {
+ private byte[] readTillFirstBoundary(PushbackInputStream pushbackInStream) throws MessagingException {
ByteArrayOutputStream preambleStream = new ByteArrayOutputStream();
try {
while (pushbackInStream.available() > 0) {
- int value = pushbackInStream.read();
- if ((byte) value == boundary[0]) {
- int boundaryIndex = 0;
- while (pushbackInStream.available() > 0 && (boundaryIndex < boundary.length)
- && ((byte) value == boundary[boundaryIndex])) {
- value = pushbackInStream.read();
- if (value == -1)
- throw new MessagingException(
- "Unexpected End of Stream while searching for first Mime Boundary");
- boundaryIndex++;
+ // read the next line
+ byte[] line = readLine(pushbackInStream);
+ // if this looks like a boundary, then make it so
+ if (line.length > 2 && line[0] == '-' && line[1] == '-') {
+ // save the preamble, if there is one.
+ byte[] preambleBytes = preambleStream.toByteArray();
+ if (preambleBytes.length > 0) {
+ preamble = new String(preambleBytes);
}
- if (boundaryIndex == boundary.length) { // boundary found
- pushbackInStream.read();
+ return line;
+ }
+ else {
+ // this is part of the preamble.
+ preambleStream.write(line);
+ preambleStream.write('\r');
+ preambleStream.write('\n');
+ }
+ }
+ throw new MessagingException("Unexpected End of Stream while searching for first Mime Boundary");
+ } catch (IOException ioe) {
+ throw new MessagingException(ioe.toString(), ioe);
+ }
+ }
- // save the preamble, if there is one.
- byte[] preambleBytes = preambleStream.toByteArray();
- if (preambleBytes.length > 0) {
- preamble = new String(preambleBytes);
- }
- return true;
- }
- else {
- // we need to add this to the preamble. We write the part of the boundary that
- // actually matched, followed by the character that was the mismatch.
- preambleStream.write(boundary, 0, boundaryIndex);
- preambleStream.write((byte)value);
+ /**
+ * Move the read pointer to the begining of the first part
+ * read till the end of first boundary. Any data read before this point are
+ * saved as the preamble.
+ *
+ * @param pushbackInStream
+ * @param boundary
+ * @throws MessagingException
+ */
+ private void readTillFirstBoundary(PushbackInputStream pushbackInStream, byte[] boundary) throws MessagingException {
+ ByteArrayOutputStream preambleStream = new ByteArrayOutputStream();
+
+ try {
+ while (pushbackInStream.available() > 0) {
+ // read the next line
+ byte[] line = readLine(pushbackInStream);
+
+ // if this is the same length as our target boundary, then compare the two.
+ if (Arrays.equals(line, boundary)) {
+ // save the preamble, if there is one.
+ byte[] preambleBytes = preambleStream.toByteArray();
+ if (preambleBytes.length > 0) {
+ preamble = new String(preambleBytes);
}
+ return;
}
else {
// this is part of the preamble.
- preambleStream.write((byte)value);
+ preambleStream.write(line);
+ preambleStream.write('\r');
+ preambleStream.write('\n');
}
}
+ throw new MessagingException("Unexpected End of Stream while searching for first Mime Boundary");
} catch (IOException ioe) {
throw new MessagingException(ioe.toString(), ioe);
}
- return false;
}
+
+ /**
+ * Read a single line of data from the input stream,
+ * returning it as an array of bytes.
+ *
+ * @param in The source input stream.
+ *
+ * @return A byte array containing the line data. Returns
+ * null if there's nothing left in the stream.
+ * @exception MessagingException
+ */
+ private byte[] readLine(PushbackInputStream in) throws IOException
+ {
+ ByteArrayOutputStream line = new ByteArrayOutputStream();
+
+ while (in.available() > 0) {
+ int value = in.read();
+ if (value == -1) {
+ // if we have nothing in the accumulator, signal an EOF back
+ if (line.size() == 0) {
+ return null;
+ }
+ break;
+ }
+ else if (value == '\r') {
+ value = in.read();
+ // we expect to find a linefeed after the carriage return, but
+ // some things play loose with the rules.
+ if (value != '\n') {
+ in.unread(value);
+ }
+ break;
+ }
+ else if (value == '\n') {
+ // naked linefeed, allow that
+ break;
+ }
+ else {
+ // write this to the line
+ line.write((byte)value);
+ }
+ }
+ // return this as an array of bytes
+ return line.toByteArray();
+ }
+
+
protected InternetHeaders createInternetHeaders(InputStream in) throws MessagingException {
return new InternetHeaders(in);
Modified: geronimo/specs/trunk/geronimo-javamail_1.4_spec/src/test/java/javax/mail/internet/MimeMultipartTest.java
URL: http://svn.apache.org/viewvc/geronimo/specs/trunk/geronimo-javamail_1.4_spec/src/test/java/javax/mail/internet/MimeMultipartTest.java?rev=646017&r1=646016&r2=646017&view=diff
==============================================================================
--- geronimo/specs/trunk/geronimo-javamail_1.4_spec/src/test/java/javax/mail/internet/MimeMultipartTest.java (original)
+++ geronimo/specs/trunk/geronimo-javamail_1.4_spec/src/test/java/javax/mail/internet/MimeMultipartTest.java Tue Apr 8 11:01:42 2008
@@ -26,6 +26,7 @@
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
+import java.io.FileInputStream;
import java.util.Properties;
import javax.mail.BodyPart;
import javax.mail.MessagingException;
@@ -93,6 +94,25 @@
MimeMessage newMessage = new MimeMessage(session, in);
assertEquals("This is a preamble\r\n", ((MimeMultipart)newMessage.getContent()).getPreamble());
+ }
+
+ public void testMIMEWriting() throws IOException, MessagingException {
+ File basedir = new File(System.getProperty("basedir", "."));
+ File testInput = new File(basedir, "src/test/resources/wmtom.bin");
+ FileInputStream inStream = new FileInputStream(testInput);
+ Properties props = new Properties();
+ javax.mail.Session session = javax.mail.Session
+ .getInstance(props, null);
+ MimeMessage mimeMessage = new MimeMessage(session, inStream);
+ DataHandler dh = mimeMessage.getDataHandler();
+ MimeMultipart multiPart = new MimeMultipart(dh.getDataSource());
+ MimeBodyPart mimeBodyPart0 = (MimeBodyPart) multiPart.getBodyPart(0);
+ Object object0 = mimeBodyPart0.getContent();
+ assertNotNull(object0);
+ MimeBodyPart mimeBodyPart1 = (MimeBodyPart) multiPart.getBodyPart(1);
+ Object object1 = mimeBodyPart1.getContent();
+ assertNotNull(object1);
+ assertEquals(multiPart.getCount(), 2);
}
protected void writeToSetUp() throws Exception {
Added: geronimo/specs/trunk/geronimo-javamail_1.4_spec/src/test/resources/wmtom.bin
URL: http://svn.apache.org/viewvc/geronimo/specs/trunk/geronimo-javamail_1.4_spec/src/test/resources/wmtom.bin?rev=646017&view=auto
==============================================================================
Binary file - no diff available.
Propchange: geronimo/specs/trunk/geronimo-javamail_1.4_spec/src/test/resources/wmtom.bin
------------------------------------------------------------------------------
svn:mime-type = application/octet-stream