in src/main/java/software/amazon/encryption/s3/internal/ContentMetadataDecodingStrategy.java [183:221]
private static String decodeS3CustomEncoding(final String s) {
final String mimeDecoded;
try {
mimeDecoded = MimeUtility.decodeText(s);
} catch (UnsupportedEncodingException ex) {
throw new S3EncryptionClientException("Unable to decode S3 object metadata: " + s, ex);
}
// Once MIME decoded, we need to recover the correct code points from the second encoding pass
// Otherwise, decryption fails
try {
final StringBuilder stringBuilder = new StringBuilder();
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
final DataOutputStream out = new DataOutputStream(baos);
final byte[] sInBytes = mimeDecoded.getBytes(StandardCharsets.UTF_8);
final char[] sInChars = mimeDecoded.toCharArray();
int nonAsciiChars = 0;
for (int i = 0; i < sInChars.length; i++) {
if (sInChars[i] > 127) {
byte[] buf = {sInBytes[i + nonAsciiChars], sInBytes[i + nonAsciiChars + 1]};
// temporarily re-encode as UTF-8
String wrongString = new String(buf, StandardCharsets.UTF_8);
// write its code point
out.write(wrongString.charAt(0));
nonAsciiChars++;
} else {
if (baos.size() > 0) {
// This is not the most efficient, but we prefer to specify UTF_8
stringBuilder.append(new String(baos.toByteArray(), StandardCharsets.UTF_8));
baos.reset();
}
stringBuilder.append(sInChars[i]);
}
}
return stringBuilder.toString();
} catch (IOException exception) {
throw new S3EncryptionClientException("Unable to decode S3 object metadata: " + s, exception);
}
}