Author: norman
Date: Thu Jan  6 10:34:45 2011
New Revision: 1055821

URL: http://svn.apache.org/viewvc?rev=1055821&view=rev
Log:
Make sure we append a CRLF if needed when reading the message via POP3. See 
JAMES-1174

Modified:
    
james/server/trunk/pop3server/src/main/java/org/apache/james/pop3server/core/CRLFTerminatedInputStream.java
    
james/server/trunk/pop3server/src/main/java/org/apache/james/pop3server/core/RetrCmdHandler.java
    
james/server/trunk/pop3server/src/main/java/org/apache/james/pop3server/core/TopCmdHandler.java
    
james/server/trunk/pop3server/src/test/java/org/apache/james/pop3server/CRLFTerminatedInputStreamTest.java

Modified: 
james/server/trunk/pop3server/src/main/java/org/apache/james/pop3server/core/CRLFTerminatedInputStream.java
URL: 
http://svn.apache.org/viewvc/james/server/trunk/pop3server/src/main/java/org/apache/james/pop3server/core/CRLFTerminatedInputStream.java?rev=1055821&r1=1055820&r2=1055821&view=diff
==============================================================================
--- 
james/server/trunk/pop3server/src/main/java/org/apache/james/pop3server/core/CRLFTerminatedInputStream.java
 (original)
+++ 
james/server/trunk/pop3server/src/main/java/org/apache/james/pop3server/core/CRLFTerminatedInputStream.java
 Thu Jan  6 10:34:45 2011
@@ -25,14 +25,17 @@ import java.io.InputStream;
 
 /**
  * This {...@link FilterInputStream} makes sure that the last chars of the 
stream are \r\n
+ * 
+ * See JAMES-1174 for an use case
  *
  */
-public class CRLFTerminatedInputStream extends ReadByteFilterInputStream{
+public class CRLFTerminatedInputStream extends FilterInputStream{
 
     private int last;
     private byte[] extraData;
     private int pos = 0;
-
+    private boolean complete = false;
+    
     private boolean endOfStream = false;
     
     public CRLFTerminatedInputStream(InputStream in) {
@@ -40,33 +43,84 @@ public class CRLFTerminatedInputStream e
     }
 
     @Override
+    public int read(byte[] b, int off, int len) throws IOException {
+        if (endOfStream == false) {
+
+            int r = in.read(b, off, len);
+            if (r == -1) {
+                endOfStream = true;
+                calculateExtraData();
+                
+                return fillArray(b, off, len);
+            } else  {
+                last = b[r -1];
+                return r;
+            }
+        } else {
+            return fillArray(b, off, len);
+        }
+    }
+
+    private int fillArray(byte[] b, int off, int len) {
+        int a = -1;
+        int i = 0;
+        if (complete) {
+            return -1;
+        }
+        while( i < len) {
+            a = readNext();
+            if (a == -1) {
+                complete = true;
+                break;
+            } else {
+                b[off + i++] = (byte) a;
+
+            }
+        }
+        return i;
+    }
+    
+    @Override
+    public int read(byte[] b) throws IOException {
+        return read(b, 0, b.length);
+    }
+
+    @Override
     public int read() throws IOException {
         if (endOfStream == false) {
             int i = super.read();
             if (i == -1) {
                 endOfStream = true;
-                if (last != '\r') {
-                    extraData = new byte[2];
-                    extraData[0] = '\r';
-                    extraData[1] = '\n';
-                } else if (last != '\n') {
-                    extraData = new byte[1];
-                    extraData[0] = '\r';
-                } else {
-                    extraData = null;
-                }
-
+                calculateExtraData();
+                return readNext();
             } else {
                 last = i;
             }
             return i;
 
         } else {
-            if (extraData == null || extraData.length == pos) {
-                return -1;
-            } else {
-                return extraData[pos++];
-            }
+            return readNext();
+        }
+    }
+    
+    private void calculateExtraData() {
+        if (last == '\n') {
+            extraData = null;
+        } else if (last == '\r') {
+            extraData = new byte[1];
+            extraData[0] = '\n';
+        } else {
+            extraData = new byte[2];
+            extraData[0] = '\r';
+            extraData[1] = '\n';
+        }
+       
+    }
+    private int readNext() {
+        if (extraData == null || extraData.length == pos) {
+            return -1;
+        } else {
+            return extraData[pos++];
         }
     }
 }

Modified: 
james/server/trunk/pop3server/src/main/java/org/apache/james/pop3server/core/RetrCmdHandler.java
URL: 
http://svn.apache.org/viewvc/james/server/trunk/pop3server/src/main/java/org/apache/james/pop3server/core/RetrCmdHandler.java?rev=1055821&r1=1055820&r2=1055821&view=diff
==============================================================================
--- 
james/server/trunk/pop3server/src/main/java/org/apache/james/pop3server/core/RetrCmdHandler.java
 (original)
+++ 
james/server/trunk/pop3server/src/main/java/org/apache/james/pop3server/core/RetrCmdHandler.java
 Thu Jan  6 10:34:45 2011
@@ -88,7 +88,9 @@ public class RetrCmdHandler implements C
                         } else {
                             in = createInputStream(content);
                         }
