summaryrefslogtreecommitdiff
path: root/Userland
diff options
context:
space:
mode:
authorAnotherTest <ali.mpfard@gmail.com>2020-07-13 12:38:59 +0430
committerAndreas Kling <kling@serenityos.org>2020-07-13 15:28:54 +0200
commit3a7a689b87d85948b10b769ea5b562c90c6be63a (patch)
tree1be409a95d8f49a95365a6310d0e593f5f6a43ca /Userland
parent6a265f7c212add181fae76c6d67546045d00f559 (diff)
downloadserenity-3a7a689b87d85948b10b769ea5b562c90c6be63a.zip
unzip: Remove some magic numbers and create directories when needed
This commit also adds an assert about the compression method instead of just writing out the compressed data.
Diffstat (limited to 'Userland')
-rw-r--r--Userland/unzip.cpp85
1 files changed, 63 insertions, 22 deletions
diff --git a/Userland/unzip.cpp b/Userland/unzip.cpp
index d14f6ca660..453d20abf2 100644
--- a/Userland/unzip.cpp
+++ b/Userland/unzip.cpp
@@ -64,49 +64,90 @@ bool find_next_central_directory(off_t file_size, const MappedFile& file, off_t
bool unpack_file_for_central_directory_index(off_t central_directory_index, const MappedFile& file)
{
+ enum CentralFileDirectoryHeaderOffsets {
+ CFDHCompressionMethodOffset = 10,
+ CFDHLocalFileHeaderIndexOffset = 42,
+ };
+ enum LocalFileHeaderOffsets {
+ LFHCompressionMethodOffset = 10,
+ LFHCompressedSizeOffset = 18,
+ LFHFileNameLengthOffset = 26,
+ LFHExtraFieldLengthOffset = 28,
+ LFHFileNameBaseOffset = 30,
+ };
+ enum CompressionMethod {
+ None = 0,
+ Shrunk = 1,
+ Factor1 = 2,
+ Factor2 = 3,
+ Factor3 = 4,
+ Factor4 = 5,
+ Implode = 6,
+ Deflate = 8,
+ EnhancedDeflate = 9,
+ PKWareDCLImplode = 10,
+ BZIP2 = 12,
+ LZMA = 14,
+ TERSE = 18,
+ LZ77 = 19,
+ };
+
u8 buffer[4];
- if (!seek_and_read(buffer, file, central_directory_index + 42, 4))
+ if (!seek_and_read(buffer, file, central_directory_index + CFDHLocalFileHeaderIndexOffset, 4))
return false;
off_t local_file_header_index = buffer[3] << 24 | buffer[2] << 16 | buffer[1] << 8 | buffer[0];
- if (!seek_and_read(buffer, file, local_file_header_index + 18, 4))
+ if (!seek_and_read(buffer, file, local_file_header_index + LFHCompressionMethodOffset, 2))
+ return false;
+ auto compression_method = buffer[1] << 8 | buffer[0];
+ // FIXME: Remove once any decompression is supported.
+ ASSERT(compression_method == None);
+
+ if (!seek_and_read(buffer, file, local_file_header_index + LFHCompressedSizeOffset, 4))
return false;
off_t compressed_file_size = buffer[3] << 24 | buffer[2] << 16 | buffer[1] << 8 | buffer[0];
- if (!seek_and_read(buffer, file, local_file_header_index + 26, 2))
+ if (!seek_and_read(buffer, file, local_file_header_index + LFHFileNameLengthOffset, 2))
return false;
off_t file_name_length = buffer[1] << 8 | buffer[0];
- if (!seek_and_read(buffer, file, local_file_header_index + 28, 2))
+ if (!seek_and_read(buffer, file, local_file_header_index + LFHExtraFieldLengthOffset, 2))
return false;
off_t extra_field_length = buffer[1] << 8 | buffer[0];
- if (!seek_and_read(buffer, file, local_file_header_index + 30, file_name_length))
+ if (!seek_and_read(buffer, file, local_file_header_index + LFHFileNameBaseOffset, file_name_length))
return false;
char file_name[file_name_length + 1];
memcpy(file_name, buffer, file_name_length);
file_name[file_name_length] = '\0';
- auto new_file = Core::File::construct(String { file_name });
- if (!new_file->open(Core::IODevice::WriteOnly)) {
- fprintf(stderr, "Can't write file %s: %s\n", file_name, new_file->error_string());
- return false;
- }
+ if (file_name[file_name_length - 1] == '/') {
+ if (mkdir(file_name, 0755) < 0) {
+ perror("mkdir");
+ return false;
+ }
+ } else {
+ auto new_file = Core::File::construct(String { file_name });
+ if (!new_file->open(Core::IODevice::WriteOnly)) {
+ fprintf(stderr, "Can't write file %s: %s\n", file_name, new_file->error_string());
+ return false;
+ }
- printf(" extracting: %s\n", file_name);
- u8 raw_file_contents[compressed_file_size];
- if (!seek_and_read(raw_file_contents, file, local_file_header_index + 30 + file_name_length + extra_field_length, compressed_file_size))
- return false;
+ printf(" extracting: %s\n", file_name);
+ u8 raw_file_contents[compressed_file_size];
+ if (!seek_and_read(raw_file_contents, file, local_file_header_index + LFHFileNameBaseOffset + file_name_length + extra_field_length, compressed_file_size))
+ return false;
- // FIXME: Try to uncompress data here. We're just ignoring it as no decompression methods are implemented yet.
- if (!new_file->write(raw_file_contents, compressed_file_size)) {
- fprintf(stderr, "Can't write file contents in %s: %s\n", file_name, new_file->error_string());
- return false;
- }
+ // FIXME: Try to uncompress data here. We're just ignoring it as no decompression methods are implemented yet.
+ if (!new_file->write(raw_file_contents, compressed_file_size)) {
+ fprintf(stderr, "Can't write file contents in %s: %s\n", file_name, new_file->error_string());
+ return false;
+ }
- if (!new_file->close()) {
- fprintf(stderr, "Can't close file %s: %s\n", file_name, new_file->error_string());
- return false;
+ if (!new_file->close()) {
+ fprintf(stderr, "Can't close file %s: %s\n", file_name, new_file->error_string());
+ return false;
+ }
}
return true;