Mega Code Archive

 
Categories / Java / Security
 

Xml dap Certs And Keys

/*  * XmldapCertsAndKeys.java  *  * Created on 6. September 2006, 11:08  *  * To change this template, choose Tools | Template Manager  * and open the template in the editor.  */ //package org.xmldap.util; import java.io.ByteArrayInputStream; import java.io.IOException; import java.math.BigInteger; import java.security.KeyFactory; import java.security.NoSuchAlgorithmException; import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.security.interfaces.RSAPrivateKey; import java.security.spec.InvalidKeySpecException; import java.security.spec.RSAPrivateKeySpec; /**  *   * @author Axel Nennker  */ public class XmldapCertsAndKeys {   static final String cert1B64 = "MIIDkDCCAvmgAwIBAgIJAO+Fcd4yj0h/MA0GCSqGSIb3DQEBBQUAMIGNMQswCQYD"       + "VQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZyYW5j"       + "aXNjbzEPMA0GA1UEChMGeG1sZGFwMScwJQYDVQQLFB5DaHVjayBNb3J0aW1vcmUg"       + "JiBBeGVsIE5lbm5rZXIxFzAVBgNVBAMTDnd3dy54bWxkYXAub3JnMB4XDTA3MDgx"       + "ODIxMTIzMVoXDTE3MDgxNTIxMTIzMVowgY0xCzAJBgNVBAYTAlVTMRMwEQYDVQQI"       + "EwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1TYW4gRnJhbmNpc2NvMQ8wDQYDVQQKEwZ4"       + "bWxkYXAxJzAlBgNVBAsUHkNodWNrIE1vcnRpbW9yZSAmIEF4ZWwgTmVubmtlcjEX"       + "MBUGA1UEAxMOd3d3LnhtbGRhcC5vcmcwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ"       + "AoGBAOKUn6/QqTZj/BWoQVxNFI0Z2AXI1azws+RyuJek60NiawQrFAKk0Ph+/YnU"       + "iQAnzbsT+juZV08UpaPa2IE3g0+RFZtODlqoGGGakSOd9NNnDuNhsdtXJWgQq8pa"       + "M9Sc4nUue31iq7LvmjSGSL5w84NglT48AcqVGr+/5vy8CfT/AgMBAAGjgfUwgfIw"       + "HQYDVR0OBBYEFGcwQKLQtW8/Dql5t70BfXX66dmaMIHCBgNVHSMEgbowgbeAFGcw"       + "QKLQtW8/Dql5t70BfXX66dmaoYGTpIGQMIGNMQswCQYDVQQGEwJVUzETMBEGA1UE"       + "CBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEPMA0GA1UEChMG"       + "eG1sZGFwMScwJQYDVQQLFB5DaHVjayBNb3J0aW1vcmUgJiBBeGVsIE5lbm5rZXIx"       + "FzAVBgNVBAMTDnd3dy54bWxkYXAub3JnggkA74Vx3jKPSH8wDAYDVR0TBAUwAwEB"       + "/zANBgkqhkiG9w0BAQUFAAOBgQAYQisGgrg1xw0TTgIZcz3JXr+ZtwjeKqEewoxC"       + "xBz1uki7hJYHIznEZq4fzSMtcBMgbKmOTzFNV0Yr/tnJ9rrljRf8EXci62ffzj+K"       + "kny7JtM6Ltxq0BJuF3jrXogdbsc5J3W9uJ7C2+uJTHG1mApbOdJGvLAGLCaNw5Np"       + "P7+ZXQ==";   /** Creates a new instance of XmldapCertsAndKeys */   private XmldapCertsAndKeys() {   }   public static X509Certificate getXmldapCert() throws CertificateException {     String certB64 = "MIIDXTCCAkUCBEQd+4EwDQYJKoZIhvcNAQEEBQAwczELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNh"         + "bGlmb3JuaWExFjAUBgNVBAcTDVNhbiBGcmFuY2lzY28xDzANBgNVBAoTBnhtbGRhcDERMA8GA1UE"         + "CxMIaW5mb2NhcmQxEzARBgNVBAMTCnhtbGRhcC5vcmcwHhcNMDYwMzIwMDA0NjU3WhcNMDYwNjE4"         + "MDA0NjU3WjBzMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2Fu"         + "IEZyYW5jaXNjbzEPMA0GA1UEChMGeG1sZGFwMREwDwYDVQQLEwhpbmZvY2FyZDETMBEGA1UEAxMK"         + "eG1sZGFwLm9yZzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANMnkVA4xfpG0bLos9FO"         + "pNBjHAdFahy2cJ7FUwuXd/IShnG+5qF/z1SdPWzRxTtpFFyodtXlBUEIbiT+IbYPZF1vCcBrcFa8"         + "Kz/4rBjrpPZgllgA/WSVKjnJvw8q4/tO6CQZSlRlj/ebNK9VyT1kN+MrKV1SGTqaIJ2l+7Rd05WH"         + "scwZMPdVWBbRrg76YTfy6H/NlQIArNLZanPvE0Vd5QfD4ZyG2hTh3y7ZlJAUndGJ/kfZw8sKuL9Q"         + "Srh4eOTc280NQUmPGz6LP5MXNmu0RxEcomod1+ToKll90yEKFAUKuPYFgm9J+vYm4tzRequLy/nj"         + "teRIkcfAdcAtt6PCYjUCAwEAATANBgkqhkiG9w0BAQQFAAOCAQEAURtxiA7qDSq/WlUpWpfWiZ7H"         + "vveQrwTaTwV/Fk3l/I9e9WIRN51uFLuiLtZMMwR02BX7Yva1KQ/Gl999cm/0b5hptJ+TU29rVPZI"         + "lI32c5vjcuSVoEda8+BRj547jlC0rNokyWm+YtBcDOwfHSPFFwVPPVxyQsVEebsiB6KazFq6iZ8A"         + "0F2HLEnpsdFnGrSwBBbH3I3PH65ofrTTgj1Mjk5kA6EVaeefDCtlkX2ogIFMlcS6ruihX2mlCLUS"         + "rlPs9TH+M4j/R/LV5QWJ93/X9gsxFrxVFGg3b75EKQP8MZ111/jaeKd80mUOAiTO06EtfjXZPrjP"         + "N4e2l05i2EGDUA==";     byte[] certBytes = Base64.decode(certB64);     CertificateFactory cf = CertificateFactory.getInstance("X509");     ByteArrayInputStream inStream = new ByteArrayInputStream(certBytes);     return (X509Certificate) cf.generateCertificate(inStream);   }   public static RSAPrivateKey getXmldapPrivateKey()       throws InvalidKeySpecException, NoSuchAlgorithmException {     String exponentB64 = "AKh/FZVHiKxcIPA8g2mN8TUdMXuX58I7z4jS+57vYta387MG3DGZtQ/XXfHdPx9WjdoW0KWE2Pl5"         + "SbOZW7tVcwigF88FrSJ5i6XDwUktmXjFwJM/TvUZlxWAKUdoOX8MC3DrAYZxeT3kC1mzAiBMPdC4"         + "W4zNe7Zo0YgbsMzQZowVxZTP4GWa/L8o3adXTvdobP1nKW5buPj9vkgaGCTxE0vQzbuiGj1HRJe9"         + "MRtvcU/I2shiIVE0F35wk8gw0FATtkvMpTpR12YVeo1JGZsHFQoD7gTD/n/NmC9Rjk2baYGj97hV"         + "9EpDRcPNsMll2pVRy4Z45j2+t/yl8WjaqK5lhkE=";     String modulusB64 = "ANMnkVA4xfpG0bLos9FOpNBjHAdFahy2cJ7FUwuXd/IShnG+5qF/z1SdPWzRxTtpFFyodtXlBUEI"         + "biT+IbYPZF1vCcBrcFa8Kz/4rBjrpPZgllgA/WSVKjnJvw8q4/tO6CQZSlRlj/ebNK9VyT1kN+Mr"         + "KV1SGTqaIJ2l+7Rd05WHscwZMPdVWBbRrg76YTfy6H/NlQIArNLZanPvE0Vd5QfD4ZyG2hTh3y7Z"         + "lJAUndGJ/kfZw8sKuL9QSrh4eOTc280NQUmPGz6LP5MXNmu0RxEcomod1+ToKll90yEKFAUKuPYF"         + "gm9J+vYm4tzRequLy/njteRIkcfAdcAtt6PCYjU=";     byte[] exponentBytes = Base64.decode(exponentB64);     byte[] modulusBytes = Base64.decode(modulusB64);     BigInteger exponent = new BigInteger(1, exponentBytes);     BigInteger modulus = new BigInteger(1, modulusBytes);     RSAPrivateKeySpec ks = new RSAPrivateKeySpec(modulus, exponent);     KeyFactory kf = KeyFactory.getInstance("RSA");     return (RSAPrivateKey) kf.generatePrivate(ks);   }   public static String getXmldapCert1String() {     return cert1B64;   }   public static X509Certificate getXmldapCert1() throws CertificateException {     byte[] certBytes = Base64.decode(cert1B64);     CertificateFactory cf = CertificateFactory.getInstance("X509");     ByteArrayInputStream inStream = new ByteArrayInputStream(certBytes);     return (X509Certificate) cf.generateCertificate(inStream);   }   public static RSAPrivateKey getXmldapPrivateKey1()       throws InvalidKeySpecException, NoSuchAlgorithmException {     byte[] modulusBytes = { (byte) 0x00, (byte) 0xe2, (byte) 0x94,         (byte) 0x9f, (byte) 0xaf, (byte) 0xd0, (byte) 0xa9,         (byte) 0x36, (byte) 0x63, (byte) 0xfc, (byte) 0x15,         (byte) 0xa8, (byte) 0x41, (byte) 0x5c, (byte) 0x4d,         (byte) 0x14, (byte) 0x8d, (byte) 0x19, (byte) 0xd8,         (byte) 0x05, (byte) 0xc8, (byte) 0xd5, (byte) 0xac,         (byte) 0xf0, (byte) 0xb3, (byte) 0xe4, (byte) 0x72,         (byte) 0xb8, (byte) 0x97, (byte) 0xa4, (byte) 0xeb,         (byte) 0x43, (byte) 0x62, (byte) 0x6b, (byte) 0x04,         (byte) 0x2b, (byte) 0x14, (byte) 0x02, (byte) 0xa4,         (byte) 0xd0, (byte) 0xf8, (byte) 0x7e, (byte) 0xfd,         (byte) 0x89, (byte) 0xd4, (byte) 0x89, (byte) 0x00,         (byte) 0x27, (byte) 0xcd, (byte) 0xbb, (byte) 0x13,         (byte) 0xfa, (byte) 0x3b, (byte) 0x99, (byte) 0x57,         (byte) 0x4f, (byte) 0x14, (byte) 0xa5, (byte) 0xa3,         (byte) 0xda, (byte) 0xd8, (byte) 0x81, (byte) 0x37,         (byte) 0x83, (byte) 0x4f, (byte) 0x91, (byte) 0x15,         (byte) 0x9b, (byte) 0x4e, (byte) 0x0e, (byte) 0x5a,         (byte) 0xa8, (byte) 0x18, (byte) 0x61, (byte) 0x9a,         (byte) 0x91, (byte) 0x23, (byte) 0x9d, (byte) 0xf4,         (byte) 0xd3, (byte) 0x67, (byte) 0x0e, (byte) 0xe3,         (byte) 0x61, (byte) 0xb1, (byte) 0xdb, (byte) 0x57,         (byte) 0x25, (byte) 0x68, (byte) 0x10, (byte) 0xab,         (byte) 0xca, (byte) 0x5a, (byte) 0x33, (byte) 0xd4,         (byte) 0x9c, (byte) 0xe2, (byte) 0x75, (byte) 0x2e,         (byte) 0x7b, (byte) 0x7d, (byte) 0x62, (byte) 0xab,         (byte) 0xb2, (byte) 0xef, (byte) 0x9a, (byte) 0x34,         (byte) 0x86, (byte) 0x48, (byte) 0xbe, (byte) 0x70,         (byte) 0xf3, (byte) 0x83, (byte) 0x60, (byte) 0x95,         (byte) 0x3e, (byte) 0x3c, (byte) 0x01, (byte) 0xca,         (byte) 0x95, (byte) 0x1a, (byte) 0xbf, (byte) 0xbf,         (byte) 0xe6, (byte) 0xfc, (byte) 0xbc, (byte) 0x09,         (byte) 0xf4, (byte) 0xff };     byte[] exponentBytes = { (byte) 0x1d, (byte) 0xe6, (byte) 0xf1,         (byte) 0x60, (byte) 0x19, (byte) 0x90, (byte) 0x8b,         (byte) 0x4e, (byte) 0x0c, (byte) 0xb1, (byte) 0xaa,         (byte) 0xff, (byte) 0xdd, (byte) 0x37, (byte) 0x8a,         (byte) 0xf3, (byte) 0xc8, (byte) 0x2a, (byte) 0x5b,         (byte) 0x31, (byte) 0x13, (byte) 0x09, (byte) 0xfc,         (byte) 0xc6, (byte) 0x30, (byte) 0xea, (byte) 0xf6,         (byte) 0xf3, (byte) 0x84, (byte) 0x5f, (byte) 0x4c,         (byte) 0x08, (byte) 0x4c, (byte) 0x09, (byte) 0x43,         (byte) 0xca, (byte) 0x23, (byte) 0x43, (byte) 0x2f,         (byte) 0x14, (byte) 0xec, (byte) 0x65, (byte) 0x77,         (byte) 0x70, (byte) 0x26, (byte) 0x18, (byte) 0x70,         (byte) 0x28, (byte) 0x55, (byte) 0x7d, (byte) 0x20,         (byte) 0x74, (byte) 0x07, (byte) 0x1b, (byte) 0x9f,         (byte) 0xa3, (byte) 0x20, (byte) 0xed, (byte) 0x0b,         (byte) 0xef, (byte) 0xb0, (byte) 0xb5, (byte) 0xeb,         (byte) 0xcd, (byte) 0x2f, (byte) 0xcd, (byte) 0x4d,         (byte) 0xde, (byte) 0x37, (byte) 0xe5, (byte) 0x86,         (byte) 0x55, (byte) 0xf2, (byte) 0x34, (byte) 0xe7,         (byte) 0xd9, (byte) 0xf7, (byte) 0xb3, (byte) 0x45,         (byte) 0x2a, (byte) 0x92, (byte) 0x1b, (byte) 0x54,         (byte) 0x49, (byte) 0x41, (byte) 0x81, (byte) 0xbd,         (byte) 0xc0, (byte) 0x63, (byte) 0xd1, (byte) 0x86,         (byte) 0x45, (byte) 0xe7, (byte) 0xe3, (byte) 0xb3,         (byte) 0xf5, (byte) 0x77, (byte) 0x5f, (byte) 0x46,         (byte) 0x93, (byte) 0x20, (byte) 0x19, (byte) 0x9a,         (byte) 0x26, (byte) 0x9f, (byte) 0x48, (byte) 0x27,         (byte) 0x4b, (byte) 0x93, (byte) 0xa7, (byte) 0x1c,         (byte) 0xf2, (byte) 0x8a, (byte) 0x3b, (byte) 0xbe,         (byte) 0x40, (byte) 0x85, (byte) 0x92, (byte) 0x8a,         (byte) 0x3c, (byte) 0xfd, (byte) 0xeb, (byte) 0x18,         (byte) 0x2e, (byte) 0x04, (byte) 0x69, (byte) 0xe5, (byte) 0xa1 };     BigInteger exponent = new BigInteger(1, exponentBytes);     BigInteger modulus = new BigInteger(1, modulusBytes);     RSAPrivateKeySpec ks = new RSAPrivateKeySpec(modulus, exponent);     KeyFactory kf = KeyFactory.getInstance("RSA");     return (RSAPrivateKey) kf.generatePrivate(ks);   } } /*  * JBoss, Home of Professional Open Source Copyright 2005, JBoss Inc., and  * individual contributors as indicated by the @authors tag. See the  * copyright.txt in the distribution for a full listing of individual  * contributors.  *   * This is free software; you can redistribute it and/or modify it under the  * terms of the GNU Lesser General Public License as published by the Free  * Software Foundation; either version 2.1 of the License, or (at your option)  * any later version.  *   * This software is distributed in the hope that it will be useful, but WITHOUT  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS  * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more  * details.  *   * You should have received a copy of the GNU Lesser General Public License  * along with this software; if not, write to the Free Software Foundation,  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA, or see the FSF  * site: http://www.fsf.org.  */ /**  * Encodes and decodes to and from Base64 notation.  *   * <p>  * Change Log:  * </p>  * <ul>  * <li>v2.1 - Cleaned up javadoc comments and unused variables and methods.  * Added some convenience methods for reading and writing to and from files.</li>  * <li>v2.0.2 - Now specifies UTF-8 encoding in places where the code fails on  * systems with other encodings (like EBCDIC).</li>  * <li>v2.0.1 - Fixed an error when decoding a single byte, that is, when the  * encoded data was a single byte.</li>  * <li>v2.0 - I got rid of methods that used booleans to set options. Now  * everything is more consolidated and cleaner. The code now detects when data  * that's being decoded is gzip-compressed and will decompress it automatically.  * Generally things are cleaner. You'll probably have to change some method  * calls that you were making to support the new options format (<tt>int</tt>s  * that you "OR" together).</li>  * <li>v1.5.1 - Fixed bug when decompressing and decoding to a byte[] using  * <tt>decode( String s, boolean gzipCompressed )</tt>. Added the ability to  * "suspend" encoding in the Output Stream so you can turn on and off the  * encoding if you need to embed base64 data in an otherwise "normal" stream  * (like an XML file).</li>  * <li>v1.5 - Output stream pases on flush() command but doesn't do anything  * itself. This helps when using GZIP streams. Added the ability to  * GZip-compress objects before encoding them.</li>  * <li>v1.4 - Added helper methods to read/write files.</li>  * <li>v1.3.6 - Fixed OutputStream.flush() so that 'position' is reset.</li>  * <li>v1.3.5 - Added flag to turn on and off line breaks. Fixed bug in input  * stream where last buffer being read, if not completely full, was not  * returned.</li>  * <li>v1.3.4 - Fixed when "improperly padded stream" error was thrown at the  * wrong time.</li>  * <li>v1.3.3 - Fixed I/O streams which were totally messed up.</li>  * </ul>  *   * <p>  * I am placing this code in the Public Domain. Do with it as you will. This  * software comes with no guarantees or warranties but with plenty of  * well-wishing instead! Please visit <a  * href="http://iharder.net/base64">http://iharder.net/base64</a> periodically  * to check for updates or to contribute improvements.  * </p>  *   * @author Robert Harder  * @author rob@iharder.net  * @version 2.1  */ class Base64 {   // provide logging   /* ******** P U B L I C F I E L D S ******** */   /** No options specified. Value is zero. */   public final static int NO_OPTIONS = 0;   /** Specify encoding. */   public final static int ENCODE = 1;   /** Specify decoding. */   public final static int DECODE = 0;   /** Specify that data should be gzip-compressed. */   public final static int GZIP = 2;   /** Don't break lines when encoding (violates strict Base64 specification) */   public final static int DONT_BREAK_LINES = 8;   /* ******** P R I V A T E F I E L D S ******** */   /** Maximum line length (76) of Base64 output. */   private final static int MAX_LINE_LENGTH = 76;   /** The equals sign (=) as a byte. */   private final static byte EQUALS_SIGN = (byte) '=';   /** The new line character (\n) as a byte. */   private final static byte NEW_LINE = (byte) '\n';   /** Preferred encoding. */   private final static String PREFERRED_ENCODING = "UTF-8";   /** The 64 valid Base64 values. */   private final static byte[] ALPHABET;   private final static byte[] _NATIVE_ALPHABET = /*                            * May be something funny                            * like EBCDIC                            */   { (byte) 'A', (byte) 'B', (byte) 'C', (byte) 'D', (byte) 'E', (byte) 'F',       (byte) 'G', (byte) 'H', (byte) 'I', (byte) 'J', (byte) 'K',       (byte) 'L', (byte) 'M', (byte) 'N', (byte) 'O', (byte) 'P',       (byte) 'Q', (byte) 'R', (byte) 'S', (byte) 'T', (byte) 'U',       (byte) 'V', (byte) 'W', (byte) 'X', (byte) 'Y', (byte) 'Z',       (byte) 'a', (byte) 'b', (byte) 'c', (byte) 'd', (byte) 'e',       (byte) 'f', (byte) 'g', (byte) 'h', (byte) 'i', (byte) 'j',       (byte) 'k', (byte) 'l', (byte) 'm', (byte) 'n', (byte) 'o',       (byte) 'p', (byte) 'q', (byte) 'r', (byte) 's', (byte) 't',       (byte) 'u', (byte) 'v', (byte) 'w', (byte) 'x', (byte) 'y',       (byte) 'z', (byte) '0', (byte) '1', (byte) '2', (byte) '3',       (byte) '4', (byte) '5', (byte) '6', (byte) '7', (byte) '8',       (byte) '9', (byte) '+', (byte) '/' };   /** Determine which ALPHABET to use. */   static {     byte[] __bytes;     try {       __bytes = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"           .getBytes(PREFERRED_ENCODING);     } // end try     catch (java.io.UnsupportedEncodingException use) {       __bytes = _NATIVE_ALPHABET; // Fall back to native encoding     } // end catch     ALPHABET = __bytes;   } // end static   /**    * Translates a Base64 value to either its 6-bit reconstruction value or a    * negative number indicating some other meaning.    **/   private final static byte[] DECODABET = { -9, -9, -9, -9, -9, -9, -9, -9,       -9, // Decimal 0 - 8       -5, -5, // Whitespace: Tab and Linefeed       -9, -9, // Decimal 11 - 12       -5, // Whitespace: Carriage Return       -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 14 -                                 // 26       -9, -9, -9, -9, -9, // Decimal 27 - 31       -5, // Whitespace: Space       -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 33 - 42       62, // Plus sign at decimal 43       -9, -9, -9, // Decimal 44 - 46       63, // Slash at decimal 47       52, 53, 54, 55, 56, 57, 58, 59, 60, 61, // Numbers zero through nine       -9, -9, -9, // Decimal 58 - 60       -1, // Equals sign at decimal 61       -9, -9, -9, // Decimal 62 - 64       0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, // Letters 'A' through                               // 'N'       14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, // Letters 'O'                               // through 'Z'       -9, -9, -9, -9, -9, -9, // Decimal 91 - 96       26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, // Letters 'a'                                 // through 'm'       39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, // Letters 'n'                                 // through 'z'       -9, -9, -9, -9 // Decimal 123 - 126   /*    * ,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 127 - 139    * -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 140 - 152    * -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 153 - 165    * -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 166 - 178    * -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 179 - 191    * -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 192 - 204    * -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 205 - 217    * -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 218 - 230    * -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 231 - 243    * -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9 // Decimal 244 - 255    */   };   // I think I end up not using the BAD_ENCODING indicator.   // private final static byte BAD_ENCODING = -9; // Indicates error in   // encoding   private final static byte WHITE_SPACE_ENC = -5; // Indicates white space in                           // encoding   private final static byte EQUALS_SIGN_ENC = -1; // Indicates equals sign in                           // encoding   /** Defeats instantiation. */   private Base64() {   }   /* ******** E N C O D I N G M E T H O D S ******** */   /**    * Encodes up to the first three bytes of array <var>threeBytes</var> and    * returns a four-byte array in Base64 notation. The actual number of    * significant bytes in your array is given by <var>numSigBytes</var>. The    * array <var>threeBytes</var> needs only be as big as    * <var>numSigBytes</var>. Code can reuse a byte array by passing a    * four-byte array as <var>b4</var>.    *     * @param b4    *            A reusable byte array to reduce array instantiation    * @param threeBytes    *            the array to convert    * @param numSigBytes    *            the number of significant bytes in your array    * @return four byte array in Base64 notation.    * @since 1.5.1    */   private static byte[] encode3to4(byte[] b4, byte[] threeBytes,       int numSigBytes) {     encode3to4(threeBytes, 0, numSigBytes, b4, 0);     return b4;   } // end encode3to4   /**    * Encodes up to three bytes of the array <var>source</var> and writes the    * resulting four Base64 bytes to <var>destination</var>. The source and    * destination arrays can be manipulated anywhere along their length by    * specifying <var>srcOffset</var> and <var>destOffset</var>. This method    * does not check to make sure your arrays are large enough to accomodate    * <var>srcOffset</var> + 3 for the <var>source</var> array or    * <var>destOffset</var> + 4 for the <var>destination</var> array. The    * actual number of significant bytes in your array is given by    * <var>numSigBytes</var>.    *     * @param source    *            the array to convert    * @param srcOffset    *            the index where conversion begins    * @param numSigBytes    *            the number of significant bytes in your array    * @param destination    *            the array to hold the conversion    * @param destOffset    *            the index where output will be put    * @return the <var>destination</var> array    * @since 1.3    */   private static byte[] encode3to4(byte[] source, int srcOffset,       int numSigBytes, byte[] destination, int destOffset) {     // 1 2 3     // 01234567890123456789012345678901 Bit position     // --------000000001111111122222222 Array position from threeBytes     // --------| || || || | Six bit groups to index ALPHABET     // >>18 >>12 >> 6 >> 0 Right shift necessary     // 0x3f 0x3f 0x3f Additional AND     // Create buffer with zero-padding if there are only one or two     // significant bytes passed in the array.     // We have to shift left 24 in order to flush out the 1's that appear     // when Java treats a value as negative that is cast from a byte to an     // int.     int inBuff = (numSigBytes > 0 ? ((source[srcOffset] << 24) >>> 8) : 0)         | (numSigBytes > 1 ? ((source[srcOffset + 1] << 24) >>> 16) : 0)         | (numSigBytes > 2 ? ((source[srcOffset + 2] << 24) >>> 24) : 0);     switch (numSigBytes) {     case 3:       destination[destOffset] = ALPHABET[(inBuff >>> 18)];       destination[destOffset + 1] = ALPHABET[(inBuff >>> 12) & 0x3f];       destination[destOffset + 2] = ALPHABET[(inBuff >>> 6) & 0x3f];       destination[destOffset + 3] = ALPHABET[(inBuff) & 0x3f];       return destination;     case 2:       destination[destOffset] = ALPHABET[(inBuff >>> 18)];       destination[destOffset + 1] = ALPHABET[(inBuff >>> 12) & 0x3f];       destination[destOffset + 2] = ALPHABET[(inBuff >>> 6) & 0x3f];       destination[destOffset + 3] = EQUALS_SIGN;       return destination;     case 1:       destination[destOffset] = ALPHABET[(inBuff >>> 18)];       destination[destOffset + 1] = ALPHABET[(inBuff >>> 12) & 0x3f];       destination[destOffset + 2] = EQUALS_SIGN;       destination[destOffset + 3] = EQUALS_SIGN;       return destination;     default:       return destination;     } // end switch   } // end encode3to4   /**    * Serializes an object and returns the Base64-encoded version of that    * serialized object. If the object cannot be serialized or there is another    * error, the method will return <tt>null</tt>. The object is not    * GZip-compressed before being encoded.    *     * @param serializableObject    *            The object to encode    * @return The Base64-encoded object    * @since 1.4    */   public static String encodeObject(java.io.Serializable serializableObject) {     return encodeObject(serializableObject, NO_OPTIONS);   } // end encodeObject   /**    * Serializes an object and returns the Base64-encoded version of that    * serialized object. If the object cannot be serialized or there is another    * error, the method will return <tt>null</tt>.    * <p>    * Valid options:    *     * <pre>    *   GZIP: gzip-compresses object before encoding it.    *   DONT_BREAK_LINES: don't break lines at 76 characters    *     <i>Note: Technically, this makes your encoding non-compliant.</i>    * </pre>    * <p>    * Example: <code>encodeObject( myObj, Base64.GZIP )</code> or    * <p>    * Example:    * <code>encodeObject( myObj, Base64.GZIP | Base64.DONT_BREAK_LINES )</code>    *     * @param serializableObject    *            The object to encode    * @param options    *            Specified options    * @return The Base64-encoded object    * @see Base64#GZIP    * @see Base64#DONT_BREAK_LINES    * @since 2.0    */   public static String encodeObject(java.io.Serializable serializableObject,       int options) {     // Streams     java.io.ByteArrayOutputStream baos = null;     java.io.OutputStream b64os = null;     java.io.ObjectOutputStream oos = null;     java.util.zip.GZIPOutputStream gzos = null;     // Isolate options     int gzip = (options & GZIP);     int dontBreakLines = (options & DONT_BREAK_LINES);     try {       // ObjectOutputStream -> (GZIP) -> Base64 -> ByteArrayOutputStream       baos = new java.io.ByteArrayOutputStream();       b64os = new Base64.OutputStream(baos, ENCODE | dontBreakLines);       // GZip?       if (gzip == GZIP) {         gzos = new java.util.zip.GZIPOutputStream(b64os);         oos = new java.io.ObjectOutputStream(gzos);       } // end if: gzip       else         oos = new java.io.ObjectOutputStream(b64os);       oos.writeObject(serializableObject);     } // end try     catch (java.io.IOException e) {       e.printStackTrace();       return null;     } // end catch     finally {       try {         oos.close();       } catch (Exception e) {       }       try {         gzos.close();       } catch (Exception e) {       }       try {         b64os.close();       } catch (Exception e) {       }       try {         baos.close();       } catch (Exception e) {       }     } // end finally     // Return value according to relevant encoding.     try {       return new String(baos.toByteArray(), PREFERRED_ENCODING);     } // end try     catch (java.io.UnsupportedEncodingException uue) {       return new String(baos.toByteArray());     } // end catch   } // end encode   /**    * Encodes a byte array into Base64 notation. Does not GZip-compress data.    *     * @param source    *            The data to convert    * @return the encode bytes    * @since 1.4    */   public static String encodeBytes(byte[] source) {     return encodeBytes(source, 0, source.length, NO_OPTIONS);   } // end encodeBytes   /**    * Encodes a byte array into Base64 notation.    * <p>    * Valid options:    *     * <pre>    *   GZIP: gzip-compresses object before encoding it.    *   DONT_BREAK_LINES: don't break lines at 76 characters    *     <i>Note: Technically, this makes your encoding non-compliant.</i>    * </pre>    * <p>    * Example: <code>encodeBytes( myData, Base64.GZIP )</code> or    * <p>    * Example:    * <code>encodeBytes( myData, Base64.GZIP | Base64.DONT_BREAK_LINES )</code>    *     *     * @param source    *            The data to convert    * @param options    *            Specified options    * @return the encoded bytes    * @see Base64#GZIP    * @see Base64#DONT_BREAK_LINES    * @since 2.0    */   public static String encodeBytes(byte[] source, int options) {     return encodeBytes(source, 0, source.length, options);   } // end encodeBytes   /**    * Encodes a byte array into Base64 notation. Does not GZip-compress data.    *     * @param source    *            The data to convert    * @param off    *            Offset in array where conversion should begin    * @param len    *            Length of data to convert    * @return the text node    * @since 1.4    */   public static String encodeBytes(byte[] source, int off, int len) {     return encodeBytes(source, off, len, NO_OPTIONS);   } // end encodeBytes   /**    * Encodes a byte array into Base64 notation.    * <p>    * Valid options:    *     * <pre>    *   GZIP: gzip-compresses object before encoding it.    *   DONT_BREAK_LINES: don't break lines at 76 characters    *     <i>Note: Technically, this makes your encoding non-compliant.</i>    * </pre>    * <p>    * Example: <code>encodeBytes( myData, Base64.GZIP )</code> or    * <p>    * Example:    * <code>encodeBytes( myData, Base64.GZIP | Base64.DONT_BREAK_LINES )</code>    *     *     * @param source    *            The data to convert    * @param off    *            Offset in array where conversion should begin    * @param len    *            Length of data to convert    * @param options    *            Specified options    * @see Base64#GZIP    * @see Base64#DONT_BREAK_LINES    * @return the text node    * @since 2.0    */   public static String encodeBytes(byte[] source, int off, int len,       int options) {     // Isolate options     int dontBreakLines = (options & DONT_BREAK_LINES);     int gzip = (options & GZIP);     // Compress?     if (gzip == GZIP) {       java.io.ByteArrayOutputStream baos = null;       java.util.zip.GZIPOutputStream gzos = null;       Base64.OutputStream b64os = null;       try {         // GZip -> Base64 -> ByteArray         baos = new java.io.ByteArrayOutputStream();         b64os = new Base64.OutputStream(baos, ENCODE | dontBreakLines);         gzos = new java.util.zip.GZIPOutputStream(b64os);         gzos.write(source, off, len);         gzos.close();       } // end try       catch (java.io.IOException e) {         e.printStackTrace();         return null;       } // end catch       finally {         try {           gzos.close();         } catch (Exception e) {         }         try {           b64os.close();         } catch (Exception e) {         }         try {           baos.close();         } catch (Exception e) {         }       } // end finally       // Return value according to relevant encoding.       try {         return new String(baos.toByteArray(), PREFERRED_ENCODING);       } // end try       catch (java.io.UnsupportedEncodingException uue) {         return new String(baos.toByteArray());       } // end catch     } // end if: compress     // Else, don't compress. Better not to use streams at all then.     else {       // Convert option to boolean in way that code likes it.       boolean breakLines = dontBreakLines == 0;       int len43 = len * 4 / 3;       byte[] outBuff = new byte[(len43) // Main 4:3           + ((len % 3) > 0 ? 4 : 0) // Account for padding           + (breakLines ? (len43 / MAX_LINE_LENGTH) : 0)]; // New                                     // lines       int d = 0;       int e = 0;       int len2 = len - 2;       int lineLength = 0;       for (; d < len2; d += 3, e += 4) {         encode3to4(source, d + off, 3, outBuff, e);         lineLength += 4;         if (breakLines && lineLength == MAX_LINE_LENGTH) {           outBuff[e + 4] = NEW_LINE;           e++;           lineLength = 0;         } // end if: end of line       } // en dfor: each piece of array       if (d < len) {         encode3to4(source, d + off, len - d, outBuff, e);         e += 4;       } // end if: some padding needed       // Return value according to relevant encoding.       try {         return new String(outBuff, 0, e, PREFERRED_ENCODING);       } // end try       catch (java.io.UnsupportedEncodingException uue) {         return new String(outBuff, 0, e);       } // end catch     } // end else: don't compress   } // end encodeBytes   /* ******** D E C O D I N G M E T H O D S ******** */   /**    * Decodes four bytes from array <var>source</var> and writes the resulting    * bytes (up to three of them) to <var>destination</var>. The source and    * destination arrays can be manipulated anywhere along their length by    * specifying <var>srcOffset</var> and <var>destOffset</var>. This method    * does not check to make sure your arrays are large enough to accomodate    * <var>srcOffset</var> + 4 for the <var>source</var> array or    * <var>destOffset</var> + 3 for the <var>destination</var> array. This    * method returns the actual number of bytes that were converted from the    * Base64 encoding.    *     *     * @param source    *            the array to convert    * @param srcOffset    *            the index where conversion begins    * @param destination    *            the array to hold the conversion    * @param destOffset    *            the index where output will be put    * @return the number of decoded bytes converted    * @since 1.3    */   private static int decode4to3(byte[] source, int srcOffset,       byte[] destination, int destOffset) {     // Example: Dk==     if (source[srcOffset + 2] == EQUALS_SIGN) {       // Two ways to do the same thing. Don't know which way I like best.       // int outBuff = ( ( DECODABET[ source[ srcOffset ] ] << 24 ) >>> 6       // )       // | ( ( DECODABET[ source[ srcOffset + 1] ] << 24 ) >>> 12 );       int outBuff = ((DECODABET[source[srcOffset]] & 0xFF) << 18)           | ((DECODABET[source[srcOffset + 1]] & 0xFF) << 12);       destination[destOffset] = (byte) (outBuff >>> 16);       return 1;     }     // Example: DkL=     else if (source[srcOffset + 3] == EQUALS_SIGN) {       // Two ways to do the same thing. Don't know which way I like best.       // int outBuff = ( ( DECODABET[ source[ srcOffset ] ] << 24 ) >>> 6       // )       // | ( ( DECODABET[ source[ srcOffset + 1 ] ] << 24 ) >>> 12 )       // | ( ( DECODABET[ source[ srcOffset + 2 ] ] << 24 ) >>> 18 );       int outBuff = ((DECODABET[source[srcOffset]] & 0xFF) << 18)           | ((DECODABET[source[srcOffset + 1]] & 0xFF) << 12)           | ((DECODABET[source[srcOffset + 2]] & 0xFF) << 6);       destination[destOffset] = (byte) (outBuff >>> 16);       destination[destOffset + 1] = (byte) (outBuff >>> 8);       return 2;     }     // Example: DkLE     else {       try {         // Two ways to do the same thing. Don't know which way I like         // best.         // int outBuff = ( ( DECODABET[ source[ srcOffset ] ] << 24 )         // >>> 6 )         // | ( ( DECODABET[ source[ srcOffset + 1 ] ] << 24 ) >>> 12 )         // | ( ( DECODABET[ source[ srcOffset + 2 ] ] << 24 ) >>> 18 )         // | ( ( DECODABET[ source[ srcOffset + 3 ] ] << 24 ) >>> 24 );         int outBuff = ((DECODABET[source[srcOffset]] & 0xFF) << 18)             | ((DECODABET[source[srcOffset + 1]] & 0xFF) << 12)             | ((DECODABET[source[srcOffset + 2]] & 0xFF) << 6)             | ((DECODABET[source[srcOffset + 3]] & 0xFF));         destination[destOffset] = (byte) (outBuff >> 16);         destination[destOffset + 1] = (byte) (outBuff >> 8);         destination[destOffset + 2] = (byte) (outBuff);         return 3;       } catch (Exception e) {         System.out.println("" + source[srcOffset] + ": "             + (DECODABET[source[srcOffset]]));         System.out.println("" + source[srcOffset + 1] + ": "             + (DECODABET[source[srcOffset + 1]]));         System.out.println("" + source[srcOffset + 2] + ": "             + (DECODABET[source[srcOffset + 2]]));         System.out.println("" + source[srcOffset + 3] + ": "             + (DECODABET[source[srcOffset + 3]]));         return -1;       } // end catch     }   } // end decodeToBytes   /**    * Very low-level access to decoding ASCII characters in the form of a byte    * array. Does not support automatically gunzipping or any other "fancy"    * features.    *     * @param source    *            The Base64 encoded data    * @param off    *            The offset of where to begin decoding    * @param len    *            The length of characters to decode    * @return decoded data    * @since 1.3    */   public static byte[] decode(byte[] source, int off, int len) {     int len34 = len * 3 / 4;     byte[] outBuff = new byte[len34]; // Upper limit on size of output     int outBuffPosn = 0;     byte[] b4 = new byte[4];     int b4Posn = 0;     int i = 0;     byte sbiCrop = 0;     byte sbiDecode = 0;     for (i = off; i < off + len; i++) {       sbiCrop = (byte) (source[i] & 0x7f); // Only the low seven bits       sbiDecode = DECODABET[sbiCrop];       if (sbiDecode >= WHITE_SPACE_ENC) // White space, Equals sign or                         // better       {         if (sbiDecode >= EQUALS_SIGN_ENC) {           b4[b4Posn++] = sbiCrop;           if (b4Posn > 3) {             outBuffPosn += decode4to3(b4, 0, outBuff, outBuffPosn);             b4Posn = 0;             // If that was the equals sign, break out of 'for' loop             if (sbiCrop == EQUALS_SIGN)               break;           } // end if: quartet built         } // end if: equals sign or better       } // end if: white space, equals sign or better       else {         throw new IllegalStateException(             "Bad Base64 input character at " + i + ": " + source[i]                 + "(decimal)");       } // end else:     } // each input character     byte[] out = new byte[outBuffPosn];     System.arraycopy(outBuff, 0, out, 0, outBuffPosn);     return out;   } // end decode   /**    * Decodes data from Base64 notation, automatically detecting    * gzip-compressed data and decompressing it.    *     * @param s    *            the string to decode    * @return the decoded data    * @since 1.4    */   public static byte[] decode(String s) {     byte[] bytes;     try {       bytes = s.getBytes(PREFERRED_ENCODING);     } // end try     catch (java.io.UnsupportedEncodingException uee) {       bytes = s.getBytes();     } // end catch       // </change>     // Decode     bytes = decode(bytes, 0, bytes.length);     // Check to see if it's gzip-compressed     // GZIP Magic Two-Byte Number: 0x8b1f (35615)     if (bytes != null && bytes.length >= 4) {       int head = (bytes[0] & 0xff) | ((bytes[1] << 8) & 0xff00);       if (java.util.zip.GZIPInputStream.GZIP_MAGIC == head) {         java.io.ByteArrayInputStream bais = null;         java.util.zip.GZIPInputStream gzis = null;         java.io.ByteArrayOutputStream baos = null;         byte[] buffer = new byte[2048];         int length = 0;         try {           baos = new java.io.ByteArrayOutputStream();           bais = new java.io.ByteArrayInputStream(bytes);           gzis = new java.util.zip.GZIPInputStream(bais);           while ((length = gzis.read(buffer)) >= 0) {             baos.write(buffer, 0, length);           } // end while: reading input           // No error? Get new bytes.           bytes = baos.toByteArray();         } // end try         catch (java.io.IOException e) {           // Just return originally-decoded bytes         } // end catch         finally {           try {             baos.close();           } catch (Exception e) {           }           try {             gzis.close();           } catch (Exception e) {           }           try {             bais.close();           } catch (Exception e) {           }         } // end finally       } // end if: gzipped     } // end if: bytes.length >= 2     return bytes;   } // end decode   /**    * Attempts to decode Base64 data and deserialize a Java Object within.    * Returns <tt>null</tt> if there was an error.    *     * @param encodedObject    *            The Base64 data to decode    * @return The decoded and deserialized object    * @since 1.5    */   public static Object decodeToObject(String encodedObject) {     // Decode and gunzip if necessary     byte[] objBytes = decode(encodedObject);     java.io.ByteArrayInputStream bais = null;     java.io.ObjectInputStream ois = null;     Object obj = null;     try {       bais = new java.io.ByteArrayInputStream(objBytes);       ois = new java.io.ObjectInputStream(bais);       obj = ois.readObject();     } // end try     catch (java.io.IOException e) {       e.printStackTrace();       obj = null;     } // end catch     catch (java.lang.ClassNotFoundException e) {       e.printStackTrace();       obj = null;     } // end catch     finally {       try {         bais.close();       } catch (Exception e) {       }       try {         ois.close();       } catch (Exception e) {       }     } // end finally     return obj;   } // end decodeObject   /**    * Convenience method for encoding data to a file.    *     * @param dataToEncode    *            byte array of data to encode in base64 form    * @param filename    *            Filename for saving encoded data    * @return <tt>true</tt> if successful, <tt>false</tt> otherwise    *     * @since 2.1    */   public static boolean encodeToFile(byte[] dataToEncode, String filename) {     boolean success = false;     Base64.OutputStream bos = null;     try {       bos = new Base64.OutputStream(           new java.io.FileOutputStream(filename), Base64.ENCODE);       bos.write(dataToEncode);       success = true;     } // end try     catch (java.io.IOException e) {       success = false;     } // end catch: IOException     finally {       try {         bos.close();       } catch (Exception e) {       }     } // end finally     return success;   } // end encodeToFile   /**    * Convenience method for decoding data to a file.    *     * @param dataToDecode    *            Base64-encoded data as a string    * @param filename    *            Filename for saving decoded data    * @return <tt>true</tt> if successful, <tt>false</tt> otherwise    *     * @since 2.1    */   public static boolean decodeToFile(String dataToDecode, String filename) {     boolean success = false;     Base64.OutputStream bos = null;     try {       bos = new Base64.OutputStream(           new java.io.FileOutputStream(filename), Base64.DECODE);       bos.write(dataToDecode.getBytes(PREFERRED_ENCODING));       success = true;     } // end try     catch (java.io.IOException e) {       success = false;     } // end catch: IOException     finally {       try {         bos.close();       } catch (Exception e) {       }     } // end finally     return success;   } // end decodeToFile   /**    * Convenience method for reading a base64-encoded file and decoding it.    *     * @param filename    *            Filename for reading encoded data    * @return decoded byte array or null if unsuccessful    *     * @since 2.1    */   public static byte[] decodeFromFile(String filename) {     byte[] decodedData = null;     Base64.InputStream bis = null;     try {       // Set up some useful variables       java.io.File file = new java.io.File(filename);       byte[] buffer = null;       int length = 0;       int numBytes = 0;       // Check for size of file       if (file.length() > Integer.MAX_VALUE) {         throw new IllegalStateException(             "File is too big for this convenience method ("                 + file.length() + " bytes).");       } // end if: file too big for int index       buffer = new byte[(int) file.length()];       // Open a stream       bis = new Base64.InputStream(new java.io.BufferedInputStream(           new java.io.FileInputStream(file)), Base64.DECODE);       // Read until done       while ((numBytes = bis.read(buffer, length, 4096)) >= 0)         length += numBytes;       // Save in a variable to return       decodedData = new byte[length];       System.arraycopy(buffer, 0, decodedData, 0, length);     } // end try     catch (java.io.IOException e) {       throw new IllegalStateException("Error decoding from file "           + filename);     } // end catch: IOException     finally {       try {         bis.close();       } catch (Exception e) {       }     } // end finally     return decodedData;   } // end decodeFromFile   /**    * Convenience method for reading a binary file and base64-encoding it.    *     * @param filename    *            Filename for reading binary data    * @return base64-encoded string or null if unsuccessful    *     * @since 2.1    */   public static String encodeFromFile(String filename) {     String encodedData = null;     Base64.InputStream bis = null;     try {       // Set up some useful variables       java.io.File file = new java.io.File(filename);       byte[] buffer = new byte[(int) (file.length() * 1.4)];       int length = 0;       int numBytes = 0;       // Open a stream       bis = new Base64.InputStream(new java.io.BufferedInputStream(           new java.io.FileInputStream(file)), Base64.ENCODE);       // Read until done       while ((numBytes = bis.read(buffer, length, 4096)) >= 0)         length += numBytes;       // Save in a variable to return       encodedData = new String(buffer, 0, length,           Base64.PREFERRED_ENCODING);     } // end try     catch (java.io.IOException e) {       throw new IllegalStateException("Error encoding from file "           + filename);     } // end catch: IOException     finally {       try {         bis.close();       } catch (Exception e) {       }     } // end finally     return encodedData;   } // end encodeFromFile   /* ******** I N N E R C L A S S I N P U T S T R E A M ******** */   /**    * A {@link Base64.InputStream} will read data from another    * <tt>java.io.InputStream</tt>, given in the constructor, and encode/decode    * to/from Base64 notation on the fly.    *     * @see Base64    * @since 1.3    */   public static class InputStream extends java.io.FilterInputStream {     private boolean encode; // Encoding or decoding     private int position; // Current position in the buffer     private byte[] buffer; // Small buffer holding converted data     private int bufferLength; // Length of buffer (3 or 4)     private int numSigBytes; // Number of meaningful bytes in the buffer     private int lineLength;     private boolean breakLines; // Break lines at less than 80 characters     /**      * Constructs a {@link Base64.InputStream} in DECODE mode.      *       * @param in      *            the <tt>java.io.InputStream</tt> from which to read data.      * @since 1.3      */     public InputStream(java.io.InputStream in) {       this(in, DECODE);     } // end constructor     /**      * Constructs a {@link Base64.InputStream} in either ENCODE or DECODE      * mode.      * <p>      * Valid options:      *       * <pre>      *   ENCODE or DECODE: Encode or Decode as data is read.      *   DONT_BREAK_LINES: don't break lines at 76 characters      *     (only meaningful when encoding)      *     <i>Note: Technically, this makes your encoding non-compliant.</i>      * </pre>      * <p>      * Example: <code>new Base64.InputStream( in, Base64.DECODE )</code>      *       *       * @param in      *            the <tt>java.io.InputStream</tt> from which to read data.      * @param options      *            Specified options      * @see Base64#ENCODE      * @see Base64#DECODE      * @see Base64#DONT_BREAK_LINES      * @since 2.0      */     public InputStream(java.io.InputStream in, int options) {       super(in);       this.breakLines = (options & DONT_BREAK_LINES) != DONT_BREAK_LINES;       this.encode = (options & ENCODE) == ENCODE;       this.bufferLength = encode ? 4 : 3;       this.buffer = new byte[bufferLength];       this.position = -1;       this.lineLength = 0;     } // end constructor     /**      * Reads enough of the input stream to convert to/from Base64 and      * returns the next byte.      *       * @return next byte      * @since 1.3      */     public int read() throws java.io.IOException {       // Do we need to get data?       if (position < 0) {         if (encode) {           byte[] b3 = new byte[3];           int numBinaryBytes = 0;           for (int i = 0; i < 3; i++) {             try {               int b = in.read();               // If end of stream, b is -1.               if (b >= 0) {                 b3[i] = (byte) b;                 numBinaryBytes++;               } // end if: not end of stream             } // end try: read             catch (java.io.IOException e) {               // Only a problem if we got no data at all.               if (i == 0)                 throw e;             } // end catch           } // end for: each needed input byte           if (numBinaryBytes > 0) {             encode3to4(b3, 0, numBinaryBytes, buffer, 0);             position = 0;             numSigBytes = 4;           } // end if: got data           else {             return -1;           } // end else         } // end if: encoding         // Else decoding         else {           byte[] b4 = new byte[4];           int i = 0;           for (i = 0; i < 4; i++) {             // Read four "meaningful" bytes:             int b = 0;             do {               b = in.read();             } while (b >= 0                 && DECODABET[b & 0x7f] <= WHITE_SPACE_ENC);             if (b < 0)               break; // Reads a -1 if end of stream             b4[i] = (byte) b;           } // end for: each needed input byte           if (i == 4) {             numSigBytes = decode4to3(b4, 0, buffer, 0);             position = 0;           } // end if: got four characters           else if (i == 0) {             return -1;           } // end else if: also padded correctly           else {             // Must have broken out from above.             throw new java.io.IOException(                 "Improperly padded Base64 input.");           } // end         } // end else: decode       } // end else: get data       // Got data?       if (position >= 0) {         // End of relevant data?         if (/* !encode && */position >= numSigBytes)           return -1;         if (encode && breakLines && lineLength >= MAX_LINE_LENGTH) {           lineLength = 0;           return '\n';         } // end if         else {           lineLength++; // This isn't important when decoding           // but throwing an extra "if" seems           // just as wasteful.           int b = buffer[position++];           if (position >= bufferLength)             position = -1;           return b & 0xFF; // This is how you "cast" a byte that's           // intended to be unsigned.         } // end else       } // end if: position >= 0       // Else error       else {         // When JDK1.4 is more accepted, use an assertion here.         throw new java.io.IOException(             "Error in Base64 code reading stream.");       } // end else     } // end read     /**      * Calls {@link #read()} repeatedly until the end of stream is reached      * or <var>len</var> bytes are read. Returns number of bytes read into      * array or -1 if end of stream is encountered.      *       * @param dest      *            array to hold values      * @param off      *            offset for array      * @param len      *            max number of bytes to read into array      * @return bytes read into array or -1 if end of stream is encountered.      * @since 1.3      */     public int read(byte[] dest, int off, int len)         throws java.io.IOException {       int i;       int b;       for (i = 0; i < len; i++) {         b = read();         // if( b < 0 && i == 0 )         // return -1;         if (b >= 0)           dest[off + i] = (byte) b;         else if (i == 0)           return -1;         else           break; // Out of 'for' loop       } // end for: each byte read       return i;     } // end read   } // end inner class InputStream   /* ******** I N N E R C L A S S O U T P U T S T R E A M ******** */   /**    * A {@link Base64.OutputStream} will write data to another    * <tt>java.io.OutputStream</tt>, given in the constructor, and    * encode/decode to/from Base64 notation on the fly.    *     * @see Base64    * @since 1.3    */   public static class OutputStream extends java.io.FilterOutputStream {     private boolean encode;     private int position;     private byte[] buffer;     private int bufferLength;     private int lineLength;     private boolean breakLines;     private byte[] b4; // Scratch used in a few places     private boolean suspendEncoding;     /**      * Constructs a {@link Base64.OutputStream} in ENCODE mode.      *       * @param out      *            the <tt>java.io.OutputStream</tt> to which data will be      *            written.      * @since 1.3      */     public OutputStream(java.io.OutputStream out) {       this(out, ENCODE);     } // end constructor     /**      * Constructs a {@link Base64.OutputStream} in either ENCODE or DECODE      * mode.      * <p>      * Valid options:      *       * <pre>      *   ENCODE or DECODE: Encode or Decode as data is read.      *   DONT_BREAK_LINES: don't break lines at 76 characters      *     (only meaningful when encoding)      *     <i>Note: Technically, this makes your encoding non-compliant.</i>      * </pre>      * <p>      * Example: <code>new Base64.OutputStream( out, Base64.ENCODE )</code>      *       * @param out      *            the <tt>java.io.OutputStream</tt> to which data will be      *            written.      * @param options      *            Specified options.      * @see Base64#ENCODE      * @see Base64#DECODE      * @see Base64#DONT_BREAK_LINES      * @since 1.3      */     public OutputStream(java.io.OutputStream out, int options) {       super(out);       this.breakLines = (options & DONT_BREAK_LINES) != DONT_BREAK_LINES;       this.encode = (options & ENCODE) == ENCODE;       this.bufferLength = encode ? 3 : 4;       this.buffer = new byte[bufferLength];       this.position = 0;       this.lineLength = 0;       this.suspendEncoding = false;       this.b4 = new byte[4];     } // end constructor     /**      * Writes the byte to the output stream after converting to/from Base64      * notation. When encoding, bytes are buffered three at a time before      * the output stream actually gets a write() call. When decoding, bytes      * are buffered four at a time.      *       * @param theByte      *            the byte to write      * @since 1.3      */     public void write(int theByte) throws java.io.IOException {       // Encoding suspended?       if (suspendEncoding) {         super.out.write(theByte);         return;       } // end if: supsended       // Encode?       if (encode) {         buffer[position++] = (byte) theByte;         if (position >= bufferLength) // Enough to encode.         {           out.write(encode3to4(b4, buffer, bufferLength));           lineLength += 4;           if (breakLines && lineLength >= MAX_LINE_LENGTH) {             out.write(NEW_LINE);             lineLength = 0;           } // end if: end of line           position = 0;         } // end if: enough to output       } // end if: encoding       // Else, Decoding       else {         // Meaningful Base64 character?         if (DECODABET[theByte & 0x7f] > WHITE_SPACE_ENC) {           buffer[position++] = (byte) theByte;           if (position >= bufferLength) // Enough to output.           {             int len = Base64.decode4to3(buffer, 0, b4, 0);             out.write(b4, 0, len);             // out.write( Base64.decode4to3( buffer ) );             position = 0;           } // end if: enough to output         } // end if: meaningful base64 character         else if (DECODABET[theByte & 0x7f] != WHITE_SPACE_ENC) {           throw new java.io.IOException(               "Invalid character in Base64 data.");         } // end else: not white space either       } // end else: decoding     } // end write     /**      * Calls {@link #write(int)} repeatedly until <var>len</var> bytes are      * written.      *       * @param theBytes      *            array from which to read bytes      * @param off      *            offset for array      * @param len      *            max number of bytes to read into array      * @since 1.3      */     public void write(byte[] theBytes, int off, int len)         throws java.io.IOException {       // Encoding suspended?       if (suspendEncoding) {         super.out.write(theBytes, off, len);         return;       } // end if: supsended       for (int i = 0; i < len; i++) {         write(theBytes[off + i]);       } // end for: each byte written     } // end write     /**      * Method added by PHIL. [Thanks, PHIL. -Rob] This pads the buffer      * without closing the stream.      *       * @throws IOException      */     public void flushBase64() throws java.io.IOException {       if (position > 0) {         if (encode) {           out.write(encode3to4(b4, buffer, position));           position = 0;         } // end if: encoding         else {           throw new java.io.IOException(               "Base64 input not properly padded.");         } // end else: decoding       } // end if: buffer partially full     } // end flush     /**      * Flushes and closes (I think, in the superclass) the stream.      *       * @since 1.3      */     public void close() throws java.io.IOException {       // 1. Ensure that pending characters are written       flushBase64();       // 2. Actually close the stream       // Base class both flushes and closes.       super.close();       buffer = null;       out = null;     } // end close     /**      * Suspends encoding of the stream. May be helpful if you need to embed      * a piece of base640-encoded data in a stream.      *       * @since 1.5.1      * @throws IOException      */     public void suspendEncoding() throws java.io.IOException {       flushBase64();       this.suspendEncoding = true;     } // end suspendEncoding     /**      * Resumes encoding of the stream. May be helpful if you need to embed a      * piece of base640-encoded data in a stream.      *       * @since 1.5.1      */     public void resumeEncoding() {       this.suspendEncoding = false;     } // end resumeEncoding   } // end inner class OutputStream } // end class Base64