commits@javamail.java.net

[javamail~mercurial:445] Infinite loop if Quota information is not correctly reported by imap serv

From: <shannon_at_kenai.com>
Date: Mon, 9 Jul 2012 18:31:20 +0000

Project: javamail
Repository: mercurial
Revision: 445
Author: shannon
Date: 2012-07-02 18:50:56 UTC
Link:

Log Message:
------------
Optimize IMAP FETCH to detect end of data without an extra FETCH.
Add mail.imap.ignorebodystructuresize to work around server bugs.
Infinite loop if Quota information is not correctly reported by imap server -
bug 5233.


Revisions:
----------
444
445


Modified Paths:
---------------
doc/release/CHANGES.txt
mail/src/main/java/com/sun/mail/imap/IMAPBodyPart.java
mail/src/main/java/com/sun/mail/imap/IMAPInputStream.java
mail/src/main/java/com/sun/mail/imap/IMAPMessage.java
mail/src/main/java/com/sun/mail/imap/IMAPStore.java
mail/src/main/java/com/sun/mail/imap/package.html
mail/src/main/java/com/sun/mail/imap/protocol/IMAPProtocol.java


Diffs:
------
diff -r 0fb22a2395e9 -r e0fe7c3c2494 doc/release/CHANGES.txt
--- a/doc/release/CHANGES.txt Wed May 02 17:29:10 2012 -0700
+++ b/doc/release/CHANGES.txt Tue May 15 14:45:15 2012 -0700
@@ -21,6 +21,7 @@
 K 4906 IMAP Store socket leak on connect with ProtocolException
 K 5086 STARTTLS when already using SSL may cause connection to fail
 K 5090 Yahoo: Error reading emails containing "undisclosed recipients"
+<no id> add mail.imap.ignorebodystructuresize to work around server bugs
 
 
                   CHANGES IN THE 1.4.5 RELEASE

diff -r 0fb22a2395e9 -r e0fe7c3c2494 mail/src/main/java/com/sun/mail/imap/IMAPBodyPart.java
--- a/mail/src/main/java/com/sun/mail/imap/IMAPBodyPart.java Wed May 02 17:29:10 2012 -0700
+++ b/mail/src/main/java/com/sun/mail/imap/IMAPBodyPart.java Tue May 15 14:45:15 2012 -0700
@@ -181,7 +181,8 @@
                 message.checkExpunged();
 
                 if (p.isREV1() && (message.getFetchBlockSize() != -1))
- return new IMAPInputStream(message, sectionId, bs.size, pk);
+ return new IMAPInputStream(message, sectionId,
+ message.ignoreBodyStructureSize() ? -1 : bs.size, pk);
 
                 // Else, vanila IMAP4, no partial fetch
 

