/* 
 * Copyright © 2011 Rebecca G. Bettencourt / Kreative Software 
 * <p> 
 * The contents of this file are subject to the Mozilla Public License 
 * Version 1.1 (the "License"); you may not use this file except in 
 * compliance with the License. You may obtain a copy of the License at 
 * <a href="http://www.mozilla.org/MPL/">http://www.mozilla.org/MPL/</a> 
 * <p> 
 * Software distributed under the License is distributed on an "AS IS" 
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the 
 * License for the specific language governing rights and limitations 
 * under the License. 
 * <p> 
 * Alternatively, the contents of this file may be used under the terms 
 * of the GNU Lesser General Public License (the "LGPL License"), in which 
 * case the provisions of LGPL License are applicable instead of those 
 * above. If you wish to allow use of your version of this file only 
 * under the terms of the LGPL License and not to allow others to use 
 * your version of this file under the MPL, indicate your decision by 
 * deleting the provisions above and replace them with the notice and 
 * other provisions required by the LGPL License. If you do not delete 
 * the provisions above, a recipient may use your version of this file 
 * under either the MPL or the LGPL License. 
 * @since OpenXION 1.3 
 * @author Rebecca G. Bettencourt, Kreative Software 
 */ 
 
//package com.kreative.openxion.util; 
 
import java.io.ByteArrayOutputStream; 
import java.io.IOException; 
import java.text.CharacterIterator; 
import java.text.StringCharacterIterator; 
 
/** 
 * The Base64 utility class implements Base-64 and Base-85 encoding and decoding algorithms. 
 * @since OpenXION 1.3 
 * @author Rebecca G. Bettencourt, Kreative Software 
 */ 
public class Base64 { 
  private Base64() {} 
   
  private static final char[] b64e = { 
    'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P', 
    'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f', 
    'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v', 
    'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/', 
  }; 
   
  public static String encodeBase64(byte[] b, int off, int len) { 
    int i = 0; 
    StringBuffer s = new StringBuffer(); 
    while (len >= 3) { 
      i = ((b[off] & 0xFF) << 16) | ((b[off+1] & 0xFF) << 8) | (b[off+2] & 0xFF); 
      s.append(b64e[(i >> 18) & 0x3F]); 
      s.append(b64e[(i >> 12) & 0x3F]); 
      s.append(b64e[(i >> 6) & 0x3F]); 
      s.append(b64e[i & 0x3F]); 
      off += 3; 
      len -= 3; 
    } 
    switch (len) { 
    case 2: 
      i = ((b[off] & 0xFF) << 16) | ((b[off+1] & 0xFF) << 8); 
      s.append(b64e[(i >> 18) & 0x3F]); 
      s.append(b64e[(i >> 12) & 0x3F]); 
      s.append(b64e[(i >> 6) & 0x3F]); 
      s.append('='); 
      break; 
    case 1: 
      i = ((b[off] & 0xFF) << 16); 
      s.append(b64e[(i >> 18) & 0x3F]); 
      s.append(b64e[(i >> 12) & 0x3F]); 
      s.append('='); 
      s.append('='); 
      break; 
    } 
    return s.toString(); 
  } 
   
  public static String encodeBase64(byte[] b) { 
    return encodeBase64(b, 0, b.length); 
  } 
   
  private static int b64d(char i) { 
    switch (i) { 
    case 'A': return 0; case 'B': return 1; case 'C': return 2; case 'D': return 3; 
    case 'E': return 4; case 'F': return 5; case 'G': return 6; case 'H': return 7; 
    case 'I': return 8; case 'J': return 9; case 'K': return 10; case 'L': return 11; 
    case 'M': return 12; case 'N': return 13; case 'O': return 14; case 'P': return 15; 
    case 'Q': return 16; case 'R': return 17; case 'S': return 18; case 'T': return 19; 
    case 'U': return 20; case 'V': return 21; case 'W': return 22; case 'X': return 23; 
    case 'Y': return 24; case 'Z': return 25; case 'a': return 26; case 'b': return 27; 
    case 'c': return 28; case 'd': return 29; case 'e': return 30; case 'f': return 31; 
    case 'g': return 32; case 'h': return 33; case 'i': return 34; case 'j': return 35; 
    case 'k': return 36; case 'l': return 37; case 'm': return 38; case 'n': return 39; 
    case 'o': return 40; case 'p': return 41; case 'q': return 42; case 'r': return 43; 
    case 's': return 44; case 't': return 45; case 'u': return 46; case 'v': return 47; 
    case 'w': return 48; case 'x': return 49; case 'y': return 50; case 'z': return 51; 
    case '0': return 52; case '1': return 53; case '2': return 54; case '3': return 55; 
    case '4': return 56; case '5': return 57; case '6': return 58; case '7': return 59; 
    case '8': return 60; case '9': return 61; case '+': return 62; case '/': return 63; 
    default: return -1; 
    } 
  } 
   
