View Javadoc
1 // Copyright (C) 2004, Brian Enigma <enigma at netninja.com> 2 // This file is part of MagicCodes. 3 // 4 // MagicCodes is free software; you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation; either version 2 of the License, or 7 // (at your option) any later version. 8 // 9 // MagicCodes is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with Foobar; if not, write to the Free Software 16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 package org.ninjasoft.magiccodes.plugins; 18 19 20 /*** 21 * Decodes BASE-64 data 22 * @author enigma 23 */ 24 public class Base64Decoder implements Plugin { 25 26 public String getName() { 27 return "BASE-64 Decoder"; 28 } 29 30 public String getDescription() { 31 return "Decodes BASE-64 text to original data"; 32 } 33 34 public boolean usesKey() { 35 return false; 36 } 37 38 public boolean isInformational() { 39 return false; 40 } 41 42 /*** 43 * Convert a Base64 character to its 6 bit value as defined by the mapping. 44 * @param c Base64 character to decode 45 * @return int representation of 6 bit value 46 */ 47 private int mapCharToInt( char c ) { 48 if ( c >= 'A' && c <= 'Z' ) { 49 return c - 'A'; 50 } 51 52 if ( c >= 'a' && c <= 'z' ) { 53 return ( c - 'a' ) + Base64Encoder.LOWER_CASE_A_VALUE; 54 } 55 56 if ( c >= '0' && c <= '9' ) { 57 return ( c - '0' ) + Base64Encoder.ZERO_VALUE; 58 } 59 60 if ( c == '+' ) { 61 return Base64Encoder.PLUS_VALUE; 62 } 63 64 if ( c == '/' ) { 65 return Base64Encoder.SLASH_VALUE; 66 } 67 68 throw new IllegalArgumentException( c + " is not a valid Base64 character." ); 69 } 70 71 /*** 72 * Simple class to wrap around the String input to ignore all of the 73 * non-Base64 characters in the input. Note that although '=' is 74 * a valid character, it does not contribute to the total number 75 * of output bytes, and is therefore ignored 76 */ 77 private class StringWrapper { 78 79 /*** 80 * The input String to be decoded 81 */ 82 private int[] mString; 83 84 /*** 85 * Current position in the String 86 */ 87 private int mIndex = 0; 88 89 /*** 90 * Total number of Base64 characters in the input 91 */ 92 private int mUsefulLength; 93 94 /*** 95 * @param c Character to be examined 96 * @return Whether or not the character is a Base64 character 97 */ 98 private boolean isUsefulChar( int i ) { 99 char c = (char) i; 100 return ( c >= 'A' && c <= 'Z' ) || 101 ( c >= 'a' && c <= 'z' ) || 102 ( c >= '0' && c <= '9' ) || 103 ( c == '+' ) || 104 ( c == '/' ); 105 } 106 107 /*** 108 * Create the wrapper and determine the number of Base64 characters in 109 * the input 110 * @param s Input String to be decoded 111 */ 112 public StringWrapper( int[] in ) { 113 mString = in; 114 mUsefulLength = 0; 115 for( int i = 0; i < in.length; i++ ) { 116 if( isUsefulChar( mString[i] ) ){ 117 mUsefulLength++; 118 } 119 } 120 } 121 122 /*** 123 * @return Total number of Base64 characters in the input. Does 124 * not include '=' 125 */ 126 public int getUsefulLength() { 127 return mUsefulLength; 128 } 129 130 /*** 131 * Traverse the String until hitting the next Base64 character. 132 * Assumes that there is still another valid Base64 character 133 * left in the String. 134 */ 135 public char getNextUsefulChar() { 136 char result = '_'; // Start with a non-Base64 character 137 while ( !isUsefulChar( result ) ) { 138 result = (char) mString[mIndex++]; 139 } 140 141 return result; 142 } 143 } 144 145 /*** 146 * Bit mask for one byte worth of bits in Base64 encoding. 147 * Equivalent to binary value 11111111b. 148 */ 149 private static final int EIGHT_BIT_MASK = 0xFF; 150 151 public int[] doAction(int[] in, int[] key) { 152 // Create a wrapper around the input to screen out non-Base64 characters 153 StringWrapper wrapper = new StringWrapper( in ); 154 // A Base64 byte array is 75% the size of its String representation 155 int byteArrayLength = wrapper.getUsefulLength() * 3 / 4; 156 157 int result[] = new int[ byteArrayLength ]; 158 159 int byteTriplet = 0; 160 int byteIndex = 0; 161 162 // Continue until we have less than 4 full characters left to 163 // decode in the input. 164 while ( byteIndex + 2 < byteArrayLength ) { 165 166 // Package a set of four characters into a byte triplet 167 // Each character contributes 6 bits of useful information 168 byteTriplet = mapCharToInt( wrapper.getNextUsefulChar() ); 169 byteTriplet <<= 6; 170 byteTriplet |= mapCharToInt( wrapper.getNextUsefulChar() ); 171 byteTriplet <<= 6; 172 byteTriplet |= mapCharToInt( wrapper.getNextUsefulChar() ); 173 byteTriplet <<= 6; 174 byteTriplet |= mapCharToInt( wrapper.getNextUsefulChar() ); 175 176 // Grab a normal byte (eight bits) out of the byte triplet 177 // and put it in the byte array 178 result[ byteIndex + 2 ] = (byte)( byteTriplet & EIGHT_BIT_MASK ); 179 byteTriplet >>= 8; 180 result[ byteIndex + 1 ] = (byte)( byteTriplet & EIGHT_BIT_MASK ); 181 byteTriplet >>= 8; 182 result[ byteIndex ] = (byte)( byteTriplet & EIGHT_BIT_MASK ); 183 byteIndex += 3; 184 } 185 186 // Check if we have one byte left to decode 187 if ( byteIndex == byteArrayLength - 1 ) { 188 // Take out the last two characters from the String 189 byteTriplet = mapCharToInt( wrapper.getNextUsefulChar() ); 190 byteTriplet <<= 6; 191 byteTriplet |= mapCharToInt( wrapper.getNextUsefulChar() ); 192 193 // Remove the padded zeros 194 byteTriplet >>= 4; 195 result[ byteIndex ] = (byte)( byteTriplet & EIGHT_BIT_MASK ); 196 } 197 198 // Check if we have two bytes left to decode 199 if ( byteIndex == byteArrayLength - 2 ) { 200 // Take out the last three characters from the String 201 byteTriplet = mapCharToInt( wrapper.getNextUsefulChar() ); 202 byteTriplet <<= 6; 203 byteTriplet |= mapCharToInt( wrapper.getNextUsefulChar() ); 204 byteTriplet <<= 6; 205 byteTriplet |= mapCharToInt( wrapper.getNextUsefulChar() ); 206 207 // Remove the padded zeros 208 byteTriplet >>= 2; 209 result[ byteIndex + 1 ] = (byte)( byteTriplet & EIGHT_BIT_MASK ); 210 byteTriplet >>= 8; 211 result[ byteIndex ] = (byte)( byteTriplet & EIGHT_BIT_MASK ); 212 } 213 214 return result; 215 } 216 217 }

This page was automatically generated by Maven