Compare commits

..

2 Commits
1.3.1 ... 1.3.2

Author SHA1 Message Date
Riley Testut
41b57b7f5e Updates app version to 1.3.2 2020-05-03 14:48:23 -07:00
Riley Testut
bab1fcb7bc Asks user for permission before installing apps with private entitlements 2020-05-02 22:06:57 -07:00
6 changed files with 177 additions and 10 deletions

View File

@@ -173,6 +173,7 @@
BFC57A6E2416FC5D00EB891E /* InstalledAppsCollectionHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFC57A6D2416FC5D00EB891E /* InstalledAppsCollectionHeaderView.swift */; }; BFC57A6E2416FC5D00EB891E /* InstalledAppsCollectionHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFC57A6D2416FC5D00EB891E /* InstalledAppsCollectionHeaderView.swift */; };
BFC57A702416FC7600EB891E /* InstalledAppsCollectionHeaderView.xib in Resources */ = {isa = PBXBuildFile; fileRef = BFC57A6F2416FC7600EB891E /* InstalledAppsCollectionHeaderView.xib */; }; BFC57A702416FC7600EB891E /* InstalledAppsCollectionHeaderView.xib in Resources */ = {isa = PBXBuildFile; fileRef = BFC57A6F2416FC7600EB891E /* InstalledAppsCollectionHeaderView.xib */; };
BFC84A4D2421A19100853474 /* SourcesViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFC84A4C2421A19100853474 /* SourcesViewController.swift */; }; BFC84A4D2421A19100853474 /* SourcesViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFC84A4C2421A19100853474 /* SourcesViewController.swift */; };
BFCCB51A245E3401001853EA /* VerifyAppOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFCCB519245E3401001853EA /* VerifyAppOperation.swift */; };
BFD2476E2284B9A500981D42 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFD2476D2284B9A500981D42 /* AppDelegate.swift */; }; BFD2476E2284B9A500981D42 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFD2476D2284B9A500981D42 /* AppDelegate.swift */; };
BFD247752284B9A500981D42 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = BFD247732284B9A500981D42 /* Main.storyboard */; }; BFD247752284B9A500981D42 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = BFD247732284B9A500981D42 /* Main.storyboard */; };
BFD247772284B9A700981D42 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = BFD247762284B9A700981D42 /* Assets.xcassets */; }; BFD247772284B9A700981D42 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = BFD247762284B9A700981D42 /* Assets.xcassets */; };
@@ -508,6 +509,7 @@
BFC57A6D2416FC5D00EB891E /* InstalledAppsCollectionHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InstalledAppsCollectionHeaderView.swift; sourceTree = "<group>"; }; BFC57A6D2416FC5D00EB891E /* InstalledAppsCollectionHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InstalledAppsCollectionHeaderView.swift; sourceTree = "<group>"; };
BFC57A6F2416FC7600EB891E /* InstalledAppsCollectionHeaderView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = InstalledAppsCollectionHeaderView.xib; sourceTree = "<group>"; }; BFC57A6F2416FC7600EB891E /* InstalledAppsCollectionHeaderView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = InstalledAppsCollectionHeaderView.xib; sourceTree = "<group>"; };
BFC84A4C2421A19100853474 /* SourcesViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SourcesViewController.swift; sourceTree = "<group>"; }; BFC84A4C2421A19100853474 /* SourcesViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SourcesViewController.swift; sourceTree = "<group>"; };
BFCCB519245E3401001853EA /* VerifyAppOperation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VerifyAppOperation.swift; sourceTree = "<group>"; };
BFD2476A2284B9A500981D42 /* AltStore.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = AltStore.app; sourceTree = BUILT_PRODUCTS_DIR; }; BFD2476A2284B9A500981D42 /* AltStore.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = AltStore.app; sourceTree = BUILT_PRODUCTS_DIR; };
BFD2476D2284B9A500981D42 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; }; BFD2476D2284B9A500981D42 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
BFD247742284B9A500981D42 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; }; BFD247742284B9A500981D42 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
@@ -1242,6 +1244,7 @@
BFA8172A23C5633D001B5953 /* FetchAnisetteDataOperation.swift */, BFA8172A23C5633D001B5953 /* FetchAnisetteDataOperation.swift */,
BF56D2AB23DF8E170006506D /* FetchAppIDsOperation.swift */, BF56D2AB23DF8E170006506D /* FetchAppIDsOperation.swift */,
BFC57A642416C72400EB891E /* DeactivateAppOperation.swift */, BFC57A642416C72400EB891E /* DeactivateAppOperation.swift */,
BFCCB519245E3401001853EA /* VerifyAppOperation.swift */,
); );
path = Operations; path = Operations;
sourceTree = "<group>"; sourceTree = "<group>";
@@ -1756,6 +1759,7 @@
BF0DCA662433BDF500E3A595 /* AnalyticsManager.swift in Sources */, BF0DCA662433BDF500E3A595 /* AnalyticsManager.swift in Sources */,
BFD5D6F4230DDB0A007955AB /* Campaign.swift in Sources */, BFD5D6F4230DDB0A007955AB /* Campaign.swift in Sources */,
BFB6B21B23186D640022A802 /* NewsItem.swift in Sources */, BFB6B21B23186D640022A802 /* NewsItem.swift in Sources */,
BFCCB51A245E3401001853EA /* VerifyAppOperation.swift in Sources */,
BFF0B6982322CAB8007A79E1 /* InstructionsViewController.swift in Sources */, BFF0B6982322CAB8007A79E1 /* InstructionsViewController.swift in Sources */,
BFA8172D23C5823E001B5953 /* InstalledExtension.swift in Sources */, BFA8172D23C5823E001B5953 /* InstalledExtension.swift in Sources */,
BFD5D6E8230CC961007955AB /* PatreonAPI.swift in Sources */, BFD5D6E8230CC961007955AB /* PatreonAPI.swift in Sources */,
@@ -2296,7 +2300,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
MARKETING_VERSION = 1.3.1; MARKETING_VERSION = 1.3.2;
PRODUCT_BUNDLE_IDENTIFIER = com.rileytestut.AltStore; PRODUCT_BUNDLE_IDENTIFIER = com.rileytestut.AltStore;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = ""; PROVISIONING_PROFILE_SPECIFIER = "";
@@ -2324,7 +2328,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
MARKETING_VERSION = 1.3.1; MARKETING_VERSION = 1.3.2;
PRODUCT_BUNDLE_IDENTIFIER = com.rileytestut.AltStore; PRODUCT_BUNDLE_IDENTIFIER = com.rileytestut.AltStore;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = ""; PROVISIONING_PROFILE_SPECIFIER = "";