  public static byte[] decodeBase64(String s) { 
    CharacterIterator it = new StringCharacterIterator(s.trim()); 
    ByteArrayOutputStream out = new ByteArrayOutputStream(); 
    int i = 0, j = 0; 
    for (char ch = it.first(); ch != CharacterIterator.DONE && ch != '='; ch = it.next()) { 
      int v = b64d(ch); 
      if (v >= 0) { 
        i = (i << 6) | v; 
        j++; 
        if (j >= 4) { 
          out.write(i >> 16); 
          out.write(i >> 8); 
          out.write(i); 
          i = 0; j = 0; 
        } 
      } 
    } 
    switch (j) { 
    case 3: 
      out.write(i >> 10); 
      out.write(i >> 2); 
      break; 
    case 2: 
      out.write(i >> 4); 
      break; 
    } 
    return out.toByteArray(); 
  } 
   
  public static String encodeUU(byte[] b, int off, int len) { 
    int i = 0; 
    StringBuffer s = new StringBuffer(); 
    while (len > 45) { 
      s.append('M'); 
      for (int j = 0; j < 45; j += 3) { 
        i = ((b[off] & 0xFF) << 16) | ((b[off+1] & 0xFF) << 8) | (b[off+2] & 0xFF); 
        s.append((char)(' '+((i >> 18) & 0x3F))); 
        s.append((char)(' '+((i >> 12) & 0x3F))); 
        s.append((char)(' '+((i >> 6) & 0x3F))); 
        s.append((char)(' '+(i & 0x3F))); 
        off += 3; 
        len -= 3; 
      } 
      s.append('\n'); 
    } 
    s.append((char)(' ' + len)); 
    while (len >= 3) { 
      i = ((b[off] & 0xFF) << 16) | ((b[off+1] & 0xFF) << 8) | (b[off+2] & 0xFF); 
      s.append((char)(' '+((i >> 18) & 0x3F))); 
      s.append((char)(' '+((i >> 12) & 0x3F))); 
      s.append((char)(' '+((i >> 6) & 0x3F))); 
      s.append((char)(' '+(i & 0x3F))); 
      off += 3; 
      len -= 3; 
    } 
    switch (len) { 
    case 2: 
      i = ((b[off] & 0xFF) << 16) | ((b[off+1] & 0xFF) << 8); 
      s.append((char)(' '+((i >> 18) & 0x3F))); 
      s.append((char)(' '+((i >> 12) & 0x3F))); 
      s.append((char)(' '+((i >> 6) & 0x3F))); 
      break; 
    case 1: 
      i = ((b[off] & 0xFF) << 16); 
      s.append((char)(' '+((i >> 18) & 0x3F))); 
      s.append((char)(' '+((i >> 12) & 0x3F))); 
      break; 
    } 
    return s.toString(); 
  } 
   
  public static String encodeUU(byte[] b) { 
    return encodeUU(b, 0, b.length); 
  } 
   
  public static byte[] decodeUU(String s) { 
    s = s.replaceAll("\r\n|\r|\n|\u2028|\u2029", "\n").trim(); 
    if (s.startsWith("begin ") && s.endsWith("\nend")) { 
      int o = s.indexOf('\n'); 
      int e = s.length()-4; 
      s = s.substring(o, e).trim(); 
    } 
    CharacterIterator it = new StringCharacterIterator(s); 
    ByteArrayOutputStream out = new ByteArrayOutputStream(); 
    int i = 0, j = 0; 
    for (char ch = it.first(); ch != CharacterIterator.DONE && ch != '`'; ch = it.next()) { 
      if (ch <= ' ' || ch >= '`') continue; 
      while (true) { 
        int v = (int)(it.next() - ' '); 
        if (v >= 0 && v < 64) { 
          i = (i << 6) | v; 
          j++; 
          if (j >= 4) { 
            out.write(i >> 16); 
            out.write(i >> 8); 
            out.write(i); 
            i = 0; j = 0; 
          } 
        } else { 
          break; 
        } 
      } 
    } 
    switch (j) { 
    case 3: 
      out.write(i >> 10); 
      out.write(i >> 2); 
      break; 
    case 2: 
      out.write(i >> 4); 
      break; 
    } 
    return out.toByteArray(); 
  } 
   
  private static final char[] xxe = { 
    '+','-','0','1','2','3','4','5','6','7','8','9','A','B','C','D', 
    'E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T', 
    'U','V','W','X','Y','Z','a','b','c','d','e','f','g','h','i','j', 
    'k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z', 
  }; 
   
