Пример #1
0
    private void buildIndex() throws IOException {
      int entryCount = get2ByteLittleEndian(zipDir, 0);

      // Add each of the files
      if (entryCount > 0) {
        directories = new HashMap<RelativeDirectory, DirectoryEntry>();
        ArrayList<Entry> entryList = new ArrayList<Entry>();
        int pos = 2;
        for (int i = 0; i < entryCount; i++) {
          pos = readEntry(pos, entryList, directories);
        }

        // Add the accumulated dirs into the same list
        for (RelativeDirectory d : directories.keySet()) {
          // use shared RelativeDirectory objects for parent dirs
          RelativeDirectory parent = getRelativeDirectory(d.dirname().getPath());
          String file = d.basename();
          Entry zipFileIndexEntry = new Entry(parent, file);
          zipFileIndexEntry.isDir = true;
          entryList.add(zipFileIndexEntry);
        }

        entries = entryList.toArray(new Entry[entryList.size()]);
        Arrays.sort(entries);
      } else {
        cleanupState();
      }
    }
Пример #2
0
 public int compareTo(Entry other) {
   RelativeDirectory otherD = other.dir;
   if (dir != otherD) {
     int c = dir.compareTo(otherD);
     if (c != 0) return c;
   }
   return name.compareTo(other.name);
 }
Пример #3
0
  ZipFileIndex(
      File zipFile,
      RelativeDirectory symbolFilePrefix,
      boolean writeIndex,
      boolean useCache,
      String cacheLocation)
      throws IOException {
    this.zipFile = zipFile;
    this.symbolFilePrefix = symbolFilePrefix;
    this.symbolFilePrefixLength =
        (symbolFilePrefix == null ? 0 : symbolFilePrefix.getPath().getBytes("UTF-8").length);
    this.writeIndex = writeIndex;
    this.usePreindexedCache = useCache;
    this.preindexedCacheLocation = cacheLocation;

    if (zipFile != null) {
      this.zipFileLastModified = zipFile.lastModified();
    }

    // Validate integrity of the zip file
    checkIndex();
  }
Пример #4
0
  private boolean writeIndex() {
    boolean ret = false;
    if (readFromIndex || !usePreindexedCache) {
      return true;
    }

    if (!writeIndex) {
      return true;
    }

    File indexFile = getIndexFile();
    if (indexFile == null) {
      return false;
    }

    RandomAccessFile raf = null;
    long writtenSoFar = 0;
    try {
      raf = new RandomAccessFile(indexFile, "rw");

      raf.writeLong(zipFileLastModified);
      writtenSoFar += 8;

      List<DirectoryEntry> directoriesToWrite = new ArrayList<DirectoryEntry>();
      Map<RelativeDirectory, Long> offsets = new HashMap<RelativeDirectory, Long>();
      raf.writeInt(directories.keySet().size());
      writtenSoFar += 4;

      for (RelativeDirectory dirName : directories.keySet()) {
        DirectoryEntry dirEntry = directories.get(dirName);

        directoriesToWrite.add(dirEntry);

        // Write the dir name bytes
        byte[] dirNameBytes = dirName.getPath().getBytes("UTF-8");
        int dirNameBytesLen = dirNameBytes.length;
        raf.writeInt(dirNameBytesLen);
        writtenSoFar += 4;

        raf.write(dirNameBytes);
        writtenSoFar += dirNameBytesLen;

        // Write the number of files in the dir
        List<Entry> dirEntries = dirEntry.getEntriesAsCollection();
        raf.writeInt(dirEntries.size());
        writtenSoFar += 4;

        offsets.put(dirName, new Long(writtenSoFar));

        // Write the offset of the file's data in the dir
        dirEntry.writtenOffsetOffset = 0L;
        raf.writeLong(0L);
        writtenSoFar += 8;
      }

      for (DirectoryEntry de : directoriesToWrite) {
        // Fix up the offset in the directory table
        long currFP = raf.getFilePointer();

        long offsetOffset = offsets.get(de.dirName).longValue();
        raf.seek(offsetOffset);
        raf.writeLong(writtenSoFar);

        raf.seek(currFP);

        // Now write each of the files in the DirectoryEntry
        List<Entry> list = de.getEntriesAsCollection();
        for (Entry zfie : list) {
          // Write the name bytes
          byte[] zfieNameBytes = zfie.name.getBytes("UTF-8");
          int zfieNameBytesLen = zfieNameBytes.length;
          raf.writeInt(zfieNameBytesLen);
          writtenSoFar += 4;
          raf.write(zfieNameBytes);
          writtenSoFar += zfieNameBytesLen;

          // Write isDir
          raf.writeByte(zfie.isDir ? (byte) 1 : (byte) 0);
          writtenSoFar += 1;

          // Write offset of bytes in the real Jar/Zip file
          raf.writeInt(zfie.offset);
          writtenSoFar += 4;

          // Write size of the file in the real Jar/Zip file
          raf.writeInt(zfie.size);
          writtenSoFar += 4;

          // Write compressed size of the file in the real Jar/Zip file
          raf.writeInt(zfie.compressedSize);
          writtenSoFar += 4;

          // Write java time stamp of the file in the real Jar/Zip file
          raf.writeLong(zfie.getLastModified());
          writtenSoFar += 8;
        }
      }
    } catch (Throwable t) {
      // Do nothing
    } finally {
      try {
        if (raf != null) {
          raf.close();
        }
      } catch (IOException ioe) {
        // Do nothing
      }
    }

    return ret;
  }
