/* * bitlet - Simple bittorrent library * Copyright (C) 2008 Alessandro Bahgat Shehata, Daniele Castagna * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.bitlet.wetorrent; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.nio.ByteBuffer; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.SortedMap; import java.util.TreeMap; import org.bitlet.wetorrent.bencode.Bencode; import org.bitlet.wetorrent.bencode.DictionaryComparator; import org.bitlet.wetorrent.util.Utils; public class Metafile extends Bencode { SortedMap rootDictionary; private SortedMap info; private String announce; private List announceList; private Long creationDate; private String comment; private String createdBy; private long pieceLength; private Long length; private List piecesSha = new LinkedList(); private List files = new LinkedList(); private String name; private byte[] infoSha1; private String infoSha1Encoded; /** * Creates a new instance of Metafile */ public Metafile(InputStream is) throws IOException, NoSuchAlgorithmException { super(is); rootDictionary = (SortedMap) getRootElement(); info = (SortedMap) rootDictionary.get(ByteBuffer.wrap("info".getBytes())); pieceLength = (Long) info.get(ByteBuffer.wrap("piece length".getBytes())); byte[] piecesByteString = ((ByteBuffer) info.get(ByteBuffer.wrap("pieces".getBytes()))).array(); for (int i = 0; i < piecesByteString.length; i += 20) { byte[] sha1 = new byte[20]; System.arraycopy(piecesByteString, i, sha1, 0, 20); piecesSha.add(sha1); } name = new String(((ByteBuffer) info.get(ByteBuffer.wrap("name".getBytes()))).array()); length = (Long) info.get(ByteBuffer.wrap("length".getBytes())); List files = (List) info.get(ByteBuffer.wrap("files".getBytes())); if (files != null) { length = new Long(0); for (Object fileObj : files) { Map file = (Map) fileObj; this.files.add(file); length += (Long) file.get(ByteBuffer.wrap("length".getBytes())); } } byte[] announceByteString = ((ByteBuffer) rootDictionary.get(ByteBuffer.wrap("announce".getBytes()))).array(); if (announceByteString != null) { announce = new String(announceByteString); } announceList = (List) rootDictionary.get(ByteBuffer.wrap("announce-list".getBytes())); creationDate = (Long) rootDictionary.get(ByteBuffer.wrap("creation date".getBytes())); ByteBuffer commentByteBuffer = (ByteBuffer) rootDictionary.get(ByteBuffer.wrap("comment".getBytes())); if (commentByteBuffer != null) { comment = new String(commentByteBuffer.array()); } ByteBuffer createdByByteBuffer = (ByteBuffer) rootDictionary.get(ByteBuffer.wrap("created by".getBytes())); if (createdByByteBuffer != null) { createdBy = new String(createdByByteBuffer.array()); } computeInfoSha1(); } public Metafile() { rootDictionary = new TreeMap(new DictionaryComparator()); setRootElement(rootDictionary); info = new TreeMap(new DictionaryComparator()); rootDictionary.put(ByteBuffer.wrap("info".getBytes()), getInfo()); announceList = new LinkedList(); } public SortedMap getInfo() { return info; } public void setInfo(SortedMap info) { this.info = info; } public String getAnnounce() { return announce; } public void setAnnounce(String announce) { this.announce = announce; } public List getAnnounceList() { return announceList; } public void setAnnounceList(List announceList) { this.announceList = announceList; } public Long getCreationDate() { return creationDate; } public void setCreationDate(Long creationDate) { this.creationDate = creationDate; } public String getComment() { return comment; } public void setComment(String comment) { this.comment = comment; } public String getCreatedBy() { return createdBy; } public void setCreatedBy(String createdBy) { this.createdBy = createdBy; } public Long getPieceLength() { return pieceLength; } public void setPieceLength(Long pieceLength) { this.pieceLength = pieceLength; } public List getPieces() { return piecesSha; } public void setPieces(List pieces) { this.piecesSha = pieces; } public void computeInfoSha1() throws NoSuchAlgorithmException, IOException { Bencode bencode = new Bencode(); bencode.setRootElement(info); MessageDigest md = MessageDigest.getInstance("SHA1"); ByteArrayOutputStream out = new ByteArrayOutputStream(); bencode.print(out); md.update(ByteBuffer.wrap(out.toByteArray())); infoSha1 = md.digest(); } public byte[] getInfoSha1() { return infoSha1; } public String getInfoSha1Encoded() { if (infoSha1Encoded == null) { infoSha1Encoded = Utils.byteArrayToURLString(getInfoSha1()); } return infoSha1Encoded; } public long getLength() { return length; } public String getName() { return name; } public void setName(String name) { this.name = name; } public List getFiles() { return files; } public boolean isSingleFile() { return (getFiles().size() == 0); } }