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(); } }
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); }