/* 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.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.ObjectOutputStream; import java.security.PrivateKey; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.List; import com.sun.jersey.api.client.ClientHandlerException; import com.sun.jersey.api.client.UniformInterfaceException; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.content.res.Resources; import android.net.Uri; import android.os.Bundle; import android.os.Environment; import android.text.method.ScrollingMovementMethod; import android.util.Log; import android.view.View; import android.view.Window; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.LinearLayout; import android.widget.TextView; import android.widget.Toast; import com.lowagie.text.exceptions.InvalidPdfException; // prueba de droidtext import com.lowagie.text.pdf.*; import com.lowagie.text.*; public class SignActivity extends Activity implements OnClickListener { private boolean embedInPdf; private String alias; private List uris; private SignView viewHolder; private List signed; private List unsigned; private ArrayList send = new ArrayList(); private SignTask task; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { //Estilando la barra de titulo final boolean customTitleSupported = requestWindowFeature(Window.FEATURE_CUSTOM_TITLE); super.onCreate(savedInstanceState); this.embedInPdf = getIntent().getBooleanExtra(IntentExtraField.EMBED_SIGNATURE_IN_PDF, false); this.alias = getIntent().getStringExtra(IntentExtraField.ALIAS); this.uris = getIntent().getParcelableArrayListExtra(IntentExtraField.FILES); this.viewHolder = new SignView(); this.task = (SignTask) getLastNonConfigurationInstance(); if (this.task != null) { this.task.activity = this; } else if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) { this.task = (SignTask) new SignTask(this, FsUtils.createOutputDirectory(this), this).execute( uris.toArray(new Uri[uris.size()])); } else { this.viewHolder.noStorageError(); } if (savedInstanceState != null) { this.send = savedInstanceState.getParcelableArrayList("send"); this.viewHolder.done(); } //Estilando Barra de titulo if(customTitleSupported) getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, R.layout.title_bar); } @Override public Object onRetainNonConfigurationInstance() { return this.task; } @Override protected void onDestroy() { this.task.cancel(true); if (this.task != null) { this.task.activity = null; } super.onDestroy(); } @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); outState.putParcelableArrayList("send", this.send); } @Override public void onBackPressed() { Intent back = new Intent(this, TibisayMovilActivity.class); startActivity(back); finish(); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.button_finish_zone: Intent back = new Intent(this, TibisayMovilActivity.class); startActivity(back); finish(); break; case R.id.button_share_zone: Intent intent = IntentUtils.sendMultipleFiles(this.send); //In case user has no email application. try{ startActivity(intent); finish(); }catch (android.content.ActivityNotFoundException e){ Toast.makeText(this, this.getString(R.string.errornoemail), Toast.LENGTH_SHORT).show(); } } } private static class SignTask extends AsyncErrorTask> { private SignActivity activity; private String directory; private Context context; public SignTask(SignActivity activity, String directory, Context context) { this.activity = activity; this.directory = directory; this.context = context; } @Override protected List doInBackground(Uri... uris) { X509Certificate[] chain; X509Certificate certificate; PrivateKey key; KeyChainStrategy keyChain = KeyChainStrategy.getInstance(); try { chain = keyChain.getCertificateChain(this.activity.alias); certificate = chain[0]; key = keyChain.getPrivateKey(this.activity.alias); } catch (Exception e) { this.cancel(true); chain=null; key=null; certificate=null; throw new RuntimeException(e); } ArrayList signed = new ArrayList(uris.length); //NEW: History. ArrayList sourcesPath = new ArrayList(); ArrayList destinationsPath = new ArrayList(); Log.d("SignActivity:SignTask", "antes del for"); for (Uri uri : uris) { Uri signedUri = null; try { String inputFilename = uri.getPath(); if (this.activity.embedInPdf && FsUtils.isPDF(inputFilename)) { // ******************************************************************** Log.d("SignActivity", "antes de CryptoUtils.signPDF"); PdfReader reader = new PdfReader(inputFilename); Log.d("SignActivity", "new PdfReader"); int n; String targetFilename = new File(this.directory, uri.getLastPathSegment()).getPath(); if ((n = targetFilename.lastIndexOf(".")) > targetFilename.lastIndexOf("/")) { targetFilename = targetFilename.substring(0, n) + "-firma.pdf"; } else { targetFilename = targetFilename + "-firma.pdf"; } Log.d("SignActivity", "targetFilename: "+targetFilename); FileOutputStream fout = new FileOutputStream(targetFilename); PdfStamper stp = PdfStamper.createSignature(reader, fout, '?'); Log.d("SignActivity", "PdfStamper.createSignature"); PdfSignatureAppearance sap = stp.getSignatureAppearance(); Log.d("SignActivity", "stp.getSignatureAppearance()"); sap.setCrypto(key, chain, null, PdfSignatureAppearance.WINCER_SIGNED); Log.d("SignActivity", "sap.setCrypto"); sap.setReason("Firma PKCS12 Android"); Log.d("SignActivity", "sap.setReason"); sap.setLocation("Imaginanet"); Log.d("SignActivity", "sap.setLocation"); stp.close(); Log.d("SignActivity", "stp.close"); //signedUri = FsUtils.saveToFile(fout, targetFilename); File file = new File(targetFilename); signedUri = Uri.fromFile(file); // ******************************************************************** /* InputStream signedPDF = CryptoUtils.signPDF(new File(inputFilename), chain, key, this.context); int n; String targetFilename = new File(this.directory, uri.getLastPathSegment()).getPath(); if ((n = targetFilename.lastIndexOf(".")) > targetFilename.lastIndexOf("/")) { targetFilename = targetFilename.substring(0, n) + "-firma.pdf"; } else { targetFilename = targetFilename + "-firma.pdf"; } signedUri = FsUtils.saveToFile(signedPDF, targetFilename); */ //TODO: signedUri for uri signed.add(uri); this.activity.send.add(signedUri); } else { FsUtils.copyTo(new File(uri.getPath()), this.directory); Log.d("SignActivity", "antes de CryptoUtils.signPKCS7"); byte[] signature = CryptoUtils.signPKCS7(new File(inputFilename), certificate, key); int n; String targetFilename = new File(this.directory, uri.getLastPathSegment()).getPath(); if ((n = targetFilename.lastIndexOf(".")) > targetFilename.lastIndexOf("/")) { targetFilename = targetFilename.substring(0, n) + ".p7b"; } else { targetFilename = targetFilename + ".p7b"; } Log.d("SignActivity", "antes de signedUri"); signedUri = FsUtils.saveToFile(signature, targetFilename); signed.add(uri); this.activity.send.add(uri); this.activity.send.add(signedUri); Log.d("SignActivity", "despues de signedUri"); } } catch (FileAlreadyExistsException e) { final Activity act = ((Activity) this.context); Toast.makeText(act, act.getString(R.string.errorServerNotReachable), Toast.LENGTH_SHORT).show(); //} catch (DocumentWritingException e) { } catch (ClientHandlerException e){ final Activity act = ((Activity) this.context); act.runOnUiThread(new Runnable() { public void run() { Toast.makeText(act, act.getString(R.string.errorServerNotReachable), Toast.LENGTH_SHORT).show(); } }); } catch (UniformInterfaceException e) { final Activity act = ((Activity) this.context); act.runOnUiThread(new Runnable() { public void run() { Toast.makeText(act, act.getString(R.string.errorConnection), Toast.LENGTH_SHORT).show(); } }); } catch (InvalidPdfException e) { //empty } catch (Exception e) { final Activity act = ((Activity) this.context); Toast.makeText(act, "exception", Toast.LENGTH_SHORT).show(); FsUtils.checkOutOfSpace(e, true); this.cancel(true); //throw new RuntimeException(e); } //HISTORY: //Fixed spaces path error with getPath instead of getEncodedPath finally{ sourcesPath.add(uri.getPath()); if (signedUri!=null) destinationsPath.add(signedUri.getPath()); else destinationsPath.add(""); } } // DIR Save history.mbs String[] pathSplit = this.directory.split("/"); String dirName = pathSplit[pathSplit.length-1]; File targetHistory = new File(this.directory, dirName); //File targetHistory = new File(this.directory, "history.mbs"); String alias = this.activity.alias; // this.saveHistoryData(alias, CertificateUtils.getSubject(chain[0]), // CertificateUtils.getSerial(chain[0]), // CertificateUtils.getIssuer(chain[0]),sourcesPath, destinationsPath, targetHistory); //---------- return signed; } @Override protected void onPostExecute(List signed) { if (this.activity != null) { if (getError() != null) { if (getError().getCause() instanceof OutOfSpaceError) { this.activity.viewHolder.outOfSpaceError(); } else { this.activity.viewHolder.unknownError(); } return; } this.activity.signed = signed; if (signed.size() < this.activity.uris.size()) { this.activity.unsigned = new ArrayList(this.activity.uris); this.activity.unsigned.removeAll(signed); } this.activity.viewHolder.update(); } } // private void saveHistoryData(String alias, String subject, String serial, String issuer, List files, // ArrayList unsigned, File path) { // // // HistoryData data = new HistoryData (alias, subject, serial, issuer, files, unsigned); // // ByteArrayOutputStream baos = new ByteArrayOutputStream(); // try{ // ObjectOutputStream oos = new ObjectOutputStream(baos); // oos.writeObject(data); // oos.flush(); // oos.close(); // }catch(IOException e){} // InputStream is = new ByteArrayInputStream(baos.toByteArray()); // // try { // FsUtils.saveToFile(is, path.getPath()); // } catch (Exception e){} // // // } } private class SignView { public LinearLayout finish; public LinearLayout share; public TextView summary; public TextView summary2; public View signing; public SignView () { setContentView(R.layout.sign); this.finish = (LinearLayout) findViewById(R.id.button_finish_zone); this.finish.setOnClickListener(SignActivity.this); this.share = (LinearLayout) findViewById(R.id.button_share_zone); this.share.setOnClickListener(SignActivity.this); this.summary = (TextView) findViewById(R.id.summary); this.summary.setMovementMethod(new ScrollingMovementMethod()); this.summary2 = (TextView) findViewById(R.id.summary2); this.summary2.setMovementMethod(new ScrollingMovementMethod()); this.signing = findViewById(R.id.signing); } public void noStorageError() { this.summary.setText(R.string.no_storage); this.signing.setVisibility(View.GONE); } public void outOfSpaceError() { this.summary.setText(R.string.error_no_space); this.signing.setVisibility(View.GONE); } public void unknownError() { this.summary.setText(R.string.error_unknown); this.signing.setVisibility(View.GONE); } public void update() { StringBuilder builder = new StringBuilder(); StringBuilder builder2 = new StringBuilder(); Resources res = SignActivity.this.getResources(); //Fix Error #75235 if (SignActivity.this.signed != null && !SignActivity.this.signed.isEmpty()) { // builder.append(res.getString(R.string.signedfiles)); for (Uri file : SignActivity.this.signed) { builder.append("\n - "); builder.append(file.getLastPathSegment()); } // builder.append("\n\n"); } if (SignActivity.this.unsigned != null && !SignActivity.this.unsigned.isEmpty()) { builder2.append(res.getString(R.string.unsigned2)); for (Uri file : SignActivity.this.unsigned) { builder2.append("\n - "); builder2.append(file.getLastPathSegment()); } } this.summary.setText(builder); this.summary2.setText(builder2); done(); } public void done() { this.signing.setVisibility(View.GONE); this.share.setEnabled(true); } } }