  public static String encodeXX(byte[] b, int off, int len) { 
    int i = 0; 
    StringBuffer s = new StringBuffer(); 
    while (len > 45) { 
      s.append(xxe[45]); 
      for (int j = 0; j < 45; j += 3) { 
        i = ((b[off] & 0xFF) << 16) | ((b[off+1] & 0xFF) << 8) | (b[off+2] & 0xFF); 
        s.append(xxe[(i >> 18) & 0x3F]); 
        s.append(xxe[(i >> 12) & 0x3F]); 
        s.append(xxe[(i >> 6) & 0x3F]); 
        s.append(xxe[i & 0x3F]); 
        off += 3; 
        len -= 3; 
      } 
      s.append('\n'); 
    } 
    s.append(xxe[len]); 
    while (len >= 3) { 
      i = ((b[off] & 0xFF) << 16) | ((b[off+1] & 0xFF) << 8) | (b[off+2] & 0xFF); 
      s.append(xxe[(i >> 18) & 0x3F]); 
      s.append(xxe[(i >> 12) & 0x3F]); 
      s.append(xxe[(i >> 6) & 0x3F]); 
      s.append(xxe[i & 0x3F]); 
      off += 3; 
      len -= 3; 
    } 
    switch (len) { 
    case 2: 
      i = ((b[off] & 0xFF) << 16) | ((b[off+1] & 0xFF) << 8); 
      s.append(xxe[(i >> 18) & 0x3F]); 
      s.append(xxe[(i >> 12) & 0x3F]); 
      s.append(xxe[(i >> 6) & 0x3F]); 
      break; 
    case 1: 
      i = ((b[off] & 0xFF) << 16); 
      s.append(xxe[(i >> 18) & 0x3F]); 
      s.append(xxe[(i >> 12) & 0x3F]); 
      break; 
    } 
    return s.toString(); 
  } 
   
  public static String encodeXX(byte[] b) { 
    return encodeXX(b, 0, b.length); 
  } 
   
  private static int xxd(char i) { 
    switch (i) { 
    case '+': return 0; case '-': return 1; case '0': return 2; case '1': return 3; 
    case '2': return 4; case '3': return 5; case '4': return 6; case '5': return 7; 
    case '6': return 8; case '7': return 9; case '8': return 10; case '9': return 11; 
    case 'A': return 12; case 'B': return 13; case 'C': return 14; case 'D': return 15; 
    case 'E': return 16; case 'F': return 17; case 'G': return 18; case 'H': return 19; 
    case 'I': return 20; case 'J': return 21; case 'K': return 22; case 'L': return 23; 
    case 'M': return 24; case 'N': return 25; case 'O': return 26; case 'P': return 27; 
    case 'Q': return 28; case 'R': return 29; case 'S': return 30; case 'T': return 31; 
    case 'U': return 32; case 'V': return 33; case 'W': return 34; case 'X': return 35; 
    case 'Y': return 36; case 'Z': return 37; case 'a': return 38; case 'b': return 39; 
    case 'c': return 40; case 'd': return 41; case 'e': return 42; case 'f': return 43; 
    case 'g': return 44; case 'h': return 45; case 'i': return 46; case 'j': return 47; 
    case 'k': return 48; case 'l': return 49; case 'm': return 50; case 'n': return 51; 
    case 'o': return 52; case 'p': return 53; case 'q': return 54; case 'r': return 55; 
    case 's': return 56; case 't': return 57; case 'u': return 58; case 'v': return 59; 
    case 'w': return 60; case 'x': return 61; case 'y': return 62; case 'z': return 63; 
    default: return -1; 
    } 
  } 
   
  public static byte[] decodeXX(String s) { 
    s = s.replaceAll("\r\n|\r|\n|\u2028|\u2029", "\n").trim(); 
    if (s.startsWith("begin ") && s.endsWith("\nend")) { 
      int o = s.indexOf('\n'); 
      int e = s.length()-4; 
      s = s.substring(o, e).trim(); 
    } 
    CharacterIterator it = new StringCharacterIterator(s); 
    ByteArrayOutputStream out = new ByteArrayOutputStream(); 
    int i = 0, j = 0; 
    for (char ch = it.first(); ch != CharacterIterator.DONE && ch != '+'; ch = it.next()) { 
      if (xxd(ch) < 0) continue; 
      while (true) { 
        int v = xxd(it.next()); 
        if (v >= 0) { 
          i = (i << 6) | v; 
          j++; 
          if (j >= 4) { 
            out.write(i >> 16); 
            out.write(i >> 8); 
            out.write(i); 
            i = 0; j = 0; 
          } 
        } else { 
          break; 
        } 
      } 
    } 
    switch (j) { 
    case 3: 
      out.write(i >> 10); 
      out.write(i >> 2); 
      break; 
    case 2: 
      out.write(i >> 4); 
      break; 
    } 
    return out.toByteArray(); 
  } 
   
