Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 536 lines (446 sloc) 21.511 kb
9fa3da5 Holy restructuring, batman! Watch out for falling folders.
andym authored
1 //
2 // SUUpdater.m
3 // Sparkle
4 //
5 // Created by Andy Matuschak on 1/4/06.
6 // Copyright 2006 Andy Matuschak. All rights reserved.
7 //
8
9 #import "SUUpdater.h"
5aa1e18 Improved headers from Charles D. H. Williams.
andym authored
10
f815eec Andy Matuschak Fixes 243884
andymatuschak authored
11 #import "SUHost.h"
12 #import "SUUpdatePermissionPrompt.h"
13
14 #import "SUAutomaticUpdateDriver.h"
15 #import "SUProbingUpdateDriver.h"
16 #import "SUUserInitiatedUpdateDriver.h"
17 #import "SUScheduledUpdateDriver.h"
43a0a7d Uli Kusterer Merge of changes from SVN repository:
uliwitness authored
18 #import "SUConstants.h"
19 #import "SULog.h"
9cc1905 Kent Sutherland Use SCNetworkReachabilityCreateWithName rather than SCNetworkCheckReacha...
ksuther authored
20 #include <SystemConfiguration/SystemConfiguration.h>
43a0a7d Uli Kusterer Merge of changes from SVN repository:
uliwitness authored
21
f815eec Andy Matuschak Fixes 243884
andymatuschak authored
22
9fa3da5 Holy restructuring, batman! Watch out for falling folders.
andym authored
23 @interface SUUpdater (Private)
43a0a7d Uli Kusterer Merge of changes from SVN repository:
uliwitness authored
24 - (id)initForBundle:(NSBundle *)bundle;
91c242a Andy Matuschak Fixes Bug #312381: "Bundles can't ask for permission to update; develope...
andymatuschak authored
25 - (void)startUpdateCycle;
f815eec Andy Matuschak Fixes 243884
andymatuschak authored
26 - (void)checkForUpdatesWithDriver:(SUUpdateDriver *)updateDriver;
ec7f38d Andy Matuschak Fixes 258547
andymatuschak authored
27 - (BOOL)automaticallyDownloadsUpdates;
a55f11d Andy Matuschak Fixed 236240
andymatuschak authored
28 - (void)scheduleNextUpdateCheck;
98832c4 Andy Matuschak Beginnings of insane SUHost-based refactoring to get rid of NSBundle+Spa...
andymatuschak authored
29 - (void)registerAsObserver;
30 - (void)unregisterAsObserver;
31 - (void)updateDriverDidFinish:(NSNotification *)note;
1aea1b6 Andy Matuschak The Sparkle preference keys are now declared private / deprecated / allo...
andymatuschak authored
32 - (NSURL *)parameterizedFeedURL;
f6710e2 Uli Kusterer Sparkle now warns the delegate before and after it brings up a modal pan...
uliwitness authored
33
34 -(void) notifyWillShowAlert;
35 -(void) notifyDidShowAlert;
36
9fa3da5 Holy restructuring, batman! Watch out for falling folders.
andym authored
37 @end
38
39 @implementation SUUpdater
40
bbedfa1 Reorganized SUUpdater.m; it's in better order now.
andym authored
41 #pragma mark Initialization
42
98832c4 Andy Matuschak Beginnings of insane SUHost-based refactoring to get rid of NSBundle+Spa...
andymatuschak authored
43 static NSMutableDictionary *sharedUpdaters = nil;
d7774c0 performed a code review, specifically:
Sean McBride authored
44 static NSString * const SUUpdaterDefaultsObservationContext = @"SUUpdaterDefaultsObservationContext";
5b76530 Made a number of fixes to potentially dangerous singleton behavior as su...
andym authored
45
bbedfa1 Reorganized SUUpdater.m; it's in better order now.
andym authored
46 + (SUUpdater *)sharedUpdater
9fa3da5 Holy restructuring, batman! Watch out for falling folders.
andym authored
47 {
98832c4 Andy Matuschak Beginnings of insane SUHost-based refactoring to get rid of NSBundle+Spa...
andymatuschak authored
48 return [self updaterForBundle:[NSBundle mainBundle]];
63011aa Beware of falling bricks! Huge refactoring commit #1: cleansing Sparkle ...
andym authored
49 }
50
98832c4 Andy Matuschak Beginnings of insane SUHost-based refactoring to get rid of NSBundle+Spa...
andymatuschak authored
51 // SUUpdater has a singleton for each bundle. We use the fact that NSBundle instances are also singletons, so we can use them as keys. If you don't trust that you can also use the identifier as key
52 + (SUUpdater *)updaterForBundle:(NSBundle *)bundle
53 {
54 if (bundle == nil) bundle = [NSBundle mainBundle];
55 id updater = [sharedUpdaters objectForKey:[NSValue valueWithNonretainedObject:bundle]];
56 if (updater == nil)
36b7d43 fixed extra ref count, half of bug #502212
Sean McBride authored
57 updater = [[[[self class] alloc] initForBundle:bundle] autorelease];
98832c4 Andy Matuschak Beginnings of insane SUHost-based refactoring to get rid of NSBundle+Spa...
andymatuschak authored
58 return updater;
59 }
60
61 // This is the designated initializer for SUUpdater, important for subclasses
43a0a7d Uli Kusterer Merge of changes from SVN repository:
uliwitness authored
62 - (id)initForBundle:(NSBundle *)bundle
63011aa Beware of falling bricks! Huge refactoring commit #1: cleansing Sparkle ...
andym authored
63 {
5bf76dd Oops! Committed the last patch with broken code; this code works.
andym authored
64 self = [super init];
98832c4 Andy Matuschak Beginnings of insane SUHost-based refactoring to get rid of NSBundle+Spa...
andymatuschak authored
65 if (bundle == nil) bundle = [NSBundle mainBundle];
561bbbe Andy Matuschak Because of the way Sparkle forces SUUpdaters to be per-bundle singletons...
andymatuschak authored
66
67 // Register as observer straight away to avoid exceptions on -dealloc when -unregisterAsObserver is called:
68 if (self)
69 [self registerAsObserver];
70
98832c4 Andy Matuschak Beginnings of insane SUHost-based refactoring to get rid of NSBundle+Spa...
andymatuschak authored
71 id updater = [sharedUpdaters objectForKey:[NSValue valueWithNonretainedObject:bundle]];
72 if (updater)
2ec35ae Finished cleaning up singleton stuff in SUUpdater.m
andym authored
73 {
74 [self release];
98832c4 Andy Matuschak Beginnings of insane SUHost-based refactoring to get rid of NSBundle+Spa...
andymatuschak authored
75 self = [updater retain];
2ec35ae Finished cleaning up singleton stuff in SUUpdater.m
andym authored
76 }
98832c4 Andy Matuschak Beginnings of insane SUHost-based refactoring to get rid of NSBundle+Spa...
andymatuschak authored
77 else if (self)
5bf76dd Oops! Committed the last patch with broken code; this code works.
andym authored
78 {
98832c4 Andy Matuschak Beginnings of insane SUHost-based refactoring to get rid of NSBundle+Spa...
andymatuschak authored
79 if (sharedUpdaters == nil)
80 sharedUpdaters = [[NSMutableDictionary alloc] init];
81 [sharedUpdaters setObject:self forKey:[NSValue valueWithNonretainedObject:bundle]];
82 host = [[SUHost alloc] initWithBundle:bundle];
d62e47c Andy Matuschak Fixing Bug #416798: "Sparkle should warn developers if the app has no pu...
andymatuschak authored
83
d0b802e Uli Kusterer Added preprocessor defines to SUConstants.h for turning on/off DSA and d...
uliwitness authored
84 #if !ENDANGER_USERS_WITH_INSECURE_UPDATES
d62e47c Andy Matuschak Fixing Bug #416798: "Sparkle should warn developers if the app has no pu...
andymatuschak authored
85 // Saving-the-developer-from-a-stupid-mistake-check:
86 if (![[[self feedURL] scheme] isEqualToString:@"https"] && ![host publicDSAKey])
f6710e2 Uli Kusterer Sparkle now warns the delegate before and after it brings up a modal pan...
uliwitness authored
87 {
88 [self notifyWillShowModalAlert];
d62e47c Andy Matuschak Fixing Bug #416798: "Sparkle should warn developers if the app has no pu...
andymatuschak authored
89 NSRunAlertPanel(@"Insecure update error!", @"For security reasons, you need to distribute your appcast over SSL or sign your updates. See Sparkle's documentation for more information.", @"OK", nil, nil);
f6710e2 Uli Kusterer Sparkle now warns the delegate before and after it brings up a modal pan...
uliwitness authored
90 [self notifyDidShowModalAlert];
91 }
43a0a7d Uli Kusterer Merge of changes from SVN repository:
uliwitness authored
92 #endif
91c242a Andy Matuschak Fixes Bug #312381: "Bundles can't ask for permission to update; develope...
andymatuschak authored
93 // This runs the permission prompt if needed, but never before the app has finished launching because the runloop won't run before that
94 [self performSelector:@selector(startUpdateCycle) withObject:nil afterDelay:0];
87f2893 Fixed warnings for missing newlines at the end of the file.
andym authored
95 }
5e05339 #76 Support for Plug-ins
catlan authored
96 return self;
97 }
98
f6710e2 Uli Kusterer Sparkle now warns the delegate before and after it brings up a modal pan...
uliwitness authored
99
98832c4 Andy Matuschak Beginnings of insane SUHost-based refactoring to get rid of NSBundle+Spa...
andymatuschak authored
100 // This will be used when the updater is instantiated in a nib such as MainMenu
101 - (id)init
102 {
103 return [self initForBundle:[NSBundle mainBundle]];
104 }
105
43a0a7d Uli Kusterer Merge of changes from SVN repository:
uliwitness authored
106 - (NSString *)description { return [NSString stringWithFormat:@"%@ <%@, %@>", [self class], [host bundlePath], [host installationPath]]; }
c386b70 Andy Matuschak Partial fix for 245277: basic descriptions for some Sparkle classes. Tha...
andymatuschak authored
107
f6710e2 Uli Kusterer Sparkle now warns the delegate before and after it brings up a modal pan...
uliwitness authored
108
109 -(void) notifyWillShowModalAlert
110 {
111 if( [delegate respondsToSelector: @selector(updaterWillShowModalAlert:)] )
112 [delegate updaterWillShowModalAlert: self];
113 }
114
115
116 -(void) notifyDidShowModalAlert
117 {
118 if( [delegate respondsToSelector: @selector(updaterDidShowModalAlert:)] )
119 [delegate updaterDidShowModalAlert: self];
120 }
121
122
91c242a Andy Matuschak Fixes Bug #312381: "Bundles can't ask for permission to update; develope...
andymatuschak authored
123 - (void)startUpdateCycle
9fa3da5 Holy restructuring, batman! Watch out for falling folders.
andym authored
124 {
98832c4 Andy Matuschak Beginnings of insane SUHost-based refactoring to get rid of NSBundle+Spa...
andymatuschak authored
125 BOOL shouldPrompt = NO;
126
127 // If the user has been asked about automatic checks, don't bother prompting
128 if ([host objectForUserDefaultsKey:SUEnableAutomaticChecksKey])
129 {
130 shouldPrompt = NO;
131 }
132 // Does the delegate want to take care of the logic for when we should ask permission to update?
b3f3944 Andy Matuschak Fixes 244857
andymatuschak authored
133 else if ([delegate respondsToSelector:@selector(updaterShouldPromptForPermissionToCheckForUpdates:)])
98832c4 Andy Matuschak Beginnings of insane SUHost-based refactoring to get rid of NSBundle+Spa...
andymatuschak authored
134 {
b3f3944 Andy Matuschak Fixes 244857
andymatuschak authored
135 shouldPrompt = [delegate updaterShouldPromptForPermissionToCheckForUpdates:self];
98832c4 Andy Matuschak Beginnings of insane SUHost-based refactoring to get rid of NSBundle+Spa...
andymatuschak authored
136 }
137 // Has he been asked already? And don't ask if the host has a default value set in its Info.plist.
5b38483 Andy Matuschak Fixes 245723
andymatuschak authored
138 else if ([host objectForKey:SUEnableAutomaticChecksKey] == nil)
98832c4 Andy Matuschak Beginnings of insane SUHost-based refactoring to get rid of NSBundle+Spa...
andymatuschak authored
139 {
140 if ([host objectForUserDefaultsKey:SUEnableAutomaticChecksKeyOld])
1aea1b6 Andy Matuschak The Sparkle preference keys are now declared private / deprecated / allo...
andymatuschak authored
141 [self setAutomaticallyChecksForUpdates:[host boolForUserDefaultsKey:SUEnableAutomaticChecksKeyOld]];
98832c4 Andy Matuschak Beginnings of insane SUHost-based refactoring to get rid of NSBundle+Spa...
andymatuschak authored
142 // Now, we don't want to ask the user for permission to do a weird thing on the first launch.
143 // We wait until the second launch.
144 else if ([host boolForUserDefaultsKey:SUHasLaunchedBeforeKey] == NO)
145 [host setBool:YES forUserDefaultsKey:SUHasLaunchedBeforeKey];
146 else
147 shouldPrompt = YES;
148 }
149
150 if (shouldPrompt)
151 {
4da902b Andy Matuschak Fixes 251968
andymatuschak authored
152 NSArray *profileInfo = [host systemProfile];
f95cf64 Andy Matuschak A little cleanup on bricooke's patch.
andymatuschak authored
153 // Always say we're sending the system profile here so that the delegate displays the parameters it would send.
827c6ad when about to show the user what will be anonymously sent, make sure the...
Brian Cooke authored
154 if ([delegate respondsToSelector:@selector(feedParametersForUpdater:sendingSystemProfile:)])
155 profileInfo = [profileInfo arrayByAddingObjectsFromArray:[delegate feedParametersForUpdater:self sendingSystemProfile:YES]];
4da902b Andy Matuschak Fixes 251968
andymatuschak authored
156 [SUUpdatePermissionPrompt promptWithHost:host systemProfile:profileInfo delegate:self];
98832c4 Andy Matuschak Beginnings of insane SUHost-based refactoring to get rid of NSBundle+Spa...
andymatuschak authored
157 // We start the update checks and register as observer for changes after the prompt finishes
9fa3da5 Holy restructuring, batman! Watch out for falling folders.
andym authored
158 }
98832c4 Andy Matuschak Beginnings of insane SUHost-based refactoring to get rid of NSBundle+Spa...
andymatuschak authored
159 else
160 {
161 // We check if the user's said they want updates, or they haven't said anything, and the default is set to checking.
162 [self scheduleNextUpdateCheck];
163 }
8c3960f Finished integrating SparklePlus profiling! Just set SUEnableSystemProfi...
andym authored
164 }
165
166 - (void)updatePermissionPromptFinishedWithResult:(SUPermissionPromptResult)result
167 {
1aea1b6 Andy Matuschak The Sparkle preference keys are now declared private / deprecated / allo...
andymatuschak authored
168 [self setAutomaticallyChecksForUpdates:(result == SUAutomaticallyCheck)];
98832c4 Andy Matuschak Beginnings of insane SUHost-based refactoring to get rid of NSBundle+Spa...
andymatuschak authored
169 // Schedule checks, but make sure we ignore the delayed call from KVO
ac4e4e4 Andy Matuschak Fixes 245991
andymatuschak authored
170 [self resetUpdateCycle];
98832c4 Andy Matuschak Beginnings of insane SUHost-based refactoring to get rid of NSBundle+Spa...
andymatuschak authored
171 }
172
173 - (void)updateDriverDidFinish:(NSNotification *)note
174 {
175 if ([note object] == driver && [driver finished])
176 {
177 [driver release]; driver = nil;
178 [self scheduleNextUpdateCheck];
179 }
8c3960f Finished integrating SparklePlus profiling! Just set SUEnableSystemProfi...
andym authored
180 }
181
42cda2d Andy Matuschak Fixes 259062
andymatuschak authored
182 - (NSDate *)lastUpdateCheckDate
c71bf3c Provide getter for SULastCheckTimeKey
Peter Speck authored
183 {
184 return [host objectForUserDefaultsKey:SULastCheckTimeKey];
185 }
186
a55f11d Andy Matuschak Fixed 236240
andymatuschak authored
187 - (void)scheduleNextUpdateCheck
ebb1f01 Andy Matuschak Removed the checkInterval IV and factored out its assignment to a checkI...
andymatuschak authored
188 {
4b6fc55 Andy Matuschak Removed unnecessary @synchronized's.
andymatuschak authored
189 if (checkTimer)
a55f11d Andy Matuschak Fixed 236240
andymatuschak authored
190 {
4b6fc55 Andy Matuschak Removed unnecessary @synchronized's.
andymatuschak authored
191 [checkTimer invalidate];
43a0a7d Uli Kusterer Merge of changes from SVN repository:
uliwitness authored
192 [checkTimer release]; // UK 2009-03-16 Timer is non-repeating, may have invalidated itself, so we had to retain it.
4b6fc55 Andy Matuschak Removed unnecessary @synchronized's.
andymatuschak authored
193 checkTimer = nil;
a55f11d Andy Matuschak Fixed 236240
andymatuschak authored
194 }
1aea1b6 Andy Matuschak The Sparkle preference keys are now declared private / deprecated / allo...
andymatuschak authored
195 if (![self automaticallyChecksForUpdates]) return;
a55f11d Andy Matuschak Fixed 236240
andymatuschak authored
196
8c3960f Finished integrating SparklePlus profiling! Just set SUEnableSystemProfi...
andym authored
197 // How long has it been since last we checked for an update?
c71bf3c Provide getter for SULastCheckTimeKey
Peter Speck authored
198 NSDate *lastCheckDate = [self lastUpdateCheckDate];
8c3960f Finished integrating SparklePlus profiling! Just set SUEnableSystemProfi...
andym authored
199 if (!lastCheckDate) { lastCheckDate = [NSDate distantPast]; }
200 NSTimeInterval intervalSinceCheck = [[NSDate date] timeIntervalSinceDate:lastCheckDate];
201
202 // Now we want to figure out how long until we check again.
c21e1ab Andy Matuschak Fixes 258529 and 257967
andymatuschak authored
203 NSTimeInterval delayUntilCheck, updateCheckInterval = [self updateCheckInterval];
204 if (updateCheckInterval < SU_MIN_CHECK_INTERVAL)
205 updateCheckInterval = SU_MIN_CHECK_INTERVAL;
206 if (intervalSinceCheck < updateCheckInterval)
207 delayUntilCheck = (updateCheckInterval - intervalSinceCheck); // It hasn't been long enough.
8c3960f Finished integrating SparklePlus profiling! Just set SUEnableSystemProfi...
andym authored
208 else
209 delayUntilCheck = 0; // We're overdue! Run one now.
43a0a7d Uli Kusterer Merge of changes from SVN repository:
uliwitness authored
210 checkTimer = [[NSTimer scheduledTimerWithTimeInterval:delayUntilCheck target:self selector:@selector(checkForUpdatesInBackground) userInfo:nil repeats:NO] retain]; // UK 2009-03-16 Timer is non-repeating, may have invalidated itself, so we had to retain it.
211 }
212
213
214 -(void) putFeedURLIntoDictionary: (NSMutableDictionary*)theDict // You release this.
215 {
216 [theDict setObject: [self feedURL] forKey: @"feedURL"];
217 }
218
219 -(void) checkForUpdatesInBgReachabilityCheckWithDriver: (SUUpdateDriver*)inDriver /* RUNS ON ITS OWN THREAD */
220 {
221 NS_DURING
222 // This method *must* be called on its own thread. SCNetworkReachabilityCheckByName
223 // can block, and it can be waiting a long time on slow networks, and we
224 // wouldn't want to beachball the main thread for a background operation.
225 // We could use asynchronous reachability callbacks, but those aren't
226 // reliable enough and can 'get lost' sometimes, which we don't want.
227
228 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
229 SCNetworkConnectionFlags flags = 0;
230 BOOL isNetworkReachable = YES;
231
232 // Don't perform automatic checks on unconnected laptops or dial-up connections that aren't online:
233 NSMutableDictionary* theDict = [NSMutableDictionary dictionary];
234 [self performSelectorOnMainThread: @selector(putFeedURLIntoDictionary:) withObject: theDict waitUntilDone: YES]; // Get feed URL on main thread, it's not safe to call elsewhere.
9cc1905 Kent Sutherland Use SCNetworkReachabilityCreateWithName rather than SCNetworkCheckReacha...
ksuther authored
235
236 const char *hostname = [[[theDict objectForKey: @"feedURL"] host] cStringUsingEncoding: NSUTF8StringEncoding];
237 SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithName(NULL, hostname);
238 Boolean reachabilityResult = SCNetworkReachabilityGetFlags(reachability, &flags);
239 CFRelease(reachability);
240
241 if( reachabilityResult )
43a0a7d Uli Kusterer Merge of changes from SVN repository:
uliwitness authored
242 {
243 BOOL reachable = (flags & kSCNetworkFlagsReachable) == kSCNetworkFlagsReachable;
244 BOOL automatic = (flags & kSCNetworkFlagsConnectionAutomatic) == kSCNetworkFlagsConnectionAutomatic;
245 BOOL local = (flags & kSCNetworkFlagsIsLocalAddress) == kSCNetworkFlagsIsLocalAddress;
246
247 //NSLog(@"reachable = %s, automatic = %s, local = %s", (reachable?"YES":"NO"), (automatic?"YES":"NO"), (local?"YES":"NO"));
248
249 if( !(reachable || automatic || local) )
250 isNetworkReachable = NO;
251 }
252
253 if( isNetworkReachable )
254 {
255 [self performSelectorOnMainThread: @selector(checkForUpdatesWithDriver:) withObject: inDriver waitUntilDone: NO];
256 }
257
258 [pool release];
259 NS_HANDLER
4f8d745 Uli Kusterer Changed a few NSLogs() to SULogs().
uliwitness authored
260 SULog(@"UNCAUGHT EXCEPTION IN UPDATE CHECK TIMER: %@",[localException reason]);
43a0a7d Uli Kusterer Merge of changes from SVN repository:
uliwitness authored
261 // Don't propagate the exception beyond here. In Carbon apps that would trash the stack.
262 NS_ENDHANDLER
dc147ec Continued incremental refactoring; things seem to still be holding toget...
andym authored
263 }
264
43a0a7d Uli Kusterer Merge of changes from SVN repository:
uliwitness authored
265
bc3be9a Touched practically every line of code in a super-monster-awesome refact...
andym authored
266 - (void)checkForUpdatesInBackground
dc147ec Continued incremental refactoring; things seem to still be holding toget...
andym authored
267 {
43a0a7d Uli Kusterer Merge of changes from SVN repository:
uliwitness authored
268 if( [delegate respondsToSelector: @selector(updaterMayCheckForUpdates:)] && ![delegate updaterMayCheckForUpdates: self] )
269 {
270 [self scheduleNextUpdateCheck];
271 return;
272 }
273
274 // Background update checks should only happen if we have a network connection.
275 // Wouldn't want to annoy users on dial-up by establishing a connection every
276 // hour or so:
277 SUUpdateDriver * theUpdateDriver = [[[([self automaticallyDownloadsUpdates] ? [SUAutomaticUpdateDriver class] : [SUScheduledUpdateDriver class]) alloc] initWithUpdater:self] autorelease];
9b5b541 Fix for Sparkle crasher in scheduleNextUpdateCheck. Originally by lapcat...
Simone Manganelli authored
278
43a0a7d Uli Kusterer Merge of changes from SVN repository:
uliwitness authored
279 [NSThread detachNewThreadSelector: @selector(checkForUpdatesInBgReachabilityCheckWithDriver:) toTarget: self withObject: theUpdateDriver];
dc147ec Continued incremental refactoring; things seem to still be holding toget...
andym authored
280 }
281
43a0a7d Uli Kusterer Merge of changes from SVN repository:
uliwitness authored
282
ba6c3b6 Andy Matuschak Cleaned up SUUpdater.h
andymatuschak authored
283 - (BOOL)mayUpdateAndRestart
43a0a7d Uli Kusterer Merge of changes from SVN repository:
uliwitness authored
284 {
285 return( !delegate || ![delegate respondsToSelector: @selector(updaterShouldRelaunchApplication:)] || [delegate updaterShouldRelaunchApplication: self] );
286 }
287
288 - (IBAction)checkForUpdates: (id)sender
9fa3da5 Holy restructuring, batman! Watch out for falling folders.
andym authored
289 {
7b39268 Andy Matuschak No longer fragile-ly using class method singletons to get to the updater...
andymatuschak authored
290 [self checkForUpdatesWithDriver:[[[SUUserInitiatedUpdateDriver alloc] initWithUpdater:self] autorelease]];
9fa3da5 Holy restructuring, batman! Watch out for falling folders.
andym authored
291 }
292
f815eec Andy Matuschak Fixes 243884
andymatuschak authored
293 - (void)checkForUpdateInformation
294 {
7b39268 Andy Matuschak No longer fragile-ly using class method singletons to get to the updater...
andymatuschak authored
295 [self checkForUpdatesWithDriver:[[[SUProbingUpdateDriver alloc] initWithUpdater:self] autorelease]];
f815eec Andy Matuschak Fixes 243884
andymatuschak authored
296 }
297
bc3be9a Touched practically every line of code in a super-monster-awesome refact...
andym authored
298 - (void)checkForUpdatesWithDriver:(SUUpdateDriver *)d
9fa3da5 Holy restructuring, batman! Watch out for falling folders.
andym authored
299 {
bc3be9a Touched practically every line of code in a super-monster-awesome refact...
andym authored
300 if ([self updateInProgress]) { return; }
43a0a7d Uli Kusterer Merge of changes from SVN repository:
uliwitness authored
301 if (checkTimer) { [checkTimer invalidate]; [checkTimer release]; checkTimer = nil; } // UK 2009-03-16 Timer is non-repeating, may have invalidated itself, so we had to retain it.
302
303 SUClearLog();
304 SULog( @"===== %@ =====", [[NSFileManager defaultManager] displayNameAtPath: [[NSBundle mainBundle] bundlePath]] );
1aea1b6 Andy Matuschak The Sparkle preference keys are now declared private / deprecated / allo...
andymatuschak authored
305
42cda2d Andy Matuschak Fixes 259062
andymatuschak authored
306 [self willChangeValueForKey:@"lastUpdateCheckDate"];
307 [host setObject:[NSDate date] forUserDefaultsKey:SULastCheckTimeKey];
308 [self didChangeValueForKey:@"lastUpdateCheckDate"];
309
bc3be9a Touched practically every line of code in a super-monster-awesome refact...
andym authored
310 driver = [d retain];
43a0a7d Uli Kusterer Merge of changes from SVN repository:
uliwitness authored
311 NSURL* theFeedURL = [self parameterizedFeedURL];
312 if( theFeedURL ) // Use a NIL URL to cancel quietly.
313 [driver checkForUpdatesAtURL: theFeedURL host:host];
314 else
315 [driver abortUpdate];
9fa3da5 Holy restructuring, batman! Watch out for falling folders.
andym authored
316 }
317
98832c4 Andy Matuschak Beginnings of insane SUHost-based refactoring to get rid of NSBundle+Spa...
andymatuschak authored
318 - (void)registerAsObserver
6a7c8b3 Substantial changes made to how Sparkle works on startup now. SUCheckAtS...
andym authored
319 {
98832c4 Andy Matuschak Beginnings of insane SUHost-based refactoring to get rid of NSBundle+Spa...
andymatuschak authored
320 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(updateDriverDidFinish:) name:SUUpdateDriverFinishedNotification object:nil];
321 [[NSUserDefaultsController sharedUserDefaultsController] addObserver:self forKeyPath:[@"values." stringByAppendingString:SUScheduledCheckIntervalKey] options:0 context:SUUpdaterDefaultsObservationContext];
322 [[NSUserDefaultsController sharedUserDefaultsController] addObserver:self forKeyPath:[@"values." stringByAppendingString:SUEnableAutomaticChecksKey] options:0 context:SUUpdaterDefaultsObservationContext];
323 }
324
325 - (void)unregisterAsObserver
326 {
327 @try
a55f11d Andy Matuschak Fixed 236240
andymatuschak authored
328 {
fba7231 Andy Matuschak We used to not register SUUpdater as an observer of the shared user defa...
andymatuschak authored
329 [[NSNotificationCenter defaultCenter] removeObserver:self];
98832c4 Andy Matuschak Beginnings of insane SUHost-based refactoring to get rid of NSBundle+Spa...
andymatuschak authored
330 [[NSUserDefaultsController sharedUserDefaultsController] removeObserver:self forKeyPath:[@"values." stringByAppendingString:SUScheduledCheckIntervalKey]];
331 [[NSUserDefaultsController sharedUserDefaultsController] removeObserver:self forKeyPath:[@"values." stringByAppendingString:SUEnableAutomaticChecksKey]];
a55f11d Andy Matuschak Fixed 236240
andymatuschak authored
332 }
fba7231 Andy Matuschak We used to not register SUUpdater as an observer of the shared user defa...
andymatuschak authored
333 @catch (NSException *e)
334 {
335 NSLog(@"Sparkle Error: [SUUpdater unregisterAsObserver] called, but the updater wasn't registered as an observer.");
336 }
98832c4 Andy Matuschak Beginnings of insane SUHost-based refactoring to get rid of NSBundle+Spa...
andymatuschak authored
337 }
338
339 - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
340 {
341 if (context == SUUpdaterDefaultsObservationContext)
342 {
343 // Allow a small delay, because perhaps the user or developer wants to change both preferences. This allows the developer to interpret a zero check interval as a sign to disable automatic checking.
344 // Or we may get this from the developer and from our own KVO observation, this will effectively coalesce them.
ac4e4e4 Andy Matuschak Fixes 245991
andymatuschak authored
345 [[self class] cancelPreviousPerformRequestsWithTarget:self selector:@selector(resetUpdateCycle) object:nil];
f9dda21 Andy Matuschak Fixes 255399
andymatuschak authored
346 [self performSelector:@selector(resetUpdateCycle) withObject:nil afterDelay:1];
98832c4 Andy Matuschak Beginnings of insane SUHost-based refactoring to get rid of NSBundle+Spa...
andymatuschak authored
347 }
348 else
349 {
350 [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
351 }
a55f11d Andy Matuschak Fixed 236240
andymatuschak authored
352 }
353
ac4e4e4 Andy Matuschak Fixes 245991
andymatuschak authored
354 - (void)resetUpdateCycle
a55f11d Andy Matuschak Fixed 236240
andymatuschak authored
355 {
ac4e4e4 Andy Matuschak Fixes 245991
andymatuschak authored
356 [[self class] cancelPreviousPerformRequestsWithTarget:self selector:@selector(resetUpdateCycle) object:nil];
98832c4 Andy Matuschak Beginnings of insane SUHost-based refactoring to get rid of NSBundle+Spa...
andymatuschak authored
357 [self scheduleNextUpdateCheck];
1c1bb3a #77 SUIgnoreChecks to ignore update, needed for Sparkle in large deploym...
catlan authored
358 }
359
1aea1b6 Andy Matuschak The Sparkle preference keys are now declared private / deprecated / allo...
andymatuschak authored
360 - (void)setAutomaticallyChecksForUpdates:(BOOL)automaticallyCheckForUpdates
361 {
362 [host setBool:automaticallyCheckForUpdates forUserDefaultsKey:SUEnableAutomaticChecksKey];
c21e1ab Andy Matuschak Fixes 258529 and 257967
andymatuschak authored
363 // Hack to support backwards compatibility with older Sparkle versions, which supported
364 // disabling updates by setting the check interval to 0.
365 if (automaticallyCheckForUpdates && [self updateCheckInterval] == 0)
366 [self setUpdateCheckInterval:SU_DEFAULT_CHECK_INTERVAL];
367 [[self class] cancelPreviousPerformRequestsWithTarget:self selector:@selector(resetUpdateCycle) object:nil];
368 // Provide a small delay in case multiple preferences are being updated simultaneously.
369 [self performSelector:@selector(resetUpdateCycle) withObject:nil afterDelay:1];
1aea1b6 Andy Matuschak The Sparkle preference keys are now declared private / deprecated / allo...
andymatuschak authored
370 }
371
372 - (BOOL)automaticallyChecksForUpdates
49cfd57 Andy Matuschak Fixed a confounding bug that somehow slipped in: when an update check wa...
andymatuschak authored
373 {
c21e1ab Andy Matuschak Fixes 258529 and 257967
andymatuschak authored
374 // Don't automatically update when the check interval is 0, to be compatible with 1.1 settings.
375 if ([self updateCheckInterval] == 0)
376 return NO;
ec7f38d Andy Matuschak Fixes 258547
andymatuschak authored
377 return [host boolForKey:SUEnableAutomaticChecksKey];
49cfd57 Andy Matuschak Fixed a confounding bug that somehow slipped in: when an update check wa...
andymatuschak authored
378 }
379
ec7f38d Andy Matuschak Fixes 258547
andymatuschak authored
380 - (void)setAutomaticallyDownloadsUpdates:(BOOL)automaticallyUpdates
381 {
382 [host setBool:automaticallyUpdates forUserDefaultsKey:SUAutomaticallyUpdateKey];
383 }
384
385 - (BOOL)automaticallyDownloadsUpdates
9fa3da5 Holy restructuring, batman! Watch out for falling folders.
andym authored
386 {
387 // If the SUAllowsAutomaticUpdatesKey exists and is set to NO, return NO.
98832c4 Andy Matuschak Beginnings of insane SUHost-based refactoring to get rid of NSBundle+Spa...
andymatuschak authored
388 if ([host objectForInfoDictionaryKey:SUAllowsAutomaticUpdatesKey] && [host boolForInfoDictionaryKey:SUAllowsAutomaticUpdatesKey] == NO)
6a7c8b3 Substantial changes made to how Sparkle works on startup now. SUCheckAtS...
andym authored
389 return NO;
9fa3da5 Holy restructuring, batman! Watch out for falling folders.
andym authored
390
ec7f38d Andy Matuschak Fixes 258547
andymatuschak authored
391 // Otherwise, automatically downloading updates is allowed. Does the user want it?
392 return [host boolForUserDefaultsKey:SUAutomaticallyUpdateKey];
9fa3da5 Holy restructuring, batman! Watch out for falling folders.
andym authored
393 }
394
1aea1b6 Andy Matuschak The Sparkle preference keys are now declared private / deprecated / allo...
andymatuschak authored
395 - (void)setFeedURL:(NSURL *)feedURL
396 {
397 [host setObject:[feedURL absoluteString] forUserDefaultsKey:SUFeedURLKey];
398 }
399
43a0a7d Uli Kusterer Merge of changes from SVN repository:
uliwitness authored
400 - (NSURL *)feedURL // *** MUST BE CALLED ON MAIN THREAD ***
645a96e Made a good deal more progress integrating the profile checking features...
andym authored
401 {
b2145b6 Andy Matuschak Killed NSURL+Parameters and moved the relevant code into SUUpdater.
andymatuschak authored
402 // A value in the user defaults overrides one in the Info.plist (so preferences panels can be created wherein users choose between beta / release feeds).
5b38483 Andy Matuschak Fixes 245723
andymatuschak authored
403 NSString *appcastString = [host objectForKey:SUFeedURLKey];
43a0a7d Uli Kusterer Merge of changes from SVN repository:
uliwitness authored
404 if( [delegate respondsToSelector: @selector(feedURLStringForUpdater:)] )
405 appcastString = [delegate feedURLStringForUpdater: self];
b2145b6 Andy Matuschak Killed NSURL+Parameters and moved the relevant code into SUUpdater.
andymatuschak authored
406 if (!appcastString) // Can't find an appcast string!
ffc44bb Fraser Speirs Added a space in the description of the SUNoFeedURL exception becuase it...
fspeirs authored
407 [NSException raise:@"SUNoFeedURL" format:@"You must specify the URL of the appcast as the SUFeedURL key in either the Info.plist or the user defaults!"];
b2145b6 Andy Matuschak Killed NSURL+Parameters and moved the relevant code into SUUpdater.
andymatuschak authored
408 NSCharacterSet* quoteSet = [NSCharacterSet characterSetWithCharactersInString: @"\"\'"]; // Some feed publishers add quotes; strip 'em.
43a0a7d Uli Kusterer Merge of changes from SVN repository:
uliwitness authored
409 NSString* castUrlStr = [appcastString stringByTrimmingCharactersInSet:quoteSet];
410 if( !castUrlStr || [castUrlStr length] == 0 )
411 return nil;
412 else
413 return [NSURL URLWithString: castUrlStr];
b2145b6 Andy Matuschak Killed NSURL+Parameters and moved the relevant code into SUUpdater.
andymatuschak authored
414 }
415
dfe0eff Mark Rowe Provide the ability to set a custom user agent string on all HTTP reques...
bdash authored
416 - (void)setUserAgentString:(NSString *)userAgent
417 {
418 if (customUserAgentString == userAgent)
419 return;
420
421 [customUserAgentString release];
422 customUserAgentString = [userAgent copy];
423 }
424
425 - (NSString *)userAgentString
426 {
427 if (customUserAgentString)
428 return customUserAgentString;
429
a032358 Andy Matuschak Removing GNU-style ?: operators. Thanks for the report, Uli.
andymatuschak authored
430 NSString *version = [SPARKLE_BUNDLE objectForInfoDictionaryKey:@"CFBundleVersion"];
431 NSString *userAgent = [NSString stringWithFormat:@"%@/%@ Sparkle/%@", [host name], [host displayVersion], version ? version : @"?"];
dfe0eff Mark Rowe Provide the ability to set a custom user agent string on all HTTP reques...
bdash authored
432 NSData *cleanedAgent = [userAgent dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
433 return [[[NSString alloc] initWithData:cleanedAgent encoding:NSASCIIStringEncoding] autorelease];
434 }
435
ec7f38d Andy Matuschak Fixes 258547
andymatuschak authored
436 - (void)setSendsSystemProfile:(BOOL)sendsSystemProfile
437 {
438 [host setBool:sendsSystemProfile forUserDefaultsKey:SUSendProfileInfoKey];
439 }
440
441 - (BOOL)sendsSystemProfile
4da902b Andy Matuschak Fixes 251968
andymatuschak authored
442 {
ec7f38d Andy Matuschak Fixes 258547
andymatuschak authored
443 return [host boolForUserDefaultsKey:SUSendProfileInfoKey];
4da902b Andy Matuschak Fixes 251968
andymatuschak authored
444 }
445
1aea1b6 Andy Matuschak The Sparkle preference keys are now declared private / deprecated / allo...
andymatuschak authored
446 - (NSURL *)parameterizedFeedURL
b2145b6 Andy Matuschak Killed NSURL+Parameters and moved the relevant code into SUUpdater.
andymatuschak authored
447 {
1aea1b6 Andy Matuschak The Sparkle preference keys are now declared private / deprecated / allo...
andymatuschak authored
448 NSURL *baseFeedURL = [self feedURL];
b2145b6 Andy Matuschak Killed NSURL+Parameters and moved the relevant code into SUUpdater.
andymatuschak authored
449
450 // Determine all the parameters we're attaching to the base feed URL.
ec7f38d Andy Matuschak Fixes 258547
andymatuschak authored
451 BOOL sendingSystemProfile = [self sendsSystemProfile];
e3226d3 A cleaned up and tested version of the one-submit-per-week code
David Smith authored
452
d1c0978 Andy Matuschak As discussed in https://bugs.launchpad.net/sparkle/+bug/243884/comments/...
andymatuschak authored
453 // Let's only send the system profiling information once per week at most, so we normalize daily-checkers vs. biweekly-checkers and the such.
e3226d3 A cleaned up and tested version of the one-submit-per-week code
David Smith authored
454 NSDate *lastSubmitDate = [host objectForUserDefaultsKey:SULastProfileSubmitDateKey];
455 if(!lastSubmitDate)
456 lastSubmitDate = [NSDate distantPast];
d1c0978 Andy Matuschak As discussed in https://bugs.launchpad.net/sparkle/+bug/243884/comments/...
andymatuschak authored
457 const NSTimeInterval oneWeek = 60 * 60 * 24 * 7;
458 sendingSystemProfile &= (-[lastSubmitDate timeIntervalSinceNow] >= oneWeek);
e3226d3 A cleaned up and tested version of the one-submit-per-week code
David Smith authored
459
645a96e Made a good deal more progress integrating the profile checking features...
andym authored
460 NSArray *parameters = [NSArray array];
b3f3944 Andy Matuschak Fixes 244857
andymatuschak authored
461 if ([delegate respondsToSelector:@selector(feedParametersForUpdater:sendingSystemProfile:)])
462 parameters = [parameters arrayByAddingObjectsFromArray:[delegate feedParametersForUpdater:self sendingSystemProfile:sendingSystemProfile]];
645a96e Made a good deal more progress integrating the profile checking features...
andym authored
463 if (sendingSystemProfile)
d1c0978 Andy Matuschak As discussed in https://bugs.launchpad.net/sparkle/+bug/243884/comments/...
andymatuschak authored
464 {
98832c4 Andy Matuschak Beginnings of insane SUHost-based refactoring to get rid of NSBundle+Spa...
andymatuschak authored
465 parameters = [parameters arrayByAddingObjectsFromArray:[host systemProfile]];
d1c0978 Andy Matuschak As discussed in https://bugs.launchpad.net/sparkle/+bug/243884/comments/...
andymatuschak authored
466 [host setObject:[NSDate date] forUserDefaultsKey:SULastProfileSubmitDateKey];
467 }
d7774c0 performed a code review, specifically:
Sean McBride authored
468 if ([parameters count] == 0) { return baseFeedURL; }
b2145b6 Andy Matuschak Killed NSURL+Parameters and moved the relevant code into SUUpdater.
andymatuschak authored
469
470 // Build up the parameterized URL.
471 NSMutableArray *parameterStrings = [NSMutableArray array];
472 NSEnumerator *profileInfoEnumerator = [parameters objectEnumerator];
473 NSDictionary *currentProfileInfo;
474 while ((currentProfileInfo = [profileInfoEnumerator nextObject]))
2768e60 Properly escapes the GET parameters in the appcast string with profile.
Lukhnos D. Liu authored
475 [parameterStrings addObject:[NSString stringWithFormat:@"%@=%@", [[[currentProfileInfo objectForKey:@"key"] description] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding], [[[currentProfileInfo objectForKey:@"value"] description] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]];
b2145b6 Andy Matuschak Killed NSURL+Parameters and moved the relevant code into SUUpdater.
andymatuschak authored
476
68e2cd6 Andy Matuschak Fixes 258492
andymatuschak authored
477 NSString *separatorCharacter = @"?";
478 if ([baseFeedURL query])
479 separatorCharacter = @"&"; // In case the URL is already http://foo.org/baz.xml?bat=4
444b0a9 Andy Matuschak Fixed a stupid mistake that prevented my fix for parameterized URLs from...
andymatuschak authored
480 NSString *appcastStringWithProfile = [NSString stringWithFormat:@"%@%@%@", [baseFeedURL absoluteString], separatorCharacter, [parameterStrings componentsJoinedByString:@"&"]];
b2145b6 Andy Matuschak Killed NSURL+Parameters and moved the relevant code into SUUpdater.
andymatuschak authored
481
482 // Clean it up so it's a valid URL
2768e60 Properly escapes the GET parameters in the appcast string with profile.
Lukhnos D. Liu authored
483 return [NSURL URLWithString:appcastStringWithProfile];
645a96e Made a good deal more progress integrating the profile checking features...
andym authored
484 }
485
1aea1b6 Andy Matuschak The Sparkle preference keys are now declared private / deprecated / allo...
andymatuschak authored
486 - (void)setUpdateCheckInterval:(NSTimeInterval)updateCheckInterval
487 {
488 [host setObject:[NSNumber numberWithDouble:updateCheckInterval] forUserDefaultsKey:SUScheduledCheckIntervalKey];
c21e1ab Andy Matuschak Fixes 258529 and 257967
andymatuschak authored
489 if (updateCheckInterval == 0) // For compatibility with 1.1's settings.
490 [self setAutomaticallyChecksForUpdates:NO];
491 [[self class] cancelPreviousPerformRequestsWithTarget:self selector:@selector(resetUpdateCycle) object:nil];
492
493 // Provide a small delay in case multiple preferences are being updated simultaneously.
494 [self performSelector:@selector(resetUpdateCycle) withObject:nil afterDelay:1];
1aea1b6 Andy Matuschak The Sparkle preference keys are now declared private / deprecated / allo...
andymatuschak authored
495 }
496
497 - (NSTimeInterval)updateCheckInterval
ebb1f01 Andy Matuschak Removed the checkInterval IV and factored out its assignment to a checkI...
andymatuschak authored
498 {
499 // Find the stored check interval. User defaults override Info.plist.
c21e1ab Andy Matuschak Fixes 258529 and 257967
andymatuschak authored
500 NSNumber *intervalValue = [host objectForKey:SUScheduledCheckIntervalKey];
501 if (intervalValue)
502 return [intervalValue doubleValue];
503 else
504 return SU_DEFAULT_CHECK_INTERVAL;
ebb1f01 Andy Matuschak Removed the checkInterval IV and factored out its assignment to a checkI...
andymatuschak authored
505 }
506
bbedfa1 Reorganized SUUpdater.m; it's in better order now.
andym authored
507 - (void)dealloc
9fa3da5 Holy restructuring, batman! Watch out for falling folders.
andym authored
508 {
98832c4 Andy Matuschak Beginnings of insane SUHost-based refactoring to get rid of NSBundle+Spa...
andymatuschak authored
509 [self unregisterAsObserver];
510 [host release];
43a0a7d Uli Kusterer Merge of changes from SVN repository:
uliwitness authored
511 if (checkTimer) { [checkTimer invalidate]; [checkTimer release]; checkTimer = nil; } // UK 2009-03-16 Timer is non-repeating, may have invalidated itself, so we had to retain it.
bbedfa1 Reorganized SUUpdater.m; it's in better order now.
andym authored
512 [super dealloc];
9fa3da5 Holy restructuring, batman! Watch out for falling folders.
andym authored
513 }
514
bc3be9a Touched practically every line of code in a super-monster-awesome refact...
andym authored
515 - (BOOL)validateMenuItem:(NSMenuItem *)item
66bbbed Restored 10.3.9 compatibility to the system version method.
andym authored
516 {
bc3be9a Touched practically every line of code in a super-monster-awesome refact...
andym authored
517 if ([item action] == @selector(checkForUpdates:))
518 return ![self updateInProgress];
519 return YES;
66bbbed Restored 10.3.9 compatibility to the system version method.
andym authored
520 }
521
645a96e Made a good deal more progress integrating the profile checking features...
andym authored
522 - (void)setDelegate:aDelegate
523 {
cd4addb Andy Matuschak Fixes 239512
andymatuschak authored
524 delegate = aDelegate;
645a96e Made a good deal more progress integrating the profile checking features...
andym authored
525 }
526
bc3be9a Touched practically every line of code in a super-monster-awesome refact...
andym authored
527 - (BOOL)updateInProgress
528 {
529 return driver && ([driver finished] == NO);
530 }
531
b3f3944 Andy Matuschak Fixes 244857
andymatuschak authored
532 - delegate { return delegate; }
533 - (NSBundle *)hostBundle { return [host bundle]; }
98832c4 Andy Matuschak Beginnings of insane SUHost-based refactoring to get rid of NSBundle+Spa...
andymatuschak authored
534
9fa3da5 Holy restructuring, batman! Watch out for falling folders.
andym authored
535 @end
Something went wrong with that request. Please try again.