View File

@@ -25,3 +25,18 @@ extension NSError
return error return error
} }
} }
protocol ALTLocalizedError: LocalizedError, CustomNSError
{
var errorFailure: String? { get }
}
extension ALTLocalizedError
{
var errorUserInfo: [String : Any] {
let userInfo = [NSLocalizedDescriptionKey: self.errorDescription,
NSLocalizedFailureReasonErrorKey: self.failureReason,
NSLocalizedFailureErrorKey: self.errorFailure].compactMapValues { $0 }
return userInfo
}
}

View File

@@ -396,6 +396,11 @@ private extension AppManager
self.set(progress, for: operation) self.set(progress, for: operation)
} }
if let viewController = presentingViewController
{
group.context.presentingViewController = viewController
}
/* Authenticate (if necessary) */ /* Authenticate (if necessary) */
var authenticationOperation: AuthenticationOperation? var authenticationOperation: AuthenticationOperation?
if group.context.session == nil if group.context.session == nil
@@ -503,6 +508,16 @@ private extension AppManager
} }
progress.addChild(downloadOperation.progress, withPendingUnitCount: 25) progress.addChild(downloadOperation.progress, withPendingUnitCount: 25)
/* Verify App */
let verifyOperation = VerifyAppOperation(context: context)
verifyOperation.resultHandler = { (result) in
switch result
{
case .failure(let error): context.error = error
case .success: break
}
}
verifyOperation.addDependency(downloadOperation)
/* Refresh Anisette Data */ /* Refresh Anisette Data */
let refreshAnisetteDataOperation = FetchAnisetteDataOperation(context: group.context) let refreshAnisetteDataOperation = FetchAnisetteDataOperation(context: group.context)
@@ -513,7 +528,7 @@ private extension AppManager
case .success(let anisetteData): group.context.session?.anisetteData = anisetteData case .success(let anisetteData): group.context.session?.anisetteData = anisetteData
} }
} }
refreshAnisetteDataOperation.addDependency(downloadOperation) refreshAnisetteDataOperation.addDependency(verifyOperation)
/* Fetch Provisioning Profiles */ /* Fetch Provisioning Profiles */
@@ -579,7 +594,7 @@ private extension AppManager
progress.addChild(installOperation.progress, withPendingUnitCount: 30) progress.addChild(installOperation.progress, withPendingUnitCount: 30)
installOperation.addDependency(sendAppOperation) installOperation.addDependency(sendAppOperation)
let operations = [downloadOperation, refreshAnisetteDataOperation, fetchProvisioningProfilesOperation, resignAppOperation, sendAppOperation, installOperation] let operations = [downloadOperation, verifyOperation, refreshAnisetteDataOperation, fetchProvisioningProfilesOperation, resignAppOperation, sendAppOperation, installOperation]
group.add(operations) group.add(operations)
self.run(operations, context: group.context) self.run(operations, context: group.context)

