diff --git a/AndroidManifest.xml b/AndroidManifest.xml index d35644a58..9e3453ca0 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -67,7 +67,7 @@ @@ -269,10 +269,6 @@ android:name="com.fsck.k9.activity.AccessibleEmailContentActivity" > - - - - - - diff --git a/res/menu/accounts_context.xml b/res/menu/accounts_context.xml index afd94bcb4..e55d13a94 100644 --- a/res/menu/accounts_context.xml +++ b/res/menu/accounts_context.xml @@ -6,17 +6,8 @@ android:title="@string/check_mail_action" /> - - - - - - + diff --git a/res/menu/accounts_option.xml b/res/menu/accounts_option.xml index f03ef2c5b..21b969c39 100644 --- a/res/menu/accounts_option.xml +++ b/res/menu/accounts_option.xml @@ -31,16 +31,8 @@ --> - - - - - - - + android:icon="@android:drawable/ic_menu_preferences" + /> diff --git a/res/menu/folder_list_option.xml b/res/menu/folder_list_option.xml index d768acdf0..0e77995b1 100644 --- a/res/menu/folder_list_option.xml +++ b/res/menu/folder_list_option.xml @@ -70,10 +70,6 @@ android:title="@string/global_settings_action" android:icon="@android:drawable/ic_menu_preferences" /> - - - - Search results Settings Open - Edit account settings - Edit folder settings - Edit global settings + Account settings + Folder settings + Global settings Remove account Clear pending actions (danger!) @@ -1028,18 +1028,4 @@ Welcome to K-9 Mail setup. K-9 is an open source mail client for Android origin » Unable to connect. - - Enter settings encryption password: - Export account settings - Export all settings - Import settings - Exporting settings... - Importing settings... - Exported settings to %s - Imported %s accounts from %s - Imported 1 account from %s - Failed to export settings: %s - Failed from import settings from %s:%s - - diff --git a/src/com/fsck/k9/Account.java b/src/com/fsck/k9/Account.java index 4bbacd1dc..719e4b15a 100644 --- a/src/com/fsck/k9/Account.java +++ b/src/com/fsck/k9/Account.java @@ -21,9 +21,7 @@ import com.fsck.k9.view.ColorChip; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; -import java.util.Collections; import java.util.Date; -import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Random; @@ -437,32 +435,6 @@ public class Account implements BaseAccount { editor.commit(); } - public static int findNewAccountNumber(List accountNumbers) { - int newAccountNumber = -1; - Collections.sort(accountNumbers); - for (int accountNumber : accountNumbers) { - if (accountNumber > newAccountNumber + 1) { - break; - } - newAccountNumber = accountNumber; - } - newAccountNumber++; - return newAccountNumber; - } - - public static List getExistingAccountNumbers(Preferences preferences) { - Account[] accounts = preferences.getAccounts(); - List accountNumbers = new LinkedList(); - for (int i = 0; i < accounts.length; i++) { - accountNumbers.add(accounts[i].getAccountNumber()); - } - return accountNumbers; - } - public static int generateAccountNumber(Preferences preferences) { - List accountNumbers = getExistingAccountNumbers(preferences); - return findNewAccountNumber(accountNumbers); - } - public synchronized void save(Preferences preferences) { SharedPreferences.Editor editor = preferences.getPreferences().edit(); @@ -478,7 +450,19 @@ public class Account implements BaseAccount { * * I bet there is a much smarter way to do this. Anyone like to suggest it? */ - mAccountNumber = generateAccountNumber(preferences); + Account[] accounts = preferences.getAccounts(); + int[] accountNumbers = new int[accounts.length]; + for (int i = 0; i < accounts.length; i++) { + accountNumbers[i] = accounts[i].getAccountNumber(); + } + Arrays.sort(accountNumbers); + for (int accountNumber : accountNumbers) { + if (accountNumber > mAccountNumber + 1) { + break; + } + mAccountNumber = accountNumber; + } + mAccountNumber++; String accountUuids = preferences.getPreferences().getString("accountUuids", ""); accountUuids += (accountUuids.length() != 0 ? "," : "") + mUuid; diff --git a/src/com/fsck/k9/K9.java b/src/com/fsck/k9/K9.java index e08cb02fb..4628d9dc1 100644 --- a/src/com/fsck/k9/K9.java +++ b/src/com/fsck/k9/K9.java @@ -447,9 +447,17 @@ public class K9 extends Application { fontSizes.save(editor); } - public static void loadPrefs(Preferences prefs) { - SharedPreferences sprefs = prefs.getPreferences(); + @Override + public void onCreate() { + maybeSetupStrictMode(); + super.onCreate(); + app = this; + + galleryBuggy = checkForBuggyGallery(); + + Preferences prefs = Preferences.getPreferences(this); + SharedPreferences sprefs = prefs.getPreferences(); DEBUG = sprefs.getBoolean("enableDebugLogging", false); DEBUG_SENSITIVE = sprefs.getBoolean("enableSensitiveLogging", false); mAnimations = sprefs.getBoolean("animations", true); @@ -497,18 +505,7 @@ public class K9 extends Application { K9.setK9Language(sprefs.getString("language", "")); K9.setK9Theme(sprefs.getInt("theme", android.R.style.Theme_Light)); - } - @Override - public void onCreate() { - maybeSetupStrictMode(); - super.onCreate(); - app = this; - - - galleryBuggy = checkForBuggyGallery(); - - loadPrefs(Preferences.getPreferences(this)); /* * We have to give MimeMessage a temp directory because File.createTempFile(String, String) * doesn't work in Android and MimeMessage does not have access to a Context. diff --git a/src/com/fsck/k9/Preferences.java b/src/com/fsck/k9/Preferences.java index 4910150b8..dece28412 100644 --- a/src/com/fsck/k9/Preferences.java +++ b/src/com/fsck/k9/Preferences.java @@ -3,12 +3,7 @@ package com.fsck.k9; import java.util.ArrayList; import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.LinkedList; import java.util.List; -import java.util.Map; - import android.content.Context; import android.content.SharedPreferences; import android.util.Config; @@ -34,8 +29,7 @@ public class Preferences { private Storage mStorage; - private Map accounts = null; - private List accountsInOrder = null; + private List accounts; private Account newAccount; private Context mContext; @@ -51,35 +45,16 @@ public class Preferences { } private synchronized void loadAccounts() { - accounts = new HashMap(); - refreshAccounts(); - } - - public synchronized void refreshAccounts() { - Map newAccountMap = new HashMap(); - accountsInOrder = new LinkedList(); String accountUuids = getPreferences().getString("accountUuids", null); if ((accountUuids != null) && (accountUuids.length() != 0)) { String[] uuids = accountUuids.split(","); + accounts = new ArrayList(uuids.length); for (String uuid : uuids) { - Account account = accounts.get(uuid); - if (account != null) { - newAccountMap.put(uuid, account); - accountsInOrder.add(account); - } else { - Account newAccount = new Account(this, uuid); - newAccountMap.put(uuid, newAccount); - accountsInOrder.add(newAccount); - } + accounts.add(new Account(this, uuid)); } + } else { + accounts = new ArrayList(); } - if ((newAccount != null) && newAccount.getAccountNumber() != -1) { - newAccountMap.put(newAccount.getUuid(), newAccount); - accountsInOrder.add(newAccount); - newAccount = null; - } - - accounts = newAccountMap; } /** @@ -92,7 +67,12 @@ public class Preferences { loadAccounts(); } - return accountsInOrder.toArray(EMPTY_ACCOUNT_ARRAY); + if ((newAccount != null) && newAccount.getAccountNumber() != -1) { + accounts.add(newAccount); + newAccount = null; + } + + return accounts.toArray(EMPTY_ACCOUNT_ARRAY); } /** @@ -101,9 +81,16 @@ public class Preferences { * @return all accounts with {@link Account#isAvailable(Context)} */ public synchronized Collection getAvailableAccounts() { - Account[] allAccounts = getAccounts(); + if (accounts == null) { + loadAccounts(); + } + + if ((newAccount != null) && newAccount.getAccountNumber() != -1) { + accounts.add(newAccount); + newAccount = null; + } Collection retval = new ArrayList(accounts.size()); - for (Account account : allAccounts) { + for (Account account : accounts) { if (account.isAvailable(mContext)) { retval.add(account); } @@ -116,22 +103,28 @@ public class Preferences { if (accounts == null) { loadAccounts(); } - Account account = accounts.get(uuid); - return account; + for (Account account : accounts) { + if (account.getUuid().equals(uuid)) { + return account; + } + } + + if ((newAccount != null) && newAccount.getUuid().equals(uuid)) { + return newAccount; + } + + return null; } public synchronized Account newAccount() { newAccount = new Account(K9.app); - accounts.put(newAccount.getUuid(), newAccount); - accountsInOrder.add(newAccount); return newAccount; } public synchronized void deleteAccount(Account account) { - accounts.remove(account.getUuid()); - accountsInOrder.remove(account); + accounts.remove(account); account.delete(this); if (newAccount == account) { diff --git a/src/com/fsck/k9/activity/Accounts.java b/src/com/fsck/k9/activity/Accounts.java index e7a9213ce..025a95058 100644 --- a/src/com/fsck/k9/activity/Accounts.java +++ b/src/com/fsck/k9/activity/Accounts.java @@ -3,13 +3,11 @@ package com.fsck.k9.activity; import android.app.AlertDialog; import android.app.Dialog; -import android.content.ContentResolver; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; -import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.util.Log; @@ -31,8 +29,6 @@ import com.fsck.k9.controller.MessagingListener; import com.fsck.k9.mail.Flag; import com.fsck.k9.view.ColorChip; -import java.io.FileNotFoundException; -import java.io.InputStream; import java.util.*; import java.util.concurrent.ConcurrentHashMap; @@ -63,8 +59,6 @@ public class Accounts extends K9ListActivity implements OnItemClickListener, OnC private SearchAccount unreadAccount = null; private SearchAccount integratedInboxAccount = null; private FontSizes mFontSizes = K9.getFontSizes(); - - private static final int ACTIVITY_REQUEST_PICK_SETTINGS_FILE = 1; class AccountsHandler extends Handler { private void setViewTitle() { @@ -135,12 +129,7 @@ public class Accounts extends K9ListActivity implements OnItemClickListener, OnC }); } } - - public void setProgress(boolean progress) - { - mHandler.progress(progress); - } - + ActivityListener mListener = new ActivityListener() { @Override public void informUserOfStatus() { @@ -593,9 +582,6 @@ public class Accounts extends K9ListActivity implements OnItemClickListener, OnC case R.id.recreate: onRecreate(realAccount); break; - case R.id.export: - onExport(realAccount); - break; } return true; } @@ -642,12 +628,6 @@ public class Accounts extends K9ListActivity implements OnItemClickListener, OnC case R.id.search: onSearchRequested(); break; - case R.id.export_all: - onExport(null); - break; - case R.id.import_settings: - onImport(); - break; default: return super.onOptionsItemSelected(item); } @@ -761,100 +741,6 @@ public class Accounts extends K9ListActivity implements OnItemClickListener, OnC } } } - - private void onImport() - { - Intent i = new Intent(Intent.ACTION_GET_CONTENT); - i.addCategory(Intent.CATEGORY_OPENABLE); - i.setType("*/*"); - startActivityForResult(Intent.createChooser(i, null), ACTIVITY_REQUEST_PICK_SETTINGS_FILE); - } - - @Override - protected void onActivityResult(int requestCode, int resultCode, Intent data) - { - Log.i(K9.LOG_TAG, "onActivityResult requestCode = " + requestCode + ", resultCode = " + resultCode + ", data = " + data); - if (resultCode != RESULT_OK) - return; - if (data == null) - { - return; - } - switch (requestCode) - { - case ACTIVITY_REQUEST_PICK_SETTINGS_FILE: - onImport(data.getData()); - break; - } - } - - private void onImport(Uri uri) - { - Log.i(K9.LOG_TAG, "onImport importing from URI " + uri.getPath()); - try - { - final String fileName = uri.getPath(); - ContentResolver resolver = getContentResolver(); - final InputStream is = resolver.openInputStream(uri); - - PasswordEntryDialog dialog = new PasswordEntryDialog(this, getString(R.string.settings_encryption_password_prompt), - new PasswordEntryDialog.PasswordEntryListener() - { - public void passwordChosen(String chosenPassword) - { - String toastText = Accounts.this.getString(R.string.settings_importing ); - Toast toast = Toast.makeText(Accounts.this.getApplication(), toastText, Toast.LENGTH_SHORT); - toast.show(); - mHandler.progress(true); - AsyncUIProcessor.getInstance(Accounts.this.getApplication()).importSettings(is, chosenPassword, new ImportListener() - { - public void failure(final String message, Exception e) - { - Accounts.this.runOnUiThread(new Runnable() - { - public void run() - { - mHandler.progress(false); - String toastText = Accounts.this.getString(R.string.settings_import_failure, fileName, message ); - Toast toast = Toast.makeText(Accounts.this.getApplication(), toastText, 1); - toast.show(); - } - }); - } - - public void importSuccess(final int numAccounts) - { - Accounts.this.runOnUiThread(new Runnable() - { - public void run() - { - mHandler.progress(false); - String toastText = - numAccounts != 1 - ? Accounts.this.getString(R.string.settings_import_success_multiple, numAccounts, fileName ) - : Accounts.this.getString(R.string.settings_import_success_single, fileName ); - Toast toast = Toast.makeText(Accounts.this.getApplication(), toastText, 1); - toast.show(); - refresh(); - } - }); - } - }); - } - - public void cancel() - { - } - }); - dialog.show(); - } - catch (FileNotFoundException fnfe) - { - String toastText = Accounts.this.getString(R.string.settings_import_failure, uri.getPath(), fnfe.getMessage() ); - Toast toast = Toast.makeText(Accounts.this.getApplication(), toastText, 1); - toast.show(); - } - } class AccountsAdapter extends ArrayAdapter { public AccountsAdapter(BaseAccount[] accounts) { diff --git a/src/com/fsck/k9/activity/ActivityListener.java b/src/com/fsck/k9/activity/ActivityListener.java index 732ffda92..432e87da2 100644 --- a/src/com/fsck/k9/activity/ActivityListener.java +++ b/src/com/fsck/k9/activity/ActivityListener.java @@ -204,6 +204,7 @@ public class ActivityListener extends MessagingListener { return mFolderCompleted; } + public int getFolderTotal() { return mFolderTotal; } diff --git a/src/com/fsck/k9/activity/AsyncUIProcessor.java b/src/com/fsck/k9/activity/AsyncUIProcessor.java deleted file mode 100644 index 4492b4869..000000000 --- a/src/com/fsck/k9/activity/AsyncUIProcessor.java +++ /dev/null @@ -1,100 +0,0 @@ -package com.fsck.k9.activity; - -import java.io.File; -import java.io.InputStream; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; - -import android.app.Application; -import android.os.Environment; - -import com.fsck.k9.K9; -import com.fsck.k9.helper.Utility; -import com.fsck.k9.preferences.StorageExporter; -import com.fsck.k9.preferences.StorageImporter; - -/** - * The class should be used to run long-running processes invoked from the UI that - * do not affect the Stores. There are probably pieces of MessagingController - * that can be moved here. - * - */ -public class AsyncUIProcessor { - - private final ExecutorService threadPool = Executors.newCachedThreadPool(); - private Application mApplication; - private static AsyncUIProcessor inst = null; - private AsyncUIProcessor(Application application) { - mApplication = application; - } - public synchronized static AsyncUIProcessor getInstance(Application application) { - if (inst == null) { - inst = new AsyncUIProcessor(application); - } - return inst; - } - public void exportSettings(final String uuid, final String encryptionKey, final ExportListener listener) { - threadPool.execute(new Runnable() { - - @Override - public void run() { - try { - // Do not store with application files. Settings exports should *not* be - // deleted when the application is uninstalled - File dir = new File(Environment.getExternalStorageDirectory() + File.separator - + mApplication.getPackageName()); - dir.mkdirs(); - File file = Utility.createUniqueFile(dir, "settings.k9s"); - String fileName = file.getAbsolutePath(); - StorageExporter.exportPreferences(mApplication, uuid, fileName, encryptionKey); - if (listener != null) { - listener.exportSuccess(fileName); - } - } catch (Exception e) { - listener.failure(e.getLocalizedMessage(), e); - } - } - } - ); - - } - public void importSettings(final String fileName, final String encryptionKey, final ImportListener listener) { - threadPool.execute(new Runnable() { - - @Override - public void run() { - try { - int numAccounts = StorageImporter.importPreferences(mApplication, fileName, encryptionKey); - K9.setServicesEnabled(mApplication); - if (listener != null) { - listener.importSuccess(numAccounts); - } - } catch (Exception e) { - listener.failure(e.getLocalizedMessage(), e); - } - } - } - ); - - } - public void importSettings(final InputStream inputStream, final String encryptionKey, final ImportListener listener) { - threadPool.execute(new Runnable() { - - @Override - public void run() { - try { - int numAccounts = StorageImporter.importPreferences(mApplication, inputStream, encryptionKey); - K9.setServicesEnabled(mApplication); - if (listener != null) { - listener.importSuccess(numAccounts); - } - } catch (Exception e) { - listener.failure(e.getLocalizedMessage(), e); - } - } - } - ); - - } - -} diff --git a/src/com/fsck/k9/activity/ExportHelper.java b/src/com/fsck/k9/activity/ExportHelper.java deleted file mode 100644 index 864689935..000000000 --- a/src/com/fsck/k9/activity/ExportHelper.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.fsck.k9.activity; - -import android.app.Activity; -import android.widget.Toast; - -import com.fsck.k9.Account; -import com.fsck.k9.R; - -public class ExportHelper { - public static void exportSettings(final Activity activity, final Progressable progressable, final Account account) { - PasswordEntryDialog dialog = new PasswordEntryDialog(activity, activity.getString(R.string.settings_encryption_password_prompt), - new PasswordEntryDialog.PasswordEntryListener() { - public void passwordChosen(String chosenPassword) { - String toastText = activity.getString(R.string.settings_exporting); - Toast toast = Toast.makeText(activity, toastText, Toast.LENGTH_SHORT); - toast.show(); - progressable.setProgress(true); - String uuid = null; - if (account != null) { - uuid = account.getUuid(); - } - AsyncUIProcessor.getInstance(activity.getApplication()).exportSettings(uuid, chosenPassword, - new ExportListener() { - public void failure(final String message, Exception e) { - activity.runOnUiThread(new Runnable() { - public void run() { - progressable.setProgress(false); - String toastText = activity.getString(R.string.settings_export_failure, message); - Toast toast = Toast.makeText(activity.getApplication(), toastText, Toast.LENGTH_LONG); - toast.show(); - } - }); - } - - public void exportSuccess(final String fileName) { - activity.runOnUiThread(new Runnable() { - public void run() { - progressable.setProgress(false); - String toastText = activity.getString(R.string.settings_export_success, fileName); - Toast toast = Toast.makeText(activity.getApplication(), toastText, Toast.LENGTH_LONG); - toast.show(); - } - }); - } - }); - } - - public void cancel() { - } - }); - dialog.show(); - } - -} diff --git a/src/com/fsck/k9/activity/ExportListener.java b/src/com/fsck/k9/activity/ExportListener.java deleted file mode 100644 index 6c2b6f3a6..000000000 --- a/src/com/fsck/k9/activity/ExportListener.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.fsck.k9.activity; - -public interface ExportListener { - public void exportSuccess(String fileName); - - public void failure(String message, Exception e); - -} diff --git a/src/com/fsck/k9/activity/FolderList.java b/src/com/fsck/k9/activity/FolderList.java index b5900bc84..55fc93076 100644 --- a/src/com/fsck/k9/activity/FolderList.java +++ b/src/com/fsck/k9/activity/FolderList.java @@ -150,12 +150,7 @@ public class FolderList extends K9ListActivity { }); } } - - public void setProgress(boolean progress) - { - mHandler.progress(progress); - } - + /** * This class is responsible for reloading the list of local messages for a * given folder, notifying the adapter that the message have been loaded and @@ -543,15 +538,7 @@ public class FolderList extends K9ListActivity { onCompact(mAccount); return true; - - case R.id.export: - onExport(mAccount); - return true; - - case R.id.export_all: - onExport(null); - return true; - + case R.id.display_1st_class: { setDisplayMode(FolderMode.FIRST_CLASS); return true; diff --git a/src/com/fsck/k9/activity/ImportListener.java b/src/com/fsck/k9/activity/ImportListener.java deleted file mode 100644 index 442b612ee..000000000 --- a/src/com/fsck/k9/activity/ImportListener.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.fsck.k9.activity; - -public interface ImportListener { - public void importSuccess(int numAccounts); - - public void failure(String message, Exception e); - -} diff --git a/src/com/fsck/k9/activity/K9Activity.java b/src/com/fsck/k9/activity/K9Activity.java index d9b29817d..3fa72700b 100644 --- a/src/com/fsck/k9/activity/K9Activity.java +++ b/src/com/fsck/k9/activity/K9Activity.java @@ -15,13 +15,11 @@ import android.view.animation.AccelerateInterpolator; import android.view.animation.Animation; import android.view.animation.TranslateAnimation; import android.widget.ScrollView; - -import com.fsck.k9.Account; import com.fsck.k9.K9; import com.fsck.k9.helper.DateFormatter; -public class K9Activity extends Activity implements Progressable { +public class K9Activity extends Activity { private GestureDetector gestureDetector; protected ScrollView mTopView; @@ -163,11 +161,6 @@ public class K9Activity extends Activity implements Progressable { return false; } } - public void setProgress(boolean progress) { - } - public void onExport(final Account account) { - ExportHelper.exportSettings(this, this, account); - } } diff --git a/src/com/fsck/k9/activity/K9ListActivity.java b/src/com/fsck/k9/activity/K9ListActivity.java index 52887bd95..204182be2 100644 --- a/src/com/fsck/k9/activity/K9ListActivity.java +++ b/src/com/fsck/k9/activity/K9ListActivity.java @@ -1,17 +1,15 @@ package com.fsck.k9.activity; import android.app.ListActivity; -import android.os.Bundle; import android.util.Log; import android.view.KeyEvent; import android.widget.AdapterView; import android.widget.ListView; - -import com.fsck.k9.Account; +import android.os.Bundle; import com.fsck.k9.K9; import com.fsck.k9.helper.DateFormatter; -public class K9ListActivity extends ListActivity implements Progressable { +public class K9ListActivity extends ListActivity { @Override public void onCreate(Bundle icicle) { K9Activity.setLanguage(this, K9.getK9Language()); @@ -89,12 +87,4 @@ public class K9ListActivity extends ListActivity implements Progressable { } return super.onKeyUp(keyCode, event); } - - public void setProgress(boolean progress) { - } - - public void onExport(final Account account) { - ExportHelper.exportSettings(this, this, account); - } - } diff --git a/src/com/fsck/k9/activity/MessageList.java b/src/com/fsck/k9/activity/MessageList.java index edfc255d4..3627a9efe 100644 --- a/src/com/fsck/k9/activity/MessageList.java +++ b/src/com/fsck/k9/activity/MessageList.java @@ -518,12 +518,7 @@ public class MessageList }); } } - - public void setProgress(boolean progress) - { - mHandler.progress(progress); - } - + public static void actionHandleFolder(Context context, Account account, String folder) { Intent intent = actionHandleFolderIntent(context, account, folder); context.startActivity(intent); @@ -1402,14 +1397,6 @@ public class MessageList onEditPrefs(); return true; } - case R.id.export: { - onExport(mAccount); - return true; - } - case R.id.export_all: { - onExport(null); - return true; - } } if (mQueryString != null) { diff --git a/src/com/fsck/k9/activity/PasswordEntryDialog.java b/src/com/fsck/k9/activity/PasswordEntryDialog.java deleted file mode 100644 index c24d23456..000000000 --- a/src/com/fsck/k9/activity/PasswordEntryDialog.java +++ /dev/null @@ -1,78 +0,0 @@ -package com.fsck.k9.activity; - -import com.fsck.k9.R; - -import android.app.AlertDialog; -import android.app.AlertDialog.Builder; -import android.content.Context; -import android.content.DialogInterface; -import android.text.Editable; -import android.text.TextWatcher; -import android.view.LayoutInflater; -import android.view.View; -import android.widget.Button; -import android.widget.EditText; - -public class PasswordEntryDialog { - public interface PasswordEntryListener { - void passwordChosen(String chosenPassword); - void cancel(); - } - PasswordEntryListener listener; - private EditText passwordView; - AlertDialog dialog; - public PasswordEntryDialog(Context context, String headerText, PasswordEntryListener listener) { - this.listener = listener; - View view = LayoutInflater.from(context).inflate(R.layout.password_entry_dialog, null); - Builder builder = new AlertDialog.Builder(context); - passwordView = (EditText)view.findViewById(R.id.password_text_box); - - builder.setView(view); - builder.setPositiveButton(R.string.okay_action, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - if (PasswordEntryDialog.this.listener != null) { - String chosenPassword = passwordView.getText().toString(); - PasswordEntryDialog.this.listener.passwordChosen(chosenPassword); - } - } - }); - builder.setNegativeButton(R.string.cancel_action, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - if (PasswordEntryDialog.this.listener != null) { - PasswordEntryDialog.this.listener.cancel(); - } - } - }); - dialog = builder.create(); - passwordView.addTextChangedListener(new TextWatcher() { - - @Override - public void afterTextChanged(Editable arg0) { } - - @Override - public void beforeTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) { } - - @Override - public void onTextChanged(CharSequence arg0, int arg1, int arg2, - int arg3) { - - Button okButton = dialog.getButton(DialogInterface.BUTTON_POSITIVE); - String chosenPassword = passwordView.getText().toString(); - okButton.setEnabled(chosenPassword.length() > 0); - - } - }); - - dialog.setMessage(headerText); - - - } - public void show() { - dialog.show(); - Button okButton = dialog.getButton(DialogInterface.BUTTON_POSITIVE); - okButton.setEnabled(false); - } - -} diff --git a/src/com/fsck/k9/activity/Progressable.java b/src/com/fsck/k9/activity/Progressable.java deleted file mode 100644 index 5201e99b3..000000000 --- a/src/com/fsck/k9/activity/Progressable.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.fsck.k9.activity; - -public interface Progressable { - public void setProgress(boolean progress); -} diff --git a/src/com/fsck/k9/helper/DateFormatter.java b/src/com/fsck/k9/helper/DateFormatter.java index f964b2183..12a9e1a31 100644 --- a/src/com/fsck/k9/helper/DateFormatter.java +++ b/src/com/fsck/k9/helper/DateFormatter.java @@ -75,10 +75,6 @@ public class DateFormatter { return sChosenFormat; } - public static void clearChosenFormat() { - sChosenFormat = null; - } - public static DateFormat getDateFormat(Context context) { String formatString = getFormat(context); return getDateFormat(context, formatString); diff --git a/src/com/fsck/k9/preferences/IStorageImporter.java b/src/com/fsck/k9/preferences/IStorageImporter.java deleted file mode 100644 index 6702c4f80..000000000 --- a/src/com/fsck/k9/preferences/IStorageImporter.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.fsck.k9.preferences; - -import com.fsck.k9.Preferences; - -import android.content.SharedPreferences; - -public interface IStorageImporter { - public abstract int importPreferences(Preferences preferences, SharedPreferences.Editor context, String data, String encryptionKey) throws StorageImportExportException; -} \ No newline at end of file diff --git a/src/com/fsck/k9/preferences/SimpleCrypto.java b/src/com/fsck/k9/preferences/SimpleCrypto.java deleted file mode 100644 index f496c9b30..000000000 --- a/src/com/fsck/k9/preferences/SimpleCrypto.java +++ /dev/null @@ -1,94 +0,0 @@ -package com.fsck.k9.preferences; - -import java.security.SecureRandom; - -import javax.crypto.Cipher; -import javax.crypto.KeyGenerator; -import javax.crypto.SecretKey; -import javax.crypto.spec.SecretKeySpec; - -import org.apache.commons.codec.binary.Base64; - - - -/** - * Copied from: - * http://www.androidsnippets.org/snippets/39/index.html - * a page which had no licensing or copyright notice - * and appeared to be intended for public use - * package net.sf.andhsli.hotspotlogin; - * Usage: - *
- * String crypto = SimpleCrypto.encrypt(masterpassword, cleartext)
- * ...
- * String cleartext = SimpleCrypto.decrypt(masterpassword, crypto)
- * 
- * @author ferenc.hechler - */ -public class SimpleCrypto { - - public static String encrypt(String seed, String cleartext, Base64 base64) throws Exception { - byte[] rawKey = getRawKey(seed.getBytes()); - byte[] result = encrypt(rawKey, cleartext.getBytes()); - return new String(base64.encode(result)); - } - - public static String decrypt(String seed, String encrypted, Base64 base64) throws Exception { - byte[] rawKey = getRawKey(seed.getBytes()); - byte[] enc = base64.decode(encrypted.getBytes()); - byte[] result = decrypt(rawKey, enc); - return new String(result); - } - - private static byte[] getRawKey(byte[] seed) throws Exception { - KeyGenerator kgen = KeyGenerator.getInstance("AES"); - SecureRandom sr = SecureRandom.getInstance("SHA1PRNG"); - sr.setSeed(seed); - kgen.init(128, sr); // 192 and 256 bits may not be available - SecretKey skey = kgen.generateKey(); - byte[] raw = skey.getEncoded(); - return raw; - } - - - private static byte[] encrypt(byte[] raw, byte[] clear) throws Exception { - SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES"); - Cipher cipher = Cipher.getInstance("AES"); - cipher.init(Cipher.ENCRYPT_MODE, skeySpec); - byte[] encrypted = cipher.doFinal(clear); - return encrypted; - } - - private static byte[] decrypt(byte[] raw, byte[] encrypted) throws Exception { - SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES"); - Cipher cipher = Cipher.getInstance("AES"); - cipher.init(Cipher.DECRYPT_MODE, skeySpec); - byte[] decrypted = cipher.doFinal(encrypted); - return decrypted; - } - -// -// public static byte[] toByte(String hexString) { -// int len = hexString.length()/2; -// byte[] result = new byte[len]; -// for (int i = 0; i < len; i++) -// result[i] = Integer.valueOf(hexString.substring(2*i, 2*i+2), 16).byteValue(); -// return result; -// } -// -// public static String toHex(byte[] buf) { -// if (buf == null) -// return ""; -// StringBuffer result = new StringBuffer(2*buf.length); -// for (int i = 0; i < buf.length; i++) { -// appendHex(result, buf[i]); -// } -// return result.toString(); -// } -// private final static String HEX = "0123456789ABCDEF"; -// private static void appendHex(StringBuffer sb, byte b) { -// sb.append(HEX.charAt((b>>4)&0x0f)).append(HEX.charAt(b&0x0f)); -// } -// -} - diff --git a/src/com/fsck/k9/preferences/StorageExporter.java b/src/com/fsck/k9/preferences/StorageExporter.java deleted file mode 100644 index acf5447a8..000000000 --- a/src/com/fsck/k9/preferences/StorageExporter.java +++ /dev/null @@ -1,91 +0,0 @@ -package com.fsck.k9.preferences; - -import java.io.File; -import java.io.IOException; -import java.io.PrintWriter; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - -import org.apache.commons.codec.binary.Base64; - -import com.fsck.k9.Account; -import com.fsck.k9.K9; -import com.fsck.k9.Preferences; - -import android.content.Context; -import android.content.SharedPreferences; -import android.util.Log; - -public class StorageExporter { - //public static String VALIDITY = "K-9MailExport"; // Does outputting a fixed string in a known location make the encrypted data easier to break? - public static void exportPreferences(Context context, String uuid, String fileName, String encryptionKey) throws StorageImportExportException { - try { - Base64 base64 = new Base64(); - File outFile = new File(fileName); - PrintWriter pf = new PrintWriter(outFile); - long keysEvaluated = 0; - long keysExported = 0; - pf.println(""); - - // String testval = SimpleCrypto.encrypt(encryptionKey, VALIDITY); - - pf.print(""); - Log.i(K9.LOG_TAG, "Exporting preferences for account " + uuid + " to file " + fileName); - - Preferences preferences = Preferences.getPreferences(context); - SharedPreferences storage = preferences.getPreferences(); - - Account[] accounts = preferences.getAccounts(); - Set accountUuids = new HashSet(); - 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++; - if (uuid != null) { - String[] comps = key.split("\\."); - String keyUuid = comps[0]; - //Log.i(K9.LOG_TAG, "Got key uuid " + keyUuid); - if (uuid.equals(keyUuid) == false) { - //Log.i(K9.LOG_TAG, "Skipping key " + key + " which is for another account or global"); - continue; - } - } else { - 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; - } - } - } - String keyEnc = SimpleCrypto.encrypt(encryptionKey, key, base64); - String valueEnc = SimpleCrypto.encrypt(encryptionKey, value, base64); - String output = keyEnc + ":" + valueEnc; - //Log.i(K9.LOG_TAG, "For key " + key + ", output is " + output); - pf.println(output); - keysExported++; - - } - - pf.println(""); - pf.close(); - - Log.i(K9.LOG_TAG, "Exported " + keysExported + " settings of " + keysEvaluated - + " total for preferences for account " + uuid + " to file " + fileName + " which is size " + outFile.length()); - } catch (IOException ie) { - throw new StorageImportExportException("Unable to export settings", ie); - } catch (Exception e) { - throw new StorageImportExportException("Unable to encrypt settings", e); - } - } -} diff --git a/src/com/fsck/k9/preferences/StorageImportExportException.java b/src/com/fsck/k9/preferences/StorageImportExportException.java deleted file mode 100644 index bc2e10592..000000000 --- a/src/com/fsck/k9/preferences/StorageImportExportException.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.fsck.k9.preferences; - -public class StorageImportExportException extends Exception { - - public StorageImportExportException() { - super(); - } - - public StorageImportExportException(String detailMessage, Throwable throwable) { - super(detailMessage, throwable); - } - - public StorageImportExportException(String detailMessage) { - super(detailMessage); - } - - public StorageImportExportException(Throwable throwable) { - super(throwable); - } - -} diff --git a/src/com/fsck/k9/preferences/StorageImporter.java b/src/com/fsck/k9/preferences/StorageImporter.java deleted file mode 100644 index 4991d266d..000000000 --- a/src/com/fsck/k9/preferences/StorageImporter.java +++ /dev/null @@ -1,141 +0,0 @@ -package com.fsck.k9.preferences; - -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.util.HashMap; -import java.util.Map; -import java.util.Stack; - -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.parsers.SAXParser; -import javax.xml.parsers.SAXParserFactory; - -import org.xml.sax.Attributes; -import org.xml.sax.InputSource; -import org.xml.sax.SAXException; -import org.xml.sax.XMLReader; -import org.xml.sax.helpers.DefaultHandler; - -import android.content.Context; -import android.content.SharedPreferences; -import android.util.Log; - -import com.fsck.k9.K9; -import com.fsck.k9.Preferences; -import com.fsck.k9.helper.DateFormatter; - -public class StorageImporter { - public static int importPreferences(Context context, String fileName, String encryptionKey) throws StorageImportExportException { - try { - InputStream is = new FileInputStream(fileName); - return importPreferences(context, is, encryptionKey); - } catch (FileNotFoundException fnfe) { - throw new StorageImportExportException("Failure reading settings file " + fileName, fnfe); - } - } - public static int importPreferences(Context context, InputStream is, String encryptionKey) throws StorageImportExportException { - try { - Preferences preferences = Preferences.getPreferences(context); - SharedPreferences storage = preferences.getPreferences(); - SharedPreferences.Editor editor = storage.edit(); - - SAXParserFactory spf = SAXParserFactory.newInstance(); - SAXParser sp = spf.newSAXParser(); - XMLReader xr = sp.getXMLReader(); - StorageImporterHandler handler = new StorageImporterHandler(); - xr.setContentHandler(handler); - - xr.parse(new InputSource(is)); - is.close(); - - Element dataset = handler.getRootElement(); - String version = dataset.attributes.get("version"); - Log.i(K9.LOG_TAG, "Got settings file version " + version); - - - IStorageImporter storageImporter = null; - if ("1".equals(version)) { - storageImporter = new StorageImporterVersion1(); - } else { - throw new StorageImportExportException("Unable to read file of version " + version - + "; (only version 1 is readable)"); - } - int numAccounts = 0; - if (storageImporter != null) { - String data = dataset.data.toString(); - numAccounts = storageImporter.importPreferences(preferences, editor, data, encryptionKey); - } - editor.commit(); - Preferences.getPreferences(context).refreshAccounts(); - DateFormatter.clearChosenFormat(); - K9.loadPrefs(Preferences.getPreferences(context)); - return numAccounts; - } catch (SAXException se) { - throw new StorageImportExportException("Failure reading settings file", se); - } catch (IOException ie) { - throw new StorageImportExportException("Failure reading settings file", ie); - } catch (ParserConfigurationException pce) { - throw new StorageImportExportException("Failure reading settings file", pce); - } - } - - private static class Element { - String name; - Map attributes = new HashMap(); - Map subElements = new HashMap(); - StringBuilder data = new StringBuilder(); - } - - private static class StorageImporterHandler extends DefaultHandler { - private Element rootElement = new Element(); - private Stack mOpenTags = new Stack(); - - public Element getRootElement() { - return this.rootElement; - } - - @Override - public void startDocument() throws SAXException { - } - - @Override - public void endDocument() throws SAXException { - /* Do nothing */ - } - - @Override - public void startElement(String namespaceURI, String localName, - String qName, Attributes attributes) throws SAXException { - Log.i(K9.LOG_TAG, "Starting element " + localName); - Element element = new Element(); - element.name = localName; - mOpenTags.push(element); - for (int i = 0; i < attributes.getLength(); i++) { - String key = attributes.getLocalName(i); - String value = attributes.getValue(i); - Log.i(K9.LOG_TAG, "Got attribute " + key + " = " + value); - element.attributes.put(key, value); - } - } - - @Override - public void endElement(String namespaceURI, String localName, String qName) { - Log.i(K9.LOG_TAG, "Ending element " + localName); - Element element = mOpenTags.pop(); - Element superElement = mOpenTags.empty() ? null : mOpenTags.peek(); - if (superElement != null) { - superElement.subElements.put(element.name, element); - } else { - rootElement = element; - } - } - - @Override - public void characters(char ch[], int start, int length) { - String value = new String(ch, start, length); - mOpenTags.peek().data.append(value); - } - } -} diff --git a/src/com/fsck/k9/preferences/StorageImporterVersion1.java b/src/com/fsck/k9/preferences/StorageImporterVersion1.java deleted file mode 100644 index cfa2fc1f1..000000000 --- a/src/com/fsck/k9/preferences/StorageImporterVersion1.java +++ /dev/null @@ -1,88 +0,0 @@ -package com.fsck.k9.preferences; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.StringReader; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.UUID; - -import org.apache.commons.codec.binary.Base64; - -import android.content.SharedPreferences; -import android.util.Log; - -import com.fsck.k9.Account; -import com.fsck.k9.K9; -import com.fsck.k9.Preferences; - -public class StorageImporterVersion1 implements IStorageImporter { - public int importPreferences(Preferences preferences, SharedPreferences.Editor editor, String data, String encryptionKey) throws StorageImportExportException { - try { - Base64 base64 = new Base64(); - List accountNumbers = Account.getExistingAccountNumbers(preferences); - Log.i(K9.LOG_TAG, "Existing accountNumbers = " + accountNumbers); - Map uuidMapping = new HashMap(); - String accountUuids = preferences.getPreferences().getString("accountUuids", null); - - StringReader sr = new StringReader(data); - BufferedReader br = new BufferedReader(sr); - String line = null; - int settingsImported = 0; - int numAccounts = 0; - do { - line = br.readLine(); - if (line != null) { - //Log.i(K9.LOG_TAG, "Got line " + line); - String[] comps = line.split(":"); - if (comps.length > 1) { - String keyEnc = comps[0]; - String valueEnc = comps[1]; - String key = SimpleCrypto.decrypt(encryptionKey, keyEnc, base64); - String value = SimpleCrypto.decrypt(encryptionKey, valueEnc, base64); - String[] keyParts = key.split("\\."); - if (keyParts.length > 1) { - String oldUuid = keyParts[0]; - String newUuid = uuidMapping.get(oldUuid); - if (newUuid == null) { - newUuid = UUID.randomUUID().toString(); - uuidMapping.put(oldUuid, newUuid); - - Log.i(K9.LOG_TAG, "Mapping oldUuid " + oldUuid + " to newUuid " + newUuid); - } - keyParts[0] = newUuid; - if ("accountNumber".equals(keyParts[1])) { - int accountNumber = Account.findNewAccountNumber(accountNumbers); - accountNumbers.add(accountNumber); - value = Integer.toString(accountNumber); - accountUuids += (accountUuids.length() != 0 ? "," : "") + newUuid; - numAccounts++; - } - StringBuilder builder = new StringBuilder(); - for (String part : keyParts) { - if (builder.length() > 0) { - builder.append("."); - } - builder.append(part); - } - key = builder.toString(); - } - //Log.i(K9.LOG_TAG, "Setting " + key + " = " + value); - settingsImported++; - editor.putString(key, value); - } - } - - } while (line != null); - - editor.putString("accountUuids", accountUuids); - Log.i(K9.LOG_TAG, "Imported " + settingsImported + " settings and " + numAccounts + " accounts"); - return numAccounts; - } catch (IOException ie) { - throw new StorageImportExportException("Unable to import settings", ie); - } catch (Exception e) { - throw new StorageImportExportException("Unable to decrypt settings", e); - } - } -}