@@ -90,6 +90,19 @@ - (NSDictionary *)currentDownload {
9090 return [download isKindOfClass: NSDictionary .class] ? download : nil ;
9191}
9292
93+ - (NSString *)stagingDestinationPathForDownload : (NSDictionary *)download {
94+ NSString *path = download[@" destinationPath" ];
95+ return [path isKindOfClass: NSString .class] && path.length > 0 ? path : nil ;
96+ }
97+
98+ - (NSString *)finalDestinationPathForDownload : (NSDictionary *)download {
99+ NSString *path = download[@" finalDestinationPath" ];
100+ if ([path isKindOfClass: NSString .class] && path.length > 0 ) {
101+ return path;
102+ }
103+ return [self stagingDestinationPathForDownload: download];
104+ }
105+
93106- (void )loadCurrentDownload {
94107 NSDictionary *download = [self currentDownload ];
95108 if (!download) {
@@ -122,7 +135,7 @@ - (BOOL)shouldHandleDownloadURL:(NSURL *)url suggestedFilename:(NSString *)sugge
122135 NSDictionary *download = [self currentDownload ];
123136 NSString *expectedFileName = download[@" fileName" ];
124137 if (![expectedFileName isKindOfClass: NSString .class] || expectedFileName.length == 0 ) {
125- expectedFileName = [download[ @" destinationPath " ] lastPathComponent ] ;
138+ expectedFileName = [self finalDestinationPathForDownload: download]. lastPathComponent ;
126139 }
127140
128141 NSString *urlFileName = url.lastPathComponent ;
@@ -154,7 +167,8 @@ - (void)startDownloadWithRequest:(NSURLRequest *)request {
154167 }
155168
156169 NSDictionary *download = [self currentDownload ];
157- NSString *destinationPath = download[@" destinationPath" ];
170+ NSString *destinationPath = [self stagingDestinationPathForDownload: download];
171+ NSString *finalDestinationPath = [self finalDestinationPathForDownload: download];
158172 if (![destinationPath isKindOfClass: NSString .class] || destinationPath.length == 0 ) {
159173 [self showDownloadError: @" Manual download destination is missing." ];
160174 return ;
@@ -163,7 +177,7 @@ - (void)startDownloadWithRequest:(NSURLRequest *)request {
163177 self.preparingDownload = YES ;
164178 self.navigationItem .rightBarButtonItem .enabled = NO ;
165179 self.progressView .progress = 0.25 ;
166- self.title = [NSString stringWithFormat: @" Downloading %@ " , destinationPath.lastPathComponent];
180+ self.title = [NSString stringWithFormat: @" Downloading %@ " , finalDestinationPath.lastPathComponent ?: destinationPath.lastPathComponent];
167181
168182 NSMutableURLRequest *downloadRequest = request.mutableCopy ;
169183 [self .webView.configuration.websiteDataStore.httpCookieStore getAllCookies: ^(NSArray <NSHTTPCookie *> *cookies) {
@@ -183,11 +197,11 @@ - (void)startDownloadWithRequest:(NSURLRequest *)request {
183197 for (NSString *header in cookieHeaders) {
184198 [downloadRequest setValue: cookieHeaders[header] forHTTPHeaderField: header];
185199 }
186- [self beginDownloadWithRequest: downloadRequest destinationPath: destinationPath];
200+ [self beginDownloadWithRequest: downloadRequest destinationPath: destinationPath finalDestinationPath: finalDestinationPath ];
187201 }];
188202}
189203
190- - (void )beginDownloadWithRequest : (NSURLRequest *)request destinationPath : (NSString *)destinationPath {
204+ - (void )beginDownloadWithRequest : (NSURLRequest *)request destinationPath : (NSString *)destinationPath finalDestinationPath : ( NSString *) finalDestinationPath {
191205 self.preparingDownload = NO ;
192206 __weak CurseForgeManualDownloadViewController *weakSelf = self;
193207 self.downloadTask = [NSURLSession .sharedSession downloadTaskWithRequest: request
@@ -198,7 +212,7 @@ - (void)beginDownloadWithRequest:(NSURLRequest *)request destinationPath:(NSStri
198212 }
199213 NSError *storeError = error;
200214 if (!storeError) {
201- storeError = [strongSelf storeDownloadedFile: location toPath: destinationPath];
215+ storeError = [strongSelf storeDownloadedFile: location toPath: destinationPath finalPath: finalDestinationPath ];
202216 }
203217 dispatch_async (dispatch_get_main_queue (), ^{
204218 strongSelf.downloadTask = nil ;
@@ -216,7 +230,7 @@ - (void)beginDownloadWithRequest:(NSURLRequest *)request destinationPath:(NSStri
216230 [self .downloadTask resume ];
217231}
218232
219- - (NSError *)storeDownloadedFile : (NSURL *)location toPath : (NSString *)destinationPath {
233+ - (NSError *)storeDownloadedFile : (NSURL *)location toPath : (NSString *)destinationPath finalPath : ( NSString *) finalDestinationPath {
220234 if (!location) {
221235 return [NSError errorWithDomain: @" CurseForgeManualDownload"
222236 code: 2
@@ -239,13 +253,34 @@ - (NSError *)storeDownloadedFile:(NSURL *)location toPath:(NSString *)destinatio
239253 return error;
240254 }
241255
256+ NSString *validationPath = destinationPath;
257+ if ([finalDestinationPath isKindOfClass: NSString .class] &&
258+ finalDestinationPath.length > 0 &&
259+ ![finalDestinationPath isEqualToString: destinationPath]) {
260+ NSURL *finalURL = [NSURL fileURLWithPath: finalDestinationPath];
261+ [NSFileManager .defaultManager createDirectoryAtURL: finalURL.URLByDeletingLastPathComponent
262+ withIntermediateDirectories: YES
263+ attributes: nil
264+ error: &error];
265+ if (error) {
266+ [NSFileManager .defaultManager removeItemAtPath: destinationPath error: nil ];
267+ return error;
268+ }
269+ [NSFileManager .defaultManager removeItemAtURL: finalURL error: nil ];
270+ if (![NSFileManager .defaultManager moveItemAtURL: destinationURL toURL: finalURL error: &error]) {
271+ [NSFileManager .defaultManager removeItemAtPath: destinationPath error: nil ];
272+ return error;
273+ }
274+ validationPath = finalDestinationPath;
275+ }
276+
242277 NSString *sha = [self currentDownload ][@" sha" ];
243- if ([sha isKindOfClass: NSString .class] && sha.length > 0 && ![self validateSHA: sha forFile: destinationPath ]) {
244- [NSFileManager .defaultManager removeItemAtPath: destinationPath error: nil ];
278+ if ([sha isKindOfClass: NSString .class] && sha.length > 0 && ![self validateSHA: sha forFile: validationPath ]) {
279+ [NSFileManager .defaultManager removeItemAtPath: validationPath error: nil ];
245280 return [NSError errorWithDomain: @" CurseForgeManualDownload"
246281 code: 1
247282 userInfo: @{NSLocalizedDescriptionKey :
248- [NSString stringWithFormat: @" SHA1 mismatch for %@ ." , destinationPath .lastPathComponent]}];
283+ [NSString stringWithFormat: @" SHA1 mismatch for %@ ." , validationPath .lastPathComponent]}];
249284 }
250285
251286 return nil ;
0 commit comments