2011-01-03 13:07:44 -05:00
|
|
|
package com.fsck.k9.mail.internet;
|
|
|
|
|
|
|
|
import java.io.IOException;
|
|
|
|
import java.io.InputStream;
|
|
|
|
import java.nio.charset.MalformedInputException;
|
|
|
|
|
2011-02-06 17:09:48 -05:00
|
|
|
class Iso2022JpToShiftJisInputStream extends InputStream {
|
|
|
|
private enum Charset {
|
2011-01-03 13:07:44 -05:00
|
|
|
ASCII, JISX0201, JISX0208,
|
|
|
|
}
|
|
|
|
|
|
|
|
private InputStream mIn;
|
|
|
|
private Charset charset = Charset.ASCII;
|
|
|
|
private int out;
|
|
|
|
private boolean hasOut = false;
|
|
|
|
|
2011-02-06 17:09:48 -05:00
|
|
|
public Iso2022JpToShiftJisInputStream(InputStream in) {
|
2011-01-03 13:07:44 -05:00
|
|
|
mIn = in;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2011-02-06 17:09:48 -05:00
|
|
|
public int read() throws IOException {
|
|
|
|
if (hasOut) {
|
2011-01-03 13:07:44 -05:00
|
|
|
hasOut = false;
|
|
|
|
return out;
|
|
|
|
}
|
|
|
|
|
|
|
|
int in1 = mIn.read();
|
2011-03-19 05:05:07 -04:00
|
|
|
while (in1 == 0x1b) {
|
2011-01-03 13:07:44 -05:00
|
|
|
in1 = mIn.read();
|
2011-02-06 17:09:48 -05:00
|
|
|
if (in1 == '(') {
|
2011-01-03 13:07:44 -05:00
|
|
|
in1 = mIn.read();
|
|
|
|
if (in1 == 'B' || in1 == 'J')
|
|
|
|
charset = Charset.ASCII;
|
|
|
|
else if (in1 == 'I') // Not defined in RFC 1468 but in CP50221.
|
|
|
|
charset = Charset.JISX0201;
|
|
|
|
else
|
|
|
|
throw new MalformedInputException(0);
|
2011-02-06 17:09:48 -05:00
|
|
|
} else if (in1 == '$') {
|
2011-01-03 13:07:44 -05:00
|
|
|
in1 = mIn.read();
|
|
|
|
if (in1 == '@' || in1 == 'B')
|
|
|
|
charset = Charset.JISX0208;
|
|
|
|
else
|
|
|
|
throw new MalformedInputException(0);
|
2011-02-06 17:09:48 -05:00
|
|
|
} else
|
2011-01-03 13:07:44 -05:00
|
|
|
throw new MalformedInputException(0);
|
|
|
|
in1 = mIn.read();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (in1 == '\n' || in1 == '\r')
|
|
|
|
charset = Charset.ASCII;
|
|
|
|
|
2011-01-29 12:56:58 -05:00
|
|
|
if (in1 < 0x21 || in1 >= 0x7f)
|
2011-01-03 13:07:44 -05:00
|
|
|
return in1;
|
|
|
|
|
2011-02-06 17:09:48 -05:00
|
|
|
switch (charset) {
|
|
|
|
case ASCII:
|
|
|
|
return in1;
|
|
|
|
case JISX0201:
|
|
|
|
return in1 + 0x80;
|
|
|
|
case JISX0208:
|
|
|
|
int in2 = mIn.read();
|
|
|
|
if (in2 < 0x21 || in2 >= 0x7f)
|
|
|
|
throw new MalformedInputException(0);
|
2011-01-03 13:07:44 -05:00
|
|
|
|
2011-02-06 17:09:48 -05:00
|
|
|
int out1 = (in1 + 1) / 2 + (in1 < 0x5f ? 0x70 : 0xb0);
|
|
|
|
int out2 = in2 + (in1 % 2 == 0 ? 0x7e : in2 < 0x60 ? 0x1f : 0x20);
|
2011-01-03 13:07:44 -05:00
|
|
|
|
2011-02-06 17:09:48 -05:00
|
|
|
out = out2;
|
|
|
|
hasOut = true;
|
2011-01-03 13:07:44 -05:00
|
|
|
|
2011-02-06 17:09:48 -05:00
|
|
|
return out1;
|
|
|
|
default:
|
|
|
|
throw new RuntimeException();
|
2011-01-03 13:07:44 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|