package com.fsck.k9.preferences;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import android.content.Context;
import android.content.SharedPreferences;
import android.os.Environment;
import android.util.Log;

import com.fsck.k9.Account;
import com.fsck.k9.K9;
import com.fsck.k9.Preferences;
import com.fsck.k9.helper.Utility;


public class StorageExporter {
    private static final String EXPORT_FILENAME = "settings.k9s";


    public static String exportToFile(Context context, boolean includeGlobals,
            Set<String> accountUuids, String encryptionKey)
            throws StorageImportExportException {

        OutputStream os = null;
        try
        {
            File dir = new File(Environment.getExternalStorageDirectory() + File.separator
                                + context.getPackageName());
            dir.mkdirs();
            File file = Utility.createUniqueFile(dir, EXPORT_FILENAME);
            String fileName = file.getAbsolutePath();
            os = new FileOutputStream(fileName);
            exportPreferences(context, os, includeGlobals, accountUuids, encryptionKey);

            // If all went well, we return the name of the file just written.
            return fileName;
        } catch (Exception e) {
            throw new StorageImportExportException();
        } finally {
            if (os != null) {
                try {
                    os.close();
                } catch (IOException ioe) {}
            }
        }
    }

    public static void exportPreferences(Context context, OutputStream os, boolean includeGlobals,
            Set<String> accountUuids, String encryptionKey) throws StorageImportExportException  {

        if (encryptionKey == null) {
            throw new StorageImportExportException("Encryption key required, but none supplied");
        }

        try {
            OutputStreamWriter sw = new OutputStreamWriter(os);
            PrintWriter pf = new PrintWriter(sw);
            pf.println("<?xml version=\"1.0\" encoding=\"utf-8\"?>");

            pf.println("<k9settings version=\"" + 1 + "\">");
            pf.flush();

            Log.i(K9.LOG_TAG, "Exporting preferences");
            K9Krypto krypto = new K9Krypto(encryptionKey, K9Krypto.MODE.ENCRYPT);
            long keysEvaluated = 0;
            long keysExported = 0;

            Preferences preferences = Preferences.getPreferences(context);
            SharedPreferences storage = preferences.getPreferences();

            if (accountUuids == null) {
                Account[] accounts = preferences.getAccounts();
                accountUuids = new HashSet<String>();
                for (Account account : accounts) {
                    accountUuids.add(account.getUuid());
                }
            }

            Map < String, ? extends Object > prefs = storage.getAll();
            for (Map.Entry < String, ? extends Object > entry : prefs.entrySet()) {
                String key = entry.getKey();
                String value = entry.getValue().toString();
                //Log.i(K9.LOG_TAG, "Evaluating key " + key);
                keysEvaluated++;
                String[] comps = key.split("\\.");
                if (comps.length > 1) {
                    String keyUuid = comps[0];
                    if (accountUuids.contains(keyUuid) == false) {
                        //Log.i(K9.LOG_TAG, "Skipping key " + key + " which is not for any current account");
                        continue;
                    }
                } else if (!includeGlobals) {
                    // Skip global config entries if the user didn't request them
                        continue;
                }
                String keyEnc = krypto.encrypt(key);
                String valueEnc = krypto.encrypt(value);
                String output = keyEnc + ":" + valueEnc;
                //Log.i(K9.LOG_TAG, "For key " + key + ", output is " + output);
                pf.println(output);
                keysExported++;

            }

            pf.flush();

            Log.i(K9.LOG_TAG, "Exported " + keysExported + " of " + keysEvaluated + " settings.");

            pf.println("</k9settings>");
            pf.flush();
        } catch (Exception e) {
            throw new StorageImportExportException(e.getLocalizedMessage(), e);
        }
    }
}

@@ -142,71 +142,8 @@
 am;%0A
-import java.io.OutputStreamWriter;%0Aimport java.io.PrintWriter;%0A
 impo
@@ -207,16 +207,53 @@
 til.Set;
+%0Aimport org.xmlpull.v1.XmlSerializer;
 %0A%0Aimport
@@ -375,16 +375,41 @@
 til.Log;
+%0Aimport android.util.Xml;
 %0A%0Aimport
@@ -2056,57 +2056,53 @@
     
-OutputStreamWriter sw = new OutputStreamWrit
+XmlSerializer serializer = Xml.newSerializ
 er(
-os
 );%0A 
@@ -2116,46 +2116,112 @@
     
-PrintWriter pf = new PrintWriter(sw
+serializer.setOutput(os, %22UTF-8%22);%0A%0A            serializer.startDocument(null, Boolean.valueOf(true)
 );%0A
+%0A
     
@@ -2232,150 +2232,264 @@
     
-pf.println(%22%3C?xml version=%5C%221.0%5C%22 encoding=%5C%22utf-8%5C%22?%3E%22);%0A%0A            pf.println(%22%3Ck9settings version=%5C%22%22 + 1 + %22%5C%22%3E%22);%0A            pf.flush(
+// Output with indentation%0A            serializer.setFeature(%22http://xmlpull.org/v1/doc/features.html#indent-output%22, true);%0A%0A            // Root tag%0A            serializer.startTag(null, %22k9settings%22);%0A            serializer.attribute(null, %22version%22, %221%22
 );%0A%0A
@@ -4317,25 +4317,37 @@
     
-pf.println(output
+serializer.text(output + %22%5Cn%22
 );%0A 
@@ -4397,33 +4397,8 @@
  %7D%0A%0A
-            pf.flush();%0A%0A
     
@@ -4509,22 +4509,33 @@
     
-pf.println(%22%3C/
+serializer.endTag(null, %22
 k9se
@@ -4540,17 +4540,16 @@
 settings
-%3E
 %22);%0A    
@@ -4560,10 +4560,56 @@
     
-pf
+serializer.endDocument();%0A            serializer
 .flu
@@ -4610,24 +4610,25 @@
 er.flush();%0A
+%0A
         %7D ca

Use XmlSerializer instead of writing XML tags manually