// package com.adarshr.raroscope; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.util.Calendar; import java.util.Date; import java.util.Enumeration; /** * Represents a RAR archive. * <p> * This class is used to enumerate the entries in a RAR file. * @author Adarsh Ramamurthy * @version 1.0, 10th March 2008 */ public class RARFile { /** * The underlying stream. */ InputStream stream; /** * Marker block of RAR archives. It is "Rar!" in reverse bytes. */ private static final long MARKER=0x21726152L; /** * To hold the available bytes in the stream. */ long available; /** * Constructs an instance of <tt>RARFile</tt> for performing operations * on the archive. * @param name the RAR file name. * @throws IOException in case of errors reading from the archive. */ public RARFile( String name) throws IOException { this(new File(name)); } /** * Constructs an instance of <tt>RARFile</tt> for performing operations * on the archive. * @param file the RAR file. * @throws IOException in case of errors reading from the archive. */ public RARFile( File file) throws IOException { this.stream=new FileInputStream(file); this.available=this.stream.available(); byte[] headers=new byte[7 + 13]; this.stream.read(headers); if (MARKER != getLong(headers,0,3)) { throw new IOException("Invalid RAR archive"); } } /** * Closes the archive. * @throws IOException in case of errors while closing. */ public void close() throws IOException { this.stream.close(); } /** * Converts the input inverted array of bytes to a long representation. * @param bytes the byte array to be converted. * @return the long value. */ protected long getLong( byte[] bytes){ long ret=0; long mask=0; for (int i=0; i < bytes.length; i++) { ret|=(bytes[i] & 0xFF) << (8 * i); mask=(mask << 8) | 0xFF; } return ret & mask; } /** * Converts the input inverted array of bytes to a long representation. * Conversion is done inclusive of both the limits specified. * @param bytes the byte array to be converted. * @param start the index to start with. * @param end the end index. * @return the long value. */ protected long getLong( byte[] bytes, int start, int end){ long ret=0; long mask=0; if (start < 0 || end >= bytes.length) { return ret; } for (int i=start, j=0; i <= end; i++, j++) { ret|=(bytes[i] & 0xFF) << (8 * j); mask=(mask << 8) | 0xFF; } return ret & mask; } /** * Converts the DOS time to Java date. * @param dosTime MS DOS format time. * @return an instance of <tt>Date</tt>. */ protected Date toDate( long dosTime){ Calendar calendar=Calendar.getInstance(); calendar.set((int)(((dosTime >> 25) & 0x7f) + 1980),(int)(((dosTime >> 21) & 0x0f) - 1),(int)((dosTime >> 16) & 0x1f),(int)((dosTime >> 11) & 0x1f),(int)((dosTime >> 5) & 0x3f),(int)((dosTime << 1) & 0x3e)); return calendar.getTime(); } /** * Translates the compression method into a string. * @param m the compression method number. * @return the compression method string. */ protected String toMethod( int m){ String method=null; switch (m) { case 0x30: method="Storing"; break; case 0x31: method="Fastest Compression"; break; case 0x32: method="Fast Compression"; break; case 0x33: method="Normal Compression"; break; case 0x34: method="Good Compression"; break; case 0x35: method="Best Compression"; break; default : method="Unknown"; break; } return method; } }