Skip to content

Commit d6970fb

Browse files
author
SideInstaller
committed
Fixed urgent bug with translations
1 parent 3a0c4bc commit d6970fb

2 files changed

Lines changed: 27 additions & 5 deletions

File tree

ios-app/CertManager.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ final class CertManager: ObservableObject {
9292
@MainActor
9393
func loadCerts() {
9494
guard !isWorking, revokingID == nil else { return }
95-
let id = engine.appleID, pw = engine.applePassword
95+
let id = engine.normalizedAppleID, pw = engine.applePassword
9696
guard !id.isEmpty, !pw.isEmpty else {
9797
lastError = L("Enter your Apple ID email and password first.")
9898
return

ios-app/Engine.swift

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -367,7 +367,7 @@ final class Engine: ObservableObject {
367367
log("⛔️ iOS \(osVersionText) isn't supported — SideInstaller needs iOS \(Engine.minimumOSText) or later.")
368368
return
369369
}
370-
guard !appleID.isEmpty, !applePassword.isEmpty else {
370+
guard !normalizedAppleID.isEmpty, !applePassword.isEmpty else {
371371
log("Enter your Apple ID email + password first.")
372372
return
373373
}
@@ -558,14 +558,23 @@ final class Engine: ObservableObject {
558558

559559
// MARK: Step 4 — Apple ID sign-in
560560

561+
/// The Apple ID as it should be sent to Apple. iOS keyboards happily leave a
562+
/// trailing space behind autocomplete or a paste, and the field gives no
563+
/// visual hint that it's there — but the username is mixed into the SRP
564+
/// proof, so that invisible space comes back as a wrong-password error.
565+
/// (The password is deliberately *not* trimmed: spaces can be part of it.)
566+
var normalizedAppleID: String {
567+
appleID.trimmingCharacters(in: .whitespacesAndNewlines)
568+
}
569+
561570
@MainActor
562571
private func signIn() async throws {
563572
if signSession != nil {
564573
log("Already signed in this session — skipping.")
565574
setStep(.signIn, .done)
566575
return
567576
}
568-
guard !appleID.isEmpty, !applePassword.isEmpty else {
577+
guard !normalizedAppleID.isEmpty, !applePassword.isEmpty else {
569578
throw EngineError.message(L("Enter your Apple ID email + password."))
570579
}
571580
setStep(.signIn, .active)
@@ -576,7 +585,7 @@ final class Engine: ObservableObject {
576585
// could fix, like a wrong password or a cancelled 2FA prompt, stop the
577586
// loop early — see below.)
578587
let servers = anisetteCandidates()
579-
let id = appleID, pw = applePassword, dir = storageDir
588+
let id = normalizedAppleID, pw = applePassword, dir = storageDir
580589
twoFactorWasCancelled = false
581590
var lastError = "no anisette servers configured"
582591

@@ -670,15 +679,28 @@ final class Engine: ObservableObject {
670679
anisetteServers.first { $0.address == address }?.name ?? address
671680
}
672681

682+
/// GrandSlam status codes that mean the credentials themselves are the
683+
/// problem. Apple localises the accompanying message, so the numeric code is
684+
/// the only reliable signal — match on it first and treat the wording as a
685+
/// fallback for servers that don't echo the code.
686+
private static let credentialErrorCodes = [
687+
"-20101", // invalid username/password
688+
"-22406", // "Enter the correct password for this Apple Account."
689+
]
690+
673691
/// Detect a definitive Apple ID credential failure (vs. a flaky anisette
674692
/// server). Switching anisette servers can't fix these, so the sign-in loop
675693
/// stops on them instead of trying every server.
676694
static func isCredentialError(_ raw: String) -> Bool {
677695
let m = raw.lowercased()
696+
if credentialErrorCodes.contains(where: m.contains) { return true }
697+
// Wording fallbacks. Apple now brands the account an "Apple Account"
698+
// rather than an "Apple ID", so both spellings have to be covered.
678699
return m.contains("apple id or password")
700+
|| m.contains("apple account or password")
679701
|| m.contains("password was incorrect")
680702
|| m.contains("incorrect apple id")
681-
|| m.contains("-20101") // GSA: invalid username/password
703+
|| m.contains("correct password")
682704
|| (m.contains("password") && m.contains("incorrect"))
683705
}
684706

0 commit comments

Comments
 (0)