Compare commits

...

19 Commits

Author SHA1 Message Date
Hannes Oud c536866906 Merge pull request #50 from IdeasOnCanvas/chore/Xcode10
Update to Xcode 10 and Swift 4.2
2018-09-24 17:20:23 +02:00
Hannes Oud ede64d2e3b Update Swift version in Readme 2018-09-24 16:10:10 +02:00
Hannes Oud 112a5a9e4f Update travis.yml for Xcode 10 and iOS 12 2018-09-24 16:09:19 +02:00
Hannes Oud 7d8cb7bd06 Update schemes, parrallelize tests and make execution order random 2018-09-24 16:06:41 +02:00
Hannes Oud da06a099ce Make tests unhosted 2018-09-24 16:04:18 +02:00
Hannes Oud 95337f7544 Upgrade to Swift 4.2 and Xcode 10 2018-09-24 16:00:56 +02:00
Hannes Oud 7ee443a4af Merge pull request #49 from IdeasOnCanvas/chore/core/moveSwiftlintFromFrameworkTarget
Move Swiftlint run script phases to example project
2018-07-05 11:03:21 +02:00
Hannes Oud ae082be181 Remove placeholder comment from script phase 2018-07-05 11:01:48 +02:00
Hannes Oud bcb0ee2c27 Move Swiftlint run script phases to example project 2018-07-03 15:23:48 +02:00
Hannes Oud f8dae53736 Merge pull request #48 from IdeasOnCanvas/enhancement/modernizeForSwift41
Remove Sourcery and update README with new references
2018-04-24 11:43:57 +02:00
Hannes Oud 5c90e58864 Update README, add links to AppStoreReceiptChecker 2018-04-16 18:22:13 +02:00
Hannes Oud df47710990 Remove sourcery from README 2018-04-16 18:12:30 +02:00
Hannes Oud 9b03d4b850 Remove sourcery from .swiftlint.yml 2018-04-16 18:08:42 +02:00
Hannes Oud 06b43589d6 Use two char indentation in swiftlint run phase, add SRCROOT as input to prepare for new build system 2018-04-16 18:06:23 +02:00
Hannes Oud 1722f04928 Remove vertical whitespaces 2018-04-16 18:06:23 +02:00
Hannes Oud 16ef7de4bf Remove Sourcery 2018-04-16 17:42:45 +02:00
Hannes Oud 7521a419d1 Upgrade swift badge in readme 2018-04-03 10:54:39 +02:00
Hannes Oud 5f0ad3de3f Merge pull request #46 from arturgrigor/master
Xcode 9.3 support and fixed the SwiftLint issue
2018-04-03 10:41:46 +02:00
Artur Grigor 40eeef07a5 Xcode 9.3 support and fixed the SwiftLint issue. 2018-04-02 14:39:19 +03:00
20 changed files with 103 additions and 264 deletions
+2 -2
View File
@@ -1,5 +1,5 @@
language: objective-c
osx_image: xcode9.2
osx_image: xcode10
env:
global:
@@ -7,7 +7,7 @@ env:
- LANG=en_US.UTF-8
- PROJECT=AppReceiptValidator/AppReceiptValidator.xcodeproj
matrix:
- DESTINATION="OS=11.2,name=iPhone X" SCHEME="AppReceiptValidator Demo iOS"
- DESTINATION="OS=12.0,name=iPhone X" SCHEME="AppReceiptValidator Demo iOS"
- DESTINATION="arch=x86_64" SCHEME="AppReceiptValidator Demo macOS"
script:
-7
View File
@@ -1,7 +0,0 @@
sources:
- AppReceiptValidator
- Sourcery/Protocols
templates:
- Sourcery/Templates
output:
Sourcery/Generated
+1 -1
View File
@@ -4,7 +4,7 @@ disabled_rules:
- nesting
- todo
excluded:
- Sourcery/Generated
- excluded_dir_example
file_length:
warning: 500
large_tuple:
@@ -13,7 +13,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
return true
}
}
@@ -24,8 +24,8 @@ class ViewController: UIViewController, UITextViewDelegate {
self.inputTextView.delegate = self
self.inputTextView.text = ""
self.outputTextView.text = "Parsed Receipt will be shown here"
NotificationCenter.default.addObserver(self, selector: #selector(triggerAutoPaste), name: .UIApplicationWillEnterForeground, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(triggerAutoPaste), name: .UIPasteboardChanged, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(triggerAutoPaste), name: UIApplication.willEnterForegroundNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(triggerAutoPaste), name: UIPasteboard.changedNotification, object: nil)
}
override func viewDidAppear(_ animated: Bool) {
@@ -32,7 +32,7 @@ final class DropAcceptingTextView: NSTextView {
}
override func performDragOperation(_ sender: NSDraggingInfo) -> Bool {
if let fileURL = sender.fileURLs.first {
if let fileURL = sender.fileURLs.first {
self.handleDroppedFile?(fileURL)
return true
}
@@ -43,7 +43,7 @@ final class DropAcceptingTextView: NSTextView {
fileprivate extension NSDraggingInfo {
var fileURLs: [URL] {
let asStrings = self.draggingPasteboard().propertyList(forType: makeFileNameType()) as? [String] ?? []
let asStrings = self.draggingPasteboard.propertyList(forType: makeFileNameType()) as? [String] ?? []
return asStrings.map { URL(fileURLWithPath: $0) }
}
}
@@ -22,7 +22,6 @@ class AppReceiptValidationInAppPurchaseTests: XCTestCase {
} catch {
XCTFail("Unexpectedly failed parsing a receipt \(error)")
}
}
func testNonMindNodeReceiptParsingWithMultipleInAppPurchases() {
@@ -39,7 +39,7 @@ class AppReceiptValidationTests: XCTestCase {
_ = try receiptValidator.parseReceipt(origin: .data(data))
XCTFail("Unexpectedly succeeded in parsing a non-receipt")
} catch {
guard let e = error as? AppReceiptValidator.Error, e == AppReceiptValidator.Error.emptyReceiptContents else {
guard error as? AppReceiptValidator.Error == AppReceiptValidator.Error.emptyReceiptContents else {
XCTFail("Unexpected error, expeced .emptyReceiptContents, got \(error)")
return
}
@@ -10,10 +10,6 @@
D1239FFF1F6A7B5000D0421E /* AppleIncRootCertificate.cer in Resources */ = {isa = PBXBuildFile; fileRef = D19095C41F601DEA0095729B /* AppleIncRootCertificate.cer */; };
D123A0001F6A7CCF00D0421E /* AppleIncRootCertificate.cer in Resources */ = {isa = PBXBuildFile; fileRef = D19095C41F601DEA0095729B /* AppleIncRootCertificate.cer */; };
D13E5B7D20331B9B001880F0 /* DropAcceptingTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D13E5B7C20331B9B001880F0 /* DropAcceptingTextView.swift */; };
D14FA7261F61350F00545540 /* AutoEquatable.swift in Sources */ = {isa = PBXBuildFile; fileRef = D14FA71F1F6134CF00545540 /* AutoEquatable.swift */; };
D14FA7271F61351000545540 /* AutoEquatable.swift in Sources */ = {isa = PBXBuildFile; fileRef = D14FA71F1F6134CF00545540 /* AutoEquatable.swift */; };
D14FA7291F61351400545540 /* AutoEquatable.generated.swift in Sources */ = {isa = PBXBuildFile; fileRef = D14FA71E1F6134CF00545540 /* AutoEquatable.generated.swift */; };
D14FA72A1F61351500545540 /* AutoEquatable.generated.swift in Sources */ = {isa = PBXBuildFile; fileRef = D14FA71E1F6134CF00545540 /* AutoEquatable.generated.swift */; };
D14FA7321F61476700545540 /* mac_mindnode_rebought_receipt in Resources */ = {isa = PBXBuildFile; fileRef = D14FA7311F61472400545540 /* mac_mindnode_rebought_receipt */; };
D14FA7331F61476800545540 /* mac_mindnode_rebought_receipt in Resources */ = {isa = PBXBuildFile; fileRef = D14FA7311F61472400545540 /* mac_mindnode_rebought_receipt */; };
D14FA7381F6181C700545540 /* OpenSSLWrappers.swift in Sources */ = {isa = PBXBuildFile; fileRef = D14FA7371F6181C700545540 /* OpenSSLWrappers.swift */; };
@@ -280,9 +276,6 @@
/* Begin PBXFileReference section */
D13E5B7C20331B9B001880F0 /* DropAcceptingTextView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DropAcceptingTextView.swift; sourceTree = "<group>"; };
D14FA71E1F6134CF00545540 /* AutoEquatable.generated.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AutoEquatable.generated.swift; sourceTree = "<group>"; };
D14FA71F1F6134CF00545540 /* AutoEquatable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AutoEquatable.swift; sourceTree = "<group>"; };
D14FA7221F6134CF00545540 /* AutoEquatable.stencil */ = {isa = PBXFileReference; lastKnownFileType = text; path = AutoEquatable.stencil; sourceTree = "<group>"; };
D14FA72E1F6143C400545540 /* Date+Convenience.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Date+Convenience.swift"; sourceTree = "<group>"; };
D14FA7311F61472400545540 /* mac_mindnode_rebought_receipt */ = {isa = PBXFileReference; lastKnownFileType = file; path = mac_mindnode_rebought_receipt; sourceTree = "<group>"; };
D14FA7371F6181C700545540 /* OpenSSLWrappers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpenSSLWrappers.swift; sourceTree = "<group>"; };
@@ -542,40 +535,6 @@
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
D14FA71B1F6134CF00545540 /* Sourcery */ = {
isa = PBXGroup;
children = (
D14FA7231F6134EC00545540 /* Protocols */,
D14FA71D1F6134CF00545540 /* Generated */,
D14FA7201F6134CF00545540 /* Templates */,
);
path = Sourcery;
sourceTree = "<group>";
};
D14FA71D1F6134CF00545540 /* Generated */ = {
isa = PBXGroup;
children = (
D14FA71E1F6134CF00545540 /* AutoEquatable.generated.swift */,
);
path = Generated;
sourceTree = "<group>";
};
D14FA7201F6134CF00545540 /* Templates */ = {
isa = PBXGroup;
children = (
D14FA7221F6134CF00545540 /* AutoEquatable.stencil */,
);
path = Templates;
sourceTree = "<group>";
};
D14FA7231F6134EC00545540 /* Protocols */ = {
isa = PBXGroup;
children = (
D14FA71F1F6134CF00545540 /* AutoEquatable.swift */,
);
path = Protocols;
sourceTree = "<group>";
};
D14FA7341F614A9C00545540 /* OpenSSL */ = {
isa = PBXGroup;
children = (
@@ -851,7 +810,6 @@
D1D6F4921F5D67E600E86FE1 = {
isa = PBXGroup;
children = (
D14FA71B1F6134CF00545540 /* Sourcery */,
D1D6F4FC1F5D696800E86FE1 /* AppReceiptValidator */,
D1D6F4E51F5D691400E86FE1 /* AppReceiptValidator Demo iOS */,
D19095821F6000A40095729B /* AppReceiptValidator Demo macOS */,
@@ -1135,6 +1093,7 @@
D190957D1F6000A40095729B /* Sources */,
D190957E1F6000A40095729B /* Frameworks */,
D190957F1F6000A40095729B /* Resources */,
D1DEE48D20EBAEE800F95036 /* Swiftlint */,
);
buildRules = (
);
@@ -1190,7 +1149,6 @@
D1D6F4B11F5D684C00E86FE1 /* Frameworks */,
D1D6F4B21F5D684C00E86FE1 /* Headers */,
D1D6F4B31F5D684C00E86FE1 /* Resources */,
D1D6F52D1F5D872200E86FE1 /* Swiftlint */,
);
buildRules = (
);
@@ -1209,7 +1167,6 @@
D1D6F4BE1F5D687400E86FE1 /* Frameworks */,
D1D6F4BF1F5D687400E86FE1 /* Headers */,
D1D6F4C01F5D687400E86FE1 /* Resources */,
D1D6F52E1F5D872B00E86FE1 /* Swiftlint */,
);
buildRules = (
);
@@ -1228,6 +1185,7 @@
D1D6F4E11F5D691400E86FE1 /* Frameworks */,
D1D6F4E21F5D691400E86FE1 /* Resources */,
D1D6F5071F5D696800E86FE1 /* Embed Frameworks */,
D1DEE48C20EBAEC800F95036 /* Swiftlint */,
);
buildRules = (
);
@@ -1246,11 +1204,12 @@
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 0900;
LastUpgradeCheck = 0900;
LastUpgradeCheck = 0930;
ORGANIZATIONNAME = "IdeasOnCanvas GmbH";
TargetAttributes = {
D19095801F6000A40095729B = {
CreatedOnToolsVersion = 9.0;
LastSwiftMigration = 1000;
ProvisioningStyle = Automatic;
SystemCapabilities = {
com.apple.Sandbox = {
@@ -1260,27 +1219,27 @@
};
D19095911F6000A40095729B = {
CreatedOnToolsVersion = 9.0;
LastSwiftMigration = 1000;
ProvisioningStyle = Automatic;
TestTargetID = D19095801F6000A40095729B;
};
D19095A81F6001800095729B = {
CreatedOnToolsVersion = 9.0;
LastSwiftMigration = 1000;
ProvisioningStyle = Automatic;
TestTargetID = D1D6F4E31F5D691400E86FE1;
};
D1D6F4B41F5D684C00E86FE1 = {
CreatedOnToolsVersion = 9.0;
LastSwiftMigration = 0900;
LastSwiftMigration = 1000;
ProvisioningStyle = Automatic;
};
D1D6F4C11F5D687400E86FE1 = {
CreatedOnToolsVersion = 9.0;
LastSwiftMigration = 0900;
LastSwiftMigration = 1000;
ProvisioningStyle = Automatic;
};
D1D6F4E31F5D691400E86FE1 = {
CreatedOnToolsVersion = 9.0;
LastSwiftMigration = 0900;
LastSwiftMigration = 1000;
ProvisioningStyle = Automatic;
};
};
@@ -1381,33 +1340,43 @@
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
D1D6F52D1F5D872200E86FE1 /* Swiftlint */ = {
D1DEE48C20EBAEC800F95036 /* Swiftlint */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
"$(SRCROOT)",
);
name = Swiftlint;
outputFileListPaths = (
);
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "if which swiftlint >/dev/null; then\n swiftlint\nelse\n echo \"warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint\"\nfi";
shellScript = "if which swiftlint >/dev/null; then\nswiftlint\nelse\necho \"warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint\"\nfi\n";
};
D1D6F52E1F5D872B00E86FE1 /* Swiftlint */ = {
D1DEE48D20EBAEE800F95036 /* Swiftlint */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
"$(SRCROOT)",
);
name = Swiftlint;
outputFileListPaths = (
);
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "if which swiftlint >/dev/null; then\n swiftlint\nelse\n echo \"warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint\"\nfi";
shellScript = "if which swiftlint >/dev/null; then\nswiftlint\nelse\necho \"warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint\"\nfi\n";
};
/* End PBXShellScriptBuildPhase section */
@@ -1454,8 +1423,6 @@
D1D6F53F1F5D89D000E86FE1 /* AppReceiptValidator.swift in Sources */,
D1FE34401F604F540029576B /* AppReceiptValidator+Parameters.swift in Sources */,
D19095C31F6019FC0095729B /* DeviceIdentifier+installedDeviceIdentifier_iOS.swift in Sources */,
D14FA7271F61351000545540 /* AutoEquatable.swift in Sources */,
D14FA7291F61351400545540 /* AutoEquatable.generated.swift in Sources */,
D1DFC5DA20037B8400C7B99B /* KnownOrUnknown.swift in Sources */,
D1FE343D1F604F020029576B /* Receipt.swift in Sources */,
D14FA73B1F618B0100545540 /* ASN1Helpers.swift in Sources */,
@@ -1473,11 +1440,9 @@
D1FE34411F604F540029576B /* AppReceiptValidator+Parameters.swift in Sources */,
D19095C01F60158B0095729B /* DeviceIdentifier+installedDeviceIdentifier_macOS.swift in Sources */,
D1FE343E1F604F020029576B /* Receipt.swift in Sources */,
D14FA72A1F61351500545540 /* AutoEquatable.generated.swift in Sources */,
D1DFC5DB20037B8400C7B99B /* KnownOrUnknown.swift in Sources */,
D14FA73C1F618B0100545540 /* ASN1Helpers.swift in Sources */,
D14FA7391F6181D000545540 /* OpenSSLWrappers.swift in Sources */,
D14FA7261F61350F00545540 /* AutoEquatable.swift in Sources */,
D19095BD1F6004D10095729B /* pkcs7_union_accessors.c in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -1558,7 +1523,7 @@
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
SDKROOT = macosx;
SWIFT_VERSION = 4.0;
SWIFT_VERSION = 4.2;
};
name = Debug;
};
@@ -1576,7 +1541,7 @@
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
SDKROOT = macosx;
SWIFT_VERSION = 4.0;
SWIFT_VERSION = 4.2;
};
name = Release;
};
@@ -1584,7 +1549,6 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_IDENTITY = "";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
@@ -1595,8 +1559,7 @@
PRODUCT_BUNDLE_IDENTIFIER = "com.ideasoncanvas.AppReceiptValidator-Demo-macOSTests";
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = macosx;
SWIFT_VERSION = 4.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/AppReceiptValidator Demo macOS.app/Contents/MacOS/AppReceiptValidator Demo macOS";
SWIFT_VERSION = 4.2;
};
name = Debug;
};
@@ -1604,7 +1567,6 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_IDENTITY = "";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
@@ -1615,8 +1577,7 @@
PRODUCT_BUNDLE_IDENTIFIER = "com.ideasoncanvas.AppReceiptValidator-Demo-macOSTests";
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = macosx;
SWIFT_VERSION = 4.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/AppReceiptValidator Demo macOS.app/Contents/MacOS/AppReceiptValidator Demo macOS";
SWIFT_VERSION = 4.2;
};
name = Release;
};
@@ -1629,9 +1590,8 @@
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "com.ideasoncanvas.AppReceiptValidator-iOSTests";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 4.0;
SWIFT_VERSION = 4.2;
TARGETED_DEVICE_FAMILY = "1,2";
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/AppReceiptValidator Demo iOS.app/AppReceiptValidator Demo iOS";
};
name = Debug;
};
@@ -1644,9 +1604,8 @@
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "com.ideasoncanvas.AppReceiptValidator-iOSTests";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 4.0;
SWIFT_VERSION = 4.2;
TARGETED_DEVICE_FAMILY = "1,2";
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/AppReceiptValidator Demo iOS.app/AppReceiptValidator Demo iOS";
};
name = Release;
};
@@ -1664,6 +1623,7 @@
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;
@@ -1671,6 +1631,7 @@
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;
@@ -1723,6 +1684,7 @@
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;
@@ -1730,6 +1692,7 @@
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;
@@ -1785,6 +1748,7 @@
PRODUCT_NAME = AppReceiptValidator;
SKIP_INSTALL = YES;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 4.2;
TARGETED_DEVICE_FAMILY = "1,2";
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
@@ -1814,6 +1778,7 @@
PRODUCT_BUNDLE_IDENTIFIER = com.ideasoncanvas.AppReceiptValidator;
PRODUCT_NAME = AppReceiptValidator;
SKIP_INSTALL = YES;
SWIFT_VERSION = 4.2;
TARGETED_DEVICE_FAMILY = "1,2";
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
@@ -1845,6 +1810,7 @@
PRODUCT_NAME = AppReceiptValidator;
SDKROOT = macosx;
SKIP_INSTALL = YES;
SWIFT_VERSION = 4.2;
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
};
@@ -1875,6 +1841,7 @@
PRODUCT_NAME = AppReceiptValidator;
SDKROOT = macosx;
SKIP_INSTALL = YES;
SWIFT_VERSION = 4.2;
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
};
@@ -1892,7 +1859,7 @@
PRODUCT_BUNDLE_IDENTIFIER = "com.ideasoncanvas.AppReceiptValidator.Demo-iOS";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 4.0;
SWIFT_VERSION = 4.2;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
@@ -1908,7 +1875,7 @@
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "com.ideasoncanvas.AppReceiptValidator.Demo-iOS";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 4.0;
SWIFT_VERSION = 4.2;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Release;
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0900"
LastUpgradeVersion = "0930"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
@@ -40,11 +40,12 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
language = ""
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
skipped = "NO">
skipped = "NO"
parallelizable = "YES"
testExecutionOrdering = "random">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "D19095A81F6001800095729B"
@@ -70,7 +71,6 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
language = ""
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0900"
LastUpgradeVersion = "0930"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
@@ -40,11 +40,12 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
language = ""
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
skipped = "NO">
skipped = "NO"
parallelizable = "YES"
testExecutionOrdering = "random">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "D19095911F6000A40095729B"
@@ -70,7 +71,6 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
language = ""
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0900"
LastUpgradeVersion = "0930"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
@@ -26,10 +26,30 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
language = ""
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
skipped = "NO"
parallelizable = "YES"
testExecutionOrdering = "random">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "D19095A81F6001800095729B"
BuildableName = "AppReceiptValidator Tests iOS.xctest"
BlueprintName = "AppReceiptValidator Tests iOS"
ReferencedContainer = "container:AppReceiptValidator.xcodeproj">
</BuildableReference>
</TestableReference>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "D1D6F4B41F5D684C00E86FE1"
BuildableName = "AppReceiptValidator.framework"
BlueprintName = "AppReceiptValidator iOS"
ReferencedContainer = "container:AppReceiptValidator.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
@@ -37,7 +57,6 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
language = ""
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0900"
LastUpgradeVersion = "0930"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
@@ -20,36 +20,23 @@
ReferencedContainer = "container:AppReceiptValidator.xcodeproj">
</BuildableReference>
</BuildActionEntry>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "NO"
buildForArchiving = "NO"
buildForAnalyzing = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "D1D6F5321F5D894900E86FE1"
BuildableName = "AppReceiptValidator_macOSTests.xctest"
BlueprintName = "AppReceiptValidator_macOSTests"
ReferencedContainer = "container:AppReceiptValidator.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
language = ""
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
skipped = "NO">
skipped = "NO"
parallelizable = "YES"
testExecutionOrdering = "random">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "D1D6F5321F5D894900E86FE1"
BuildableName = "AppReceiptValidator_macOSTests.xctest"
BlueprintName = "AppReceiptValidator_macOSTests"
BlueprintIdentifier = "D19095911F6000A40095729B"
BuildableName = "AppReceiptValidator Tests macOS.xctest"
BlueprintName = "AppReceiptValidator Tests macOS"
ReferencedContainer = "container:AppReceiptValidator.xcodeproj">
</BuildableReference>
</TestableReference>
@@ -70,7 +57,6 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
language = ""
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
@@ -336,7 +336,6 @@ private extension AppReceiptValidator {
case expirationDate = 21
}
/// See Receipt.swift for details and a link to Apple reference
enum KnownInAppPurchaseAttribute: Int32 {
case quantity = 1701
@@ -11,7 +11,7 @@ import Foundation
/// Receipts are made up of a number of fields. This represents all fields that are available locally when parsing a receipt file in ASN.1 form.
///
/// See [Apple Reference](https://developer.apple.com/library/content/releasenotes/General/ValidateAppStoreReceipt/Chapters/ReceiptFields.html)
public struct Receipt {
public struct Receipt: Equatable {
/// The apps bundle identifier. This corresponds to the value of `CFBundleIdentifier` in the Info.plist file.
/// Use this value to validate if the receipt was indeed generated for your app. ASN.1 Field Type 2.
@@ -70,10 +70,6 @@ public struct Receipt {
public init() {}
}
// MARK: - Equatable
extension Receipt: AutoEquatable {}
// MARK: - CustomStringConvertible
extension Receipt: CustomStringConvertible, CustomDebugStringConvertible {
@@ -115,7 +111,7 @@ extension Receipt: CustomStringConvertible, CustomDebugStringConvertible {
/// - Subscription Auto Renew Status
/// - Subscription Auto Renew Preference
/// - Subscription Price Consent Status
public struct InAppPurchaseReceipt {
public struct InAppPurchaseReceipt: Equatable {
/// The number of items purchased. ASN.1 Field Type 1701.
/// This value corresponds to the quantity property of the `SKPayment` object stored in the transactions payment property.
@@ -189,10 +185,6 @@ public struct InAppPurchaseReceipt {
public init() {}
}
// MARK: - Equatable
extension InAppPurchaseReceipt: AutoEquatable {}
// MARK: - CustomStringConvertible
extension InAppPurchaseReceipt: CustomStringConvertible, CustomDebugStringConvertible {
@@ -1,56 +0,0 @@
// Generated using Sourcery 0.10.0 https://github.com/krzysztofzablocki/Sourcery
// DO NOT EDIT
// swiftlint:disable file_length
private func compareOptionals<T>(lhs: T?, rhs: T?, compare: (_ lhs: T, _ rhs: T) -> Bool) -> Bool {
switch (lhs, rhs) {
case let (lValue?, rValue?):
return compare(lValue, rValue)
case (nil, nil):
return true
default:
return false
}
}
private func compareArrays<T>(lhs: [T], rhs: [T], compare: (_ lhs: T, _ rhs: T) -> Bool) -> Bool {
guard lhs.count == rhs.count else { return false }
for (idx, lhsItem) in lhs.enumerated() {
guard compare(lhsItem, rhs[idx]) else { return false }
}
return true
}
// MARK: - AutoEquatable for classes, protocols, structs
// MARK: - InAppPurchaseReceipt AutoEquatable
extension InAppPurchaseReceipt: Equatable {}
public func == (lhs: InAppPurchaseReceipt, rhs: InAppPurchaseReceipt) -> Bool {
guard compareOptionals(lhs: lhs.quantity, rhs: rhs.quantity, compare: ==) else { return false }
guard compareOptionals(lhs: lhs.productIdentifier, rhs: rhs.productIdentifier, compare: ==) else { return false }
guard compareOptionals(lhs: lhs.transactionIdentifier, rhs: rhs.transactionIdentifier, compare: ==) else { return false }
guard compareOptionals(lhs: lhs.originalTransactionIdentifier, rhs: rhs.originalTransactionIdentifier, compare: ==) else { return false }
guard compareOptionals(lhs: lhs.purchaseDate, rhs: rhs.purchaseDate, compare: ==) else { return false }
guard compareOptionals(lhs: lhs.originalPurchaseDate, rhs: rhs.originalPurchaseDate, compare: ==) else { return false }
guard compareOptionals(lhs: lhs.subscriptionExpirationDate, rhs: rhs.subscriptionExpirationDate, compare: ==) else { return false }
guard compareOptionals(lhs: lhs.cancellationDate, rhs: rhs.cancellationDate, compare: ==) else { return false }
guard compareOptionals(lhs: lhs.webOrderLineItemId, rhs: rhs.webOrderLineItemId, compare: ==) else { return false }
return true
}
// MARK: - Receipt AutoEquatable
extension Receipt: Equatable {}
public func == (lhs: Receipt, rhs: Receipt) -> Bool {
guard compareOptionals(lhs: lhs.bundleIdentifier, rhs: rhs.bundleIdentifier, compare: ==) else { return false }
guard compareOptionals(lhs: lhs.bundleIdData, rhs: rhs.bundleIdData, compare: ==) else { return false }
guard compareOptionals(lhs: lhs.appVersion, rhs: rhs.appVersion, compare: ==) else { return false }
guard compareOptionals(lhs: lhs.opaqueValue, rhs: rhs.opaqueValue, compare: ==) else { return false }
guard compareOptionals(lhs: lhs.sha1Hash, rhs: rhs.sha1Hash, compare: ==) else { return false }
guard compareOptionals(lhs: lhs.originalAppVersion, rhs: rhs.originalAppVersion, compare: ==) else { return false }
guard compareOptionals(lhs: lhs.receiptCreationDate, rhs: rhs.receiptCreationDate, compare: ==) else { return false }
guard compareOptionals(lhs: lhs.expirationDate, rhs: rhs.expirationDate, compare: ==) else { return false }
guard lhs.inAppPurchaseReceipts == rhs.inAppPurchaseReceipts else { return false }
return true
}
// MARK: - AutoEquatable for Enums
@@ -1,8 +0,0 @@
//
// AutoEquatable.swift
//
//
// Created by Hannes Oud on 07.09.17.
//
protocol AutoEquatable {}
@@ -1,62 +0,0 @@
// swiftlint:disable file_length
fileprivate func compareOptionals<T>(lhs: T?, rhs: T?, compare: (_ lhs: T, _ rhs: T) -> Bool) -> Bool {
switch (lhs, rhs) {
case let (lValue?, rValue?):
return compare(lValue, rValue)
case (nil, nil):
return true
default:
return false
}
}
fileprivate func compareArrays<T>(lhs: [T], rhs: [T], compare: (_ lhs: T, _ rhs: T) -> Bool) -> Bool {
guard lhs.count == rhs.count else { return false }
for (idx, lhsItem) in lhs.enumerated() {
guard compare(lhsItem, rhs[idx]) else { return false }
}
return true
}
{% macro compareVariables variables %}
{% for variable in variables where variable.readAccess != "private" and variable.readAccess != "fileprivate" %}{% if not variable.annotations.skipEquality %}guard {% if not variable.isOptional %}{% if not variable.annotations.arrayEquality %}lhs.{{ variable.name }} == rhs.{{ variable.name }}{% else %}compareArrays(lhs: lhs.{{ variable.name }}, rhs: rhs.{{ variable.name }}, compare: ==){% endif %}{% else %}compareOptionals(lhs: lhs.{{ variable.name }}, rhs: rhs.{{ variable.name }}, compare: ==){% endif %} else { return false }{% endif %}
{% endfor %}
{% endmacro %}
// MARK: - AutoEquatable for classes, protocols, structs
{% for type in types.implementing.AutoEquatable|!enum %}
// MARK: - {{ type.name }} AutoEquatable
{% if not type.kind == "protocol" %}extension {{ type.name }}: Equatable {}{% endif %}
{% if type.supertype.based.Equatable or type.supertype.implements.AutoEquatable %}THIS WONT COMPILE, WE DONT SUPPORT INHERITANCE for AutoEquatable{% endif %}
{{ type.accessLevel }} func == (lhs: {{ type.name }}, rhs: {{ type.name }}) -> Bool {
{% if not type.kind == "protocol" %}
{% call compareVariables type.storedVariables %}
{% else %}
{% call compareVariables type.allVariables %}
{% endif %}
return true
}
{% endfor %}
// MARK: - AutoEquatable for Enums
{% for type in types.implementing.AutoEquatable|enum %}
// MARK: - {{ type.name }} AutoEquatable
extension {{ type.name }}: Equatable {}
{{ type.accessLevel }} func == (lhs: {{ type.name }}, rhs: {{ type.name }}) -> Bool {
switch (lhs, rhs) {
{% for case in type.cases %}
{% if case.hasAssociatedValue %}case (.{{ case.name }}(let lhs), .{{ case.name }}(let rhs)):{% else %}case (.{{ case.name }}, .{{ case.name }}):{% endif %}
{% ifnot case.hasAssociatedValue %}return true{% else %}
{% if case.associatedValues.count == 1 %}
return lhs == rhs
{% else %}
{% for associated in case.associatedValues %}if lhs.{{ associated.externalName }} != rhs.{{ associated.externalName }} { return false }
{% endfor %}return true
{% endif %}
{% endif %}
{% endfor %}
{% if type.cases.count > 1 %}default: return false{% endif %}
}
}
{% endfor %}
+8 -6
View File
@@ -2,7 +2,7 @@
[![Carthage Compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage)
![Platforms iOS, macOS](https://img.shields.io/badge/Platform-iOS%20|%20macOS-blue.svg "Platforms iOS, macOS")
![Language Swift](https://img.shields.io/badge/Language-Swift%204-orange.svg "Language")
![Language Swift](https://img.shields.io/badge/Language-Swift%204.2-orange.svg "Swift 4.2")
[![License Apache 2.0 + OpenSSL](https://img.shields.io/badge/License-Apache%202.0%20|%20OpenSSL%20-aaaaff.svg "License")](LICENSE)
[![Build Status](https://travis-ci.org/IdeasOnCanvas/AppReceiptValidator.svg?branch=master)](https://travis-ci.org/IdeasOnCanvas/AppReceiptValidator)
[![Twitter: @hannesoid](https://img.shields.io/badge/Twitter-@hannesoid-red.svg?style=flat)](https://twitter.com/hannesoid)
@@ -73,7 +73,7 @@ Receipt(
)
```
**Receipt** is *Equatable*, thanks [Sourcery](https://github.com/krzysztofzablocki/Sourcery), so you can do comparisons in Unit Tests.
**Receipt** is *Equatable*, so you can do comparisons in Unit Tests.
There are also some opt-in unofficial attributes, but this is experimental and should not be used in production.
### Validating a receipt's signature and hash
@@ -150,19 +150,20 @@ If you have no receipt (happens in development builds) or your receipt is invali
### AppReceiptValidator Uses OpenSSL
OpenSSL is used for pkcs7 container parsing and signature validation, and also for parsing the ASN1 payload of the pkcs7, which contains the receipts attributes.
OpenSSL is used for PKCS#7 container parsing and signature validation, and also for parsing the ASN1 payload of the PKCS#7, which contains the receipts attributes.
### Other Options
##### Alternatives to PKCS7 of OpenSSL
##### Alternatives to PKCS#7 of OpenSSL
- `Security.framework` - `CMSDecoder` for PKCS7 interaction *only available on macOS*
- `BoringSSL` instead of OpenSSL, Pod, *only available on iOS (?)*
- `Security.framework` - `CMSDecoder` for PKCS#7 interaction *only available on macOS*, [AppStoreReceiptChecker](https://github.com/delicious-monster/AppStoreReceiptChecker) uses this.
- `BoringSSL` instead of OpenSSL, seems included as frameworks in modern iOS and macOS, but not officially supported?
##### Alternatives to ASN1 of OpenSSL
- [decoding-asn1-der-sequences-in-swift](http://nspasteboard.com/2016/10/23/decoding-asn1-der-sequences-in-swift/) implemented [here](https://gist.github.com/Jugale/2daaec0715d4f6d7347534d42bfa7110)
- [Asn1Parser.swift](https://github.com/TakeScoop/SwiftyRSA/blob/03250be7319d8c54159234e5258ead395ea4de4c/SwiftyRSA/Asn1Parser.swift)
- [AppStoreReceiptChecker](https://github.com/delicious-monster/AppStoreReceiptChecker)
##### Validation Server to Server
An app can send its receipt file to a backend from where Apples receipt API can be called. See Resources.
@@ -187,6 +188,7 @@ Advantages doing it locally:
- [nsomar about Module Maps 1](http://nsomar.com/project-and-private-headers-in-a-swift-and-objective-c-framework/)
- [nsomar about Module Maps 2](http://nsomar.com/modular-framework-creating-and-using-them/)
- [SwiftyStoreKit](https://github.com/bizz84/SwiftyStoreKit)
- [AppStoreReceiptChecker](https://github.com/delicious-monster/AppStoreReceiptChecker) - macOS, uses CMSDecoder and a Swift ASN1 Implementation
## Updating Apple Root Certificate
For convenience, AppReceiptValidator contains a copy of apples root certificate to validate the signature against. If uncomfortable with this, you can specify your own by changing the parameters like this: