diff --git a/AltStore/Operations/Errors/SourceError.swift b/AltStore/Operations/Errors/SourceError.swift index bbf0110d..648b7e3d 100644 --- a/AltStore/Operations/Errors/SourceError.swift +++ b/AltStore/Operations/Errors/SourceError.swift @@ -24,6 +24,9 @@ extension SourceError case missingPermissionUsageDescription case missingScreenshotSize + + case marketplaceAppsNotSupported = 101 + case marketplaceAppsRequired } static func unsupported(_ source: Source) -> SourceError { SourceError(code: .unsupported, source: source) } @@ -41,6 +44,14 @@ extension SourceError static func missingScreenshotSize(for screenshot: AppScreenshot, source: Source) -> SourceError { SourceError(code: .missingScreenshotSize, source: source, app: screenshot.app, screenshotURL: screenshot.imageURL) } + + static func marketplaceAppsNotSupported(source: Source) -> SourceError { + return SourceError(code: .marketplaceAppsNotSupported, source: source) + } + + static func marketplaceAppsRequired(source: Source) -> SourceError { + return SourceError(code: .marketplaceAppsRequired, source: source) + } } struct SourceError: ALTLocalizedError @@ -128,6 +139,14 @@ struct SourceError: ALTLocalizedError let failureReason = baseMessage + ": \(screenshotURL.absoluteString)" return failureReason + + case .marketplaceAppsNotSupported: + let failureReason = String(format: NSLocalizedString("The source “%@” contains notarized apps, which are not supported by this version of AltStore.", comment: ""), self.$source.name) + return failureReason + + case .marketplaceAppsRequired: + let failureReason = String(format: NSLocalizedString("The source “%@” contains non-marketplace apps, which are not supported by this version of AltStore.", comment: ""), self.$source.name) + return failureReason } } @@ -166,6 +185,10 @@ struct SourceError: ALTLocalizedError let recoverySuggestion = NSLocalizedString("Please remove the existing source in order to add this one.", comment: "") return recoverySuggestion + case .marketplaceAppsRequired: + let failureReason = String(format: NSLocalizedString("AltStore can only install marketplace apps that have been notarized by Apple.", comment: ""), self.$source.name) + return failureReason + default: return nil } } diff --git a/AltStore/Operations/FetchSourceOperation.swift b/AltStore/Operations/FetchSourceOperation.swift index 1eacc0eb..52866172 100644 --- a/AltStore/Operations/FetchSourceOperation.swift +++ b/AltStore/Operations/FetchSourceOperation.swift @@ -226,6 +226,12 @@ private extension FetchSourceOperation // All iPad screenshots MUST have an explicit size. guard screenshot.size != nil else { throw SourceError.missingScreenshotSize(for: screenshot, source: source) } } + + #if MARKETPLACE + guard app.marketplaceID != nil else { throw SourceError.marketplaceAppsRequired(source: source) } + #else + guard app.marketplaceID == nil else { throw SourceError.marketplaceAppsNotSupported(source: source) } + #endif } if let previousSourceID = self.$source.identifier diff --git a/AltStoreCore/Model/AltStore.xcdatamodeld/AltStore 16.xcdatamodel/contents b/AltStoreCore/Model/AltStore.xcdatamodeld/AltStore 16.xcdatamodel/contents index e02a449e..f6b5f36c 100644 --- a/AltStoreCore/Model/AltStore.xcdatamodeld/AltStore 16.xcdatamodel/contents +++ b/AltStoreCore/Model/AltStore.xcdatamodeld/AltStore 16.xcdatamodel/contents @@ -250,6 +250,7 @@ + diff --git a/AltStoreCore/Model/StoreApp.swift b/AltStoreCore/Model/StoreApp.swift index 2f374e79..005b271b 100644 --- a/AltStoreCore/Model/StoreApp.swift +++ b/AltStoreCore/Model/StoreApp.swift @@ -152,6 +152,9 @@ public class StoreApp: NSManagedObject, Decodable, Fetchable @NSManaged public private(set) var tintColor: UIColor? @NSManaged public private(set) var isBeta: Bool + // Required for Marketplace apps. + @NSManaged public private(set) var marketplaceID: String? + @NSManaged public var isPledged: Bool @NSManaged public private(set) var isPledgeRequired: Bool @NSManaged public private(set) var isHiddenWithoutPledge: Bool @@ -275,6 +278,7 @@ public class StoreApp: NSManagedObject, Decodable, Fetchable { case name case bundleIdentifier + case marketplaceID case developerName case localizedDescription case iconURL @@ -345,6 +349,8 @@ public class StoreApp: NSManagedObject, Decodable, Fetchable } else { throw DecodingError.dataCorruptedError(forKey: .downloadURL, in: container, debugDescription: "E downloadURL:String or downloadURLs:[[Platform:URL]] key required.") } + // Required for Marketplace apps, but we'll verify later. + self.marketplaceID = try container.decodeIfPresent(String.self, forKey: .marketplaceID) // else { // throw DecodingError.dataCorruptedError(forKey: .downloadURL, in: container, debugDescription: "E downloadURL:String or downloadURLs:[[Platform:URL]] key required.")