in geronimo-mail_2.1_impl/geronimo-mail_2.1_provider/src/main/java/org/apache/geronimo/mail/store/imap/connection/IMAPResponseTokenizer.java [699:813]
public static int decode(String original, int index, StringBuffer result) throws MessagingException {
// look for the section terminator
int terminator = original.indexOf('-', index);
// unmatched?
if (terminator == -1) {
throw new MessagingException("Invalid UTF-7 encoded string");
}
// is this just an escaped "&"?
if (terminator == index + 1) {
// append and skip over this.
result.append('&');
return index + 2;
}
// step over the starting char
index++;
int chars = terminator - index;
int quads = chars / 4;
int residual = chars % 4;
// buffer for decoded characters
byte[] buffer = new byte[4];
int bufferCount = 0;
// process each of the full triplet pairs
for (int i = 0; i < quads; i++) {
byte b1 = decodingTable[original.charAt(index++) & 0xff];
byte b2 = decodingTable[original.charAt(index++) & 0xff];
byte b3 = decodingTable[original.charAt(index++) & 0xff];
byte b4 = decodingTable[original.charAt(index++) & 0xff];
buffer[bufferCount++] = (byte)((b1 << 2) | (b2 >> 4));
buffer[bufferCount++] = (byte)((b2 << 4) | (b3 >> 2));
buffer[bufferCount++] = (byte)((b3 << 6) | b4);
// we've written 3 bytes to the buffer, but we might have a residual from a previous
// iteration to deal with.
if (bufferCount == 4) {
// two complete chars here
b1 = buffer[0];
b2 = buffer[1];
result.append((char)((b1 << 8) + (b2 & 0xff)));
b1 = buffer[2];
b2 = buffer[3];
result.append((char)((b1 << 8) + (b2 & 0xff)));
bufferCount = 0;
}
else {
// we need to save the 3rd byte for the next go around
b1 = buffer[0];
b2 = buffer[1];
result.append((char)((b1 << 8) + (b2 & 0xff)));
buffer[0] = buffer[2];
bufferCount = 1;
}
}
// properly encoded, we should have an even number of bytes left.
switch (residual) {
// no residual...so we better not have an extra in the buffer
case 0:
// this is invalid...we have an odd number of bytes so far,
if (bufferCount == 1) {
throw new MessagingException("Invalid UTF-7 encoded string");
}
// one byte left. This shouldn't be valid. We need at least 2 bytes to
// encode one unprintable char.
case 1:
throw new MessagingException("Invalid UTF-7 encoded string");
// ok, we have two bytes left, which can only encode a single byte. We must have
// a dangling unhandled char.
case 2:
{
if (bufferCount != 1) {
throw new MessagingException("Invalid UTF-7 encoded string");
}
byte b1 = decodingTable[original.charAt(index++) & 0xff];
byte b2 = decodingTable[original.charAt(index++) & 0xff];
buffer[bufferCount++] = (byte)((b1 << 2) | (b2 >> 4));
b1 = buffer[0];
b2 = buffer[1];
result.append((char)((b1 << 8) + (b2 & 0xff)));
break;
}
// we have 2 encoded chars. In this situation, we can't have a leftover.
case 3:
{
// this is invalid...we have an odd number of bytes so far,
if (bufferCount == 1) {
throw new MessagingException("Invalid UTF-7 encoded string");
}
byte b1 = decodingTable[original.charAt(index++) & 0xff];
byte b2 = decodingTable[original.charAt(index++) & 0xff];
byte b3 = decodingTable[original.charAt(index++) & 0xff];
buffer[bufferCount++] = (byte)((b1 << 2) | (b2 >> 4));
buffer[bufferCount++] = (byte)((b2 << 4) | (b3 >> 2));
b1 = buffer[0];
b2 = buffer[1];
result.append((char)((b1 << 8) + (b2 & 0xff)));
break;
}
}
// return the new scan location
return terminator + 1;
}