From 3682b65a4a2f2fa5103b65d632b540bf60a82b33 Mon Sep 17 00:00:00 2001 From: Magesh K <47920326+mahee96@users.noreply.github.com> Date: Sun, 10 Nov 2024 02:54:18 +0530 Subject: [PATCH] restore changes dropped from altstore by 1713fcc --- AltServer/ErrorDetailsViewController.swift | 48 +++++++++++++++++++ AltStore.xcodeproj/project.pbxproj | 2 + AltStore/Managing Apps/AppManager.swift | 38 ++++++++++++++- .../Operations/DownloadAppOperation.swift | 4 +- .../FetchProvisioningProfilesOperation.swift | 4 ++ AltStore/Operations/OperationError.swift | 1 + AltStore/Operations/VerifyAppOperation.swift | 2 + .../Error Log/ErrorLogViewController.swift | 4 +- AltStore/Settings/PatreonViewController.swift | 2 +- AltStoreCore/Model/StoreApp.swift | 25 ++++++++++ AltStoreCore/Patreon/PatreonAPI.swift | 45 ++++++++--------- Shared/Extensions/NSError+AltStore.swift | 2 + 12 files changed, 150 insertions(+), 27 deletions(-) create mode 100644 AltServer/ErrorDetailsViewController.swift diff --git a/AltServer/ErrorDetailsViewController.swift b/AltServer/ErrorDetailsViewController.swift new file mode 100644 index 00000000..6f9fd1c7 --- /dev/null +++ b/AltServer/ErrorDetailsViewController.swift @@ -0,0 +1,48 @@ +// +// ErrorDetailsViewController.swift +// AltServer +// +// Created by Riley Testut on 10/4/22. +// Copyright © 2022 Riley Testut. All rights reserved. +// + +import AppKit + +class ErrorDetailsViewController: NSViewController +{ + var error: NSError? { + didSet { + self.update() + } + } + + @IBOutlet private var errorCodeLabel: NSTextField! + @IBOutlet private var detailedDescriptionLabel: NSTextField! + + override func viewDidLoad() + { + super.viewDidLoad() + + self.detailedDescriptionLabel.preferredMaxLayoutWidth = 800 + } +} + +private extension ErrorDetailsViewController +{ + func update() + { + if !self.isViewLoaded + { + self.loadView() + } + + guard let error = self.error else { return } + + self.errorCodeLabel.stringValue = error.localizedErrorCode + + let font = self.detailedDescriptionLabel.font ?? NSFont.systemFont(ofSize: 12) + let detailedDescription = error.formattedDetailedDescription(with: font) + self.detailedDescriptionLabel.attributedStringValue = detailedDescription + } +} + diff --git a/AltStore.xcodeproj/project.pbxproj b/AltStore.xcodeproj/project.pbxproj index fe52cefb..725acbe2 100644 --- a/AltStore.xcodeproj/project.pbxproj +++ b/AltStore.xcodeproj/project.pbxproj @@ -847,6 +847,7 @@ D533E8B82727B61400A9B5DD /* fragmentzip.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = fragmentzip.h; sourceTree = ""; }; D533E8BB2727BBEE00A9B5DD /* libfragmentzip.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libfragmentzip.a; path = Dependencies/fragmentzip/libfragmentzip.a; sourceTree = SOURCE_ROOT; }; D533E8BD2727BBF800A9B5DD /* libcurl.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libcurl.a; path = Dependencies/libcurl/libcurl.a; sourceTree = SOURCE_ROOT; }; + D540E93728EE1BDE000F1B0F /* ErrorDetailsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ErrorDetailsViewController.swift; sourceTree = ""; }; D54DED1328CBC44B008B27A0 /* ErrorLogTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ErrorLogTableViewCell.swift; sourceTree = ""; }; D55E163528776CB000A627A1 /* ComplicationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComplicationView.swift; sourceTree = ""; }; D57DF637271E32F000677701 /* PatchApp.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = PatchApp.storyboard; sourceTree = ""; }; @@ -1021,6 +1022,7 @@ B33FFB8F295F8CF2002259E6 /* Recovered References */ = { isa = PBXGroup; children = ( + D540E93728EE1BDE000F1B0F /* ErrorDetailsViewController.swift */, ); name = "Recovered References"; sourceTree = ""; diff --git a/AltStore/Managing Apps/AppManager.swift b/AltStore/Managing Apps/AppManager.swift index 05328c0b..ad2a5e2d 100644 --- a/AltStore/Managing Apps/AppManager.swift +++ b/AltStore/Managing Apps/AppManager.swift @@ -1957,7 +1957,43 @@ private extension AppManager UNUserNotificationCenter.current().add(request) } - + func log(_ error: Error, for operation: AppOperation) + { + // Sanitize NSError on same thread before performing background task. + let sanitizedError = (error as NSError).sanitizedForSerialization() + + let loggedErrorOperation: LoggedError.Operation = { + switch operation + { + case .install: return .install + case .update: return .update + case .refresh: return .refresh + case .activate: return .activate + case .deactivate: return .deactivate + case .backup: return .backup + case .restore: return .restore + } + }() + + DatabaseManager.shared.persistentContainer.performBackgroundTask { context in + var app = operation.app + if let managedApp = app as? NSManagedObject, let tempApp = context.object(with: managedApp.objectID) as? AppProtocol + { + app = tempApp + } + + do + { + _ = LoggedError(error: sanitizedError, app: app, operation: loggedErrorOperation, context: context) + try context.save() + } + catch let saveError + { + print("[ALTLog] Failed to log error \(sanitizedError.domain) code \(sanitizedError.code) for \(app.bundleIdentifier):", saveError) + } + } + } + func run(_ operations: [Foundation.Operation], context: OperationContext?, requiresSerialQueue: Bool = false) { // Find "Install AltStore" operation if it already exists in `context` diff --git a/AltStore/Operations/DownloadAppOperation.swift b/AltStore/Operations/DownloadAppOperation.swift index d4e975c5..e6651784 100644 --- a/AltStore/Operations/DownloadAppOperation.swift +++ b/AltStore/Operations/DownloadAppOperation.swift @@ -20,6 +20,7 @@ final class DownloadAppOperation: ResultOperation private let appName: String private let bundleIdentifier: String + private var sourceURL: URL? private let destinationURL: URL private let session = URLSession(configuration: .default) @@ -32,6 +33,7 @@ final class DownloadAppOperation: ResultOperation self.appName = app.name self.bundleIdentifier = app.bundleIdentifier + self.sourceURL = app.url self.destinationURL = destinationURL super.init() @@ -111,7 +113,7 @@ private extension DownloadAppOperation { } func download(@Managed _ app: AppProtocol) { - guard let sourceURL = $app.url else { return self.finish(.failure(OperationError.appNotFound(name: self.appName))) } + guard let sourceURL = self.sourceURL else { return self.finish(.failure(OperationError.appNotFound(name: self.appName))) } self.downloadIPA(from: sourceURL) { result in do diff --git a/AltStore/Operations/FetchProvisioningProfilesOperation.swift b/AltStore/Operations/FetchProvisioningProfilesOperation.swift index ace2ff09..574ebd16 100644 --- a/AltStore/Operations/FetchProvisioningProfilesOperation.swift +++ b/AltStore/Operations/FetchProvisioningProfilesOperation.swift @@ -263,6 +263,10 @@ extension FetchProvisioningProfilesOperation { throw OperationError.maximumAppIDLimitReached(appName: application.name, requiredAppIDs: requiredAppIDs, availableAppIDs: availableAppIDs, expirationDate: expirationDate) } + else + { + throw ALTAppleAPIError(.maximumAppIDLimitReached) + } } } //App ID name must be ascii. If the name is not ascii, using bundleID instead diff --git a/AltStore/Operations/OperationError.swift b/AltStore/Operations/OperationError.swift index b98f630f..fc21d117 100644 --- a/AltStore/Operations/OperationError.swift +++ b/AltStore/Operations/OperationError.swift @@ -78,6 +78,7 @@ extension OperationError static func openAppFailed(name: String?) -> OperationError { OperationError(code: .openAppFailed, appName: name) } + static let domain = OperationError(code: .unknown)._domain static func SideJITIssue(error: String?) -> OperationError { var o = OperationError(code: .SideJITIssue) diff --git a/AltStore/Operations/VerifyAppOperation.swift b/AltStore/Operations/VerifyAppOperation.swift index 4c946e9a..7f0ce63e 100644 --- a/AltStore/Operations/VerifyAppOperation.swift +++ b/AltStore/Operations/VerifyAppOperation.swift @@ -116,6 +116,8 @@ final class VerifyAppOperation: ResultOperation { throw error } + let appName = self.context.app?.name ?? NSLocalizedString("The app", comment: "") + self.localizedFailure = String(format: NSLocalizedString("%@ could not be installed.", comment: ""), appName) guard let app = self.context.app else { throw OperationError.invalidParameters("VerifyAppOperation.main: self.context.app is nil") diff --git a/AltStore/Settings/Error Log/ErrorLogViewController.swift b/AltStore/Settings/Error Log/ErrorLogViewController.swift index d58fd64c..23786b9b 100644 --- a/AltStore/Settings/Error Log/ErrorLogViewController.swift +++ b/AltStore/Settings/Error Log/ErrorLogViewController.swift @@ -105,8 +105,8 @@ private extension ErrorLogViewController self?.searchFAQ(for: loggedError) }, UIAction(title: NSLocalizedString("View More Details", comment: ""), image: UIImage(systemName: "ellipsis.circle")) { [weak self] _ in - - } + self?.viewMoreDetails(for: loggedError) + }, ]) cell.menuButton.menu = menu diff --git a/AltStore/Settings/PatreonViewController.swift b/AltStore/Settings/PatreonViewController.swift index 63b1e4f6..79eb346b 100644 --- a/AltStore/Settings/PatreonViewController.swift +++ b/AltStore/Settings/PatreonViewController.swift @@ -348,7 +348,7 @@ extension PatreonViewController: UICollectionViewDelegateFlowLayout switch section { case .about: return .zero - case .patrons: return CGSize(width: 0, height: 0) + case .patrons: return CGSize(width: 320, height: 44) } } } diff --git a/AltStoreCore/Model/StoreApp.swift b/AltStoreCore/Model/StoreApp.swift index 6a973a28..eee50b5c 100644 --- a/AltStoreCore/Model/StoreApp.swift +++ b/AltStoreCore/Model/StoreApp.swift @@ -169,6 +169,31 @@ public class StoreApp: NSManagedObject, Decodable, Fetchable return self._versions.array as! [AppVersion] } + @nonobjc public var size: Int64? { + guard let version = self.latestSupportedVersion else { return nil } + return version.size + } + + @nonobjc public var version: String? { + guard let version = self.latestSupportedVersion else { return nil } + return version.version + } + + @nonobjc public var versionDescription: String? { + guard let version = self.latestSupportedVersion else { return nil } + return version.localizedDescription + } + + @nonobjc public var versionDate: Date? { + guard let version = self.latestSupportedVersion else { return nil } + return version.date + } + + @nonobjc public var downloadURL: URL? { + guard let version = self.latestSupportedVersion else { return nil } + return version.downloadURL + } + private override init(entity: NSEntityDescription, insertInto context: NSManagedObjectContext?) { super.init(entity: entity, insertInto: context) diff --git a/AltStoreCore/Patreon/PatreonAPI.swift b/AltStoreCore/Patreon/PatreonAPI.swift index f0af867d..0a0b34d1 100644 --- a/AltStoreCore/Patreon/PatreonAPI.swift +++ b/AltStoreCore/Patreon/PatreonAPI.swift @@ -15,24 +15,25 @@ private let clientSecret = "Zow0ggt9YgwIyd4DVLoO9Z02KuuIXW44xhx4lfL27x2u-_u4FE4r private let campaignID = "12794837" -extension PatreonAPI +typealias PatreonAPIError = PatreonAPIErrorCode.Error +enum PatreonAPIErrorCode: Int, ALTErrorEnum, CaseIterable { - enum Error: LocalizedError - { - case unknown - case notAuthenticated - case invalidAccessToken - - var errorDescription: String? { - switch self - { - case .unknown: return NSLocalizedString("An unknown error occurred.", comment: "") - case .notAuthenticated: return NSLocalizedString("No connected Patreon account.", comment: "") - case .invalidAccessToken: return NSLocalizedString("Invalid access token.", comment: "") - } + case unknown + case notAuthenticated + case invalidAccessToken + + var errorFailureReason: String { + switch self + { + case .unknown: return NSLocalizedString("An unknown error occurred.", comment: "") + case .notAuthenticated: return NSLocalizedString("No connected Patreon account.", comment: "") + case .invalidAccessToken: return NSLocalizedString("Invalid access token.", comment: "") } } - +} + +extension PatreonAPI +{ enum AuthorizationType { case none @@ -110,7 +111,7 @@ public extension PatreonAPI let components = URLComponents(url: callbackURL, resolvingAgainstBaseURL: false), let codeQueryItem = components.queryItems?.first(where: { $0.name == "code" }), let code = codeQueryItem.value - else { throw Error.unknown } + else { throw PatreonAPIError(.unknown) } self.fetchAccessToken(oauthCode: code) { (result) in switch result @@ -151,9 +152,9 @@ public extension PatreonAPI self.send(request, authorizationType: .user) { (result: Result) in switch result { - case .failure(Error.notAuthenticated): + case .failure(~PatreonAPIErrorCode.notAuthenticated): self.signOut() { (result) in - completion(.failure(Error.notAuthenticated)) + completion(.failure(PatreonAPIError(.notAuthenticated))) } case .failure(let error): completion(.failure(error)) @@ -357,11 +358,11 @@ private extension PatreonAPI { case .none: break case .creator: - guard let creatorAccessToken = Keychain.shared.patreonCreatorAccessToken else { return completion(.failure(Error.invalidAccessToken)) } + guard let creatorAccessToken = Keychain.shared.patreonCreatorAccessToken else { return completion(.failure(PatreonAPIError(.invalidAccessToken))) } request.setValue("Bearer " + creatorAccessToken, forHTTPHeaderField: "Authorization") case .user: - guard let accessToken = Keychain.shared.patreonAccessToken else { return completion(.failure(Error.notAuthenticated)) } + guard let accessToken = Keychain.shared.patreonAccessToken else { return completion(.failure(PatreonAPIError(.notAuthenticated))) } request.setValue("Bearer " + accessToken, forHTTPHeaderField: "Authorization") } @@ -374,8 +375,8 @@ private extension PatreonAPI { switch authorizationType { - case .creator: completion(.failure(Error.invalidAccessToken)) - case .none: completion(.failure(Error.notAuthenticated)) + case .creator: completion(.failure(PatreonAPIError(.invalidAccessToken))) + case .none: completion(.failure(PatreonAPIError(.notAuthenticated))) case .user: self.refreshAccessToken() { (result) in switch result diff --git a/Shared/Extensions/NSError+AltStore.swift b/Shared/Extensions/NSError+AltStore.swift index a6162365..4b85ed1f 100644 --- a/Shared/Extensions/NSError+AltStore.swift +++ b/Shared/Extensions/NSError+AltStore.swift @@ -73,6 +73,7 @@ public extension NSError { var userInfo = self.userInfo userInfo[NSLocalizedDescriptionKey] = self.localizedDescription + userInfo[NSLocalizedFailureErrorKey] = self.localizedFailure userInfo[NSLocalizedFailureReasonErrorKey] = self.localizedFailureReason userInfo[NSLocalizedRecoverySuggestionErrorKey] = self.localizedRecoverySuggestion userInfo[NSDebugDescriptionErrorKey] = self.localizedDebugDescription @@ -124,6 +125,7 @@ public extension NSError var userInfo = self.userInfo userInfo[NSDebugDescriptionErrorKey] = self.localizedDebugDescription + userInfo[NSLocalizedDescriptionKey] = self.localizedDescription userInfo[NSLocalizedFailureErrorKey] = self.localizedFailure userInfo[NSLocalizedFailureReasonErrorKey] = self.localizedFailureReason userInfo[NSLocalizedRecoverySuggestionErrorKey] = self.localizedRecoverySuggestion