mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-07 20:17:37 +00:00
173 lines
6.7 KiB
Java
173 lines
6.7 KiB
Java
/* -*- Mode: java; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
|
*
|
|
* The contents of this file are subject to the Mozilla Public License
|
|
* Version 1.0 (the "License"); you may not use this file except in
|
|
* compliance with the License. You may obtain a copy of the License at
|
|
* http://www.mozilla.org/MPL/
|
|
*
|
|
* Software distributed under the License is distributed on an "AS IS"
|
|
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
|
|
* the License for the specific language governing rights and limitations
|
|
* under the License.
|
|
*
|
|
* The Original Code is the Grendel mail/news client.
|
|
*
|
|
* The Initial Developer of the Original Code is Netscape Communications
|
|
* Corporation. Portions created by Netscape are Copyright (C) 1997
|
|
* Netscape Communications Corporation. All Rights Reserved.
|
|
*
|
|
* Created: Jamie Zawinski <jwz@netscape.com>, 28 Aug 1997.
|
|
*
|
|
* Contributors: Edwin Woudt <edwin@woudt.nl>
|
|
*/
|
|
|
|
package grendel.mime.encoder;
|
|
|
|
import calypso.util.ByteBuf;
|
|
import calypso.util.Assert;
|
|
|
|
/** Implements a plaintext -> Quoted-Printable encoder.
|
|
*/
|
|
public class MimeQuotedPrintableEncoder extends MimeEncoder {
|
|
|
|
boolean had_whitespace = false;
|
|
int output_column = 0;
|
|
byte last_code = NUL;
|
|
|
|
static private final byte NUL = 0; // don't encode
|
|
static private final byte ESC = 1; // always encode
|
|
static private final byte SPC = 2; // horizontal whitespace
|
|
static private final byte BOL = 3; // encode if at beginning of line
|
|
static private final byte CR = 4; // carriage return
|
|
static private final byte LF = 5; // linefeed
|
|
|
|
static private final byte map[] = {
|
|
ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC, // 000-007
|
|
ESC, SPC, LF, ESC, ESC, CR, ESC, ESC, // 010-017
|
|
ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC, // 020-027
|
|
ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC, // 030-037
|
|
SPC, NUL, NUL, NUL, NUL, NUL, NUL, NUL, // 040-047 !"#$%&'
|
|
NUL, NUL, NUL, NUL, NUL, NUL, BOL, NUL, // 050-057 ()*+,-./
|
|
NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, // 060-067 01234567
|
|
NUL, NUL, NUL, NUL, NUL, ESC, NUL, NUL, // 070-077 89:;<=>?
|
|
|
|
NUL, NUL, NUL, NUL, NUL, NUL, BOL, NUL, // 100-107 @ABCDEFG
|
|
NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, // 110-117 HIJKLMNO
|
|
NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, // 120-127 PQRSTUVW
|
|
NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, // 130-137 XYZ[\]^_
|
|
NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, // 140-147 `abcdefg
|
|
NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, // 150-157 hijklmno
|
|
NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, // 160-167 pqrstuvw
|
|
NUL, NUL, NUL, NUL, NUL, NUL, NUL, ESC, // 170-177 xyz{|}~
|
|
|
|
ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC, // 200-207
|
|
ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC, // 210-217
|
|
ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC, // 220-227
|
|
ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC, // 230-237
|
|
ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC, // 240-247
|
|
ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC, // 250-257
|
|
ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC, // 260-267
|
|
ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC, // 270-277
|
|
|
|
ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC, // 300-307
|
|
ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC, // 310-317
|
|
ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC, // 320-327
|
|
ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC, // 330-337
|
|
ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC, // 340-347
|
|
ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC, // 350-357
|
|
ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC, // 360-367
|
|
ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC, // 370-377
|
|
};
|
|
|
|
static private final byte hex[] = {
|
|
(byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5', (byte)'6', (byte)'7',
|
|
(byte)'8', (byte)'9', (byte)'A', (byte)'B', (byte)'C', (byte)'D', (byte)'E', (byte)'F'
|
|
};
|
|
|
|
static private final byte crlf[] = "\r\n".getBytes();
|
|
static private final byte eq_crlf[] = "=\r\n".getBytes();
|
|
static private final byte eq_crlf_crlf[] = "=\r\n\r\n".getBytes();
|
|
|
|
|
|
/** Given a sequence of input bytes, produces a sequence of output bytes
|
|
using the quoted-printable encoding. If there are bytes in `out'
|
|
already, the new bytes are appended, so the caller should do
|
|
`out.setLength(0)' first if that's desired.
|
|
*/
|
|
public final void translate(ByteBuf in, ByteBuf out) {
|
|
|
|
byte inb[] = in.toBytes();
|
|
int in_length = in.length();
|
|
|
|
for (int i = 0; i < in_length; i++) {
|
|
byte b = inb[i];
|
|
byte c = map[b];
|
|
|
|
if (c == NUL) { // non-special character
|
|
out.append(b);
|
|
output_column++;
|
|
had_whitespace = false;
|
|
|
|
} else if (c == SPC) { // whitespace
|
|
out.append(b);
|
|
output_column++;
|
|
had_whitespace = true;
|
|
|
|
} else if (c == LF && last_code == CR) {
|
|
// We already processed this linebreak;
|
|
// ignore the LF in the CRLF pair.
|
|
|
|
} else if (c == CR || c == LF) { // start of linebreak
|
|
|
|
if (had_whitespace) {
|
|
// Whitespace cannot be allowed to occur at the end of the line.
|
|
// So we encode " \n" as " =\n\n", that is, the whitespace, a
|
|
// soft line break, and then a hard line break.
|
|
//
|
|
out.append(eq_crlf_crlf);
|
|
had_whitespace = false;
|
|
} else {
|
|
out.append(crlf);
|
|
}
|
|
output_column = 0;
|
|
|
|
} else if (c == BOL && output_column != 0) { // beginning-of-line
|
|
out.append(b); // special, while not
|
|
output_column++; // at beginning-of-line
|
|
had_whitespace = false;
|
|
|
|
} else { // special character
|
|
out.append((byte) '=');
|
|
out.append((byte) hex[0xF & (b >> 4)]);
|
|
out.append((byte) hex[0xF & b]);
|
|
output_column += 3;
|
|
had_whitespace = false;
|
|
}
|
|
|
|
last_code = c;
|
|
|
|
Assert.Assertion(output_column <= 76);
|
|
|
|
if (output_column >= 73) {
|
|
out.append(eq_crlf);
|
|
output_column = 0;
|
|
had_whitespace = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
/** Tell the quoted-printable encoder that no more input data will be
|
|
forthcoming. This may result in output, as a result of flushing the
|
|
internal buffer. This object must not be used again after calling eof().
|
|
If there are bytes in `out' already, the new bytes are appended,
|
|
so the caller should do `out.setLength(0)' first if that's desired.
|
|
*/
|
|
public final void eof(ByteBuf out) {
|
|
if (output_column != 0) {
|
|
out.append(eq_crlf);
|
|
output_column = 0;
|
|
had_whitespace = false;
|
|
}
|
|
}
|
|
}
|