# HG changeset patch # User František Kučera # 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 {