/* Tibisay Movil Copyright (C) 2013 Antonio Araujo (aaraujo@cenditel.gob.ve), Jose Ruiz (jruiz@cenditel.gob.ve), Fundacion Centro Nacional de Desarrollo e Investigacion en Tecnologias Libres - CENDITEL. La Fundación CENDITEL concede permiso para usar, copiar, distribuir y/o modificar este programa, reconociendo el derecho que la humanidad posee al libre acceso al conocimiento, bajo los términos de la licencia de software GPL versión 2.0 de la Free Software Foundation. Este programa se distribuye con la esperanza de que sea util, pero SIN NINGUNA GARANTIA; tampoco las implicitas garantias de MERCANTILIDAD o ADECUACION A UN PROPOSITO PARTICULAR. Para mayor información sobre los términos de la licencia ver el archivo llamado "gpl-2.0.txt" en ingles. */ package ve.gob.cenditel.tibisaymovil; import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.security.cert.Certificate; import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.HashMap; import ee.sk.digidoc.DigiDocException; import ee.sk.digidoc.SignedDoc; import android.os.Bundle; import android.os.Environment; import android.annotation.SuppressLint; import android.app.Activity; import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.util.Log; import android.view.LayoutInflater; import android.view.Menu; import android.view.View; import android.view.ViewGroup; import android.view.Window; import android.view.View.OnClickListener; import android.widget.AdapterView; import android.widget.BaseAdapter; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.ListView; import android.widget.RadioButton; import android.widget.TextView; import android.widget.Toast; import android.widget.AdapterView.OnItemClickListener; // activity para gestionar los certificados de destinatarios disponibles para cifrar // un archivo public class EncryptionCertificatesActivity extends Activity { // layout del boton agregar certificado private LinearLayout button_add; // layout del boton eliminar certificado private LinearLayout button_remove; // ListView que mantiene la lista de certificados private ListView certificate_list; // ruta del directorio que almancena los certificados de destinatarios String certificatesDir; // id de certificado seleccionado int certificateSelectedIndex = -1; // lista de rutas absolutas de archivos de certificados HashMap certificatesPathHashMap = null; // intent para relanzar al momento de eliminar un certificado Intent starterIntent = null; @Override protected void onCreate(Bundle savedInstanceState) { //Estilando la barra de titulo final boolean customTitleSupported = requestWindowFeature(Window.FEATURE_CUSTOM_TITLE); super.onCreate(savedInstanceState); setContentView(R.layout.activity_encryption_certificates); //Estilando Barra de titulo if(customTitleSupported) getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, R.layout.title_bar); button_remove = (LinearLayout) this.findViewById(R.id.button_remove_certificate_zone); button_add = (LinearLayout) this.findViewById(R.id.button_add_certificate_zone); final TextView labelRemoveCertificate = (TextView) this.findViewById(R.id.label_certificate_to_remove); labelRemoveCertificate.setVisibility(View.GONE); final LinearLayout layoutCertificateToRemove = (LinearLayout) this.findViewById(R.id.layout_certificate_to_remove); layoutCertificateToRemove.setVisibility(View.GONE); final TextView certificateToRemove = (TextView) this.findViewById(R.id.filename_text); starterIntent = getIntent(); // lista de certificados final ArrayList certificates = new ArrayList(); // asignar ruta de certificados de destinatarios certificatesDir = Environment.getExternalStorageDirectory().getAbsolutePath() + "/" + getResources().getString(R.string.app_name) + "/" + getResources().getString(R.string.certificates_dir) + "/"; //Toast.makeText(getApplicationContext(), "certificatesDir: "+ certificatesDir, Toast.LENGTH_SHORT).show(); // chequear disponibilidad de directorio de certificados if (!checkCertificatesDirectoryAvailability()){ return; } // Leer el contenido del directorio de certificados // Crea un arreglo con las lista de archivos contenidos en el directorio cwd File f = new File(certificatesDir); File[] ls = f.listFiles(); if (ls != null) { //Toast.makeText(getApplicationContext(), "numero de archivos: " +Integer.toString(ls.length), Toast.LENGTH_SHORT).show(); certificatesPathHashMap = new HashMap(); String recipient = null; // iterar sobre todos los archivos de certificados // en el KeyStore for (File iFile : ls) { try { X509Certificate recvCert = SignedDoc.readCertificate(new File(iFile.getAbsolutePath())); recipient = SignedDoc.getCommonName(recvCert.getSubjectDN().getName()); //Toast.makeText(getApplicationContext(), "Destinatario: "+ recipient,Toast.LENGTH_SHORT).show(); certificates.add(new RecipientCertificate(recipient)); certificatesPathHashMap.put(recipient, iFile.getAbsolutePath()); } catch (DigiDocException e) { Toast.makeText(getApplicationContext(), "DigiDocException: "+ e.getMessage(), Toast.LENGTH_SHORT).show(); } }// fin de la iteracion sobre iFile } // se crea el adaptador para mostrar los certificados de destinatarios final RecipientCertificateAdapter certificateAdapter = new RecipientCertificateAdapter(EncryptionCertificatesActivity.this, certificates); final ListView certificateListView = (ListView) findViewById(R.id.certificate_list); certificateListView.setAdapter(certificateAdapter); certificateListView.setOnItemClickListener(new android.widget.AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView parent, View view, int position, long id) { Object o = certificateListView.getItemAtPosition(position); RecipientCertificate c = (RecipientCertificate) o; certificateSelectedIndex = position; labelRemoveCertificate.setVisibility(View.VISIBLE); layoutCertificateToRemove.setVisibility(View.VISIBLE); certificateToRemove.setText(c.getName()); //Toast.makeText(getApplicationContext(), "click sobre certificado"+ c.getName(), Toast.LENGTH_SHORT).show(); } }); // habilita el click sobre la acción para agregar un certificado nuevo button_add.setOnClickListener(new OnClickListener() { public void onClick(View v) { //Intent oIntent = new Intent(BDOCVerifyResultActivity.this, TibisayMovilActivity.class); //oIntent.setAction(Intent.ACTION_VIEW); //oIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); //startActivity(oIntent); //finish(); //Toast.makeText(getApplicationContext(), "Se debe agregar un certificado", Toast.LENGTH_SHORT).show(); // llamar a función para cargar certificado loadNewCertificate(); } }); // habilita el click sobre la acción eliminar el certificado seleccionado button_remove.setOnClickListener(new OnClickListener() { public void onClick(View v) { //shareIt(); //Toast.makeText(getApplicationContext(), "eliminar un certificado", Toast.LENGTH_SHORT).show(); if (certificateSelectedIndex == -1){ // 1. Instantiate an AlertDialog.Builder with its constructor AlertDialog.Builder builder = new AlertDialog.Builder(EncryptionCertificatesActivity.this); // 2. Chain together various setter methods to set the dialog characteristics builder.setMessage("Debe seleccionar un certificado para eliminarlo.") .setTitle("Información:"); builder.setPositiveButton("Ok", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { // User clicked OK button //Toast.makeText(getApplicationContext(), "User clicked OK button", Toast.LENGTH_LONG).show(); } }); // 3. Get the AlertDialog from create() AlertDialog dialog = builder.create(); dialog.show(); }else{ // 1. Instantiate an AlertDialog.Builder with its constructor AlertDialog.Builder builder = new AlertDialog.Builder(EncryptionCertificatesActivity.this); // 2. Chain together various setter methods to set the dialog characteristics builder.setMessage("¿Está seguro de eliminar el certificado?.") .setTitle("Información:"); builder.setPositiveButton("Ok", new DialogInterface.OnClickListener() { @SuppressLint("NewApi") public void onClick(DialogInterface dialog, int id) { // User clicked OK button //Toast.makeText(getApplicationContext(), "User clicked OK button", Toast.LENGTH_LONG).show(); // funcion para eliminar el certificado // ... String pathToErase = certificatesPathHashMap.get(certificateToRemove.getText()); File file = new File(pathToErase); boolean deleted = file.delete(); //actualizar la lista de certificados en ListView certificateAdapter.notifyDataSetChanged(); labelRemoveCertificate.setVisibility(View.GONE); layoutCertificateToRemove.setVisibility(View.GONE); // la funcion recreate esta disponible a partir del api 11 if (android.os.Build.VERSION.SDK_INT >= 11) { EncryptionCertificatesActivity.this.recreate(); } else { startActivity(starterIntent); finish(); } //Toast.makeText(getApplicationContext(), "**archivo a borrar: "+pathToErase, Toast.LENGTH_LONG).show(); } }); builder.setNegativeButton("Cancelar", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { // User cancelled the dialog //Toast.makeText(getApplicationContext(), "User clicked Cancel button", Toast.LENGTH_LONG).show(); labelRemoveCertificate.setVisibility(View.GONE); layoutCertificateToRemove.setVisibility(View.GONE); } }); // 3. Get the AlertDialog from create() AlertDialog dialog = builder.create(); dialog.show(); } } }); } // fin de funcion onCreate() @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.encryption_certificates, menu); return true; } /** * Carga un nuevo certificado al lanzar CertificateToLoadActivity. * @return void */ public void loadNewCertificate() { Intent intent = new Intent(this, CertificateToLoadActivity.class); startActivity(intent); finish(); } // clase que abstrae un certificado de destinatario // se utiliza para mostrar en la interfaz grafica cada certificado // de destinatario almancenado por la aplicacion public class RecipientCertificate { private String mName; public RecipientCertificate(String name){ mName = name; } public void setName(String name) { this.mName = name; } public String getName() { return mName; } } // fin de clase RecipientCertificate // clase que abstrae el adaptador para llenar el ListView de documentos que // se encuentran dentro del contenedor BDOC private class RecipientCertificateAdapter extends BaseAdapter { private ArrayList mRecipientCertificateList; private LayoutInflater lInflater; private RecipientCertificateAdapter(Context context, ArrayList certificates) { this.lInflater = LayoutInflater.from(context); this.mRecipientCertificateList = certificates; } @Override public int getCount() { return mRecipientCertificateList.size(); } @Override public Object getItem(int position) { return mRecipientCertificateList.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder container = null; if (convertView == null){ container = new ViewHolder(); convertView = lInflater.inflate(R.layout.recipient_certificate_info, null); container.filename_text = (TextView) convertView.findViewById(R.id.filename_text); //container.filename_modified = (TextView) convertView.findViewById(R.id.filename_modified); container.type_image = (ImageView) convertView.findViewById(R.id.type_image); convertView.setTag(container); }else{ container = (ViewHolder) convertView.getTag(); } RecipientCertificate certificate = (RecipientCertificate) getItem(position); container.filename_text.setText(certificate.getName()); //container.filename_modified.setText(certificate.getName()); container.type_image.setImageResource(R.drawable.ic_archivo); return convertView; } class ViewHolder{ TextView filename_text; //TextView filename_modified; ImageView type_image; } } // fin de la clase RecipientCertificateAdapter /** * Prepara directorio * @return boolean */ boolean prepareDirectory(String dir) { try { if (makedirs(dir)) { return true; } else { return false; } } catch (Exception e) { e.printStackTrace(); //Toast.makeText(this, "Could not initiate File System.. Is Sdcard mounted properly?", Toast.LENGTH_LONG).show(); Toast.makeText(this, "No se pudo iniciar el sistema de archivos. ¿Está la SDCARD montada?", Toast.LENGTH_LONG).show(); return false; } } /** * Crea directorio utilizando la variable tmpDir * @return boolean */ private boolean makedirs(String dir) { //File tempdir = new File(extractedDirFiles); File tempdir = new File(dir); if (!tempdir.exists()) tempdir.mkdirs(); return (tempdir.isDirectory()); } /** * Chequea la disponibilidad del directorio de /TibisayMovil/CertificatesToEncrypt * @return boolean */ private boolean checkCertificatesDirectoryAvailability() { // verificar acceso al directorio /mnt/sdcard/TibisayMovil/CertificatesToEncrypt boolean mExternalStorageAvailable = false; boolean mExternalStorageWriteable = false; String state = Environment.getExternalStorageState(); AlertDialog.Builder builder = new AlertDialog.Builder(EncryptionCertificatesActivity.this); if (Environment.MEDIA_MOUNTED.equals(state)) { // We can read and write the media mExternalStorageAvailable = mExternalStorageWriteable = true; //Toast.makeText(getApplicationContext(), "We can read and write the media", Toast.LENGTH_SHORT).show(); // Crear directorio CertificatesToEncrypt donde se almacenan los certificados de // destinatarios para cifrado /* String certificatesDir = Environment.getExternalStorageDirectory() + "/" + getResources().getString(R.string.app_name) + "/" + getResources().getString(R.string.certificates_dir) + "/"; */ if (prepareDirectory(certificatesDir)){ return true; }else{ builder.setMessage("No existe el directorio "+certificatesDir+" para almacenar certificados.").setTitle("Error:"); } } else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) { // We can only read the media mExternalStorageAvailable = true; mExternalStorageWriteable = false; //Toast.makeText(getApplicationContext(), "We can only read the media", Toast.LENGTH_SHORT).show(); builder.setMessage("Directorio "+certificatesDir+ " montado de solo lectura. No se pueden almancenar certificados.").setTitle("Error:"); } else { // Something else is wrong. It may be one of many other states, but all we need // to know is we can neither read nor write mExternalStorageAvailable = mExternalStorageWriteable = false; //Toast.makeText(getApplicationContext(), "we can neither read nor write", Toast.LENGTH_SHORT).show(); builder.setMessage("Directorio "+certificatesDir+ " no está disponible. No se pueden almancenar certificados.").setTitle("Error:"); } builder.setNegativeButton("Cancelar", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { // User cancelled the dialog EncryptionCertificatesActivity.this.finish(); } }); AlertDialog dialog = builder.create(); dialog.show(); return false; } } // fin de la activity