SMTP: dot escaping – imported GNU code.
authorFrantišek Kučera <franta-hg@frantovo.cz>
Tue Oct 25 10:16:13 2011 +0200 (2011-10-25)
changeset 107b723308e1359
parent 106 dc04a3c2c557
child 108 fdc075324ef3
SMTP: dot escaping – imported GNU code.
src/org/sonews/util/io/CRLFOutputStream.java
src/org/sonews/util/io/SMTPOutputStream.java
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/org/sonews/util/io/CRLFOutputStream.java	Tue Oct 25 10:16:13 2011 +0200
     1.3 @@ -0,0 +1,155 @@
     1.4 +/* CRLFOutputStream.java --
     1.5 +Copyright (C) 2002, 2003, 2004  Free Software Foundation, Inc.
     1.6 +
     1.7 +This file is part of GNU Classpath.
     1.8 +
     1.9 +GNU Classpath is free software; you can redistribute it and/or modify
    1.10 +it under the terms of the GNU General Public License as published by
    1.11 +the Free Software Foundation; either version 2, or (at your option)
    1.12 +any later version.
    1.13 +
    1.14 +GNU Classpath is distributed in the hope that it will be useful, but
    1.15 +WITHOUT ANY WARRANTY; without even the implied warranty of
    1.16 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    1.17 +General Public License for more details.
    1.18 +
    1.19 +You should have received a copy of the GNU General Public License
    1.20 +along with GNU Classpath; see the file COPYING.  If not, write to the
    1.21 +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    1.22 +02110-1301 USA.
    1.23 +
    1.24 +Linking this library statically or dynamically with other modules is
    1.25 +making a combined work based on this library.  Thus, the terms and
    1.26 +conditions of the GNU General Public License cover the whole
    1.27 +combination.
    1.28 +
    1.29 +As a special exception, the copyright holders of this library give you
    1.30 +permission to link this library with independent modules to produce an
    1.31 +executable, regardless of the license terms of these independent
    1.32 +modules, and to copy and distribute the resulting executable under
    1.33 +terms of your choice, provided that you also meet, for each linked
    1.34 +independent module, the terms and conditions of the license of that
    1.35 +module.  An independent module is a module which is not derived from
    1.36 +or based on this library.  If you modify this library, you may extend
    1.37 +this exception to your version of the library, but you are not
    1.38 +obligated to do so.  If you do not wish to do so, delete this
    1.39 +exception statement from your version. 
    1.40 + */
    1.41 +package org.sonews.util.io; // original package: gnu.java.net
    1.42 +
    1.43 +import java.io.FilterOutputStream;
    1.44 +import java.io.IOException;
    1.45 +import java.io.OutputStream;
    1.46 +import java.io.UnsupportedEncodingException;
    1.47 +
    1.48 +/** 
    1.49 + * An output stream that filters LFs into CR/LF pairs.
    1.50 + *
    1.51 + * @author Chris Burdess (dog@gnu.org)
    1.52 + */
    1.53 +public class CRLFOutputStream extends FilterOutputStream {
    1.54 +
    1.55 +	static final String US_ASCII = "US-ASCII";
    1.56 +	/**
    1.57 +	 * The CR octet.
    1.58 +	 */
    1.59 +	public static final int CR = 13;
    1.60 +	/**
    1.61 +	 * The LF octet.
    1.62 +	 */
    1.63 +	public static final int LF = 10;
    1.64 +	/**
    1.65 +	 * The CR/LF pair.
    1.66 +	 */
    1.67 +	public static final byte[] CRLF = {CR, LF};
    1.68 +	/**
    1.69 +	 * The last byte read.
    1.70 +	 */
    1.71 +	protected int last;
    1.72 +
    1.73 +	/**
    1.74 +	 * Constructs a CR/LF output stream connected to the specified output stream.
    1.75 +	 */
    1.76 +	public CRLFOutputStream(OutputStream out) {
    1.77 +		super(out);
    1.78 +		last = -1;
    1.79 +	}
    1.80 +
    1.81 +	/**
    1.82 +	 * Writes a character to the underlying stream.
    1.83 +	 * @exception IOException if an I/O error occurred
    1.84 +	 */
    1.85 +	@Override
    1.86 +	public void write(int ch) throws IOException {
    1.87 +		if (ch == CR) {
    1.88 +			out.write(CRLF);
    1.89 +		} else if (ch == LF) {
    1.90 +			if (last != CR) {
    1.91 +				out.write(CRLF);
    1.92 +			}
    1.93 +		} else {
    1.94 +			out.write(ch);
    1.95 +		}
    1.96 +		last = ch;
    1.97 +	}
    1.98 +
    1.99 +	/**
   1.100 +	 * Writes a byte array to the underlying stream.
   1.101 +	 * @exception IOException if an I/O error occurred
   1.102 +	 */
   1.103 +	@Override
   1.104 +	public void write(byte[] b) throws IOException {
   1.105 +		write(b, 0, b.length);
   1.106 +	}
   1.107 +
   1.108 +	/**
   1.109 +	 * Writes a portion of a byte array to the underlying stream.
   1.110 +	 * @exception IOException if an I/O error occurred
   1.111 +	 */
   1.112 +	@Override
   1.113 +	public void write(byte[] b, int off, int len) throws IOException {
   1.114 +		int d = off;
   1.115 +		len += off;
   1.116 +		for (int i = off; i < len; i++) {
   1.117 +			switch (b[i]) {
   1.118 +				case CR:
   1.119 +					out.write(b, d, i - d);
   1.120 +					out.write(CRLF, 0, 2);
   1.121 +					d = i + 1;
   1.122 +					break;
   1.123 +				case LF:
   1.124 +					if (last != CR) {
   1.125 +						out.write(b, d, i - d);
   1.126 +						out.write(CRLF, 0, 2);
   1.127 +					}
   1.128 +					d = i + 1;
   1.129 +					break;
   1.130 +			}
   1.131 +			last = b[i];
   1.132 +		}
   1.133 +		if (len - d > 0) {
   1.134 +			out.write(b, d, len - d);
   1.135 +		}
   1.136 +	}
   1.137 +
   1.138 +	/**
   1.139 +	 * Writes the specified ASCII string to the underlying stream.
   1.140 +	 * @exception IOException if an I/O error occurred
   1.141 +	 */
   1.142 +	public void write(String text) throws IOException {
   1.143 +		try {
   1.144 +			byte[] bytes = text.getBytes(US_ASCII);
   1.145 +			write(bytes, 0, bytes.length);
   1.146 +		} catch (UnsupportedEncodingException e) {
   1.147 +			throw new IOException("The US-ASCII encoding is not supported on this system", e);
   1.148 +		}
   1.149 +	}
   1.150 +
   1.151 +	/**
   1.152 +	 * Writes a newline to the underlying stream.
   1.153 +	 * @exception IOException if an I/O error occurred
   1.154 +	 */
   1.155 +	public void writeln() throws IOException {
   1.156 +		out.write(CRLF, 0, 2);
   1.157 +	}
   1.158 +}
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/src/org/sonews/util/io/SMTPOutputStream.java	Tue Oct 25 10:16:13 2011 +0200
     2.3 @@ -0,0 +1,111 @@
     2.4 +/*
     2.5 +GNU-Classpath Extensions: javamail
     2.6 +Copyright (C) 2002 Chris Burdess
     2.7 +
     2.8 +For more information on the classpathx please mail:
     2.9 +nferrier@tapsellferrier.co.uk
    2.10 +
    2.11 +This program is free software; you can redistribute it and/or
    2.12 +modify it under the terms of the GNU Lesser General Public License
    2.13 +as published by the Free Software Foundation; either version 2
    2.14 +of the License, or (at your option) any later version.
    2.15 +
    2.16 +This program is distributed in the hope that it will be useful,
    2.17 +but WITHOUT ANY WARRANTY; without even the implied warranty of
    2.18 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    2.19 +GNU General Public License for more details.
    2.20 +
    2.21 +You should have received a copy of the GNU General Public License
    2.22 +along with this program; if not, write to the Free Software
    2.23 +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
    2.24 + */
    2.25 +package org.sonews.util.io; // original package: gnu.mail.providers.smtp
    2.26 +
    2.27 +import java.io.FilterOutputStream;
    2.28 +import java.io.IOException;
    2.29 +
    2.30 +/**
    2.31 + * An output stream implementing the SMTP specification for dot escaping.
    2.32 + * Objects of this class are intended to be chained with CRLFOutputStream
    2.33 + * instances as all SMTP output is intended to be CRLF-escaped.
    2.34 + *
    2.35 + * @author dog@gnu.org
    2.36 + * @version 0.1
    2.37 + */
    2.38 +public class SMTPOutputStream extends FilterOutputStream {
    2.39 +
    2.40 +	/**
    2.41 +	 * The LF octet.
    2.42 +	 */
    2.43 +	public static final int LF = 0x0a;
    2.44 +	/**
    2.45 +	 * The dot octet.
    2.46 +	 */
    2.47 +	public static final int DOT = 0x2e;
    2.48 +	/**
    2.49 +	 * The last octet read.
    2.50 +	 */
    2.51 +	protected int last;
    2.52 +
    2.53 +	/**
    2.54 +	 * Constructs an SMTP output stream connected to the specified output stream.
    2.55 +	 * The underlying output stream should coordinate proper CRLF pairs at
    2.56 +	 * line ends.
    2.57 +	 * @param out a CRLFOutputStream
    2.58 +	 */
    2.59 +	public SMTPOutputStream(CRLFOutputStream out) {
    2.60 +		super(out);
    2.61 +	}
    2.62 +
    2.63 +	/**
    2.64 +	 * Writes a character to the underlying stream.
    2.65 +	 * @exception IOException if an I/O error occurred
    2.66 +	 */
    2.67 +	@Override
    2.68 +	public void write(int ch) throws IOException {
    2.69 +		if (ch == DOT) {
    2.70 +			if (last == LF) {
    2.71 +				out.write(DOT);
    2.72 +			}
    2.73 +		}
    2.74 +		out.write(ch);
    2.75 +		last = ch;
    2.76 +	}
    2.77 +
    2.78 +	/**
    2.79 +	 * Writes a byte array to the underlying stream.
    2.80 +	 * @exception IOException if an I/O error occurred
    2.81 +	 */
    2.82 +	@Override
    2.83 +	public void write(byte b[]) throws IOException {
    2.84 +		write(b, 0, b.length);
    2.85 +	}
    2.86 +
    2.87 +	/**
    2.88 +	 * Writes a portion of a byte array to the underlying stream.
    2.89 +	 * @exception IOException if an I/O error occurred
    2.90 +	 */
    2.91 +	@Override
    2.92 +	public void write(byte b[], int off, int len) throws IOException {
    2.93 +		int d = off;
    2.94 +		len += off;
    2.95 +		for (int i = off; i < len; i++) {
    2.96 +			switch (b[i]) {
    2.97 +				case DOT:
    2.98 +					int l = (i - d);
    2.99 +					if (l > 0) {
   2.100 +						out.write(b, d, l);
   2.101 +					}
   2.102 +					d = i;
   2.103 +					if (last == LF) {
   2.104 +						out.write(DOT);
   2.105 +					}
   2.106 +					break;
   2.107 +			}
   2.108 +			last = b[i];
   2.109 +		}
   2.110 +		if (len - d > 0) {
   2.111 +			out.write(b, d, len - d);
   2.112 +		}
   2.113 +	}
   2.114 +}