source: trunk/macosx/BlocklistDownloader.m @ 13248

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

#4822 Enable Automatic Reference Counting

  • Property svn:keywords set to Date Rev Author Id
File size: 8.5 KB
Line 
1/******************************************************************************
2 * $Id: BlocklistDownloader.m 13248 2012-03-10 03:38:58Z 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- (void) finishDownloadSuccess;
35
36@end
37
38@implementation BlocklistDownloader
39
40BlocklistDownloader * fDownloader = nil;
41+ (BlocklistDownloader *) downloader
42{
43    if (!fDownloader)
44    {
45        fDownloader = [[BlocklistDownloader alloc] init];
46        [fDownloader startDownload];
47    }
48   
49    return fDownloader;
50}
51
52+ (BOOL) isRunning
53{
54    return fDownloader != nil;
55}
56
57- (void) setViewController: (BlocklistDownloaderViewController *) viewController
58{
59    fViewController = viewController;
60    if (fViewController)
61    {
62        switch (fState)
63        {
64            case BLOCKLIST_DL_START:
65                [fViewController setStatusStarting];
66                break;
67            case BLOCKLIST_DL_DOWNLOADING:
68                [fViewController setStatusProgressForCurrentSize: fCurrentSize expectedSize: fExpectedSize];
69                break;
70            case BLOCKLIST_DL_PROCESSING:
71                [fViewController setStatusProcessing];
72                break;
73        }
74    }
75}
76
77
78- (void) cancelDownload
79{
80    [fViewController setFinished];
81   
82    [fDownload cancel];
83   
84    [[BlocklistScheduler scheduler] updateSchedule];
85   
86    fDownloader = nil;
87}
88
89//using the actual filename is the best bet
90- (void) download: (NSURLDownload *) download decideDestinationWithSuggestedFilename: (NSString *) filename
91{
92    [fDownload setDestination: [NSTemporaryDirectory() stringByAppendingPathComponent: filename] allowOverwrite: NO];
93}
94
95- (void) download: (NSURLDownload *) download didCreateDestination: (NSString *) path
96{
97    fDestination = path;
98}
99
100- (void) download: (NSURLDownload *) download didReceiveResponse: (NSURLResponse *) response
101{
102    fState = BLOCKLIST_DL_DOWNLOADING;
103   
104    fCurrentSize = 0;
105    fExpectedSize = [response expectedContentLength];
106   
107    [fViewController setStatusProgressForCurrentSize: fCurrentSize expectedSize: fExpectedSize];
108}
109
110- (void) download: (NSURLDownload *) download didReceiveDataOfLength: (NSUInteger) length
111{
112    fCurrentSize += length;
113    [fViewController setStatusProgressForCurrentSize: fCurrentSize expectedSize: fExpectedSize];
114}
115
116- (void) download: (NSURLDownload *) download didFailWithError: (NSError *) error
117{
118    [fViewController setFailed: [error localizedDescription]];
119   
120    [[NSUserDefaults standardUserDefaults] setObject: [NSDate date] forKey: @"BlocklistNewLastUpdate"];
121    [[BlocklistScheduler scheduler] updateSchedule];
122   
123    fDownloader = nil;
124}
125
126- (void) downloadDidFinish: (NSURLDownload *) download
127{
128    fState = BLOCKLIST_DL_PROCESSING;
129    [self performSelectorInBackground: @selector(finishDownloadSuccess) withObject: nil];
130}
131
132- (BOOL) download: (NSURLDownload *) download shouldDecodeSourceDataOfMIMEType: (NSString *) encodingType
133{
134    return YES;
135}
136
137@end
138
139@implementation BlocklistDownloader (Private)
140
141- (void) startDownload
142{
143    fState = BLOCKLIST_DL_START;
144   
145    [[BlocklistScheduler scheduler] cancelSchedule];
146   
147    NSString * urlString = [[NSUserDefaults standardUserDefaults] stringForKey: @"BlocklistURL"];
148    if (!urlString)
149        urlString = @"";
150    else if (![urlString isEqualToString: @""] && [urlString rangeOfString: @"://"].location == NSNotFound)
151        urlString = [@"http://" stringByAppendingString: urlString];
152   
153    NSURLRequest * request = [NSURLRequest requestWithURL: [NSURL URLWithString: urlString]];
154   
155    fDownload = [[NSURLDownload alloc] initWithRequest: request delegate: self];
156}
157
158//.gz, .tar.gz, .tgz, and .bgz will be decompressed by NSURLDownload for us. However, we have to do .zip files manually.
159- (void) decompressBlocklist
160{
161        if ([[[fDestination pathExtension] lowercaseString] isEqualToString: @"zip"]) {
162                BOOL success = NO;
163       
164        NSString * workingDirectory = [fDestination stringByDeletingLastPathComponent];
165               
166                //First, perform the actual unzipping
167                NSTask  * unzip = [[NSTask alloc] init];
168                [unzip setLaunchPath: @"/usr/bin/unzip"];
169                [unzip setCurrentDirectoryPath: workingDirectory];
170                [unzip setArguments: [NSArray arrayWithObjects:
171                                @"-o",  /* overwrite */
172                                @"-q", /* quiet! */
173                                fDestination, /* source zip file */
174                                @"-d", workingDirectory, /*destination*/
175                                nil]];
176               
177                @try
178                {
179                        [unzip launch];
180                        [unzip waitUntilExit];
181                       
182                        if ([unzip terminationStatus] == 0)
183                                success = YES;
184                }
185                @catch(id exc)
186                {
187                        success = NO;
188                }
189               
190                if (success) {
191                        //Now find out what file we actually extracted; don't just assume it matches the zipfile's name
192                        NSTask *zipinfo;
193                       
194                        zipinfo = [[NSTask alloc] init];
195                        [zipinfo setLaunchPath: @"/usr/bin/zipinfo"];
196                        [zipinfo setArguments: [NSArray arrayWithObjects:
197                                    @"-1",  /* just the filename */
198                                    fDestination, /* source zip file */
199                                    nil]];
200                        [zipinfo setStandardOutput: [NSPipe pipe]];
201                                               
202                        @try
203                        {
204                                NSFileHandle * zipinfoOutput = [[zipinfo standardOutput] fileHandleForReading];
205
206                                [zipinfo launch];
207                                [zipinfo waitUntilExit];
208                               
209                                NSString * actualFilename = [[NSString alloc] initWithData: [zipinfoOutput readDataToEndOfFile]
210                                                encoding: NSUTF8StringEncoding];
211                                actualFilename = [actualFilename stringByTrimmingCharactersInSet: [NSCharacterSet whitespaceAndNewlineCharacterSet]];
212                                NSString * newBlocklistPath = [workingDirectory stringByAppendingPathComponent: actualFilename];
213                               
214                                //Finally, delete the ZIP file; we're done with it, and we'll return the unzipped blocklist
215                                [[NSFileManager defaultManager] removeItemAtPath: fDestination error: NULL];
216               
217                fDestination = newBlocklistPath;
218                        }
219            @catch(id exc) {}
220                }               
221        }
222}
223
224
225- (void) finishDownloadSuccess
226{
227    @autoreleasepool
228    {
229        [fViewController setStatusProcessing];
230       
231        //process data
232        NSAssert(fDestination != nil, @"the blocklist file destination has not been specified");
233       
234        [self decompressBlocklist];
235       
236        const int count = tr_blocklistSetContent([PrefsController handle], [fDestination UTF8String]);
237       
238        //delete downloaded file
239        [[NSFileManager defaultManager] removeItemAtPath: fDestination error: NULL];
240       
241        if (count > 0)
242            [fViewController setFinished];
243        else
244            [fViewController setFailed: NSLocalizedString(@"The specified blocklist file did not contain any valid rules.",
245                                            "blocklist fail message")];
246       
247        //update last updated date for schedule
248        NSDate * date = [NSDate date];
249        [[NSUserDefaults standardUserDefaults] setObject: date forKey: @"BlocklistNewLastUpdate"];
250        [[NSUserDefaults standardUserDefaults] setObject: date forKey: @"BlocklistNewLastUpdateSuccess"];
251        [[BlocklistScheduler scheduler] updateSchedule];
252       
253        [[NSNotificationCenter defaultCenter] postNotificationName: @"BlocklistUpdated" object: nil];
254    }
255   
256    fDownloader = nil;
257}
258
259@end
Note: See TracBrowser for help on using the repository browser.