/* 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.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.lang.reflect.Field; import java.net.HttpURLConnection; import java.net.URL; import java.security.KeyStore; import java.security.cert.Certificate; import java.security.cert.CertificateFactory; import java.util.ArrayList; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManagerFactory; import android.net.Uri; import android.os.AsyncTask; import android.os.Bundle; import android.os.Environment; import android.os.Looper; import android.app.Activity; import android.app.AlertDialog; import android.app.Dialog; import android.app.ProgressDialog; import android.content.DialogInterface; import android.content.Intent; import android.util.Log; import android.view.Menu; import android.view.Window; import android.webkit.MimeTypeMap; import android.widget.Toast; public class DownloaderActivity extends Activity { // cadena que mantiene la ruta para almacenar los archivos // extraidos de un contendor BDOC private String extractedDirFiles; // cadena que mantiene la ruta para almacenar los archivos // descargados desde un servidor para verificar su firma private String downloadedDirFiles; // ruta absoluta al archivo a verificar private String fileToVerify; // extension del archivo a verificar private String fileToVerifyExtension; // cadena que mantiene la URL al descargar archivo con https String urlhttps = null; // Progress Dialog private ProgressDialog mProgressDialog; // Progress dialog type (0 - for Horizontal progress bar) public static final int DIALOG_DOWNLOAD_PROGRESS = 0; @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_downloader); setContentView(R.layout.activity_verify_result_bdoc); //Estilando Barra de titulo if(customTitleSupported) getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, R.layout.title_bar); // ------------------------------------------------------------------------------------ // el siguiente segmento de codigo permite obtener los nombres de los archivos // que estan en /res/raw ArrayList list = new ArrayList(); Field[] fields = R.raw.class.getFields(); for (int l=0; l < fields.length; l++) { try { Toast.makeText(getApplicationContext(), "DownloaderActivity: "+Integer.toString(l)+ " "+ Integer.toString(fields[l].getInt(null)), Toast.LENGTH_SHORT).show(); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block Toast.makeText(getApplicationContext(), "DownloaderActivity: IllegalArgumentException "+e.getMessage(), Toast.LENGTH_SHORT).show(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block Toast.makeText(getApplicationContext(), "DownloaderActivity: IllegalAccessException "+e.getMessage(), Toast.LENGTH_SHORT).show(); } } /* for(Field f : fields) try { Toast.makeText(getApplicationContext(), "DownloaderActivity: Fields.length: "+Integer.toString(fields.length), Toast.LENGTH_SHORT).show(); Toast.makeText(getApplicationContext(), "DownloaderActivity: "+f.getName(), Toast.LENGTH_SHORT).show(); //list.add(splitString[0]); } catch (IllegalArgumentException e) { Toast.makeText(getApplicationContext(), "DownloaderActivity: IllegalArgumentException "+e.getMessage(), Toast.LENGTH_SHORT).show(); } */ // ------------------------------------------------------------------------------------ // chequear si intent tiene data final android.content.Intent intent = getIntent(); final Bundle bundle = getIntent().getExtras(); if (intent != null) { //Toast.makeText(getApplicationContext(), "DownloaderActivity: intent != null", Toast.LENGTH_SHORT).show(); final android.net.Uri data = intent.getData (); if (data != null) { //Toast.makeText(getApplicationContext(), "data != null", Toast.LENGTH_SHORT).show(); // verificar el tipo de scheme String scheme = data.getScheme(); // verificacion de un archivo que esta en el dispositivo if (scheme.equals("file")) { //Toast.makeText(getApplicationContext(), "file: "+data.getPath(), Toast.LENGTH_SHORT).show(); // verificar el archivo if (data.getPath().endsWith("bdoc")){ fileToVerify = data.getPath(); // ejecutar la verificacion //doBdocVerification(data.getPath()); }else{ //Toast.makeText(getApplicationContext(), "¡Por Implementar!", Toast.LENGTH_SHORT).show(); } } // verificacion de un archivo que se debe descargar if (scheme.equals("https")) { //Toast.makeText(getApplicationContext(), "scheme: "+data.toString(), Toast.LENGTH_SHORT).show(); //Toast.makeText(getApplicationContext(), "externalStorage: "+Environment.getExternalStorageDirectory().toString(), Toast.LENGTH_SHORT).show(); urlhttps = data.toString(); new DownloadFileAsync().execute(data.toString(), "false"); //new DownloadFileFromURL().execute("http://farm1.static.flickr.com/114/298125983_0e4bf66782_b.jpg"); //Toast.makeText(getApplicationContext(), "****despues de execute()", Toast.LENGTH_SHORT).show(); // verificar el archivo //Toast.makeText(getApplicationContext(), "Ahora viene la verificación del archivo", Toast.LENGTH_SHORT).show(); } return; } // verificacion de archivo desde la Activity principal if (bundle != null) { fileToVerify = bundle.getString("fileToVerify"); fileToVerifyExtension = bundle.getString("fileExtension"); //Toast.makeText(getApplicationContext(), "fileToVerify bundle!=null: "+fileToVerify, Toast.LENGTH_SHORT).show(); if (fileToVerifyExtension.equals("bdoc")){ //Toast.makeText(getApplicationContext(), "verificacion de archivo desde la Activity principal", Toast.LENGTH_SHORT).show(); // ejecutar la verificacion //doBdocVerification(fileToVerify); }else{ //Toast.makeText(getApplicationContext(), "¡Por Implementar!", Toast.LENGTH_SHORT).show(); } //return; } }else{ //Toast.makeText(getApplicationContext(), "intent == null", Toast.LENGTH_SHORT).show(); } } /** * Prepara directorio * @return boolean */ private 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(); // if (tempdir.isDirectory()) // { // File[] files = tempdir.listFiles(); // for (File file : files) // { // if (!file.delete()) // { // System.out.println("Failed to delete " + file); // } // } // } return (tempdir.isDirectory()); } /** * Showing Dialog for downloading file * */ @Override protected Dialog onCreateDialog(int id) { switch (id) { case DIALOG_DOWNLOAD_PROGRESS: // we set this to 0 mProgressDialog = new ProgressDialog(this); mProgressDialog.setMessage("Descargando archivo. Por favor espere..."); mProgressDialog.setIndeterminate(false); mProgressDialog.setMax(100); mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); mProgressDialog.setCancelable(true); mProgressDialog.show(); return mProgressDialog; default: return null; } } // clase para descargar archivo private class DownloadFileAsync extends AsyncTask> { File rootDir = Environment.getExternalStorageDirectory(); /** * Before starting background thread * Show Progress Bar Dialog * */ @Override protected void onPreExecute() { super.onPreExecute(); showDialog(DIALOG_DOWNLOAD_PROGRESS); } /** * Downloading file in background thread * */ @Override protected ArrayList doInBackground(String... params) { // para solventar error: // Can't create handler inside thread that has not called Looper.prepare() Looper.prepare(); int count; Log.d("doInBackground", params[0]); // resultArray [0] -> 0 para ruta de archivo valida // resultArray [0] -> 1 ocurrio un error // resultArray [1] -> ruta del archivo descargado // resultArray [1] -> mensaje de la excepcion ArrayList resultArray = new ArrayList(); resultArray.clear(); String outputString = null; try { URL url = new URL(params[0]); int lenghtOfFile = 0; InputStream input = null; if (url.getProtocol().equals("http")){ HttpURLConnection httpConnection = (HttpURLConnection) url.openConnection(); input = new BufferedInputStream(httpConnection.getInputStream()); lenghtOfFile = httpConnection.getContentLength(); }else{ // https // ejecutar la descarga despues de haber aceptado que el certificado // no es conocido if (params[1].equals("true")){ Log.d("***", "params[1].equals(true)"); // descarga del certificado del servidor // crear certificate factory CertificateFactory cf = CertificateFactory.getInstance("X.509"); // crear un KeyStore String keyStoreType = KeyStore.getDefaultType(); KeyStore keyStore = KeyStore.getInstance(keyStoreType); keyStore.load(null, null); // obtener vector de campos de /res/raw Field[] fields = R.raw.class.getFields(); InputStream caInput = null; // iterar sobre todos los certificados incluidos en /res/raw y cargarlos // en el KeyStore for (int l=0; l < fields.length; l++) { try { //Toast.makeText(getApplicationContext(), "DownloaderActivity: "+Integer.toString(l)+ " "+ // Integer.toString(fields[l].getInt(null)), Toast.LENGTH_SHORT).show(); caInput = new BufferedInputStream(getResources().openRawResource(fields[l].getInt(null))); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block Toast.makeText(getApplicationContext(), "DownloaderActivity: IllegalArgumentException "+e.getMessage(), Toast.LENGTH_SHORT).show(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block Toast.makeText(getApplicationContext(), "DownloaderActivity: IllegalAccessException "+e.getMessage(), Toast.LENGTH_SHORT).show(); } Certificate ca; try { ca = cf.generateCertificate(caInput); //Log.d("**ca:", ((X509Certificate) ca).getSubjectDN()); //Log.d("*** try: ca.toString()", ca.toString()); } finally { caInput.close(); } keyStore.setCertificateEntry("ca"+Integer.toString(l), ca); }// fin de la iteracion sobre /res/raw // Create a TrustManager that trusts the CAs in our KeyStore String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm(); TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm); tmf.init(keyStore); Log.d("***", "despues de crear TrustManager"); // Create an SSLContext that uses our TrustManager SSLContext context = SSLContext.getInstance("TLS"); context.init(null, tmf.getTrustManagers(), null); Log.d("***", "despues de crear SSLContext"); HttpsURLConnection httpsConnection = (HttpsURLConnection) url.openConnection(); Log.d("***", "despues de crear httpsConnection"); httpsConnection.setSSLSocketFactory(context.getSocketFactory()); Log.d("***", "despues de crear setSSLSocketFactory"); //input = new BufferedInputStream(httpsConnection.getInputStream()); input = httpsConnection.getInputStream(); Log.d("***", "despues de crear BufferedInputStream"); lenghtOfFile = httpsConnection.getContentLength(); Log.d("***", "se acepto la excepcion"); /* // descarga del certificado del servidor CertificateFactory cf = CertificateFactory.getInstance("X.509"); InputStream caInput = new BufferedInputStream(getResources().openRawResource(R.raw.gestion)); Certificate ca; try { ca = cf.generateCertificate(caInput); //Log.d("**ca:", ((X509Certificate) ca).getSubjectDN()); //Log.d("*** try: ca.toString()", ca.toString()); } finally { caInput.close(); } Log.d("***", "despues de Certificate ca"); // Create a KeyStore containing our trusted CAs String keyStoreType = KeyStore.getDefaultType(); KeyStore keyStore = KeyStore.getInstance(keyStoreType); keyStore.load(null, null); keyStore.setCertificateEntry("ca", ca); Log.d("***", "despues de crear KeyStore"); // Create a TrustManager that trusts the CAs in our KeyStore String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm(); TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm); tmf.init(keyStore); Log.d("***", "despues de crear TrustManager"); // Create an SSLContext that uses our TrustManager SSLContext context = SSLContext.getInstance("TLS"); context.init(null, tmf.getTrustManagers(), null); Log.d("***", "despues de crear SSLContext"); HttpsURLConnection httpsConnection = (HttpsURLConnection) url.openConnection(); Log.d("***", "despues de crear httpsConnection"); httpsConnection.setSSLSocketFactory(context.getSocketFactory()); Log.d("***", "despues de crear setSSLSocketFactory"); //input = new BufferedInputStream(httpsConnection.getInputStream()); input = httpsConnection.getInputStream(); Log.d("***", "despues de crear BufferedInputStream"); lenghtOfFile = httpsConnection.getContentLength(); Log.d("***", "se acepto la excepcion"); */ }else{ HttpsURLConnection httpsConnection = (HttpsURLConnection) url.openConnection(); input = new BufferedInputStream(httpsConnection.getInputStream()); lenghtOfFile = httpsConnection.getContentLength(); } } // Crear directorio DownloadedFiles donde se almacenan los archivos descargados // desde un servidor para verificar su firma downloadedDirFiles = Environment.getExternalStorageDirectory() + "/" + getResources().getString(R.string.app_name) + "/" + getResources().getString(R.string.downloaded_dir_files) + "/"; prepareDirectory(downloadedDirFiles); //int lenghtOfFile = conexion.getContentLength(); Log.d("ANDRO_ASYNC", "Lenght of file: " + lenghtOfFile); //InputStream input = new BufferedInputStream(url.openStream()); //InputStream input = new BufferedInputStream(conexion.getInputStream()); //OutputStream output = new FileOutputStream("/mnt/sdcard/TibisayMovil/ExtractedFiles/photo.jpg"); //OutputStream output = new FileOutputStream(new File(rootDir+"/midescarga/", "foto.jpg")); String urlString = url.toString(); String[] values = urlString.split("/"); //OutputStream output = new FileOutputStream(new File(downloadedDirFiles, "acta.2.bdoc")); OutputStream output = new FileOutputStream(new File(downloadedDirFiles, values[values.length-1])); byte data[] = new byte[1024]; long total = 0; while ((count = input.read(data)) != -1) { total += count; publishProgress(""+(int)((total*100)/lenghtOfFile)); output.write(data, 0, count); } output.flush(); output.close(); input.close(); resultArray.add("0"); //resultArray.add(output.toString()); resultArray.add(downloadedDirFiles+values[values.length-1]); } catch (Exception e) { Log.e("Error: ", e.getMessage()); outputString = e.getMessage(); resultArray.add("1"); resultArray.add(e.toString()); } //return null; return resultArray; } protected void onProgressUpdate(String... progress) { Log.d("ANDRO_ASYNC",progress[0]); mProgressDialog.setProgress(Integer.parseInt(progress[0])); } @Override protected void onPostExecute(ArrayList result) { dismissDialog(DIALOG_DOWNLOAD_PROGRESS); //Toast.makeText(getApplicationContext(), "onPostExecute: "+ result.get(0), Toast.LENGTH_LONG).show(); // ocurrio una excepcion if (result.get(0).equals("1")){ //Toast.makeText(getApplicationContext(), "onPostExecute: dentro del if" , Toast.LENGTH_LONG).show(); // ocurrio un problema AlertDialog.Builder builder = new AlertDialog.Builder(DownloaderActivity.this); String exception = ""; boolean fileFound = true; if (result.get(1).contains("Trust anchor for certification path not found")){ exception = "Intenta descargar un archivo de un servidor con certificado no confiable. ¿Desea continuar?."; } if (result.get(1).contains("java.io.FileNotFoundException")){ String [] v = result.get(1).split("/"); int length = v.length; exception = "No se encontró el archivo "+ v[length-1] +" en el servidor."; fileFound = false; } builder.setMessage(exception).setTitle("Error al descargar el archivo"); if (fileFound){ builder.setPositiveButton("Ok", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { // User clicked OK button Log.d("***", "DownloadFileAsync().execute(urlhttps, true)"); //Toast.makeText(getApplicationContext(), "DownloadFileAsync().execute("+urlhttps+", true)", Toast.LENGTH_LONG).show(); // pasar como segundo argmento que se acepta que el sertivor es desconocido new DownloadFileAsync().execute(urlhttps, "true"); } }); } builder.setNegativeButton("Cancelar", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { // User cancelled the dialog DownloaderActivity.this.finish(); } }); AlertDialog dialog = builder.create(); dialog.show(); }else{ // no ocurrió excepcion //Toast.makeText(getApplicationContext(), "Se descargo correctamente el archivo", Toast.LENGTH_LONG).show(); //Toast.makeText(getApplicationContext(), "result.get(0): "+result.get(0), Toast.LENGTH_LONG).show(); //Toast.makeText(getApplicationContext(), "result.get(1): "+result.get(1), Toast.LENGTH_LONG).show(); //Toast.makeText(getApplicationContext(), "downloadedDirFiles: "+downloadedDirFiles, Toast.LENGTH_LONG).show(); // lanzar activity para mostrar resultados de verificacion Intent intent = new Intent(DownloaderActivity.this, BDOCVerifyResultActivity.class); intent.putExtra("fileToVerify", result.get(1)); //Toast.makeText(getApplicationContext(), "putExtra1: "+result.get(1), Toast.LENGTH_LONG).show(); File f = new File(result.get(1)); Uri selectedUri = Uri.fromFile(f); String fileExtension = MimeTypeMap.getFileExtensionFromUrl(selectedUri.toString()); intent.putExtra("fileExtension", fileExtension); //Toast.makeText(getApplicationContext(), "putExtra2: "+fileExtension, Toast.LENGTH_LONG).show(); startActivity(intent); DownloaderActivity.this.finish(); } } } // fin de la clase DownloadFileAsync } // fin de DownloaderActivity