124 lines
3.6 KiB
Java
124 lines
3.6 KiB
Java
|
|
package zutil.network.torrent;
|
||
|
|
|
||
|
|
import java.io.FileNotFoundException;
|
||
|
|
import java.io.IOException;
|
||
|
|
import java.util.HashMap;
|
||
|
|
import java.util.LinkedList;
|
||
|
|
|
||
|
|
import zutil.FileFinder;
|
||
|
|
import zutil.MultiPrintStream;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* http://wiki.theory.org/BitTorrentSpecification
|
||
|
|
* @author Ziver
|
||
|
|
*
|
||
|
|
*/
|
||
|
|
public class TorrentParser {
|
||
|
|
/**
|
||
|
|
* Example use
|
||
|
|
*/
|
||
|
|
public static void main(String[] args){
|
||
|
|
try {
|
||
|
|
String tmp = FileFinder.getFileContent(FileFinder.find("C:\\Users\\Ziver\\Desktop\\test.torrent"));
|
||
|
|
MultiPrintStream.out.dump(TorrentParser.decode(tmp));
|
||
|
|
|
||
|
|
} catch (FileNotFoundException e) {
|
||
|
|
e.printStackTrace();
|
||
|
|
} catch (IOException e) {
|
||
|
|
e.printStackTrace();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Returns the representation of the data in the BEncoded string
|
||
|
|
*
|
||
|
|
* @param data The data to be decoded
|
||
|
|
* @return
|
||
|
|
*/
|
||
|
|
public static Object decode(String data){
|
||
|
|
return decode_BEncoded(new StringBuffer(data));
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Returns the representation of the data in the BEncoded string
|
||
|
|
*
|
||
|
|
* @param data The data to be decoded
|
||
|
|
* @param index The index in data to start from
|
||
|
|
* @return
|
||
|
|
*/
|
||
|
|
@SuppressWarnings("unchecked")
|
||
|
|
private static Object decode_BEncoded(StringBuffer data){
|
||
|
|
String tmp;
|
||
|
|
char c = ' ';
|
||
|
|
|
||
|
|
switch (data.charAt(0)) {
|
||
|
|
/**
|
||
|
|
* Integers are prefixed with an i and terminated by an e. For
|
||
|
|
* example, 123 would bEcode to i123e, -3272002 would bEncode to
|
||
|
|
* i-3272002e.
|
||
|
|
*/
|
||
|
|
case 'i':
|
||
|
|
//System.out.println("Found Integer at "+index);
|
||
|
|
data.deleteCharAt(0);
|
||
|
|
tmp = data.substring(0, data.indexOf("e"));
|
||
|
|
data.delete(0, tmp.length() + 1);
|
||
|
|
//System.out.println(tmp);
|
||
|
|
return new Long(tmp);
|
||
|
|
/**
|
||
|
|
* Lists are prefixed with a l and terminated by an e. The list
|
||
|
|
* should contain a series of bEncoded elements. For example, the
|
||
|
|
* list of strings ["Monduna", "Bit", "Torrents"] would bEncode to
|
||
|
|
* l7:Monduna3:Bit8:Torrentse. The list [1, "Monduna", 3, ["Sub", "List"]]
|
||
|
|
* would bEncode to li1e7:Mondunai3el3:Sub4:Listee
|
||
|
|
*/
|
||
|
|
case 'l':
|
||
|
|
//System.out.println("Found List at "+index);
|
||
|
|
data.deleteCharAt(0);
|
||
|
|
LinkedList list = new LinkedList();
|
||
|
|
c = data.charAt(0);
|
||
|
|
while(c != 'e'){
|
||
|
|
list.add(decode_BEncoded(data));
|
||
|
|
c = data.charAt(0);
|
||
|
|
}
|
||
|
|
data.deleteCharAt(0);
|
||
|
|
//MultiPrintStream.out.dump(list);
|
||
|
|
if(list.size() == 1) return list.poll();
|
||
|
|
else return list;
|
||
|
|
/**
|
||
|
|
* Dictionaries are prefixed with a d and terminated by an e. They
|
||
|
|
* are similar to list, except that items are in key value pairs. The
|
||
|
|
* dictionary {"key":"value", "Monduna":"com", "bit":"Torrents", "number":7}
|
||
|
|
* would bEncode to d3:key5:value7:Monduna3:com3:bit:8:Torrents6:numberi7ee
|
||
|
|
*/
|
||
|
|
case 'd':
|
||
|
|
//System.out.println("Found Dictionary at "+index);
|
||
|
|
data.deleteCharAt(0);
|
||
|
|
HashMap map = new HashMap();
|
||
|
|
c = data.charAt(0);
|
||
|
|
while(c != 'e'){
|
||
|
|
Object tmp2 = decode_BEncoded(data);
|
||
|
|
map.put(tmp2, decode_BEncoded(data));
|
||
|
|
c = data.charAt(0);
|
||
|
|
}
|
||
|
|
data.deleteCharAt(0);
|
||
|
|
//MultiPrintStream.out.dump(map);
|
||
|
|
return map;
|
||
|
|
/**
|
||
|
|
* Strings are prefixed with their length followed by a colon.
|
||
|
|
* For example, "Monduna" would bEncode to 7:Monduna and "BitTorrents"
|
||
|
|
* would bEncode to 11:BitTorrents.
|
||
|
|
*/
|
||
|
|
default:
|
||
|
|
//System.out.println("Found String at "+index);
|
||
|
|
tmp = data.substring(0, data.indexOf(":"));
|
||
|
|
int length = Integer.parseInt(tmp);
|
||
|
|
data.delete(0, tmp.length()+1);
|
||
|
|
String ret = data.substring(0, length);
|
||
|
|
data.delete(0, length);
|
||
|
|
//System.out.println(data.substring(i, i+length));
|
||
|
|
return ret;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|