mirror of
https://github.com/xtool-org/xtool.git
synced 2026-02-04 11:53:30 +01:00
71 lines
2.6 KiB
Swift
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())
|
|
}
|
|
}
|
|
|
|
}
|