Compare commits

...

33 Commits

Author SHA1 Message Date
Hannes Oud 26385ee11b Merge pull request #52 from lightsprint09/extension-save
Support App extensions
2019-03-26 10:32:04 +01:00
Lukas Schmidt a96f16969d support app extensions to silence warning when use in a extension 2019-03-10 12:54:43 +01:00
Hannes Oud 1ba0b31095 Merge pull request #51 from IdeasOnCanvas/enhancement/deviceIdentifierFromMacAddress
Support DeviceIdentifier from MAC Address String
2018-11-22 16:11:06 +01:00
Hannes Oud 5121e901f5 Remove unneeded prefix 2018-11-22 16:10:44 +01:00
Hannes Oud d31ab05fe2 Update gif 2018-11-22 12:29:06 +01:00
Hannes Oud c4769bc42a Update mac demo app to support identifiers 2018-11-22 12:22:58 +01:00
Hannes Oud 6605544598 Add tests for DeviceIdentifier 2018-11-22 11:54:19 +01:00
Hannes Oud 3bb92db368 Add DeviceIdentifier initializer with macAddress string 2018-11-22 11:48:28 +01:00
Hannes Oud 97b0adff0a Make primary mac address function internal (testable) 2018-11-22 11:48:13 +01:00
Hannes Oud bf875864ea Fix typo 2018-11-22 11:47:50 +01:00
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
Hannes Oud 11563b5094 Remove simulator list printing 2018-02-15 15:22:24 +01:00
Hannes Oud 35815fcd7c Disable code signing and mac app sandbox 2018-02-15 15:21:33 +01:00
Hannes Oud 17c598d414 Fix xcrun typo in .travis.yml 2018-02-15 14:53:57 +01:00
Hannes Oud cff64329b3 Update .travis.yml indention, output simulators and variables 2018-02-15 14:15:10 +01:00
27 changed files with 292 additions and 324 deletions
+7 -7
View File
@@ -1,18 +1,18 @@
language: objective-c
osx_image: xcode9.2
osx_image: xcode10
env:
global:
- LC_CTYPE=en_US.UTF-8
- LANG=en_US.UTF-8
- PROJECT=AppReceiptValidator/AppReceiptValidator.xcodeproj
matrix:
- DESTINATION="OS=11.2,name=iPhone X" SCHEME="AppReceiptValidator Demo iOS"
- LC_CTYPE=en_US.UTF-8
- LANG=en_US.UTF-8
- PROJECT=AppReceiptValidator/AppReceiptValidator.xcodeproj
matrix:
- DESTINATION="OS=12.0,name=iPhone X" SCHEME="AppReceiptValidator Demo iOS"
- DESTINATION="arch=x86_64" SCHEME="AppReceiptValidator Demo macOS"
script:
- set -o pipefail
- xcodebuild -version
- xcodebuild -showsdks
- echo "PROJECT $PROJECT, SCHEME $SCHEME, DESTINATION $DESTINATION"
- xcodebuild -project "$PROJECT" -scheme "$SCHEME" -destination "$DESTINATION" -configuration Debug ONLY_ACTIVE_ARCH=NO ENABLE_TESTABILITY=YES test | xcpretty;
-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) {
@@ -1,10 +1,5 @@
<?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>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.files.user-selected.read-only</key>
<true/>
</dict>
<dict/>
</plist>
@@ -1,9 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="13771" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" initialViewController="B8D-0N-5wS">
<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="14460.31" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" initialViewController="B8D-0N-5wS">
<dependencies>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="13771"/>
<capability name="Constraints with non-1.0 multipliers" minToolsVersion="5.1"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="14460.31"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
@@ -686,7 +685,7 @@
<scene sceneID="R2V-B0-nI4">
<objects>
<windowController id="B8D-0N-5wS" sceneMemberID="viewController">
<window key="window" title="AppReceiptValidator Receipt Parser" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" oneShot="NO" releasedWhenClosed="NO" showsToolbarButton="NO" visibleAtLaunch="NO" animationBehavior="default" id="IQv-IB-iLA">
<window key="window" title="AppReceiptValidator Receipt Parser" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" visibleAtLaunch="NO" animationBehavior="default" id="IQv-IB-iLA">
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/>
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
<rect key="contentRect" x="196" y="240" width="480" height="270"/>
@@ -712,78 +711,93 @@
<autoresizingMask key="autoresizingMask"/>
<subviews>
<scrollView horizontalLineScroll="10" horizontalPageScroll="10" verticalLineScroll="10" verticalPageScroll="10" hasHorizontalScroller="NO" usesPredominantAxisScrolling="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ynK-dw-fFc">
<rect key="frame" x="0.0" y="0.0" width="316" height="270"/>
<clipView key="contentView" id="yEL-yO-YvB">
<rect key="frame" x="1" y="1" width="314" height="268"/>
<rect key="frame" x="0.0" y="22" width="316" height="248"/>
<clipView key="contentView" drawsBackground="NO" id="yEL-yO-YvB">
<rect key="frame" x="1" y="1" width="314" height="246"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textView toolTip="Paste Base64 here" importsGraphics="NO" richText="NO" verticallyResizable="YES" usesFontPanel="YES" findStyle="panel" allowsCharacterPickerTouchBarItem="NO" allowsUndo="YES" usesRuler="YES" allowsNonContiguousLayout="YES" textCompletion="NO" id="0xW-mT-lME" customClass="DropAcceptingTextView" customModule="AppReceiptValidator_Demo_macOS" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="314" height="268"/>
<rect key="frame" x="0.0" y="0.0" width="314" height="246"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<size key="minSize" width="314" height="268"/>
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
<size key="minSize" width="314" height="246"/>
<size key="maxSize" width="629" height="10000000"/>
<color key="insertionPointColor" white="0.0" alpha="1" colorSpace="calibratedWhite"/>
<color key="insertionPointColor" name="textColor" catalog="System" colorSpace="catalog"/>
</textView>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</clipView>
<scroller key="horizontalScroller" hidden="YES" verticalHuggingPriority="750" doubleValue="1" horizontal="YES" id="TaD-v9-pOg">
<scroller key="horizontalScroller" hidden="YES" wantsLayer="YES" verticalHuggingPriority="750" doubleValue="1" horizontal="YES" id="TaD-v9-pOg">
<rect key="frame" x="-100" y="-100" width="87" height="18"/>
<autoresizingMask key="autoresizingMask"/>
</scroller>
<scroller key="verticalScroller" verticalHuggingPriority="750" doubleValue="1" horizontal="NO" id="hkR-e4-WtN">
<rect key="frame" x="299" y="1" width="16" height="268"/>
<scroller key="verticalScroller" wantsLayer="YES" verticalHuggingPriority="750" doubleValue="1" horizontal="NO" id="hkR-e4-WtN">
<rect key="frame" x="299" y="1" width="16" height="246"/>
<autoresizingMask key="autoresizingMask"/>
</scroller>
</scrollView>
<scrollView toolTip="Parsed Receipt will be shown here" horizontalLineScroll="10" horizontalPageScroll="10" verticalLineScroll="10" verticalPageScroll="10" hasHorizontalScroller="NO" usesPredominantAxisScrolling="NO" translatesAutoresizingMaskIntoConstraints="NO" id="6mt-ay-mAL">
<rect key="frame" x="316" y="0.0" width="315" height="270"/>
<clipView key="contentView" id="YwZ-F9-Cvh">
<clipView key="contentView" drawsBackground="NO" id="YwZ-F9-Cvh">
<rect key="frame" x="1" y="1" width="313" height="268"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textView importsGraphics="NO" richText="NO" verticallyResizable="YES" usesFontPanel="YES" findStyle="panel" allowsCharacterPickerTouchBarItem="NO" allowsUndo="YES" usesRuler="YES" allowsNonContiguousLayout="YES" textCompletion="NO" id="GHT-gS-G1g" customClass="TextView" customModule="AppReceiptValidator_Demo_macOS" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="313" height="268"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
<size key="minSize" width="313" height="268"/>
<size key="maxSize" width="463" height="10000000"/>
<color key="insertionPointColor" white="0.0" alpha="1" colorSpace="calibratedWhite"/>
<color key="insertionPointColor" name="textColor" catalog="System" colorSpace="catalog"/>
</textView>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</clipView>
<scroller key="horizontalScroller" hidden="YES" verticalHuggingPriority="750" doubleValue="1" horizontal="YES" id="xmd-vm-w1P">
<scroller key="horizontalScroller" hidden="YES" wantsLayer="YES" verticalHuggingPriority="750" doubleValue="1" horizontal="YES" id="xmd-vm-w1P">
<rect key="frame" x="-100" y="-100" width="87" height="18"/>
<autoresizingMask key="autoresizingMask"/>
</scroller>
<scroller key="verticalScroller" verticalHuggingPriority="750" doubleValue="1" horizontal="NO" id="uk9-Sg-RUp">
<scroller key="verticalScroller" wantsLayer="YES" verticalHuggingPriority="750" doubleValue="1" horizontal="NO" id="uk9-Sg-RUp">
<rect key="frame" x="298" y="1" width="16" height="268"/>
<autoresizingMask key="autoresizingMask"/>
</scroller>
</scrollView>
<textField verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="yvX-By-nNw">
<rect key="frame" x="0.0" y="0.0" width="316" height="22"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" borderStyle="bezel" placeholderString="Optional DeviceIdentifier for Validation (MAC Address, UUID, Base64)" drawsBackground="YES" id="Z2r-sB-vIS">
<font key="font" usesAppearanceFont="YES"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<connections>
<action selector="identifierDidChange:" target="XfG-lQ-9wD" id="ccM-mH-NPQ"/>
</connections>
</textField>
</subviews>
<constraints>
<constraint firstItem="6mt-ay-mAL" firstAttribute="leading" secondItem="yvX-By-nNw" secondAttribute="trailing" id="231-cE-39Q"/>
<constraint firstItem="6mt-ay-mAL" firstAttribute="top" secondItem="m2S-Jp-Qdl" secondAttribute="top" id="CdY-lv-wee"/>
<constraint firstItem="ynK-dw-fFc" firstAttribute="leading" secondItem="m2S-Jp-Qdl" secondAttribute="leading" id="Cvz-FD-lzg"/>
<constraint firstItem="yvX-By-nNw" firstAttribute="top" secondItem="ynK-dw-fFc" secondAttribute="bottom" id="KSy-yc-TCD"/>
<constraint firstItem="ynK-dw-fFc" firstAttribute="top" secondItem="m2S-Jp-Qdl" secondAttribute="top" id="Rno-M6-Pjq"/>
<constraint firstItem="6mt-ay-mAL" firstAttribute="width" secondItem="m2S-Jp-Qdl" secondAttribute="width" multiplier="1:2" id="SWu-Yn-pVc"/>
<constraint firstAttribute="bottom" secondItem="yvX-By-nNw" secondAttribute="bottom" id="WOQ-2e-jWj"/>
<constraint firstAttribute="trailing" secondItem="6mt-ay-mAL" secondAttribute="trailing" id="Yun-Rd-wsm"/>
<constraint firstItem="ynK-dw-fFc" firstAttribute="top" secondItem="m2S-Jp-Qdl" secondAttribute="top" id="gIn-Ps-HEe"/>
<constraint firstAttribute="bottom" secondItem="6mt-ay-mAL" secondAttribute="bottom" id="lKc-RV-ybx"/>
<constraint firstAttribute="bottom" secondItem="ynK-dw-fFc" secondAttribute="bottom" id="qAW-TV-hHz"/>
<constraint firstItem="yvX-By-nNw" firstAttribute="leading" secondItem="m2S-Jp-Qdl" secondAttribute="leading" id="s2r-QB-ZQb"/>
<constraint firstItem="ynK-dw-fFc" firstAttribute="width" secondItem="m2S-Jp-Qdl" secondAttribute="width" multiplier="1:2" id="wsI-iB-DvJ"/>
</constraints>
</view>
<connections>
<outlet property="dropReceivingView" destination="0xW-mT-lME" id="cuR-H1-BKN"/>
<outlet property="identifierTextField" destination="yvX-By-nNw" id="pW5-lJ-8Cy"/>
<outlet property="inputTextView" destination="0xW-mT-lME" id="8Y7-yb-63r"/>
<outlet property="outputTextView" destination="GHT-gS-G1g" id="cVN-4m-knJ"/>
</connections>
</viewController>
<customObject id="rPt-NT-nkU" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="76" y="726"/>
<point key="canvasLocation" x="75.5" y="726"/>
</scene>
</scenes>
</document>
@@ -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) }
}
}
@@ -12,9 +12,11 @@ import Cocoa
// MARK: - ViewController
class ViewController: NSViewController, NSTextViewDelegate {
class ViewController: NSViewController, NSTextViewDelegate, NSTextFieldDelegate {
private var textFieldObserver: Any?
@IBOutlet private var inputTextView: NSTextView!
@IBOutlet private var identifierTextField: NSTextField!
@IBOutlet private var outputTextView: NSTextView!
@IBOutlet private var dropReceivingView: DropAcceptingTextView!
@@ -28,12 +30,24 @@ class ViewController: NSViewController, NSTextViewDelegate {
self.dropReceivingView.handleDroppedFile = { [unowned self] url in
self.update(url: url)
}
self.textFieldObserver = NotificationCenter.default.addObserver(forName: NSTextField.textDidChangeNotification, object: self.identifierTextField, queue: .main) { [weak self] notification in
guard let self = self else { return }
self.identifierDidChange(self.identifierTextField)
}
}
// MARK: - NSTextViewDelegate
func textDidChange(_ notification: Notification) {
let string = inputTextView.string
let string = self.inputTextView.string
self.update(base64String: string)
}
// MARK: - Identifier Textfield
@IBAction func identifierDidChange(_ sender: NSTextField) {
let string = self.inputTextView.string
self.update(base64String: string)
}
@@ -57,7 +71,8 @@ private extension ViewController {
}
do {
let result = try AppReceiptValidator().parseUnofficialReceipt(origin: .data(data))
self.render(string: "\(result.receipt)\n\(result.unofficialReceipt)")
let validationResult = self.validateReceiptIfNecessary(data: data, macAddress: self.identifierTextField.stringValue) ?? "<Receipt not Validated, No Identifier provided, Supported: UUID, base64, MAC-Address>"
self.render(string: "\(validationResult)\n\n✅ Receipt Parsed\n\(result.receipt)\n\(result.unofficialReceipt)")
} catch {
self.render(string: "\(error)")
}
@@ -79,6 +94,26 @@ private extension ViewController {
}
}
func validateReceiptIfNecessary(data: Data, macAddress: String?) -> String? {
guard let macAddress = macAddress, macAddress.isEmpty == false else { return nil }
let sanitized = macAddress.trimmingCharacters(in: .whitespacesAndNewlines)
let deviceIdentifier = AppReceiptValidator.Parameters.DeviceIdentifier(macAddress: sanitized) ??
(UUID(uuidString: sanitized).flatMap { AppReceiptValidator.Parameters.DeviceIdentifier(uuid: $0) }) ??
AppReceiptValidator.Parameters.DeviceIdentifier(base64Encoded: sanitized)
guard let identifier = deviceIdentifier else { return "<Receipt not Validated\nIdentifier not parseable>" }
let parameters = AppReceiptValidator.Parameters(receiptOrigin: .data(data), shouldValidateSignaturePresence: true, signatureValidation: .shouldValidate(rootCertificateOrigin: .cerFileBundledWithAppReceiptValidator), shouldValidateHash: true, deviceIdentifier: identifier, propertyValidations: [])
let result = AppReceiptValidator().validateReceipt(parameters: parameters)
switch result {
case .success:
return "✅ Receipt Validated\nSignature and Hash Check successful"
case .error(let error, _, _):
return "❌ Receipt Invalid\n\(error)"
}
}
func render(string: String) {
self.outputTextView.string = string
}
@@ -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
}
@@ -0,0 +1,56 @@
//
// DeviceIdentifierTests.swift
// AppReceiptValidator
//
// Created by Hannes Oud on 22.11.18.
// Copyright © 2018 IdeasOnCanvas GmbH. All rights reserved.
//
@testable import AppReceiptValidator
import Foundation
import XCTest
final class DeviceIdentifierTests: XCTestCase {
func testBase64Initializer() {
let deviceIdentifier = AppReceiptValidator.Parameters.DeviceIdentifier(base64Encoded: "bEAItZRe")
XCTAssertNotNil(deviceIdentifier)
}
func testMacAddressInitializer() {
XCTAssertNotNil(AppReceiptValidator.Parameters.DeviceIdentifier(macAddress: "00:0d:3f:cd:02:5f"))
}
func testMacAddressInitializerOtherSeparator() {
XCTAssertNotNil(AppReceiptValidator.Parameters.DeviceIdentifier(macAddress: "00-0d-3f-cd-02-5f", separator: "-"))
}
func testUUIDInitializer() {
XCTAssertNotNil(AppReceiptValidator.Parameters.DeviceIdentifier(uuid: UUID()))
}
func testCurrent() {
let deviceIdentifierData = AppReceiptValidator.Parameters.DeviceIdentifier.currentDevice.getData()
XCTAssertNotNil(deviceIdentifierData)
}
#if os(macOS)
func testMacAddressRetrieval() {
guard let (data, string) = AppReceiptValidator.Parameters.DeviceIdentifier.getPrimaryNetworkMACAddress() else {
XCTFail("Failed to get device mac address")
return
}
guard let deviceIdentifierData = AppReceiptValidator.Parameters.DeviceIdentifier.currentDevice.getData() else {
XCTFail("Failed to get device mac address")
return
}
XCTAssertEqual(data, deviceIdentifierData)
guard let deviceIdentifierFromString = AppReceiptValidator.Parameters.DeviceIdentifier(macAddress: string) else {
XCTFail("Failed to get device identifier from mac address string")
return
}
XCTAssertEqual(deviceIdentifierFromString.getData(), deviceIdentifierData)
}
#endif
}
@@ -7,13 +7,11 @@
objects = {
/* Begin PBXBuildFile section */
D114544621A6BDE6001BEC61 /* DeviceIdentifierTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D114544521A6BDE6001BEC61 /* DeviceIdentifierTests.swift */; };
D114544721A6BDE6001BEC61 /* DeviceIdentifierTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D114544521A6BDE6001BEC61 /* DeviceIdentifierTests.swift */; };
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 */; };
@@ -279,10 +277,8 @@
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
D114544521A6BDE6001BEC61 /* DeviceIdentifierTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeviceIdentifierTests.swift; sourceTree = "<group>"; };
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 +538,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 = (
@@ -644,6 +606,7 @@
D1D6F5411F5D8A3800E86FE1 /* AppReceiptValidationTests.swift */,
D1AA845A1F6ABB31007F2558 /* AppReceiptPropertyValidationTests.swift */,
D150A0ED1F669A880026ED04 /* AppReceiptValidationInAppPurchaseTests.swift */,
D114544521A6BDE6001BEC61 /* DeviceIdentifierTests.swift */,
D1D6F5481F5D9B1100E86FE1 /* Tools */,
D1D6F5431F5D8DBC00E86FE1 /* Test Assets */,
);
@@ -851,7 +814,6 @@
D1D6F4921F5D67E600E86FE1 = {
isa = PBXGroup;
children = (
D14FA71B1F6134CF00545540 /* Sourcery */,
D1D6F4FC1F5D696800E86FE1 /* AppReceiptValidator */,
D1D6F4E51F5D691400E86FE1 /* AppReceiptValidator Demo iOS */,
D19095821F6000A40095729B /* AppReceiptValidator Demo macOS */,
@@ -1135,6 +1097,7 @@
D190957D1F6000A40095729B /* Sources */,
D190957E1F6000A40095729B /* Frameworks */,
D190957F1F6000A40095729B /* Resources */,
D1DEE48D20EBAEE800F95036 /* Swiftlint */,
);
buildRules = (
);
@@ -1190,7 +1153,6 @@
D1D6F4B11F5D684C00E86FE1 /* Frameworks */,
D1D6F4B21F5D684C00E86FE1 /* Headers */,
D1D6F4B31F5D684C00E86FE1 /* Resources */,
D1D6F52D1F5D872200E86FE1 /* Swiftlint */,
);
buildRules = (
);
@@ -1209,7 +1171,6 @@
D1D6F4BE1F5D687400E86FE1 /* Frameworks */,
D1D6F4BF1F5D687400E86FE1 /* Headers */,
D1D6F4C01F5D687400E86FE1 /* Resources */,
D1D6F52E1F5D872B00E86FE1 /* Swiftlint */,
);
buildRules = (
);
@@ -1228,6 +1189,7 @@
D1D6F4E11F5D691400E86FE1 /* Frameworks */,
D1D6F4E21F5D691400E86FE1 /* Resources */,
D1D6F5071F5D696800E86FE1 /* Embed Frameworks */,
D1DEE48C20EBAEC800F95036 /* Swiftlint */,
);
buildRules = (
);
@@ -1246,36 +1208,42 @@
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 = {
enabled = 0;
};
};
};
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;
};
};
@@ -1376,33 +1344,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 */
@@ -1425,6 +1403,7 @@
D19095CD1F601E960095729B /* AppReceiptValidationTests.swift in Sources */,
D1AA845D1F6ABB59007F2558 /* AppReceiptPropertyValidationTests.swift in Sources */,
D150A0EF1F669A880026ED04 /* AppReceiptValidationInAppPurchaseTests.swift in Sources */,
D114544721A6BDE6001BEC61 /* DeviceIdentifierTests.swift in Sources */,
D150A0F01F67E0990026ED04 /* Date+Convenience.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -1437,6 +1416,7 @@
D19095CE1F601E980095729B /* AppReceiptValidationTests.swift in Sources */,
D1AA845C1F6ABB59007F2558 /* AppReceiptPropertyValidationTests.swift in Sources */,
D150A0EE1F669A880026ED04 /* AppReceiptValidationInAppPurchaseTests.swift in Sources */,
D114544621A6BDE6001BEC61 /* DeviceIdentifierTests.swift in Sources */,
D150A0F11F67E0990026ED04 /* Date+Convenience.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -1449,8 +1429,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 */,
@@ -1468,11 +1446,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;
@@ -1543,17 +1519,17 @@
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_ENTITLEMENTS = "AppReceiptValidator Demo macOS/AppReceiptValidator_Demo_macOS.entitlements";
CODE_SIGN_IDENTITY = "Mac Developer";
CODE_SIGN_IDENTITY = "";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
DEVELOPMENT_TEAM = W6L39UYL6Z;
DEVELOPMENT_TEAM = "";
INFOPLIST_FILE = "AppReceiptValidator Demo macOS/Info.plist";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "com.ideasoncanvas.AppReceiptValidator-Demo-macOS";
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
SDKROOT = macosx;
SWIFT_VERSION = 4.0;
SWIFT_VERSION = 4.2;
};
name = Debug;
};
@@ -1561,17 +1537,17 @@
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_ENTITLEMENTS = "AppReceiptValidator Demo macOS/AppReceiptValidator_Demo_macOS.entitlements";
CODE_SIGN_IDENTITY = "Mac Developer";
CODE_SIGN_IDENTITY = "";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
DEVELOPMENT_TEAM = W6L39UYL6Z;
DEVELOPMENT_TEAM = "";
INFOPLIST_FILE = "AppReceiptValidator Demo macOS/Info.plist";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "com.ideasoncanvas.AppReceiptValidator-Demo-macOS";
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
SDKROOT = macosx;
SWIFT_VERSION = 4.0;
SWIFT_VERSION = 4.2;
};
name = Release;
};
@@ -1579,19 +1555,17 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_IDENTITY = "Mac Developer";
CODE_SIGN_IDENTITY = "";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
DEVELOPMENT_TEAM = W6L39UYL6Z;
DEVELOPMENT_TEAM = "";
INFOPLIST_FILE = "AppReceiptValidator Tests macOS/Info.plist";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
MACOSX_DEPLOYMENT_TARGET = 10.12;
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;
};
@@ -1599,19 +1573,17 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_IDENTITY = "Mac Developer";
CODE_SIGN_IDENTITY = "";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
DEVELOPMENT_TEAM = W6L39UYL6Z;
DEVELOPMENT_TEAM = "";
INFOPLIST_FILE = "AppReceiptValidator Tests macOS/Info.plist";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
MACOSX_DEPLOYMENT_TARGET = 10.12;
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;
};
@@ -1619,14 +1591,13 @@
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_TEAM = W6L39UYL6Z;
DEVELOPMENT_TEAM = "";
INFOPLIST_FILE = "AppReceiptValidator Tests iOS/Info.plist";
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;
};
@@ -1634,14 +1605,13 @@
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_TEAM = W6L39UYL6Z;
DEVELOPMENT_TEAM = "";
INFOPLIST_FILE = "AppReceiptValidator Tests iOS/Info.plist";
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;
};
@@ -1659,6 +1629,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;
@@ -1666,6 +1637,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;
@@ -1674,7 +1646,7 @@
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_IDENTITY = "";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
@@ -1718,6 +1690,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;
@@ -1725,6 +1698,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;
@@ -1733,7 +1707,7 @@
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_IDENTITY = "";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
@@ -1759,12 +1733,13 @@
D1D6F4BB1F5D684C00E86FE1 /* Debug */ = {
isa = XCBuildConfiguration;
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 = W6L39UYL6Z;
DEVELOPMENT_TEAM = "";
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
@@ -1780,6 +1755,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 = "";
@@ -1789,12 +1765,13 @@
D1D6F4BC1F5D684C00E86FE1 /* Release */ = {
isa = XCBuildConfiguration;
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 = W6L39UYL6Z;
DEVELOPMENT_TEAM = "";
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
@@ -1809,6 +1786,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 = "";
@@ -1818,12 +1796,13 @@
D1D6F4C81F5D687400E86FE1 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
APPLICATION_EXTENSION_API_ONLY = YES;
CODE_SIGN_IDENTITY = "";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 1;
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = W6L39UYL6Z;
DEVELOPMENT_TEAM = "";
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
@@ -1840,6 +1819,7 @@
PRODUCT_NAME = AppReceiptValidator;
SDKROOT = macosx;
SKIP_INSTALL = YES;
SWIFT_VERSION = 4.2;
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
};
@@ -1848,12 +1828,13 @@
D1D6F4C91F5D687400E86FE1 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
APPLICATION_EXTENSION_API_ONLY = YES;
CODE_SIGN_IDENTITY = "";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 1;
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = W6L39UYL6Z;
DEVELOPMENT_TEAM = "";
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
@@ -1870,6 +1851,7 @@
PRODUCT_NAME = AppReceiptValidator;
SDKROOT = macosx;
SKIP_INSTALL = YES;
SWIFT_VERSION = 4.2;
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
};
@@ -1881,13 +1863,13 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_TEAM = W6L39UYL6Z;
DEVELOPMENT_TEAM = "";
INFOPLIST_FILE = "AppReceiptValidator Demo iOS/Info.plist";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
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;
@@ -1898,12 +1880,12 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_TEAM = W6L39UYL6Z;
DEVELOPMENT_TEAM = "";
INFOPLIST_FILE = "AppReceiptValidator Demo iOS/Info.plist";
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"
@@ -83,7 +83,7 @@ public extension AppReceiptValidator.Parameters {
/// Used for calculating/validating the SHA1-Hash part of a receipt.
///
/// - currentDevice: Obtains it from the system location: MAC Adress on macOS, deviceIdentifierForVendor on iOS
/// - currentDevice: Obtains it from the system location: MAC Address on macOS, deviceIdentifierForVendor on iOS
/// - data: Specific Data to use
public enum DeviceIdentifier {
@@ -99,6 +99,20 @@ public extension AppReceiptValidator.Parameters {
self = .data(uuid.data)
}
/// Returns .data by parsing a MAC Address String
///
/// - Parameters:
/// - macAddress: A MAC Address of the form "00:0d:3f:cd:02:5f"
/// - separator: Defaults to `":"`
///
/// - Note: on macOS the MAC Addresses can be read from terminal command `ifconfig` looking for ther `ether` entry of `5e`.
public init?(macAddress: String, separator: String = ":") {
let bytes = macAddress.components(separatedBy: separator).compactMap { UInt8($0, radix: 16) }
guard bytes.count == 6 else { return nil }
self = .data(Data(bytes))
}
public func getData() -> Data? {
switch self {
case .data(let data):
@@ -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
@@ -20,7 +20,7 @@ extension AppReceiptValidator.Parameters.DeviceIdentifier {
/// Original implementation https://gist.github.com/mminer/82975d3781e2f42fc644d7fbfbf4f905
///
/// - Returns: The MAC Address as Data and String representation
private static func getPrimaryNetworkMACAddress() -> (data: Data, addressString: String)? {
static func getPrimaryNetworkMACAddress() -> (data: Data, addressString: String)? {
let matching = IOServiceMatching("IOEthernetInterface") as NSMutableDictionary
matching[kIOPropertyMatchKey] = ["IOPrimaryInterface": true]
var servicesIterator: io_iterator_t = 0
@@ -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:
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 299 KiB

After

Width:  |  Height:  |  Size: 463 KiB