SMTP: correct escaping of messages containing lines with single dot.
authorFrantišek Kučera <franta-hg@frantovo.cz>
Tue, 25 Oct 2011 10:39:57 +0200
changeset 108fdc075324ef3
parent 107 b723308e1359
child 109 03cc47e9daee
SMTP: correct escaping of messages containing lines with single dot.
src/org/sonews/daemon/NNTPConnection.java
src/org/sonews/daemon/command/ArticleCommand.java
src/org/sonews/util/io/CRLFOutputStream.java
     1.1 --- a/src/org/sonews/daemon/NNTPConnection.java	Tue Oct 25 10:16:13 2011 +0200
     1.2 +++ b/src/org/sonews/daemon/NNTPConnection.java	Tue Oct 25 10:39:57 2011 +0200
     1.3 @@ -17,6 +17,7 @@
     1.4   */
     1.5  package org.sonews.daemon;
     1.6  
     1.7 +import java.io.ByteArrayOutputStream;
     1.8  import java.io.IOException;
     1.9  import java.net.InetSocketAddress;
    1.10  import java.net.SocketException;
    1.11 @@ -36,6 +37,8 @@
    1.12  import org.sonews.storage.StorageBackendException;
    1.13  import org.sonews.util.Log;
    1.14  import org.sonews.util.Stats;
    1.15 +import org.sonews.util.io.CRLFOutputStream;
    1.16 +import org.sonews.util.io.SMTPOutputStream;
    1.17  
    1.18  /**
    1.19   * For every SocketChannel (so TCP/IP connection) there is an instance of
    1.20 @@ -306,6 +309,30 @@
    1.21  		this.lineBuffers.addOutputBuffer(ByteBuffer.wrap(rawLines));
    1.22  		writeToChannel(CharBuffer.wrap(NEWLINE), charset, null);
    1.23  	}
    1.24 +	
    1.25 +	/**
    1.26 +	 * Same as {@link #println(byte[]) } but escapes lines containing single dot,
    1.27 +	 * which has special meaning in protocol (end of message).
    1.28 +	 * 
    1.29 +	 * This method is safe to be used for writing messages – if message contains 
    1.30 +	 * a line with single dot, it will be doubled and thus not interpreted 
    1.31 +	 * by NNTP client as end of message
    1.32 +	 * 
    1.33 +	 * @param rawLines
    1.34 +	 * @throws IOException 
    1.35 +	 */
    1.36 +	public void printlnEscapeDots(final byte[] rawLines) throws IOException {
    1.37 +		// TODO: optimalizace
    1.38 +		
    1.39 +		ByteArrayOutputStream baos = new ByteArrayOutputStream(rawLines.length + 10);
    1.40 +		CRLFOutputStream crlfStream = new CRLFOutputStream(baos);
    1.41 +		SMTPOutputStream smtpStream = new SMTPOutputStream(crlfStream);
    1.42 +		smtpStream.write(rawLines);
    1.43 +		
    1.44 +		println(baos.toByteArray());
    1.45 +		
    1.46 +		smtpStream.close();
    1.47 +	}
    1.48  
    1.49  	/**
    1.50  	 * Encodes the given CharBuffer using the given Charset to a bunch of
     2.1 --- a/src/org/sonews/daemon/command/ArticleCommand.java	Tue Oct 25 10:16:13 2011 +0200
     2.2 +++ b/src/org/sonews/daemon/command/ArticleCommand.java	Tue Oct 25 10:39:57 2011 +0200
     2.3 @@ -101,11 +101,11 @@
     2.4  					+ " article retrieved - head and body follow");
     2.5  			conn.println(article.getHeaderSource());
     2.6  			conn.println("");
     2.7 -			conn.println(article.getBody());
     2.8 +			conn.printlnEscapeDots(article.getBody());
     2.9  			conn.println(".");
    2.10  		} else if (command[0].equalsIgnoreCase("BODY")) {
    2.11  			conn.println("222 " + artIndex + " " + article.getMessageID() + " body");
    2.12 -			conn.println(article.getBody());
    2.13 +			conn.printlnEscapeDots(article.getBody());
    2.14  			conn.println(".");
    2.15  		} /*
    2.16  		 * HEAD: This command is mandatory.
     3.1 --- a/src/org/sonews/util/io/CRLFOutputStream.java	Tue Oct 25 10:16:13 2011 +0200
     3.2 +++ b/src/org/sonews/util/io/CRLFOutputStream.java	Tue Oct 25 10:39:57 2011 +0200
     3.3 @@ -46,6 +46,7 @@
     3.4   * An output stream that filters LFs into CR/LF pairs.
     3.5   *
     3.6   * @author Chris Burdess (dog@gnu.org)
     3.7 + * @version classpath-0.98
     3.8   */
     3.9  public class CRLFOutputStream extends FilterOutputStream {
    3.10