private static String decodeS3CustomEncoding()

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);
        }
    }