Compare commits

..

13 Commits

Author SHA1 Message Date
Thomas Zoechling aa74238c4b Update to Xcode recommended settings 2020-11-05 18:09:18 +01:00
Thomas Zoechling 93aab03b6f Merge branch 'main' into experiment/openSSLXCFramework 2020-11-05 18:07:03 +01:00
Hannes Oud 04d3d8c291 Use date for unofficial receipt parts (cherry pick) 2020-10-16 15:10:19 +02:00
Hannes Oud afa0a3da1d Add support for sub-second (ms) dates in receipts as fallback (cherry pick)
based on https://github.com/IdeasOnCanvas/AppReceiptValidator/issues/72
2020-10-16 15:09:42 +02:00
Michael Schwarz c60d292b27 Merge pull request #73 from IdeasOnCanvas/enhancement/relaxDateParsing
Relax date parsing
2020-10-16 11:45:57 +02:00
Hannes Oud 4452349d49 Use date for unofficial receipt parts 2020-10-09 11:53:02 +02:00
Hannes Oud d726caa79d Add support for sub-second (ms) dates in receipts as fallback
based on https://github.com/IdeasOnCanvas/AppReceiptValidator/issues/72
2020-10-09 11:52:52 +02:00
Thomas Zoechling f7c331ab74 Update package URL in README 2020-09-07 16:51:33 +02:00
Thomas Zoechling d6fd4b7da8 Merge pull request #69 from arturgrigor/experiment/openSSLXCFramework
Universal framework (iOS, macOS and tvOS) and SPM support
2020-09-07 16:50:15 +02:00
Artur Grigor 7118684684 Updated the iOS platform version in the SPM manifest. 2020-09-07 15:25:24 +03:00
Artur Grigor a9d3350d0b Bumped the iOS Deployment Target to 13.4 in Build Settings. Bumped the iOS platform version in the SPM manifest to iOS 13. Fixed a warning with the Tests target. 2020-09-07 15:09:49 +03:00
Artur Grigor 7b0605440a Fixed compilation of the AppReceiptValidator Demo macOS target and running the tests for it. 2020-09-07 13:49:35 +03:00
Artur Grigor 8bb6bdf4ce Merge pull request #1 from IdeasOnCanvas/experiment/openSSLXCFramework_ag
Fixes on suggested unified framework & package
2020-09-07 13:27:34 +03:00
12 changed files with 145 additions and 90 deletions
@@ -0,0 +1,28 @@
//
// ReceiptDateFormatterTests.swift
// AppReceiptValidator
//
// Created by Hannes Oud on 09.10.20.
// Copyright © 2020 IdeasOnCanvas GmbH. All rights reserved.
//
import AppReceiptValidator
import Foundation
import XCTest
final class ReceiptDateFormatterTests: XCTestCase {
func testDateFormatting() throws {
let dateStrings = [
"2020-01-01T12:00:00Z",
"2020-01-01T12:00:00.123Z",
"2020-01-01T12:00:00.999Z",
"2020-01-01T12:00:01Z"
]
for dateString in dateStrings {
let parsed = try XCTUnwrap(AppReceiptValidator.ReceiptDateFormatter.date(from: dateString))
XCTAssertEqual(AppReceiptValidator.ReceiptDateFormatter.string(from: parsed), dateString)
}
}
}
@@ -15,7 +15,7 @@ extension Date {
/// - Parameter string: Example "2018-07-12T10:57:42Z", defaults to "2017-01-01T12:00:00Z"
/// - Returns: The date
public static func demoDate(string: String = "2017-01-01T12:00:00Z") -> Date {
guard let date = AppReceiptValidator.asn1DateFormatter.date(from: string) else {
guard let date = AppReceiptValidator.ReceiptDateFormatter.date(from: string) else {
fatalError("Failed to deserialize expected date \(string), use format like '2017-01-01T12:00:00Z'")
}
@@ -8,7 +8,7 @@
/* Begin PBXBuildFile section */
BA09A90224E136CA00798DBC /* openssl.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = BA09A90124E136CA00798DBC /* openssl.xcframework */; };
D114544621A6BDE6001BEC61 /* DeviceIdentifierTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D114544521A6BDE6001BEC61 /* DeviceIdentifierTests.swift */; };
D11B81CF2530687D00E19863 /* ReceiptDateFormatterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D11B81CE2530687D00E19863 /* ReceiptDateFormatterTests.swift */; };
D1239FFF1F6A7B5000D0421E /* AppleIncRootCertificate.cer in Resources */ = {isa = PBXBuildFile; fileRef = D19095C41F601DEA0095729B /* AppleIncRootCertificate.cer */; };
D13E5B7D20331B9B001880F0 /* DropAcceptingTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D13E5B7C20331B9B001880F0 /* DropAcceptingTextView.swift */; };
D14FA7321F61476700545540 /* mac_mindnode_rebought_receipt in Resources */ = {isa = PBXBuildFile; fileRef = D14FA7311F61472400545540 /* mac_mindnode_rebought_receipt */; };
@@ -20,13 +20,11 @@
D150A0F11F67E0990026ED04 /* Date+Convenience.swift in Sources */ = {isa = PBXBuildFile; fileRef = D14FA72E1F6143C400545540 /* Date+Convenience.swift */; };
D15358AE1F62C12500F297D0 /* grandUnifiedExpiredAppleCert_receipt.b64 in Resources */ = {isa = PBXBuildFile; fileRef = D15358A51F62BEC100F297D0 /* grandUnifiedExpiredAppleCert_receipt.b64 */; };
D15358B41F62C47400F297D0 /* deprecatedSinglesTypeExpiredAppleCert_receipt.b64 in Resources */ = {isa = PBXBuildFile; fileRef = D15358B11F62C3C400F297D0 /* deprecatedSinglesTypeExpiredAppleCert_receipt.b64 */; };
D15358EF1F62D2C100F297D0 /* AppReceiptValidator.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = D1D6F4B51F5D684C00E86FE1 /* AppReceiptValidator.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
D19095841F6000A40095729B /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D19095831F6000A40095729B /* AppDelegate.swift */; };
D19095861F6000A40095729B /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D19095851F6000A40095729B /* ViewController.swift */; };
D19095881F6000A40095729B /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = D19095871F6000A40095729B /* Assets.xcassets */; };
D190958B1F6000A40095729B /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = D19095891F6000A40095729B /* Main.storyboard */; };
D19095AE1F6001800095729B /* AppReceiptValidator.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D1D6F4B51F5D684C00E86FE1 /* AppReceiptValidator.framework */; };
D19095B81F6003AB0095729B /* AppReceiptValidator.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D1D6F4B51F5D684C00E86FE1 /* AppReceiptValidator.framework */; };
D19095C31F6019FC0095729B /* DeviceIdentifier+installedDeviceIdentifier_iOS.swift in Sources */ = {isa = PBXBuildFile; fileRef = D19095C11F6019E70095729B /* DeviceIdentifier+installedDeviceIdentifier_iOS.swift */; };
D19095C71F601E580095729B /* TestAssetLoading.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1D6F5491F5D9B1F00E86FE1 /* TestAssetLoading.swift */; };
D19095C81F601E5D0095729B /* hannes_mac_mindnode_Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = D1D6F5441F5D8DF700E86FE1 /* hannes_mac_mindnode_Info.plist */; };
@@ -37,8 +35,6 @@
D19095CE1F601E980095729B /* AppReceiptValidationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1D6F5411F5D8A3800E86FE1 /* AppReceiptValidationTests.swift */; };
D1A428A91FE4267A00926BA5 /* UnofficialReceipt.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1A428A81FE4267A00926BA5 /* UnofficialReceipt.swift */; };
D1AA845C1F6ABB59007F2558 /* AppReceiptPropertyValidationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1AA845A1F6ABB31007F2558 /* AppReceiptPropertyValidationTests.swift */; };
D1BC0C6B250628EA0067458F /* AppReceiptValidator.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D1D6F4B51F5D684C00E86FE1 /* AppReceiptValidator.framework */; };
D1BC0C6C250628EA0067458F /* AppReceiptValidator.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = D1D6F4B51F5D684C00E86FE1 /* AppReceiptValidator.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
D1D6F4E71F5D691400E86FE1 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1D6F4E61F5D691400E86FE1 /* AppDelegate.swift */; };
D1D6F4E91F5D691400E86FE1 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1D6F4E81F5D691400E86FE1 /* ViewController.swift */; };
D1D6F4EC1F5D691400E86FE1 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = D1D6F4EA1F5D691400E86FE1 /* Main.storyboard */; };
@@ -49,16 +45,13 @@
D1FE343D1F604F020029576B /* Receipt.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1FE343C1F604F020029576B /* Receipt.swift */; };
D1FE34401F604F540029576B /* AppReceiptValidator+Parameters.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1FE343F1F604F540029576B /* AppReceiptValidator+Parameters.swift */; };
FE4C60A72502686A00CED438 /* DeviceIdentifier+installedDeviceIdentifier_macOS.swift in Sources */ = {isa = PBXBuildFile; fileRef = D19095BF1F60158B0095729B /* DeviceIdentifier+installedDeviceIdentifier_macOS.swift */; };
FE5F53A1250645EA00EC23BA /* AppReceiptValidator.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D1D6F4B51F5D684C00E86FE1 /* AppReceiptValidator.framework */; };
FE5F53A4250646F800EC23BA /* AppReceiptValidator.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D1D6F4B51F5D684C00E86FE1 /* AppReceiptValidator.framework */; };
FE5F53A52506470900EC23BA /* AppReceiptValidator.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = D1D6F4B51F5D684C00E86FE1 /* AppReceiptValidator.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
FE5F53A72506471C00EC23BA /* AppReceiptValidator.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = D1D6F4B51F5D684C00E86FE1 /* AppReceiptValidator.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
D11616D21F5ED38A00D966D5 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = D1D6F4931F5D67E600E86FE1 /* Project object */;
proxyType = 1;
remoteGlobalIDString = D1D6F4B41F5D684C00E86FE1;
remoteInfo = "AppReceiptValidator iOS";
};
D19095AF1F6001800095729B /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = D1D6F4931F5D67E600E86FE1 /* Project object */;
@@ -66,14 +59,14 @@
remoteGlobalIDString = D1D6F4B41F5D684C00E86FE1;
remoteInfo = "AppReceiptValidator iOS";
};
D19095B41F6001900095729B /* PBXContainerItemProxy */ = {
FE5F539F250645E500EC23BA /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = D1D6F4931F5D67E600E86FE1 /* Project object */;
proxyType = 1;
remoteGlobalIDString = D1D6F4E31F5D691400E86FE1;
remoteInfo = "AppReceiptValidator Demo iOS";
remoteGlobalIDString = D1D6F4B41F5D684C00E86FE1;
remoteInfo = AppReceiptValidator;
};
D1BC0C6D250628EA0067458F /* PBXContainerItemProxy */ = {
FE5F53A2250646F400EC23BA /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = D1D6F4931F5D67E600E86FE1 /* Project object */;
proxyType = 1;
@@ -89,18 +82,18 @@
dstPath = "";
dstSubfolderSpec = 10;
files = (
D1BC0C6C250628EA0067458F /* AppReceiptValidator.framework in Embed Frameworks */,
FE5F53A52506470900EC23BA /* AppReceiptValidator.framework in Embed Frameworks */,
);
name = "Embed Frameworks";
runOnlyForDeploymentPostprocessing = 0;
};
D1D6F5071F5D696800E86FE1 /* Embed Frameworks */ = {
FE5F53A62506471000EC23BA /* Embed Frameworks */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 10;
files = (
D15358EF1F62D2C100F297D0 /* AppReceiptValidator.framework in Embed Frameworks */,
FE5F53A72506471C00EC23BA /* AppReceiptValidator.framework in Embed Frameworks */,
);
name = "Embed Frameworks";
runOnlyForDeploymentPostprocessing = 0;
@@ -110,6 +103,7 @@
/* Begin PBXFileReference section */
BA09A90124E136CA00798DBC /* openssl.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = openssl.xcframework; sourceTree = "<group>"; };
D114544521A6BDE6001BEC61 /* DeviceIdentifierTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeviceIdentifierTests.swift; sourceTree = "<group>"; };
D11B81CE2530687D00E19863 /* ReceiptDateFormatterTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReceiptDateFormatterTests.swift; sourceTree = "<group>"; };
D13E5B7C20331B9B001880F0 /* DropAcceptingTextView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DropAcceptingTextView.swift; 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>"; };
@@ -163,7 +157,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
D1BC0C6B250628EA0067458F /* AppReceiptValidator.framework in Frameworks */,
FE5F53A4250646F800EC23BA /* AppReceiptValidator.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -187,7 +181,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
D19095B81F6003AB0095729B /* AppReceiptValidator.framework in Frameworks */,
FE5F53A1250645EA00EC23BA /* AppReceiptValidator.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -257,6 +251,7 @@
D1D6F5411F5D8A3800E86FE1 /* AppReceiptValidationTests.swift */,
D1AA845A1F6ABB31007F2558 /* AppReceiptPropertyValidationTests.swift */,
D150A0ED1F669A880026ED04 /* AppReceiptValidationInAppPurchaseTests.swift */,
D11B81CE2530687D00E19863 /* ReceiptDateFormatterTests.swift */,
D114544521A6BDE6001BEC61 /* DeviceIdentifierTests.swift */,
D1D6F5481F5D9B1100E86FE1 /* Tools */,
D1D6F5431F5D8DBC00E86FE1 /* Test Assets */,
@@ -386,7 +381,7 @@
buildRules = (
);
dependencies = (
D1BC0C6E250628EA0067458F /* PBXTargetDependency */,
FE5F53A3250646F400EC23BA /* PBXTargetDependency */,
);
name = "AppReceiptValidator Demo macOS";
productName = "AppReceiptValidator Demo macOS";
@@ -405,7 +400,6 @@
);
dependencies = (
D19095B01F6001800095729B /* PBXTargetDependency */,
D19095B51F6001900095729B /* PBXTargetDependency */,
);
name = "AppReceiptValidator Tests";
productName = AppReceiptValidator_iOSTests;
@@ -437,13 +431,13 @@
D1D6F4E01F5D691400E86FE1 /* Sources */,
D1D6F4E11F5D691400E86FE1 /* Frameworks */,
D1D6F4E21F5D691400E86FE1 /* Resources */,
D1D6F5071F5D696800E86FE1 /* Embed Frameworks */,
D1DEE48C20EBAEC800F95036 /* Swiftlint */,
FE5F53A62506471000EC23BA /* Embed Frameworks */,
);
buildRules = (
);
dependencies = (
D11616D31F5ED38A00D966D5 /* PBXTargetDependency */,
FE5F53A0250645E500EC23BA /* PBXTargetDependency */,
);
name = "AppReceiptValidator Demo iOS";
productName = "Demo iOS";
@@ -457,7 +451,7 @@
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 0900;
LastUpgradeCheck = 1200;
LastUpgradeCheck = 1220;
ORGANIZATIONNAME = "IdeasOnCanvas GmbH";
TargetAttributes = {
D19095801F6000A40095729B = {
@@ -483,7 +477,6 @@
D1D6F4E31F5D691400E86FE1 = {
CreatedOnToolsVersion = 9.0;
LastSwiftMigration = 1020;
ProvisioningStyle = Automatic;
};
};
};
@@ -615,7 +608,7 @@
D19095CE1F601E980095729B /* AppReceiptValidationTests.swift in Sources */,
D1AA845C1F6ABB59007F2558 /* AppReceiptPropertyValidationTests.swift in Sources */,
D150A0EE1F669A880026ED04 /* AppReceiptValidationInAppPurchaseTests.swift in Sources */,
D114544621A6BDE6001BEC61 /* DeviceIdentifierTests.swift in Sources */,
D11B81CF2530687D00E19863 /* ReceiptDateFormatterTests.swift in Sources */,
D150A0F11F67E0990026ED04 /* Date+Convenience.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -648,25 +641,20 @@
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
D11616D31F5ED38A00D966D5 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = D1D6F4B41F5D684C00E86FE1 /* AppReceiptValidator */;
targetProxy = D11616D21F5ED38A00D966D5 /* PBXContainerItemProxy */;
};
D19095B01F6001800095729B /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = D1D6F4B41F5D684C00E86FE1 /* AppReceiptValidator */;
targetProxy = D19095AF1F6001800095729B /* PBXContainerItemProxy */;
};
D19095B51F6001900095729B /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = D1D6F4E31F5D691400E86FE1 /* AppReceiptValidator Demo iOS */;
targetProxy = D19095B41F6001900095729B /* PBXContainerItemProxy */;
};
D1BC0C6E250628EA0067458F /* PBXTargetDependency */ = {
FE5F53A0250645E500EC23BA /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = D1D6F4B41F5D684C00E86FE1 /* AppReceiptValidator */;
targetProxy = D1BC0C6D250628EA0067458F /* PBXContainerItemProxy */;
targetProxy = FE5F539F250645E500EC23BA /* PBXContainerItemProxy */;
};
FE5F53A3250646F400EC23BA /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = D1D6F4B41F5D684C00E86FE1 /* AppReceiptValidator */;
targetProxy = FE5F53A2250646F400EC23BA /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
@@ -703,7 +691,6 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_IDENTITY = "-";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
DEVELOPMENT_TEAM = "";
INFOPLIST_FILE = "AppReceiptValidator Demo macOS/Info.plist";
@@ -715,7 +702,9 @@
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
SDKROOT = macosx;
SUPPORTED_PLATFORMS = macosx;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = 6;
};
name = Debug;
};
@@ -724,7 +713,6 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_IDENTITY = "-";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
DEVELOPMENT_TEAM = "";
INFOPLIST_FILE = "AppReceiptValidator Demo macOS/Info.plist";
@@ -736,14 +724,15 @@
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
SDKROOT = macosx;
SUPPORTED_PLATFORMS = macosx;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = 6;
};
name = Release;
};
D19095B21F6001800095729B /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_TEAM = "";
INFOPLIST_FILE = "AppReceiptValidator Tests iOS/Info.plist";
LD_RUNPATH_SEARCH_PATHS = (
@@ -751,17 +740,16 @@
"@executable_path/Frameworks",
"@loader_path/Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.15;
PRODUCT_BUNDLE_IDENTIFIER = "com.ideasoncanvas.AppReceiptValidator-iOSTests";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
D19095B31F6001800095729B /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_TEAM = "";
INFOPLIST_FILE = "AppReceiptValidator Tests iOS/Info.plist";
LD_RUNPATH_SEARCH_PATHS = (
@@ -769,10 +757,10 @@
"@executable_path/Frameworks",
"@loader_path/Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.15;
PRODUCT_BUNDLE_IDENTIFIER = "com.ideasoncanvas.AppReceiptValidator-iOSTests";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Release;
};
@@ -808,7 +796,6 @@
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_IDENTITY = "";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
@@ -827,7 +814,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
IPHONEOS_DEPLOYMENT_TARGET = 13.4;
MACOSX_DEPLOYMENT_TARGET = 10.11;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
@@ -836,8 +823,8 @@
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG IS_FRAMEWORK_TARGET";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2,3";
TVOS_DEPLOYMENT_TARGET = 11.0;
TARGETED_DEVICE_FAMILY = "1,2,3,6";
TVOS_DEPLOYMENT_TARGET = 12.0;
};
name = Debug;
};
@@ -873,7 +860,6 @@
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_IDENTITY = "";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
@@ -886,7 +872,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
IPHONEOS_DEPLOYMENT_TARGET = 13.4;
MACOSX_DEPLOYMENT_TARGET = 10.11;
MTL_ENABLE_DEBUG_INFO = NO;
PRODUCT_NAME = AppReceiptValidator;
@@ -895,8 +881,8 @@
SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_OPTIMIZATION_LEVEL = "-O";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2,3";
TVOS_DEPLOYMENT_TARGET = 11.0;
TARGETED_DEVICE_FAMILY = "1,2,3,6";
TVOS_DEPLOYMENT_TARGET = 12.0;
VALIDATE_PRODUCT = YES;
};
name = Release;
@@ -906,8 +892,6 @@
buildSettings = {
APPLICATION_EXTENSION_API_ONLY = YES;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_IDENTITY = "";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = "";
@@ -936,8 +920,6 @@
buildSettings = {
APPLICATION_EXTENSION_API_ONLY = YES;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_IDENTITY = "";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = "";
@@ -965,7 +947,6 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_TEAM = "";
INFOPLIST_FILE = "AppReceiptValidator Demo iOS/Info.plist";
LD_RUNPATH_SEARCH_PATHS = (
@@ -974,6 +955,9 @@
);
PRODUCT_BUNDLE_IDENTIFIER = "com.ideasoncanvas.AppReceiptValidator.Demo-iOS";
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = "iphonesimulator iphoneos";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
@@ -985,7 +969,6 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_TEAM = "";
INFOPLIST_FILE = "AppReceiptValidator Demo iOS/Info.plist";
LD_RUNPATH_SEARCH_PATHS = (
@@ -994,6 +977,9 @@
);
PRODUCT_BUNDLE_IDENTIFIER = "com.ideasoncanvas.AppReceiptValidator.Demo-iOS";
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = "iphonesimulator iphoneos";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1200"
LastUpgradeVersion = "1220"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1200"
LastUpgradeVersion = "1220"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
@@ -28,9 +28,9 @@
buildForAnalyzing = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "D19095911F6000A40095729B"
BuildableName = "AppReceiptValidator Tests macOS.xctest"
BlueprintName = "AppReceiptValidator Tests macOS"
BlueprintIdentifier = "D19095A81F6001800095729B"
BuildableName = "AppReceiptValidator Tests.xctest"
BlueprintName = "AppReceiptValidator Tests"
ReferencedContainer = "container:AppReceiptValidator.xcodeproj">
</BuildableReference>
</BuildActionEntry>
@@ -43,14 +43,12 @@
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
skipped = "NO"
parallelizable = "YES"
testExecutionOrdering = "random">
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "D19095911F6000A40095729B"
BuildableName = "AppReceiptValidator Tests macOS.xctest"
BlueprintName = "AppReceiptValidator Tests macOS"
BlueprintIdentifier = "D19095A81F6001800095729B"
BuildableName = "AppReceiptValidator Tests.xctest"
BlueprintName = "AppReceiptValidator Tests"
ReferencedContainer = "container:AppReceiptValidator.xcodeproj">
</BuildableReference>
</TestableReference>
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1200"
LastUpgradeVersion = "1220"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
@@ -88,16 +88,6 @@ public struct AppReceiptValidator {
let receiptContainer = try self.extractPKCS7Container(data: receiptData)
return try parseReceipt(pkcs7: receiptContainer, parseUnofficialParts: true)
}
/// Uses receipt-conform representation of dates like "2017-01-01T12:00:00Z"
public static let asn1DateFormatter: DateFormatter = {
// Date formatter code from https://www.objc.io/issues/17-security/receipt-validation/#parsing-the-receipt
let dateFormatter = DateFormatter()
dateFormatter.locale = Locale(identifier: "en_US_POSIX")
dateFormatter.dateFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ss'Z'"
dateFormatter.timeZone = TimeZone(secondsFromGMT: 0)
return dateFormatter
}()
}
// MARK: - Full Validation
@@ -348,6 +338,59 @@ private extension AppReceiptValidator {
}
}
// MARK: - ReceiptDateFormatter
extension AppReceiptValidator {
/// Static formatting methods to use for string encoded date values in receipts
public enum ReceiptDateFormatter {
/// Uses receipt-conform representation of dates like "2017-01-01T12:00:00Z",
/// as a fallback, dates like "2017-01-01T12:00:00.123Z" are also parsed.
public static func date(from string: String) -> Date? {
return self.asn1DateFormatter.date(from: string) // expected
?? self.fallbackDateFormatterWithMS.date(from: string) // try again with milliseconds
}
/// Returns receipt-conform string representation of dates like "2017-01-01T12:00:00Z",
/// but if the date has sub-second fractions a millisecond representation like "2017-01-01T12:00:00.123Z" is returned.
public static func string(from date: Date) -> String {
if floor(date.timeIntervalSince1970) == date.timeIntervalSince1970 {
// Integer seconds granularity is what we expect
return self.asn1DateFormatter.string(from: date)
} else {
// millis seconds granularity is what we expect
return self.fallbackDateFormatterWithMS.string(from: date)
}
}
/// Uses receipt-conform representation of dates like "2017-01-01T12:00:00Z"
static let asn1DateFormatter: DateFormatter = {
// Date formatter code from https://www.objc.io/issues/17-security/receipt-validation/#parsing-the-receipt
let dateFormatter = DateFormatter()
dateFormatter.locale = Locale(identifier: "en_US_POSIX")
dateFormatter.dateFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ss'Z'"
dateFormatter.timeZone = TimeZone(secondsFromGMT: 0)
return dateFormatter
}()
/// Uses receipt-conform representation of dates like "2017-01-01T12:00:00.123Z"
///
/// This is not the officially intended format, but added after hearing reports about new format adding ms https://twitter.com/depth42/status/1314179654811607041
private static let fallbackDateFormatterWithMS: DateFormatter = {
let dateFormatter = DateFormatter()
dateFormatter.locale = Locale(identifier: "en_US_POSIX")
dateFormatter.dateFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'SSS'Z'"
dateFormatter.timeZone = TimeZone(secondsFromGMT: 0)
return dateFormatter
}()
}
/// Uses receipt-conform representation of dates like "2017-01-01T12:00:00Z"
@available(*, deprecated, message: "Use AppReceiptValidator.ReceiptDateFormatter.string(from:) or AppReceiptValidator.ReceiptDateFormatter.date(from:) instead, to cover unexpected date formats")
public static let asn1DateFormatter: DateFormatter = ReceiptDateFormatter.asn1DateFormatter
}
// MARK: - Result
extension AppReceiptValidator {
@@ -153,7 +153,7 @@ extension ASN1Object {
var dateValue: Date? {
guard let string = self.stringValue else { return nil }
return AppReceiptValidator.asn1DateFormatter.date(from: string)
return AppReceiptValidator.ReceiptDateFormatter.date(from: string)
}
}
@@ -294,7 +294,7 @@ private struct StringFormatter {
func format(_ date: Date?) -> String {
guard let date = date else { return fallback }
return quoted(AppReceiptValidator.asn1DateFormatter.string(from: date))
return quoted(AppReceiptValidator.ReceiptDateFormatter.string(from: date))
}
func format(_ string: String?) -> String {
@@ -318,7 +318,7 @@ private func parseBase64(string: String) -> Data? {
// Parses a string of type "2017-01-01T12:00:00Z"
private func parseDate(string: String) -> Date? {
guard let date = AppReceiptValidator.asn1DateFormatter.date(from: string) else {
guard let date = AppReceiptValidator.ReceiptDateFormatter.date(from: string) else {
assertionFailure("Date could not be parsed from string '\(string)', make sure it has a correct format, example `2017-01-01T12:00:00Z`")
return nil
}
@@ -61,7 +61,7 @@ public enum KnownUnofficialReceiptAttribute: Int32 {
var parsingType: ParsingType {
switch self {
case .date1, .date2, .date3:
return .string
return .date
case .provisioningType, .ageRating, .clientName:
return .string
}
@@ -115,7 +115,7 @@ extension UnofficialReceipt.Entry.Value: CustomStringConvertible {
case .string(let value):
return "\"\(value)\""
case .date(let date):
return AppReceiptValidator.asn1DateFormatter.string(from: date)
return AppReceiptValidator.ReceiptDateFormatter.string(from: date)
case .bytes(let bytes):
if bytes.count == 2 && bytes.first == 12 && bytes.dropFirst().first == 0 {
return "2 bytes (12, 0)"
+1 -1
View File
@@ -5,7 +5,7 @@ import PackageDescription
let package = Package(
name: "AppReceiptValidator",
platforms: [
.iOS(.v10),
.iOS("13.4"),
.macOS(.v10_11),
.tvOS(.v11)
],
+1 -1
View File
@@ -25,7 +25,7 @@ github "IdeasOnCanvas/AppReceiptValidator"
To install using Swift Package Manager, add this to the `dependencies:` section in your Package.swift file:
```swift
.package(url: "https://github.com/arturgrigor/AppReceiptValidator", .branch("experiment/openSSLXCFramework")),
.package(url: "https://github.com/IdeasOnCanvas/AppReceiptValidator.git", .branch("experiment/openSSLXCFramework")),
```
## Usage in Code