source: dispositivos_moviles/TibisayMovil/src/ve/gob/cenditel/tibisaymovil/FilesToPKCS7SignActivity.java @ 67541a6

Last change on this file since 67541a6 was 288126d, checked in by Jose Ruiz <joseruiz@…>, 11 years ago

Manejo de repositorio de certificados y firma con pkcs7

  • Property mode set to 100644
File size: 21.6 KB
Line 
1package ve.gob.cenditel.tibisaymovil;
2
3import java.io.File;
4import java.text.SimpleDateFormat;
5import java.util.ArrayList;
6import java.util.Collections;
7import java.util.Date;
8import java.util.List;
9
10
11import ve.gob.cenditel.tibisaymovil.R;
12import android.app.Activity;
13import android.app.AlertDialog;
14import android.content.DialogInterface;
15import android.content.Intent;
16import android.content.DialogInterface.OnCancelListener;
17import android.content.DialogInterface.OnDismissListener;
18import android.graphics.drawable.Drawable;
19import android.net.Uri;
20import android.os.Build;
21import android.os.Bundle;
22import android.view.LayoutInflater;
23import android.view.View;
24import android.view.ViewGroup;
25import android.view.View.OnClickListener;
26import android.view.Window;
27import android.webkit.MimeTypeMap;
28import android.widget.AdapterView;
29import android.widget.BaseAdapter;
30import android.widget.CheckBox;
31import android.widget.ImageView;
32import android.widget.LinearLayout;
33import android.widget.ListView;
34import android.widget.TextView;
35import android.widget.AdapterView.OnItemClickListener;
36import android.widget.Toast;
37
38public class FilesToPKCS7SignActivity extends KeyChainClientActivity implements OnItemClickListener, OnClickListener {
39
40        private File cwd;
41    private List<File> selected;
42    private FileBrowserView viewHolder;
43    private FileListAdapter listAdapter;
44        private int requestCode;
45        private int resultCode;
46        private Intent data;
47        private String privateKeyAlias;
48
49        @Override
50        protected void onCreate(Bundle savedInstanceState) {
51                //Estilando la barra de titulo
52                final boolean customTitleSupported = requestWindowFeature(Window.FEATURE_CUSTOM_TITLE);
53
54                super.onCreate(savedInstanceState);
55               
56                this.viewHolder = new FileBrowserView();       
57
58        if (savedInstanceState != null) {
59               
60                this.selected = TypeUtils.convertToFileList(savedInstanceState.getStringArrayList("selected"));
61            if (this.selected.size() > 0) {             
62                FilesToPKCS7SignActivity.this.updateButton
63                (FilesToPKCS7SignActivity.this.viewHolder.accept,true);
64            }
65           
66            this.cwd = new File(savedInstanceState.getString("cwd"));
67            this.viewHolder.fileList.setAdapter(this.listAdapter = new FileListAdapter(this.cwd.getAbsolutePath()));
68           
69        } else {
70            this.selected = new ArrayList<File>();
71            this.viewHolder.fileList.setAdapter(this.listAdapter = new FileListAdapter());
72        }
73       
74       
75        boolean enabled = false;
76        if (!this.selected.isEmpty())
77                enabled = this.viewHolder.accept.isEnabled();
78       
79                FilesToPKCS7SignActivity.this.updateButton(FilesToPKCS7SignActivity.this.viewHolder.accept,enabled);
80       
81        FilesToPKCS7SignActivity.this.updateButton
82        (FilesToPKCS7SignActivity.this.viewHolder.accept,enabled);
83       
84        //Estilando Barra de titulo
85                if(customTitleSupported)
86                        getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, R.layout.title_bar);
87                //Obtiene o crea un instancia de en keyChain y le asigna la actividad que lo genera
88               
89        KeyChainStrategy.getInstance().setClientActivity(this);
90        }
91
92       
93    /**
94     * Provides the data to be shown in the file browser ListView.
95     *
96     * @author José M. Prieto (jmprieto@emergya.com)
97     */
98    private class FileListAdapter extends BaseAdapter {
99
100        private final ArrayList<File> directories;
101        private final ArrayList<File> files;
102
103        private FileListAdapter() {
104            this("/");
105        }
106
107        private FileListAdapter(String location) {
108            this(location, "");
109        }
110       
111        private FileListAdapter(String location, String filterMimeType) {
112               
113            directories = new ArrayList<File>();
114            files = new ArrayList<File>();
115           
116            //Obtiene etiqueta que se colocará antes del path que visualizará el usuario
117                String toPathText = FilesToPKCS7SignActivity.this.getString(R.string.pathstring)+":   ";
118                //Coloca el texto de la etiqueta en la vista
119                FilesToPKCS7SignActivity.this.viewHolder.pathString.setText(toPathText);
120                //Coloca el texto con el path actual
121                FilesToPKCS7SignActivity.this.viewHolder.path.setText(location);
122                //Crea un objeto file cwd con la ubicacion dada en location
123            FilesToPKCS7SignActivity.this.cwd = new File(location);
124            //Obtiene el directorio padre del objeto file cwd
125            File parent = FilesToPKCS7SignActivity.this.cwd.getParentFile();
126            //Si tiene un padre, lo agrega en la posición cero de la lista de directorios 
127           
128            if (parent != null) {
129                directories.add(0, parent);
130            }
131           
132            //Crea un arreglo con las lista de archivos contenidos en el directorio cwd
133            File[] ls = FilesToPKCS7SignActivity.this.cwd.listFiles();
134            if (ls != null) {
135                for (File f : ls) { //recorre todos los archivos contenidos en el directorio
136                       
137                    if (FsUtils.isHiddenOrNotReadable(f)) { // Si son ocultos no hace nada
138                        continue;
139                    }
140                  // Si son directorios los agrega a la lista de directorios a partir de la posición 1
141                  // En la posición 0 se encuentra el directorio padre 
142                    if (f.isDirectory()) {
143                        directories.add(f);
144                    } else // De lo contrario lo agrega a la lista de archivos
145                        {
146                        //Valida tipo de archivo a mostrar
147                        Uri selectedUri = Uri.fromFile(f);
148                        String fileExtension = MimeTypeMap.getFileExtensionFromUrl(selectedUri.toString());
149                        String mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(fileExtension);
150                         
151//                        Toast.makeText(FileToSignHandwrittenSignatureActivity.this,
152//                          "FileExtension: " + fileExtension + "\n" +
153//                          "MimeType: " + mimeType,
154//                          Toast.LENGTH_LONG).show();
155                       
156                        //Filtra por mimeType
157                        if(filterMimeType.isEmpty() || filterMimeType == mimeType)
158                            files.add(f);
159                               
160                    }
161                }
162            }
163
164            Collections.sort(directories); // Ordena los directorios alfabeticamente
165            Collections.sort(files); // Ordena los archivos alfabeticamente
166        }
167       
168        /**
169         * Retorna cantidad total de elementos que se listarán en el directorio.
170         */
171        @Override 
172        public int getCount() {
173               
174            return directories.size() + files.size();
175           
176        }
177
178        /**
179         * Dada una posición en el listado del directorio, retorna un archivo o directorio
180         * según corresponda.
181         */
182        @Override
183        public File getItem(int position) {
184
185            if (position < directories.size()) {
186                return directories.get(position);
187            } else {
188                return files.get(position - directories.size());
189            }
190        }
191
192        /**
193         * Retorna un código hash para el archivo, permite comparar si dos archivos son los mismos
194         */
195        @Override
196        public long getItemId(int position) {
197
198            return getItem(position).hashCode();
199        }
200       
201        /**
202         * Crea la visualización de cada item del fileBrowser
203         */
204        @Override
205        public View getView(int position, View convertView, ViewGroup parent) {
206
207                //Crea la vista de cada fila del filebrowser a partir del layout
208            if (convertView == null) {
209                LayoutInflater inflater = LayoutInflater.from(FilesToPKCS7SignActivity.this);
210                convertView = inflater.inflate(R.layout.files_to_pkcs7_sign_item, parent, false); 
211            }
212           
213            // Se enlaza a cada componente del layout
214            ImageView image = (ImageView) convertView.findViewById(R.id.type_image);
215            TextView fileName = (TextView) convertView.findViewById(R.id.filename_text);
216            TextView modified = (TextView) convertView.findViewById(R.id.filename_modified);
217           
218            // Se obtiene el archivo ubicado en position
219                File file = getItem(position);
220               
221                //RadioButton
222            CheckBox check = (CheckBox) convertView.findViewById(R.id.file_check);
223            check.setFocusable(false);
224           
225            // Se asignan los iconos según el tipo de archivo y se oculta el radio en los directorios
226            if (file.isDirectory()) {
227                image.setImageResource(R.drawable.ic_carpeta);
228                check.setVisibility(View.INVISIBLE);
229                check.setChecked(false);
230            } else {
231                image.setImageResource(R.drawable.ic_archivo);
232                check.setVisibility(View.VISIBLE);
233                if (!FilesToPKCS7SignActivity.this.selected.contains(file)){
234                        check.setChecked(false);
235                } else{
236                        check.setChecked(true);
237                }
238         
239            }
240
241            // Si es el directorio que hace referencia al padre le coloca como nombre ".."
242            if (file.isDirectory() && position == 0 && ! "/".equals(FilesToPKCS7SignActivity.this.cwd.getAbsolutePath())) {
243                fileName.setText("..");
244            } else {
245                fileName.setText(file.getName());
246            }
247 
248           
249            //Datos de modificación del archivo
250            SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
251            Date date = new Date(file.lastModified());
252           
253            String dateString = FilesToPKCS7SignActivity.this.getString(R.string.modified)+": ";
254            if (file.lastModified()>0)
255                modified.setText(dateString+sdf.format(date));
256            else
257                modified.setText(dateString+"-");
258           
259            return convertView;
260        }
261       
262        /**
263         * Controla la selección de cada item del fileBrowser
264         */
265        public void select(ListView parent, int position) {
266
267            File item = getItem(position);
268            //Si es un directorio el seleccionado se hace un llamado del fileBrowser del directorio
269            if (item.isDirectory()) {
270                parent.setAdapter(FilesToPKCS7SignActivity.this.listAdapter = new FileListAdapter(item.getAbsolutePath()));
271            } else { // Si es un archivo
272               
273                        //Se agrega el archivo a la lista de seleccionados si no se encuentra en la misma               
274                if (!FilesToPKCS7SignActivity.this.selected.contains(item)){
275                       
276                        FilesToPKCS7SignActivity.this.selected.add(item);                       
277                        FilesToPKCS7SignActivity.this.updateButton(FilesToPKCS7SignActivity.this.viewHolder.accept,true);               
278                                               
279                }
280                else{ // De lo contrario se elimina de la lista de seleccionados
281                       
282                        FilesToPKCS7SignActivity.this.selected.remove(item);
283                       
284                        if (FilesToPKCS7SignActivity.this.selected.isEmpty()){
285                               
286                                FilesToPKCS7SignActivity.this.updateButton(FilesToPKCS7SignActivity.this.viewHolder.accept,false);
287
288                               
289                        }else {
290                                FilesToPKCS7SignActivity.this.updateButton(FilesToPKCS7SignActivity.this.viewHolder.accept,true);
291
292                        }
293                                       
294                }
295                notifyDataSetChanged();
296           }
297        }       
298    }   
299
300
301   
302   
303    @Override
304    protected void onSaveInstanceState(Bundle outState) {
305        super.onSaveInstanceState(outState);
306
307        outState.putParcelable("intent", this.getIntent());
308        outState.putString("cwd", this.cwd.getAbsolutePath());
309        outState.putStringArrayList("selected", TypeUtils.convertToStringArrayList(this.selected));
310       
311        outState.putParcelable("intent", this.data);
312        outState.putInt("requestCode", this.requestCode);
313        outState.putInt("resultCode", this.resultCode);
314       
315        }
316   
317    private void updateButton(View v, boolean bool) {
318        try{
319
320                v.setEnabled(bool);
321                if (v instanceof TextView){
322                        Drawable icon = ((TextView)v).getCompoundDrawables()[1];
323                        if (icon!=null)
324                        if (bool)
325                                icon.setAlpha(255);
326                        else
327                                icon.setAlpha(127);     
328                }
329                if (v instanceof ImageView){
330                        ImageView result = (ImageView) v;
331                        if (bool)
332                                result.setAlpha(255);
333                        else
334                                result.setAlpha(127);   
335                }
336       
337        }catch(NullPointerException e){}
338                       
339        }
340   
341    private void updateButton(LinearLayout layout, boolean bool) {
342        try{
343        layout.setEnabled(bool);
344        for (int i=0; i<layout.getChildCount();i++){
345                this.updateButton(layout.getChildAt(i), bool);
346        }
347        }catch(NullPointerException e){}
348                       
349        }
350
351       
352       
353        /**
354     * Holds references to view objects.
355     *
356     * @author José M. Prieto (jmprieto@emergya.com)
357     */
358    private class FileBrowserView {
359
360        public ListView fileList;
361        public TextView path;
362        public LinearLayout accept;
363                public LinearLayout clear;
364        public TextView pathString;
365
366        public FileBrowserView() {
367
368            setContentView(R.layout.activity_file_to_sign_handwritten_signature);
369            this.path = (TextView) findViewById(R.id.path);
370            this.pathString = (TextView) findViewById(R.id.pathstring);
371
372            this.fileList = (ListView) findViewById(R.id.file_list);
373            this.fileList.setOnItemClickListener(FilesToPKCS7SignActivity.this);
374            this.fileList.setItemsCanFocus(true);
375         
376           
377            this.clear = (LinearLayout) findViewById(R.id.button_clear_zone);
378            this.clear.setOnClickListener(FilesToPKCS7SignActivity.this);
379           
380            this.accept = (LinearLayout) findViewById(R.id.button_accept_zone);
381            this.accept.setOnClickListener(FilesToPKCS7SignActivity.this);
382
383        }
384    }
385   
386        @Override
387    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
388       
389       
390        if (parent.getId() == R.id.file_list) { // user selects a file
391            this.listAdapter.select((ListView) parent, position);
392           
393        } else { // user de-selects a file
394            //this.listAdapter.addIfSameDirectory(selectedAdapter.doUnselect((ListView) parent, position));
395               
396        }
397        //this.viewHolder.numSelected.setText(Integer.toString(this.selected.size()));
398    }
399
400    @Override
401    public void onClick(View v) {
402
403        switch (v.getId()) {
404
405       
406        case R.id.button_clear_zone:
407
408                this.selected.clear();
409                this.listAdapter.notifyDataSetChanged();
410
411                //this.viewHolder.numSelected.setText(""+this.selected.size());
412            this.updateButton(this.viewHolder.accept, false);
413                break;         
414       
415
416       
417            case R.id.button_accept_zone: 
418
419                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH || this.getFileStreamPath(DirectKeyChain.keyStoreFilename).exists()){
420                       
421           
422                Intent intent = new Intent(this, FilesToPKCS7SignConfirmationActivity.class);
423                intent.putStringArrayListExtra(IntentExtraField.FILES, TypeUtils.convertToStringArrayList(this.selected));
424                startActivityForResult(intent, ActivityResult.FILES_CONFIRMATED);
425         
426               
427                        }else{
428                                this.createNoKeyStoreDialog();
429                        }
430           
431                break;         
432       
433        }
434    }
435   
436   
437        private void createNoKeyStoreDialog() {
438                AlertDialog.Builder builder = new AlertDialog.Builder(this);
439
440                builder.setCancelable(false);
441                builder.setMessage(R.string.error_keystore_file);
442                builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
443                public void onClick(DialogInterface dialog, int id) {
444                    dialog.dismiss();
445                }
446            });
447                AlertDialog dialog = builder.create(); 
448                dialog.show();
449               
450        }
451   
452        @Override
453    protected void onActivityResult(int requestCode, int resultCode, final Intent data) {
454        Toast.makeText(this, "result", Toast.LENGTH_LONG).show();
455
456        this.requestCode = requestCode;
457        this.resultCode = resultCode;
458        this.data=data;
459        Toast.makeText(this, "request_code="+this.requestCode+" result="+this.resultCode, Toast.LENGTH_LONG).show();
460       
461       
462
463        if (resultCode == RESULT_CANCELED && requestCode!=ActivityResult.FILES_CONFIRMATED
464                &&      requestCode!=ActivityResult.IMPORT_CERTIFICATE) {
465                //Removed to fix task error #73085
466            /*setResult(RESULT_CANCELED);
467            finish();
468            return;
469            */
470               
471               
472                if (this.selected.size()>0){
473                 Intent intent = new Intent(this, FilesToPKCS7SignConfirmationActivity.class);
474             intent.putStringArrayListExtra(IntentExtraField.FILES, TypeUtils.convertToStringArrayList(this.selected));
475             startActivityForResult(intent, ActivityResult.FILES_CONFIRMATED);
476                }
477               
478               
479        }
480
481       
482        switch (requestCode) {
483        case ActivityResult.CHECK_CERTIFICATE_VALIDITY:
484
485            if (resultCode == RESULT_OK) {
486                Toast.makeText(FilesToPKCS7SignActivity.this, "aqui", Toast.LENGTH_LONG).show();
487
488                boolean embedSignature = data.getBooleanExtra(IntentExtraField.EMBED_SIGNATURE_IN_PDF, false);
489                Intent intent = new Intent(this, SignActivity.class);
490                intent.putExtra(IntentExtraField.EMBED_SIGNATURE_IN_PDF, embedSignature);
491                intent.putExtra(IntentExtraField.ALIAS, this.privateKeyAlias);
492                intent.putParcelableArrayListExtra(IntentExtraField.FILES, TypeUtils.convertToUriArrayList(this.selected));
493                startActivity(intent);
494               
495                //Finish only in this branch to fix error #73085
496                finish();
497            }
498            break;
499       
500        case ActivityResult.FILES_CONFIRMATED:
501                if (resultCode == RESULT_OK){
502                                               
503                        this.selected.clear();
504                        List<String> paths = data.getStringArrayListExtra(IntentExtraField.FILES);
505                        for (String s: paths)
506                                this.selected.add(new File(s));
507                       
508                        this.listAdapter.notifyDataSetChanged();
509                        KeyChainStrategy.getInstance().choosePrivateKeyAlias();
510
511                }
512                break;
513        }
514               
515               
516//        if (requestCode == ActivityResult.IMPORT_CERTIFICATE && resultCode == Activity.RESULT_OK) {
517//            //this.launchPasswordDialog(data);
518//        }
519    }
520       
521
522
523    private void launchPasswordDialog(final Intent data) {
524                //TODO: Setting boolean to false instead of true. Disables "New KeyStore" option.
525
526        final PasswordDialog dialog = new PasswordDialog(this, R.string.certificate_password, false);
527        dialog.setAcceptListener(new OnClickListener() {
528
529            @Override
530            public void onClick(View v) {
531
532                try {
533                        DirectKeyChain direct = DirectKeyChain.getInstance();
534                    int imported = direct.importCertificate(data.getData(), dialog.getPassword());
535                    String text = FilesToPKCS7SignActivity.this.getResources().getQuantityString(R.plurals.number_imported_certificates, imported, imported);
536                    Toast.makeText(FilesToPKCS7SignActivity.this, text, Toast.LENGTH_LONG).show();
537                    direct.saveKeystore();
538                    direct.refreshAdapter();
539                   
540                } catch (IncorrectPasswordException e) {
541                    Toast toast = Toast.makeText(FilesToPKCS7SignActivity.this, R.string.incorrect_password, Toast.LENGTH_LONG);
542                    toast.show();
543                } catch (Exception e) {
544                    Toast toast = Toast.makeText(FilesToPKCS7SignActivity.this, R.string.error_reading_p12, Toast.LENGTH_LONG);
545                    toast.show();
546                }
547               
548             
549               
550                dialog.dismiss();
551                FilesToPKCS7SignActivity.this.requestCode=Integer.MIN_VALUE;
552                FilesToPKCS7SignActivity.this.resultCode=Integer.MIN_VALUE;
553                FilesToPKCS7SignActivity.this.data=null;
554            }
555        });
556       
557       
558       
559        //TODO:
560       
561       dialog.setOnDismissListener(new OnDismissListener(){
562
563                @Override
564                public void onDismiss(DialogInterface arg0) {
565                        FilesToPKCS7SignActivity.this.data=null;
566                        FilesToPKCS7SignActivity.this.requestCode=Integer.MIN_VALUE;
567                        FilesToPKCS7SignActivity.this.resultCode=Integer.MIN_VALUE;                     
568                }});
569       
570       
571       
572       
573        dialog.setOnCancelListener(new OnCancelListener(){
574
575                        @Override
576                        public void onCancel(DialogInterface dialog) {
577                                FilesToPKCS7SignActivity.this.data=null;
578                                FilesToPKCS7SignActivity.this.requestCode=Integer.MIN_VALUE;
579                                FilesToPKCS7SignActivity.this.resultCode=Integer.MIN_VALUE;                             
580                        }});
581       
582        dialog.show();
583       
584        }
585
586
587    @Override
588    public void setAlias(String alias) {
589
590        if (alias == null) {
591                Toast.makeText(CustomKeyChain.activity, "alias null", Toast.LENGTH_LONG).show();
592
593            finish();
594            return;
595        }
596       // Toast.makeText(this, "setAlias="+alias, Toast.LENGTH_LONG).show();
597       
598        this.privateKeyAlias = alias;
599        Intent intent = new Intent(this, CertValidatorActivity.class);
600        intent.putExtra(IntentExtraField.ALIAS, alias);
601        intent.putParcelableArrayListExtra(IntentExtraField.FILES, TypeUtils.convertToUriArrayList(this.selected));
602        startActivityForResult(intent, ActivityResult.CHECK_CERTIFICATE_VALIDITY);
603    }
604       
605
606}
Note: See TracBrowser for help on using the repository browser.