  private static final char[] hqxe = { 
    '!','"','#','$','%','&','\'','(',')','*','+',',','-','0','1','2', 
    '3','4','5','6','8','9','@','A','B','C','D','E','F','G','H','I', 
    'J','K','L','M','N','P','Q','R','S','T','U','V','X','Y','Z','[', 
    '`','a','b','c','d','e','f','h','i','j','k','l','m','p','q','r', 
  }; 
   
  public static String encodeBinHex(byte[] b, int off, int len) { 
    // phase 1 - RLE 
    ByteArrayOutputStream iout = new ByteArrayOutputStream(); 
    while (len > 0) { 
      byte v = b[off++]; 
      int r = 1; 
      len--; 
      while (len > 0 && b[off] == v && r < 255) { 
        off++; 
        r++; 
        len--; 
      } 
      if (r > 2) { 
        if (v == (byte)0x90) { 
          iout.write(0x90); 
          iout.write(0); 
        } else { 
          iout.write(v); 
        } 
        iout.write(0x90); 
        iout.write(r); 
      } else while (r-->0) { 
        if (v == (byte)0x90) { 
          iout.write(0x90); 
          iout.write(0); 
        } else { 
          iout.write(v); 
        } 
      } 
    } 
    b = iout.toByteArray(); 
    off = 0; 
    len = b.length; 
    // phase 2 - base64 encoding 
    int i = 0; 
    StringBuffer s = new StringBuffer(); 
    s.append(':'); 
    while (len >= 3) { 
      i = ((b[off] & 0xFF) << 16) | ((b[off+1] & 0xFF) << 8) | (b[off+2] & 0xFF); 
      s.append(hqxe[(i >> 18) & 0x3F]); 
      s.append(hqxe[(i >> 12) & 0x3F]); 
      s.append(hqxe[(i >> 6) & 0x3F]); 
      s.append(hqxe[i & 0x3F]); 
      off += 3; 
      len -= 3; 
    } 
    switch (len) { 
    case 2: 
      i = ((b[off] & 0xFF) << 16) | ((b[off+1] & 0xFF) << 8); 
      s.append(hqxe[(i >> 18) & 0x3F]); 
      s.append(hqxe[(i >> 12) & 0x3F]); 
      s.append(hqxe[(i >> 6) & 0x3F]); 
      break; 
    case 1: 
      i = ((b[off] & 0xFF) << 16); 
      s.append(hqxe[(i >> 18) & 0x3F]); 
      s.append(hqxe[(i >> 12) & 0x3F]); 
      break; 
    } 
    s.append(':'); 
    return s.toString(); 
  } 
   
  public static String encodeBinHex(byte[] b) { 
    return encodeBinHex(b, 0, b.length); 
  } 
   
  private static int hqxd(char i) { 
    switch (i) { 
    case '!': return 0; case '"': return 1; case '#': return 2; case '$': return 3; 
    case '%': return 4; case '&': return 5; case '\'': return 6; case '(': return 7; 
    case ')': return 8; case '*': return 9; case '+': return 10; case ',': return 11; 
    case '-': return 12; case '0': return 13; case '1': return 14; case '2': return 15; 
    case '3': return 16; case '4': return 17; case '5': return 18; case '6': return 19; 
    case '8': return 20; case '9': return 21; case '@': return 22; case 'A': return 23; 
    case 'B': return 24; case 'C': return 25; case 'D': return 26; case 'E': return 27; 
    case 'F': return 28; case 'G': return 29; case 'H': return 30; case 'I': return 31; 
    case 'J': return 32; case 'K': return 33; case 'L': return 34; case 'M': return 35; 
    case 'N': return 36; case 'P': return 37; case 'Q': return 38; case 'R': return 39; 
    case 'S': return 40; case 'T': return 41; case 'U': return 42; case 'V': return 43; 
    case 'X': return 44; case 'Y': return 45; case 'Z': return 46; case '[': return 47; 
    case '`': return 48; case 'a': return 49; case 'b': return 50; case 'c': return 51; 
    case 'd': return 52; case 'e': return 53; case 'f': return 54; case 'h': return 55; 
    case 'i': return 56; case 'j': return 57; case 'k': return 58; case 'l': return 59; 
    case 'm': return 60; case 'p': return 61; case 'q': return 62; case 'r': return 63; 
    default: return -1; 
    } 
  } 
   
