ZipInflaterpublic final class ZipInflater extends Object A class that can inflate a zip archive. |
Fields Summary |
---|
private static final String | TAGLogging tag | private static final int | BUFFER_SIZE_BYTESThe size of the buffer used to read from the archive. | private static final String | PATH_NAVIGATION_COMPONENTThe path navigation component (i.e. "../"). | private static final String | DATA_PARTITION_ROOTThe root of the data partition. | private static final long | SIZE_MULTIPLIERWe need two be able to store two versions of gears in parallel:
- the zipped version
- the unzipped version, which will be loaded next time the browser is started.
We are conservative and do not attempt to unpack unless there enough free
space on the device to store 4 times the new Gears size. |
Methods Summary |
---|
private static final long | freeSpace()
StatFs data_partition = new StatFs(DATA_PARTITION_ROOT);
long freeSpace = data_partition.getAvailableBlocks() *
data_partition.getBlockSize();
Log.i(TAG, "Free space on the data partition: " + freeSpace);
return freeSpace;
| public static boolean | inflate(java.lang.String filename, java.lang.String path)Unzips the archive with the given name.
Log.i(TAG, "Extracting " + filename + " to " + path);
// Check that the path ends with a separator.
if (!path.endsWith(File.separator)) {
Log.e(TAG, "Path missing trailing separator: " + path);
return false;
}
boolean result = false;
// Use a ZipFile to get an enumeration of the entries and
// calculate the overall uncompressed size of the archive. Also
// check for existing files or directories that have the same
// name as the entries in the archive. Also check for invalid
// entry names (e.g names that attempt to navigate to the
// parent directory).
ZipInputStream zipStream = null;
long uncompressedSize = 0;
try {
ZipFile zipFile = new ZipFile(filename);
try {
Enumeration entries = zipFile.entries();
while (entries.hasMoreElements()) {
ZipEntry entry = (ZipEntry) entries.nextElement();
uncompressedSize += entry.getSize();
// Check against entry names that may attempt to navigate
// out of the destination directory.
if (entry.getName().indexOf(PATH_NAVIGATION_COMPONENT) >= 0) {
throw new IOException("Illegal entry name: " + entry.getName());
}
// Check against entries with the same name as pre-existing files or
// directories.
File file = new File(path + entry.getName());
if (file.exists()) {
// A file or directory with the same name already exist.
// This must not happen, so we treat this as an error.
throw new IOException(
"A file or directory with the same name already exists.");
}
}
} finally {
zipFile.close();
}
Log.i(TAG, "Determined uncompressed size: " + uncompressedSize);
// Check we have enough space to unpack this archive.
if (freeSpace() <= uncompressedSize * SIZE_MULTIPLIER) {
throw new IOException("Not enough space to unpack this archive.");
}
zipStream = new ZipInputStream(
new BufferedInputStream(new FileInputStream(filename)));
ZipEntry entry;
int counter;
byte buffer[] = new byte[BUFFER_SIZE_BYTES];
// Iterate through the entries and write each of them to a file.
while ((entry = zipStream.getNextEntry()) != null) {
File file = new File(path + entry.getName());
if (entry.isDirectory()) {
// If the entry denotes a directory, we need to create a
// directory with the same name.
file.mkdirs();
} else {
CRC32 checksum = new CRC32();
BufferedOutputStream output = new BufferedOutputStream(
new FileOutputStream(file),
BUFFER_SIZE_BYTES);
try {
// Read the entry and write it to the file.
while ((counter = zipStream.read(buffer, 0, BUFFER_SIZE_BYTES)) !=
-1) {
output.write(buffer, 0, counter);
checksum.update(buffer, 0, counter);
}
output.flush();
} finally {
output.close();
}
if (checksum.getValue() != entry.getCrc()) {
throw new IOException(
"Integrity check failed for: " + entry.getName());
}
}
zipStream.closeEntry();
}
result = true;
} catch (FileNotFoundException ex) {
Log.e(TAG, "The zip file could not be found. " + ex);
} catch (IOException ex) {
Log.e(TAG, "Could not read or write an entry. " + ex);
} catch(IllegalArgumentException ex) {
Log.e(TAG, "Could not create the BufferedOutputStream. " + ex);
} finally {
if (zipStream != null) {
try {
zipStream.close();
} catch (IOException ex) {
// Ignored.
}
}
// Discard any exceptions and return the result to the native side.
return result;
}
|
|