diff --git a/.gitignore b/.gitignore index 686626a..d536a96 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,9 @@ build/ !default.mode2v3 *.perspectivev3 !default.perspectivev3 +Products/ + + xcuserdata *.xccheckout *.moved-aside diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..6bf3ae3 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "CARExtractor/QLCARFiles"] + path = CARExtractor/QLCARFiles + url = https://github.com/devcxm/QLCARFiles.git diff --git a/CARExtractor/CARExtractor.xcodeproj/project.pbxproj b/CARExtractor/CARExtractor.xcodeproj/project.pbxproj old mode 100755 new mode 100644 index 2da1191..2fb9194 --- a/CARExtractor/CARExtractor.xcodeproj/project.pbxproj +++ b/CARExtractor/CARExtractor.xcodeproj/project.pbxproj @@ -3,67 +3,113 @@ archiveVersion = 1; classes = { }; - objectVersion = 46; + objectVersion = 50; objects = { /* Begin PBXBuildFile section */ - CA7B544419FF10F80019A015 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = CA7B544319FF10F80019A015 /* main.m */; }; - CA7B546419FF4A110019A015 /* CoreUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CA7B546319FF4A110019A015 /* CoreUI.framework */; }; + 8982EB282484F82200BCB558 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 8982EB272484F82200BCB558 /* main.m */; }; + 8982EB362484F92E00BCB558 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8982EB352484F92E00BCB558 /* Foundation.framework */; }; + 8982EB3F2484F9B400BCB558 /* ImageUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = 8982EB3A2484F9B400BCB558 /* ImageUtilities.m */; }; + 8982EB402484F9B400BCB558 /* CarUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = 8982EB3D2484F9B400BCB558 /* CarUtilities.m */; }; + 8982EB482484FD6700BCB558 /* CoreUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8982EB462484FD6700BCB558 /* CoreUI.framework */; }; /* End PBXBuildFile section */ +/* Begin PBXCopyFilesBuildPhase section */ + 8982EB222484F82200BCB558 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = /usr/share/man/man1/; + dstSubfolderSpec = 0; + files = ( + ); + runOnlyForDeploymentPostprocessing = 1; + }; +/* End PBXCopyFilesBuildPhase section */ + /* Begin PBXFileReference section */ - CA7B544019FF10F80019A015 /* CARExtractor */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = CARExtractor; sourceTree = BUILT_PRODUCTS_DIR; }; - CA7B544319FF10F80019A015 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; - CA7B546319FF4A110019A015 /* CoreUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreUI.framework; path = ../../../../../../System/Library/PrivateFrameworks/CoreUI.framework; sourceTree = ""; }; + 8982EB242484F82200BCB558 /* CARExtractor */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = CARExtractor; sourceTree = BUILT_PRODUCTS_DIR; }; + 8982EB272484F82200BCB558 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 8982EB352484F92E00BCB558 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; + 8982EB3A2484F9B400BCB558 /* ImageUtilities.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ImageUtilities.m; sourceTree = ""; }; + 8982EB3B2484F9B400BCB558 /* CarUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CarUtilities.h; sourceTree = ""; }; + 8982EB3C2484F9B400BCB558 /* CoreUI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CoreUI.h; sourceTree = ""; }; + 8982EB3D2484F9B400BCB558 /* CarUtilities.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CarUtilities.m; sourceTree = ""; }; + 8982EB3E2484F9B400BCB558 /* ImageUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImageUtilities.h; sourceTree = ""; }; + 8982EB462484FD6700BCB558 /* CoreUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreUI.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk/System/Library/PrivateFrameworks/CoreUI.framework; sourceTree = DEVELOPER_DIR; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ - CA7B543D19FF10F80019A015 /* Frameworks */ = { + 8982EB212484F82200BCB558 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - CA7B546419FF4A110019A015 /* CoreUI.framework in Frameworks */, + 8982EB362484F92E00BCB558 /* Foundation.framework in Frameworks */, + 8982EB482484FD6700BCB558 /* CoreUI.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ - CA7B543719FF10F80019A015 = { + 8982EB1B2484F82200BCB558 = { isa = PBXGroup; children = ( - CA7B544219FF10F80019A015 /* CARExtractor */, - CA7B544119FF10F80019A015 /* Products */, + 8982EB262484F82200BCB558 /* CARExtractor */, + 8982EB252484F82200BCB558 /* Products */, + 8982EB342484F92E00BCB558 /* Frameworks */, ); sourceTree = ""; }; - CA7B544119FF10F80019A015 /* Products */ = { + 8982EB252484F82200BCB558 /* Products */ = { isa = PBXGroup; children = ( - CA7B544019FF10F80019A015 /* CARExtractor */, + 8982EB242484F82200BCB558 /* CARExtractor */, ); name = Products; sourceTree = ""; }; - CA7B544219FF10F80019A015 /* CARExtractor */ = { + 8982EB262484F82200BCB558 /* CARExtractor */ = { isa = PBXGroup; children = ( - CA7B546319FF4A110019A015 /* CoreUI.framework */, - CA7B544319FF10F80019A015 /* main.m */, + 8982EB392484F9B400BCB558 /* Common */, + 8982EB272484F82200BCB558 /* main.m */, ); path = CARExtractor; sourceTree = ""; }; + 8982EB342484F92E00BCB558 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 8982EB462484FD6700BCB558 /* CoreUI.framework */, + 8982EB352484F92E00BCB558 /* Foundation.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 8982EB392484F9B400BCB558 /* Common */ = { + isa = PBXGroup; + children = ( + 8982EB3B2484F9B400BCB558 /* CarUtilities.h */, + 8982EB3D2484F9B400BCB558 /* CarUtilities.m */, + 8982EB3C2484F9B400BCB558 /* CoreUI.h */, + 8982EB3E2484F9B400BCB558 /* ImageUtilities.h */, + 8982EB3A2484F9B400BCB558 /* ImageUtilities.m */, + ); + name = Common; + path = QLCARFiles/Common; + sourceTree = SOURCE_ROOT; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ - CA7B543F19FF10F80019A015 /* CARExtractor */ = { + 8982EB232484F82200BCB558 /* CARExtractor */ = { isa = PBXNativeTarget; - buildConfigurationList = CA7B544719FF10F80019A015 /* Build configuration list for PBXNativeTarget "CARExtractor" */; + buildConfigurationList = 8982EB2B2484F82200BCB558 /* Build configuration list for PBXNativeTarget "CARExtractor" */; buildPhases = ( - CA7B543C19FF10F80019A015 /* Sources */, - CA7B543D19FF10F80019A015 /* Frameworks */, - CA7B544A19FF110C0019A015 /* Run Script */, + 8982EB202484F82200BCB558 /* Sources */, + 8982EB212484F82200BCB558 /* Frameworks */, + 8982EB222484F82200BCB558 /* CopyFiles */, + 8982EB412484FB3400BCB558 /* ShellScript */, ); buildRules = ( ); @@ -71,189 +117,232 @@ ); name = CARExtractor; productName = CARExtractor; - productReference = CA7B544019FF10F80019A015 /* CARExtractor */; + productReference = 8982EB242484F82200BCB558 /* CARExtractor */; productType = "com.apple.product-type.tool"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ - CA7B543819FF10F80019A015 /* Project object */ = { + 8982EB1C2484F82200BCB558 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0600; - ORGANIZATIONNAME = BrandonMcQuilkin; + LastUpgradeCheck = 1150; + ORGANIZATIONNAME = chi; TargetAttributes = { - CA7B543F19FF10F80019A015 = { - CreatedOnToolsVersion = 6.0; + 8982EB232484F82200BCB558 = { + CreatedOnToolsVersion = 11.5; }; }; }; - buildConfigurationList = CA7B543B19FF10F80019A015 /* Build configuration list for PBXProject "CARExtractor" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; + buildConfigurationList = 8982EB1F2484F82200BCB558 /* Build configuration list for PBXProject "CARExtractor" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( en, + Base, ); - mainGroup = CA7B543719FF10F80019A015; - productRefGroup = CA7B544119FF10F80019A015 /* Products */; + mainGroup = 8982EB1B2484F82200BCB558; + productRefGroup = 8982EB252484F82200BCB558 /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( - CA7B543F19FF10F80019A015 /* CARExtractor */, + 8982EB232484F82200BCB558 /* CARExtractor */, ); }; /* End PBXProject section */ /* Begin PBXShellScriptBuildPhase section */ - CA7B544A19FF110C0019A015 /* Run Script */ = { + 8982EB412484FB3400BCB558 /* ShellScript */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); + inputFileListPaths = ( + ); inputPaths = ( ); - name = "Run Script"; + outputFileListPaths = ( + ); outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "mkdir -p \"${PROJECT_DIR}/Product\";\ncp \"${TARGET_BUILD_DIR}/${TARGET_NAME}\" \"${PROJECT_DIR}/Product/${TARGET_NAME}\""; + shellScript = "mkdir -p \"${PROJECT_DIR}/../Products\";\nrm -f \"${PROJECT_DIR}/../Products/${TARGET_NAME}\";\ncp \"${TARGET_BUILD_DIR}/${TARGET_NAME}\" \"${PROJECT_DIR}/../Products/${TARGET_NAME}\"\n"; }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ - CA7B543C19FF10F80019A015 /* Sources */ = { + 8982EB202484F82200BCB558 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - CA7B544419FF10F80019A015 /* main.m in Sources */, + 8982EB3F2484F9B400BCB558 /* ImageUtilities.m in Sources */, + 8982EB402484F9B400BCB558 /* CarUtilities.m in Sources */, + 8982EB282484F82200BCB558 /* main.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin XCBuildConfiguration section */ - CA7B544519FF10F80019A015 /* Debug */ = { + 8982EB292484F82200BCB558 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.9; - MTL_ENABLE_DEBUG_INFO = YES; + MACOSX_DEPLOYMENT_TARGET = 10.15; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; }; name = Debug; }; - CA7B544619FF10F80019A015 /* Release */ = { + 8982EB2A2484F82200BCB558 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = YES; + COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.9; + MACOSX_DEPLOYMENT_TARGET = 10.15; MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; SDKROOT = macosx; }; name = Release; }; - CA7B544819FF10F80019A015 /* Debug */ = { + 8982EB2C2484F82200BCB558 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - FRAMEWORK_SEARCH_PATHS = ( + CODE_SIGN_STYLE = Automatic; + PRODUCT_NAME = "$(TARGET_NAME)"; + SYSTEM_FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks", + "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks", ); - MACOSX_DEPLOYMENT_TARGET = 10.8; - PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Debug; }; - CA7B544919FF10F80019A015 /* Release */ = { + 8982EB2D2484F82200BCB558 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - FRAMEWORK_SEARCH_PATHS = ( + CODE_SIGN_STYLE = Automatic; + PRODUCT_NAME = "$(TARGET_NAME)"; + SYSTEM_FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks", + "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks", ); - MACOSX_DEPLOYMENT_TARGET = 10.8; - PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ - CA7B543B19FF10F80019A015 /* Build configuration list for PBXProject "CARExtractor" */ = { + 8982EB1F2484F82200BCB558 /* Build configuration list for PBXProject "CARExtractor" */ = { isa = XCConfigurationList; buildConfigurations = ( - CA7B544519FF10F80019A015 /* Debug */, - CA7B544619FF10F80019A015 /* Release */, + 8982EB292484F82200BCB558 /* Debug */, + 8982EB2A2484F82200BCB558 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - CA7B544719FF10F80019A015 /* Build configuration list for PBXNativeTarget "CARExtractor" */ = { + 8982EB2B2484F82200BCB558 /* Build configuration list for PBXNativeTarget "CARExtractor" */ = { isa = XCConfigurationList; buildConfigurations = ( - CA7B544819FF10F80019A015 /* Debug */, - CA7B544919FF10F80019A015 /* Release */, + 8982EB2C2484F82200BCB558 /* Debug */, + 8982EB2D2484F82200BCB558 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; - rootObject = CA7B543819FF10F80019A015 /* Project object */; + rootObject = 8982EB1C2484F82200BCB558 /* Project object */; } diff --git a/CARExtractor/CARExtractor.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/CARExtractor/CARExtractor.xcodeproj/project.xcworkspace/contents.xcworkspacedata old mode 100755 new mode 100644 diff --git a/CARExtractor/CARExtractor.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/CARExtractor/CARExtractor.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/CARExtractor/CARExtractor.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/CARExtractor/CARExtractor.xcodeproj/xcshareddata/xcschemes/CARExtractor.xcscheme b/CARExtractor/CARExtractor.xcodeproj/xcshareddata/xcschemes/CARExtractor.xcscheme deleted file mode 100644 index 99a251e..0000000 --- a/CARExtractor/CARExtractor.xcodeproj/xcshareddata/xcschemes/CARExtractor.xcscheme +++ /dev/null @@ -1,102 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/CARExtractor/CARExtractor/main.m b/CARExtractor/CARExtractor/main.m old mode 100755 new mode 100644 index 4259a84..01cf42e --- a/CARExtractor/CARExtractor/main.m +++ b/CARExtractor/CARExtractor/main.m @@ -2,136 +2,211 @@ // main.m // CARExtractor // -// Created by Brandon McQuilkin on 10/27/14. -// -// Based on by cartool Steven Troughton-Smith on 14/07/2013. -// Copyright (c) 2013 High Caffeine Content. All rights reserved. +// Created by chixm on 2020/6/1. +// Copyright © 2020 chi. All rights reserved. // #import -#pragma Private Frameworks - -@interface CUICommonAssetStorage : NSObject - --(NSArray *)allAssetKeys; --(NSArray *)allRenditionNames; - --(id)initWithPath:(NSString *)p; - --(NSString *)versionString; - - -@end - -@interface CUINamedImage : NSObject - --(CGImageRef)image; - -@end - -@interface CUIRenditionKey : NSObject -@end - -@interface CUIThemeFacet : NSObject - -+(CUIThemeFacet *)themeWithContentsOfURL:(NSURL *)u error:(NSError **)e; -+ (void)_invalidateArtworkCaches; - -@end - -@interface CUICatalog : NSObject - --(id)initWithName:(NSString *)n fromBundle:(NSBundle *)b; --(id)allKeys; --(CUINamedImage *)imageWithName:(NSString *)n scaleFactor:(CGFloat)s; --(CUINamedImage *)imageWithName:(NSString *)n scaleFactor:(CGFloat)s deviceIdiom:(int)idiom; - -@end +#import "CoreUI.h" +#import "CarUtilities.h" -#define kCoreThemeIdiomPhone 1 -#define kCoreThemeIdiomPad 2 +static NSString *kProccessingNotificationName = nil; +static CFTimeInterval s_lastPostNotificationTime = 0; -#pragma mark Export Image +void postProccessingNotification(NSDictionary *userInfo) { + CFTimeInterval currentMediaTime = CACurrentMediaTime(); + if (currentMediaTime - s_lastPostNotificationTime < 0.05f) { + return; + } + s_lastPostNotificationTime = currentMediaTime; + if (kProccessingNotificationName && userInfo.count > 0) { + CFNotificationCenterRef distributedCenter = + CFNotificationCenterGetDistributedCenter(); + + CFNotificationCenterPostNotification(distributedCenter, + (__bridge CFStringRef)kProccessingNotificationName, + NULL, + (__bridge CFDictionaryRef)userInfo, + TRUE); + } +} -void CGImageWriteToFile(CGImageRef image, NSString *path) +NSString * FindUniquePathForPath(NSString *inPath, NSString *optionalPathComponent, BOOL forceUseOptionalFileNamePathComponent) { - if (![[NSFileManager defaultManager] fileExistsAtPath:path.stringByDeletingLastPathComponent]) - [[NSFileManager defaultManager] createDirectoryAtPath:path.stringByDeletingLastPathComponent withIntermediateDirectories:true attributes:nil error:nil]; + NSString *outPath = inPath; - CFURLRef url = (__bridge CFURLRef)[NSURL fileURLWithPath:path]; - CGImageDestinationRef destination = CGImageDestinationCreateWithURL(url, kUTTypePNG, 1, NULL); - CGImageDestinationAddImage(destination, image, nil); + // If the path exists, add the optional path component for differenciation + if([optionalPathComponent length] > 0 && ([[NSFileManager defaultManager] fileExistsAtPath:inPath] || forceUseOptionalFileNamePathComponent)) + { + NSString *pathExtension = [inPath pathExtension]; + if([pathExtension length] > 0) + { + NSString *replaceString = [NSString stringWithFormat:@".%@", pathExtension]; + outPath = [inPath stringByReplacingOccurrencesOfString:replaceString withString:[NSString stringWithFormat:@"~%@%@", optionalPathComponent, replaceString] options:NSBackwardsSearch range:NSMakeRange(0, [inPath length])]; + } + else + { + outPath = [inPath stringByAppendingFormat:@"%@", [NSString stringWithFormat:@"~%@", optionalPathComponent]]; + } + } - if (!CGImageDestinationFinalize(destination)) { - -#ifdef DEBUG - NSLog(@"Failed to write image to %@", path); -#endif - + // Ensure the path does not exist + NSString *initialPath = outPath; + if([[NSFileManager defaultManager] fileExistsAtPath:initialPath]) + { + NSString *pathExtension = [initialPath pathExtension]; + if([pathExtension length] > 0) + { + NSString *replaceString = [NSString stringWithFormat:@".%@", pathExtension]; + NSUInteger fileSuffix = 1; + while([[NSFileManager defaultManager] fileExistsAtPath:outPath]) + { + outPath = [initialPath stringByReplacingOccurrencesOfString:replaceString withString:[NSString stringWithFormat:@"~%ld%@", fileSuffix, replaceString] options:NSBackwardsSearch range:NSMakeRange(0, [initialPath length])]; + fileSuffix++; + } + } + else + { + NSUInteger fileSuffix = 1; + while([[NSFileManager defaultManager] fileExistsAtPath:outPath]) + { + outPath = [initialPath stringByAppendingFormat:@"%@", [NSString stringWithFormat:@"~%ld", fileSuffix]]; + fileSuffix++; + } + } } - CFRelease(destination); + return outPath; } -#pragma mark Export CAR +void DumpCGImageToPath(CGImageRef inImage, NSString *inPath) +{ + if(inImage != NULL && inPath != nil) + { + // Get the file URL + CFURLRef fileURL = (__bridge CFURLRef)[NSURL fileURLWithPath:inPath]; + + // Write the CGImageRef to disk + CGImageDestinationRef destinationRef = CGImageDestinationCreateWithURL(fileURL, kUTTypePNG, 1, NULL); + if(destinationRef != NULL) + { + CGImageDestinationAddImage(destinationRef, inImage, nil); + if (!CGImageDestinationFinalize(destinationRef)) + { + NSLog(@"Could not dump the image to %@", inPath); + } + + CFRelease(destinationRef); + } + } +} -void exportCarFileAtPath(NSString * carPath, NSString *outputDirectoryPath) +void ProcessNamedLookup(NSString *inOutputFolder, NSString *fileName, NSString *optionalFileNameComponent, BOOL forceUseOptionalFileNamePathComponent, CGImageRef cgImage, NSData *representation) { - NSError *error = nil; + // + // + // From /Applications/Xcode.app/Contents/Developer/Platforms/AppleTVSimulator.platform/Developer/SDKs/AppleTVSimulator.sdk/System/Library/PrivateFrameworks/CoreThemeDefinition.framework/CoreThemeDefinition + // "ZZZZExplicitlyPackedAsset-%d.%d.%d-gamut%d" + // "ZZZZPackedAsset-%d.%d.%d-gamut%d" + // "ZZZZFlattenedImage-%d.%d.%d" + // "ZZZZRadiosityImage-%d.%d.%d" + // + + if([fileName hasPrefix:@"ZZZZPackedAsset"]) + { + // Ignore ZZZZPackedAsset + return; + } - CUIThemeFacet *facet = [CUIThemeFacet themeWithContentsOfURL:[NSURL fileURLWithPath:carPath] error:&error]; - CUICatalog *catalog = [[CUICatalog alloc] init]; - /* Override CUICatalog to point to a file rather than a bundle */ - [catalog setValue:facet forKey:@"_storageRef"]; - /* CUICommonAssetStorage won't link */ - CUICommonAssetStorage *storage = [[NSClassFromString(@"CUICommonAssetStorage") alloc] initWithPath:carPath]; + NSString *uniqueFilePath = FindUniquePathForPath([inOutputFolder stringByAppendingPathComponent:fileName], optionalFileNameComponent, forceUseOptionalFileNamePathComponent); - for (NSString *key in [storage allRenditionNames]) + if(cgImage != NULL) { - -#ifdef DEBUG - NSLog(@"Writing Image:%@", key); -#endif - - CGImageRef iphone1X = [[catalog imageWithName:key scaleFactor:1.0 deviceIdiom:kCoreThemeIdiomPhone] image]; - CGImageRef iphone2X = [[catalog imageWithName:key scaleFactor:2.0 deviceIdiom:kCoreThemeIdiomPhone] image]; - CGImageRef iphone3X = [[catalog imageWithName:key scaleFactor:3.0 deviceIdiom:kCoreThemeIdiomPhone] image]; - CGImageRef ipad1X = [[catalog imageWithName:key scaleFactor:1.0 deviceIdiom:kCoreThemeIdiomPad] image]; - CGImageRef ipad2X = [[catalog imageWithName:key scaleFactor:2.0 deviceIdiom:kCoreThemeIdiomPad] image]; - - if (iphone1X) - CGImageWriteToFile(iphone1X, [outputDirectoryPath stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.png", key]]); - - if (iphone2X && iphone2X != iphone1X) - CGImageWriteToFile(iphone2X, [outputDirectoryPath stringByAppendingPathComponent:[NSString stringWithFormat:@"%@@2x.png", key]]); - - if (iphone3X && iphone3X != iphone2X) - CGImageWriteToFile(iphone3X, [outputDirectoryPath stringByAppendingPathComponent:[NSString stringWithFormat:@"%@@3x.png", key]]); - - if (ipad1X && ipad1X != iphone1X) - CGImageWriteToFile(ipad1X, [outputDirectoryPath stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.png", key]]); - - if (ipad2X && ipad2X != iphone2X) - CGImageWriteToFile(ipad2X, [outputDirectoryPath stringByAppendingPathComponent:[NSString stringWithFormat:@"%@@2x.png", key]]); + DumpCGImageToPath(cgImage, uniqueFilePath); + } + else if([representation isKindOfClass:[NSData class]]) + { + [(NSData *)representation writeToFile:uniqueFilePath atomically:NO]; + } + else + { + NSLog(@"Nothing to output for %@", uniqueFilePath); + } +} + +void exportCarFileAtPath(NSString * carPath, NSString *outputDirectoryPath) +{ + + outputDirectoryPath = [outputDirectoryPath stringByExpandingTildeInPath]; + + if (![[NSFileManager defaultManager] fileExistsAtPath:outputDirectoryPath]) { + [[NSFileManager defaultManager] createDirectoryAtPath:outputDirectoryPath withIntermediateDirectories:YES attributes:nil error:nil]; } + + + __block NSMutableArray *filenameListM = [NSMutableArray array]; + + ProcessCarFileAtPath(carPath, outputDirectoryPath, ^(NSString *inOutputFolder, CarNamedLookupDict carNamedLookupDict) + { + if(carNamedLookupDict != nil) + { + NSString *fileName = carNamedLookupDict[kCarInfoDict_FilenameKey]; + if([fileName hasPrefix:@"ZZZZExplicitlyPackedAsset-"] || + [fileName hasPrefix:@"ZZZZPackedAsset-"] || + [fileName hasPrefix:@"ZZZZFlattenedImage-"] || + [fileName hasPrefix:@"ZZZZRadiosityImage-"]) + { + // Ignore assets like: + // "ZZZZExplicitlyPackedAsset-%d.%d.%d-gamut%d" + // "ZZZZPackedAsset-%d.%d.%d-gamut%d" + // "ZZZZFlattenedImage-%d.%d.%d" + // "ZZZZRadiosityImage-%d.%d.%d" + return; + } + + if (!fileName || [filenameListM containsObject:fileName]) { + return; + } + + postProccessingNotification(@{@"name":fileName}); + + [filenameListM addObject:fileName]; + + CGImageRef cgImage = (__bridge CGImageRef)(carNamedLookupDict[kCarInfoDict_CGImageKey]); + NSData *assetData = carNamedLookupDict[kCarInfoDict_DataKey]; + + NSString *optionalFileNamePathComponent = nil; + if(cgImage != nil) + { + optionalFileNamePathComponent = [NSString stringWithFormat:@"%ldx%ld", CGImageGetWidth(cgImage), CGImageGetHeight(cgImage)]; + } + + BOOL forceUseOptionalFileNamePathComponent = [carNamedLookupDict[kCarInfoDict_IsMultisizeImageKey] boolValue]; + ProcessNamedLookup(inOutputFolder, fileName, optionalFileNamePathComponent, forceUseOptionalFileNamePathComponent, cgImage, assetData); + } + }); } + int main(int argc, const char * argv[]) { @autoreleasepool { + if (argc > 3) { + for (int i = 2; i < argc; ++i) { + NSString *argvString = [NSString stringWithUTF8String:argv[i]]; + if ([argvString containsString:@"--DistributedNotificationName="]) { + NSArray *components = [argvString componentsSeparatedByString:@"="]; + if (components.count == 2) { + kProccessingNotificationName = components.lastObject.length > 0 ? components.lastObject : nil; + } + break; + } + } + } - //Check inputs - NSString *input = [[NSUserDefaults standardUserDefaults] stringForKey:@"i"]; - NSString *output = [[NSUserDefaults standardUserDefaults] stringForKey:@"o"]; - if (!input || !output) { -#ifdef DEBUG - NSLog(@"Invalid call, missing input or output."); -#endif - return 1; - } + exportCarFileAtPath([NSString stringWithUTF8String:argv[1]], argc > 2 ? [NSString stringWithUTF8String:argv[2]] : nil); - exportCarFileAtPath(input, output); } return 0; } diff --git a/CARExtractor/QLCARFiles b/CARExtractor/QLCARFiles new file mode 160000 index 0000000..1cab8d2 --- /dev/null +++ b/CARExtractor/QLCARFiles @@ -0,0 +1 @@ +Subproject commit 1cab8d26c2a157721384f0a089accaaf93860f1b diff --git a/README.md b/README.md index f8796a6..a362bb6 100644 --- a/README.md +++ b/README.md @@ -1,26 +1,43 @@ -#iOS Images Extractor -iOS Images Extractor is a Mac app to normalize , decode and extract images from iOS apps. +# iOS Images Extractor +iOS Images Extractor is a Mac app to normalize, decode and extract images from iOS apps. You can download binary release from the [latest releases](https://github.com/devcxm/iOS-Images-Extractor/releases/latest). (Sorry for my bad English) -##Support Files +![logo](https://raw.githubusercontent.com/devcxm/iOS-Images-Extractor/master/iOSImagesExtractor/iOSImagesExtractor/Images.xcassets/AppIcon.appiconset/AppIcon-256.png) + +## Support Files - `png、jpg` - `ipa` - `car(Assets.car)` -##Usage -###[中文使用方法看这里](/README_zh-Hans.md) +## Build +``` +git clone https://github.com/devcxm/iOS-Images-Extractor +cd iOS-Images-Extractor +git submodule update --init --recursive +open iOSImagesExtractor.xcworkspace +``` +### [中文使用方法看这里](/README_zh-Hans.md) -##Screenshot +## Screenshot ![(Screenshot)](https://cloud.githubusercontent.com/assets/8568955/7927878/874f0594-0918-11e5-9fe3-452372f5affd.gif) +## Requirements +_**OS X 10.14 or later.**_ + +## Change Logs +* v0.4.0 2020-06-03 + * Replace extractor with [Timac/QLCARFiles](https://github.com/Timac/QLCARFiles). + * Support export raw PDF files. + * Better output folder grading. + * Quickly install `QLCARFiles`(macOS QuickLook Plugin) to visualize .car files. -##Download -####You can download binary release from the [latest releases](https://github.com/devcxm/iOS-Images-Extractor/releases/latest). +- v0.3.1 2016-05-15 + * Add app icons and update CARExtractor. -##Requirements -_**OS X 10.8 or later.**_ +- v0.2.5 2015-06-02 + * First release. -##Credits +## Credits - Matt Connolly [ZipArchive](https://github.com/mattconnolly/ZipArchive) @@ -28,6 +45,8 @@ _**OS X 10.8 or later.**_ - Danger Cove [DCOAboutWindow](https://github.com/DangerCove/DCOAboutWindow) +- Timac [QLCARFiles](https://github.com/Timac/QLCARFiles) + ## License iOS Images Extractor is released under the MIT license. See [LICENSE](/LICENSE) for details. diff --git a/README_zh-Hans.md b/README_zh-Hans.md index 2a62b9c..3470554 100644 --- a/README_zh-Hans.md +++ b/README_zh-Hans.md @@ -1,14 +1,13 @@ -#中文使用说明 +# 中文使用说明 -##发行版本 +## 发行版本 -###下载地址:[百度网盘下载](http://pan.baidu.com/s/1jG9wZcU) +### 下载地址:[百度网盘下载](http://pan.baidu.com/s/1i4T8seT) -##系统要求 -* 软件最低支持OS X 10.8 -* 解压Assets.car文件需要OS X 10.10或以上版本的系统 +## 系统要求 +* OS X 10.14 -##使用说明 -###打开软件后,拖拽`ipa`、`car文件`、`png`、`jpg`或者`整个文件夹`到软件窗口,点击`Start`按钮即可开始提取图片资源文件。 -###图片默认输出到`/User/用户名/Downloads/iOSImagesExtractor`文件夹,可直接点击`Output Dir`按钮快速跳转到输出文件夹。 +## 使用说明 +### 打开软件后,拖拽`ipa`、`car文件`、`png`、`jpg`或者`整个文件夹`到软件窗口,点击`Start`按钮即可开始提取图片资源文件。 +### 图片默认输出到`/User/用户名/Downloads/iOSImagesExtractor`文件夹,可直接点击`Output Dir`按钮快速跳转到输出文件夹。 diff --git a/iOSImagesExtractor.xcworkspace/contents.xcworkspacedata b/iOSImagesExtractor.xcworkspace/contents.xcworkspacedata index 4a037f5..adda89b 100755 --- a/iOSImagesExtractor.xcworkspace/contents.xcworkspacedata +++ b/iOSImagesExtractor.xcworkspace/contents.xcworkspacedata @@ -4,7 +4,4 @@ - - diff --git a/iOSImagesExtractor.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/iOSImagesExtractor.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/iOSImagesExtractor.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/iOSImagesExtractor/iOSImagesExtractor.xcodeproj/project.pbxproj b/iOSImagesExtractor/iOSImagesExtractor.xcodeproj/project.pbxproj index 1a1f1c5..434758b 100755 --- a/iOSImagesExtractor/iOSImagesExtractor.xcodeproj/project.pbxproj +++ b/iOSImagesExtractor/iOSImagesExtractor.xcodeproj/project.pbxproj @@ -7,6 +7,9 @@ objects = { /* Begin PBXBuildFile section */ + 892829E22485EC1C009E0A31 /* QLCARFiles.qlgenerator in Resources */ = {isa = PBXBuildFile; fileRef = 892829E02485EC1C009E0A31 /* QLCARFiles.qlgenerator */; }; + 8982EB4C2485060C00BCB558 /* CARExtractor in Resources */ = {isa = PBXBuildFile; fileRef = 8982EB4B2485060C00BCB558 /* CARExtractor */; }; + 89A989562486368C009170D0 /* NSAlert+XM.m in Sources */ = {isa = PBXBuildFile; fileRef = 89A989552486368C009170D0 /* NSAlert+XM.m */; }; C24D24F01B16047E00DDE534 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = C24D24EF1B16047E00DDE534 /* Images.xcassets */; }; C24D25141B16051500DDE534 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = C24D25121B16051500DDE534 /* AppDelegate.m */; }; C24D25151B16051500DDE534 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = C24D25131B16051500DDE534 /* main.m */; }; @@ -27,10 +30,53 @@ C24D25531B16120100DDE534 /* Credits.rtf in Resources */ = {isa = PBXBuildFile; fileRef = C24D25511B16120100DDE534 /* Credits.rtf */; }; C2AE37681B1992090099434F /* LICENSE in Resources */ = {isa = PBXBuildFile; fileRef = C2AE37671B1992090099434F /* LICENSE */; }; C2CF8B821B17F7EC00AA92B1 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = C24D24F11B16047E00DDE534 /* MainMenu.xib */; }; - C2CF8B861B1805EF00AA92B1 /* CARExtractor in Resources */ = {isa = PBXBuildFile; fileRef = C2CF8B851B1805EF00AA92B1 /* CARExtractor */; }; /* End PBXBuildFile section */ +/* Begin PBXContainerItemProxy section */ + 8962398D248508EE005E7EC9 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 89623989248508EE005E7EC9 /* CARExtractor.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 8982EB242484F82200BCB558; + remoteInfo = CARExtractor; + }; + 8962398F24850902005E7EC9 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 89623989248508EE005E7EC9 /* CARExtractor.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = 8982EB232484F82200BCB558; + remoteInfo = CARExtractor; + }; + 897AD2972485E812002D1D58 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 897AD2922485E812002D1D58 /* QLCARFiles.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = FA11D6741E7BF96900912157; + remoteInfo = QLCARFiles; + }; + 897AD2992485E812002D1D58 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 897AD2922485E812002D1D58 /* QLCARFiles.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 029425B6217D00FF00ED1FA5; + remoteInfo = carDump; + }; + 897AD29B2485E84A002D1D58 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 897AD2922485E812002D1D58 /* QLCARFiles.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = FA11D6731E7BF96900912157; + remoteInfo = QLCARFiles; + }; +/* End PBXContainerItemProxy section */ + /* Begin PBXFileReference section */ + 892829E02485EC1C009E0A31 /* QLCARFiles.qlgenerator */ = {isa = PBXFileReference; lastKnownFileType = file; name = QLCARFiles.qlgenerator; path = ../../Products/QLCARFiles.qlgenerator; sourceTree = ""; }; + 89623989248508EE005E7EC9 /* CARExtractor.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = CARExtractor.xcodeproj; path = ../CARExtractor/CARExtractor.xcodeproj; sourceTree = ""; }; + 897AD2922485E812002D1D58 /* QLCARFiles.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = QLCARFiles.xcodeproj; path = ../CARExtractor/QLCARFiles/QLCARFiles.xcodeproj; sourceTree = ""; }; + 8982EB4B2485060C00BCB558 /* CARExtractor */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.executable"; name = CARExtractor; path = ../../Products/CARExtractor; sourceTree = ""; }; + 89A989542486368C009170D0 /* NSAlert+XM.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSAlert+XM.h"; sourceTree = ""; }; + 89A989552486368C009170D0 /* NSAlert+XM.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "NSAlert+XM.m"; sourceTree = ""; }; C24D24E51B16047E00DDE534 /* iOS Images Extractor.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "iOS Images Extractor.app"; sourceTree = BUILT_PRODUCTS_DIR; }; C24D24E91B16047E00DDE534 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; C24D24EF1B16047E00DDE534 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; @@ -81,9 +127,28 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 8962398A248508EE005E7EC9 /* Products */ = { + isa = PBXGroup; + children = ( + 8962398E248508EE005E7EC9 /* CARExtractor */, + ); + name = Products; + sourceTree = ""; + }; + 897AD2932485E812002D1D58 /* Products */ = { + isa = PBXGroup; + children = ( + 897AD2982485E812002D1D58 /* QLCARFiles.qlgenerator */, + 897AD29A2485E812002D1D58 /* carDump */, + ); + name = Products; + sourceTree = ""; + }; C24D24DC1B16047D00DDE534 = { isa = PBXGroup; children = ( + 897AD2922485E812002D1D58 /* QLCARFiles.xcodeproj */, + 89623989248508EE005E7EC9 /* CARExtractor.xcodeproj */, C24D24E71B16047E00DDE534 /* iOSImagesExtractor */, C24D24E61B16047E00DDE534 /* Products */, ); @@ -207,6 +272,8 @@ children = ( C24D253C1B16058A00DDE534 /* XMDragView.h */, C24D253D1B16058A00DDE534 /* XMDragView.m */, + 89A989542486368C009170D0 /* NSAlert+XM.h */, + 89A989552486368C009170D0 /* NSAlert+XM.m */, ); path = Views; sourceTree = ""; @@ -215,8 +282,10 @@ isa = PBXGroup; children = ( C24D254F1B1611F300DDE534 /* About */, + 892829E02485EC1C009E0A31 /* QLCARFiles.qlgenerator */, C24D24EF1B16047E00DDE534 /* Images.xcassets */, C24D24F11B16047E00DDE534 /* MainMenu.xib */, + 8982EB4B2485060C00BCB558 /* CARExtractor */, ); name = Resources; sourceTree = ""; @@ -266,6 +335,8 @@ buildRules = ( ); dependencies = ( + 897AD29C2485E84A002D1D58 /* PBXTargetDependency */, + 8962399024850902005E7EC9 /* PBXTargetDependency */, ); name = iOSImagesExtractor; productName = iOSImagesExtractor; @@ -291,12 +362,23 @@ developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( + English, en, Base, ); mainGroup = C24D24DC1B16047D00DDE534; productRefGroup = C24D24E61B16047E00DDE534 /* Products */; projectDirPath = ""; + projectReferences = ( + { + ProductGroup = 8962398A248508EE005E7EC9 /* Products */; + ProjectRef = 89623989248508EE005E7EC9 /* CARExtractor.xcodeproj */; + }, + { + ProductGroup = 897AD2932485E812002D1D58 /* Products */; + ProjectRef = 897AD2922485E812002D1D58 /* QLCARFiles.xcodeproj */; + }, + ); projectRoot = ""; targets = ( C24D24E41B16047D00DDE534 /* iOSImagesExtractor */, @@ -304,14 +386,39 @@ }; /* End PBXProject section */ +/* Begin PBXReferenceProxy section */ + 8962398E248508EE005E7EC9 /* CARExtractor */ = { + isa = PBXReferenceProxy; + fileType = "compiled.mach-o.executable"; + path = CARExtractor; + remoteRef = 8962398D248508EE005E7EC9 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 897AD2982485E812002D1D58 /* QLCARFiles.qlgenerator */ = { + isa = PBXReferenceProxy; + fileType = wrapper.cfbundle; + path = QLCARFiles.qlgenerator; + remoteRef = 897AD2972485E812002D1D58 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 897AD29A2485E812002D1D58 /* carDump */ = { + isa = PBXReferenceProxy; + fileType = "compiled.mach-o.executable"; + path = carDump; + remoteRef = 897AD2992485E812002D1D58 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; +/* End PBXReferenceProxy section */ + /* Begin PBXResourcesBuildPhase section */ C24D24E31B16047D00DDE534 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - C2CF8B861B1805EF00AA92B1 /* CARExtractor in Resources */, + 892829E22485EC1C009E0A31 /* QLCARFiles.qlgenerator in Resources */, C2CF8B821B17F7EC00AA92B1 /* MainMenu.xib in Resources */, C24D254B1B16110000DDE534 /* DCOAboutWindow.xib in Resources */, + 8982EB4C2485060C00BCB558 /* CARExtractor in Resources */, C2AE37681B1992090099434F /* LICENSE in Resources */, C24D25531B16120100DDE534 /* Credits.rtf in Resources */, C24D24F01B16047E00DDE534 /* Images.xcassets in Resources */, @@ -333,7 +440,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "mkdir -p \"${PROJECT_DIR}/../Products\";\ncp -r \"${TARGET_BUILD_DIR}/${PRODUCT_NAME}.app\" \"${PROJECT_DIR}/../Products/${PRODUCT_NAME}.app\""; + shellScript = "mkdir -p \"${PROJECT_DIR}/../Products\";\nrm -rf \"${PROJECT_DIR}/../Products/${PRODUCT_NAME}.app\";\ncp -r \"${TARGET_BUILD_DIR}/${PRODUCT_NAME}.app\" \"${PROJECT_DIR}/../Products/${PRODUCT_NAME}.app\"\n"; }; /* End PBXShellScriptBuildPhase section */ @@ -346,6 +453,7 @@ C24D25301B16053200DDE534 /* ZipArchive.m in Sources */, C24D252F1B16053200DDE534 /* zip.c in Sources */, C24D254D1B16110000DDE534 /* DCOTransparentScroller.m in Sources */, + 89A989562486368C009170D0 /* NSAlert+XM.m in Sources */, C24D25351B16054000DDE534 /* MainViewController.m in Sources */, C24D254E1B16110000DDE534 /* DCOTransparentScrollView.m in Sources */, C24D252E1B16053200DDE534 /* unzip.c in Sources */, @@ -360,6 +468,19 @@ }; /* End PBXSourcesBuildPhase section */ +/* Begin PBXTargetDependency section */ + 8962399024850902005E7EC9 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = CARExtractor; + targetProxy = 8962398F24850902005E7EC9 /* PBXContainerItemProxy */; + }; + 897AD29C2485E84A002D1D58 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = QLCARFiles; + targetProxy = 897AD29B2485E84A002D1D58 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + /* Begin PBXVariantGroup section */ C24D24F11B16047E00DDE534 /* MainMenu.xib */ = { isa = PBXVariantGroup; @@ -453,9 +574,11 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; COMBINE_HIDPI_IMAGES = YES; + CURRENT_PROJECT_VERSION = 0603; INFOPLIST_FILE = iOSImagesExtractor/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; - MACOSX_DEPLOYMENT_TARGET = 10.8; + MACOSX_DEPLOYMENT_TARGET = 10.14; + MARKETING_VERSION = 0.4.0; PRODUCT_NAME = "iOS Images Extractor"; SDKROOT = macosx; }; @@ -466,9 +589,11 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; COMBINE_HIDPI_IMAGES = YES; + CURRENT_PROJECT_VERSION = 0603; INFOPLIST_FILE = iOSImagesExtractor/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; - MACOSX_DEPLOYMENT_TARGET = 10.8; + MACOSX_DEPLOYMENT_TARGET = 10.14; + MARKETING_VERSION = 0.4.0; PRODUCT_NAME = "iOS Images Extractor"; SDKROOT = macosx; }; diff --git a/iOSImagesExtractor/iOSImagesExtractor.xcodeproj/xcshareddata/xcschemes/iOSImagesExtractor.xcscheme b/iOSImagesExtractor/iOSImagesExtractor.xcodeproj/xcshareddata/xcschemes/iOSImagesExtractor.xcscheme index 29975d9..5743f89 100644 --- a/iOSImagesExtractor/iOSImagesExtractor.xcodeproj/xcshareddata/xcschemes/iOSImagesExtractor.xcscheme +++ b/iOSImagesExtractor/iOSImagesExtractor.xcodeproj/xcshareddata/xcschemes/iOSImagesExtractor.xcscheme @@ -14,7 +14,7 @@ buildForAnalyzing = "YES"> @@ -37,12 +37,10 @@ - - + shouldUseLaunchSchemeArgsEnv = "YES"> + + @@ -72,14 +73,12 @@ ReferencedContainer = "container:iOSImagesExtractor.xcodeproj"> - - diff --git a/iOSImagesExtractor/iOSImagesExtractor/Classes/Main/App/AppDelegate.m b/iOSImagesExtractor/iOSImagesExtractor/Classes/Main/App/AppDelegate.m index 1caa7fb..c995032 100755 --- a/iOSImagesExtractor/iOSImagesExtractor/Classes/Main/App/AppDelegate.m +++ b/iOSImagesExtractor/iOSImagesExtractor/Classes/Main/App/AppDelegate.m @@ -48,8 +48,7 @@ - (void)applicationDidFinishLaunching:(NSNotification *)aNotification { NSArray *consV = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-0.0-[selfView]-0.0-|" options:0 metrics:nil views:views]; [selfView.superview addConstraints:consV]; - - + [self.mainVc checkForUpdates:NO]; } - (IBAction)showAboutWindow:(id)sender { @@ -62,6 +61,10 @@ - (IBAction)showAboutWindow:(id)sender { [self.aboutWindowController showWindow:nil]; } +- (void)application:(NSApplication *)sender openFiles:(NSArray *)filenames { + NSLog(@""); +} + - (void)applicationWillTerminate:(NSNotification *)aNotification { // Insert code here to tear down your application } diff --git a/iOSImagesExtractor/iOSImagesExtractor/Classes/Main/Controllers/MainViewController.h b/iOSImagesExtractor/iOSImagesExtractor/Classes/Main/Controllers/MainViewController.h index 6b880e9..f79fe74 100755 --- a/iOSImagesExtractor/iOSImagesExtractor/Classes/Main/Controllers/MainViewController.h +++ b/iOSImagesExtractor/iOSImagesExtractor/Classes/Main/Controllers/MainViewController.h @@ -16,4 +16,6 @@ @interface MainViewController : NSViewController +- (void)checkForUpdates:(BOOL)manualCheck; + @end diff --git a/iOSImagesExtractor/iOSImagesExtractor/Classes/Main/Controllers/MainViewController.m b/iOSImagesExtractor/iOSImagesExtractor/Classes/Main/Controllers/MainViewController.m index aba15a5..a1baafc 100755 --- a/iOSImagesExtractor/iOSImagesExtractor/Classes/Main/Controllers/MainViewController.m +++ b/iOSImagesExtractor/iOSImagesExtractor/Classes/Main/Controllers/MainViewController.m @@ -8,16 +8,16 @@ #import "MainViewController.h" -#pragma mark - libs +#pragma mark - Vendors #import "ZipArchive.h" -#pragma mark - models +#pragma mark - Models #import "XMFileItem.h" -#pragma mark - views +#pragma mark - Views #import "XMDragView.h" - +#import "NSAlert+XM.h" @interface MainViewController () @@ -94,12 +94,43 @@ @interface MainViewController () */ - (IBAction)clickButton:(NSButton*)sender { @@ -161,22 +196,40 @@ - (IBAction)clickButton:(NSButton*)sender { [[NSWorkspace sharedWorkspace] activateFileViewerSelectingURLs:fileURLs]; } else { - NSAlert *alert = [NSAlert alertWithMessageText:@"No Output" defaultButton:@"OK" alternateButton:nil otherButton:nil informativeTextWithFormat:@"There is no output."]; - [alert beginSheetModalForWindow:self.view.window completionHandler:nil]; + + [[NSAlert xm_alertWithMessageText:@"No Output" informativeText:@"There is no output." defaultButton:nil] beginSheetModalForWindow:self.view.window completionHandler:nil]; } } else if (sender.tag == 400) {// About - - [[NSApplication sharedApplication].delegate performSelector:NSSelectorFromString(@"showAboutWindow:") withObject:nil]; + NSMenu * menu = [[NSMenu alloc] initWithTitle:@"More Options"]; + { + NSMenuItem *installOrRemovePluginItem = [[NSMenuItem alloc] initWithTitle:[NSString stringWithFormat:@"%@ QLCARFiles QuickLook Plugin", ([[NSFileManager defaultManager] fileExistsAtPath:[self.class QuickLookpluginInstallLocation]] ? @"Remove" : @"Install")] action:@selector(clickMenuItem:) keyEquivalent:@""]; + installOrRemovePluginItem.target = self; + installOrRemovePluginItem.tag = 1000; + + NSMenuItem *checkForUpdatesItem = [[NSMenuItem alloc] initWithTitle:@"Check for Updates" action:@selector(clickMenuItem:) keyEquivalent:@""]; + checkForUpdatesItem.target = self; + checkForUpdatesItem.tag = 2000; + + NSMenuItem * aboutItem = [[NSMenuItem alloc] initWithTitle:@"About" action:@selector(clickMenuItem:) keyEquivalent:@""]; + aboutItem.target = self; + aboutItem.tag = 9001; + + [menu addItem:installOrRemovePluginItem]; + [menu addItem:[NSMenuItem separatorItem]]; + [menu addItem:checkForUpdatesItem]; + [menu addItem:[NSMenuItem separatorItem]]; + [menu addItem:aboutItem]; + + [NSMenu popUpContextMenu:menu withEvent:[NSApplication sharedApplication].currentEvent forView:sender]; + } } else if (sender.tag == 200) {// Start if (self.dragFileList.count < 1) { - NSAlert *alert = [NSAlert alertWithMessageText:@"Error" defaultButton:@"OK" alternateButton:nil otherButton:nil informativeTextWithFormat:@"Drag files into window first."]; - [alert beginSheetModalForWindow:self.view.window completionHandler:nil]; - + [[NSAlert xm_alertWithMessageText:@"Error" informativeText:@"Drag files into window first." defaultButton:nil] beginSheetModalForWindow:self.view.window completionHandler:nil]; return; } @@ -216,10 +269,9 @@ - (IBAction)clickButton:(NSButton*)sender { XMFileItem *fileItem = carArray[i]; - NSString *outputPath = [existCarPath stringByAppendingPathComponent:[NSString stringWithFormat:@"car_images_%@", [MainViewController getRandomStringWithCount:5] - ]]; - [self setStatusString:[NSString stringWithFormat:@"Processing %@ ...", fileItem.fileName]]; - [self doCarFilesWithPath:fileItem.filePath outputPath:outputPath]; + NSString *outputPath = [existCarPath stringByAppendingPathComponent:[NSString stringWithFormat:@"car_images_%@", [MainViewController getRandomStringWithCount:5]]]; +// [self setStatusString:[NSString stringWithFormat:@"Processing %@ ...", fileItem.fileName]]; + [self exportCarFileAtPath:fileItem.filePath outputPath:outputPath tag:nil]; } } @@ -242,14 +294,107 @@ - (IBAction)clickButton:(NSButton*)sender { [self.allFileList removeAllObjects]; }); }); + } +} + + +- (void)clickMenuItem:(NSMenuItem *)sender { + + if (sender.tag == 1000) { + NSString *destPath = [self.class QuickLookpluginInstallLocation]; + NSString *informativeText = nil; + if ([[NSFileManager defaultManager] fileExistsAtPath:destPath]) { + [self.class excuteShellScript:[NSString stringWithFormat:@"rm -rf %@;qlmanage -r;", destPath.xm_shellPath]]; + informativeText = @"Remove QLCARFiles successfully."; + } else { + NSString *qlgeneratorSourcePath = [[NSBundle mainBundle].resourcePath stringByAppendingPathComponent:@"QLCARFiles.qlgenerator"]; + [self.class excuteShellScript:[NSString stringWithFormat:@"xattr -c -r %@;cp -r %@ %@;qlmanage -r;", qlgeneratorSourcePath.xm_shellPath, qlgeneratorSourcePath.xm_shellPath, destPath.xm_shellPath]]; + informativeText = @"Install QLCARFiles successfully, if QuickLook plugins not woking, you can try to log out macOS, then log in back."; + } + [[NSAlert xm_alertWithMessageText:@"macOS Quick Look Plugin" informativeText:informativeText defaultButton:nil] beginSheetModalForWindow:self.view.window completionHandler:nil]; - + } else if (sender.tag == 2000) { + [self checkForUpdates:YES]; + } else if (sender.tag == 9001) { + [[NSApplication sharedApplication].delegate performSelector:NSSelectorFromString(@"showAboutWindow:") withObject:nil]; } } +#pragma mark - Private Method ++ (NSString *)QuickLookpluginInstallLocation { + NSString *location = [@"~/Library/QuickLook/QLCARFiles.qlgenerator" stringByExpandingTildeInPath]; + return location; +} + ++ (void)excuteShellScript:(NSString *)script +{ + // 初始化并设置shell路径 + NSTask *task = [[NSTask alloc] init]; + [task setLaunchPath: @"/bin/bash"]; + // -c 用来执行string-commands(命令字符串),也就说不管后面的字符串里是什么都会被当做shellcode来执行 + NSArray *arguments = [NSArray arrayWithObjects: @"-c", script, nil]; + [task setArguments: arguments]; + + // 新建输出管道作为Task的输出 + NSPipe *pipe = [NSPipe pipe]; + [task setStandardOutput: pipe]; + + // 开始task + NSFileHandle *file = [pipe fileHandleForReading]; + [task launch]; + + // 获取运行结果 + NSData *data = [file readDataToEndOfFile]; + NSString *output = [[NSString alloc] initWithData: data encoding: NSUTF8StringEncoding]; + + XMLog(@"%@", output); +} + +#pragma mark - Public Method + +- (void)checkForUpdates:(BOOL)manualCheck { + [[[NSURLSession sharedSession] dataTaskWithURL:[NSURL URLWithString:@"https://raw.githubusercontent.com/devcxm/iOS-Images-Extractor/pages/appfiles/appinfos.json"] completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) { + if (!error && data) { + NSDictionary *JSONObject = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil]; + if ([JSONObject isKindOfClass:[NSDictionary class]] && JSONObject.count > 3) { + dispatch_async(dispatch_get_main_queue(), ^{ + NSString *appVersion = [[NSBundle mainBundle].infoDictionary objectForKey:@"CFBundleShortVersionString"]; + NSString *latestVersion = [JSONObject objectForKey:@"version"]; + + if ([appVersion compare:latestVersion options:NSNumericSearch] == NSOrderedAscending) { + NSAlert *updateAlert = [[NSAlert alloc] init]; + updateAlert.messageText = @"New Update Available"; + updateAlert.informativeText = [JSONObject objectForKey:@"changelog"]; + [updateAlert addButtonWithTitle:@"Download"]; + [updateAlert addButtonWithTitle:@"Close"]; + __weak typeof(updateAlert) weakAlert = updateAlert; + [updateAlert beginSheetModalForWindow:self.view.window completionHandler:^(NSModalResponse returnCode) { + if (weakAlert.buttons.firstObject.tag == returnCode) { + [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:[JSONObject objectForKey:@"app_update_url"]]]; + } + }]; + + } else { + if (manualCheck) { + [[NSAlert xm_alertWithMessageText:@"Update" informativeText:@"No update available." defaultButton:nil] beginSheetModalForWindow:self.view.window completionHandler:nil]; + } + } + }); + + } + } else { + if (manualCheck) { + dispatch_async(dispatch_get_main_queue(), ^{ + [[NSAlert xm_alertWithMessageText:@"Update" informativeText:@"Failed to check for updates." defaultButton:nil] beginSheetModalForWindow:self.view.window completionHandler:nil]; + }); + } + + } + }] resume]; +} #pragma mark - XMDragViewDelegate @@ -315,7 +460,7 @@ - (void)addPathsWithArray:(NSArray*)path } -#pragma mark - business +#pragma mark - Extract Methods /** * 遍历获取拖进来的所有的文件 @@ -419,8 +564,17 @@ - (void)doZipFilesWithPath:(NSString*)path outputPath:(NSString*)outputPath for (int i = 0; i < carArrayM.count; ++i) {// 处理car文件 XMFileItem *fileItem = carArrayM[i]; - [self setStatusString:[NSString stringWithFormat:@"Processing %@ ...", fileItem.fileName]]; - [self doCarFilesWithPath:fileItem.filePath outputPath:[outputPath stringByAppendingPathComponent:@"car_images"]]; +// [self setStatusString:[NSString stringWithFormat:@"Processing %@ ...", fileItem.fileName]]; + NSString *tag = nil; + // ipa安装包不只1个car文件时,放在不同的文件夹 + if (carArrayM.count > 1) { + NSString *filePath = fileItem.filePath; + if ([[filePath stringByDeletingLastPathComponent].pathExtension isEqualToString:@"app"]) { + tag = @"AppRoot"; + } + } + + [self exportCarFileAtPath:fileItem.filePath outputPath:[outputPath stringByAppendingPathComponent:@"car_images"] tag:tag]; } } @@ -443,10 +597,10 @@ - (void)doPngOrJpgFileWithPath:(NSString*)path outputPath:(NSString*)outputPath NSData *saveData = nil; if ([extension isEqualToString:@"png"]) { - saveData = [self imageDataWithImage:tmpImage bitmapImageFileType:NSPNGFileType]; + saveData = [self imageDataWithImage:tmpImage bitmapImageFileType:NSBitmapImageFileTypePNG]; } else if ([extension isEqualToString:@"jpg"]){ - saveData = [self imageDataWithImage:tmpImage bitmapImageFileType:NSJPEGFileType]; + saveData = [self imageDataWithImage:tmpImage bitmapImageFileType:NSBitmapImageFileTypeJPEG]; } // 写入新文件 @@ -466,7 +620,7 @@ - (void)doPngOrJpgFileWithPath:(NSString*)path outputPath:(NSString*)outputPath - (NSData*)imageDataWithImage:(NSImage*)image bitmapImageFileType:(NSBitmapImageFileType)fileType { NSBitmapImageRep *rep = [NSBitmapImageRep imageRepWithData:[image TIFFRepresentation]]; - return [rep representationUsingType:fileType properties:nil]; + return [rep representationUsingType:fileType properties:@{}]; } /** @@ -475,61 +629,45 @@ - (NSData*)imageDataWithImage:(NSImage*)image bitmapImageFileType:(NSBitmapImage * @param path Assets.car路径 * @param outputPath 保存路径 */ -- (void)doCarFilesWithPath:(NSString*)path outputPath:(NSString*)outputPath -{ - +- (void)exportCarFileAtPath:(NSString*)path outputPath:(NSString*)outputPath tag:(NSString *)tag { // 判断CARExtractor处理程序是否存在 if (self.carExtractorLocation.length < 1) { dispatch_sync(dispatch_get_main_queue(), ^{ - NSAlert *alert = [NSAlert alertWithMessageText:@"Error" defaultButton:@"OK" alternateButton:nil otherButton:nil informativeTextWithFormat:@"Can't find CARExtractor"]; - [alert beginSheetModalForWindow:self.view.window completionHandler:nil]; + [[NSAlert xm_alertWithMessageText:@"Error" informativeText:@"Can't find CARExtractor." defaultButton:nil] beginSheetModalForWindow:self.view.window completionHandler:nil]; }); return; } - // 以下源代码来自https://github.com/Marxon13/iOS-Asset-Extractor + if (tag.length == 0) { + NSString *bundleName = [path stringByDeletingLastPathComponent].lastPathComponent; + if ([bundleName.pathExtension caseInsensitiveCompare:@"bundle"] == NSOrderedSame) { + tag = [bundleName stringByReplacingOccurrencesOfString:@"." withString:@"_"]; + } + } + + if (tag.length > 0) { + outputPath = [outputPath stringByAppendingPathComponent:tag]; + } + - //Create the task to run the process NSTask *task = [[NSTask alloc] init]; [task setLaunchPath:self.carExtractorLocation]; - NSArray *arguments = @[@"-i", path, @"-o", outputPath]; + NSArray *arguments = @[path, outputPath, [NSString stringWithFormat:@"--DistributedNotificationName=%@", [NSBundle mainBundle].bundleIdentifier]]; [task setArguments:arguments]; - //Handle output - NSPipe *pipe = [[NSPipe alloc] init]; - task.standardOutput = pipe; - - [pipe.fileHandleForReading waitForDataInBackgroundAndNotify]; - [[NSNotificationCenter defaultCenter] addObserverForName:NSFileHandleDataAvailableNotification object:[pipe fileHandleForReading] queue:nil usingBlock:^(NSNotification *notification){ -// NSData *output = [[pipe fileHandleForReading] availableData]; -// NSString *outString = [[NSString alloc] initWithData:output encoding:NSUTF8StringEncoding]; -// XMLog(@"ddddddddd%@", outString); -// if (outputPath.length > 0) { -// [self setStatusString:outString]; -// } - - [[pipe fileHandleForReading] waitForDataInBackgroundAndNotify]; - }]; - //Run the task [task launch]; [task waitUntilExit]; - - [[NSNotificationCenter defaultCenter] removeObserver:nil name:NSFileHandleDataAvailableNotification object:[pipe fileHandleForReading]]; - } - /** * 遍历路径下特定扩展名的文件 * * @param path 遍历路径 * @param extensionArray 包含的扩展名 - * - * @return <#return value description#> */ + (NSArray*)getFileListWithPath:(NSString*)path extensions:(NSArray*)extensionArray { @@ -582,7 +720,7 @@ + (void)createDirectoryWithPath:(NSString*)path if (err) { - XMLog(@"come here <#identifier#> %@ ...", err.localizedDescription); + XMLog(@"come here %@ ...", err.localizedDescription); } } @@ -590,9 +728,6 @@ + (void)createDirectoryWithPath:(NSString*)path /** * 获取随机字符串 * - * @param count <#count description#> - * - * @return <#return value description#> */ + (NSString*)getRandomStringWithCount:(NSInteger)count { @@ -618,14 +753,14 @@ - (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView { //- (NSView *)tableView:(NSTableView *)tableView // viewForTableColumn:(NSTableColumn *)tableColumn // row:(NSInteger)row { -// +// // // Retrieve to get the @"MyView" from the pool or, // // if no version is available in the pool, load the Interface Builder version // NSTableCellView *result = [tableView makeViewWithIdentifier:@"MyView" owner:self]; -// +// // // Set the stringValue of the cell's text field to the nameArray value at row // result.textField.stringValue = [self.numberCodes objectAtIndex:row]; -// +// // // Return the result // return result; //} diff --git a/iOSImagesExtractor/iOSImagesExtractor/Classes/Main/Controllers/MainViewController.xib b/iOSImagesExtractor/iOSImagesExtractor/Classes/Main/Controllers/MainViewController.xib index 3ffea48..19b3cf3 100755 --- a/iOSImagesExtractor/iOSImagesExtractor/Classes/Main/Controllers/MainViewController.xib +++ b/iOSImagesExtractor/iOSImagesExtractor/Classes/Main/Controllers/MainViewController.xib @@ -1,8 +1,9 @@ - - + + - + + @@ -32,7 +33,7 @@ - + @@ -44,7 +45,7 @@ - + - + - - + + diff --git a/iOSImagesExtractor/iOSImagesExtractor/Classes/Main/Models/XMFileItem.h b/iOSImagesExtractor/iOSImagesExtractor/Classes/Main/Models/XMFileItem.h index ff9aabe..a371d82 100755 --- a/iOSImagesExtractor/iOSImagesExtractor/Classes/Main/Models/XMFileItem.h +++ b/iOSImagesExtractor/iOSImagesExtractor/Classes/Main/Models/XMFileItem.h @@ -34,7 +34,14 @@ @property (nonatomic, assign, readonly) BOOL isFileExists; -#pragma mark - 类工厂 +#pragma mark - 类方法 + (instancetype)xmFileItemWithPath:(NSString*)filePath; @end + + +@interface NSString (_ShellPath) + +@property (nonatomic, copy, readonly) NSString *xm_shellPath; + +@end diff --git a/iOSImagesExtractor/iOSImagesExtractor/Classes/Main/Models/XMFileItem.m b/iOSImagesExtractor/iOSImagesExtractor/Classes/Main/Models/XMFileItem.m index 22d1c9f..1af837f 100755 --- a/iOSImagesExtractor/iOSImagesExtractor/Classes/Main/Models/XMFileItem.m +++ b/iOSImagesExtractor/iOSImagesExtractor/Classes/Main/Models/XMFileItem.m @@ -51,7 +51,6 @@ - (BOOL)isFileExists -#pragma mark - 类工厂 + (instancetype)xmFileItemWithPath:(NSString*)filePath { XMFileItem *item = [[self alloc]init]; @@ -60,3 +59,16 @@ + (instancetype)xmFileItemWithPath:(NSString*)filePath } @end + + +@implementation NSString (_ShellPath) + +- (NSString *)xm_shellPath { + NSString *spaceString =@" "; + NSString *backslash = @"\\"; + NSString *path = [self stringByReplacingOccurrencesOfString:@" " withString:[NSString stringWithFormat:@"%@%@",backslash,spaceString]]; + + return path; +} + +@end diff --git a/iOSImagesExtractor/iOSImagesExtractor/Classes/Main/Views/NSAlert+XM.h b/iOSImagesExtractor/iOSImagesExtractor/Classes/Main/Views/NSAlert+XM.h new file mode 100644 index 0000000..f96eb77 --- /dev/null +++ b/iOSImagesExtractor/iOSImagesExtractor/Classes/Main/Views/NSAlert+XM.h @@ -0,0 +1,19 @@ +// +// NSAlert+XM.h +// iOSImagesExtractor +// +// Created by chixm on 2020/6/2. +// Copyright © 2020 chi. All rights reserved. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface NSAlert (XM) + ++ (instancetype)xm_alertWithMessageText:(nullable NSString *)message informativeText:(nullable NSString *)informativeText defaultButton:(nullable NSString *)defaultButton; + +@end + +NS_ASSUME_NONNULL_END diff --git a/iOSImagesExtractor/iOSImagesExtractor/Classes/Main/Views/NSAlert+XM.m b/iOSImagesExtractor/iOSImagesExtractor/Classes/Main/Views/NSAlert+XM.m new file mode 100644 index 0000000..fa4979b --- /dev/null +++ b/iOSImagesExtractor/iOSImagesExtractor/Classes/Main/Views/NSAlert+XM.m @@ -0,0 +1,23 @@ +// +// NSAlert+XM.m +// iOSImagesExtractor +// +// Created by chixm on 2020/6/2. +// Copyright © 2020 chi. All rights reserved. +// + +#import "NSAlert+XM.h" + +@implementation NSAlert (XM) + ++ (instancetype)xm_alertWithMessageText:(NSString *)message informativeText:(NSString *)informativeText defaultButton:(NSString *)defaultButton { + NSAlert *alert = [[self alloc] init]; + alert.messageText = message ?: @"";; + alert.informativeText = informativeText ?: @""; + if (defaultButton.length > 0) { + [alert addButtonWithTitle:defaultButton]; + } + return alert; +} + +@end diff --git a/iOSImagesExtractor/iOSImagesExtractor/Credits.rtf b/iOSImagesExtractor/iOSImagesExtractor/Credits.rtf index 62d1f9e..0936b6f 100755 --- a/iOSImagesExtractor/iOSImagesExtractor/Credits.rtf +++ b/iOSImagesExtractor/iOSImagesExtractor/Credits.rtf @@ -1,21 +1,23 @@ -{\rtf1\ansi\ansicpg936\cocoartf1347\cocoasubrtf570 -{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\rtf1\ansi\ansicpg936\cocoartf2513 +\cocoatextscaling0\cocoaplatform0{\fonttbl\f0\fswiss\fcharset0 Helvetica-Bold;\f1\fswiss\fcharset0 Helvetica;} {\colortbl;\red255\green255\blue255;} -\paperw11900\paperh16840\vieww9600\viewh8400\viewkind0 -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720 +{\*\expandedcolortbl;;} +\paperw11900\paperh16840\vieww37300\viewh20180\viewkind0 +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\partightenfactor0 \f0\b\fs28 \cf0 Engineering: -\b0\fs24 \ +\f1\b0\fs24 \ -\fs26 {\field{\*\fldinst{HYPERLINK "https://github.com/devcxm"}}{\fldrslt devcxm}} {\field{\*\fldinst{HYPERLINK "mailto:devcxm@qq.com?subject=About%20iOS-Images-Extractor&body=Hi"}}{\fldrslt devcxm@qq.com}} +\fs26 {\field{\*\fldinst{HYPERLINK "https://github.com/devcxm"}}{\fldrslt devcxm}} {\field{\*\fldinst{HYPERLINK "mailto:devcxm@qq.com?subject=About%20iOS-Images-Extractor&body=Hi"}}{\fldrslt devcxm@gmail.com}} \fs24 \ \ -\b\fs28 With special thanks to: -\b0\fs24 \ +\f0\b\fs28 With special thanks to: +\f1\b0\fs24 \ \fs26 {\field{\*\fldinst{HYPERLINK "https://github.com/mattconnolly/ZipArchive"}}{\fldrslt ZipArchive}}(Matt Connolly)\ {\field{\*\fldinst{HYPERLINK "https://github.com/Marxon13/iOS-Asset-Extractor"}}{\fldrslt iOS-Asset-Extractor}}(Brandon McQuilkin)\ - {\field{\*\fldinst{HYPERLINK "https://github.com/DangerCove/DCOAboutWindow"}}{\fldrslt DCOAboutWindow}}(Danger Cove) + {\field{\*\fldinst{HYPERLINK "https://github.com/DangerCove/DCOAboutWindow"}}{\fldrslt DCOAboutWindow}}(Danger Cove) \ + {\field{\*\fldinst{HYPERLINK "https://github.com/Timac/QLCARFiles"}}{\fldrslt QLCARFiles}}(Timac) \fs24 \ } \ No newline at end of file diff --git a/iOSImagesExtractor/iOSImagesExtractor/Images.xcassets/AppIcon.appiconset/AppIcon-128.png b/iOSImagesExtractor/iOSImagesExtractor/Images.xcassets/AppIcon.appiconset/AppIcon-128.png new file mode 100644 index 0000000..7e462ed Binary files /dev/null and b/iOSImagesExtractor/iOSImagesExtractor/Images.xcassets/AppIcon.appiconset/AppIcon-128.png differ diff --git a/iOSImagesExtractor/iOSImagesExtractor/Images.xcassets/AppIcon.appiconset/AppIcon-128@2x.png b/iOSImagesExtractor/iOSImagesExtractor/Images.xcassets/AppIcon.appiconset/AppIcon-128@2x.png new file mode 100644 index 0000000..fde6a79 Binary files /dev/null and b/iOSImagesExtractor/iOSImagesExtractor/Images.xcassets/AppIcon.appiconset/AppIcon-128@2x.png differ diff --git a/iOSImagesExtractor/iOSImagesExtractor/Images.xcassets/AppIcon.appiconset/AppIcon-16.png b/iOSImagesExtractor/iOSImagesExtractor/Images.xcassets/AppIcon.appiconset/AppIcon-16.png new file mode 100644 index 0000000..8fe09d1 Binary files /dev/null and b/iOSImagesExtractor/iOSImagesExtractor/Images.xcassets/AppIcon.appiconset/AppIcon-16.png differ diff --git a/iOSImagesExtractor/iOSImagesExtractor/Images.xcassets/AppIcon.appiconset/AppIcon-16@2x.png b/iOSImagesExtractor/iOSImagesExtractor/Images.xcassets/AppIcon.appiconset/AppIcon-16@2x.png new file mode 100644 index 0000000..8155eb5 Binary files /dev/null and b/iOSImagesExtractor/iOSImagesExtractor/Images.xcassets/AppIcon.appiconset/AppIcon-16@2x.png differ diff --git a/iOSImagesExtractor/iOSImagesExtractor/Images.xcassets/AppIcon.appiconset/AppIcon-256.png b/iOSImagesExtractor/iOSImagesExtractor/Images.xcassets/AppIcon.appiconset/AppIcon-256.png new file mode 100644 index 0000000..fde6a79 Binary files /dev/null and b/iOSImagesExtractor/iOSImagesExtractor/Images.xcassets/AppIcon.appiconset/AppIcon-256.png differ diff --git a/iOSImagesExtractor/iOSImagesExtractor/Images.xcassets/AppIcon.appiconset/AppIcon-256@2x.png b/iOSImagesExtractor/iOSImagesExtractor/Images.xcassets/AppIcon.appiconset/AppIcon-256@2x.png new file mode 100644 index 0000000..b1109ae Binary files /dev/null and b/iOSImagesExtractor/iOSImagesExtractor/Images.xcassets/AppIcon.appiconset/AppIcon-256@2x.png differ diff --git a/iOSImagesExtractor/iOSImagesExtractor/Images.xcassets/AppIcon.appiconset/AppIcon-32.png b/iOSImagesExtractor/iOSImagesExtractor/Images.xcassets/AppIcon.appiconset/AppIcon-32.png new file mode 100644 index 0000000..8155eb5 Binary files /dev/null and b/iOSImagesExtractor/iOSImagesExtractor/Images.xcassets/AppIcon.appiconset/AppIcon-32.png differ diff --git a/iOSImagesExtractor/iOSImagesExtractor/Images.xcassets/AppIcon.appiconset/AppIcon-32@2x.png b/iOSImagesExtractor/iOSImagesExtractor/Images.xcassets/AppIcon.appiconset/AppIcon-32@2x.png new file mode 100644 index 0000000..3f31efd Binary files /dev/null and b/iOSImagesExtractor/iOSImagesExtractor/Images.xcassets/AppIcon.appiconset/AppIcon-32@2x.png differ diff --git a/iOSImagesExtractor/iOSImagesExtractor/Images.xcassets/AppIcon.appiconset/AppIcon-512.png b/iOSImagesExtractor/iOSImagesExtractor/Images.xcassets/AppIcon.appiconset/AppIcon-512.png new file mode 100644 index 0000000..b1109ae Binary files /dev/null and b/iOSImagesExtractor/iOSImagesExtractor/Images.xcassets/AppIcon.appiconset/AppIcon-512.png differ diff --git a/iOSImagesExtractor/iOSImagesExtractor/Images.xcassets/AppIcon.appiconset/AppIcon-512@2x.png b/iOSImagesExtractor/iOSImagesExtractor/Images.xcassets/AppIcon.appiconset/AppIcon-512@2x.png new file mode 100644 index 0000000..47daef5 Binary files /dev/null and b/iOSImagesExtractor/iOSImagesExtractor/Images.xcassets/AppIcon.appiconset/AppIcon-512@2x.png differ diff --git a/iOSImagesExtractor/iOSImagesExtractor/Images.xcassets/AppIcon.appiconset/Contents.json b/iOSImagesExtractor/iOSImagesExtractor/Images.xcassets/AppIcon.appiconset/Contents.json index 2db2b1c..37326bf 100755 --- a/iOSImagesExtractor/iOSImagesExtractor/Images.xcassets/AppIcon.appiconset/Contents.json +++ b/iOSImagesExtractor/iOSImagesExtractor/Images.xcassets/AppIcon.appiconset/Contents.json @@ -1,53 +1,63 @@ { "images" : [ { - "idiom" : "mac", "size" : "16x16", + "idiom" : "mac", + "filename" : "AppIcon-16.png", "scale" : "1x" }, { - "idiom" : "mac", "size" : "16x16", + "idiom" : "mac", + "filename" : "AppIcon-16@2x.png", "scale" : "2x" }, { - "idiom" : "mac", "size" : "32x32", + "idiom" : "mac", + "filename" : "AppIcon-32.png", "scale" : "1x" }, { - "idiom" : "mac", "size" : "32x32", + "idiom" : "mac", + "filename" : "AppIcon-32@2x.png", "scale" : "2x" }, { - "idiom" : "mac", "size" : "128x128", + "idiom" : "mac", + "filename" : "AppIcon-128.png", "scale" : "1x" }, { - "idiom" : "mac", "size" : "128x128", + "idiom" : "mac", + "filename" : "AppIcon-128@2x.png", "scale" : "2x" }, { - "idiom" : "mac", "size" : "256x256", + "idiom" : "mac", + "filename" : "AppIcon-256.png", "scale" : "1x" }, { - "idiom" : "mac", "size" : "256x256", + "idiom" : "mac", + "filename" : "AppIcon-256@2x.png", "scale" : "2x" }, { - "idiom" : "mac", "size" : "512x512", + "idiom" : "mac", + "filename" : "AppIcon-512.png", "scale" : "1x" }, { - "idiom" : "mac", "size" : "512x512", + "idiom" : "mac", + "filename" : "AppIcon-512@2x.png", "scale" : "2x" } ], diff --git a/iOSImagesExtractor/iOSImagesExtractor/Images.xcassets/Contents.json b/iOSImagesExtractor/iOSImagesExtractor/Images.xcassets/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/iOSImagesExtractor/iOSImagesExtractor/Images.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/iOSImagesExtractor/iOSImagesExtractor/Info.plist b/iOSImagesExtractor/iOSImagesExtractor/Info.plist index f8a380a..7ee8443 100755 --- a/iOSImagesExtractor/iOSImagesExtractor/Info.plist +++ b/iOSImagesExtractor/iOSImagesExtractor/Info.plist @@ -17,17 +17,17 @@ CFBundlePackageType APPL CFBundleShortVersionString - 0.2.6 + $(MARKETING_VERSION) CFBundleSignature ???? CFBundleVersion - 0706 + $(CURRENT_PROJECT_VERSION) LSApplicationCategoryType - public.app-category.utilities + public.app-category.developer-tools LSMinimumSystemVersion $(MACOSX_DEPLOYMENT_TARGET) NSHumanReadableCopyright - Copyright © 2015 chi. All rights reserved. + Copyright © 2015~2020 chi. All rights reserved. NSMainNibFile MainMenu NSPrincipalClass