  public static byte[] decodeBinHex(String s) { 
    // phase 1 - base64 encoding 
    CharacterIterator it = new StringCharacterIterator(s.trim()); 
    ByteArrayOutputStream iout = new ByteArrayOutputStream(); 
    int i = 0, j = 0; 
    char ch = it.first(); 
    if (ch == ':') ch = it.next(); 
    while (ch != CharacterIterator.DONE && ch != ':') { 
      int v = hqxd(ch); 
      if (v >= 0) { 
        i = (i << 6) | v; 
        j++; 
        if (j >= 4) { 
          iout.write(i >> 16); 
          iout.write(i >> 8); 
          iout.write(i); 
          i = 0; j = 0; 
        } 
      } 
      ch = it.next(); 
    } 
    switch (j) { 
    case 3: 
      iout.write(i >> 10); 
      iout.write(i >> 2); 
      break; 
    case 2: 
      iout.write(i >> 4); 
      break; 
    } 
    byte[] b = iout.toByteArray(); 
    // phase 2 - RLE 
    int off = 0; 
    ByteArrayOutputStream out = new ByteArrayOutputStream(); 
    byte last = 0; 
    while (off < b.length) { 
      byte v = b[off++]; 
      if (v == (byte)0x90 && off < b.length) { 
        int r = b[off++] & 0xFF; 
        if (r == 0) { 
          out.write(last = (byte)0x90); 
        } else { 
          r--; 
          while (r-->0) { 
            out.write(last); 
          } 
        } 
      } else { 
        out.write(last = v); 
      } 
    } 
    return out.toByteArray(); 
  } 
   
  public static String encodeASCII85(byte[] b, int off, int len) { 
    long i = 0; 
    StringBuffer s = new StringBuffer(); 
    s.append("<~"); 
    while (len >= 4) { 
      i = ((b[off] & 0xFFL) << 24L) | ((b[off+1] & 0xFFL) << 16L) | ((b[off+2] & 0xFFL) << 8L) | (b[off+3] & 0xFFL); 
      if (i == 0) { 
        s.append('z'); 
      } else { 
        s.append((char)('!' + ((i / 52200625) % 85))); 
        s.append((char)('!' + ((i / 614125) % 85))); 
        s.append((char)('!' + ((i / 7225) % 85))); 
        s.append((char)('!' + ((i / 85) % 85))); 
        s.append((char)('!' + (i % 85))); 
      } 
      off += 4; 
      len -= 4; 
    } 
    switch (len) { 
    case 3: 
      i = ((b[off] & 0xFFL) << 24L) | ((b[off+1] & 0xFFL) << 16L) | ((b[off+2] & 0xFFL) << 8L); 
      s.append((char)('!' + ((i / 52200625) % 85))); 
      s.append((char)('!' + ((i / 614125) % 85))); 
      s.append((char)('!' + ((i / 7225) % 85))); 
      s.append((char)('!' + ((i / 85) % 85))); 
      break; 
    case 2: 
      i = ((b[off] & 0xFFL) << 24L) | ((b[off+1] & 0xFFL) << 16L); 
      s.append((char)('!' + ((i / 52200625) % 85))); 
      s.append((char)('!' + ((i / 614125) % 85))); 
      s.append((char)('!' + ((i / 7225) % 85))); 
      break; 
    case 1: 
      i = ((b[off] & 0xFFL) << 24L); 
      s.append((char)('!' + ((i / 52200625) % 85))); 
      s.append((char)('!' + ((i / 614125) % 85))); 
      break; 
    } 
    s.append("~>"); 
    return s.toString(); 
  } 
   
  public static String encodeASCII85(byte[] b) { 
    return encodeASCII85(b, 0, b.length); 
  } 
   
  public static byte[] decodeASCII85(String s) { 
    s = s.trim(); 
    if (s.startsWith("<~") && s.endsWith("~>")) { 
      s = s.substring(2, s.length()-2).trim(); 
    } 
    CharacterIterator it = new StringCharacterIterator(s); 
    ByteArrayOutputStream out = new ByteArrayOutputStream(); 
    long i = 0; int j = 0; 
    for (char ch = it.first(); ch != CharacterIterator.DONE && ch != '~'; ch = it.next()) { 
      if (ch == 'z' && j == 0) { 
        out.write(0); 
        out.write(0); 
        out.write(0); 
        out.write(0); 
      } else if (ch == 'y' && j == 0) { 
        out.write(' '); 
        out.write(' '); 
        out.write(' '); 
        out.write(' '); 
      } else if (ch == 'x' && j == 0) { 
        out.write(-1); 
        out.write(-1); 
        out.write(-1); 
        out.write(-1); 
      } else if (ch >= '!' && ch <= 'u') { 
        i = i * 85L + (long)(ch - '!'); 
        j++; 
        if (j >= 5) { 
          out.write((int)(i >> 24L)); 
          out.write((int)(i >> 16L)); 
          out.write((int)(i >> 8L)); 
          out.write((int)i); 
          i = 0; j = 0; 
        } 
      } 
    } 
    switch (j) { 
    case 4: 
      i = i * 85L + 84L; 
      out.write((int)(i >> 24L)); 
      out.write((int)(i >> 16L)); 
      out.write((int)(i >> 8L)); 
      break; 
    case 3: 
      i = i * 85L + 84L; 
      i = i * 85L + 84L; 
      out.write((int)(i >> 24L)); 
      out.write((int)(i >> 16L)); 
      break; 
    case 2: 
      i = i * 85L + 84L; 
      i = i * 85L + 84L; 
      i = i * 85L + 84L; 
      out.write((int)(i >> 24L)); 
      break; 
    } 
    return out.toByteArray(); 
  } 
   
