Skip to content

Commit

Permalink
feat: support for icons in subdirectories
Browse files Browse the repository at this point in the history
  • Loading branch information
relikd committed Feb 27, 2024
1 parent 9559cd5 commit 46e6309
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 23 deletions.
31 changes: 16 additions & 15 deletions ProvisionQL/AppIcon.m
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ - (BOOL)canExtractImage {
- (NSImage * _Nonnull)extractImage:(NSDictionary * _Nullable)appPlist {
// no need to unwrap the plist, and most .ipa should include the Artwork anyway
if (_meta.type == FileTypeIPA) {
NSData *data = [_meta.zipFile unzipFile:@"iTunesArtwork"];
NSData *data = [_meta.zipFile unzipFile:@"iTunesArtwork" isExactMatch:YES];
if (data) {
#ifdef DEBUG
NSLog(@"[icon] using iTunesArtwork.");
Expand All @@ -78,11 +78,10 @@ - (NSImage * _Nonnull)extractImage:(NSDictionary * _Nullable)appPlist {
NSLog(@"[icon] using plist image file %@", actualName);
#endif
if (_meta.type == FileTypeIPA) {
NSData *data = [_meta.zipFile unzipFile:[@"Payload/*.app/" stringByAppendingString:actualName]];
NSData *data = [_meta.zipFile unzipFile:actualName isExactMatch:YES];
return [[NSImage alloc] initWithData:data];
}
NSURL *basePath = _meta.effectiveUrl ?: _meta.url;
return [[NSImage alloc] initWithContentsOfURL:[basePath URLByAppendingPathComponent:actualName]];
return [[NSImage alloc] initWithContentsOfURL:[NSURL fileURLWithPath:actualName isDirectory:NO]];
}

#ifdef CUI_ENABLED
Expand Down Expand Up @@ -231,13 +230,13 @@ - (NSString * _Nullable)expandImageName:(NSArray<NSString *> * _Nonnull)iconList
if (_meta.type == FileTypeIPA) {
if (!_meta.zipFile) {
// in case unzip in memory is not available, fallback to pattern matching with dynamic suffix
return [[iconList firstObject] stringByAppendingString:@"*"];
return [NSString stringWithFormat:@"Payload/*.app/%@*", iconList.firstObject];
}
for (NSString *fileName in iconList) {
NSString *zipPath = [NSString stringWithFormat:@"Payload/*.app/%@*", fileName];
for (NSString *iconPath in iconList) {
NSString *zipPath = [NSString stringWithFormat:@"Payload/*.app/%@*", iconPath];
for (ZipEntry *zip in [_meta.zipFile filesMatching:zipPath]) {
if (zip.sizeUncompressed > 0) {
[matches addObject:[zip.filepath lastPathComponent]];
[matches addObject:zip.filepath];
}
}
if (matches.count > 0) {
Expand All @@ -247,13 +246,15 @@ - (NSString * _Nullable)expandImageName:(NSArray<NSString *> * _Nonnull)iconList
} else if (_meta.type == FileTypeArchive || _meta.type == FileTypeExtension) {
NSURL *basePath = _meta.effectiveUrl ?: _meta.url;
NSFileManager *fileManager = [NSFileManager defaultManager];
NSArray<NSString *> *appContents = [fileManager contentsOfDirectoryAtPath:basePath.path error:nil];
for (NSString *fileName in iconList) {
for (NSString *file in appContents) {
for (NSString *iconPath in iconList) {
NSString *fileName = [iconPath lastPathComponent];
NSString *basename = [basePath URLByAppendingPathComponent:iconPath isDirectory:NO].path;
NSString *parentDir = [basename stringByDeletingLastPathComponent];
for (NSString *file in [fileManager contentsOfDirectoryAtPath:parentDir error:nil]) {
if ([file hasPrefix:fileName]) {
NSString *fullPath = [basePath URLByAppendingPathComponent:file isDirectory:NO].path;
NSString *fullPath = [parentDir stringByAppendingPathComponent:file];
if ([fileManager attributesOfItemAtPath:fullPath error:nil].fileSize > 0) {
[matches addObject:file];
[matches addObject:fullPath];
}
}
}
Expand Down Expand Up @@ -303,8 +304,8 @@ - (NSInteger)resolutionIndex:(NSString *)iconName {
/// Given a list of filenames, order them highest resolution first.
- (NSArray<NSString *> *)sortedByResolution:(NSArray<NSString *> *)icons {
return [icons sortedArrayUsingComparator:^NSComparisonResult(NSString *obj1, NSString *obj2) {
NSInteger i1 = [self resolutionIndex:obj1];
NSInteger i2 = [self resolutionIndex:obj2];
NSInteger i1 = [self resolutionIndex:[obj1 lastPathComponent]];
NSInteger i2 = [self resolutionIndex:[obj2 lastPathComponent]];
return i1 < i2 ? NSOrderedAscending : i1 > i2? NSOrderedDescending : NSOrderedSame;
}];
}
Expand Down
4 changes: 2 additions & 2 deletions ProvisionQL/Shared.m
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ QuickLookInfo initQLInfo(CFStringRef contentTypeUTI, CFURLRef url) {
/// Load a file from bundle into memory. Either by file path or via unzip.
NSData * _Nullable readPayloadFile(QuickLookInfo meta, NSString *filename) {
switch (meta.type) {
case FileTypeIPA: return [meta.zipFile unzipFile:[@"Payload/*.app/" stringByAppendingString:filename]];
case FileTypeIPA: return [meta.zipFile unzipFile:[@"Payload/*.app/" stringByAppendingString:filename] isExactMatch:NO];
case FileTypeArchive: return [NSData dataWithContentsOfURL:[meta.effectiveUrl URLByAppendingPathComponent:filename]];
case FileTypeExtension: return [NSData dataWithContentsOfURL:[meta.url URLByAppendingPathComponent:filename]];
case FileTypeProvision: return nil;
Expand Down Expand Up @@ -106,7 +106,7 @@ QuickLookInfo initQLInfo(CFStringRef contentTypeUTI, CFURLRef url) {
/// Read @c iTunesMetadata.plist if available
NSDictionary * _Nullable readPlistItunes(QuickLookInfo meta) {
if (meta.type == FileTypeIPA) {
return asPlistOrNil([meta.zipFile unzipFile:@"iTunesMetadata.plist"]);
return asPlistOrNil([meta.zipFile unzipFile:@"iTunesMetadata.plist" isExactMatch:YES]);
}
return nil;
}
Expand Down
2 changes: 1 addition & 1 deletion ProvisionQL/ZipFile.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ NS_ASSUME_NONNULL_BEGIN

@interface ZipFile : NSObject
+ (instancetype)open:(NSString *)path;
- (NSData * _Nullable)unzipFile:(NSString *)filePath;
- (NSData * _Nullable)unzipFile:(NSString *)filePath isExactMatch:(BOOL)exact;
- (void)unzipFile:(NSString *)filePath toDir:(NSString *)targetDir;
- (NSArray<ZipEntry*> * _Nullable)filesMatching:(NSString * _Nonnull)path;
@end
Expand Down
14 changes: 9 additions & 5 deletions ProvisionQL/ZipFile.m
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ - (instancetype)initWithFile:(NSString *)path {

/// Unzip file directly into memory.
/// @param filePath File path inside zip file.
- (NSData * _Nullable)unzipFile:(NSString *)filePath {
- (NSData * _Nullable)unzipFile:(NSString *)filePath isExactMatch:(BOOL)exact {
if (self.centralDirectory) {
ZipEntry *matchingFile = [self.centralDirectory zipEntryWithPath:filePath];
if (!matchingFile) {
Expand All @@ -56,15 +56,15 @@ - (NSData * _Nullable)unzipFile:(NSString *)filePath {
}
}
// fallback to sys unzip
return [self sysUnzipFile:filePath];
return [self sysUnzipFile:filePath isExactMatch:exact];
}

/// Unzip file to filesystem.
/// @param filePath File path inside zip file.
/// @param targetDir Directory in which to unzip the file.
- (void)unzipFile:(NSString *)filePath toDir:(NSString *)targetDir {
if (self.centralDirectory) {
NSData *data = [self unzipFile:filePath];
NSData *data = [self unzipFile:filePath isExactMatch:NO];
if (data) {
NSString *outputPath = [targetDir stringByAppendingPathComponent:[filePath lastPathComponent]];
#ifdef DEBUG
Expand All @@ -80,11 +80,15 @@ - (void)unzipFile:(NSString *)filePath toDir:(NSString *)targetDir {

// MARK: - fallback to sys call

- (NSData * _Nullable)sysUnzipFile:(NSString *)filePath {
- (NSData * _Nullable)sysUnzipFile:(NSString *)filePath isExactMatch:(BOOL)exact {
NSTask *task = [NSTask new];
[task setLaunchPath:@"/usr/bin/unzip"];
[task setStandardOutput:[NSPipe pipe]];
[task setArguments:@[@"-p", self.pathToZipFile, filePath, @"-x", @"*/*/*/*"]];
if (exact) {
[task setArguments:@[@"-p", self.pathToZipFile, filePath]];
} else {
[task setArguments:@[@"-p", self.pathToZipFile, filePath, @"-x", @"*/*/*/*"]];
}
[task launch];

#ifdef DEBUG
Expand Down

0 comments on commit 46e6309

Please sign in to comment.