Added Base64Encoder

This commit is contained in:
Ziver Koc 2015-11-17 18:59:50 +01:00
parent 67e4d54fde
commit 034166b413
7 changed files with 219 additions and 57 deletions

16
src/zutil/converters/Converter.java Normal file → Executable file
View file

@ -170,22 +170,6 @@ public class Converter {
return object; return object;
} }
/**
* Checks if the given interface is implemented in the object
*
* @param object the object to look for the interface
* @param interf the interface to look for
* @return true if the interface is implemented else false
*/
public static boolean isInstanceOf(Object object, Class<?> interf){
Class<?>[] objectInterf = object.getClass().getInterfaces();
for(int i=0; i<objectInterf.length ;i++){
if(objectInterf[i] == interf){
return true;
}
}
return false;
}
/** array needed for byteToHex */ /** array needed for byteToHex */
private static char[] HEX_CHARS = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'}; private static char[] HEX_CHARS = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};

0
src/zutil/parser/BBCodeParser.java Normal file → Executable file
View file

14
src/zutil/parser/BEncodedParser.java Normal file → Executable file
View file

@ -37,7 +37,7 @@ public class BEncodedParser {
/** /**
* Returns the representation of the data in the BEncoded string * Returns the representation of the data in the BEncoded string
* *
* @param data The data to be decoded * @param data is the data to be decoded
* @return * @return
*/ */
public static DataNode read(String data){ public static DataNode read(String data){
@ -47,8 +47,8 @@ public class BEncodedParser {
/** /**
* Returns the representation of the data in the BEncoded string * Returns the representation of the data in the BEncoded string
* *
* @param data The data to be decoded * @param data is the data to be decoded
* @param index The index in data to start from * @param index is the index in data to start from
* @return * @return
*/ */
private static DataNode decode_BEncoded(MutableInt index, StringBuilder data){ private static DataNode decode_BEncoded(MutableInt index, StringBuilder data){
@ -62,11 +62,9 @@ public class BEncodedParser {
* i-3272002e. * i-3272002e.
*/ */
case 'i': case 'i':
//System.out.println("Found Integer at "+index);
index.i++; index.i++;
tmp = data.substring(index.i, data.indexOf("e")); tmp = data.substring(index.i, data.indexOf("e"));
index.i += tmp.length() + 1; index.i += tmp.length() + 1;
//System.out.println(tmp);
return new DataNode( new Long(tmp)); return new DataNode( new Long(tmp));
/** /**
* Lists are prefixed with a l and terminated by an e. The list * Lists are prefixed with a l and terminated by an e. The list
@ -76,7 +74,6 @@ public class BEncodedParser {
* would bEncode to li1e7:Mondunai3el3:Sub4:Listee * would bEncode to li1e7:Mondunai3el3:Sub4:Listee
*/ */
case 'l': case 'l':
//System.out.println("Found List at "+index);
index.i++; index.i++;
DataNode list = new DataNode( DataType.List ); DataNode list = new DataNode( DataType.List );
c = data.charAt(index.i); c = data.charAt(index.i);
@ -85,7 +82,6 @@ public class BEncodedParser {
c = data.charAt(index.i); c = data.charAt(index.i);
} }
index.i++; index.i++;
//MultiPrintStream.out.dump(list);
if(list.size() == 1) return list.get(0); if(list.size() == 1) return list.get(0);
else return list; else return list;
/** /**
@ -95,7 +91,6 @@ public class BEncodedParser {
* would bEncode to d3:key5:value7:Monduna3:com3:bit:8:Torrents6:numberi7ee * would bEncode to d3:key5:value7:Monduna3:com3:bit:8:Torrents6:numberi7ee
*/ */
case 'd': case 'd':
//System.out.println("Found Dictionary at "+index);
index.i++; index.i++;
DataNode map = new DataNode( DataType.Map ); DataNode map = new DataNode( DataType.Map );
c = data.charAt(index.i); c = data.charAt(index.i);
@ -105,7 +100,6 @@ public class BEncodedParser {
c = data.charAt(index.i); c = data.charAt(index.i);
} }
index.i++; index.i++;
//MultiPrintStream.out.dump(map);
return map; return map;
/** /**
* Strings are prefixed with their length followed by a colon. * Strings are prefixed with their length followed by a colon.
@ -113,13 +107,11 @@ public class BEncodedParser {
* would bEncode to 11:BitTorrents. * would bEncode to 11:BitTorrents.
*/ */
default: default:
//System.out.println("Found String at "+index);
tmp = data.substring(index.i, data.indexOf(":")); tmp = data.substring(index.i, data.indexOf(":"));
int length = Integer.parseInt(tmp); int length = Integer.parseInt(tmp);
index.i += tmp.length() + 1; index.i += tmp.length() + 1;
String ret = data.substring(index.i, length); String ret = data.substring(index.i, length);
index.i += length; index.i += length;
//System.out.println(data.substring(i, i+length));
return new DataNode( ret ); return new DataNode( ret );
} }
} }

20
src/zutil/parser/Base64Decoder.java Normal file → Executable file
View file

@ -52,23 +52,23 @@ public class Base64Decoder {
public static String decode( String data ){ public static String decode( String data ){
Base64Decoder base64 = new Base64Decoder(); Base64Decoder base64 = new Base64Decoder();
base64.write( data ); base64.read( data );
return base64.toString(); return base64.toString();
} }
public static String decodeToHex( String data ){ public static String decodeToHex( String data ){
Base64Decoder base64 = new Base64Decoder(); Base64Decoder base64 = new Base64Decoder();
base64.write( data ); base64.read( data );
return Converter.toHexString( base64.getByte() ); return Converter.toHexString( base64.getByte() );
} }
public static byte[] decodeToByte( String data ){ public static byte[] decodeToByte( String data ){
Base64Decoder base64 = new Base64Decoder(); Base64Decoder base64 = new Base64Decoder();
base64.write( data ); base64.read( data );
return base64.getByte(); return base64.getByte();
} }
public void write( String data ){ public void read( String data ){
byte[] buffer = new byte[ (data.length()*6/8) + 1 ]; byte[] buffer = new byte[ (data.length()*6/8) + 1 ];
int buffi = 0; int buffi = 0;
if( rest != 0 ) if( rest != 0 )
@ -121,18 +121,8 @@ public class Base64Decoder {
rest_data = 0; rest_data = 0;
} }
public static String addPadding( String data ){
int padding = 4 - (data.length() % 4);
switch( padding ){
case 0: return data;
case 1: return data + "=";
case 2: return data + "==";
case 3: return data + "===";
}
return null;
}
private byte getByte( char c ){ private static byte getByte( char c ){
switch(c){ switch(c){
case 'A': return (byte)( 0 & 0xff); case 'A': return (byte)( 0 & 0xff);
case 'B': return (byte)( 1 & 0xff); case 'B': return (byte)( 1 & 0xff);

View file

@ -0,0 +1,162 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2015 Ziver Koc
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package zutil.parser;
public class Base64Encoder {
public static String encode( byte[] data ){
Base64Encoder base64 = new Base64Encoder();
return base64.write( data );
}
public static String encode( String data ){
Base64Encoder base64 = new Base64Encoder();
return base64.write( data.getBytes() );
}
private static String write( byte[] data ){
char[] buffer = new char[getBufferLength(data.length)];
int buffIndex = 0;
int rest = 0; // how much rest we have
for( int i=0; i<data.length; i++){
byte b = 0;
switch(rest){
case 0:
b = (byte)((data[i] >> 2) & 0b0011_1111);
break;
case 2:
b = (byte) ((data[i-1] << 4) & 0b0011_0000);
b |= (byte) ((data[i] >> 4) & 0b0000_1111);
break;
case 4:
b = (byte) ((data[i-1] << 2) & 0b0011_1100);
b |= (byte) ((data[i] >> 6) & 0b0000_0011);
break;
case 6:
--i; // Go back one element
b = (byte) (data[i] & 0b0011_1111);
break;
}
rest = (rest + 2) % 8;
buffer[buffIndex++] = getChar(b);
}
// Any rest left?
if(rest == 2)
buffer[buffIndex++] = getChar((byte) ((data[data.length-1] << 4) & 0b0011_0000));
else if(rest == 4)
buffer[buffIndex++] = getChar((byte) ((data[data.length-1] << 2) & 0b0011_1100));
else if(rest == 6)
buffer[buffIndex++] = getChar((byte) (data[data.length-1] & 0b0011_1111));
// Add padding
for(; buffIndex<buffer.length; ++buffIndex)
buffer[buffIndex] = '=';
return new String(buffer);
}
private static int getBufferLength(int length) {
int buffLength = (int) Math.ceil(length*8/6.0);
// Padding
if(buffLength%4 != 0)
buffLength += 4 - buffLength%4;
return buffLength;
}
private static char getChar( byte b ){
switch(b){
case (byte)( 0 & 0xff): return 'A';
case (byte)( 1 & 0xff): return 'B';
case (byte)( 2 & 0xff): return 'C';
case (byte)( 3 & 0xff): return 'D';
case (byte)( 4 & 0xff): return 'E';
case (byte)( 5 & 0xff): return 'F';
case (byte)( 6 & 0xff): return 'G';
case (byte)( 7 & 0xff): return 'H';
case (byte)( 8 & 0xff): return 'I';
case (byte)( 9 & 0xff): return 'J';
case (byte)(10 & 0xff): return 'K';
case (byte)(11 & 0xff): return 'L';
case (byte)(12 & 0xff): return 'M';
case (byte)(13 & 0xff): return 'N';
case (byte)(14 & 0xff): return 'O';
case (byte)(15 & 0xff): return 'P';
case (byte)(16 & 0xff): return 'Q';
case (byte)(17 & 0xff): return 'R';
case (byte)(18 & 0xff): return 'S';
case (byte)(19 & 0xff): return 'T';
case (byte)(20 & 0xff): return 'U';
case (byte)(21 & 0xff): return 'V';
case (byte)(22 & 0xff): return 'W';
case (byte)(23 & 0xff): return 'X';
case (byte)(24 & 0xff): return 'Y';
case (byte)(25 & 0xff): return 'Z';
case (byte)(26 & 0xff): return 'a';
case (byte)(27 & 0xff): return 'b';
case (byte)(28 & 0xff): return 'c';
case (byte)(29 & 0xff): return 'd';
case (byte)(30 & 0xff): return 'e';
case (byte)(31 & 0xff): return 'f';
case (byte)(32 & 0xff): return 'g';
case (byte)(33 & 0xff): return 'h';
case (byte)(34 & 0xff): return 'i';
case (byte)(35 & 0xff): return 'j';
case (byte)(36 & 0xff): return 'k';
case (byte)(37 & 0xff): return 'l';
case (byte)(38 & 0xff): return 'm';
case (byte)(39 & 0xff): return 'n';
case (byte)(40 & 0xff): return 'o';
case (byte)(41 & 0xff): return 'p';
case (byte)(42 & 0xff): return 'q';
case (byte)(43 & 0xff): return 'r';
case (byte)(44 & 0xff): return 's';
case (byte)(45 & 0xff): return 't';
case (byte)(46 & 0xff): return 'u';
case (byte)(47 & 0xff): return 'v';
case (byte)(48 & 0xff): return 'w';
case (byte)(49 & 0xff): return 'w';
case (byte)(50 & 0xff): return 'y';
case (byte)(51 & 0xff): return 'z';
case (byte)(52 & 0xff): return '0';
case (byte)(53 & 0xff): return '1';
case (byte)(54 & 0xff): return '2';
case (byte)(55 & 0xff): return '3';
case (byte)(56 & 0xff): return '4';
case (byte)(57 & 0xff): return '5';
case (byte)(58 & 0xff): return '6';
case (byte)(59 & 0xff): return '7';
case (byte)(60 & 0xff): return '8';
case (byte)(61 & 0xff): return '9';
case (byte)(62 & 0xff): return '+';
case (byte)(63 & 0xff): return '/';
}
return 0;
}
}

View file

@ -26,6 +26,7 @@ package zutil.parser.json;
import sun.reflect.generics.reflectiveObjects.NotImplementedException; import sun.reflect.generics.reflectiveObjects.NotImplementedException;
import zutil.ClassUtil; import zutil.ClassUtil;
import zutil.parser.Base64Encoder;
import zutil.parser.DataNode; import zutil.parser.DataNode;
import zutil.parser.DataNode.DataType; import zutil.parser.DataNode.DataType;
import static zutil.parser.json.JSONObjectInputStream.*; import static zutil.parser.json.JSONObjectInputStream.*;
@ -86,11 +87,19 @@ public class JSONObjectOutputStream extends OutputStream implements ObjectOutput
} }
// Add an array // Add an array
else if(objClass.isArray()){ else if(objClass.isArray()){
root = new DataNode(DataNode.DataType.List); // Special case for byte arrays
if(objClass.getComponentType() == byte[].class) {
root = new DataNode(DataType.String);
root.set(Base64Encoder.encode((byte[])obj));
}
// Other arrays
else {
root = new DataNode(DataType.List);
for (int i = 0; i < Array.getLength(obj); i++) { for (int i = 0; i < Array.getLength(obj); i++) {
root.add(getDataNode(Array.get(obj, i))); root.add(getDataNode(Array.get(obj, i)));
} }
} }
}
// List // List
else if(List.class.isAssignableFrom(objClass)){ else if(List.class.isAssignableFrom(objClass)){
root = new DataNode(DataNode.DataType.List); root = new DataNode(DataNode.DataType.List);

33
test/zutil/test/Base64Test.java Normal file → Executable file
View file

@ -25,27 +25,52 @@ package zutil.test;
import org.junit.Test; import org.junit.Test;
import zutil.parser.Base64Decoder; import zutil.parser.Base64Decoder;
import zutil.parser.Base64Encoder;
import java.util.Base64;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
public class Base64Test { public class Base64Test {
@Test @Test
public void testHexToByte() { public void decode() {
assertEquals( "Man is distinguished, not only by his reason, but by this singular passion from other animals, which is a lust of the mind, that by a perseverance of delight in the continued and indefatigable generation of knowledge, exceeds the short vehemence of any carnal pleasure.", assertEquals( "Man is distinguished, not only by his reason, but by this singular passion from other animals, which is a lust of the mind, that by a perseverance of delight in the continued and indefatigable generation of knowledge, exceeds the short vehemence of any carnal pleasure.",
Base64Decoder.decode("TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieSB0aGlzIHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYWxzLCB3aGljaCBpcyBhIGx1c3Qgb2YgdGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodCBpbiB0aGUgY29udGludWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZGdlLCBleGNlZWRzIHRoZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS4=") Base64Decoder.decode("TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieSB0aGlzIHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYWxzLCB3aGljaCBpcyBhIGx1c3Qgb2YgdGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodCBpbiB0aGUgY29udGludWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZGdlLCBleGNlZWRzIHRoZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS4=")
); );
Base64Decoder decoder = new Base64Decoder(); Base64Decoder decoder = new Base64Decoder();
decoder.clear(); decoder.clear();
decoder.write("YW55IGNhcm5hbCBwbGVhc3VyZQ=="); decoder.read("YW55IGNhcm5hbCBwbGVhc3VyZQ==");
assertEquals( "any carnal pleasure", decoder.toString() ); assertEquals( "any carnal pleasure", decoder.toString() );
decoder.clear(); decoder.clear();
decoder.write("bGVhc3VyZS4="); decoder.read("bGVhc3VyZS4=");
assertEquals( "leasure.", decoder.toString() ); assertEquals( "leasure.", decoder.toString() );
decoder.clear(); decoder.clear();
decoder.write("YW55IGNhcm5hbCBwbGVhc3Vy"); decoder.read("YW55IGNhcm5hbCBwbGVhc3Vy");
assertEquals( "any carnal pleasur", decoder.toString() ); assertEquals( "any carnal pleasur", decoder.toString() );
decoder.clear(); decoder.clear();
} }
@Test
public void encode() {
/*assertEquals("TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieSB0aGlzIHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYWxzLCB3aGljaCBpcyBhIGx1c3Qgb2YgdGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodCBpbiB0aGUgY29udGludWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZGdlLCBleGNlZWRzIHRoZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS4=" ,
Base64Encoder.encode("Man is distinguished, not only by his reason, but by this singular passion from other animals, which is a lust of the mind, that by a perseverance of delight in the continued and indefatigable generation of knowledge, exceeds the short vehemence of any carnal pleasure.")
);*/
assertEquals("YW55IGNhcm5hbCBwbGVhc3VyZQ==", Base64Encoder.encode("any carnal pleasure"));
assertEquals("bGVhc3VyZS4=", Base64Encoder.encode("leasure."));
assertEquals("YW55IGNhcm5hbCBwbGVhc3Vy", Base64Encoder.encode("any carnal pleasur"));
}
@Test
public void encodeJavaUtil() {
/*assertEquals("TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieSB0aGlzIHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYWxzLCB3aGljaCBpcyBhIGx1c3Qgb2YgdGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodCBpbiB0aGUgY29udGludWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZGdlLCBleGNlZWRzIHRoZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS4=" ,
Base64.getEncoder().encodeToString("Man is distinguished, not only by his reason, but by this singular passion from other animals, which is a lust of the mind, that by a perseverance of delight in the continued and indefatigable generation of knowledge, exceeds the short vehemence of any carnal pleasure.".getBytes())
);*/
assertEquals("YW55IGNhcm5hbCBwbGVhc3VyZQ==", Base64.getEncoder().encodeToString("any carnal pleasure".getBytes()));
assertEquals("bGVhc3VyZS4=", Base64.getEncoder().encodeToString("leasure.".getBytes()));
assertEquals("YW55IGNhcm5hbCBwbGVhc3Vy", Base64.getEncoder().encodeToString("any carnal pleasur".getBytes()));
}
} }