import java.io.*; // input/output classes import java.util.zip.CRC32; // CRC checksumming import java.util.Properties; // Hashtable import java.util.Enumeration; // Enumeration for the hashtable import java.net.*; // internet sockets class CRCRepair { private String CRCPropertiesFile; // contains the CRC values, filename, and mirror private String File2Test; // the file to check private Properties failedCRCTest = new Properties(); // hashtable of failed sections private String mirror; // URL of the file (HTTP only) private String totalsize; // total size of the File2Test CRCRepair(String crcfile){ // Constructor CRCPropertiesFile = crcfile; } public static void main(String[] Args){ // main if(Args.length==0){ // no arguments supplied System.out.println("Usage:"); System.out.println("java crcrepair [filename]\tChecks the file whose CRC values are stated in [filename]"); System.out.println("java crcrepair --make [file] [filename]\tCreates a valid profile of [file] in [filename] holding CRC values"); System.exit(0); }else if(Args.length==1){ // one argument supplied CRCRepair crcr = new CRCRepair(Args[0]); crcr.examine(); }else if(Args[0].compareTo("--make")==0){ // "make" arguement supplied CRCRepair crcr = new CRCRepair(Args[2]); crcr.make(Args[1]); } } public void examine(){ // examine a file try{ BufferedReader props = new BufferedReader(new FileReader(CRCPropertiesFile)); // the Filename, Mirror, and CRC values File2Test = props.readLine(); // read the Filename and parse it File2Test = File2Test.substring(File2Test.indexOf(":")+1).trim(); FileInputStream testfile = new FileInputStream(File2Test); // open the file long index = 0; // position is at the beginning of the file long filelen = (new File(File2Test)).length(); // set the size of the file (long) totalsize = Long.toString(filelen); // set the size of the file (String) mirror = props.readLine(); // set the mirror of the file String line = props.readLine(); while(line != null){ // for each line in the profile, CRC32 checksum = new CRC32(); // make a CRC checking object long checksumresult = Long.parseLong(line.substring(line.indexOf(":")+1).trim()); // get the expected checksum result int size = Integer.parseInt(line.substring(line.indexOf("[")+1, line.indexOf("]"))); // get the number of bytes in the CRC byte[] input = new byte[size]; // create a byte buffer testfile.read(input); // read into the byte buffer checksum.update(input); // add the bytes to the CRC checker System.out.println((checksum.getValue() == checksumresult)?"Passed CRC":"Failed CRC!"); // show the result of the check if(checksum.getValue() != checksumresult){ // compare the result to the expected result failedCRCTest.setProperty(Long.toString(index), Integer.toString(size)); // it failed the test -- add an entry to the hashtable System.out.println("Failure noted: starting index " + index + ", size " + size + " bytes"); // notify the user which range } line = props.readLine(); // read in another line index += size; // move the index } fixit(); // attempt to fix any checksum failures System.out.println("Press return to exit."); // all done System.in.read(); }catch(Exception e){ // catch and print any exceptions e.printStackTrace(); } } public void fixit() throws Exception { Enumeration keys = failedCRCTest.propertyNames(); // list all the hashtable elements while(keys.hasMoreElements()){ // while there are elements String key = (String)keys.nextElement(); // get the next one download(key, failedCRCTest.getProperty(key), totalsize); // attempt to download the portion that failed } } public void download(String start, String size, String total) throws Exception { System.out.println("Downloading the section starting at " + start + " with a length of " + size + " bytes"); // notify of download Socket http = new Socket(mirror.substring(mirror.indexOf(":")+1, mirror.indexOf(",")).trim(), 80); // parse the site PrintWriter pw = new PrintWriter(http.getOutputStream(), true); // make an outstream InputStream is = http.getInputStream(); // get an instream pw.println("GET " + mirror.substring(mirror.indexOf(",")+1).trim() + " HTTP/1.1"); // send the HTTP/1.1 request pw.println("Host: " + mirror.substring(mirror.indexOf(":")+1, mirror.indexOf(",")).trim()); pw.println("Range: bytes=" + start + "-" + (Integer.parseInt(start) + Integer.parseInt(size))); // with the correct range pw.println("Connection: close"); pw.println(); RandomAccessFile raf = new RandomAccessFile(File2Test, "rw"); // open the corrupted file with the ability to seek throughout raf.seek(Integer.parseInt(start)); // seek to the beginning of the corrupted data String line = ""; while(line.endsWith("\r\n\r\n")==false){ // read through the HTTP/1.1 headers line += (char)is.read(); } System.out.print("0%"); // here we go byte[] buf = new byte[6144]; // create a byte buffer int inp = is.read(buf); // read to it int count = 0; // keep track of % done while(inp != -1){ // while there's more for(int i=0; i