Пример #5
0
    private int readEntry(
        int pos, List<Entry> entryList, Map<RelativeDirectory, DirectoryEntry> directories)
        throws IOException {
      if (get4ByteLittleEndian(zipDir, pos) != 0x02014b50) {
        throw new ZipException("cannot read zip file entry");
      }

      int dirStart = pos + 46;
      int fileStart = dirStart;
      int fileEnd = fileStart + get2ByteLittleEndian(zipDir, pos + 28);

      if (zipFileIndex.symbolFilePrefixLength != 0
          && ((fileEnd - fileStart) >= symbolFilePrefixLength)) {
        dirStart += zipFileIndex.symbolFilePrefixLength;
        fileStart += zipFileIndex.symbolFilePrefixLength;
      }
      // Force any '\' to '/'. Keep the position of the last separator.
      for (int index = fileStart; index < fileEnd; index++) {
        byte nextByte = zipDir[index];
        if (nextByte == (byte) '\\') {
          zipDir[index] = (byte) '/';
          fileStart = index + 1;
        } else if (nextByte == (byte) '/') {
          fileStart = index + 1;
        }
      }

      RelativeDirectory directory = null;
      if (fileStart == dirStart) directory = getRelativeDirectory("");
      else if (lastDir != null && lastLen == fileStart - dirStart - 1) {
        int index = lastLen - 1;
        while (zipDir[lastStart + index] == zipDir[dirStart + index]) {
          if (index == 0) {
            directory = lastDir;
            break;
          }
          index--;
        }
      }

      // Sub directories
      if (directory == null) {
        lastStart = dirStart;
        lastLen = fileStart - dirStart - 1;

        directory = getRelativeDirectory(new String(zipDir, dirStart, lastLen, "UTF-8"));
        lastDir = directory;

        // Enter also all the parent directories
        RelativeDirectory tempDirectory = directory;

        while (directories.get(tempDirectory) == null) {
          directories.put(tempDirectory, new DirectoryEntry(tempDirectory, zipFileIndex));
          if (tempDirectory.path.indexOf("/") == tempDirectory.path.length() - 1) break;
          else {
            // use shared RelativeDirectory objects for parent dirs
            tempDirectory = getRelativeDirectory(tempDirectory.dirname().getPath());
          }
        }
      } else {
        if (directories.get(directory) == null) {
          directories.put(directory, new DirectoryEntry(directory, zipFileIndex));
        }
      }

      // For each dir create also a file
      if (fileStart != fileEnd) {
        Entry entry =
            new Entry(directory, new String(zipDir, fileStart, fileEnd - fileStart, "UTF-8"));

        entry.setNativeTime(get4ByteLittleEndian(zipDir, pos + 12));
        entry.compressedSize = get4ByteLittleEndian(zipDir, pos + 20);
        entry.size = get4ByteLittleEndian(zipDir, pos + 24);
        entry.offset = get4ByteLittleEndian(zipDir, pos + 42);
        entryList.add(entry);
      }

      return pos
          + 46
          + get2ByteLittleEndian(zipDir, pos + 28)
          + get2ByteLittleEndian(zipDir, pos + 30)
          + get2ByteLittleEndian(zipDir, pos + 32);
    }
Пример #6
0
 @Override
 public boolean equals(Object o) {
   if (!(o instanceof Entry)) return false;
   Entry other = (Entry) o;
   return dir.equals(other.dir) && name.equals(other.name);
 }