View File

@@ -17,6 +17,8 @@ class OperationContext
var server: Server? var server: Server?
var error: Error? var error: Error?
var presentingViewController: UIViewController?
let operations: NSHashTable<Foundation.Operation> let operations: NSHashTable<Foundation.Operation>
init(server: Server? = nil, error: Error? = nil, operations: [Foundation.Operation] = []) init(server: Server? = nil, error: Error? = nil, operations: [Foundation.Operation] = [])

View File

@@ -0,0 +1,131 @@
//
// VerifyAppOperation.swift
// AltStore
//
// Created by Riley Testut on 5/2/20.
// Copyright © 2020 Riley Testut. All rights reserved.
//
import Foundation
import AltSign
import AltKit
import Roxas
enum VerificationError: ALTLocalizedError
{
case privateEntitlements(ALTApplication, [String: Any])
var app: ALTApplication {
switch self {
case .privateEntitlements(let app, _): return app
}
}
var errorFailure: String? {
return String(format: NSLocalizedString("“%@” could not be installed.", comment: ""), app.name)
}
var failureReason: String? {
switch self
{
case .privateEntitlements(let app, _):
return String(format: NSLocalizedString("“%@” requires private permissions.", comment: ""), app.name)
}
}
}
@objc(VerifyAppOperation)
class VerifyAppOperation: ResultOperation<Void>
{
let context: AppOperationContext
var verificationHandler: ((VerificationError) -> Bool)?
init(context: AppOperationContext)
{
self.context = context
super.init()
}
override func main()
{
super.main()
do
{
if let error = self.context.error
{
throw error
}
guard let app = self.context.app else { throw OperationError.invalidParameters }
if let commentStart = app.entitlementsString.range(of: "<!---><!-->"), let commentEnd = app.entitlementsString.range(of: "<!-- -->")
{
// Psychic Paper private entitlements.
let entitlementsStart = app.entitlementsString.index(after: commentStart.upperBound)
let rawEntitlements = String(app.entitlementsString[entitlementsStart ..< commentEnd.lowerBound])
let plistTemplate = """
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
%@
</dict>
</plist>
"""
let entitlementsPlist = String(format: plistTemplate, rawEntitlements)
let entitlements = try PropertyListSerialization.propertyList(from: entitlementsPlist.data(using: .utf8)!, options: [], format: nil) as! [String: Any]
let error = VerificationError.privateEntitlements(app, entitlements)
self.process(error) { (result) in
self.finish(result.mapError { $0 as Error })
}
return
}
self.finish(.success(()))
}
catch
{
self.finish(.failure(error))
}
}
}
private extension VerifyAppOperation
{
func process(_ error: VerificationError, completion: @escaping (Result<Void, VerificationError>) -> Void)
{
guard let presentingViewController = self.context.presentingViewController else { return completion(.failure(error)) }
DispatchQueue.main.async {
switch error
{
case .privateEntitlements(_, let entitlements):
let permissions = entitlements.keys.sorted().joined(separator: "\n")
let message = String(format: NSLocalizedString("""
You must allow access to these private permissions before continuing:
%@
Private permissions allow apps to do more than normally allowed by iOS, including potentially accessing sensitive private data. Make sure to only install apps from sources you trust.
""", comment: ""), permissions)
let alertController = UIAlertController(title: error.failureReason ?? error.localizedDescription, message: message, preferredStyle: .alert)
alertController.addAction(UIAlertAction(title: NSLocalizedString("Allow Access", comment: ""), style: .destructive) { (action) in
completion(.success(()))
})
alertController.addAction(UIAlertAction(title: NSLocalizedString("Deny Access", comment: ""), style: .default, handler: { (action) in
completion(.failure(error))
}))
presentingViewController.present(alertController, animated: true, completion: nil)
}
}
}
}

View File