  private static final char[] k85e = { 
    '!','#','$','%','&','(',')','+',',','-','.','0','1','2','3','4','5', 
    '6','7','8','9',':',';','=','@','A','B','C','D','E','F','G','H','I', 
    'J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z', 
    '[',']','^','_','`','a','b','c','d','e','f','g','h','i','j','k','l', 
    'm','n','o','p','q','r','s','t','u','v','w','x','y','z','{','}','~', 
  }; 
   
  public static String encodeKreative85(byte[] b, int off, int len) { 
    long i = 0; 
    StringBuffer s = new StringBuffer(); 
    while (len >= 4) { 
      i = ((b[off] & 0xFFL) << 24L) | ((b[off+1] & 0xFFL) << 16L) | ((b[off+2] & 0xFFL) << 8L) | (b[off+3] & 0xFFL); 
      s.append(k85e[(int)((i / 52200625) % 85)]); 
      s.append(k85e[(int)((i / 614125) % 85)]); 
      s.append(k85e[(int)((i / 7225) % 85)]); 
      s.append(k85e[(int)((i / 85) % 85)]); 
      s.append(k85e[(int)(i % 85)]); 
      off += 4; 
      len -= 4; 
    } 
    switch (len) { 
    case 3: 
      i = ((b[off] & 0xFFL) << 24L) | ((b[off+1] & 0xFFL) << 16L) | ((b[off+2] & 0xFFL) << 8L); 
      s.append(k85e[(int)((i / 52200625) % 85)]); 
      s.append(k85e[(int)((i / 614125) % 85)]); 
      s.append(k85e[(int)((i / 7225) % 85)]); 
      s.append(k85e[(int)((i / 85) % 85)]); 
      break; 
    case 2: 
      i = ((b[off] & 0xFFL) << 24L) | ((b[off+1] & 0xFFL) << 16L); 
      s.append(k85e[(int)((i / 52200625) % 85)]); 
      s.append(k85e[(int)((i / 614125) % 85)]); 
      s.append(k85e[(int)((i / 7225) % 85)]); 
      break; 
    case 1: 
      i = ((b[off] & 0xFFL) << 24L); 
      s.append(k85e[(int)((i / 52200625) % 85)]); 
      s.append(k85e[(int)((i / 614125) % 85)]); 
      break; 
    } 
    return s.toString(); 
  } 
   
  public static String encodeKreative85(byte[] b) { 
    return encodeKreative85(b, 0, b.length); 
  } 
   
  public static String encodeLegacy85(byte[] b, int off, int len) { 
    long i = 0; 
    StringBuffer s = new StringBuffer(); 
    s.append('<'); 
    s.append(k85e[(int)((long)len % 85L)]); 
    s.append(k85e[(int)(((long)len / 85L) % 85L)]); 
    s.append(k85e[(int)(((long)len / 7225L) % 85L)]); 
    s.append(k85e[(int)(((long)len / 614125L) % 85L)]); 
    s.append(k85e[(int)(((long)len / 52200625L) % 85L)]); 
    s.append('>'); 
    while (len >= 4) { 
      i = ((b[off+3] & 0xFFL) << 24L) | ((b[off+2] & 0xFFL) << 16L) | ((b[off+1] & 0xFFL) << 8L) | (b[off] & 0xFFL); 
      s.append(k85e[(int)(i % 85L)]); 
      s.append(k85e[(int)((i / 85L) % 85L)]); 
      s.append(k85e[(int)((i / 7225L) % 85L)]); 
      s.append(k85e[(int)((i / 614125L) % 85L)]); 
      s.append(k85e[(int)((i / 52200625L) % 85L)]); 
      off += 4; 
      len -= 4; 
    } 
    if (len > 0) { 
      switch (len) { 
      case 3: 
        i = ((b[off+2] & 0xFFL) << 16L) | ((b[off+1] & 0xFFL) << 8L) | (b[off] & 0xFFL); 
        break; 
      case 2: 
        i = ((b[off+1] & 0xFFL) << 8L) | (b[off] & 0xFFL); 
        break; 
      case 1: 
        i = (b[off] & 0xFFL); 
        break; 
      } 
      s.append(k85e[(int)(i % 85L)]); 
      s.append(k85e[(int)((i / 85L) % 85L)]); 
      s.append(k85e[(int)((i / 7225L) % 85L)]); 
      s.append(k85e[(int)((i / 614125L) % 85L)]); 
      s.append(k85e[(int)((i / 52200625L) % 85L)]); 
    } 
    return s.toString(); 
  } 
   
