src/org/sonews/util/io/SMTPOutputStream.java
author František Kučera <franta-hg@frantovo.cz>
Tue, 25 Oct 2011 10:39:57 +0200
changeset 108 fdc075324ef3
parent 107 b723308e1359
permissions -rw-r--r--
SMTP: correct escaping of messages containing lines with single dot.
     1 /*
     2 GNU-Classpath Extensions: javamail
     3 Copyright (C) 2002 Chris Burdess
     4 
     5 For more information on the classpathx please mail:
     6 nferrier@tapsellferrier.co.uk
     7 
     8 This program is free software; you can redistribute it and/or
     9 modify it under the terms of the GNU Lesser General Public License
    10 as published by the Free Software Foundation; either version 2
    11 of the License, or (at your option) any later version.
    12 
    13 This program is distributed in the hope that it will be useful,
    14 but WITHOUT ANY WARRANTY; without even the implied warranty of
    15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    16 GNU General Public License for more details.
    17 
    18 You should have received a copy of the GNU General Public License
    19 along with this program; if not, write to the Free Software
    20 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
    21  */
    22 package org.sonews.util.io; // original package: gnu.mail.providers.smtp
    23 
    24 import java.io.FilterOutputStream;
    25 import java.io.IOException;
    26 
    27 /**
    28  * An output stream implementing the SMTP specification for dot escaping.
    29  * Objects of this class are intended to be chained with CRLFOutputStream
    30  * instances as all SMTP output is intended to be CRLF-escaped.
    31  *
    32  * @author dog@gnu.org
    33  * @version 0.1
    34  */
    35 public class SMTPOutputStream extends FilterOutputStream {
    36 
    37 	/**
    38 	 * The LF octet.
    39 	 */
    40 	public static final int LF = 0x0a;
    41 	/**
    42 	 * The dot octet.
    43 	 */
    44 	public static final int DOT = 0x2e;
    45 	/**
    46 	 * The last octet read.
    47 	 */
    48 	protected int last;
    49 
    50 	/**
    51 	 * Constructs an SMTP output stream connected to the specified output stream.
    52 	 * The underlying output stream should coordinate proper CRLF pairs at
    53 	 * line ends.
    54 	 * @param out a CRLFOutputStream
    55 	 */
    56 	public SMTPOutputStream(CRLFOutputStream out) {
    57 		super(out);
    58 	}
    59 
    60 	/**
    61 	 * Writes a character to the underlying stream.
    62 	 * @exception IOException if an I/O error occurred
    63 	 */
    64 	@Override
    65 	public void write(int ch) throws IOException {
    66 		if (ch == DOT) {
    67 			if (last == LF) {
    68 				out.write(DOT);
    69 			}
    70 		}
    71 		out.write(ch);
    72 		last = ch;
    73 	}
    74 
    75 	/**
    76 	 * Writes a byte array to the underlying stream.
    77 	 * @exception IOException if an I/O error occurred
    78 	 */
    79 	@Override
    80 	public void write(byte b[]) throws IOException {
    81 		write(b, 0, b.length);
    82 	}
    83 
    84 	/**
    85 	 * Writes a portion of a byte array to the underlying stream.
    86 	 * @exception IOException if an I/O error occurred
    87 	 */
    88 	@Override
    89 	public void write(byte b[], int off, int len) throws IOException {
    90 		int d = off;
    91 		len += off;
    92 		for (int i = off; i < len; i++) {
    93 			switch (b[i]) {
    94 				case DOT:
    95 					int l = (i - d);
    96 					if (l > 0) {
    97 						out.write(b, d, l);
    98 					}
    99 					d = i;
   100 					if (last == LF) {
   101 						out.write(DOT);
   102 					}
   103 					break;
   104 			}
   105 			last = b[i];
   106 		}
   107 		if (len - d > 0) {
   108 			out.write(b, d, len - d);
   109 		}
   110 	}
   111 }