21 package com.google.appinventor.components.runtime.multidex;
 
   24 import java.io.IOException;
 
   25 import java.io.RandomAccessFile;
 
   26 import java.util.zip.CRC32;
 
   27 import java.util.zip.ZipException;
 
   33     static class CentralDirectory {
 
   40     private static final int ENDHDR = 22;
 
   41     private static final int ENDSIG = 0x6054b50;
 
   46     private static final int BUFFER_SIZE = 0x4000;
 
   54     static long getZipCrc(File apk) 
throws IOException {
 
   55         RandomAccessFile raf = 
new RandomAccessFile(apk, 
"r");
 
   57             CentralDirectory dir = findCentralDirectory(raf);
 
   59             return computeCrcOfCentralDir(raf, dir);
 
   66     static CentralDirectory findCentralDirectory(RandomAccessFile raf) 
throws IOException,
 
   68         long scanOffset = raf.length() - ENDHDR;
 
   70             throw new ZipException(
"File too short to be a zip file: " + raf.length());
 
   73         long stopOffset = scanOffset - 0x10000 ;
 
   78         int endSig = Integer.reverseBytes(ENDSIG);
 
   81             if (raf.readInt() == endSig) {
 
   86             if (scanOffset < stopOffset) {
 
   87                 throw new ZipException(
"End Of Central Directory signature not found");
 
   99         CentralDirectory dir = 
new CentralDirectory();
 
  100         dir.size = Integer.reverseBytes(raf.readInt()) & 0xFFFFFFFFL;
 
  101         dir.offset = Integer.reverseBytes(raf.readInt()) & 0xFFFFFFFFL;
 
  106     static long computeCrcOfCentralDir(RandomAccessFile raf, CentralDirectory dir)
 
  108         CRC32 crc = 
new CRC32();
 
  109         long stillToRead = dir.size;
 
  110         raf.seek(dir.offset);
 
  111         int length = (int) Math.min(BUFFER_SIZE, stillToRead);
 
  112         byte[] buffer = 
new byte[BUFFER_SIZE];
 
  113         length = raf.read(buffer, 0, length);
 
  114         while (length != -1) {
 
  115             crc.update(buffer, 0, length);
 
  116             stillToRead -= length;
 
  117             if (stillToRead == 0) {
 
  120             length = (int) Math.min(BUFFER_SIZE, stillToRead);
 
  121             length = raf.read(buffer, 0, length);
 
  123         return crc.getValue();