  public static String encodeLegacy85(byte[] b) { 
    return encodeLegacy85(b, 0, b.length); 
  } 
   
  private static int k85d(char i) { 
    switch (i) { 
    case '!': return 0; case '#': return 1; case '$': return 2; case '%': return 3; case '&': return 4; 
    case '(': return 5; case ')': return 6; case '+': return 7; case ',': return 8; case '-': return 9; 
    case '.': return 10; case '0': return 11; case '1': return 12; case '2': return 13; case '3': return 14; 
    case '4': return 15; case '5': return 16; case '6': return 17; case '7': return 18; case '8': return 19; 
    case '9': return 20; case ':': return 21; case ';': return 22; case '=': return 23; case '@': return 24; 
    case 'A': return 25; case 'B': return 26; case 'C': return 27; case 'D': return 28; case 'E': return 29; 
    case 'F': return 30; case 'G': return 31; case 'H': return 32; case 'I': return 33; case 'J': return 34; 
    case 'K': return 35; case 'L': return 36; case 'M': return 37; case 'N': return 38; case 'O': return 39; 
    case 'P': return 40; case 'Q': return 41; case 'R': return 42; case 'S': return 43; case 'T': return 44; 
    case 'U': return 45; case 'V': return 46; case 'W': return 47; case 'X': return 48; case 'Y': return 49; 
    case 'Z': return 50; case '[': return 51; case ']': return 52; case '^': return 53; case '_': return 54; 
    case '`': return 55; case 'a': return 56; case 'b': return 57; case 'c': return 58; case 'd': return 59; 
    case 'e': return 60; case 'f': return 61; case 'g': return 62; case 'h': return 63; case 'i': return 64; 
    case 'j': return 65; case 'k': return 66; case 'l': return 67; case 'm': return 68; case 'n': return 69; 
    case 'o': return 70; case 'p': return 71; case 'q': return 72; case 'r': return 73; case 's': return 74; 
    case 't': return 75; case 'u': return 76; case 'v': return 77; case 'w': return 78; case 'x': return 79; 
    case 'y': return 80; case 'z': return 81; case '{': return 82; case '}': return 83; case '~': return 84; 
    default: return -1; 
    } 
  } 
   
  public static byte[] decodeKreative85(String s) { 
    CharacterIterator it = new StringCharacterIterator(s.trim()); 
    ByteArrayOutputStream out = new ByteArrayOutputStream(); 
    long i = 0; int j = 0; 
    for (char ch = it.first(); ch != CharacterIterator.DONE; ch = it.next()) { 
      int v = k85d(ch); 
      if (v >= 0) { 
        i = i * 85L + v; 
        j++; 
        if (j >= 5) { 
          out.write((int)(i >> 24L)); 
          out.write((int)(i >> 16L)); 
          out.write((int)(i >> 8L)); 
          out.write((int)i); 
          i = 0; j = 0; 
        } 
      } 
    } 
    switch (j) { 
    case 4: 
      i = i * 85L + 84L; 
      out.write((int)(i >> 24L)); 
      out.write((int)(i >> 16L)); 
      out.write((int)(i >> 8L)); 
      break; 
    case 3: 
      i = i * 85L + 84L; 
      i = i * 85L + 84L; 
      out.write((int)(i >> 24L)); 
      out.write((int)(i >> 16L)); 
      break; 
    case 2: 
      i = i * 85L + 84L; 
      i = i * 85L + 84L; 
      i = i * 85L + 84L; 
      out.write((int)(i >> 24L)); 
      break; 
    } 
    return out.toByteArray(); 
  } 
   
