Skip to content
This repository was archived by the owner on Mar 7, 2026. It is now read-only.

Commit 1f84957

Browse files
authored
Fix swift 6 compile errors
1 parent 4611197 commit 1f84957

3 files changed

Lines changed: 97 additions & 189 deletions

File tree

Sources/prostore/certificates/CertificatesManager.swift

Lines changed: 59 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -20,32 +20,33 @@ public enum CertificateError: Error {
2020
case unknown
2121
}
2222

23-
/// CertificatesManager handles cert extraction/checking and exposes the currently selected identity.
24-
/// Replace `SecIdentity` with your own wrapper type if you use a custom model.
2523
public final class CertificatesManager: ObservableObject {
2624
public static let shared = CertificatesManager()
2725
private init() {}
2826

29-
// REMOVED: @Published public var selectedCertificate: SecIdentity? = nil
30-
3127
/// Returns the currently selected SecIdentity by loading from the selected folder in UserDefaults
3228
public var selectedIdentity: SecIdentity? {
3329
guard let folderName = UserDefaults.standard.string(forKey: "selectedCertificateFolder"),
3430
!folderName.isEmpty else {
3531
return nil
3632
}
3733

38-
let certDir = CertificateFileManager.shared.certificatesDirectory.appendingPathComponent(folderName)
34+
let certDir = CertificateFileManager.shared.certificatesDirectory
35+
.appendingPathComponent(folderName)
36+
3937
let p12URL = certDir.appendingPathComponent("certificate.p12")
40-
let pwURL = certDir.appendingPathComponent("password.txt")
38+
let pwURL = certDir.appendingPathComponent("password.txt")
4139

4240
guard let p12Data = try? Data(contentsOf: p12URL),
43-
let password = try? String(contentsOf: pwURL, encoding: .utf8)?.trimmingCharacters(in: .whitespacesAndNewlines) else {
41+
let passwordRaw = try? String(contentsOf: pwURL, encoding: .utf8) else {
4442
return nil
4543
}
4644

45+
let password = passwordRaw.trimmingCharacters(in: .whitespacesAndNewlines)
46+
4747
var items: CFArray?
4848
let options = [kSecImportExportPassphrase as String: password] as CFDictionary
49+
4950
let status = SecPKCS12Import(p12Data as CFData, options, &items)
5051

5152
guard status == errSecSuccess,
@@ -55,35 +56,29 @@ public final class CertificatesManager: ObservableObject {
5556
return nil
5657
}
5758

58-
return identityAny as! SecIdentity
59+
return identityAny as? SecIdentity
5960
}
6061

61-
// MARK: - Utility: SHA256 hex
62+
// MARK: - SHA256 hex
6263
public static func sha256Hex(_ d: Data) -> String {
6364
let digest = SHA256.hash(data: d)
6465
return digest.map { String(format: "%02x", $0) }.joined()
6566
}
6667

67-
// MARK: - Export public key bytes for a SecCertificate
68+
// MARK: - Public key data
6869
private static func publicKeyData(from cert: SecCertificate) throws -> Data {
6970
guard let secKey = SecCertificateCopyKey(cert) else {
7071
throw CertificateError.certExtractionFailed
7172
}
72-
73-
var cfErr: Unmanaged<CFError>?
74-
guard let keyData = SecKeyCopyExternalRepresentation(secKey, &cfErr) as Data? else {
75-
if let cfError = cfErr?.takeRetainedValue() {
76-
let code = CFErrorGetCode(cfError)
77-
throw CertificateError.publicKeyExportFailed(OSStatus(code))
78-
} else {
79-
throw CertificateError.publicKeyExportFailed(-1)
80-
}
73+
var error: Unmanaged<CFError>?
74+
guard let data = SecKeyCopyExternalRepresentation(secKey, &error) as Data? else {
75+
let code = error?.takeRetainedValue().map { CFErrorGetCode($0) as OSStatus } ?? -1
76+
throw CertificateError.publicKeyExportFailed(code)
8177
}
82-
83-
return keyData
78+
return data
8479
}
8580

86-
// MARK: - Extract certificates array from mobileprovision (PKCS7) blob
81+
// MARK: - Extract certs from mobileprovision
8782
private static func certificatesFromMobileProvision(_ data: Data) throws -> [SecCertificate] {
8883
let startTag = Data("<plist".utf8)
8984
let endTag = Data("</plist>".utf8)
@@ -96,122 +91,79 @@ public final class CertificatesManager: ObservableObject {
9691
let plistData = data[startRange.lowerBound..<endRange.upperBound]
9792
let parsed = try PropertyListSerialization.propertyList(from: Data(plistData), options: [], format: nil)
9893

99-
guard let dict = parsed as? [String: Any] else {
100-
throw CertificateError.plistExtractionFailed
94+
guard let dict = parsed as? [String: Any],
95+
let devArray = dict["DeveloperCertificates"] as? [Any] else {
96+
throw CertificateError.noCertsInProvision
10197
}
10298

103-
var resultCerts: [SecCertificate] = []
104-
if let devArray = dict["DeveloperCertificates"] as? [Any] {
105-
for item in devArray {
106-
if let certData = item as? Data {
107-
if let secCert = SecCertificateCreateWithData(nil, certData as CFData) {
108-
resultCerts.append(secCert)
109-
}
110-
} else if let base64String = item as? String,
111-
let certData = Data(base64Encoded: base64String) {
112-
if let secCert = SecCertificateCreateWithData(nil, certData as CFData) {
113-
resultCerts.append(secCert)
114-
}
115-
}
99+
var result: [SecCertificate] = []
100+
for item in devArray {
101+
if let certData = item as? Data,
102+
let cert = SecCertificateCreateWithData(nil, certData as CFData) {
103+
result.append(cert)
104+
} else if let base64 = item as? String,
105+
let certData = Data(base64Encoded: base64),
106+
let cert = SecCertificateCreateWithData(nil, certData as CFData) {
107+
result.append(cert)
116108
}
117109
}
118110

119-
if resultCerts.isEmpty {
120-
throw CertificateError.noCertsInProvision
121-
}
122-
123-
return resultCerts
111+
guard !result.isEmpty else { throw CertificateError.noCertsInProvision }
112+
return result
124113
}
125114

126-
// MARK: - Readable display name from mobileprovision
115+
// MARK: - Display name from provision
127116
public func getCertificateName(mobileProvisionData: Data) -> String? {
128-
// Extract the <plist>...</plist> block
129117
let startTag = Data("<plist".utf8)
130118
let endTag = Data("</plist>".utf8)
131119
guard let startRange = mobileProvisionData.range(of: startTag),
132-
let endRange = mobileProvisionData.range(of: endTag) else {
133-
return nil
134-
}
135-
136-
let plistDataSlice = mobileProvisionData[startRange.lowerBound..<endRange.upperBound]
137-
let plistData = Data(plistDataSlice)
120+
let endRange = mobileProvisionData.range(of: endTag) else { return nil }
138121

139-
guard let parsed = try? PropertyListSerialization.propertyList(from: plistData, options: [], format: nil),
140-
let dict = parsed as? [String: Any] else {
141-
return nil
142-
}
122+
let plistData = mobileProvisionData[startRange.lowerBound..<endRange.upperBound]
123+
guard let parsed = try? PropertyListSerialization.propertyList(from: Data(plistData), options: [], format: nil),
124+
let dict = parsed as? [String: Any] else { return nil }
143125

144-
if let teamName = dict["TeamName"] as? String, !teamName.isEmpty {
145-
return teamName
146-
}
147-
if let name = dict["Name"] as? String, !name.isEmpty {
148-
return name
149-
}
150-
return nil
126+
return (dict["TeamName"] as? String) ?? (dict["Name"] as? String)
151127
}
152128

153-
// MARK: - Top-level check: verify p12 matches one of the embedded certs in mobileprovision
154-
/// Returns .success(.success) if match, .success(.noMatch) if no match, or .failure(Error)
129+
// MARK: - Check p12 ↔ mobileprovision match
155130
public static func check(p12Data: Data, password: String, mobileProvisionData: Data) -> Result<CertificateCheckResult, Error> {
156131
let options = [kSecImportExportPassphrase as String: password] as CFDictionary
157-
var itemsCF: CFArray?
158-
159-
let importStatus = SecPKCS12Import(p12Data as CFData, options, &itemsCF)
160-
161-
if importStatus == errSecAuthFailed {
162-
return .success(.incorrectPassword)
163-
}
132+
var items: CFArray?
164133

165-
guard importStatus == errSecSuccess, let items = itemsCF as? [[String: Any]], items.count > 0 else {
166-
return .failure(CertificateError.p12ImportFailed(importStatus))
167-
}
134+
let status = SecPKCS12Import(p12Data as CFData, options, &items)
168135

169-
guard let first = items.first else {
170-
return .failure(CertificateError.identityExtractionFailed)
171-
}
136+
if status == errSecAuthFailed { return .success(.incorrectPassword) }
172137

173-
// kSecImportItemIdentity should be present
174-
guard let identityAny = first[kSecImportItemIdentity as String] else {
175-
return .failure(CertificateError.identityExtractionFailed)
138+
guard status == errSecSuccess,
139+
let itemsArray = items as? [[String: Any]],
140+
let identityAny = itemsArray.first?[kSecImportItemIdentity as String],
141+
CFGetTypeID(identityAny as CFTypeRef) == SecIdentityGetTypeID(),
142+
let identity = identityAny as? SecIdentity else {
143+
return .failure(CertificateError.p12ImportFailed(status))
176144
}
177145

178-
// Verify CFTypeID is SecIdentity, then force-cast
179-
guard CFGetTypeID(identityAny as CFTypeRef) == SecIdentityGetTypeID() else {
180-
return .failure(CertificateError.identityExtractionFailed)
181-
}
182-
let identity = identityAny as! SecIdentity
183-
184146
var certRef: SecCertificate?
185-
let certStatus = SecIdentityCopyCertificate(identity, &certRef)
186-
187-
guard certStatus == errSecSuccess, let p12Cert = certRef else {
147+
guard SecIdentityCopyCertificate(identity, &certRef) == errSecSuccess,
148+
let p12Cert = certRef else {
188149
return .failure(CertificateError.certExtractionFailed)
189150
}
190151

191152
do {
192-
let p12PubKeyData = try publicKeyData(from: p12Cert)
193-
let p12Hash = sha256Hex(p12PubKeyData)
194-
195-
let embeddedCerts = try certificatesFromMobileProvision(mobileProvisionData)
196-
197-
for cert in embeddedCerts {
198-
do {
199-
let embPubKeyData = try publicKeyData(from: cert)
200-
let embHash = sha256Hex(embPubKeyData)
201-
202-
if embHash == p12Hash {
203-
return .success(.success)
204-
}
205-
} catch {
206-
// continue checking other embedded certs
207-
continue
153+
let p12KeyData = try publicKeyData(from: p12Cert)
154+
let p12Hash = sha256Hex(p12KeyData)
155+
156+
let embedded = try certificatesFromMobileProvision(mobileProvisionData)
157+
158+
for cert in embedded {
159+
let keyData = try publicKeyData(from: cert)
160+
if sha256Hex(keyData) == p12Hash {
161+
return .success(.success)
208162
}
209163
}
210-
211164
return .success(.noMatch)
212165
} catch {
213166
return .failure(error)
214167
}
215168
}
216-
}
217-
169+
}

Sources/prostore/signing/DownloadSignManager.swift

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,14 @@
22
import Foundation
33
import Combine
44

5-
class DownloadSignManager: ObservableObject {
5+
final class DownloadSignManager: ObservableObject, @unchecked Sendable {
6+
@Published var isProcessing = false
67
@Published var progress: Double = 0.0
78
@Published var status: String = ""
8-
@Published var isProcessing: Bool = false
9-
@Published var showSuccess: Bool = false
10-
11-
private var downloadTask: URLSessionDownloadTask?
9+
@Published var showSuccess = false
10+
1211
private var cancellables = Set<AnyCancellable>()
13-
12+
1413
func downloadAndSign(app: AltApp) {
1514
guard let downloadURL = app.downloadURL else {
1615
self.status = "No download URL available"

0 commit comments

Comments
 (0)