Files
xtool-mirror/Sources/XKit/Installation/ProfileManager.swift
2025-05-06 11:30:59 +05:30

71 lines
2.6 KiB
Swift

//
// ProfileManager.swift
// XKit
//
// Created by Kabir Oberai on 25/03/21.
// Copyright © 2021 Kabir Oberai. All rights reserved.
//
import Foundation
import SwiftyMobileDevice
public final class ProfileManager {
private let client: MISAgentClient
private let version: String
private lazy var ge9_3: Bool = {
let components = version.split(separator: ".")
guard !components.isEmpty, let major = Int(components[0]) else { return false }
if major > 9 {
return true
} else if major < 9 {
return false
}
guard components.count >= 2, let minor = Int(components[1]) else { return false }
return minor >= 3
}()
public init(connection: Connection) async throws {
self.client = try await connection.startClient()
self.version = try connection.client.value(ofType: String.self, forDomain: nil, key: "ProductVersion")
}
private func allProfiles() throws -> [Mobileprovision] {
try (ge9_3 ? client.profiles() : client.profilesLegacy())
.map(Mobileprovision.init(data:))
}
private func parse(profiles: [Mobileprovision]) throws -> [String: [(Mobileprovision, Mobileprovision.Digest)]] {
let pairs = try profiles.compactMap { (p: Mobileprovision) -> (String, (Mobileprovision, Mobileprovision.Digest))? in
let d = try p.digest()
let ents = try d.entitlements.entitlements()
guard let appID = ents.lazy.compactMap({ $0 as? ApplicationIdentifierEntitlement }).first
else { return nil }
return (appID.rawValue, (p, d))
}
return Dictionary(grouping: pairs) { $0.0 }.mapValues { $0.map { $0.1 } }
}
public func install(profiles: [Mobileprovision]) throws {
let toInstall = try parse(profiles: profiles)
let installed = try parse(profiles: allProfiles())
for (bundleID, profiles) in toInstall {
guard profiles.count == 1 else {
print("Unexpected # of profiles for \(bundleID): \(profiles.count). Skipping.")
continue
}
let profile = profiles[0]
let installedProfiles = installed[bundleID] ?? []
for installedProfile in installedProfiles {
print("Removing \(installedProfile.1.uuid) for \(bundleID)")
try client.removeProfile(withUUID: installedProfile.1.uuid)
}
print("Installing profile with UUID \(profile.1.uuid)")
try client.install(profile: profile.0.data())
}
}
}