package com.undatech.opaque;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateEncodingException;
import java.security.cert.X509Certificate;
import java.text.ChoiceFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import android.app.Activity;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.util.Base64;
import android.util.Log;
import com.undatech.opaque.R;
import com.undatech.opaque.dialogs.ChoiceFragment;
import com.undatech.opaque.dialogs.GetTextFragment;
import com.undatech.opaque.dialogs.SelectTextElementFragment;
import com.undatech.opaque.util.SslUtils;
public class RemoteCanvasActivityHandler extends Handler {
private static String TAG = "RemoteCanvasActivityHandler";
private Context context;
private RemoteCanvas c;
private ConnectionSettings settings;
public RemoteCanvasActivityHandler(Context context, RemoteCanvas c, ConnectionSettings settings) {
super();
this.context = context;
this.c = c;
this.settings = settings;
}
@Override
public void handleMessage(Message msg) {
FragmentManager fm;
switch (msg.what) {
case Constants.VV_OVER_HTTP_FAILURE:
MessageDialogs.displayMessageAndFinish(context, R.string.error_failed_to_download_vv_http,
R.string.error_dialog_title);
break;
case Constants.VV_OVER_HTTPS_FAILURE:
MessageDialogs.displayMessageAndFinish(context, R.string.error_failed_to_download_vv_https,
R.string.error_dialog_title);
case Constants.VV_DOWNLOAD_TIMEOUT:
MessageDialogs.displayMessageAndFinish(context, R.string.error_vv_download_timeout,
R.string.error_dialog_title);
case Constants.PVE_FAILED_TO_AUTHENTICATE:
MessageDialogs.displayMessageAndFinish(context, R.string.error_pve_failed_to_authenticate,
R.string.error_dialog_title);
break;
case Constants.PVE_FAILED_TO_PARSE_JSON:
MessageDialogs.displayMessageAndFinish(context, R.string.error_pve_failed_to_parse_json,
R.string.error_dialog_title);
break;
case Constants.PVE_VMID_NOT_NUMERIC:
MessageDialogs.displayMessageAndFinish(context, R.string.error_pve_vmid_not_numeric,
R.string.error_dialog_title);
break;
case Constants.PVE_API_UNEXPECTED_CODE:
MessageDialogs.displayMessageAndFinish(context, R.string.error_pve_api_unexpected_code,
R.string.error_dialog_title, msg.getData().getString("error"));
break;
case Constants.PVE_API_IO_ERROR:
MessageDialogs.displayMessageAndFinish(context, R.string.error_pve_api_io_error,
R.string.error_dialog_title, msg.getData().getString("error"));
break;
case Constants.PVE_TIMEOUT_COMMUNICATING:
MessageDialogs.displayMessageAndFinish(context, R.string.error_pve_timeout_communicating,
R.string.error_dialog_title);
break;
case Constants.PVE_NULL_DATA:
MessageDialogs.displayMessageAndFinish(context, R.string.error_pve_null_data,
R.string.error_dialog_title);
break;
case Constants.VV_FILE_ERROR:
c.disconnectAndShowMessage(R.string.vv_file_error, R.string.error_dialog_title);
break;
case Constants.NO_VM_FOUND_FOR_USER:
c.disconnectAndShowMessage(R.string.error_no_vm_found_for_user, R.string.error_dialog_title);
break;
case Constants.OVIRT_SSL_HANDSHAKE_FAILURE:
c.disconnectAndShowMessage(R.string.error_ovirt_ssl_handshake_failure, R.string.error_dialog_title);
break;
case Constants.VM_LOOKUP_FAILED:
c.disconnectAndShowMessage(R.string.error_vm_lookup_failed, R.string.error_dialog_title);
break;
case Constants.OVIRT_AUTH_FAILURE:
c.disconnectAndShowMessage(R.string.error_ovirt_auth_failure, R.string.error_dialog_title);
break;
case Constants.VM_LAUNCHED:
c.disconnectAndShowMessage(R.string.info_vm_launched_on_stand_by, R.string.info_dialog_title);
break;
case Constants.LAUNCH_VNC_VIEWER:
/* TODO: Implement:
android.util.Log.d(TAG, "Trying to launch VNC viewer");
Intent intent = new Intent ();
String intentURI = "vnc://" + address + ":" + port + "?password=" + password;
try {
intent = Intent.parseUri(intentURI, Intent.URI_INTENT_SCHEME);
} catch (URISyntaxException e) {
}
myself.canvas.getContext().startActivity(intent);
disconnectAndCleanup();
finish();
*/
c.disconnectAndShowMessage(R.string.error_no_vnc_support_yet, R.string.error_dialog_title);
break;
case Constants.GET_PASSWORD:
c.progressDialog.dismiss();
fm = ((FragmentActivity)context).getSupportFragmentManager();
GetTextFragment getPassword = GetTextFragment.newInstance(
context.getString(R.string.enter_password),
(RemoteCanvasActivity)context, true);
// TODO: Add OK button.
//newFragment.setCancelable(false);
getPassword.show(fm, "getPassword");
break;
case Constants.DIALOG_DISPLAY_VMS:
c.progressDialog.dismiss();
ArrayList<String> vms = msg.getData().getStringArrayList("vms");
if (vms.size() > 0) {
fm = ((FragmentActivity)context).getSupportFragmentManager();
SelectTextElementFragment displayVms = SelectTextElementFragment.newInstance(
context.getString(R.string.select_vm_title),
vms, (RemoteCanvasActivity)context);
displayVms.setCancelable(false);
displayVms.show(fm, "selectVm");
}
break;
case Constants.SPICE_CONNECT_SUCCESS:
c.progressDialog.dismiss();
synchronized(c.spicecomm) {
c.spiceUpdateReceived = true;
c.spicecomm.notifyAll();
}
break;
case Constants.SPICE_CONNECT_FAILURE:
String e = msg.getData().getString("message");
c.progressDialog.dismiss();
// Only if we were intending to stay connected, and the connection failed, show an error message.
if (c.stayConnected) {
if (!c.spiceUpdateReceived) {
c.disconnectAndShowMessage(R.string.error_ovirt_unable_to_connect, R.string.error_dialog_title, e);
} else {
c.disconnectAndShowMessage(R.string.error_connection_interrupted, R.string.error_dialog_title, e);
}
}
break;
case Constants.OVIRT_TIMEOUT:
c.progressDialog.dismiss();
c.disconnectAndShowMessage(R.string.error_ovirt_timeout, R.string.error_dialog_title);
break;
case Constants.DIALOG_X509_CERT:
X509Certificate cert = (X509Certificate)msg.obj;
validateX509Cert(cert);
break;
}
}
/**
* If there is a saved cert, checks the one given against it. If a signature was passed in
* and no saved cert, then check that signature. Otherwise, presents the
* given cert's signature to the user for approval.
*
* The saved data must always win over any passed-in URI data
*
* @param cert the given cert.
*/
private void validateX509Cert (final X509Certificate cert) {
byte[] certDataTemp = null;
try {
certDataTemp = cert.getEncoded();
} catch (Exception ex) {
ex.printStackTrace();
return;
}
final byte[] certData = certDataTemp;
String md5Hash = "";
String sha1Hash = "";
String sha256Hash = "";
try {
md5Hash = SslUtils.signature("MD5", certData);
sha1Hash = SslUtils.signature("SHA-1", certData);
sha256Hash = SslUtils.signature("SHA-256", certData);
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
String certInfo;
certInfo = String.format(context.getString(R.string.info_cert), md5Hash, sha1Hash, sha256Hash,
cert.getSubjectX500Principal().getName(),
cert.getIssuerX500Principal().getName(),
cert.getNotBefore(),
cert.getNotAfter()
);
// TODO: Create title string
ChoiceFragment certDialog = ChoiceFragment.newInstance(
context.getString(R.string.ca_new_or_changed),
certInfo,
"Accept",
"Reject",
new ChoiceFragment.OnFragmentDismissedListener() {
@Override
public void onResponseObtained(boolean result) {
if (result) {
android.util.Log.e(TAG, "We were told to continue");
settings.setOvirtCaData(Base64.encodeToString(certData, Base64.DEFAULT));
settings.saveToSharedPreferences(RemoteCanvasActivityHandler.this.context);
synchronized (RemoteCanvasActivityHandler.this) {
RemoteCanvasActivityHandler.this.notify();
}
} else {
android.util.Log.e(TAG, "We were told not to continue");
((Activity)context).finish();
}
}
});
FragmentManager fm = ((FragmentActivity)context).getSupportFragmentManager();
certDialog.setCancelable(false);
certDialog.show(fm, "certDialog");
}
/**
* Convenience function to create a message with a single key and String value pair in it.
* @param what
* @param key
* @param value
* @return
*/
public static Message getMessageString (int what, String key, String value) {
Message m = new Message();
m.what = what;
Bundle d = new Bundle();
d.putString(key, value);
m.setData(d);
return m;
}
/**
* Convenience function to create a message with a single key and String value pair in it.
* @param what
* @param key
* @param value
* @return
*/
public static Message getMessageStringList (int what, String key, ArrayList<String> value) {
Message m = new Message();
m.what = what;
Bundle d = new Bundle();
d.putStringArrayList(key, value);
m.setData(d);
return m;
}
}