Skip to content

Commit a3e4beb

Browse files
author
*
committed
Fix restore image download
1 parent b4f7a8b commit a3e4beb

File tree

10 files changed

+151
-190
lines changed

10 files changed

+151
-190
lines changed

virtualOS.xcodeproj/project.pbxproj

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -275,7 +275,7 @@
275275
CODE_SIGN_IDENTITY = "Apple Development";
276276
CODE_SIGN_STYLE = Automatic;
277277
COMBINE_HIDPI_IMAGES = YES;
278-
CURRENT_PROJECT_VERSION = 31;
278+
CURRENT_PROJECT_VERSION = 34;
279279
DEAD_CODE_STRIPPING = YES;
280280
DEVELOPMENT_TEAM = 2AD47BTDQ6;
281281
ENABLE_APP_SANDBOX = YES;
@@ -294,7 +294,7 @@
294294
"$(inherited)",
295295
"@executable_path/../Frameworks",
296296
);
297-
MARKETING_VERSION = 2.3;
297+
MARKETING_VERSION = 2.3.1;
298298
PRODUCT_BUNDLE_IDENTIFIER = com.github.yep.ios.virtualOS;
299299
PRODUCT_NAME = "$(TARGET_NAME)";
300300
PROVISIONING_PROFILE_SPECIFIER = "";
@@ -312,7 +312,7 @@
312312
CODE_SIGN_IDENTITY = "Apple Development";
313313
CODE_SIGN_STYLE = Automatic;
314314
COMBINE_HIDPI_IMAGES = YES;
315-
CURRENT_PROJECT_VERSION = 31;
315+
CURRENT_PROJECT_VERSION = 34;
316316
DEAD_CODE_STRIPPING = YES;
317317
DEVELOPMENT_TEAM = 2AD47BTDQ6;
318318
ENABLE_APP_SANDBOX = YES;
@@ -331,7 +331,7 @@
331331
"$(inherited)",
332332
"@executable_path/../Frameworks",
333333
);
334-
MARKETING_VERSION = 2.3;
334+
MARKETING_VERSION = 2.3.1;
335335
PRODUCT_BUNDLE_IDENTIFIER = com.github.yep.ios.virtualOS;
336336
PRODUCT_NAME = "$(TARGET_NAME)";
337337
PROVISIONING_PROFILE_SPECIFIER = "";

virtualOS/Extension/URL+Paths.swift

Lines changed: 48 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,7 @@
99
import Foundation
1010

