/* * Created on Oct 5, 2003 * Created by Paul Gardner * Modified Apr 13, 2004 by Alon Rohter * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.core3.torrent.impl; import java.io.*; import java.util.*; import org.gudy.azureus2.core3.torrent.*; import org.gudy.azureus2.core3.util.*; public class TOTorrentFileHasher { protected boolean do_other_per_file_hash; protected int piece_length; protected Vector pieces = new Vector(); protected byte[] buffer; protected int buffer_pos; protected SHA1Hasher overall_sha1_hash; // protected ED2KHasher overall_ed2k_hash; protected byte[] sha1_digest; protected byte[] ed2k_digest; protected byte[] per_file_sha1_digest; protected byte[] per_file_ed2k_digest; protected TOTorrentFileHasherListener listener; protected boolean cancelled; protected TOTorrentFileHasher( boolean _do_other_overall_hashes, boolean _do_other_per_file_hash, int _piece_length, TOTorrentFileHasherListener _listener ) { if ( _do_other_overall_hashes ){ overall_sha1_hash = new SHA1Hasher(); // overall_ed2k_hash = new ED2KHasher(); } do_other_per_file_hash = _do_other_per_file_hash; piece_length = _piece_length; listener = _listener; buffer = new byte[piece_length]; } long add( File _file ) throws TOTorrentException { long file_length = 0; InputStream is = null; SHA1Hasher sha1_hash = null; // ED2KHasher ed2k_hash = null; try{ if ( do_other_per_file_hash ){ sha1_hash = new SHA1Hasher(); // ed2k_hash = new ED2KHasher(); } is = new BufferedInputStream(new FileInputStream( _file ), 65536); while(true){ if ( cancelled ){ throw( new TOTorrentException( "TOTorrentCreate: operation cancelled", TOTorrentException.RT_CANCELLED )); } int len = is.read( buffer, buffer_pos, piece_length - buffer_pos ); if ( len > 0 ){ if ( do_other_per_file_hash ){ sha1_hash.update( buffer, buffer_pos, len ); // ed2k_hash.update( buffer, buffer_pos, len ); } file_length += len; buffer_pos += len; if ( buffer_pos == piece_length ){ // hash this piece byte[] hash = new SHA1Hasher().calculateHash(buffer); if ( overall_sha1_hash != null ){ overall_sha1_hash.update( buffer ); // overall_ed2k_hash.update( buffer ); } pieces.add( hash ); if ( listener != null ){ listener.pieceHashed( pieces.size() ); } buffer_pos = 0; } }else{ break; } } if ( do_other_per_file_hash ){ per_file_sha1_digest = sha1_hash.getDigest(); // per_file_ed2k_digest = ed2k_hash.getDigest(); } }catch( TOTorrentException e ){ throw( e ); }catch( Throwable e ){ throw( new TOTorrentException( "TOTorrentFileHasher: file read fails '" + e.toString() + "'", TOTorrentException.RT_READ_FAILS )); }finally { if (is != null) { try { is.close(); } catch (Exception e) { } } } return( file_length ); } protected byte[] getPerFileSHA1Digest() { return( per_file_sha1_digest ); } protected byte[] getPerFileED2KDigest() { return( per_file_ed2k_digest ); } protected byte[][] getPieces() throws TOTorrentException { try{ if ( buffer_pos > 0 ){ byte[] rem = new byte[buffer_pos]; System.arraycopy( buffer, 0, rem, 0, buffer_pos ); pieces.addElement(new SHA1Hasher().calculateHash(rem)); if ( overall_sha1_hash != null ){ overall_sha1_hash.update( rem ); // overall_ed2k_hash.update( rem ); } if ( listener != null ){ listener.pieceHashed( pieces.size() ); } buffer_pos = 0; } if ( overall_sha1_hash != null && sha1_digest == null ){ sha1_digest = overall_sha1_hash.getDigest(); // ed2k_digest = overall_ed2k_hash.getDigest(); } byte[][] res = new byte[pieces.size()][]; pieces.copyInto( res ); return( res ); }catch( Throwable e ){ throw( new TOTorrentException( "TOTorrentFileHasher: file read fails '" + e.toString() + "'", TOTorrentException.RT_READ_FAILS )); } } protected byte[] getED2KDigest() throws TOTorrentException { if ( ed2k_digest == null ){ getPieces(); } return( ed2k_digest ); } protected byte[] getSHA1Digest() throws TOTorrentException { if ( sha1_digest == null ){ getPieces(); } return( sha1_digest ); } protected void cancel() { cancelled = true; } }