mirror of
https://github.com/SideStore/SideStore.git
synced 2026-02-21 04:33:30 +01:00
Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
41b57b7f5e | ||
|
|
bab1fcb7bc |
@@ -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 = "";
|
||||||
|
|||||||
@@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|
||||||
|
|||||||
@@ -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] = [])
|
||||||
|
|||||||
131
AltStore/Operations/VerifyAppOperation.swift
Normal file
131
AltStore/Operations/VerifyAppOperation.swift
Normal 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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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",
|
||||||
|
|||||||
Reference in New Issue
Block a user