blob: 4f823091973ba72163e9a9c213a734d1adc19aad [file] [log] [blame]
package org.bouncycastle.mime.encoding;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
/**
* Input stream that processes quoted-printable data, converting it into what was originally intended.
*/
public class QuotedPrintableInputStream
extends FilterInputStream
{
public QuotedPrintableInputStream(InputStream input)
{
super(input);
}
public int read(byte[] buf, int bufOff, int len) throws IOException
{
int i = 0;
while (i != len)
{
int ch = this.read();
if (ch < 0)
{
break;
}
buf[i + bufOff] = (byte)ch;
i++;
}
if (i == 0)
{
return -1;
}
return i;
}
public int read()
throws IOException
{
int v = in.read();
if (v == -1)
{
return -1;
}
// V was the quote '=' character/
while (v == '=')
{
//
// Get the next character.
//
int j = in.read();
if (j == -1)
{
throw new IllegalStateException("Quoted '=' at end of stream");
}
// For systems generating CRLF line endings.
if (j == '\r')
{
j = in.read();
if (j == '\n')
{
//
// This was a line break that was not actually a line break in the original information.
// So return the next data.
//
j = in.read();
}
v = j;
continue;
}
else if (j == '\n')
{
// As above but without preceding CR.
v = in.read();
continue;
}
else
{
int chr = 0;
if (j >= '0' && j <= '9')
{
chr = j - '0';
}
else if (j >= 'A' && j <= 'F')
{
chr = 10 + (j - 'A');
}
else
{
throw new IllegalStateException("Expecting '0123456789ABCDEF after quote that was not immediately followed by LF or CRLF");
}
chr <<= 4;
j = in.read();
if (j >= '0' && j <= '9')
{
chr |= j - '0';
}
else if (j >= 'A' && j <= 'F')
{
chr |= 10 + (j - 'A');
}
else
{
throw new IllegalStateException("Expecting second '0123456789ABCDEF after quote that was not immediately followed by LF or CRLF");
}
return chr;
}
}
return v;
}
}