@@ -7,9 +7,9 @@
"name": "AltStore", "name": "AltStore",
"bundleIdentifier": "com.rileytestut.AltStore", "bundleIdentifier": "com.rileytestut.AltStore",
"developerName": "Riley Testut", "developerName": "Riley Testut",
"version": "1.3.1", "version": "1.3.2",
"versionDate": "2020-05-01T13:00:00-07:00", "versionDate": "2020-05-03T14:00:00-07:00",
"versionDescription": "This update adds support for installing apps using private entitlements via Psychic Paper.\n\nFor more info, check out https://siguza.github.io/psychicpaper/\n\nPREVIOUS UPDATE:\n• Sideload any app (.ipa file) directly from Files.\n• Manage which apps are (in-)active at any time from the My Apps tab (optionally via drag and drop)*\n• Dramatically faster app refresh times*\n• Improved error messages when refreshing apps*\n• Improved stability when refreshing apps over WiFi*\n• Removes cached apps after they have been uninstalled.\n• Fixes peek & pop on iOS 12.\n• Fixes missing recovery suggestions for some errors.\n• Fixes secondary AltStore appearing after refresh under certain circumstances.\n\n* Requires latest AltServer version. Update AltServer by choosing \"Check For Updates...\" from the AltServer menu.", "versionDescription": "NEW\n• Displays \"Grant Permission\" alert that lists all private permissions when installing an app that uses them.\n\nNOTE: No permission alert will appear for apps without private entitlements.\n\nPREVIOUS UPDATES:\n• Adds support for installing apps using private entitlements via Psychic Paper (https://siguza.github.io/psychicpaper/)\n• Sideload any app (.ipa file) directly from Files.\n• Manage which apps are (in-)active at any time from the My Apps tab (optionally via drag and drop)*\n• Dramatically faster app refresh times*\n• Improved error messages when refreshing apps*\n• Improved stability when refreshing apps over WiFi*\n• Removes cached apps after they have been uninstalled.\n• Fixes peek & pop on iOS 12.\n• Fixes missing recovery suggestions for some errors.\n• Fixes secondary AltStore appearing after refresh under certain circumstances.\n\n* Requires latest AltServer version. Update AltServer by choosing \"Check For Updates...\" from the AltServer menu.",
"downloadURL": "https://f000.backblazeb2.com/file/altstore/altstore.ipa", "downloadURL": "https://f000.backblazeb2.com/file/altstore/altstore.ipa",
"localizedDescription": "AltStore is an alternative app store for non-jailbroken devices. \n\nThis version of AltStore allows you to install Delta, an all-in-one emulator for iOS, as well as sideload other .ipa files from the Files app.", "localizedDescription": "AltStore is an alternative app store for non-jailbroken devices. \n\nThis version of AltStore allows you to install Delta, an all-in-one emulator for iOS, as well as sideload other .ipa files from the Files app.",
"iconURL": "https://user-images.githubusercontent.com/705880/65270980-1eb96f80-dad1-11e9-9367-78ccd25ceb02.png", "iconURL": "https://user-images.githubusercontent.com/705880/65270980-1eb96f80-dad1-11e9-9367-78ccd25ceb02.png",
@@ -36,9 +36,9 @@
"bundleIdentifier": "com.rileytestut.AltStore.Beta", "bundleIdentifier": "com.rileytestut.AltStore.Beta",
"developerName": "Riley Testut", "developerName": "Riley Testut",
"subtitle": "An alternative App Store for iOS.", "subtitle": "An alternative App Store for iOS.",
"version": "1.3.1b", "version": "1.3.2b1",
"versionDate": "2020-05-01T13:00:00-07:00", "versionDate": "2020-05-03T14:00:00-07:00",
"versionDescription": "This update adds support for installing apps using private entitlements via Psychic Paper.\n\nFor more info, check out https://siguza.github.io/psychicpaper/", "versionDescription": "NEW\n• Displays \"Grant Permission\" alert that lists all private entitlements when installing an app that uses them.\n\nNOTE: No permission alert will appear for apps without private entitlements.\n\nPREVIOUS UPDATE\n• Adds support for installing apps using private entitlements via Psychic Paper (https://siguza.github.io/psychicpaper/)",
"downloadURL": "https://f000.backblazeb2.com/file/altstore/altstore-beta.ipa", "downloadURL": "https://f000.backblazeb2.com/file/altstore/altstore-beta.ipa",
"localizedDescription": "AltStore is an alternative app store for non-jailbroken devices. \n\nThis beta release of AltStore adds support for 3rd party sources, allowing you to download apps from other developers directly through AltStore.", "localizedDescription": "AltStore is an alternative app store for non-jailbroken devices. \n\nThis beta release of AltStore adds support for 3rd party sources, allowing you to download apps from other developers directly through AltStore.",
"iconURL": "https://user-images.githubusercontent.com/705880/65270980-1eb96f80-dad1-11e9-9367-78ccd25ceb02.png", "iconURL": "https://user-images.githubusercontent.com/705880/65270980-1eb96f80-dad1-11e9-9367-78ccd25ceb02.png",