-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add support for single gzip'ed files
- Loading branch information
Showing
3 changed files
with
136 additions
and
40 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,9 +4,9 @@ README | |
qlZipInfo v1.1.3 | ||
By Sriranga Veeraraghavan <[email protected]> | ||
|
||
qlZipInfo is a QuickLook generator for zip, jar, tar, tar.gz | ||
(.tgz), tar.bz2 (.tbz2), tar.Z (.tZ), xar (.xar, .pkg), debian | ||
(.deb), 7zip (.7z), xz, cab, and lha archives and ISO9660 images. | ||
qlZipInfo is a QuickLook generator for zip, jar, tar, tar.gz (.tgz), | ||
tar.bz2 (.tbz2), tar.Z (.tZ), xar (.xar, .pkg), debian (.deb), | ||
7zip (.7z), xz, cab, gzip, and lha archives and ISO9660 images. | ||
|
||
qlZipInfo relies on libarchive (https://libarchive.org/). | ||
|
||
|
@@ -39,7 +39,8 @@ History: | |
|
||
v1.1.3 - add support for Microsoft CAB files (Install- | ||
Sheild CAB files have a different format and | ||
aren't yet supported) | ||
aren't yet supported) and gzip'ed archives of | ||
a single file | ||
v1.1.2 - fix (partially?) listing non-ASCII filenames | ||
v1.1.1 - add support for xar / pkg, debian (.deb), 7zip | ||
(.7z), xz, and lha archives and ISO9660 images | ||
|
@@ -71,4 +72,3 @@ History: | |
License: | ||
|
||
Please see LICENSE.txt | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -24,6 +24,8 @@ | |
make the header row fixed | ||
v. 0.2.2 (06/20/2021) - add support for rar, rar4, lha, 7z, xz, and | ||
debian (.deb) archives | ||
v. 0.2.3 (07/21/2021) - add support for indiviudal files that are | ||
gzip'ed | ||
Copyright (c) 2015-2021 Sriranga R. Veeraraghavan <[email protected]> | ||
|
@@ -55,6 +57,7 @@ a copy of this software and associated documentation files (the | |
#import <QuickLook/QuickLook.h> | ||
#import <CommonCrypto/CommonDigest.h> | ||
|
||
#include <stdio.h> | ||
#include <sys/syslimits.h> | ||
#include <sys/stat.h> | ||
#include <iconv.h> | ||
|
@@ -159,6 +162,10 @@ Default error code (MacOS extractErr error code from MacErrors.h) See: | |
static const char *gFileSizeGigaBytes = "G"; | ||
static const char *gFileSizeTeraBytes = "T"; | ||
|
||
/* UTIs for files that may require special handling */ | ||
|
||
static const CFStringRef gUTIGZip = CFSTR("org.gnu.gnu-zip-archive"); | ||
|
||
/* prototypes */ | ||
|
||
OSStatus GeneratePreviewForURL(void *thisInterface, | ||
|
@@ -202,15 +209,19 @@ OSStatus GeneratePreviewForURL(void *thisInterface, | |
unsigned long i = 0, fileCount = 0; | ||
off_t totalSize = 0; | ||
off_t totalCompressedSize = 0; | ||
off_t fileCompressedSize = 0; | ||
Float64 compression = 0; | ||
bool isFolder = FALSE; | ||
bool isGZFile = false; | ||
fileSizeSpec_t fileSizeSpecInZip; | ||
|
||
FILE *gzFile = NULL; | ||
UInt8 gzCompressedSize[4]; | ||
|
||
if (url == NULL) { | ||
fprintf(stderr, "qlZipInfo: ERROR: url is null\n"); | ||
return zipQLFailed; | ||
} | ||
|
||
/* get the local file system path for the specified file */ | ||
|
||
zipFileName = | ||
|
@@ -291,19 +302,51 @@ file path using CFStringGetCString() b/c the file path | |
archive_read_support_format_7zip(a); | ||
archive_read_support_format_cab(a); | ||
|
||
if ((r = archive_read_open_filename(a, zipFileNameStr, 10240))) | ||
r = archive_read_open_filename(a, zipFileNameStr, 10240); | ||
|
||
if (r != ARCHIVE_OK) | ||
{ | ||
fprintf(stderr, | ||
"qlZipInfo: ERROR: %s\n", | ||
archive_error_string(a)); | ||
|
||
archive_read_close(a); | ||
archive_read_free(a); | ||
return zipQLFailed; | ||
|
||
r = zipQLFailed; | ||
} | ||
|
||
|
||
if (r == zipQLFailed) | ||
{ | ||
if (CFEqual(contentTypeUTI,gUTIGZip) != true) | ||
{ | ||
return r; | ||
} | ||
|
||
/* this is a gzip'ed file, re-try opening in raw mode */ | ||
|
||
isGZFile = true; | ||
a = archive_read_new(); | ||
archive_read_support_format_raw(a); | ||
archive_read_support_filter_gzip(a); | ||
|
||
r = archive_read_open_filename(a, zipFileNameStr, 10240); | ||
|
||
if (r != ARCHIVE_OK) | ||
{ | ||
fprintf(stderr, | ||
"qlZipInfo: ERROR: gz: %s\n", | ||
archive_error_string(a)); | ||
archive_read_close(a); | ||
archive_read_free(a); | ||
return zipQLFailed; | ||
} | ||
} | ||
|
||
/* exit if the user canceled the preview */ | ||
|
||
if (QLPreviewRequestIsCancelled(preview)) { | ||
if (QLPreviewRequestIsCancelled(preview)) | ||
{ | ||
archive_read_close(a); | ||
archive_read_free(a); | ||
return noErr; | ||
|
@@ -538,8 +581,15 @@ file path using CFStringGetCString() b/c the file path | |
fileNameInZip = gFileNameUnavilable; | ||
} | ||
|
||
isFolder = | ||
archive_entry_filetype(entry) == AE_IFDIR ? TRUE : FALSE; | ||
if (isGZFile == true) | ||
{ | ||
isFolder = FALSE; | ||
} | ||
else | ||
{ | ||
isFolder = | ||
(archive_entry_filetype(entry) == AE_IFDIR ? TRUE : FALSE); | ||
} | ||
|
||
/* start the table row for this file */ | ||
|
||
|
@@ -556,22 +606,25 @@ file path using CFStringGetCString() b/c the file path | |
*/ | ||
|
||
qlEntryIcon = (NSString *)gFileIcon; | ||
|
||
if (isFolder == TRUE) | ||
{ | ||
qlEntryIcon = (NSString *)gFolderIcon; | ||
} | ||
else if (archive_entry_is_encrypted(entry)) | ||
{ | ||
qlEntryIcon = (NSString *)gFileEncyrptedIcon; | ||
} | ||
else if (archive_entry_filetype(entry) == AE_IFLNK) | ||
{ | ||
qlEntryIcon = (NSString *)gFileLinkIcon; | ||
} | ||
else if (archive_entry_filetype(entry) != AE_IFREG) | ||
|
||
if (isGZFile != true) | ||
{ | ||
qlEntryIcon = (NSString *)gFileSpecialIcon; | ||
if (isFolder == TRUE) | ||
{ | ||
qlEntryIcon = (NSString *)gFolderIcon; | ||
} | ||
else if (archive_entry_is_encrypted(entry)) | ||
{ | ||
qlEntryIcon = (NSString *)gFileEncyrptedIcon; | ||
} | ||
else if (archive_entry_filetype(entry) == AE_IFLNK) | ||
{ | ||
qlEntryIcon = (NSString *)gFileLinkIcon; | ||
} | ||
else if (archive_entry_filetype(entry) != AE_IFREG) | ||
{ | ||
qlEntryIcon = (NSString *)gFileSpecialIcon; | ||
} | ||
} | ||
|
||
[qlHtml appendFormat: @"<td align=\"center\">%@</td>", | ||
|
@@ -597,16 +650,52 @@ file path using CFStringGetCString() b/c the file path | |
[qlHtml appendString: | ||
@"<td align=\"center\" colspan=\"2\"><pre>--</pre></td>"]; | ||
} else { | ||
|
||
if (isGZFile == true) | ||
{ | ||
/* | ||
if this is a gzip'ed file, assume that the uncompressed | ||
size is stored in the last 4 bytes of the file (which | ||
might be wrong for files greater than 4GB); see: | ||
http://www.abeel.be/content/determine-uncompressed-size-gzip-file | ||
https://stackoverflow.com/questions/9209138/uncompressed-file-size-using-zlibs-gzip-file-access-function | ||
*/ | ||
|
||
gzFile = fopen(zipFileNameStr, "r"); | ||
if (gzFile != NULL) | ||
{ | ||
memset(gzCompressedSize, 0, 4); | ||
|
||
if (fseek(gzFile, -4, SEEK_END) == 0) | ||
{ | ||
if (fread(gzCompressedSize, 1 , 4, gzFile) == 4) | ||
{ | ||
fileCompressedSize = | ||
(gzCompressedSize[3] << 24) | | ||
(gzCompressedSize[2] << 16) | | ||
(gzCompressedSize[1] << 8) + | ||
gzCompressedSize[0]; | ||
} | ||
} | ||
|
||
fclose(gzFile); | ||
} | ||
} | ||
else | ||
{ | ||
fileCompressedSize = archive_entry_size(entry); | ||
} | ||
|
||
/* clear the file size spec */ | ||
|
||
memset(&fileSizeSpecInZip, 0, sizeof(fileSizeSpec_t)); | ||
|
||
/* get the file's size spec */ | ||
|
||
getFileSizeSpec(archive_entry_size(entry), | ||
getFileSizeSpec(fileCompressedSize, | ||
&fileSizeSpecInZip); | ||
|
||
/* print out the file's size in B, K, M, G, or T */ | ||
|
||
[qlHtml appendFormat: | ||
|
@@ -699,21 +788,28 @@ file path using CFStringGetCString() b/c the file path | |
/* close the row */ | ||
|
||
[qlHtml appendString:@"</tr>\n"]; | ||
|
||
/* update the total compressed sizes */ | ||
|
||
/* update the total compressed and uncompressed sizes */ | ||
|
||
totalSize += archive_entry_size(entry); | ||
totalSize += fileCompressedSize; | ||
|
||
/* if this was a GZip'ed file, no need to repeat the loop */ | ||
|
||
if (isGZFile == true) | ||
{ | ||
break; | ||
} | ||
} | ||
|
||
/* close the zip file */ | ||
|
||
archive_read_close(a); | ||
archive_read_free(a); | ||
|
||
/* close the table body */ | ||
/* close the main table's body */ | ||
|
||
[qlHtml appendString: @"</tbody>\n"]; | ||
|
||
/* | ||
start the summary row for the zip file - | ||
[total size] [blank] [ no. of files] | ||
|
@@ -734,7 +830,7 @@ file path using CFStringGetCString() b/c the file path | |
/* clear the file size spec */ | ||
|
||
memset(&fileSizeSpecInZip, 0, sizeof(fileSizeSpec_t)); | ||
|
||
/* get the file's total uncompressed size spec */ | ||
|
||
getFileSizeSpec(totalSize, | ||
|
@@ -767,7 +863,7 @@ file path using CFStringGetCString() b/c the file path | |
|
||
[qlHtml appendString: | ||
@"<td align=\"right\" colspan=\"2\"><pre> </pre></td>"]; | ||
|
||
/* close the summary row */ | ||
|
||
[qlHtml appendString:@"</tr>\n"]; | ||
|