# HG changeset patch
# User František Kučera <franta-hg@frantovo.cz>
# Date 1319531997 -7200
# Node ID fdc075324ef353f6dd0bd52cbf1d3065b02870e6
# Parent  b723308e1359cb8713ada964783864d34a5b6601
SMTP: correct escaping of messages containing lines with single dot.

diff -r b723308e1359 -r fdc075324ef3 src/org/sonews/daemon/NNTPConnection.java
--- a/src/org/sonews/daemon/NNTPConnection.java	Tue Oct 25 10:16:13 2011 +0200
+++ b/src/org/sonews/daemon/NNTPConnection.java	Tue Oct 25 10:39:57 2011 +0200
@@ -17,6 +17,7 @@
  */
 package org.sonews.daemon;
 
+import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.net.InetSocketAddress;
 import java.net.SocketException;
@@ -36,6 +37,8 @@
 import org.sonews.storage.StorageBackendException;
 import org.sonews.util.Log;
 import org.sonews.util.Stats;
+import org.sonews.util.io.CRLFOutputStream;
+import org.sonews.util.io.SMTPOutputStream;
 
 /**
  * For every SocketChannel (so TCP/IP connection) there is an instance of
@@ -306,6 +309,30 @@
 		this.lineBuffers.addOutputBuffer(ByteBuffer.wrap(rawLines));
 		writeToChannel(CharBuffer.wrap(NEWLINE), charset, null);
 	}
+	
+	/**
+	 * Same as {@link #println(byte[]) } but escapes lines containing single dot,
+	 * which has special meaning in protocol (end of message).
+	 * 
+	 * This method is safe to be used for writing messages – if message contains 
+	 * a line with single dot, it will be doubled and thus not interpreted 
+	 * by NNTP client as end of message
+	 * 
+	 * @param rawLines
+	 * @throws IOException 
+	 */
+	public void printlnEscapeDots(final byte[] rawLines) throws IOException {
+		// TODO: optimalizace
+		
+		ByteArrayOutputStream baos = new ByteArrayOutputStream(rawLines.length + 10);
+		CRLFOutputStream crlfStream = new CRLFOutputStream(baos);
+		SMTPOutputStream smtpStream = new SMTPOutputStream(crlfStream);
+		smtpStream.write(rawLines);
+		
+		println(baos.toByteArray());
+		
+		smtpStream.close();
+	}
 
 	/**
 	 * Encodes the given CharBuffer using the given Charset to a bunch of
diff -r b723308e1359 -r fdc075324ef3 src/org/sonews/daemon/command/ArticleCommand.java
--- a/src/org/sonews/daemon/command/ArticleCommand.java	Tue Oct 25 10:16:13 2011 +0200
+++ b/src/org/sonews/daemon/command/ArticleCommand.java	Tue Oct 25 10:39:57 2011 +0200
@@ -101,11 +101,11 @@
 					+ " article retrieved - head and body follow");
 			conn.println(article.getHeaderSource());
 			conn.println("");
-			conn.println(article.getBody());
+			conn.printlnEscapeDots(article.getBody());
 			conn.println(".");
 		} else if (command[0].equalsIgnoreCase("BODY")) {
 			conn.println("222 " + artIndex + " " + article.getMessageID() + " body");
-			conn.println(article.getBody());
+			conn.printlnEscapeDots(article.getBody());
 			conn.println(".");
 		} /*
 		 * HEAD: This command is mandatory.
diff -r b723308e1359 -r fdc075324ef3 src/org/sonews/util/io/CRLFOutputStream.java
--- a/src/org/sonews/util/io/CRLFOutputStream.java	Tue Oct 25 10:16:13 2011 +0200
+++ b/src/org/sonews/util/io/CRLFOutputStream.java	Tue Oct 25 10:39:57 2011 +0200
@@ -46,6 +46,7 @@
  * An output stream that filters LFs into CR/LF pairs.
  *
  * @author Chris Burdess (dog@gnu.org)
+ * @version classpath-0.98
  */
 public class CRLFOutputStream extends FilterOutputStream {