Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1ba0b31095 | |||
| 5121e901f5 | |||
| d31ab05fe2 | |||
| c4769bc42a | |||
| 6605544598 | |||
| 3bb92db368 | |||
| 97b0adff0a | |||
| bf875864ea |
@@ -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>
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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,6 +7,8 @@
|
||||
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 */; };
|
||||
@@ -275,6 +277,7 @@
|
||||
/* 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>"; };
|
||||
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>"; };
|
||||
@@ -603,6 +606,7 @@
|
||||
D1D6F5411F5D8A3800E86FE1 /* AppReceiptValidationTests.swift */,
|
||||
D1AA845A1F6ABB31007F2558 /* AppReceiptPropertyValidationTests.swift */,
|
||||
D150A0ED1F669A880026ED04 /* AppReceiptValidationInAppPurchaseTests.swift */,
|
||||
D114544521A6BDE6001BEC61 /* DeviceIdentifierTests.swift */,
|
||||
D1D6F5481F5D9B1100E86FE1 /* Tools */,
|
||||
D1D6F5431F5D8DBC00E86FE1 /* Test Assets */,
|
||||
);
|
||||
@@ -1399,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;
|
||||
@@ -1411,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;
|
||||
|
||||
@@ -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):
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 299 KiB After Width: | Height: | Size: 463 KiB |
Reference in New Issue
Block a user