diff --git a/twackup-gui/Twackup.xcodeproj/project.pbxproj b/twackup-gui/Twackup.xcodeproj/project.pbxproj index cd83aca..84286e3 100644 --- a/twackup-gui/Twackup.xcodeproj/project.pbxproj +++ b/twackup-gui/Twackup.xcodeproj/project.pbxproj @@ -19,6 +19,7 @@ 0B434F9A2935E29300311FB6 /* DpkgDetailVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B434F992935E29300311FB6 /* DpkgDetailVC.swift */; }; 0B434F9C2935E90000311FB6 /* DatabaseDetailVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B434F9B2935E90000311FB6 /* DatabaseDetailVC.swift */; }; 0B434F9E2935E97200311FB6 /* DatabasePackageDetailedView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B434F9D2935E97200311FB6 /* DatabasePackageDetailedView.swift */; }; + 0B47A8852C2AD9700043B8A7 /* MobileCoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0B47A8842C2AD9700043B8A7 /* MobileCoreServices.framework */; }; 0B48B1B62C21B40000D21737 /* BlankSlate in Frameworks */ = {isa = PBXBuildFile; productRef = 0B48B1B52C21B40000D21737 /* BlankSlate */; }; 0B48B1B82C22B04600D21737 /* DebsListVC+BlankSlate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B48B1B72C22B04600D21737 /* DebsListVC+BlankSlate.swift */; }; 0B48B1BA2C22B2CD00D21737 /* DpkgListVC+BlankSlate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B48B1B92C22B2CD00D21737 /* DpkgListVC+BlankSlate.swift */; }; @@ -100,6 +101,12 @@ 0B434F9B2935E90000311FB6 /* DatabaseDetailVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DatabaseDetailVC.swift; sourceTree = ""; }; 0B434F9D2935E97200311FB6 /* DatabasePackageDetailedView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DatabasePackageDetailedView.swift; sourceTree = ""; }; 0B434FA02936351700311FB6 /* twackup.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = twackup.h; path = ../target/twackup.h; sourceTree = ""; }; + 0B47A8752C2AD8790043B8A7 /* _LSQueryResult.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = _LSQueryResult.h; sourceTree = ""; }; + 0B47A8762C2AD8790043B8A7 /* LSApplicationProxy.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LSApplicationProxy.h; sourceTree = ""; }; + 0B47A8792C2AD8790043B8A7 /* LSBundleProxy.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LSBundleProxy.h; sourceTree = ""; }; + 0B47A87D2C2AD8790043B8A7 /* LSResourceProxy.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LSResourceProxy.h; sourceTree = ""; }; + 0B47A8822C2AD9690043B8A7 /* CoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreServices.framework; path = System/Library/Frameworks/CoreServices.framework; sourceTree = SDKROOT; }; + 0B47A8842C2AD9700043B8A7 /* MobileCoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MobileCoreServices.framework; path = System/Library/Frameworks/MobileCoreServices.framework; sourceTree = SDKROOT; }; 0B48B1B72C22B04600D21737 /* DebsListVC+BlankSlate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "DebsListVC+BlankSlate.swift"; sourceTree = ""; }; 0B48B1B92C22B2CD00D21737 /* DpkgListVC+BlankSlate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "DpkgListVC+BlankSlate.swift"; sourceTree = ""; }; 0B48B1C12C22E43B00D21737 /* libroot.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libroot.a; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -178,6 +185,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 0B47A8852C2AD9700043B8A7 /* MobileCoreServices.framework in Frameworks */, 0B48B1CF2C22E47A00D21737 /* libroot.a in Frameworks */, 0BE87E932C1E05CE009C95A7 /* NukeUI in Frameworks */, C1FF8C5621CC9FEC564B8CCE /* Pods_Twackup.framework in Frameworks */, @@ -221,6 +229,25 @@ path = Preferences; sourceTree = ""; }; + 0B47A8802C2AD8790043B8A7 /* MobileCoreServices */ = { + isa = PBXGroup; + children = ( + 0B47A8752C2AD8790043B8A7 /* _LSQueryResult.h */, + 0B47A8762C2AD8790043B8A7 /* LSApplicationProxy.h */, + 0B47A8792C2AD8790043B8A7 /* LSBundleProxy.h */, + 0B47A87D2C2AD8790043B8A7 /* LSResourceProxy.h */, + ); + path = MobileCoreServices; + sourceTree = ""; + }; + 0B47A8812C2AD8790043B8A7 /* include */ = { + isa = PBXGroup; + children = ( + 0B47A8802C2AD8790043B8A7 /* MobileCoreServices */, + ); + path = include; + sourceTree = ""; + }; 0B48EF442C200CA7007C0EC0 /* UI Models */ = { isa = PBXGroup; children = ( @@ -271,6 +298,7 @@ children = ( 0BE87E942C1E2214009C95A7 /* Localizable.xcstrings */, 0B88C31F2930E32800BA5312 /* Sources */, + 0B47A8812C2AD8790043B8A7 /* include */, 0B8661712930ADA400EA4301 /* Assets.xcassets */, 0B8661732930ADA400EA4301 /* LaunchScreen.storyboard */, 0B8661762930ADA400EA4301 /* Info.plist */, @@ -471,6 +499,8 @@ A9DB1EE24AF2E5EE6554C623 /* Frameworks */ = { isa = PBXGroup; children = ( + 0B47A8842C2AD9700043B8A7 /* MobileCoreServices.framework */, + 0B47A8822C2AD9690043B8A7 /* CoreServices.framework */, CEF70D3062CF0C2BA7D149B4 /* Pods_Twackup.framework */, ); name = Frameworks; diff --git a/twackup-gui/Twackup/Bridging-Header.h b/twackup-gui/Twackup/Bridging-Header.h index ee88a39..707efd0 100644 --- a/twackup-gui/Twackup/Bridging-Header.h +++ b/twackup-gui/Twackup/Bridging-Header.h @@ -11,6 +11,7 @@ #import "twackup.h" #import "libroot.h" #import +#import "LSApplicationProxy.h" @interface UIScrollView (Private) @property (assign, nonatomic, readonly, getter=_minimumContentOffset) CGPoint minimumContentOffset; diff --git a/twackup-gui/Twackup/Sources/FFI Models/Dpkg.swift b/twackup-gui/Twackup/Sources/FFI Models/Dpkg.swift index 700be1c..46b415c 100644 --- a/twackup-gui/Twackup/Sources/FFI Models/Dpkg.swift +++ b/twackup-gui/Twackup/Sources/FFI Models/Dpkg.swift @@ -26,7 +26,27 @@ actor Dpkg { } nonisolated static let defaultSaveDirectory: URL = { - FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0] + var url = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0] + + let proxy = LSApplicationProxy.forCurrentProcess() + let unsandboxed = (proxy?.entitlements["com.apple.private.security.no-sandbox"] as? Bool) ?? false + if unsandboxed { + url = URL(fileURLWithPath: "/var/mobile/Documents/Twackup") + } + + var isDir: ObjCBool = true + let exists = FileManager.default.fileExists(atPath: url.path, isDirectory: &isDir) + + // Application is not usable without directories created + // swiftlint:disable force_try + if exists && !isDir.boolValue { + try! FileManager.default.removeItem(at: url) + } else if !exists { + try! FileManager.default.createDirectory(at: url, withIntermediateDirectories: true) + } + // swiftlint:enable force_try + + return url }() private let innerDpkg: UnsafeMutablePointer diff --git a/twackup-gui/Twackup/include/MobileCoreServices/LSApplicationProxy.h b/twackup-gui/Twackup/include/MobileCoreServices/LSApplicationProxy.h new file mode 100644 index 0000000..18e955e --- /dev/null +++ b/twackup-gui/Twackup/include/MobileCoreServices/LSApplicationProxy.h @@ -0,0 +1,36 @@ +#import "LSBundleProxy.h" + +@class LSPlugInKitProxy; + +API_AVAILABLE(ios(4.0)) +@interface LSApplicationProxy : LSBundleProxy + ++ (instancetype)applicationProxyForIdentifier:(NSString *)identifier; + +@property (nonatomic, readonly) NSString *applicationIdentifier; +@property (nonatomic, readonly) NSString *vendorName API_AVAILABLE(ios(7.0)); +@property (nonatomic, readonly) NSString *itemName API_AVAILABLE(ios(7.1)); +@property (nonatomic, readonly) NSString *sdkVersion API_AVAILABLE(ios(8.0)); +@property (nonatomic, readonly) NSString *teamID API_AVAILABLE(ios(8.0)); +@property (nonatomic, readonly) NSDate *registeredDate API_AVAILABLE(ios(9.0)); +@property (nonatomic, readonly) NSString *sourceAppIdentifier API_AVAILABLE(ios(8.2)); // e.g. App Store, TestFlight + +@property (nonatomic, readonly) NSArray *plugInKitPlugins API_AVAILABLE(ios(8.0)); +@property (nonatomic, readonly) NSArray *deviceFamily API_AVAILABLE(ios(8.0)); +@property (nonatomic, readonly) NSArray *activityTypes API_AVAILABLE(ios(10.0)); + +@property (nonatomic, readonly, getter=isAppUpdate) BOOL appUpdate API_AVAILABLE(ios(7.0)); +@property (nonatomic, readonly, getter=isInstalled) BOOL installed API_AVAILABLE(ios(7.0)); +@property (nonatomic, readonly, getter=isNewsstandApp) BOOL newsstandApp API_AVAILABLE(ios(7.0)); +@property (nonatomic, readonly, getter=isPlaceholder) BOOL placeholder API_AVAILABLE(ios(7.0)); +@property (nonatomic, readonly, getter=isRestricted) BOOL restricted API_AVAILABLE(ios(7.0)); +@property (nonatomic, readonly, getter=isPurchasedReDownload) BOOL purchasedReDownload API_AVAILABLE(ios(8.0)); +@property (nonatomic, readonly, getter=isWatchKitApp) BOOL watchKitApp API_AVAILABLE(ios(8.2)); +@property (nonatomic, readonly, getter=isBetaApp) BOOL betaApp API_AVAILABLE(ios(8.2)); +@property (nonatomic, readonly, getter=isAdHocCodeSigned) BOOL adHocCodeSigned API_AVAILABLE(ios(9.0)); +@property (nonatomic, readonly, getter=isLaunchProhibited) BOOL launchProhibited API_AVAILABLE(ios(10.0)); +@property (nonatomic, readonly, getter=isAppStoreVendable) BOOL appStoreVendable API_AVAILABLE(ios(11.0)); + +@property (nonatomic, readonly) BOOL isStickerProvider API_DEPRECATED("Removed in iOS 11", ios(10.0, 11.0)); + +@end diff --git a/twackup-gui/Twackup/include/MobileCoreServices/LSBundleProxy.h b/twackup-gui/Twackup/include/MobileCoreServices/LSBundleProxy.h new file mode 100644 index 0000000..c450124 --- /dev/null +++ b/twackup-gui/Twackup/include/MobileCoreServices/LSBundleProxy.h @@ -0,0 +1,36 @@ +#import "LSResourceProxy.h" + +API_AVAILABLE(ios(8.0)) +@interface LSBundleProxy : LSResourceProxy + ++ (instancetype)bundleProxyForCurrentProcess API_AVAILABLE(ios(10.0)); ++ (instancetype)bundleProxyForIdentifier:(NSString *)identifier; ++ (instancetype)bundleProxyForURL:(NSURL *)url; + +@property (nonatomic, readonly) NSUUID *cacheGUID; + +@property (nonatomic, copy) NSURL *appStoreReceiptURL; +@property (nonatomic, readonly) NSURL *bundleContainerURL; +@property (nonatomic, readonly) NSURL *bundleURL; +@property (nonatomic, readonly) NSURL *containerURL; +@property (nonatomic, readonly) NSURL *dataContainerURL; + +@property (nonatomic, readonly) NSString *bundleExecutable; +@property (nonatomic, readonly) NSString *bundleIdentifier; +@property (nonatomic, readonly) NSString *bundleType; +@property (nonatomic, readonly) NSString *canonicalExecutablePath API_AVAILABLE(ios(10.3)); + +@property (nonatomic, readonly) NSDictionary *entitlements; +@property (nonatomic, readonly) NSDictionary *environmentVariables; +@property (nonatomic, readonly) NSDictionary *groupContainerURLs; + +@property (nonatomic, copy) NSArray *machOUUIDs; +@property (nonatomic, readonly) NSString *signerIdentity; +@property (nonatomic, readonly, getter=isContainerized) BOOL containerized API_AVAILABLE(ios(11.0)); +@property (nonatomic, readonly) BOOL profileValidated API_AVAILABLE(ios(11.0)); + +@property (nonatomic, readonly) NSString *localizedShortName; + +- (NSUUID *)uniqueIdentifier API_AVAILABLE(ios(9.0)); + +@end diff --git a/twackup-gui/Twackup/include/MobileCoreServices/LSResourceProxy.h b/twackup-gui/Twackup/include/MobileCoreServices/LSResourceProxy.h new file mode 100644 index 0000000..72bb8c0 --- /dev/null +++ b/twackup-gui/Twackup/include/MobileCoreServices/LSResourceProxy.h @@ -0,0 +1,12 @@ +#import "_LSQueryResult.h" + +API_AVAILABLE(ios(4.0)) // subclass of NSObject until iOS 10.0 +@interface LSResourceProxy : _LSQueryResult + +@property (nonatomic, copy) NSString *boundApplicationIdentifier; +@property (nonatomic, copy) NSURL *boundContainerURL API_AVAILABLE(ios(5.0)); +@property (nonatomic, copy) NSURL *boundDataContainerURL API_DEPRECATED("Access through the appropriate subclass property", ios(8.0, 11.0)); + +@property (nonatomic, retain) NSString *localizedName; + +@end diff --git a/twackup-gui/Twackup/include/MobileCoreServices/_LSQueryResult.h b/twackup-gui/Twackup/include/MobileCoreServices/_LSQueryResult.h new file mode 100644 index 0000000..110ee66 --- /dev/null +++ b/twackup-gui/Twackup/include/MobileCoreServices/_LSQueryResult.h @@ -0,0 +1,6 @@ +#import + +API_AVAILABLE(ios(10.0)) +@interface _LSQueryResult : NSObject + +@end