1111
extension URL {
12-
static let basePath = NSHomeDirectory() + "/Documents"
13-
static let bundleName = "virtualOS.bundle/"
14-
static let restoreImageName = "RestoreImage.ipsw"
12+
static let basePath = NSHomeDirectory() + "/Documents"
1513

1614
static var baseURL: URL {
1715
return URL(fileURLWithPath: basePath)
@@ -45,15 +43,36 @@ extension URL {
4543
return self.appending(path: "Parameters.txt")
4644
}
4745

48-
static func nextURL(for url: URL, index i: Int, baseName: String) -> URL {
49-
// ensure we're working with a directory, not a file
50-
var directoryURL = url
51-
if !url.hasDirectoryPath {
52-
directoryURL = url.deletingLastPathComponent()
46+
/// Start accessing security scoped URL for the VM files directory.
47+
/// - Returns: VM files directory URL or default value
48+
static func startAccessingVMFilesDirectory() -> URL {
49+
if let bookmarkPath = UserDefaults.standard.vmFilesDirectory?.removingPercentEncoding,
50+
let bookmarkData = UserDefaults.standard.vmFilesDirectoryBookmarkData
51+
{
52+
if Bookmark.startAccess(bookmarkData: bookmarkData, for: bookmarkPath) == nil {
53+
// previous vm file directory no longer exists, reset to default
54+
UserDefaults.standard.vmFilesDirectory = URL.basePath
55+
return URL.baseURL
56+
}
57+
return URL.restoreImageURL
5358
}
54-
55-
let filename = "\(baseName)_\(i).ipsw"
56-
return directoryURL.appendingPathComponent(filename)
59+
return URL.baseURL // default
60+
}
61+
62+
/// Start accessing security scoped URL for the restore images directory.
63+
/// - Returns: Restore image directory URL or default value
64+
static func startAccessingRestoreImagesDirectory() -> URL {
65+
if let bookmarkPath = UserDefaults.standard.restoreImagesDirectory?.removingPercentEncoding,
66+
let bookmarkData = UserDefaults.standard.restoreImagesDirectoryBookmarkData
67+
{
68+
if Bookmark.startAccess(bookmarkData: bookmarkData, for: bookmarkPath) == nil {
69+
// previous restore image directory no longer exists, reset
70+
UserDefaults.standard.restoreImagesDirectory = URL.basePath
71+
return URL.baseURL
72+
}
73+
return URL.restoreImageURL
74+
}
75+
return URL.baseURL // default
5776
}
5877

5978
fileprivate static func fileURL(for path: String?) -> URL {
@@ -63,5 +82,23 @@ extension URL {
6382
return baseURL // default value
6483
}
6584

85+
static func createFilename(baseURL: URL, name: String, suffix: String) -> URL {
86+
// try to find a filename that does not exist
87+
let restoreImagesDirectoryURL = URL.startAccessingRestoreImagesDirectory()
88+
var url = restoreImagesDirectoryURL.appendingPathComponent("\(name).\(suffix)")
89+
var i = 1
90+
var exists = true
91+
92+
while exists {
93+
if FileManager.default.fileExists(atPath: url.path) {
94+
url = restoreImagesDirectoryURL.appendingPathComponent("\(name)_\(i).\(suffix)")
95+
i += 1
96+
} else {
97+
exists = false
98+
}
99+
}
100+
return url
101+
}
102+
66103
}
67104

virtualOS/Extension/UserDefaults+Settings.swift

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,11 @@ extension UserDefaults {
3131

3232
var vmFilesDirectory: String? {
3333
get {
34-
return string(forKey: Self.vmFilesDirectoryKey)
34+
if let result = string(forKey: Self.vmFilesDirectoryKey) {
35+
return result.removingPercentEncoding
36+
} else {
37+
return nil
38+
}
3539
}
3640
set {
3741
set(newValue, forKey: Self.vmFilesDirectoryKey)
@@ -51,7 +55,11 @@ extension UserDefaults {
5155

5256
var restoreImagesDirectory: String? {
5357
get {
54-
return string(forKey: Self.restoreImagesDirectoryKey)
58+
if let result = string(forKey: Self.restoreImagesDirectoryKey) {
59+
return result.removingPercentEncoding
60+
} else {
61+
return nil
62+
}
5563
}
5664
set {
5765
set(newValue, forKey: Self.restoreImagesDirectoryKey)
@@ -78,9 +86,4 @@ extension UserDefaults {
7886
synchronize()
7987
}
8088
}
81-
82-
func resetVMFilesDirectory() {
83-
UserDefaults.standard.vmFilesDirectory = URL.baseURL.path
84-
UserDefaults.standard.vmFilesDirectoryBookmarkData = Bookmark.createBookmarkData(fromUrl: URL.baseURL)
85-
}
8689
}

virtualOS/Model/Bookmark.swift

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -60,17 +60,4 @@ struct Bookmark {
6060
}
6161
Self.accessedURLs = [:]
6262
}
63-
64-
static func startRestoreImagesDirectoryAccess() -> Bool {
65-
guard let filesDirectoryString = UserDefaults.standard.restoreImagesDirectory ?? UserDefaults.standard.vmFilesDirectory else {
66-
return false
67-
}
68-
69-
// grant access
70-
let bookmarkData = UserDefaults.standard.restoreImagesDirectoryBookmarkData ?? UserDefaults.standard.vmFilesDirectoryBookmarkData
71-
if Bookmark.startAccess(bookmarkData: bookmarkData, for: filesDirectoryString) == nil {
72-
return false
73-
}
74-
return true
75-
}
7663
}

virtualOS/RestoreImage/RestoreImageDownload.swift

Lines changed: 7 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -46,27 +46,19 @@ final class RestoreImageDownload {
4646

4747
fileprivate func progressDone(error: Error?) {
4848
FileModel.cleanUpTemporaryFiles()
49-
delegate?.progress(100, progressString: "Done")
49+
delegate?.progress(100, progressString: "Restore image download finished.")
5050
delegate?.done(error: error)
5151
}
5252

5353
fileprivate func download(restoreImage: VZMacOSRestoreImage) {
5454
Logger.shared.log(level: .default, "downloading restore image for \(restoreImage.operatingSystemVersionString)")
5555

56-
var targetURL: URL? = nil
57-
if let filesDirectoryString = UserDefaults.standard.restoreImagesDirectory ?? UserDefaults.standard.vmFilesDirectory {
58-
targetURL = createRestoreImageURL(directoryString: filesDirectoryString)
59-
60-
// grant access for the restore images path
61-
guard Bookmark.startRestoreImagesDirectoryAccess() else {
62-
Logger.shared.warning("Could not start accessing bookmark \(filesDirectoryString)")
63-
return
64-
}
65-
}
66-
56+
let restoreImagesDirectoryURL = URL.startAccessingRestoreImagesDirectory()
57+
let restoreImagesURL = URL.createFilename(baseURL: restoreImagesDirectoryURL, name: "RestoreImage", suffix: "ipsw")
58+
6759
let downloadTask = URLSession.shared.downloadTask(with: restoreImage.url) { tempURL, response, error in
6860
self.downloading = false
69-
self.downloadFinished(tempURL: tempURL, restoreImageURL: targetURL, error: error)
61+
self.downloadFinished(tempURL: tempURL, restoreImageURL: restoreImagesURL, error: error)
7062
}
7163
observation = downloadTask.progress.observe(\.fractionCompleted) { _, _ in }
7264
downloadTask.resume()
@@ -109,7 +101,6 @@ final class RestoreImageDownload {
109101
}
110102
Logger.shared.log(level: .default, "download finished")
111103

112-
let moveError = RestoreError(localizedDescription: "Failed to prepare downloaded restore image")
113104
if let tempURL, let restoreImageURL {
114105
Logger.shared.log(level: .debug, "moving restore image: \(tempURL) to \(restoreImageURL)")
115106
delegate?.progress(99, progressString: "Preparing file. Please wait...")
@@ -119,29 +110,11 @@ final class RestoreImageDownload {
119110
Logger.shared.log(level: .default, "moved restore image to \(restoreImageURL)")
120111
progressDone(error: nil)
121112
} catch {
122-
Logger.shared.log(level: .error, "failed to prepare restore image: \(error.localizedDescription)")
123-
progressDone(error: moveError)
113+
progressDone(error: RestoreError(localizedDescription: "Failed to prepare downloaded restore image: \(error.localizedDescription)"))
124114
}
125115
} else {
126-
Logger.shared.log(level: .error, "failed to prepare downloaded restore image ")
127-
progressDone(error: moveError)
128-
}
129-
}
130-
131-
fileprivate func createRestoreImageURL(directoryString: String) -> URL {
132-
// try to find a filename that does not exist
133-
var url = URL(fileURLWithPath: directoryString)
134-
var exists = true
135-
var i = 1
136-
while exists {
137-
url = URL.nextURL(for: url, index: i, baseName: "RestoreImage")
138-
if FileManager.default.fileExists(atPath: url.path) {
139-
i += 1
140-
} else {
141-
exists = false
142-
}
116+
progressDone(error: RestoreError(localizedDescription: "Failed to prepare downloaded restore image: invalid destination"))
143117
}
144-
return url
145118
}
146119
}
147120

0 commit comments

Comments
 (0)