/*
* Copyright 2011 David Brazdil
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package uk.ac.cam.db538.cryptosms.ui;
import java.util.ArrayList;
import uk.ac.cam.db538.cryptosms.Preferences;
import uk.ac.cam.db538.cryptosms.R;
import uk.ac.cam.db538.cryptosms.SimCard;
import uk.ac.cam.db538.cryptosms.state.State;
import uk.ac.cam.db538.cryptosms.storage.Conversation;
import uk.ac.cam.db538.cryptosms.storage.StorageFileException;
import uk.ac.cam.db538.cryptosms.ui.DialogManager.DialogBuilder;
import uk.ac.cam.db538.cryptosms.utils.SimNumber;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.content.DialogInterface.OnClickListener;
import android.content.res.Resources;
import android.os.Bundle;
import android.telephony.PhoneNumberUtils;
/*
* Utilities for handling issues with SIM card
*/
public class UtilsSimIssues {
private static boolean mImportShown = false;
private static boolean mWarningSIMNotPresent = false;
private static final String DIALOG_NO_SIM_AVAILABLE = "DIALOG_NO_SIM_AVAILABLE";
private static final String DIALOG_IMPORT_KEYS = "DIALOG_IMPORT_KEYS";
private static final String DIALOG_NO_SESSION_KEYS = "DIALOG_NO_SESSION_KEYS";
private static final String DIALOG_EXISTING_PHONE_NUMBERS = "DIALOG_EXISTING_PHONE_NUMBERS";
/**
* Prepare dialogs.
*
* @param manager the manager
* @param context the context
*/
public static void prepareDialogs(final DialogManager manager, final Context context) {
manager.addBuilder(new DialogBuilder() {
@Override
public Dialog onBuild(Bundle params) {
Resources res = context.getResources();
return new AlertDialog.Builder(context)
.setTitle(res.getString(R.string.error_no_sim_available))
.setMessage(res.getString(R.string.error_no_sim_available_details))
.setPositiveButton(res.getString(R.string.ok), new DummyOnClickListener())
.setCancelable(false)
.create();
}
@Override
public String getId() {
return DIALOG_NO_SIM_AVAILABLE;
}
});
manager.addBuilder(new DialogBuilder() {
@Override
public Dialog onBuild(Bundle params) {
Resources res = context.getResources();
return new AlertDialog.Builder(context)
.setTitle(res.getString(R.string.menu_move_sessions_none))
.setMessage(res.getString(R.string.menu_move_sessions_none_details))
.setNeutralButton(res.getString(R.string.ok), new DummyOnClickListener())
.create();
}
@Override
public String getId() {
return DIALOG_NO_SESSION_KEYS;
}
});
manager.addBuilder(new DialogBuilder() {
@Override
public Dialog onBuild(Bundle params) {
Resources res = context.getResources();
// make list of phone numbers that have session keys
final ArrayList<SimNumber> phoneNumbers = new ArrayList<SimNumber>();
try {
phoneNumbers.addAll(Conversation.filterOnlyPhoneNumbers(Conversation.getAllSimNumbersStored()));
} catch (StorageFileException ex) {
}
// are there any?
if (phoneNumbers.size() > 0) {
return new AlertDialog.Builder(context)
.setTitle(res.getString(R.string.error_no_sim_number))
.setMessage(res.getString(R.string.error_no_sim_number_details))
.setNegativeButton(res.getString(R.string.never), new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
SharedPreferences.Editor editor = Preferences.getSingleton().getPreferences().edit();
editor.putString(Preferences.PREFERENCES_IMPORT_NEVER, SimCard.getSingleton().getNumber().getNumber());
editor.commit();
}
})
.setNeutralButton(res.getString(R.string.later), new DummyOnClickListener())
.setPositiveButton(res.getString(R.string.yes), new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
UtilsSimIssues.moveSessionKeys(manager);
}
})
.setCancelable(false)
.create();
}
return null;
}
@Override
public String getId() {
return DIALOG_IMPORT_KEYS;
}
});
manager.addBuilder(new DialogBuilder() {
@Override
public Dialog onBuild(Bundle params) {
Resources res = context.getResources();
final SimNumber simNumber = SimCard.getSingleton().getPhoneNumber();
final ArrayList<SimNumber> phoneNumbers = new ArrayList<SimNumber>();
try {
phoneNumbers.addAll(Conversation.filterOutNumber(
Conversation.filterOnlyPhoneNumbers(
Conversation.getAllSimNumbersStored()
),
simNumber
)
);
} catch (StorageFileException ex) {
}
String[] numbers = new String[phoneNumbers.size() + 1];
int i = 0;
for (SimNumber n : phoneNumbers)
numbers[i++] = n.getNumber();
numbers[i] = res.getString(R.string.error_no_sim_number_import_none);
// display them in a dialog
return new AlertDialog.Builder(context)
.setTitle(res.getString(R.string.error_no_sim_number_import))
.setItems(numbers, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int item) {
if (item < phoneNumbers.size()) {
try {
if (simNumber.getNumber().length() == 0)
Conversation.changeAllSessionKeys(phoneNumbers.get(item), SimCard.getSingleton().getSerialNumber());
else
Conversation.changeAllSessionKeys(phoneNumbers.get(item), simNumber);
} catch (StorageFileException ex) {
State.fatalException(ex);
return;
}
}
}
})
.create();
}
@Override
public String getId() {
return DIALOG_EXISTING_PHONE_NUMBERS;
}
});
}
/**
* Handles issues with SIM card.
* Checks that SIM knows its phone number,
* and if not and there already are some session keys, it offers
* an import of these.
*
* @param context the context
* @param dialogManager the dialog manager
*/
public static void handleSimIssues(Context context, DialogManager dialogManager) {
SimNumber simNumber = SimCard.getSingleton().getNumber();
if (simNumber == null) {
// no SIM present (possibly Airplane mode)
if (!mWarningSIMNotPresent) {
dialogManager.showDialog(DIALOG_NO_SIM_AVAILABLE, null);
mWarningSIMNotPresent = true;
}
} else if (simNumber.isSerial()) {
// offer import
// check preferences
String pref = Preferences.getSingleton().getPreferences().getString(Preferences.PREFERENCES_IMPORT_NEVER, null);
SimNumber declinedSim = null;
if (pref != null)
declinedSim = new SimNumber(pref, true);
if (!mImportShown && (declinedSim == null || simNumber.equals(declinedSim))) {
mImportShown = true;
dialogManager.showDialog(DIALOG_IMPORT_KEYS, null);
}
}
}
/**
* Lets the user transfer some of the existing keys to different SIM / phone number.
*
* @param context the context
* @param dialogManager the dialog manager
* @throws StorageFileException the storage file exception
*/
public static void moveSessionKeys(Context context, DialogManager dialogManager) throws StorageFileException {
//TODO: Nicer import!!!
// Let the user choose which contacts, etc...
SimNumber simNumber = SimCard.getSingleton().getPhoneNumber();
if (simNumber == null) // no SIM or Airplane mode
return;
ArrayList<SimNumber> phoneNumbers = Conversation.filterOutNumber(
Conversation.filterOnlyPhoneNumbers(
Conversation.getAllSimNumbersStored()
),
simNumber
);
if (phoneNumbers.size() > 0)
moveSessionKeys(dialogManager);
else
dialogManager.showDialog(DIALOG_NO_SESSION_KEYS, null);
}
/**
* Shows a dialog for moving session keys
*
* @param dialogManager the dialog manager
*/
public static void moveSessionKeys(DialogManager dialogManager) {
if (!SimCard.getSingleton().isNumberAvailable())
return;
dialogManager.showDialog(DIALOG_EXISTING_PHONE_NUMBERS, null);
}
/**
* Returns the given phone number in a unified format
*
* @param phoneNumber the phone number
* @return the string
*/
public static String formatPhoneNumber(String phoneNumber) {
return PhoneNumberUtils.stripSeparators(phoneNumber);
}
}