  public static byte[] decodeLegacy85(String s) { 
    int targetLength = -1; 
    s = s.trim(); 
    if (s.length() >= 7 && s.charAt(0) == '<' && s.charAt(6) == '>') { 
      targetLength =  
        k85d(s.charAt(1)) + 
        k85d(s.charAt(2)) * 85 + 
        k85d(s.charAt(3)) * 7225 + 
        k85d(s.charAt(4)) * 614125 + 
        k85d(s.charAt(5)) * 52200625; 
      s = s.substring(7).trim(); 
    } 
    CharacterIterator it = new StringCharacterIterator(s); 
    ByteArrayOutputStream out = new ByteArrayOutputStream(); 
    long i = 0; int j = 0; long k = 1; 
    for (char ch = it.first(); ch != CharacterIterator.DONE; ch = it.next()) { 
      int v = k85d(ch); 
      if (v >= 0) { 
        i += v * k; 
        j++; 
        k *= 85; 
        if (j >= 5) { 
          out.write((int)i); 
          out.write((int)(i >> 8L)); 
          out.write((int)(i >> 16L)); 
          out.write((int)(i >> 24L)); 
          i = 0; j = 0; k = 1; 
        } 
      } 
    } 
    if (j > 0) { 
      out.write((int)i); 
      out.write((int)(i >> 8L)); 
      out.write((int)(i >> 16L)); 
      out.write((int)(i >> 24L)); 
    } 
    if (targetLength >= 0) { 
      byte[] b = out.toByteArray(); 
      byte[] bt = new byte[targetLength]; 
      for (int x = 0; x < targetLength && x < b.length; x++) { 
        bt[x] = b[x]; 
      } 
      return bt; 
    } else { 
      return out.toByteArray(); 
    } 
  } 
   
  public static void main(String[] args) throws IOException { 
    boolean decode = false; 
    int mode = 0; 
    for (String arg : args) { 
      if (arg.equals("-e")) { 
        decode = false; 
      } else if (arg.equals("-d")) { 
        decode = true; 
      } else if (arg.equals("-b64")) { 
        mode = 0; 
      } else if (arg.equals("-hqx")) { 
        mode = 1; 
      } else if (arg.equals("-a85")) { 
        mode = 2; 
      } else if (arg.equals("-l85")) { 
        mode = 3; 
      } else if (arg.equals("-k85")) { 
        mode = 4; 
      } else if (arg.equals("-uue")) { 
        mode = 5; 
      } else if (arg.equals("-xxe")) { 
        mode = 6; 
      } else if (arg.equals("--")) { 
        ByteArrayOutputStream out = new ByteArrayOutputStream(); 
        byte[] buf = new byte[1048576]; 
        int len = 0; 
        while ((len = System.in.read(buf)) >= 0) { 
          out.write(buf, 0, len); 
        } 
        out.close(); 
        if (decode) { 
          switch (mode) { 
          case 0: System.out.println(new String(decodeBase64(out.toString()))); break; 
          case 1: System.out.println(new String(decodeBinHex(out.toString()))); break; 
          case 2: System.out.println(new String(decodeASCII85(out.toString()))); break; 
          case 3: System.out.println(new String(decodeLegacy85(out.toString()))); break; 
          case 4: System.out.println(new String(decodeKreative85(out.toString()))); break; 
          case 5: System.out.println(new String(decodeUU(out.toString()))); break; 
          case 6: System.out.println(new String(decodeXX(out.toString()))); break; 
          } 
        } else { 
          switch (mode) { 
          case 0: System.out.println(encodeBase64(out.toByteArray())); break; 
          case 1: System.out.println(encodeBinHex(out.toByteArray())); break; 
          case 2: System.out.println(encodeASCII85(out.toByteArray())); break; 
          case 3: System.out.println(encodeLegacy85(out.toByteArray())); break; 
          case 4: System.out.println(encodeKreative85(out.toByteArray())); break; 
          case 5: System.out.println(encodeUU(out.toByteArray())); break; 
          case 6: System.out.println(encodeXX(out.toByteArray())); break; 
          } 
        } 
      } else if (decode) { 
        switch (mode) { 
        case 0: System.out.println(new String(decodeBase64(arg))); break; 
        case 1: System.out.println(new String(decodeBinHex(arg))); break; 
        case 2: System.out.println(new String(decodeASCII85(arg))); break; 
        case 3: System.out.println(new String(decodeLegacy85(arg))); break; 
        case 4: System.out.println(new String(decodeKreative85(arg))); break; 
        case 5: System.out.println(new String(decodeUU(arg))); break; 
        case 6: System.out.println(new String(decodeXX(arg))); break; 
        } 
      } else { 
        switch (mode) { 
        case 0: System.out.println(encodeBase64(arg.getBytes())); break; 
        case 1: System.out.println(encodeBinHex(arg.getBytes())); break; 
        case 2: System.out.println(encodeASCII85(arg.getBytes())); break; 
        case 3: System.out.println(encodeLegacy85(arg.getBytes())); break; 
        case 4: System.out.println(encodeKreative85(arg.getBytes())); break; 
        case 5: System.out.println(encodeUU(arg.getBytes())); break; 
        case 6: System.out.println(encodeXX(arg.getBytes())); break; 
        } 
      } 
    } 
  } 
} 
 
    
     
     
     
     
  
  |