commits@javamail.java.net

[javamail~mercurial:849] Better handle mailbox starting with garbage, e.g., blank line - bug 8405

From: <shannon_at_java.net>
Date: Wed, 24 Aug 2016 23:55:42 +0000

Project: javamail
Repository: mercurial
Revision: 849
Author: shannon
Date: 2016-08-24 23:55:06 UTC
Link:

Log Message:
------------
Better handle mailbox starting with garbage, e.g., blank line - bug 8405


Revisions:
----------
849


Modified Paths:
---------------
mbox/src/main/java/com/sun/mail/mbox/MessageLoader.java


Added Paths:
------------
mbox/src/test/java/com/sun/mail/mbox/MboxFolderTest.java


Diffs:
------
diff -r c0c4fcd9a7a0 -r e1c884d868d1 mbox/src/main/java/com/sun/mail/mbox/MessageLoader.java
--- a/mbox/src/main/java/com/sun/mail/mbox/MessageLoader.java Wed Aug 24 13:11:20 2016 -0700
+++ b/mbox/src/main/java/com/sun/mail/mbox/MessageLoader.java Wed Aug 24 16:55:06 2016 -0700
@@ -86,7 +86,7 @@
             fos = temp.getAppendStream();
             int n;
             // keep loading messages as long as we have headers
- while ((n = skipHeader()) >= 0) {
+ while ((n = skipHeader(loaded == 0)) >= 0) {
                 long start;
                 if (n == 0) {
                     // didn't find a Content-Length, skip the body
@@ -139,11 +139,13 @@
      * Update the MessageMetadata based on the headers seen.
      * return -1 on EOF.
      */
- private int skipHeader() throws IOException {
+ private int skipHeader(boolean first) throws IOException {
         int clen = 0;
         boolean bol = true;
         int lpos = -1;
         int b;
+ boolean saw_unix_from = false;
+ int lineno = 0;
         md = new MboxFolder.MessageMetadata();
         md.start = prevend;
         md.recent = true;
@@ -155,13 +157,17 @@
             }
             if (b == '\n') {
                 bol = true;
+ lineno++;
                 // newline at end of line, was the line one of the headers
                 // we're looking for?
                 if (lpos > 7) {
                     // XXX - make this more efficient?
                     String s = new String(line, 0, lpos);
                     // fast check for Content-Length header
- if (line[7] == '-' && isPrefix(s, "Content-Length:")) {
+ if (lineno == 1 && line[0] == 'F' && isPrefix(s, "From ")) {
+ saw_unix_from = true;
+ } else if (line[7] == '-' &&
+ isPrefix(s, "Content-Length:")) {
                         s = s.substring(15).trim();
                         try {
                             clen = Integer.parseInt(s);
@@ -198,7 +204,12 @@
                     line[lpos++] = (char)b;
             }
         }
- if (b < 0)
+
+ // if we hit EOF, or this is the first message we're loading and
+ // it doesn't have a UNIX From line, return EOF.
+ // (After the first message, UNIX From lines are seen by skipBody
+ // to terminate the message.)
+ if (b < 0 || (first && !saw_unix_from))
             return -1;
         else
             return clen;

diff -r c0c4fcd9a7a0 -r e1c884d868d1 mbox/src/test/java/com/sun/mail/mbox/MboxFolderTest.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mbox/src/test/java/com/sun/mail/mbox/MboxFolderTest.java Wed Aug 24 16:55:06 2016 -0700
@@ -0,0 +1,112 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright (c) 2009-2016 Oracle and/or its affiliates. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common Development
+ * and Distribution License("CDDL") (collectively, the "License"). You
+ * may not use this file except in compliance with the License. You can
+ * obtain a copy of the License at
+ * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
+ * or packager/legal/LICENSE.txt. See the License for the specific
+ * language governing permissions and limitations under the License.
+ *
+ * When distributing the software, include this License Header Notice in each
+ * file and include the License file at packager/legal/LICENSE.txt.
+ *
+ * GPL Classpath Exception:
+ * Oracle designates this particular file as subject to the "Classpath"
+ * exception as provided by Oracle in the GPL Version 2 section of the License
+ * file that accompanied this code.
+ *
+ * Modifications:
+ * If applicable, add the following below the License Header, with the fields
+ * enclosed by brackets [] replaced by your own identifying information:
+ * "Portions Copyright [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ * If you wish your version of this file to be governed by only the CDDL or
+ * only the GPL Version 2, indicate your decision by adding "[Contributor]
+ * elects to include this software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice of license, a
+ * recipient has the option to distribute your version of this file under
+ * either the CDDL, the GPL Version 2 or to extend the choice of license to
+ * its licensees as provided above. However, if you add GPL Version 2 code
+ * and therefore, elected the GPL Version 2 license, then the option applies
+ * only if the new code is made subject to such option by the copyright
+ * holder.
+ */
+
+package com.sun.mail.mbox;
+
+import java.io.File;
+import java.io.PrintWriter;
+import java.util.Properties;
+
+import javax.mail.Session;
+import javax.mail.Store;
+import javax.mail.Folder;
+
+import org.junit.Test;
+import org.junit.BeforeClass;
+import org.junit.AfterClass;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+/**
+ * Test of mbox folders.
+ */
+public final class MboxFolderTest {
+
+ @BeforeClass
+ public static void before() {
+ System.setProperty("mail.mbox.locktype", "none");
+ }
+
+ @AfterClass
+ public static void after() {
+ System.getProperties().remove("mail.mbox.locktype");
+ }
+
+ /**
+ * Test that a mailbox that has garbage at the beginning
+ * (such as a gratuitous blank line) is handled without
+ * crashing and without corrupting the mailbox.
+ */
+ @Test
+ public void testGarbageAtStartOfFolder() throws Exception {
+ Folder f = null;
+ try {
+ File temp = File.createTempFile("mbox", ".mbx");
+ temp.deleteOnExit();
+ PrintWriter pw = new PrintWriter(temp);
+ pw.println();
+ pw.println("From - Tue Aug 23 11:56:51 2011");
+ pw.println();
+ pw.println("test");
+ pw.println();
+ pw.close();
+ long size = temp.length();
+
+ Properties properties = new Properties();
+ Session session = Session.getInstance(properties);
+ Store store = session.getStore("mbox");
+ store.connect();
+ f = store.getFolder(temp.getAbsolutePath());
+ f.open(Folder.READ_WRITE);
+ assertEquals(0, f.getMessageCount());
+ f.close(true);
+ assertEquals(size, temp.length());
+ } catch (Exception ex) {
+ System.out.println(ex);
+ //ex.printStackTrace();
+ fail(ex.toString());
+ } finally {
+ if (f != null) {
+ f.delete(false);
+ f.getStore().close();
+ }
+ }
+ }
+}