@@ -52,13 +52,19 @@ struct CertificatePicker: View {
5252 . textContentType ( . password)
5353 . autocorrectionDisabled ( )
5454 . textInputAutocapitalization ( . never)
55+ . submitLabel ( . done)
56+ . onSubmit {
57+ if let url = pickedURL {
58+ model. handleCertificate ( fileUrl: url, urlBase: urlBase, password: password)
59+ }
60+ }
5561 }
5662 }
5763 }
5864 . onAppear {
5965 model. delegate = delegate
6066 }
61- . navigationTitle ( " _cert_navigation_title_ " )
67+ . navigationTitle ( NSLocalizedString ( " _cert_navigation_title_ " , comment : " " ) )
6268 . navigationBarTitleDisplayMode ( . inline)
6369 . toolbar {
6470 ToolbarItem ( placement: . cancellationAction) {
@@ -76,6 +82,7 @@ struct CertificatePicker: View {
7682 } label: {
7783 Image ( systemName: " checkmark " )
7884 }
85+ . keyboardShortcut ( . defaultAction)
7986 . disabled ( pickedURL == nil || password. isEmpty)
8087 . tint ( Color ( NCBrandColor . shared. customer) )
8188 }
@@ -88,81 +95,14 @@ struct CertificatePicker: View {
8895 }
8996 }
9097 }
91- . alert ( " _client_cert_wrong_password_ " , isPresented: $model. isWrongPassword) { }
92- }
93- }
94- }
95-
96- protocol CertificatePickerDelegate : AnyObject {
97- func certificatePickerDidImportIdentity( _ picker: CertificatePickerModel , for urlBase: String )
98- }
99-
100- @Observable class CertificatePickerModel : NSObject , UIDocumentPickerDelegate {
101- var isWrongPassword = false
102- @ObservationIgnored weak var delegate : CertificatePickerDelegate ?
103-
104- func handleCertificate( fileUrl: URL , urlBase: String , password: String ) {
105- if fileUrl. startAccessingSecurityScopedResource ( ) {
106- defer {
107- fileUrl. stopAccessingSecurityScopedResource ( )
108- }
109-
110- if let identity = getIdentityFromP12 ( from: fileUrl, password: password) {
111- let urlWithoutScheme = urlBase. replacingOccurrences ( of: " https:// " , with: " " ) . replacingOccurrences ( of: " http:// " , with: " " )
112- let label = " client_identity_ \( urlWithoutScheme) "
113- storeIdentityInKeychain ( identity: identity, label: label)
114- delegate? . certificatePickerDidImportIdentity ( self , for: urlBase)
115- } else {
116- isWrongPassword = true
98+ . alert ( NSLocalizedString ( " _client_cert_wrong_password_ " , comment: " " ) , isPresented: $model. isWrongPassword) { }
99+ . onChange ( of: model. isCertImportedSuccessfully) { _, newValue in
100+ if newValue { dismiss ( ) }
117101 }
118102 }
119103 }
120-
121- func getIdentityFromP12( from url: URL , password: String ) -> SecIdentity ? {
122- guard let p12Data = try ? Data ( contentsOf: url) else { return nil }
123-
124- let options = [ kSecImportExportPassphrase as String : password]
125- var items : CFArray ?
126- let status = SecPKCS12Import ( p12Data as CFData , options as CFDictionary , & items)
127-
128- if status == errSecSuccess,
129- let array = items as? [ [ String : Any ] ] {
130- // swiftlint:disable force_cast
131- if let identity = array. first ? [ kSecImportItemIdentity as String ] as! SecIdentity ? {
132- // swiftlint:enable force_cast
133- return identity
134- }
135- }
136- return nil
137- }
138-
139- func storeIdentityInKeychain( identity: SecIdentity , label: String ) {
140- let addQuery : [ String : Any ] = [
141- kSecValueRef as String : identity,
142- kSecClass as String : kSecClassIdentity,
143- kSecAttrLabel as String : label,
144- kSecAttrAccessible as String : kSecAttrAccessibleAfterFirstUnlock
145- ]
146-
147- let classes = [ kSecClassIdentity, kSecClassCertificate, kSecClassKey]
148- for secClass in classes {
149- let deleteQuery : [ String : Any ] = [
150- kSecClass as String : secClass,
151- kSecAttrLabel as String : label,
152- kSecAttrAccessible as String : kSecAttrAccessibleAfterFirstUnlock
153- ]
154- let status = SecItemDelete ( deleteQuery as CFDictionary )
155- print ( " Deleting \( secClass) : \( status) " )
156- }
157-
158- let addStatus = SecItemAdd ( addQuery as CFDictionary , nil )
159- print ( " Add status: \( addStatus) " )
160-
161- }
162-
163104}
164105
165106#Preview {
166107 CertificatePicker ( urlBase: " test.com " )
167108}
168-
0 commit comments