package com.zegoggles.smssync.mail;

import android.content.ContentResolver;
import android.net.Uri;
import android.text.TextUtils;
import com.fsck.k9.mail.Body;
import com.fsck.k9.mail.MessagingException;
import com.fsck.k9.mail.filter.Base64OutputStream;
import com.fsck.k9.mail.internet.MimeBodyPart;
import com.fsck.k9.mail.internet.MimeHeader;
import com.fsck.k9.mail.internet.TextBody;
import org.apache.commons.io.IOUtils;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;

class Attachment {
    public static MimeBodyPart createTextPart(String text) throws MessagingException {
        return new MimeBodyPart(new TextBody(text));
    }

    public static MimeBodyPart createPartFromUri(ContentResolver resolver, Uri uri, String filename, String contentType) throws MessagingException {
        return createPart(new ResolverBody(resolver, uri), filename, contentType);
    }

    public static MimeBodyPart createPartFromFile(File file, String contentType) throws MessagingException {
        return createPart(new FileBody(file), file.getName(), contentType);
    }

    private static MimeBodyPart createPart(Body body, final String filename, final String contentType) throws MessagingException {
        MimeBodyPart part = new MimeBodyPart(body, contentType);

        String contentTypeHeader = TextUtils.isEmpty(contentType) ? "application/octet-stream" : contentType;
        String disposition = "attachment";
        if (!TextUtils.isEmpty(filename)) {
            // should set both name and filename parameters
            // http://www.imc.org/ietf-smtp/mail-archive/msg05023.html
            disposition += encodeRFC2231("filename", filename);
            contentTypeHeader += encodeRFC2231("name", filename);
        }
        part.setHeader(MimeHeader.HEADER_CONTENT_TYPE, contentTypeHeader);
        part.setHeader(MimeHeader.HEADER_CONTENT_DISPOSITION, disposition);
        part.setHeader(MimeHeader.HEADER_CONTENT_TRANSFER_ENCODING, "base64");
        return part;
    }

    private static abstract class Base64Body implements Body {
        @Override
        public void writeTo(OutputStream outputStream) throws IOException, MessagingException {
            InputStream in = getInputStream();
            Base64OutputStream base64Out = new Base64OutputStream(outputStream);
            IOUtils.copy(in, base64Out);
            base64Out.close();
        }
    }

    private static class ResolverBody extends Base64Body {
        private ContentResolver mResolver;
        private Uri mUri;

        public ResolverBody(ContentResolver contentResolver, Uri uri) {
            mResolver = contentResolver;
            mUri = uri;
        }

        public InputStream getInputStream() throws MessagingException {
            try {
                return mResolver.openInputStream(mUri);
            } catch (FileNotFoundException fnfe) {
                /*
                 * Since it's completely normal for us to try to serve up attachments that
                 * have been blown away, we just return an empty stream.
                 */
                return new ByteArrayInputStream(new byte[0]);
            }
        }
    }

    private static class FileBody extends Base64Body {
        private final File file;

        public FileBody(File file) {
            this.file = file;
        }

        @Override
        public InputStream getInputStream() throws MessagingException {
            try {
                return new FileInputStream(file);
            } catch (FileNotFoundException e) {
                return new ByteArrayInputStream(new byte[0]);
            }
        }
    }

    // RFC2231 encoding from geronimo-javamail
    private static final String MIME_SPECIALS = "()<>@,;:\\\"/[]?=" + "\t ";
    private static final String RFC2231_SPECIALS = "*'%" + MIME_SPECIALS;
    private static final char[] HEX_DIGITS = "0123456789ABCDEF".toCharArray();

    private static String encodeRFC2231(String key, String value) {
        StringBuilder buf = new StringBuilder();
        boolean encoded = encodeRFC2231value(value, buf);
        if (encoded) {
            return "; " + key + "*=" + buf.toString();
        } else {
            return "; " + key + "=" + value;
        }
    }

    private static boolean encodeRFC2231value(String value, StringBuilder buf) {
        String charset = "UTF-8";
        buf.append(charset);
        buf.append("''"); // no language
        byte[] bytes;
        try {
            bytes = value.getBytes(charset);
        } catch (UnsupportedEncodingException e) {
            return true;
        }
        boolean encoded = false;
        for (byte aByte : bytes) {
            int ch = aByte & 0xff;
            if (ch <= 32 || ch >= 127 || RFC2231_SPECIALS.indexOf(ch) != -1) {
                buf.append('%');
                buf.append(HEX_DIGITS[ch >> 4]);
                buf.append(HEX_DIGITS[ch & 0xf]);
                encoded = true;
            } else {
                buf.append((char) ch);
            }
        }
        return encoded;
    }
}

@@ -125,16 +125,41 @@
 tUtils;%0A
+import android.util.Log;%0A
 import c
@@ -708,16 +708,62 @@
 ption;%0A%0A
+import static com.zegoggles.smssync.App.TAG;%0A%0A
 class At
@@ -2494,24 +2494,59 @@
 utStream();%0A
+            if (in != null)  %7B%0A    
             
@@ -2626,16 +2626,20 @@
         
+    
 IOUtils.
@@ -2671,16 +2671,20 @@
         
+    
 base64Ou
@@ -2690,24 +2690,111 @@
 ut.close();%0A
+            %7D else %7B%0A                Log.w(TAG, %22input stream is null%22);%0A            %7D%0A
         %7D%0A  

Fix NPE