-                        session.writeStream(new ExtraDotInputStream(in));
+                        //session.writeStream(new ExtraDotInputStream(in));
+                        session.writeStream(new ExtraDotInputStream(new 
CRLFTerminatedInputStream(in)));
+
                     } finally {                         
                         // write a single dot to mark message as complete
                         session.writeStream(new 
ByteArrayInputStream(".\r\n".getBytes()));

Modified: 
james/server/trunk/pop3server/src/main/java/org/apache/james/pop3server/core/TopCmdHandler.java
URL: 
http://svn.apache.org/viewvc/james/server/trunk/pop3server/src/main/java/org/apache/james/pop3server/core/TopCmdHandler.java?rev=1055821&r1=1055820&r2=1055821&view=diff
==============================================================================
--- 
james/server/trunk/pop3server/src/main/java/org/apache/james/pop3server/core/TopCmdHandler.java
 (original)
+++ 
james/server/trunk/pop3server/src/main/java/org/apache/james/pop3server/core/TopCmdHandler.java
 Thu Jan  6 10:34:45 2011
@@ -128,7 +128,7 @@ public class TopCmdHandler extends RetrC
                             bodyIn = createInputStream(content);
                         }
                         // write body
-                        session.writeStream(new 
CountingBodyInputStream(bodyIn, lines));
+                        session.writeStream(new CountingBodyInputStream(new 
CRLFTerminatedInputStream(bodyIn), lines));
 
                     } finally {
                         // write a single dot to mark message as complete

Modified: 
james/server/trunk/pop3server/src/test/java/org/apache/james/pop3server/CRLFTerminatedInputStreamTest.java
URL: 
http://svn.apache.org/viewvc/james/server/trunk/pop3server/src/test/java/org/apache/james/pop3server/CRLFTerminatedInputStreamTest.java?rev=1055821&r1=1055820&r2=1055821&view=diff
==============================================================================
--- 
james/server/trunk/pop3server/src/test/java/org/apache/james/pop3server/CRLFTerminatedInputStreamTest.java
 (original)
+++ 
james/server/trunk/pop3server/src/test/java/org/apache/james/pop3server/CRLFTerminatedInputStreamTest.java
 Thu Jan  6 10:34:45 2011
@@ -31,7 +31,30 @@ public class CRLFTerminatedInputStreamTe
 
     public void testCRLFPresent() throws IOException {
         String data = "Subject: test\r\n\r\ndata\r\n";
-        CRLFTerminatedInputStream in = new CRLFTerminatedInputStream(new 
ByteArrayInputStream(data.getBytes()));
+        check(data, data);
+        checkWithArray(data, data);
+
+    }
+    
+    
+    public void testCRPresent() throws IOException {
+        String data = "Subject: test\r\n\r\ndata\r";
+        String expected = data + "\n";
+        check(data, expected);
+        checkWithArray(data, expected);
+    }
+    
+    public void testNonPresent() throws IOException {
+        String data = "Subject: test\r\n\r\ndata";
+        String expected = data + "\r\n";
+        check(data, expected);
+        checkWithArray(data, expected);
+
+    }
+    
+    
+    private void check(String source, String expected) throws IOException {
+        CRLFTerminatedInputStream in = new CRLFTerminatedInputStream(new 
ByteArrayInputStream(source.getBytes()));
         
         ByteArrayOutputStream out = new ByteArrayOutputStream();
         
@@ -43,6 +66,24 @@ public class CRLFTerminatedInputStreamTe
         out.close();
         
         String output = new String(out.toByteArray());
-        assertEquals(data, output);
+        assertEquals(expected, output);
+    }
+    
+    private void checkWithArray(String source, String expected) throws 
IOException {
+        CRLFTerminatedInputStream in = new CRLFTerminatedInputStream(new 
ByteArrayInputStream(source.getBytes()));
+        
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        
+        byte[] buf = new byte[1024];
+        int i = 0;
+        while ((i = in.read(buf)) != -1) {
+            out.write(buf, 0, i);
+        }
+
+        in.close();
+        out.close();
+        
+        String output = new String(out.toByteArray());
+        assertEquals(expected, output);
     }
 }



---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to