import java.util.ArrayList; import java.util.Arrays; /** * Created : May 27, 2012 * * @author pquiring */ public class MetaFile { private byte metaData[]; private ArrayList<MetaTag> metaList; public int tagBegin, tagEnd; //set by getTag() private int metaIdx; public void read(byte data[]) throws Exception { metaData = data; metaIdx = 0; metaList = new ArrayList<MetaTag>(); readMeta(metaList); } private void readMeta(ArrayList<MetaTag> list) throws Exception { while (metaIdx < metaData.length) { MetaTag tag = new MetaTag(); tag.pos = metaIdx; if ((metaData[metaIdx] >= '0') && (metaData[metaIdx] <= '9')) { //string length:string data String str = ""; while (metaData[metaIdx] != ':') { str += (char)metaData[metaIdx++]; } metaIdx++; int strLength = Integer.valueOf(str); tag.obj = Arrays.copyOfRange(metaData, metaIdx, metaIdx + strLength); list.add(tag); metaIdx += strLength; if (strLength < 128) { // if (log) JFLog.log(" create:s:" + new String((byte[])list.get(list.size()-1).obj)); } else { // if (log) JFLog.log(" create:s: ...long string..."); } continue; } switch (metaData[metaIdx++]) { case 'i': //integer String str = ""; while (metaData[metaIdx] != 'e') { str += (char)metaData[metaIdx++]; } metaIdx++; tag.obj = Long.valueOf(str); list.add(tag); // if (log) JFLog.log(" create:i:" + tag.obj); break; case 'd': //dict // if (log) JFLog.log(" create:d"); ArrayList<MetaTag> dict = new ArrayList<MetaTag>(); tag.obj = dict; list.add(tag); readMeta(dict); tag.endpos = metaIdx-1; break; case 'l': //list (handled same as dict) // if (log) JFLog.log(" create:l"); ArrayList<MetaTag> sublist = new ArrayList<MetaTag>(); tag.obj = sublist; list.add(tag); readMeta(sublist); tag.endpos = metaIdx-1; break; case 'e': // if (log) JFLog.log(" end"); return; default: throw new Exception("bad torrent"); } } } public Object getTag(String path[]) throws Exception { return getTag(path, metaList); } public Object getTag(String path[], ArrayList<MetaTag> list) throws Exception { int pathIdx = 0; while (pathIdx < path.length) { int listLength = list.size(); if (path[pathIdx].equals("d")) { // if (log) JFLog.log("getTag:d0:length=" + listLength); list = (ArrayList<MetaTag>)list.get(0).obj; pathIdx++; continue; } if (path[pathIdx].startsWith("d:")) { // if (log) JFLog.log("getTag:d:length=" + listLength); boolean found = false; for(int a=0;a<listLength;a++) { Object o = list.get(a).obj; if (o instanceof byte[]) { String s = new String((byte[])o, "UTF-8"); if (s.equals(path[pathIdx].substring(2))) { if (pathIdx == path.length-1) { return list.get(a+1).obj; } else { list = (ArrayList<MetaTag>)list.get(a+1).obj; pathIdx++; found = true; break; } } } } if (!found) return null; continue; } if (path[pathIdx].startsWith("s:")) { // if (log) JFLog.log("getTag:s"); for(int a=0;a<listLength;a++) { Object o = list.get(a).obj; if (o instanceof byte[]) { String s = new String((byte[])o, "UTF-8"); if (s.equals(path[pathIdx].substring(2))) { tagBegin = list.get(a+1).pos; tagEnd = list.get(a+1).endpos; return list.get(a+1).obj; } } } return null; } if (path[pathIdx].startsWith("i:")) { // if (log) JFLog.log("getTag:i"); for(int a=0;a<listLength;a++) { Object o = list.get(a).obj; if (o instanceof byte[]) { String s = new String((byte[])o, "UTF-8"); if (s.equals(path[pathIdx].substring(2))) { return list.get(a+1).obj; } } } return null; } if (path[pathIdx].startsWith("l:")) { // if (log) JFLog.log("getTag:l:length=" + listLength); boolean found = false; for(int a=0;a<listLength;a++) { Object o = list.get(a).obj; if (o instanceof byte[]) { String s = new String((byte[])o, "UTF-8"); if (s.equals(path[pathIdx].substring(2))) { if (pathIdx == path.length-1) { return list.get(a+1).obj; } else { list = (ArrayList<MetaTag>)list.get(a+1).obj; pathIdx++; found = true; break; //out of for loop } } } } if (!found) return null; continue; } } return null; } }