001/*
002 *  $URL: $
003 *  $Author: $
004 *  $Revision: $
005 *  $Date: $
006 */
007/*
008 *
009 *  Written by Tom Gutwin - WebARTS Design.
010 *  Copyright (C) 2016-2018 WebARTS Design, North Vancouver Canada
011 *  http://www.webarts.bc.ca
012 *
013 *  This program is free software; you can redistribute it and/or modify
014 *  it under the terms of the GNU General Public License as published by
015 *  the Free Software Foundation; either version 2 of the License, or
016 *  (at your option) any later version.
017 *
018 *  This program is distributed in the hope that it will be useful,
019 *  but WITHOUT ANY WARRANTY; without_ even the implied warranty of
020 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
021 *  GNU General Public License for more details.
022 *
023 *  You should have received a copy of the GNU General Public License
024 *  along with this program; if not, write to the Free Software
025 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
026 */
027package ca.bc.webarts.tools;
028
029import java.io.File;
030import java.io.FileOutputStream;
031import java.io.IOException;
032import java.io.InputStreamReader;
033import java.io.OutputStream;
034import java.security.GeneralSecurityException;
035import java.security.NoSuchAlgorithmException;
036import java.text.NumberFormat;
037import java.util.Collections;
038import java.util.List;
039import java.util.Properties;
040import java.util.Vector;
041//import java.util.Base64;
042
043import es.vocali.util.AESCrypt;
044
045import javax.crypto.Cipher;
046import javax.crypto.KeyGenerator;
047import javax.crypto.SecretKey;
048import javax.crypto.spec.IvParameterSpec;
049import javax.crypto.spec.SecretKeySpec;
050
051import org.apache.commons.codec.binary.Base64;
052
053import javax.xml.bind.DatatypeConverter;
054import com.aftexsw.util.bzip.BZip;
055
056/**
057 * A simple application that encrypts files with AES. It encrypts the file and saves it with an added suffix
058   *  all you need to do is:
059   *  <pre>
060   *  // Encrypt
061   * String encryptedFilename = instance.encrypt(instance.getloadFilePath());
062   *  if (encryptedFilename!=null && !encryptedFilename.equals(""))
063   *  {
064   *    // Send File to GDrive
065   *    instance.setloadFilePath(encryptedFilename);
066   *    File uploadedFile = instance.uploadFile(false);
067   *  }
068   *  </pre>
069   * <br />
070   * If You want to use this from the commandline to encrypt or de-crypt, all you have to do is pass it the file name.<br />
071   * if the filename ends with '_etbg' it will try to decrypt the file; if not it will encrypt it AND add the '_etbg' to
072   * the end of the filename (before any existing extension).<br />
073   * <br />
074   * The encrypted file <i>can</i> also be compressed bz2.<br />
075   * Optionally, you can also pass it a AES password/key as a 2nd arg.
076   *
077   *
078   **/
079public class TomsCrypter
080{
081  /**  A holder for this clients System File Separator.  */
082  public final static String SYSTEM_FILE_SEPERATOR = java.io.File.separator;
083
084  /**  A holder for this clients System line termination separator.  */
085  public final static String SYSTEM_LINE_SEPERATOR =
086                                           System.getProperty("line.separator");
087  private static final String APPLICATION_NAME = "WebARTSDesign-TomsCrypter/0.1";
088  private static final String DEFAULT_DOWNLOAD_DIR = ".";
089  private static final String DEFAULT_LOAD_FILENAME = "./cryptDoc.txt";
090  private static final String DEFAULT_DATASTORE_DIR = System.getProperty("user.home")+
091                                                      SYSTEM_FILE_SEPERATOR+
092                                                      ".store"+
093                                                      SYSTEM_FILE_SEPERATOR+
094                                                      "TomsCrypter";
095
096  /** The Extension to use on the filename to markk it as AESEncrypted. **/
097  private static final String ECRYPT_FILEMARKER_DEFAULT="etbg";
098
099  /**  The VM classpath (used in some methods)..  */
100  public static String CLASSPATH = System.getProperty("class.path");
101
102  /**  The users home ditrectory.  */
103  public static String USERHOME = System.getProperty("user.home");
104
105  /**  The users pwd ditrectory.  */
106  public static String USERDIR = System.getProperty("user.dir");
107
108  /**  A holder This classes name (used when logging).  */
109  private static String CLASSNAME = "ca.bc.webarts.widgets.TomsCrypter";
110
111  private String loadFilePath_ = DEFAULT_LOAD_FILENAME;
112  private String dirForDownload_ = DEFAULT_DOWNLOAD_DIR;
113  private java.io.File loadFile_ = new java.io.File(loadFilePath_);
114
115  /** Directory to store user credentials. */
116  private  java.io.File dataStoreDir_ = null;
117
118  /** Filename suffix for the encrypted file. */
119  private  String encryptFilemarker_ = ECRYPT_FILEMARKER_DEFAULT;
120
121  /** Password for the AES Encryption **/
122  private String eCryptPass = "k2yaRe9~hQ2g^43kL;p[;@3dnldiqnhyw68nayiqgT351TQ[P]ov_QbjqU8&6.+/?0^5%1~";
123  String jceKey1 = "BFr4r482vW;6Hnj("; // 128 bit key
124  String jceKey2 = "^gaRe1%8sm8&54hL";
125
126  private static Cipher cipher = null;
127
128
129  /** Default constructor that gets all the basic class settimgs setup and gives you a class instance to do the work.
130   *  Then all you need to do is:
131   *  <pre>
132   *  GDriveCrypter instance = new GDriveCrypter(); // uses the DEFAULT_LOAD_FILENAME
133   *  //Authorize GDrive
134   *  instance.initDrive(instance.authorize());
135   *
136   *  // Encrypt
137   * String encryptedFilename = instance.encrypt(instance.getloadFilePath());
138   *  if (encryptedFilename!=null && !encryptedFilename.equals(""))
139   *  {
140   *    // Send File to GDrive
141   *    instance.setloadFilePath(encryptedFilename);
142   *    File uploadedFile = instance.uploadFile(false);
143   *  }
144   *  </pre>
145   *
146   **/
147  public  TomsCrypter() throws GeneralSecurityException, IOException
148  {
149    loadFilePath_ = DEFAULT_LOAD_FILENAME;
150    dirForDownload_  = DEFAULT_DOWNLOAD_DIR;
151    loadFile_ = new java.io.File(loadFilePath_);
152    dataStoreDir_ = new java.io.File(DEFAULT_DATASTORE_DIR);
153  }
154
155
156  /** Constructor that gets all the basic class settimgs setup, setsup the filename to upload and gives you a class instance to do the work.
157   *  Then all you need to do is:
158   *  <pre>
159   *  String fileNameToUpload = "someFile.txt";
160   *  TomsCrypter instance = new TomsCrypter(fileNameToUpload);
161
162   *  instance.initDrive(instance.authorize());
163   *
164   *  // Encrypt
165   * String encryptedFilename = instance.encrypt(instance.getloadFilePath());
166   *  if (encryptedFilename!=null && !encryptedFilename.equals(""))
167   *  {
168   *    // Send File to GDrive
169   *    instance.setloadFilePath(encryptedFilename);
170   *    File uploadedFile = instance.uploadFile(false);
171   *  }
172   *  </pre>
173   *
174   **/
175  public  TomsCrypter(String fileName) throws GeneralSecurityException, IOException
176  {
177    loadFilePath_ = fileName;
178    dirForDownload_  = DEFAULT_DOWNLOAD_DIR;
179    loadFile_ = new java.io.File(loadFilePath_);
180    dataStoreDir_ = new java.io.File(DEFAULT_DATASTORE_DIR);
181  }
182
183
184  /**
185   * Returns the value of encryptFilemarker.
186   */
187  public String getEncryptFilemarker()
188  {
189    return encryptFilemarker_;
190  }
191
192
193  /**
194   * Sets the value of encryptFilemarker_.
195   * @param encryptFilemarker The value to assign encryptFilemarker_.
196   */
197  public void setEncryptFilemarker(String encryptFilemarker)
198  {
199    this.encryptFilemarker_ = encryptFilemarker;
200  }
201
202
203  /** set the eCryptPass password used for encryption. **/
204  protected void seteCryptPass(String pass)
205  {
206      eCryptPass = pass;
207  }
208  /** get the eCryptPass password used for encryption. **/
209  private String geteCryptPass() { return eCryptPass; }
210
211
212  /** Set the filename path for the file that will be uploaded. **/
213  private void setloadFilePath(String path)
214  {
215      loadFilePath_ = path;
216      loadFile_ = new java.io.File(loadFilePath_);
217  }
218  /** get the filename path for the file that will be uploaded. **/
219  private String getloadFilePath() { return loadFilePath_; }
220
221
222
223  /** recursively creates parent dirs and the requested dir **/
224  public static void ensureFolderExists(java.io.File folder)
225  {
226    if ((folder != null) && !(folder.isDirectory() ))
227    {
228      ensureFolderExists(folder.getParentFile());
229      boolean suc = folder.mkdir();
230    }
231  }
232
233
234  /** Alias for encryptFile.**/
235  public String encrypt(String pass,String filename) { return encryptFile(pass, filename);}
236  /** Alias for encryptFile using the default Pass.**/
237  public String encrypt(String filename) { return encryptFile(geteCryptPass(), filename);}
238  /**
239    * encrypts the file with AES using the current class passwordKey and returns the encrypted filename.
240    * <br />
241    * When the file is encrypted it is saved with the same filename BUT with a '_etbg' appended to the end.
242    **/
243  public String encryptFile(String filename) { return encrypt(geteCryptPass(), filename);}
244
245
246  /**
247    * encrypts the AES  file using the passed in passwordKey and returns the encrypted filename.
248    * <br />
249    * When the file is encrypted it is saved with the same filename BUT with a '_etbg' appended to the end.
250    **/
251  public String encryptFile(String pass, String filename)
252  {
253    String retVal = "";
254    String encryptedFilename = loadFilePath_+"_"+getEncryptFilemarker() ;
255    try
256    {
257      AESCrypt aes = new AESCrypt(pass); //debug, passwd, AESCrypt.DIGEST_ALG_256
258      if (loadFilePath_.lastIndexOf(".")!= -1)
259      {
260        encryptedFilename = loadFilePath_.substring(0,loadFilePath_.lastIndexOf("."))+
261                                 "_"+getEncryptFilemarker() +"."+
262                                 loadFilePath_.substring(loadFilePath_.lastIndexOf(".")+1);
263      }
264      //else
265      //  encryptedFilename = loadFilePath_+"_"+getEncryptFilemarker() ;
266      aes.encrypt(2, loadFilePath_, encryptedFilename);
267      retVal = encryptedFilename;
268    }
269    catch(Exception ex)
270    {
271      System.err.println("did NOT encrypt file: "+loadFilePath_ + " to "+encryptedFilename);
272      ex.printStackTrace();
273    }
274    return retVal;
275  }
276
277
278  /** Alias for encryptString using the default Pass.**/
279  public String encryptString(String value) {return jceEncryptString(value);};
280  public String jceEncryptString(String value) {return jceEncryptString(jceKey1, jceKey2, value);};
281  public String jceEncryptString(String key1, String key2, String value)
282  {
283    try
284    {
285      IvParameterSpec iv = new IvParameterSpec(key2.getBytes("UTF-8"));
286
287      SecretKeySpec skeySpec = new SecretKeySpec(key1.getBytes("UTF-8"),
288              "AES");
289      if (cipher == null) cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
290      cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
291      byte[] encrypted = cipher.doFinal(value.getBytes());
292      //System.out.println("encrypted string:" + Base64.encodeBase64String(encrypted));
293      return Base64.encodeBase64String(encrypted);
294      //return new String(encrypted);
295    } catch (Exception ex) {
296        ex.printStackTrace();
297    }
298    return null;
299  }
300
301
302  public String decryptString(String encrypted) {return jceEncryptString(encrypted);};
303  public String jceDecryptString(String encrypted) {return jceDecryptString(jceKey1, jceKey2, encrypted);};
304  public String jceDecryptString(String key1, String key2, String encrypted)
305  {
306    try
307    {
308      IvParameterSpec iv = new IvParameterSpec(key2.getBytes("UTF-8"));
309
310      SecretKeySpec skeySpec = new SecretKeySpec(key1.getBytes("UTF-8"),
311              "AES");
312      if (cipher == null) cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
313      cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
314      byte[] original = cipher.doFinal(Base64.decodeBase64(encrypted));
315      //byte[] original = cipher.doFinal(encrypted.getBytes());
316
317      return new String(original);
318    } catch (Exception ex) {
319        ex.printStackTrace();
320    }
321    return null;
322  }
323
324
325  /** Takes a Base64 encoded string and creates an AES SecretKey from it. **/
326  public static SecretKey decodeBase64ToAESKey(final String encodedKey)
327        throws IllegalArgumentException
328  {
329    try
330    {
331        // throws IllegalArgumentException - if src is not in valid Base64
332        // scheme
333        final byte[] keyData = Base64.decodeBase64(encodedKey); //     Base64.getDecoder().decode(encodedKey);
334        final int keysize = keyData.length * Byte.SIZE;
335
336        // this should be checked by a SecretKeyFactory, but that doesn't exist for AES
337        switch (keysize)
338        {
339          case 128:
340          case 192:
341          case 256:
342              break;
343          default:
344            throw new IllegalArgumentException("Invalid key size for AES: " + keysize);
345        }
346
347        if (Cipher.getMaxAllowedKeyLength("AES") < keysize)
348        {
349            // this may be an issue if unlimited crypto is not installed
350            throw new IllegalArgumentException("Key size of " + keysize
351                    + " not supported in this runtime");
352        }
353
354        // throws IllegalArgumentException - if key is empty
355        final SecretKeySpec aesKey = new SecretKeySpec(keyData, "AES");
356        return aesKey;
357    }
358    catch (final NoSuchAlgorithmException e)
359    {
360        // AES functionality is a requirement for any Java SE runtime
361        throw new IllegalStateException(
362                "AES should always be present in a Java SE runtime", e);
363    }
364  }
365
366
367  /** Serializes an AES SecretKkey to a Base64 encoded string. **/
368  public static String encodeAESKeyToBase64(final SecretKey aesKey)
369        throws IllegalArgumentException
370  {
371    if (!aesKey.getAlgorithm().equalsIgnoreCase("AES"))
372    {
373        throw new IllegalArgumentException("Not an AES key");
374    }
375
376    final byte[] keyData = aesKey.getEncoded();
377    final String encodedKey = new String(Base64.encodeBase64(keyData)); //  Base64.getEncoder().encodeToString(keyData);
378    return encodedKey;
379  }
380
381
382
383  /** Alias for decryptFile.**/
384  public String decrypt(String pass,String filename) { return decryptFile(pass, filename);}
385  /** Alias for decryptFile using the default Pass.**/
386  public String decrypt(String filename) { return decryptFile(geteCryptPass(), filename);}
387  /**
388    * Decrypts the AES crypted file using the current class passwordKey and returns the decrypted filename.
389    **/
390  public String decryptFile(String filename) { return decryptFile(geteCryptPass(), filename);}
391
392
393  /**
394    * Decrypts the AES crypted file using the passed in passwordKey and returns the decrypted filename.
395    **/
396  public String decryptFile(String pass, String filename)
397  {
398    String retVal = "";
399    String decryptedFilename = filename.substring(0,filename.lastIndexOf("_"+getEncryptFilemarker() )) +
400                               filename.substring( filename.lastIndexOf("_"+getEncryptFilemarker() ) +
401                                                   ("_"+getEncryptFilemarker() ).length());
402    try
403    {
404      AESCrypt aes = new AESCrypt( pass); //debug, passwd
405      aes.decrypt( filename, decryptedFilename);
406      if(new java.io.File(decryptedFilename).length()>0)
407        retVal = decryptedFilename;
408      //new java.io.File(decryptedFilename).length();
409    }
410    catch(Exception ex)
411    {
412      System.err.println("did NOT decrypt file: "+filename);
413      ex.printStackTrace();
414    }
415    return retVal;
416  }
417
418
419  /** Alias for decryptString using the default Pass.**/
420  //public String decryptString(String eText) { return decryptString(geteCryptPass(), eText);}
421  /**
422    * decrypts the text with AES using the passed in passwordKey and returns the encrypted textString.
423    * @return the AES encrypted text or "" if error
424    **/
425    /*
426  public String decryptString(String pass, String eText)
427  {
428    String retVal = "";
429    java.io.InputStream eStream = new java.io.ByteArrayInputStream(eText.getBytes(java.nio.charset.Charset.forName("UTF-8")));
430    java.io.ByteArrayOutputStream stream = new java.io.ByteArrayOutputStream();
431    try
432    {
433      String tmpFilename = System.getProperty("java.io.tmpdir")+SYSTEM_FILE_SEPERATOR+"eh6H71mxh9S_etbg.txt";
434      ca.bc.webarts.widgets.Util.writeStringToFile(eText ,tmpFilename);
435      String dFilename = decryptFile(tmpFilename);
436      retVal = ca.bc.webarts.widgets.Util.readFileToString(dFilename);
437      java.nio.file.Path path = java.nio.file.FileSystems.getDefault().getPath(dFilename);
438      java.nio.file.Files.deleteIfExists(path);
439      path = java.nio.file.FileSystems.getDefault().getPath(tmpFilename);
440      java.nio.file.Files.deleteIfExists(path);
441    }
442    catch(Exception ex)
443    {
444      System.err.println("did NOT decrypt "+eText);
445      ex.printStackTrace();
446    }
447    return retVal;
448  }
449*/
450
451  /** UnBzips the passed file (that must have a '.bz2' extension) to its same filename
452   *  in the same dir  without the '.bz2' extension.
453   * @param  fo  The File object to unzip - must have a '.bz2' extension.
454   **/
455  public static long unBzip2It(java.io.File fo)
456  {
457    final String methodName = CLASSNAME + ".bzip2It(File)";
458    //logger_.debug("Entering " + methodName);
459    long retVal = 0L;
460
461    String fullFilename = fo.getAbsolutePath().trim();
462      java.io.File outFile = null;
463    if (fullFilename.lastIndexOf(".bz2")>-1)
464    {
465      String unzippedFilename = fullFilename.substring(0, fullFilename.lastIndexOf(".bz2"));
466      outFile = new java.io.File(unzippedFilename);
467      BZip.decompress(fo, outFile);
468      }
469  retVal = outFile.length();
470
471    //logger_.debug("Exiting " + methodName);
472    return retVal;
473  }
474
475
476  /**
477   *  Wrapper method to accept a dir or individual file in the passed in File
478   *  object AND then calls the method that writes the passed file/dir to this
479   *  MultiZip instances zip output stream. This is a recursive function. If the
480   *  passed File object is a file then it calls the function to write to zip
481   *  output stream. If it is a directory it gets the list of file objects in
482   *  the child directory and recurses on them.
483   *
484   * @param  fo  The File object to zip up (can be an actual file or dir).
485   * @return     the new length in bytes of the zipped file
486   */
487  public static long bzip2It(java.io.File fo)
488  {
489    final String methodName = CLASSNAME + ".bzip2It(File)";
490    //logger_.debug("Entering " + methodName);
491    long retVal = 0L;
492
493    String fullFilename = fo.getAbsolutePath().trim();
494    if (!fo.isDirectory())
495    {
496      //logger_.info("Bzip2ing "+fullFilename);
497        StringBuffer outLocation = new StringBuffer();
498          // zip it in place
499          //logger_.info("Bzip2ing "+fullFilename);
500          java.io.File outFile = new java.io.File(fullFilename + ".bz2");
501
502          ensureFolderExists(outFile.getParentFile());
503          try
504          {
505            BZip.compress(fo, outFile, 9);
506            //compressedFilenames_.add(fullFilename + ".bz2");
507            retVal += outFile.length();
508          }
509          catch (java.lang.ArithmeticException mathEx)
510          {
511            //logger_.error("BZip2 ERROR: " + fullFilename);
512            //logger_.error(mathEx.getMessage());
513          }
514    }
515    else
516    {
517        //logger_.info("Recursing " + fo.getPath());
518        String srcFileNames[] = fo.list();
519        for (int i = 0; i < srcFileNames.length; i++)
520        {
521          retVal += bzip2It(new java.io.File(fullFilename + java.io.File.separator +
522              srcFileNames[i]));
523        }
524    }
525
526    //logger_.debug("Exiting " + methodName);
527    return retVal;
528  }
529
530
531  /** Prints out the help syntax and usage details. **/
532  public static String printUsage()
533  {
534    final String methodName = CLASSNAME + ": printUsage()";
535    String retVal = "";
536
537    retVal += "\n"+"\n"+APPLICATION_NAME+"\n- - - - - - - - - - - - - - - - - - - - \n"+"Class "+CLASSNAME+"\n";
538    retVal += "A simple application that encrypts (or de-crypts) files with AES.  All it requires is the filename.\n\n";
539    retVal += "  If the filename ends with '_etbg' it will try to decrypt the file; if not, it will encrypt it AND add ";
540    retVal += "the '_etbg' to the end of the filename (before any existing extension).\n";
541    retVal += "   --> The encrypted file can also be compressed bz2. \n";
542    retVal += "   --> It does NOT remove the original file after completion.\n";
543    retVal += "   --> Optionally, you can also pass it a AES passPhrase/key as an optional argumnent before the filename.\n";
544    retVal += "   --> if a phassphrase is not passed... it uses a default passphrae.. \n";
545    retVal += "\n";
546    retVal += "Usage: java "+CLASSNAME+" filename  [passPhrase]\n";
547    retVal += "      one command parameter is required... filename - the the filename to encrypt or decrypt\n\n";
548    retVal += "Examples:\n";
549    retVal += "      java "+CLASSNAME+" mySecretStuff.txt\n"+"        --> encrypts mySecretStuff.txt\n\n";
550    retVal += "      java "+CLASSNAME+" mySecretStuff_etbg.txt\n"+"        --> de-crypts mySecretStuff.txt\n\n";
551    retVal += "      java "+CLASSNAME+" mySecretStuff.txt gYre%8B9@dsw}\n";
552    retVal += "        --> uses gYre%8B9@dsw} as the passphrase  when encrypting (or de-crypting) the mySecretStuff.txt file\n\n";
553    System.out.println(retVal);
554    return retVal;
555  }
556
557
558
559  /**
560    * Syntax:<br />
561    * java ca.bc.webarts.tools.TomsCrypter [passwordKey] filename<br />
562    * <br />
563    * NOTE: if filename has the encrypted filemarker 'etbg' in its filename,
564    * then this will DEcrypt the passed in filename.
565    *
566    * <br />
567    * When the file is encrypted it is saved with the same filename BUT with a '_etbg' appended to the end.
568    * <br />
569    **/
570  public static void main(String[] args)
571  {
572    boolean encrypting = false;
573    boolean compressing = false;
574    String fileName = DEFAULT_LOAD_FILENAME;
575    try
576    {
577      TomsCrypter instance = null;
578      TomsCrypter instance2 = new TomsCrypter();
579      if (args.length>0)
580      {
581        fileName = args[0];
582        System.out.println(fileName);
583        instance = new TomsCrypter(fileName);
584      }
585      else
586      {
587        if ((new File(fileName)).exists())
588          instance = new TomsCrypter();
589        else
590          printUsage();
591      }
592      if (args.length>1)
593      {
594        instance.seteCryptPass(args[1]);
595        instance2.seteCryptPass(args[1]);
596      }
597
598      if (instance.getloadFilePath().lastIndexOf(instance.getEncryptFilemarker() ) == -1)
599        encrypting=true;
600
601      if(encrypting)
602      {
603        // Encrypt
604        View.header1("encrypting File:"+instance.getloadFilePath());
605        String encryptedFilename = instance.encrypt(instance.getloadFilePath());
606        System.out.print("Testing encryptString("+"ec5e0705142ac3e10fb22c0f5bfbd97b62082b1002e1e52003e782da8cd7c142"+") = \n   ");
607        String eString = instance2.encryptString("ec5e0705142ac3e10fb22c0f5bfbd97b62082b1002e1e52003e782da8cd7c142");
608        System.out.println(eString);
609        System.out.print("\nTesting decryptString("+eString+") = ");
610        String decryptedString = instance2.decryptString(eString);
611        System.out.println(decryptedString);
612
613        if (compressing && encryptedFilename!=null && !encryptedFilename.equals(""))
614        {
615          // BZip it
616          View.header1("BZipping encrypted File:"+encryptedFilename);
617          if (bzip2It(new java.io.File(encryptedFilename))>0L)
618          {
619            View.header1("Success");
620            encryptedFilename=encryptedFilename+ ".bz2";
621          }
622          View.header1("Success!");
623        }
624        //return;
625      }
626      else // download and decrypt
627      {
628
629       if (args.length>0)
630       {
631          View.header1("Uncompressing ");
632          //uncompress it
633          if (fileName.indexOf(".bz2")!=-1)
634          {
635            instance.unBzip2It(new File(fileName));
636            fileName = fileName.substring(0,fileName.lastIndexOf(".bz2"));
637          }
638
639          //decrypting
640          View.header1("decrypting "+fileName);
641          instance.decryptFile(fileName);
642        }
643      }
644    }
645    catch (GeneralSecurityException gSecEx)
646    {
647      System.err.println(gSecEx.getMessage());
648    }
649    catch (IOException e)
650    {
651      System.err.println(e.getMessage());
652    }
653    catch (Throwable t)
654    {
655      t.printStackTrace();
656    }
657    System.exit(1);
658  }
659}
660
661/**
662 * Utility methods to print to the command line.
663 */
664class View {
665
666  static void header1(String name) {
667    System.out.println();
668    System.out.println("================== " + name + " ==================");
669    System.out.println();
670  }
671
672  static void header2(String name) {
673    System.out.println();
674    System.out.println("~~~~~~~~~~~~~~~~~~ " + name + " ~~~~~~~~~~~~~~~~~~");
675    System.out.println();
676  }
677}