source: trunk/macosx/BlocklistDownloader.m @ 13250

Last change on this file since 13250 was 13250, checked in by livings124, 10 years ago

replace a method with GCD calls

  • Property svn:keywords set to Date Rev Author Id
File size: 8.6 KB
Line 
1/******************************************************************************
2 * $Id: BlocklistDownloader.m 13250 2012-03-10 13:59:44Z livings124 $
3 *
4 * Copyright (c) 2008-2012 Transmission authors and contributors
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 *****************************************************************************/
24
25#import "BlocklistDownloader.h"
26#import "BlocklistDownloaderViewController.h"
27#import "BlocklistScheduler.h"
28#import "PrefsController.h"
29
30@interface BlocklistDownloader (Private)
31
32- (void) startDownload;
33- (void) decompressBlocklist;
34
35@end
36
37@implementation BlocklistDownloader
38
39BlocklistDownloader * fBLDownloader = nil;
40+ (BlocklistDownloader *) downloader
41{
42    if (!fBLDownloader)
43    {
44        fBLDownloader = [[BlocklistDownloader alloc] init];
45        [fBLDownloader startDownload];
46    }
47   
48    return fBLDownloader;
49}
50
51+ (BOOL) isRunning
52{
53    return fBLDownloader != nil;
54}
55
56- (void) setViewController: (BlocklistDownloaderViewController *) viewController
57{
58    fViewController = viewController;
59    if (fViewController)
60    {
61        switch (fState)
62        {
63            case BLOCKLIST_DL_START:
64                [fViewController setStatusStarting];
65                break;
66            case BLOCKLIST_DL_DOWNLOADING:
67                [fViewController setStatusProgressForCurrentSize: fCurrentSize expectedSize: fExpectedSize];
68                break;
69            case BLOCKLIST_DL_PROCESSING:
70                [fViewController setStatusProcessing];
71                break;
72        }
73    }
74}
75
76
77- (void) cancelDownload
78{
79    [fViewController setFinished];
80   
81    [fDownload cancel];
82   
83    [[BlocklistScheduler scheduler] updateSchedule];
84   
85    fBLDownloader = nil;
86}
87
88//using the actual filename is the best bet
89- (void) download: (NSURLDownload *) download decideDestinationWithSuggestedFilename: (NSString *) filename
90{
91    [fDownload setDestination: [NSTemporaryDirectory() stringByAppendingPathComponent: filename] allowOverwrite: NO];
92}
93
94- (void) download: (NSURLDownload *) download didCreateDestination: (NSString *) path
95{
96    fDestination = path;
97}
98
99- (void) download: (NSURLDownload *) download didReceiveResponse: (NSURLResponse *) response
100{
101    fState = BLOCKLIST_DL_DOWNLOADING;
102   
103    fCurrentSize = 0;
104    fExpectedSize = [response expectedContentLength];
105   
106    [fViewController setStatusProgressForCurrentSize: fCurrentSize expectedSize: fExpectedSize];
107}
108
109- (void) download: (NSURLDownload *) download didReceiveDataOfLength: (NSUInteger) length
110{
111    fCurrentSize += length;
112    [fViewController setStatusProgressForCurrentSize: fCurrentSize expectedSize: fExpectedSize];
113}
114
115- (void) download: (NSURLDownload *) download didFailWithError: (NSError *) error
116{
117    [fViewController setFailed: [error localizedDescription]];
118   
119    [[NSUserDefaults standardUserDefaults] setObject: [NSDate date] forKey: @"BlocklistNewLastUpdate"];
120    [[BlocklistScheduler scheduler] updateSchedule];
121   
122    fBLDownloader = nil;
123}
124
125- (void) downloadDidFinish: (NSURLDownload *) download
126{
127    fState = BLOCKLIST_DL_PROCESSING;
128   
129    [fViewController setStatusProcessing];
130   
131    //process data
132    NSAssert(fDestination != nil, @"the blocklist file destination has not been specified");
133   
134    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
135        [self decompressBlocklist];
136       
137        dispatch_async(dispatch_get_main_queue(), ^{
138            const int count = tr_blocklistSetContent([PrefsController handle], [fDestination UTF8String]);
139           
140            //delete downloaded file
141            [[NSFileManager defaultManager] removeItemAtPath: fDestination error: NULL];
142           
143            if (count > 0)
144                [fViewController setFinished];
145            else
146                [fViewController setFailed: NSLocalizedString(@"The specified blocklist file did not contain any valid rules.",
147                                                              "blocklist fail message")];
148           
149            //update last updated date for schedule
150            NSDate * date = [NSDate date];
151            [[NSUserDefaults standardUserDefaults] setObject: date forKey: @"BlocklistNewLastUpdate"];
152            [[NSUserDefaults standardUserDefaults] setObject: date forKey: @"BlocklistNewLastUpdateSuccess"];
153            [[BlocklistScheduler scheduler] updateSchedule];
154           
155            [[NSNotificationCenter defaultCenter] postNotificationName: @"BlocklistUpdated" object: nil];
156           
157            fBLDownloader = nil;
158        });
159    });
160}
161
162- (BOOL) download: (NSURLDownload *) download shouldDecodeSourceDataOfMIMEType: (NSString *) encodingType
163{
164    return YES;
165}
166
167@end
168
169@implementation BlocklistDownloader (Private)
170
171- (void) startDownload
172{
173    fState = BLOCKLIST_DL_START;
174   
175    [[BlocklistScheduler scheduler] cancelSchedule];
176   
177    NSString * urlString = [[NSUserDefaults standardUserDefaults] stringForKey: @"BlocklistURL"];
178    if (!urlString)
179        urlString = @"";
180    else if (![urlString isEqualToString: @""] && [urlString rangeOfString: @"://"].location == NSNotFound)
181        urlString = [@"http://" stringByAppendingString: urlString];
182   
183    NSURLRequest * request = [NSURLRequest requestWithURL: [NSURL URLWithString: urlString]];
184   
185    fDownload = [[NSURLDownload alloc] initWithRequest: request delegate: self];
186}
187
188//.gz, .tar.gz, .tgz, and .bgz will be decompressed by NSURLDownload for us. However, we have to do .zip files manually.
189- (void) decompressBlocklist
190{
191        if ([[[fDestination pathExtension] lowercaseString] isEqualToString: @"zip"]) {
192                BOOL success = NO;
193       
194        NSString * workingDirectory = [fDestination stringByDeletingLastPathComponent];
195               
196                //First, perform the actual unzipping
197                NSTask  * unzip = [[NSTask alloc] init];
198                [unzip setLaunchPath: @"/usr/bin/unzip"];
199                [unzip setCurrentDirectoryPath: workingDirectory];
200                [unzip setArguments: [NSArray arrayWithObjects:
201                                @"-o",  /* overwrite */
202                                @"-q", /* quiet! */
203                                fDestination, /* source zip file */
204                                @"-d", workingDirectory, /*destination*/
205                                nil]];
206               
207                @try
208                {
209                        [unzip launch];
210                        [unzip waitUntilExit];
211                       
212                        if ([unzip terminationStatus] == 0)
213                                success = YES;
214                }
215                @catch(id exc)
216                {
217                        success = NO;
218                }
219               
220                if (success) {
221                        //Now find out what file we actually extracted; don't just assume it matches the zipfile's name
222                        NSTask *zipinfo;
223                       
224                        zipinfo = [[NSTask alloc] init];
225                        [zipinfo setLaunchPath: @"/usr/bin/zipinfo"];
226                        [zipinfo setArguments: [NSArray arrayWithObjects:
227                                    @"-1",  /* just the filename */
228                                    fDestination, /* source zip file */
229                                    nil]];
230                        [zipinfo setStandardOutput: [NSPipe pipe]];
231                                               
232                        @try
233                        {
234                                NSFileHandle * zipinfoOutput = [[zipinfo standardOutput] fileHandleForReading];
235
236                                [zipinfo launch];
237                                [zipinfo waitUntilExit];
238                               
239                                NSString * actualFilename = [[NSString alloc] initWithData: [zipinfoOutput readDataToEndOfFile]
240                                                encoding: NSUTF8StringEncoding];
241                                actualFilename = [actualFilename stringByTrimmingCharactersInSet: [NSCharacterSet whitespaceAndNewlineCharacterSet]];
242                                NSString * newBlocklistPath = [workingDirectory stringByAppendingPathComponent: actualFilename];
243                               
244                                //Finally, delete the ZIP file; we're done with it, and we'll return the unzipped blocklist
245                                [[NSFileManager defaultManager] removeItemAtPath: fDestination error: NULL];
246               
247                fDestination = newBlocklistPath;
248                        }
249            @catch(id exc) {}
250                }               
251        }
252}
253
254@end
Note: See TracBrowser for help on using the repository browser.