diff -r 0fb22a2395e9 -r e0fe7c3c2494 mail/src/main/java/com/sun/mail/imap/IMAPInputStream.java
--- a/mail/src/main/java/com/sun/mail/imap/IMAPInputStream.java Wed May 02 17:29:10 2012 -0700
+++ b/mail/src/main/java/com/sun/mail/imap/IMAPInputStream.java Tue May 15 14:45:15 2012 -0700
@@ -1,7 +1,7 @@
 /*
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
  *
- * Copyright (c) 1997-2010 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997-2012 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
@@ -63,6 +63,7 @@
     private int bufcount; // The index one greater than the index of the
                           // last valid byte in 'buf'
     private int bufpos; // The current position within 'buf'
+ private boolean lastBuffer; // is this the last buffer of data?
     private boolean peek; // peek instead of fetch?
     private ByteArray readbuf; // reuse for each read
 
@@ -113,10 +114,11 @@
      */
     private void fill() throws IOException {
         /*
+ * If we've read the last buffer, there's no more to read.
          * If we know the total number of bytes available from this
          * section, let's check if we have consumed that many bytes.
          */
- if (max != -1 && pos >= max) {
+ if (lastBuffer || max != -1 && pos >= max) {
             if (pos == 0)
                 checkSeen();
             readbuf = null; // XXX - return to pool?
@@ -128,6 +130,7 @@
             readbuf = new ByteArray(blksize + slop);
 
         ByteArray ba;
+ int cnt;
         // Acquire MessageCacheLock, to freeze seqnum.
         synchronized (msg.getMessageCacheLock()) {
             try {
@@ -139,7 +142,7 @@
                                 "No content for expunged message");
 
                 int seqnum = msg.getSequenceNumber();
- int cnt = blksize;
+ cnt = blksize;
                 if (max != -1 && pos + blksize > max)
                     cnt = max - pos;
                 if (peek)
@@ -169,6 +172,8 @@
         bufpos = ba.getStart();
         int n = ba.getCount(); // will be zero, if all data has been
                                   // consumed from the server.
+ // if we got less than we asked for, this is the last buffer of data
+ lastBuffer = n < cnt;
         bufcount = bufpos + n;
         pos += n;
     }

diff -r 0fb22a2395e9 -r e0fe7c3c2494 mail/src/main/java/com/sun/mail/imap/IMAPMessage.java
--- a/mail/src/main/java/com/sun/mail/imap/IMAPMessage.java Wed May 02 17:29:10 2012 -0700
+++ b/mail/src/main/java/com/sun/mail/imap/IMAPMessage.java Tue May 15 14:45:15 2012 -0700
@@ -229,6 +229,11 @@
         return ((IMAPStore)folder.getStore()).getFetchBlockSize();
     }
 
+ // Return the block size for FETCH requests
+ protected boolean ignoreBodyStructureSize() {
+ return ((IMAPStore)folder.getStore()).ignoreBodyStructureSize();
+ }
+
     /**
      * Get the "From" attribute.
      */
@@ -583,7 +588,8 @@
 
                 if (p.isREV1() && (getFetchBlockSize() != -1)) // IMAP4rev1
                     return new IMAPInputStream(this, toSection("TEXT"),
- bs != null ? bs.size : -1, pk);
+ bs != null && !ignoreBodyStructureSize() ?
+ bs.size : -1, pk);
 
                 if (p.isREV1()) {
                     BODY b;

diff -r 0fb22a2395e9 -r e0fe7c3c2494 mail/src/main/java/com/sun/mail/imap/IMAPStore.java
--- a/mail/src/main/java/com/sun/mail/imap/IMAPStore.java Wed May 02 17:29:10 2012 -0700
+++ b/mail/src/main/java/com/sun/mail/imap/IMAPStore.java Tue May 15 14:45:15 2012 -0700
@@ -1,7 +1,7 @@
 /*
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
  *
- * Copyright (c) 1997-2011 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997-2012 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
@@ -164,6 +164,8 @@
                                         // in FETCH requests. Defaults to
                                         // 16K
 
+ private boolean ignoreSize; // ignore the size in BODYSTRUCTURE?
+
     private final int statusCacheTimeout; // cache Status for 1 second
 
     private final int appendBufferSize; // max size of msg buffered for append
@@ -432,6 +434,12 @@
                 out.println("DEBUG: mail.imap.fetchsize: " + blksize);
         }
 
+ ignoreSize = PropUtil.getBooleanSessionProperty(session,
+ "mail." + name +".ignorebodystructuresize", false);
+ if (debug)
+ out.println("DEBUG: mail.imap.ignorebodystructuresize: " +
+ ignoreSize);
+
         statusCacheTimeout = PropUtil.getIntSessionProperty(session,
             "mail." + name + ".statuscachetimeout", 1000);
         if (debug)
@@ -1265,6 +1273,13 @@
     }
 
     /**
+ * Ignore the size reported in the BODYSTRUCTURE when fetching data?
+ */
+ boolean ignoreBodyStructureSize() {
+ return ignoreSize;
+ }
+
+ /**
      * Get a reference to the session.
      */
     Session getSession() {

diff -r 0fb22a2395e9 -r e0fe7c3c2494 mail/src/main/java/com/sun/mail/imap/package.html
--- a/mail/src/main/java/com/sun/mail/imap/package.html Wed May 02 17:29:10 2012 -0700
+++ b/mail/src/main/java/com/sun/mail/imap/package.html Tue May 15 14:45:15 2012 -0700
@@ -136,6 +136,21 @@
 </TR>
 
 <TR>
+<TD>mail.imap.ignorebodystructuresize</TD>
+<TD>boolean</TD>
+<TD>The IMAP BODYSTRUCTURE response includes the exact size of each body part.
+Normally, this size is used to determine how much data to fetch for each
+body part.
+Some servers report this size incorrectly in some cases; this property can
+be set to work around such server bugs.
+If this property is set to true, this size is ignored and data is fetched
+until the server reports the end of data.
+This will result in an extra fetch if the data size is a multiple of the
+block size.
+Defaults to false.</TD>
+</TR>
+
+<TR>
 <TD>mail.imap.connectiontimeout</TD>
 <TD>int</TD>
 <TD>Socket connection timeout value in milliseconds.


diff -r e0fe7c3c2494 -r bc39523cca98 doc/release/CHANGES.txt
--- a/doc/release/CHANGES.txt Tue May 15 14:45:15 2012 -0700
+++ b/doc/release/CHANGES.txt Mon Jul 02 11:50:56 2012 -0700
@@ -21,6 +21,7 @@
 K 4906 IMAP Store socket leak on connect with ProtocolException
 K 5086 STARTTLS when already using SSL may cause connection to fail
 K 5090 Yahoo: Error reading emails containing "undisclosed recipients"
+K 5233 Infinite loop if Quota information is not correctly reported by server
 <no id> add mail.imap.ignorebodystructuresize to work around server bugs
 
 

diff -r e0fe7c3c2494 -r bc39523cca98 mail/src/main/java/com/sun/mail/imap/protocol/IMAPProtocol.java
--- a/mail/src/main/java/com/sun/mail/imap/protocol/IMAPProtocol.java Tue May 15 14:45:15 2012 -0700
+++ b/mail/src/main/java/com/sun/mail/imap/protocol/IMAPProtocol.java Mon Jul 02 11:50:56 2012 -0700
@@ -1,7 +1,7 @@
 /*
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
  *
- * Copyright (c) 1997-2011 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997-2012 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
@@ -1917,7 +1917,8 @@
                     ir.readAtomString();
                     // for each quotaroot add a placeholder quota
                     String root = null;
- while ((root = ir.readAtomString()) != null)
+ while ((root = ir.readAtomString()) != null &&
+ root.length() > 0)
                         tab.put(root, new Quota(root));
                     r[i] = null;
                 } else if (ir.keyEquals("QUOTA")) {