@@ -22,7 +22,7 @@ As a first application, users who can prove they indeed hold a valid passport ca
|
||||
|
||||
- ✅ Basic passport verifier circuit
|
||||
- 🚧 Optimization
|
||||
- ✅ Selective disclosure
|
||||
- 🚧 Selective disclosure
|
||||
- ✅ Basic react native frontend
|
||||
- ✅ Passport verification pipeline, android
|
||||
- 🚧 Passport verification pipeline, iOS
|
||||
|
||||
16
app/App.tsx
@@ -38,7 +38,7 @@ import { config } from "@gluestack-ui/config" // Optional if you want to use def
|
||||
|
||||
// @ts-ignore
|
||||
import PassportReader from 'react-native-passport-reader';
|
||||
import {checkInputs, getFirstName} from './utils/checks';
|
||||
import {getFirstName, formatDuration, formatProof} from './utils/utils';
|
||||
import {
|
||||
DEFAULT_PNUMBER,
|
||||
DEFAULT_DOB,
|
||||
@@ -46,9 +46,17 @@ import {
|
||||
DEFAULT_ADDRESS,
|
||||
LOCAL_IP,
|
||||
} from '@env';
|
||||
import {DataHash, PassportData} from './types/passportData';
|
||||
import {arraysAreEqual, bytesToBigDecimal, dataHashesObjToArray, formatAndConcatenateDataHashes, formatDuration, formatMrz, formatProof, splitToWords} from './utils/utils';
|
||||
import {hash, toUnsignedByte} from './utils/computeEContent';
|
||||
import {DataHash, PassportData} from '../common/src/utils/types';
|
||||
import {
|
||||
hash,
|
||||
toUnsignedByte,
|
||||
checkInputs,
|
||||
bytesToBigDecimal,
|
||||
dataHashesObjToArray,
|
||||
formatAndConcatenateDataHashes,
|
||||
formatMrz,
|
||||
splitToWords
|
||||
} from '../common/src/utils/utils';
|
||||
|
||||
console.log('DEFAULT_PNUMBER', DEFAULT_PNUMBER);
|
||||
console.log('LOCAL_IP', LOCAL_IP);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Embassy App
|
||||
# Proof of Passport App
|
||||
|
||||
Only Android right now, under heavy development
|
||||
|
||||
|
||||
@@ -37,14 +37,14 @@ dependencies {
|
||||
implementation 'com.google.android.material:material:1.7.0'
|
||||
implementation 'androidx.core:core-ktx:1.9.0'
|
||||
implementation 'com.wdullaer:materialdatetimepicker:3.5.2'
|
||||
implementation 'org.jmrtd:jmrtd:0.7.18'
|
||||
implementation 'org.jmrtd:jmrtd:0.7.18' // getting different errors whether it's 18 or 40 // 23 <== this works
|
||||
// implementation files('../../../../../jmrtd-0.7.18-sources/target/jmrtd-0.7.18.jar')
|
||||
// implementation files('../../app/libs/jmrtd-0.7.18.jar')
|
||||
implementation 'net.sf.scuba:scuba-sc-android:0.0.18'
|
||||
implementation 'com.madgag.spongycastle:prov:1.54.0.0'
|
||||
implementation 'com.gemalto.jp2:jp2-android:1.0.3'
|
||||
implementation 'com.github.mhshams:jnbis:1.1.0'
|
||||
implementation 'org.bouncycastle:bcpkix-jdk15on:1.65' // do not update
|
||||
// implementation 'org.bouncycastle:bcpkix-jdk15on:1.65' // do not update
|
||||
implementation 'commons-io:commons-io:2.8.0'
|
||||
implementation 'com.squareup.okhttp3:okhttp:4.9.0'
|
||||
implementation 'com.android.support:appcompat-v7:25.1.0'
|
||||
@@ -63,4 +63,4 @@ cargo {
|
||||
targets = ["arm64", "darwin-aarch64"] // Those work
|
||||
apiLevel = 29
|
||||
profile = 'release'
|
||||
}
|
||||
}
|
||||
@@ -254,8 +254,11 @@ class RNPassportReaderModule(private val reactContext: ReactApplicationContext)
|
||||
override fun doInBackground(vararg params: Void?): Exception? {
|
||||
try {
|
||||
isoDep.timeout = 10000
|
||||
Log.e("MY_LOGS", "This should obvsly log")
|
||||
val cardService = CardService.getInstance(isoDep)
|
||||
Log.e("MY_LOGS", "cardService gotten")
|
||||
cardService.open()
|
||||
Log.e("MY_LOGS", "cardService opened")
|
||||
val service = PassportService(
|
||||
cardService,
|
||||
PassportService.NORMAL_MAX_TRANCEIVE_LENGTH,
|
||||
@@ -263,31 +266,42 @@ class RNPassportReaderModule(private val reactContext: ReactApplicationContext)
|
||||
false,
|
||||
false,
|
||||
)
|
||||
Log.e("MY_LOGS", "service gotten")
|
||||
service.open()
|
||||
Log.e("MY_LOGS", "service opened")
|
||||
var paceSucceeded = false
|
||||
try {
|
||||
Log.e("MY_LOGS", "trying to get cardAccessFile...")
|
||||
val cardAccessFile = CardAccessFile(service.getInputStream(PassportService.EF_CARD_ACCESS))
|
||||
Log.e("MY_LOGS", "cardAccessFile: ${cardAccessFile}")
|
||||
|
||||
val securityInfoCollection = cardAccessFile.securityInfos
|
||||
for (securityInfo: SecurityInfo in securityInfoCollection) {
|
||||
if (securityInfo is PACEInfo) {
|
||||
Log.e("MY_LOGS", "trying PACE...")
|
||||
service.doPACE(
|
||||
bacKey,
|
||||
securityInfo.objectIdentifier,
|
||||
PACEInfo.toParameterSpec(securityInfo.parameterId),
|
||||
null,
|
||||
)
|
||||
Log.e("MY_LOGS", "PACE succeeded")
|
||||
paceSucceeded = true
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Log.w(TAG, e)
|
||||
Log.w("MY_LOGS", e)
|
||||
}
|
||||
Log.e("MY_LOGS", "Sending select applet command with paceSucceeded: ${paceSucceeded}") // this is false so PACE doesn't succeed
|
||||
service.sendSelectApplet(paceSucceeded)
|
||||
if (!paceSucceeded) {
|
||||
try {
|
||||
Log.e("MY_LOGS", "trying to get EF_COM...")
|
||||
service.getInputStream(PassportService.EF_COM).read()
|
||||
} catch (e: Exception) {
|
||||
service.doBAC(bacKey)
|
||||
Log.e("MY_LOGS", "doing BAC")
|
||||
service.doBAC(bacKey) // <======================== error happens here
|
||||
Log.e("MY_LOGS", "BAC done")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,4 +9,3 @@
|
||||
# For example, to use nvm with brew, add the following line
|
||||
# . "$(brew --prefix nvm)/nvm.sh" --no-use
|
||||
export NODE_BINARY=$(command -v node)
|
||||
export BREW_FIX=$(command -v brew)
|
||||
|
||||
@@ -1,695 +0,0 @@
|
||||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 51;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
28BAEE044BE68A5986B97866 /* Pods_NFCPassportReaderApp.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A7BD003B33886ED0F3F03325 /* Pods_NFCPassportReaderApp.framework */; };
|
||||
8C4EEF9CDD6DAFEF26F8909A /* Pods_NFCPassportReaderAppTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA39DA603B1A7EBD8FC38112 /* Pods_NFCPassportReaderAppTests.framework */; };
|
||||
A1298C9F25D53A5C00F5713E /* ViewExt.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1298C9E25D53A5C00F5713E /* ViewExt.swift */; };
|
||||
A1614B9225D5856600191749 /* ExportPassportView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1614B9125D5856600191749 /* ExportPassportView.swift */; };
|
||||
A16EB23122A9E9E10008F53F /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = A16EB23022A9E9E10008F53F /* AppDelegate.swift */; };
|
||||
A16EB23322A9E9E10008F53F /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = A16EB23222A9E9E10008F53F /* SceneDelegate.swift */; };
|
||||
A16EB23A22A9E9E20008F53F /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A16EB23922A9E9E20008F53F /* Assets.xcassets */; };
|
||||
A16EB23D22A9E9E20008F53F /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = A16EB23B22A9E9E20008F53F /* LaunchScreen.storyboard */; };
|
||||
A17134BE22C8EF7200C457C3 /* MainView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A17134BD22C8EF7100C457C3 /* MainView.swift */; };
|
||||
A17134C022C8F0A600C457C3 /* PassportUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = A17134BF22C8F0A600C457C3 /* PassportUtils.swift */; };
|
||||
A17375F525F78B0D005995DA /* PACETests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A17375F425F78B0C005995DA /* PACETests.swift */; };
|
||||
A1769DF725D3E318006002D1 /* SettingsStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1769DF625D3E318006002D1 /* SettingsStore.swift */; };
|
||||
A1816E9C22C9059F00F546A0 /* PassportView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1816E9B22C9059F00F546A0 /* PassportView.swift */; };
|
||||
A18248C22369D17300581384 /* DetailsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A18248C12369D17300581384 /* DetailsView.swift */; };
|
||||
A182DE6125DD6F1300341204 /* StoredPassportView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A182DE6025DD6F1300341204 /* StoredPassportView.swift */; };
|
||||
A182DE6325DD730D00341204 /* FileManagerExt.swift in Sources */ = {isa = PBXBuildFile; fileRef = A182DE6225DD730D00341204 /* FileManagerExt.swift */; };
|
||||
A182DE6825DD7EA600341204 /* MRZScannerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A182DE6725DD7EA600341204 /* MRZScannerViewController.swift */; };
|
||||
A1A13B9525B8A29E0026074C /* UIApplicationExt.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1A13B9425B8A29E0026074C /* UIApplicationExt.swift */; };
|
||||
A1A4C0F725B5E4D70070908B /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1A4C0F625B5E4D70070908B /* Foundation.framework */; };
|
||||
A1C234C225DD19DE003FFD79 /* PassportSummaryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1C234C125DD19DE003FFD79 /* PassportSummaryView.swift */; };
|
||||
A1CE83AC22C91D1300E3EACF /* StringExt.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1CE83AB22C91D1300E3EACF /* StringExt.swift */; };
|
||||
A1DD3F3F22C535F10067255C /* masterList.pem in Resources */ = {isa = PBXBuildFile; fileRef = A1DD3F3E22C535F00067255C /* masterList.pem */; };
|
||||
A1EBC5242370BAB2004DD19E /* DataGroupParsingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1EBC5212370BAB2004DD19E /* DataGroupParsingTests.swift */; };
|
||||
A1EBC5252370BAB2004DD19E /* NFCPassportReaderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1EBC5222370BAB2004DD19E /* NFCPassportReaderTests.swift */; };
|
||||
A1FDC52E25D3F15D00D22FF4 /* SettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1FDC52D25D3F15D00D22FF4 /* SettingsView.swift */; };
|
||||
A1FDC53225D3F19E00D22FF4 /* ViewModifiers.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1FDC53125D3F19E00D22FF4 /* ViewModifiers.swift */; };
|
||||
A1FDC53425D3F1DE00D22FF4 /* CheckBoxView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1FDC53325D3F1DE00D22FF4 /* CheckBoxView.swift */; };
|
||||
A1FDC53625D43AB400D22FF4 /* MRZEntryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1FDC53525D43AB400D22FF4 /* MRZEntryView.swift */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
A1EBC5122370B88D004DD19E /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = A16EB22522A9E9E10008F53F /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = A16EB22C22A9E9E10008F53F;
|
||||
remoteInfo = NFCPassportReaderApp;
|
||||
};
|
||||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
29684A8780D423313153D8B6 /* Pods-NFCPassportReaderAppTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NFCPassportReaderAppTests.release.xcconfig"; path = "Target Support Files/Pods-NFCPassportReaderAppTests/Pods-NFCPassportReaderAppTests.release.xcconfig"; sourceTree = "<group>"; };
|
||||
3B684038F7C81C32BA310074 /* Pods-NFCPassportReaderAppTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NFCPassportReaderAppTests.debug.xcconfig"; path = "Target Support Files/Pods-NFCPassportReaderAppTests/Pods-NFCPassportReaderAppTests.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
574315DEF74ED0B9CC6A8DC7 /* Pods-NFCPassportReaderApp.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NFCPassportReaderApp.debug.xcconfig"; path = "Target Support Files/Pods-NFCPassportReaderApp/Pods-NFCPassportReaderApp.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
A1095E982588FBB100D2A46A /* CHANGELOG */ = {isa = PBXFileReference; lastKnownFileType = text; name = CHANGELOG; path = ../../../CHANGELOG; sourceTree = "<group>"; };
|
||||
A1095E9B2589032D00D2A46A /* readme.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; name = readme.md; path = ../../readme.md; sourceTree = "<group>"; };
|
||||
A1298C9E25D53A5C00F5713E /* ViewExt.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewExt.swift; sourceTree = "<group>"; };
|
||||
A1614B9125D5856600191749 /* ExportPassportView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExportPassportView.swift; sourceTree = "<group>"; };
|
||||
A16EB22D22A9E9E10008F53F /* NFCPassportReaderApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = NFCPassportReaderApp.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
A16EB23022A9E9E10008F53F /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||
A16EB23222A9E9E10008F53F /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = "<group>"; };
|
||||
A16EB23922A9E9E20008F53F /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||
A16EB23C22A9E9E20008F53F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
||||
A16EB23E22A9E9E20008F53F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
A16EB24422A9EA000008F53F /* NFCPassportReader.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = NFCPassportReader.entitlements; sourceTree = "<group>"; };
|
||||
A17134BD22C8EF7100C457C3 /* MainView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MainView.swift; sourceTree = "<group>"; };
|
||||
A17134BF22C8F0A600C457C3 /* PassportUtils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PassportUtils.swift; sourceTree = "<group>"; };
|
||||
A17375F425F78B0C005995DA /* PACETests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PACETests.swift; sourceTree = "<group>"; };
|
||||
A1769DF625D3E318006002D1 /* SettingsStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsStore.swift; sourceTree = "<group>"; };
|
||||
A1816E9B22C9059F00F546A0 /* PassportView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PassportView.swift; sourceTree = "<group>"; };
|
||||
A18248C12369D17300581384 /* DetailsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DetailsView.swift; sourceTree = "<group>"; };
|
||||
A182DE6025DD6F1300341204 /* StoredPassportView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StoredPassportView.swift; sourceTree = "<group>"; };
|
||||
A182DE6225DD730D00341204 /* FileManagerExt.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileManagerExt.swift; sourceTree = "<group>"; };
|
||||
A182DE6725DD7EA600341204 /* MRZScannerViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MRZScannerViewController.swift; sourceTree = "<group>"; };
|
||||
A1A13B9425B8A29E0026074C /* UIApplicationExt.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIApplicationExt.swift; sourceTree = "<group>"; };
|
||||
A1A4C0F625B5E4D70070908B /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
|
||||
A1C234C125DD19DE003FFD79 /* PassportSummaryView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PassportSummaryView.swift; sourceTree = "<group>"; };
|
||||
A1CE83AB22C91D1300E3EACF /* StringExt.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StringExt.swift; sourceTree = "<group>"; };
|
||||
A1DD3F3E22C535F00067255C /* masterList.pem */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = masterList.pem; sourceTree = "<group>"; };
|
||||
A1EBC50D2370B88D004DD19E /* NFCPassportReaderAppTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = NFCPassportReaderAppTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
A1EBC5112370B88D004DD19E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
A1EBC5212370BAB2004DD19E /* DataGroupParsingTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DataGroupParsingTests.swift; sourceTree = "<group>"; };
|
||||
A1EBC5222370BAB2004DD19E /* NFCPassportReaderTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NFCPassportReaderTests.swift; sourceTree = "<group>"; };
|
||||
A1FDC52D25D3F15D00D22FF4 /* SettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsView.swift; sourceTree = "<group>"; };
|
||||
A1FDC53125D3F19E00D22FF4 /* ViewModifiers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewModifiers.swift; sourceTree = "<group>"; };
|
||||
A1FDC53325D3F1DE00D22FF4 /* CheckBoxView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckBoxView.swift; sourceTree = "<group>"; };
|
||||
A1FDC53525D43AB400D22FF4 /* MRZEntryView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MRZEntryView.swift; sourceTree = "<group>"; };
|
||||
A7BD003B33886ED0F3F03325 /* Pods_NFCPassportReaderApp.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_NFCPassportReaderApp.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
B239DD4BD3AA9ECF4F595D22 /* Pods-NFCPassportReaderApp.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NFCPassportReaderApp.release.xcconfig"; path = "Target Support Files/Pods-NFCPassportReaderApp/Pods-NFCPassportReaderApp.release.xcconfig"; sourceTree = "<group>"; };
|
||||
DA39DA603B1A7EBD8FC38112 /* Pods_NFCPassportReaderAppTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_NFCPassportReaderAppTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
A16EB22A22A9E9E10008F53F /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
A1A4C0F725B5E4D70070908B /* Foundation.framework in Frameworks */,
|
||||
28BAEE044BE68A5986B97866 /* Pods_NFCPassportReaderApp.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
A1EBC50A2370B88D004DD19E /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
8C4EEF9CDD6DAFEF26F8909A /* Pods_NFCPassportReaderAppTests.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
A1298C9B25D539CD00F5713E /* HelperViews */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
A1FDC53325D3F1DE00D22FF4 /* CheckBoxView.swift */,
|
||||
A1298C9E25D53A5C00F5713E /* ViewExt.swift */,
|
||||
A1FDC53125D3F19E00D22FF4 /* ViewModifiers.swift */,
|
||||
);
|
||||
path = HelperViews;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
A16EB22422A9E9E10008F53F = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
A16EB22F22A9E9E10008F53F /* NFCPassportReaderApp */,
|
||||
A1EBC50E2370B88D004DD19E /* NFCPassportReaderAppTests */,
|
||||
A16EB22E22A9E9E10008F53F /* Products */,
|
||||
EE354654AF07CDA5F9366735 /* Pods */,
|
||||
A1A4C0E325B5D3370070908B /* Frameworks */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
A16EB22E22A9E9E10008F53F /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
A16EB22D22A9E9E10008F53F /* NFCPassportReaderApp.app */,
|
||||
A1EBC50D2370B88D004DD19E /* NFCPassportReaderAppTests.xctest */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
A16EB22F22A9E9E10008F53F /* NFCPassportReaderApp */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
A16EB24422A9EA000008F53F /* NFCPassportReader.entitlements */,
|
||||
A1CE83AF22C91DB600E3EACF /* Model */,
|
||||
A182DE6425DD731900341204 /* Extensions */,
|
||||
A1CE83B022C91DF100E3EACF /* Views */,
|
||||
A16EB23022A9E9E10008F53F /* AppDelegate.swift */,
|
||||
A16EB23222A9E9E10008F53F /* SceneDelegate.swift */,
|
||||
A16EB23922A9E9E20008F53F /* Assets.xcassets */,
|
||||
A16EB23B22A9E9E20008F53F /* LaunchScreen.storyboard */,
|
||||
A16EB23E22A9E9E20008F53F /* Info.plist */,
|
||||
A1DD3F3E22C535F00067255C /* masterList.pem */,
|
||||
A1095E982588FBB100D2A46A /* CHANGELOG */,
|
||||
A1095E9B2589032D00D2A46A /* readme.md */,
|
||||
);
|
||||
path = NFCPassportReaderApp;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
A182DE6425DD731900341204 /* Extensions */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
A1CE83AB22C91D1300E3EACF /* StringExt.swift */,
|
||||
A182DE6225DD730D00341204 /* FileManagerExt.swift */,
|
||||
A1A13B9425B8A29E0026074C /* UIApplicationExt.swift */,
|
||||
);
|
||||
path = Extensions;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
A1A4C0E325B5D3370070908B /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
A1A4C0F625B5E4D70070908B /* Foundation.framework */,
|
||||
A7BD003B33886ED0F3F03325 /* Pods_NFCPassportReaderApp.framework */,
|
||||
DA39DA603B1A7EBD8FC38112 /* Pods_NFCPassportReaderAppTests.framework */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
A1CE83AF22C91DB600E3EACF /* Model */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
A17134BF22C8F0A600C457C3 /* PassportUtils.swift */,
|
||||
A1769DF625D3E318006002D1 /* SettingsStore.swift */,
|
||||
);
|
||||
path = Model;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
A1CE83B022C91DF100E3EACF /* Views */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
A1298C9B25D539CD00F5713E /* HelperViews */,
|
||||
A17134BD22C8EF7100C457C3 /* MainView.swift */,
|
||||
A1FDC53525D43AB400D22FF4 /* MRZEntryView.swift */,
|
||||
A1FDC52D25D3F15D00D22FF4 /* SettingsView.swift */,
|
||||
A1816E9B22C9059F00F546A0 /* PassportView.swift */,
|
||||
A1C234C125DD19DE003FFD79 /* PassportSummaryView.swift */,
|
||||
A18248C12369D17300581384 /* DetailsView.swift */,
|
||||
A182DE6025DD6F1300341204 /* StoredPassportView.swift */,
|
||||
A1614B9125D5856600191749 /* ExportPassportView.swift */,
|
||||
A182DE6725DD7EA600341204 /* MRZScannerViewController.swift */,
|
||||
);
|
||||
path = Views;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
A1EBC50E2370B88D004DD19E /* NFCPassportReaderAppTests */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
A1EBC5212370BAB2004DD19E /* DataGroupParsingTests.swift */,
|
||||
A1EBC5222370BAB2004DD19E /* NFCPassportReaderTests.swift */,
|
||||
A1EBC5112370B88D004DD19E /* Info.plist */,
|
||||
A17375F425F78B0C005995DA /* PACETests.swift */,
|
||||
);
|
||||
path = NFCPassportReaderAppTests;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
EE354654AF07CDA5F9366735 /* Pods */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
574315DEF74ED0B9CC6A8DC7 /* Pods-NFCPassportReaderApp.debug.xcconfig */,
|
||||
B239DD4BD3AA9ECF4F595D22 /* Pods-NFCPassportReaderApp.release.xcconfig */,
|
||||
3B684038F7C81C32BA310074 /* Pods-NFCPassportReaderAppTests.debug.xcconfig */,
|
||||
29684A8780D423313153D8B6 /* Pods-NFCPassportReaderAppTests.release.xcconfig */,
|
||||
);
|
||||
path = Pods;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
A16EB22C22A9E9E10008F53F /* NFCPassportReaderApp */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = A16EB24122A9E9E20008F53F /* Build configuration list for PBXNativeTarget "NFCPassportReaderApp" */;
|
||||
buildPhases = (
|
||||
441F58E6FEE1B28C771C6B72 /* [CP] Check Pods Manifest.lock */,
|
||||
A16EB22922A9E9E10008F53F /* Sources */,
|
||||
A16EB22A22A9E9E10008F53F /* Frameworks */,
|
||||
A16EB22B22A9E9E10008F53F /* Resources */,
|
||||
4E62328E60F074D699104549 /* [CP] Embed Pods Frameworks */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = NFCPassportReaderApp;
|
||||
productName = NFCTest;
|
||||
productReference = A16EB22D22A9E9E10008F53F /* NFCPassportReaderApp.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
A1EBC50C2370B88D004DD19E /* NFCPassportReaderAppTests */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = A1EBC5162370B88D004DD19E /* Build configuration list for PBXNativeTarget "NFCPassportReaderAppTests" */;
|
||||
buildPhases = (
|
||||
11A5FABC15C673E24DA3F0C2 /* [CP] Check Pods Manifest.lock */,
|
||||
A1EBC5092370B88D004DD19E /* Sources */,
|
||||
A1EBC50A2370B88D004DD19E /* Frameworks */,
|
||||
A1EBC50B2370B88D004DD19E /* Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
A1EBC5132370B88D004DD19E /* PBXTargetDependency */,
|
||||
);
|
||||
name = NFCPassportReaderAppTests;
|
||||
productName = NFCPassportReaderAppTests;
|
||||
productReference = A1EBC50D2370B88D004DD19E /* NFCPassportReaderAppTests.xctest */;
|
||||
productType = "com.apple.product-type.bundle.unit-test";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
A16EB22522A9E9E10008F53F /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastSwiftUpdateCheck = 1120;
|
||||
LastUpgradeCheck = 1300;
|
||||
ORGANIZATIONNAME = "Andy Qua";
|
||||
TargetAttributes = {
|
||||
A16EB22C22A9E9E10008F53F = {
|
||||
CreatedOnToolsVersion = 11.0;
|
||||
LastSwiftMigration = 1100;
|
||||
};
|
||||
A1EBC50C2370B88D004DD19E = {
|
||||
CreatedOnToolsVersion = 11.2;
|
||||
TestTargetID = A16EB22C22A9E9E10008F53F;
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = A16EB22822A9E9E10008F53F /* Build configuration list for PBXProject "NFCPassportReaderApp" */;
|
||||
compatibilityVersion = "Xcode 9.3";
|
||||
developmentRegion = en;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
Base,
|
||||
);
|
||||
mainGroup = A16EB22422A9E9E10008F53F;
|
||||
productRefGroup = A16EB22E22A9E9E10008F53F /* Products */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
A16EB22C22A9E9E10008F53F /* NFCPassportReaderApp */,
|
||||
A1EBC50C2370B88D004DD19E /* NFCPassportReaderAppTests */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXResourcesBuildPhase section */
|
||||
A16EB22B22A9E9E10008F53F /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
A16EB23D22A9E9E20008F53F /* LaunchScreen.storyboard in Resources */,
|
||||
A1DD3F3F22C535F10067255C /* masterList.pem in Resources */,
|
||||
A16EB23A22A9E9E20008F53F /* Assets.xcassets in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
A1EBC50B2370B88D004DD19E /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXShellScriptBuildPhase section */
|
||||
11A5FABC15C673E24DA3F0C2 /* [CP] Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
|
||||
"${PODS_ROOT}/Manifest.lock",
|
||||
);
|
||||
name = "[CP] Check Pods Manifest.lock";
|
||||
outputFileListPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
"$(DERIVED_FILE_DIR)/Pods-NFCPassportReaderAppTests-checkManifestLockResult.txt",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
441F58E6FEE1B28C771C6B72 /* [CP] Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
|
||||
"${PODS_ROOT}/Manifest.lock",
|
||||
);
|
||||
name = "[CP] Check Pods Manifest.lock";
|
||||
outputFileListPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
"$(DERIVED_FILE_DIR)/Pods-NFCPassportReaderApp-checkManifestLockResult.txt",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
4E62328E60F074D699104549 /* [CP] Embed Pods Frameworks */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-NFCPassportReaderApp/Pods-NFCPassportReaderApp-frameworks-${CONFIGURATION}-input-files.xcfilelist",
|
||||
);
|
||||
name = "[CP] Embed Pods Frameworks";
|
||||
outputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-NFCPassportReaderApp/Pods-NFCPassportReaderApp-frameworks-${CONFIGURATION}-output-files.xcfilelist",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-NFCPassportReaderApp/Pods-NFCPassportReaderApp-frameworks.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
A16EB22922A9E9E10008F53F /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
A182DE6825DD7EA600341204 /* MRZScannerViewController.swift in Sources */,
|
||||
A1CE83AC22C91D1300E3EACF /* StringExt.swift in Sources */,
|
||||
A1FDC53625D43AB400D22FF4 /* MRZEntryView.swift in Sources */,
|
||||
A17134BE22C8EF7200C457C3 /* MainView.swift in Sources */,
|
||||
A16EB23122A9E9E10008F53F /* AppDelegate.swift in Sources */,
|
||||
A1816E9C22C9059F00F546A0 /* PassportView.swift in Sources */,
|
||||
A1769DF725D3E318006002D1 /* SettingsStore.swift in Sources */,
|
||||
A1298C9F25D53A5C00F5713E /* ViewExt.swift in Sources */,
|
||||
A182DE6325DD730D00341204 /* FileManagerExt.swift in Sources */,
|
||||
A1FDC52E25D3F15D00D22FF4 /* SettingsView.swift in Sources */,
|
||||
A182DE6125DD6F1300341204 /* StoredPassportView.swift in Sources */,
|
||||
A1FDC53225D3F19E00D22FF4 /* ViewModifiers.swift in Sources */,
|
||||
A1C234C225DD19DE003FFD79 /* PassportSummaryView.swift in Sources */,
|
||||
A1614B9225D5856600191749 /* ExportPassportView.swift in Sources */,
|
||||
A18248C22369D17300581384 /* DetailsView.swift in Sources */,
|
||||
A1FDC53425D3F1DE00D22FF4 /* CheckBoxView.swift in Sources */,
|
||||
A1A13B9525B8A29E0026074C /* UIApplicationExt.swift in Sources */,
|
||||
A16EB23322A9E9E10008F53F /* SceneDelegate.swift in Sources */,
|
||||
A17134C022C8F0A600C457C3 /* PassportUtils.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
A1EBC5092370B88D004DD19E /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
A1EBC5252370BAB2004DD19E /* NFCPassportReaderTests.swift in Sources */,
|
||||
A17375F525F78B0D005995DA /* PACETests.swift in Sources */,
|
||||
A1EBC5242370BAB2004DD19E /* DataGroupParsingTests.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXTargetDependency section */
|
||||
A1EBC5132370B88D004DD19E /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = A16EB22C22A9E9E10008F53F /* NFCPassportReaderApp */;
|
||||
targetProxy = A1EBC5122370B88D004DD19E /* PBXContainerItemProxy */;
|
||||
};
|
||||
/* End PBXTargetDependency section */
|
||||
|
||||
/* Begin PBXVariantGroup section */
|
||||
A16EB23B22A9E9E20008F53F /* LaunchScreen.storyboard */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
A16EB23C22A9E9E20008F53F /* Base */,
|
||||
);
|
||||
name = LaunchScreen.storyboard;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXVariantGroup section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
A16EB23F22A9E9E20008F53F /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
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;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
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_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||
MTL_FAST_MATH = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
A16EB24022A9E9E20008F53F /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
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;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
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_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
MTL_FAST_MATH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
SWIFT_COMPILATION_MODE = wholemodule;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-O";
|
||||
VALIDATE_PRODUCT = YES;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
A16EB24222A9E9E20008F53F /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 574315DEF74ED0B9CC6A8DC7 /* Pods-NFCPassportReaderApp.debug.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = NFCPassportReaderApp/NFCPassportReader.entitlements;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 4.1;
|
||||
DEVELOPMENT_TEAM = BV8DN58CD3;
|
||||
INFOPLIST_FILE = NFCPassportReaderApp/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.1;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.iag.nfcpassportreader;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = 1;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
A16EB24322A9E9E20008F53F /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = B239DD4BD3AA9ECF4F595D22 /* Pods-NFCPassportReaderApp.release.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = NFCPassportReaderApp/NFCPassportReader.entitlements;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 4.1;
|
||||
DEVELOPMENT_TEAM = BV8DN58CD3;
|
||||
INFOPLIST_FILE = NFCPassportReaderApp/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.1;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.iag.nfcpassportreader;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = 1;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
A1EBC5142370B88D004DD19E /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 3B684038F7C81C32BA310074 /* Pods-NFCPassportReaderAppTests.debug.xcconfig */;
|
||||
buildSettings = {
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
DEVELOPMENT_TEAM = A4ZM73UFF5;
|
||||
INFOPLIST_FILE = NFCPassportReaderAppTests/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.2;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
"@loader_path/Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.andyqua.NFCPassportReaderAppTests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/NFCPassportReaderApp.app/NFCPassportReaderApp";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
A1EBC5152370B88D004DD19E /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 29684A8780D423313153D8B6 /* Pods-NFCPassportReaderAppTests.release.xcconfig */;
|
||||
buildSettings = {
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
DEVELOPMENT_TEAM = A4ZM73UFF5;
|
||||
INFOPLIST_FILE = NFCPassportReaderAppTests/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.2;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
"@loader_path/Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.andyqua.NFCPassportReaderAppTests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/NFCPassportReaderApp.app/NFCPassportReaderApp";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
A16EB22822A9E9E10008F53F /* Build configuration list for PBXProject "NFCPassportReaderApp" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
A16EB23F22A9E9E20008F53F /* Debug */,
|
||||
A16EB24022A9E9E20008F53F /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
A16EB24122A9E9E20008F53F /* Build configuration list for PBXNativeTarget "NFCPassportReaderApp" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
A16EB24222A9E9E20008F53F /* Debug */,
|
||||
A16EB24322A9E9E20008F53F /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
A1EBC5162370B88D004DD19E /* Build configuration list for PBXNativeTarget "NFCPassportReaderAppTests" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
A1EBC5142370B88D004DD19E /* Debug */,
|
||||
A1EBC5152370B88D004DD19E /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = A16EB22522A9E9E10008F53F /* Project object */;
|
||||
}
|
||||
@@ -1,106 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1300"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "A16EB22C22A9E9E10008F53F"
|
||||
BuildableName = "NFCPassportReaderApp.app"
|
||||
BlueprintName = "NFCPassportReaderApp"
|
||||
ReferencedContainer = "container:NFCPassportReaderApp.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<Testables>
|
||||
<TestableReference
|
||||
skipped = "NO">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "NFCPassportReaderTests"
|
||||
BuildableName = "NFCPassportReaderTests"
|
||||
BlueprintName = "NFCPassportReaderTests"
|
||||
ReferencedContainer = "container:..">
|
||||
</BuildableReference>
|
||||
</TestableReference>
|
||||
<TestableReference
|
||||
skipped = "NO">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "A1EBC50C2370B88D004DD19E"
|
||||
BuildableName = "NFCPassportReaderAppTests.xctest"
|
||||
BlueprintName = "NFCPassportReaderAppTests"
|
||||
ReferencedContainer = "container:NFCPassportReaderApp.xcodeproj">
|
||||
</BuildableReference>
|
||||
</TestableReference>
|
||||
</Testables>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
disableMainThreadChecker = "YES"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
debugServiceExtension = "internal"
|
||||
allowLocationSimulation = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "A16EB22C22A9E9E10008F53F"
|
||||
BuildableName = "NFCPassportReaderApp.app"
|
||||
BlueprintName = "NFCPassportReaderApp"
|
||||
ReferencedContainer = "container:NFCPassportReaderApp.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
<EnvironmentVariables>
|
||||
<EnvironmentVariable
|
||||
key = "OS_ACTIVITY_MODE"
|
||||
value = "disable"
|
||||
isEnabled = "YES">
|
||||
</EnvironmentVariable>
|
||||
</EnvironmentVariables>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Release"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
debugDocumentVersioning = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "A16EB22C22A9E9E10008F53F"
|
||||
BuildableName = "NFCPassportReaderApp.app"
|
||||
BlueprintName = "NFCPassportReaderApp"
|
||||
ReferencedContainer = "container:NFCPassportReaderApp.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
||||
@@ -1,10 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "group:NFCPassportReaderApp.xcodeproj">
|
||||
</FileRef>
|
||||
<FileRef
|
||||
location = "group:Pods/Pods.xcodeproj">
|
||||
</FileRef>
|
||||
</Workspace>
|
||||
@@ -1,8 +0,0 @@
|
||||
<?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>PreviewsEnabled</key>
|
||||
<false/>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -1,39 +0,0 @@
|
||||
//
|
||||
// AppDelegate.swift
|
||||
// NFCPassportReaderApp
|
||||
//
|
||||
// Created by Andy Qua on 06/06/2019.
|
||||
// Copyright © 2019 Andy Qua. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import CoreNFC
|
||||
|
||||
@UIApplicationMain
|
||||
class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||
|
||||
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func applicationWillTerminate(_ application: UIApplication) {
|
||||
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
|
||||
}
|
||||
|
||||
// MARK: UISceneSession Lifecycle
|
||||
|
||||
func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
|
||||
// Called when a new scene session is being created.
|
||||
// Use this method to select a configuration to create the new scene with.
|
||||
return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
|
||||
}
|
||||
|
||||
func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
|
||||
// Called when the user discards a scene session.
|
||||
// If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
|
||||
// Use this method to release any resources that were specific to the discarded scenes, as they will not return.
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -1,158 +0,0 @@
|
||||
{
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
},
|
||||
"images" : [
|
||||
{
|
||||
"size" : "40x40",
|
||||
"filename" : "icon-40.png",
|
||||
"idiom" : "ipad",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"size" : "40x40",
|
||||
"idiom" : "ipad",
|
||||
"scale" : "2x",
|
||||
"filename" : "icon-40@2x.png"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "60x60",
|
||||
"scale" : "2x",
|
||||
"filename" : "icon-60@2x.png"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"filename" : "icon-72.png",
|
||||
"size" : "72x72",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"scale" : "2x",
|
||||
"idiom" : "ipad",
|
||||
"size" : "72x72",
|
||||
"filename" : "icon-72@2x.png"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "76x76",
|
||||
"scale" : "1x",
|
||||
"filename" : "icon-76.png"
|
||||
},
|
||||
{
|
||||
"scale" : "2x",
|
||||
"size" : "76x76",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "icon-76@2x.png"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "50x50",
|
||||
"filename" : "icon-small-50.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"scale" : "2x",
|
||||
"filename" : "icon-small-50@2x.png",
|
||||
"size" : "50x50",
|
||||
"idiom" : "ipad"
|
||||
},
|
||||
{
|
||||
"scale" : "1x",
|
||||
"filename" : "icon-small.png",
|
||||
"idiom" : "iphone",
|
||||
"size" : "29x29"
|
||||
},
|
||||
{
|
||||
"scale" : "2x",
|
||||
"size" : "29x29",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "icon-small@2x.png"
|
||||
},
|
||||
{
|
||||
"filename" : "icon.png",
|
||||
"idiom" : "iphone",
|
||||
"size" : "57x57",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"scale" : "2x",
|
||||
"size" : "57x57",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "icon@2x.png"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-small@3x.png",
|
||||
"size" : "29x29",
|
||||
"idiom" : "iphone",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"size" : "40x40",
|
||||
"scale" : "3x",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "icon-40@3x.png"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-60@3x.png",
|
||||
"scale" : "3x",
|
||||
"idiom" : "iphone",
|
||||
"size" : "60x60"
|
||||
},
|
||||
{
|
||||
"size" : "40x40",
|
||||
"filename" : "icon-40@2x.png",
|
||||
"idiom" : "iphone",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"scale" : "1x",
|
||||
"idiom" : "ipad",
|
||||
"size" : "29x29",
|
||||
"filename" : "icon-small.png"
|
||||
},
|
||||
{
|
||||
"size" : "29x29",
|
||||
"scale" : "2x",
|
||||
"filename" : "icon-small@2x.png",
|
||||
"idiom" : "ipad"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"filename" : "icon-83.5@2x.png",
|
||||
"scale" : "2x",
|
||||
"size" : "83.5x83.5"
|
||||
},
|
||||
{
|
||||
"size" : "20x20",
|
||||
"scale" : "2x",
|
||||
"filename" : "notification-icon@2x.png",
|
||||
"idiom" : "iphone"
|
||||
},
|
||||
{
|
||||
"scale" : "3x",
|
||||
"filename" : "notification-icon@3x.png",
|
||||
"idiom" : "iphone",
|
||||
"size" : "20x20"
|
||||
},
|
||||
{
|
||||
"filename" : "notification-icon~ipad.png",
|
||||
"idiom" : "ipad",
|
||||
"size" : "20x20",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "notification-icon~ipad@2x.png",
|
||||
"size" : "20x20",
|
||||
"scale" : "2x",
|
||||
"idiom" : "ipad"
|
||||
},
|
||||
{
|
||||
"filename" : "ios-marketing.png",
|
||||
"size" : "1024x1024",
|
||||
"idiom" : "ios-marketing",
|
||||
"scale" : "1x"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
Before Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 4.2 KiB |
|
Before Width: | Height: | Size: 7.0 KiB |
|
Before Width: | Height: | Size: 7.0 KiB |
|
Before Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 3.7 KiB |
|
Before Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 3.9 KiB |
|
Before Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 5.7 KiB |
|
Before Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 4.6 KiB |
|
Before Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 6.9 KiB |
|
Before Width: | Height: | Size: 370 KiB |
|
Before Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 723 B |
|
Before Width: | Height: | Size: 1.5 KiB |
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "background.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 387 KiB |
@@ -1,21 +0,0 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "head.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 187 KiB |
@@ -1,25 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13122.16" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
|
||||
<dependencies>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13104.12"/>
|
||||
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--View Controller-->
|
||||
<scene sceneID="EHf-IW-A2E">
|
||||
<objects>
|
||||
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
|
||||
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="backgroundColor" xcode11CocoaTouchSystemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
|
||||
<viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
|
||||
</view>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="53" y="375"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
</document>
|
||||
@@ -1,16 +0,0 @@
|
||||
//
|
||||
// FileManagerExt.swift
|
||||
// NFCPassportReaderApp
|
||||
//
|
||||
// Created by Andy Qua on 17/02/2021.
|
||||
// Copyright © 2021 Andy Qua. All rights reserved.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
extension FileManager {
|
||||
static var cachesFolder : URL {
|
||||
FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask)[0]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
//
|
||||
// StringExt.swift
|
||||
// NFCPassportReaderApp
|
||||
//
|
||||
// Created by Andy Qua on 30/06/2019.
|
||||
// Copyright © 2019 Andy Qua. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
/// Some Utility methods for string - access characters by index
|
||||
extension String {
|
||||
subscript(_ i: Int) -> String {
|
||||
let idx1 = index(startIndex, offsetBy: i)
|
||||
let idx2 = index(idx1, offsetBy: 1)
|
||||
return String(self[idx1..<idx2])
|
||||
}
|
||||
|
||||
subscript (bounds: CountableRange<Int>) -> String {
|
||||
let start = index(startIndex, offsetBy: bounds.lowerBound)
|
||||
let end = index(startIndex, offsetBy: bounds.upperBound)
|
||||
return String(self[start..<end])
|
||||
}
|
||||
|
||||
subscript (bounds: CountableClosedRange<Int>) -> String {
|
||||
let start = index(startIndex, offsetBy: bounds.lowerBound)
|
||||
let end = index(startIndex, offsetBy: bounds.upperBound)
|
||||
return String(self[start...end])
|
||||
}
|
||||
|
||||
subscript (bounds: CountablePartialRangeFrom<Int>) -> String {
|
||||
let start = index(startIndex, offsetBy: bounds.lowerBound)
|
||||
return String(self[start...])
|
||||
}
|
||||
|
||||
func strip() -> String {
|
||||
let trimmed = self.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
return trimmed
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
//
|
||||
// UIApplicationExt.swift
|
||||
// NFCPassportReaderApp
|
||||
//
|
||||
// Created by Andy Qua on 20/01/2021.
|
||||
// Copyright © 2021 Andy Qua. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
extension UIApplication {
|
||||
static var release: String {
|
||||
return Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as! String? ?? "x.x"
|
||||
}
|
||||
static var build: String {
|
||||
return Bundle.main.object(forInfoDictionaryKey: "CFBundleVersion") as! String? ?? "x"
|
||||
}
|
||||
static var version: String {
|
||||
return "\(release).\(build)"
|
||||
}
|
||||
}
|
||||
@@ -1,77 +0,0 @@
|
||||
<?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>CFBundleDevelopmentRegion</key>
|
||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||
<key>CFBundleDisplayName</key>
|
||||
<string>NFCPassportReaderApp</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>$(MARKETING_VERSION)</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>$(CURRENT_PROJECT_VERSION)</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>NFCReaderUsageDescription</key>
|
||||
<string>This app uses NFC to scan passports</string>
|
||||
<key>NSCameraUsageDescription</key>
|
||||
<string>This app uses the camera to read passports</string>
|
||||
<key>UIApplicationSceneManifest</key>
|
||||
<dict>
|
||||
<key>UIApplicationSupportsMultipleScenes</key>
|
||||
<false/>
|
||||
<key>UISceneConfigurations</key>
|
||||
<dict>
|
||||
<key>UIWindowSceneSessionRoleApplication</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
<string>LaunchScreen</string>
|
||||
<key>UISceneConfigurationName</key>
|
||||
<string>Default Configuration</string>
|
||||
<key>UISceneDelegateClassName</key>
|
||||
<string>$(PRODUCT_MODULE_NAME).SceneDelegate</string>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>UIFileSharingEnabled</key>
|
||||
<true/>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
<string>LaunchScreen</string>
|
||||
<key>UIRequiredDeviceCapabilities</key>
|
||||
<array>
|
||||
<string>nfc</string>
|
||||
<string>armv7</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations~ipad</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>com.apple.developer.nfc.readersession.iso7816.select-identifiers</key>
|
||||
<array>
|
||||
<string>A0000002471001</string>
|
||||
<string>A0000002472001</string>
|
||||
<string>00000000000000</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -1,76 +0,0 @@
|
||||
//
|
||||
// PassportUtils.swift
|
||||
// NFCPassportReaderApp
|
||||
//
|
||||
// Created by Andy Qua on 30/06/2019.
|
||||
// Copyright © 2019 Andy Qua. All rights reserved.
|
||||
//
|
||||
|
||||
import NFCPassportReader
|
||||
|
||||
class PassportUtils {
|
||||
|
||||
func getMRZKey(passportNumber: String, dateOfBirth: String, dateOfExpiry: String ) -> String {
|
||||
|
||||
// Pad fields if necessary
|
||||
let pptNr = pad( passportNumber, fieldLength:9)
|
||||
let dob = pad( dateOfBirth, fieldLength:6)
|
||||
let exp = pad( dateOfExpiry, fieldLength:6)
|
||||
|
||||
// Calculate checksums
|
||||
let passportNrChksum = calcCheckSum(pptNr)
|
||||
let dateOfBirthChksum = calcCheckSum(dob)
|
||||
let expiryDateChksum = calcCheckSum(exp)
|
||||
|
||||
let mrzKey = "\(pptNr)\(passportNrChksum)\(dob)\(dateOfBirthChksum)\(exp)\(expiryDateChksum)"
|
||||
|
||||
return mrzKey
|
||||
}
|
||||
|
||||
func pad( _ value : String, fieldLength:Int ) -> String {
|
||||
// Pad out field lengths with < if they are too short
|
||||
let paddedValue = (value + String(repeating: "<", count: fieldLength)).prefix(fieldLength)
|
||||
return String(paddedValue)
|
||||
}
|
||||
|
||||
func calcCheckSum( _ checkString : String ) -> Int {
|
||||
let characterDict = ["0" : "0", "1" : "1", "2" : "2", "3" : "3", "4" : "4", "5" : "5", "6" : "6", "7" : "7", "8" : "8", "9" : "9", "<" : "0", " " : "0", "A" : "10", "B" : "11", "C" : "12", "D" : "13", "E" : "14", "F" : "15", "G" : "16", "H" : "17", "I" : "18", "J" : "19", "K" : "20", "L" : "21", "M" : "22", "N" : "23", "O" : "24", "P" : "25", "Q" : "26", "R" : "27", "S" : "28","T" : "29", "U" : "30", "V" : "31", "W" : "32", "X" : "33", "Y" : "34", "Z" : "35"]
|
||||
|
||||
var sum = 0
|
||||
var m = 0
|
||||
let multipliers : [Int] = [7, 3, 1]
|
||||
for c in checkString {
|
||||
guard let lookup = characterDict["\(c)"],
|
||||
let number = Int(lookup) else { return 0 }
|
||||
let product = number * multipliers[m]
|
||||
sum += product
|
||||
m = (m+1) % 3
|
||||
}
|
||||
|
||||
return (sum % 10)
|
||||
}
|
||||
|
||||
static func shareLogs() {
|
||||
do {
|
||||
let arr = Log.logData
|
||||
let data = try JSONSerialization.data(withJSONObject: arr, options: .prettyPrinted)
|
||||
|
||||
let temporaryURL = URL(fileURLWithPath: NSTemporaryDirectory() + "passportreader.log")
|
||||
try data.write(to: temporaryURL)
|
||||
|
||||
let av = UIActivityViewController(activityItems: [temporaryURL], applicationActivities: nil)
|
||||
let keyWindow = UIApplication.shared.connectedScenes
|
||||
.filter({$0.activationState == .foregroundActive})
|
||||
.map({$0 as? UIWindowScene})
|
||||
.compactMap({$0})
|
||||
.first?.windows
|
||||
.filter({$0.isKeyWindow}).first
|
||||
|
||||
keyWindow?.rootViewController?.present(av, animated: true, completion: nil)
|
||||
} catch {
|
||||
print( "ERROR - \(error)" )
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,107 +0,0 @@
|
||||
//
|
||||
// SettingsStore.swift
|
||||
// NFCPassportReaderApp
|
||||
//
|
||||
// Created by Andy Qua on 10/02/2021.
|
||||
// Copyright © 2021 Andy Qua. All rights reserved.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
import Combine
|
||||
import NFCPassportReader
|
||||
|
||||
final class SettingsStore: ObservableObject {
|
||||
|
||||
private enum Keys {
|
||||
static let captureLog = "captureLog"
|
||||
static let logLevel = "logLevel"
|
||||
static let useNewVerification = "useNewVerification"
|
||||
static let savePassportOnScan = "savePassportOnScan"
|
||||
static let passportNumber = "passportNumber"
|
||||
static let dateOfBirth = "dateOfBirth"
|
||||
static let dateOfExpiry = "dateOfExpiry"
|
||||
|
||||
static let allVals = [captureLog, logLevel, useNewVerification, passportNumber, dateOfBirth, dateOfExpiry]
|
||||
}
|
||||
|
||||
private let cancellable: Cancellable
|
||||
private let defaults: UserDefaults
|
||||
|
||||
let objectWillChange = PassthroughSubject<Void, Never>()
|
||||
|
||||
init(defaults: UserDefaults = .standard) {
|
||||
self.defaults = defaults
|
||||
|
||||
|
||||
defaults.register(defaults: [
|
||||
Keys.captureLog: true,
|
||||
Keys.logLevel: 1,
|
||||
Keys.useNewVerification: true,
|
||||
Keys.savePassportOnScan: false,
|
||||
Keys.passportNumber: "",
|
||||
Keys.dateOfBirth: Date().timeIntervalSince1970,
|
||||
Keys.dateOfExpiry: Date().timeIntervalSince1970,
|
||||
])
|
||||
|
||||
cancellable = NotificationCenter.default
|
||||
.publisher(for: UserDefaults.didChangeNotification)
|
||||
.map { _ in () }
|
||||
.subscribe(objectWillChange)
|
||||
}
|
||||
|
||||
func reset() {
|
||||
if let bundleID = Bundle.main.bundleIdentifier {
|
||||
UserDefaults.standard.removePersistentDomain(forName: bundleID)
|
||||
}
|
||||
}
|
||||
|
||||
var shouldCaptureLogs: Bool {
|
||||
set { defaults.set(newValue, forKey: Keys.captureLog) }
|
||||
get { defaults.bool(forKey: Keys.captureLog) }
|
||||
}
|
||||
|
||||
var logLevel: LogLevel {
|
||||
get {
|
||||
return LogLevel(rawValue:defaults.integer(forKey: Keys.logLevel)) ?? .info
|
||||
}
|
||||
set {
|
||||
defaults.set(newValue.rawValue, forKey: Keys.logLevel)
|
||||
}
|
||||
}
|
||||
|
||||
var useNewVerificationMethod: Bool {
|
||||
set { defaults.set(newValue, forKey: Keys.useNewVerification) }
|
||||
get { defaults.bool(forKey: Keys.useNewVerification) }
|
||||
}
|
||||
|
||||
var savePassportOnScan: Bool {
|
||||
set { defaults.set(newValue, forKey: Keys.savePassportOnScan) }
|
||||
get { defaults.bool(forKey: Keys.savePassportOnScan) }
|
||||
}
|
||||
|
||||
var passportNumber: String {
|
||||
set { defaults.set(newValue, forKey: Keys.passportNumber) }
|
||||
get { defaults.string(forKey: Keys.passportNumber) ?? "" }
|
||||
}
|
||||
|
||||
var dateOfBirth: Date {
|
||||
set {
|
||||
defaults.set(newValue.timeIntervalSince1970, forKey: Keys.dateOfBirth)
|
||||
}
|
||||
get {
|
||||
let d = Date(timeIntervalSince1970: defaults.double(forKey: Keys.dateOfBirth))
|
||||
return d
|
||||
}
|
||||
}
|
||||
|
||||
var dateOfExpiry: Date {
|
||||
set {
|
||||
defaults.set(newValue.timeIntervalSince1970, forKey: Keys.dateOfExpiry) }
|
||||
get {
|
||||
let d = Date(timeIntervalSince1970: defaults.double(forKey: Keys.dateOfExpiry))
|
||||
return d
|
||||
}
|
||||
}
|
||||
|
||||
@Published var passport : NFCPassportModel?
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
<?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.developer.nfc.readersession.formats</key>
|
||||
<array>
|
||||
<string>TAG</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -1,57 +0,0 @@
|
||||
//
|
||||
// SceneDelegate.swift
|
||||
// NFCPassportReaderApp
|
||||
//
|
||||
// Created by Andy Qua on 06/06/2019.
|
||||
// Copyright © 2019 Andy Qua. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import SwiftUI
|
||||
|
||||
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
|
||||
|
||||
var window: UIWindow?
|
||||
var settings = SettingsStore()
|
||||
|
||||
|
||||
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
|
||||
|
||||
// Use a UIHostingController as window root view controller
|
||||
if let windowScene = scene as? UIWindowScene {
|
||||
let window = UIWindow(windowScene: windowScene)
|
||||
window.rootViewController = UIHostingController(rootView: MainView().environmentObject(settings))
|
||||
self.window = window
|
||||
window.makeKeyAndVisible()
|
||||
}
|
||||
}
|
||||
|
||||
func sceneDidDisconnect(_ scene: UIScene) {
|
||||
// Called as the scene is being released by the system.
|
||||
// This occurs shortly after the scene enters the background, or when its session is discarded.
|
||||
// Release any resources associated with this scene that can be re-created the next time the scene connects.
|
||||
// The scene may re-connect later, as its session was not neccessarily discarded (see `application:didDiscardSceneSessions` instead).
|
||||
}
|
||||
|
||||
func sceneDidBecomeActive(_ scene: UIScene) {
|
||||
// Called when the scene has moved from an inactive state to an active state.
|
||||
// Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
|
||||
}
|
||||
|
||||
func sceneWillResignActive(_ scene: UIScene) {
|
||||
// Called when the scene will move from an active state to an inactive state.
|
||||
// This may occur due to temporary interruptions (ex. an incoming phone call).
|
||||
}
|
||||
|
||||
func sceneWillEnterForeground(_ scene: UIScene) {
|
||||
// Called as the scene transitions from the background to the foreground.
|
||||
// Use this method to undo the changes made on entering the background.
|
||||
}
|
||||
|
||||
func sceneDidEnterBackground(_ scene: UIScene) {
|
||||
// Called as the scene transitions from the foreground to the background.
|
||||
// Use this method to save data, release shared resources, and store enough scene-specific state information
|
||||
// to restore the scene back to its current state.
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,197 +0,0 @@
|
||||
//
|
||||
// DetailsView.swift
|
||||
// NFCPassportReaderApp
|
||||
//
|
||||
// Created by Andy Qua on 30/10/2019.
|
||||
// Copyright © 2019 Andy Qua. All rights reserved.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
import NFCPassportReader
|
||||
|
||||
struct Item : Identifiable {
|
||||
var id = UUID()
|
||||
var title : String
|
||||
var value : String
|
||||
|
||||
var textColor : Color {
|
||||
return value.hasPrefix("FAILED") ? Color.red : Color.primary
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
struct DetailsView : View {
|
||||
private var passport: NFCPassportModel
|
||||
private var sectionNames = ["Chip information", "Verification information", "Document signing certificate", "Country signing certificate", "Security Info details", "Datagroup Hashes"]
|
||||
private var sections = [[Item]]()
|
||||
|
||||
init( passport : NFCPassportModel ) {
|
||||
self.passport = passport
|
||||
sections.append(getChipInfoSection(self.passport))
|
||||
sections.append(getVerificationDetailsSection(self.passport))
|
||||
sections.append(getCertificateSigningCertDetails(certItems:self.passport.documentSigningCertificate?.getItemsAsDict()))
|
||||
sections.append(getCertificateSigningCertDetails(certItems:self.passport.countrySigningCertificate?.getItemsAsDict()))
|
||||
sections.append(getSecurityInfosSection(self.passport))
|
||||
sections.append(getDataGroupHashesSection(self.passport))
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
VStack {
|
||||
List {
|
||||
ForEach( 0 ..< self.sectionNames.count ) { i in
|
||||
if self.sections[i].count > 0 {
|
||||
SectionGroup(sectionTitle: self.sectionNames[i], items: self.sections[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func getChipInfoSection(_ passport: NFCPassportModel) -> [Item] {
|
||||
// Build Chip info section
|
||||
let chipInfo = [Item(title:"LDS Version", value: passport.LDSVersion),
|
||||
Item(title:"Data groups present", value: passport.dataGroupsPresent.joined(separator: ", ")),
|
||||
Item(title:"Data groups read", value: passport.dataGroupsAvailable.map { $0.getName()}.joined(separator: ", "))]
|
||||
|
||||
return chipInfo
|
||||
}
|
||||
|
||||
func getVerificationDetailsSection(_ passport: NFCPassportModel) -> [Item] {
|
||||
// Build Verification Info section
|
||||
var activeAuth : String = "Not supported"
|
||||
if passport.activeAuthenticationSupported {
|
||||
activeAuth = passport.activeAuthenticationPassed ? "SUCCESS\nSignature verified" : "FAILED\nCould not verify signature"
|
||||
}
|
||||
var chipAuth : String = "Not supported"
|
||||
if passport.isChipAuthenticationSupported {
|
||||
switch( passport.chipAuthenticationStatus ) {
|
||||
case .notDone:
|
||||
chipAuth = "Supported - Not done"
|
||||
case .success:
|
||||
chipAuth = "SUCCESS\nSignature verified"
|
||||
case .failed:
|
||||
chipAuth = "FAILED\nCould not verify signature"
|
||||
}
|
||||
}
|
||||
|
||||
var authType : String = "Authentication not done"
|
||||
if passport.PACEStatus == .success {
|
||||
authType = "PACE"
|
||||
} else if passport.BACStatus == .success {
|
||||
authType = "BAC"
|
||||
}
|
||||
|
||||
// Do PACE Info
|
||||
var paceStatus = "Not Supported"
|
||||
if passport.isPACESupported {
|
||||
switch( passport.PACEStatus ) {
|
||||
case .notDone:
|
||||
paceStatus = "Supported - Not done"
|
||||
case .success:
|
||||
paceStatus = "SUCCESS"
|
||||
case .failed:
|
||||
paceStatus = "FAILED"
|
||||
}
|
||||
}
|
||||
|
||||
let verificationDetails : [Item] = [
|
||||
Item(title: "Access Control", value: authType),
|
||||
Item(title: "PACE", value: paceStatus),
|
||||
Item(title: "Chip Authentication", value: chipAuth),
|
||||
Item(title: "Active Authentication", value: activeAuth),
|
||||
Item(title: "Document Signing Certificate", value: passport.documentSigningCertificateVerified ? "SUCCESS\nSOD Signature verified" : "FAILED\nCouldn't verify SOD signature"),
|
||||
Item(title: "Country signing Certificate", value: passport.passportCorrectlySigned ? "SUCCESS\nmatched to country signing certificate" : "FAILED\nCouldn't build trust chain"),
|
||||
Item(title: "Data group hashes", value: passport.passportDataNotTampered ? "SUCCESS\nAll hashes match" : "FAILED\nCouldn't match hashes" )
|
||||
]
|
||||
|
||||
return verificationDetails
|
||||
}
|
||||
|
||||
func getCertificateSigningCertDetails( certItems : [CertificateItem : String]? ) -> [Item] {
|
||||
let titles : [String] = ["Serial number", "Signature algorithm", "Public key algorithm", "Certificate fingerprint", "Issuer", "Subject", "Valid from", "Valid to"]
|
||||
|
||||
var items = [Item]()
|
||||
if certItems?.count ?? 0 == 0 {
|
||||
items.append( Item(title:"Certificate details", value: "NOT FOUND" ) )
|
||||
} else {
|
||||
for title in titles {
|
||||
let ci = CertificateItem(rawValue:title)!
|
||||
items.append( Item(title:title, value: certItems?[ci] ?? "") )
|
||||
}
|
||||
}
|
||||
return items
|
||||
}
|
||||
|
||||
func getDataGroupHashesSection(_ passport: NFCPassportModel) -> [Item] {
|
||||
var dgHashes = [Item]()
|
||||
for id in DataGroupId.allCases {
|
||||
if let hash = passport.dataGroupHashes[id] {
|
||||
dgHashes.append( Item(title:hash.id, value:hash.match ? "MATCHED" : "UNMATCHED"))
|
||||
dgHashes.append( Item(title:"SOD Hash", value: hash.sodHash))
|
||||
dgHashes.append( Item(title:"Computed Hash", value: hash.computedHash))
|
||||
}
|
||||
}
|
||||
return dgHashes
|
||||
}
|
||||
|
||||
func getSecurityInfosSection( _ passport : NFCPassportModel) -> [Item] {
|
||||
guard let dg14 = passport.getDataGroup(.DG14) as? DataGroup14 else { return [] }
|
||||
|
||||
var items = [Item]()
|
||||
for secInfo in dg14.securityInfos {
|
||||
var title : String = ""
|
||||
var value : String = ""
|
||||
if let cai = secInfo as? ChipAuthenticationInfo {
|
||||
title = "ChipAuthenticationInfo"
|
||||
value = "\(secInfo.getProtocolOIDString())\n\(secInfo.getObjectIdentifier())\nUses Key Id: \(cai.getKeyId())"
|
||||
} else if let capki = secInfo as? ChipAuthenticationPublicKeyInfo {
|
||||
title = "ChipAuthenticationPublicKeyInfo"
|
||||
value = "\(secInfo.getProtocolOIDString())\n\(secInfo.getObjectIdentifier())\nKey Id: \(capki.getKeyId())"
|
||||
} else if let pacei = secInfo as? PACEInfo {
|
||||
title = "PACEInfo"
|
||||
value = "\(pacei.getProtocolOIDString())\n\(pacei.getObjectIdentifier())\nParameter ID: \(pacei.getParameterId() ?? -1)"
|
||||
} else if let activeAuthInfo = secInfo as? ActiveAuthenticationInfo {
|
||||
title = "ActiveAuthenticationInfo"
|
||||
value =
|
||||
"\(activeAuthInfo.getProtocolOIDString())\n\(activeAuthInfo.getSignatureAlgorithmOIDString() ?? "")"
|
||||
}
|
||||
|
||||
items.append( Item(title:title, value: value))
|
||||
|
||||
}
|
||||
return items
|
||||
}
|
||||
}
|
||||
|
||||
struct SectionGroup : View {
|
||||
var sectionTitle : String
|
||||
var items : [Item]
|
||||
|
||||
var body: some View {
|
||||
Section(header: Text(sectionTitle)) {
|
||||
ForEach(self.items) { item in
|
||||
VStack(alignment:.leading, spacing:0) {
|
||||
Text(item.title)
|
||||
.font(.headline)
|
||||
Text(item.value)
|
||||
.foregroundColor(item.textColor)
|
||||
.lineLimit(nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
struct DetailsView_Previews: PreviewProvider {
|
||||
|
||||
static var previews: some View {
|
||||
let settings = SettingsStore()
|
||||
let passport = NFCPassportModel()
|
||||
return DetailsView(passport:passport)
|
||||
.environmentObject(settings)
|
||||
.environment( \.colorScheme, .light)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,164 +0,0 @@
|
||||
//
|
||||
// ExportPassportView.swift
|
||||
// NFCPassportReaderApp
|
||||
//
|
||||
// Created by Andy Qua on 11/02/2021.
|
||||
// Copyright © 2021 Andy Qua. All rights reserved.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
import NFCPassportReader
|
||||
|
||||
struct MultipleSelectionRow: View {
|
||||
var title: String
|
||||
var isSelected: Bool
|
||||
var action: () -> Void
|
||||
|
||||
var body: some View {
|
||||
Button(action: self.action) {
|
||||
HStack {
|
||||
Text(self.title)
|
||||
if self.isSelected {
|
||||
Spacer()
|
||||
Image(systemName: "checkmark")
|
||||
}
|
||||
}
|
||||
}
|
||||
.foregroundColor(.primary)
|
||||
}
|
||||
}
|
||||
|
||||
struct ExportPassportView: View {
|
||||
@EnvironmentObject var settings: SettingsStore
|
||||
|
||||
@State var items: [DataGroupId] = []
|
||||
@State var selections: [DataGroupId] = []
|
||||
@State var isAASupported : Bool = false
|
||||
@State var includeAA : Bool = false
|
||||
|
||||
var body: some View {
|
||||
Form {
|
||||
Section(header: Text("Select Passport items to export"), footer:Text("* contains personal information")) {
|
||||
List {
|
||||
ForEach(items, id: \.self) { item in
|
||||
MultipleSelectionRow(title: dgToText(item), isSelected: self.selections.contains(item)) {
|
||||
if self.selections.contains(item) {
|
||||
self.selections.removeAll(where: { $0 == item })
|
||||
}
|
||||
else {
|
||||
self.selections.append(item)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if isAASupported {
|
||||
Toggle("Include Active Authentication Challenge/Response?", isOn: $includeAA)
|
||||
.foregroundColor(.primary)
|
||||
}
|
||||
}
|
||||
Button(action: {
|
||||
sharePassport()
|
||||
}, label: {
|
||||
Text("Export selected passport details")
|
||||
.font(.title3)
|
||||
})
|
||||
.foregroundColor(.primary)
|
||||
}
|
||||
.navigationTitle("Export passport")
|
||||
.onAppear() {
|
||||
if let passport = settings.passport {
|
||||
items = [.SOD, .COM]
|
||||
items.append(contentsOf: DataGroupId.allCases.filter { passport.dataGroupsAvailable.contains($0) } )
|
||||
|
||||
// Default select only the DGs that contain no personal info.
|
||||
selections = [.SOD, .COM, .DG14, .DG15]
|
||||
isAASupported = passport.activeAuthenticationSupported
|
||||
if isAASupported {
|
||||
includeAA = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension ExportPassportView {
|
||||
func sharePassport() {
|
||||
do {
|
||||
let dict = settings.passport!.dumpPassportData( selectedDataGroups:selections,includeActiveAuthenticationData: includeAA)
|
||||
let data = try JSONSerialization.data(withJSONObject: dict, options: .prettyPrinted)
|
||||
|
||||
let temporaryURL = URL(fileURLWithPath: NSTemporaryDirectory() + "passport.json")
|
||||
try data.write(to: temporaryURL)
|
||||
|
||||
let av = UIActivityViewController(activityItems: [temporaryURL], applicationActivities: nil)
|
||||
|
||||
let keyWindow = UIApplication.shared.connectedScenes
|
||||
.filter({$0.activationState == .foregroundActive})
|
||||
.map({$0 as? UIWindowScene})
|
||||
.compactMap({$0})
|
||||
.first?.windows
|
||||
.filter({$0.isKeyWindow}).first
|
||||
|
||||
keyWindow?.rootViewController?.present(av, animated: true, completion: nil)
|
||||
} catch {
|
||||
print( "ERROR - \(error)" )
|
||||
}
|
||||
}
|
||||
|
||||
func dgToText( _ dg : DataGroupId ) -> String {
|
||||
switch ( dg ) {
|
||||
case .SOD:
|
||||
return "SOD - Document Security Object"
|
||||
case .COM:
|
||||
return "COM - Header and DG Presence"
|
||||
case .DG1:
|
||||
return "DG1* - MRZ Info"
|
||||
case .DG2:
|
||||
return "DG2* - Face image"
|
||||
case .DG3:
|
||||
return "DG3* - Fingerprints"
|
||||
case .DG4:
|
||||
return "DG4* - Iris"
|
||||
case .DG5:
|
||||
return "DG5* - Displayed portrait"
|
||||
case .DG6:
|
||||
return "DG6 - Reserved"
|
||||
case .DG7:
|
||||
return "DG7* - Signature"
|
||||
case .DG8:
|
||||
return "DG8* - Data features"
|
||||
case .DG9:
|
||||
return "DG9* - Structure features"
|
||||
case .DG10:
|
||||
return "DG10* - Substance features"
|
||||
case .DG11:
|
||||
return "DG11* - Additional personal info"
|
||||
case .DG12:
|
||||
return "DG12* - Additional document info"
|
||||
case .DG13:
|
||||
return "DG13* - Optional details"
|
||||
case .DG14:
|
||||
return "DG14 - Security options"
|
||||
case .DG15:
|
||||
return "DG15 - Active Auth PubKey"
|
||||
case .DG16:
|
||||
return "DG16 - Person(s) to notify"
|
||||
default:
|
||||
return "Unknown"
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
struct ExportPassportView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
let settings = SettingsStore()
|
||||
settings.passport = NFCPassportModel()
|
||||
|
||||
return NavigationView {
|
||||
ExportPassportView()
|
||||
}
|
||||
.environmentObject(settings)
|
||||
}
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
//
|
||||
// CheckBoxView.swift
|
||||
// NFCPassportReaderApp
|
||||
//
|
||||
// Created by Andy Qua on 10/02/2021.
|
||||
// Copyright © 2021 Andy Qua. All rights reserved.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct CheckBoxButtonStyle: ButtonStyle {
|
||||
|
||||
func makeBody(configuration: Self.Configuration) -> some View {
|
||||
configuration.label
|
||||
.foregroundColor(.secondary)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
struct CheckBoxView: View {
|
||||
@Binding var checked: Bool
|
||||
var text : String
|
||||
|
||||
var body: some View {
|
||||
HStack() {
|
||||
|
||||
Button(action: {
|
||||
withAnimation {
|
||||
self.checked.toggle()
|
||||
}
|
||||
}) {
|
||||
HStack(alignment: .center, spacing: 10) {
|
||||
Text(text)
|
||||
Image(systemName:self.checked ? "checkmark.square.fill" : "square")
|
||||
}
|
||||
}
|
||||
.frame(height: 44, alignment: .center)
|
||||
.padding(.trailing)
|
||||
.buttonStyle(CheckBoxButtonStyle())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct CheckBoxView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
CheckBoxView( checked: .constant(true), text:"Are you on?")
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
//
|
||||
// ViewExt.swift
|
||||
// NFCPassportReaderApp
|
||||
//
|
||||
// Created by Andy Qua on 11/02/2021.
|
||||
// Copyright © 2021 Andy Qua. All rights reserved.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
import UIKit
|
||||
|
||||
extension View {
|
||||
func hideKeyboard() {
|
||||
UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
|
||||
}
|
||||
|
||||
func visibility(hidden: Binding<Bool>) -> some View {
|
||||
modifier(VisibilityStyle(hidden: hidden))
|
||||
}
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
//
|
||||
// ViewModifiers.swift
|
||||
// NFCPassportReaderApp
|
||||
//
|
||||
// Created by Andy Qua on 10/02/2021.
|
||||
// Copyright © 2021 Andy Qua. All rights reserved.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct ClearButton: ViewModifier {
|
||||
@Binding var text: String
|
||||
|
||||
public func body(content: Content) -> some View {
|
||||
HStack {
|
||||
content
|
||||
if !text.isEmpty {
|
||||
Button(action: { self.text = "" },
|
||||
label: {
|
||||
Image(systemName: "delete.left")
|
||||
.foregroundColor(Color(UIColor.opaqueSeparator))
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct VisibilityStyle: ViewModifier {
|
||||
|
||||
@Binding var hidden: Bool
|
||||
func body(content: Content) -> some View {
|
||||
Group {
|
||||
if hidden {
|
||||
content.hidden()
|
||||
} else {
|
||||
content
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,125 +0,0 @@
|
||||
//
|
||||
// MRZEntryView.swift
|
||||
// NFCPassportReaderApp
|
||||
//
|
||||
// Created by Andy Qua on 10/02/2021.
|
||||
// Copyright © 2021 Andy Qua. All rights reserved.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
// This will be removed once DatePicker inline works correctly
|
||||
struct DateView : View {
|
||||
@Binding var date : Date
|
||||
var title : String
|
||||
|
||||
var body : some View {
|
||||
VStack {
|
||||
Text(title)
|
||||
.font(.largeTitle)
|
||||
Spacer()
|
||||
DatePicker("Date of birth", selection:$date, displayedComponents: .date)
|
||||
.environment(\.timeZone, TimeZone(secondsFromGMT: 0)!)
|
||||
.datePickerStyle(WheelDatePickerStyle())
|
||||
.labelsHidden()
|
||||
Spacer()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This should be a nice simple inline DatePicker here
|
||||
// BUT there are bugs when you select dates it changes the date format
|
||||
// from DD MMM YYYY to DD/MM/YYYY!)
|
||||
// Will update when/if this gets fixed!
|
||||
struct MRZEntryView : View {
|
||||
@EnvironmentObject var settings: SettingsStore
|
||||
|
||||
// These will be removed once DatePicker inline works correctly
|
||||
@State private var editDOB = false
|
||||
@State private var editDOE = false
|
||||
@State private var editDateTitle : String = ""
|
||||
|
||||
var body : some View {
|
||||
let passportNrBinding = Binding<String>(get: {
|
||||
settings.passportNumber
|
||||
}, set: {
|
||||
settings.passportNumber = $0.uppercased()
|
||||
})
|
||||
VStack {
|
||||
NavigationLink( destination: DateView(date:$settings.dateOfBirth, title:editDateTitle), isActive: $editDOB) { Text("") }
|
||||
NavigationLink( destination: DateView(date:$settings.dateOfExpiry, title:editDateTitle), isActive: $editDOE) { Text("") }
|
||||
|
||||
TextField("Passport number", text: passportNrBinding)
|
||||
.textCase(.uppercase)
|
||||
.modifier(ClearButton(text: passportNrBinding))
|
||||
.textContentType(.name)
|
||||
.foregroundColor(Color.primary)
|
||||
.padding([.leading, .trailing])
|
||||
.ignoresSafeArea(.keyboard, edges: .all)
|
||||
|
||||
Divider()
|
||||
|
||||
// Replace with DatePicker once it works correctly
|
||||
HStack {
|
||||
VStack {
|
||||
Text( "Date of birth" )
|
||||
Button(formatDate(settings.dateOfBirth)) {
|
||||
editDateTitle = "Select date of birth"
|
||||
editDOB = true
|
||||
}
|
||||
.padding(.horizontal, 15)
|
||||
.padding(.vertical, 8)
|
||||
.background(Color.black.opacity(0.07))
|
||||
.cornerRadius(8)
|
||||
}
|
||||
Spacer()
|
||||
VStack {
|
||||
Text( "Passport expiry date" )
|
||||
Button(formatDate(settings.dateOfExpiry)) {
|
||||
editDateTitle = "Select passport expiry date"
|
||||
editDOE = true
|
||||
}
|
||||
.padding(.horizontal, 15)
|
||||
.padding(.vertical, 8)
|
||||
.background(Color.black.opacity(0.07))
|
||||
.cornerRadius(8)
|
||||
}
|
||||
}
|
||||
.padding([.leading, .trailing])
|
||||
|
||||
Divider()
|
||||
}
|
||||
.ignoresSafeArea(.keyboard, edges: .bottom)
|
||||
}
|
||||
}
|
||||
|
||||
// This will be removed once DatePicker inline works correctly
|
||||
extension MRZEntryView {
|
||||
|
||||
func formatDate( _ date : Date ) -> String {
|
||||
let df = DateFormatter()
|
||||
df.timeZone = TimeZone.init(secondsFromGMT: 0)
|
||||
df.dateFormat = "dd MMM yyyy"
|
||||
let dateStr = df.string(from:date)
|
||||
return dateStr
|
||||
}
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
struct MRZEntryView_Previews : PreviewProvider {
|
||||
|
||||
static var previews: some View {
|
||||
let settings = SettingsStore()
|
||||
|
||||
return
|
||||
Group {
|
||||
NavigationView {
|
||||
MRZEntryView()
|
||||
}
|
||||
.environmentObject(settings)
|
||||
.environment( \.colorScheme, .light)
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1,90 +0,0 @@
|
||||
//
|
||||
// MRZScannerViewController.swift
|
||||
// NFCPassportReaderApp
|
||||
//
|
||||
// Created by Andy Qua on 17/02/2021.
|
||||
// Copyright © 2021 Andy Qua. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import SwiftUI
|
||||
import QKMRZScanner
|
||||
|
||||
// Wraps the QKMRZScanner component in a simple UIView that allows a scan of the MRZ area from a Passport/ID Card
|
||||
struct MRZScanner: UIViewControllerRepresentable {
|
||||
let completionHandler: (String,Date,Date) -> Void
|
||||
|
||||
func makeUIViewController(context: Context) -> MRZScannerViewController {
|
||||
let vc = MRZScannerViewController()
|
||||
vc.mrzScannerView.delegate = context.coordinator
|
||||
return vc
|
||||
}
|
||||
|
||||
func updateUIViewController(_ uiViewController: MRZScannerViewController, context: Context) {
|
||||
|
||||
}
|
||||
|
||||
func makeCoordinator() -> Coordinator {
|
||||
return Coordinator(completionHandler: completionHandler)
|
||||
}
|
||||
|
||||
final class Coordinator: NSObject, QKMRZScannerViewDelegate {
|
||||
let completionHandler: (String,Date,Date) -> Void
|
||||
|
||||
init(completionHandler: @escaping (String,Date,Date) -> Void) {
|
||||
self.completionHandler = completionHandler
|
||||
}
|
||||
|
||||
func mrzScannerView(_ mrzScannerView: QKMRZScannerView, didFind scanResult: QKMRZScanResult) {
|
||||
print(scanResult)
|
||||
if let dob = scanResult.birthdate, let doe = scanResult.expiryDate {
|
||||
completionHandler(scanResult.documentNumber, dob, doe)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: UIViewController implementation
|
||||
class MRZScannerViewController: UIViewController {
|
||||
let mrzScannerView = QKMRZScannerView()
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
self.title = "Scan Passport"
|
||||
self.navigationController?.title = "Scan passport"
|
||||
|
||||
|
||||
let lbl = UILabel()
|
||||
lbl.text = "Please scan the Machine Readable Zone."
|
||||
lbl.numberOfLines = 0
|
||||
self.view.addSubview(mrzScannerView)
|
||||
self.view.addSubview(lbl)
|
||||
|
||||
mrzScannerView.translatesAutoresizingMaskIntoConstraints = false
|
||||
mrzScannerView.topAnchor.constraint(equalTo: view.topAnchor, constant:50).isActive = true
|
||||
mrzScannerView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
|
||||
mrzScannerView.widthAnchor.constraint(equalToConstant: view.bounds.width).isActive = true
|
||||
mrzScannerView.heightAnchor.constraint(equalToConstant: view.bounds.width).isActive = true
|
||||
|
||||
lbl.translatesAutoresizingMaskIntoConstraints = false
|
||||
lbl.leadingAnchor.constraint(equalTo: mrzScannerView.leadingAnchor, constant: 10).isActive = true
|
||||
lbl.topAnchor.constraint(equalTo: mrzScannerView.bottomAnchor, constant: 10).isActive = true
|
||||
lbl.trailingAnchor.constraint(equalTo: mrzScannerView.trailingAnchor, constant: 10).isActive = true
|
||||
}
|
||||
override func viewWillAppear(_ animated: Bool) {
|
||||
super.viewWillAppear(animated)
|
||||
mrzScannerView.startScanning()
|
||||
}
|
||||
|
||||
override func viewWillDisappear(_ animated: Bool) {
|
||||
super.viewWillDisappear(animated)
|
||||
mrzScannerView.stopScanning()
|
||||
}
|
||||
}
|
||||
|
||||
extension MRZScannerViewController : QKMRZScannerViewDelegate {
|
||||
func mrzScannerView(_ mrzScannerView: QKMRZScannerView, didFind scanResult: QKMRZScanResult) {
|
||||
print(scanResult)
|
||||
}
|
||||
}
|
||||
|
||||