Rename configurations to Debug and Release.
[MacTF.git] / UKUpdateChecker.m
blob80b37ad4dc5f13c416e96234e5c847504c6782a9
1 //
2 //  UKUpdateChecker.m
3 //  NiftyFeatures
4 //
5 //  Created by Uli Kusterer on Sun Nov 23 2003.
6 //  Copyright (c) 2003 M. Uli Kusterer. All rights reserved.
7 //
9 #import "UKUpdateChecker.h"
12 @implementation UKUpdateChecker
15 // -----------------------------------------------------------------------------
16 //      awakeFromNib:
17 //              This object has been created and loaded at startup. If this is first
18 //              launch, ask user whether we should check for updates periodically at
19 //              startup and adjust the prefs accurately.
21 //              If the user wants us to check for updates periodically, check whether
22 //              it is time and if so, initiate the check.
24 //      REVISIONS:
25 //              2004-03-19      witness Documented.
26 // -----------------------------------------------------------------------------
28 -(void) awakeFromNib
30         NSNumber        *   doCheck = [[NSUserDefaults standardUserDefaults] objectForKey: @"UKUpdateChecker:CheckAtStartup"];
31         NSString        *   appName = [[NSFileManager defaultManager] displayNameAtPath: [[NSBundle mainBundle] bundlePath]]; 
32         NSNumber        *   lastCheckDateNum = [[NSUserDefaults standardUserDefaults] objectForKey: @"UKUpdateChecker:LastCheckDate"];
33         NSDate          *   lastCheckDate = nil;
34         
35         if( doCheck == nil )            // No setting in prefs yet? First launch! Ask!
36         {
37                 if( NSRunAlertPanel( NSLocalizedStringFromTable(@"CHECK_FOR_UPDATES_TITLE", @"UKUpdateChecker", @"Asking whether to check for updates at startup - dialog title"),
38                                                         NSLocalizedStringFromTable(@"CHECK_FOR_UPDATES_TEXT", @"UKUpdateChecker", @"Asking whether to check for updates at startup - dialog text"),
39                                                         NSLocalizedStringFromTable(@"Yes",@"UKUpdateChecker", nil), NSLocalizedStringFromTable(@"No",@"UKUpdateChecker", nil), nil, appName ) == NSAlertDefaultReturn )
40                         doCheck = [NSNumber numberWithBool:YES];
41                 else
42                         doCheck = [NSNumber numberWithBool:NO];
43                 
44                 // Save user's preference to prefs file:
45                 [[NSUserDefaults standardUserDefaults] setObject: doCheck forKey: @"UKUpdateChecker:CheckAtStartup"];
46         }
47         
48         [prefsButton setState: [doCheck boolValue]];    // Update prefs button, if we have one.
49         
50         // If user wants us to check for updates at startup, do so:
51         if( [doCheck boolValue] )
52         {
53                 NSTimeInterval  timeSinceLastCheck;
54                 
55                 // Determine how long since last check:
56                 if( lastCheckDateNum == nil )
57                         lastCheckDate = [NSDate distantPast];  // If there's no date in prefs, use something guaranteed to be past.
58                 else
59                         lastCheckDate = [NSDate dateWithTimeIntervalSinceReferenceDate: [lastCheckDateNum doubleValue]];
60                 timeSinceLastCheck = -[lastCheckDate timeIntervalSinceNow];
61                 
62                 // If last check was more than DAYS_BETWEEN_CHECKS days ago, check again now:
63                 if( timeSinceLastCheck > (3600 *24 *DAYS_BETWEEN_CHECKS) )
64                 {
65                         [self checkForUpdatesAndNotifyIfUnsuccessful: NO];
66                         [[NSUserDefaults standardUserDefaults] setObject: [NSNumber numberWithDouble: [NSDate timeIntervalSinceReferenceDate]] forKey: @"UKUpdateChecker:LastCheckDate"];
67                 }
68         }
72 // -----------------------------------------------------------------------------
73 //      checkForUpdates:
74 //              IBAction to hook up to the "check for updates" menu item.
76 //      REVISIONS:
77 //              2004-03-19      witness Documented.
78 // -----------------------------------------------------------------------------
80 -(IBAction) checkForUpdates: (id)sender
82         [self checkForUpdatesAndNotifyIfUnsuccessful: YES];             // YES means we *also* tell the user about failure, since this is in response to a menu item.
86 // -----------------------------------------------------------------------------
87 //      latestVersionsDictionary:
88 //              Load a dictionary containing info on the latest versions of this app.
90 //              This first tries to get MacPAD-compatible version information. If the
91 //              developer didn't provide that, it will try the old UKUpdateChecker
92 //              scheme instead.
94 //      REVISIONS:
95 //              2004-03-19      witness Documented.
96 // -----------------------------------------------------------------------------
98 -(NSDictionary*)        latestVersionsDictionary
100         NSString*   fpath = [[NSBundle mainBundle] pathForResource: UKUpdateCheckerURLFilename ofType: @"url"];
101         
102         // Do we have a MacPAD.url file?
103         if( [[NSFileManager defaultManager] fileExistsAtPath: fpath] )  // MacPAD-compatible!
104         {
105                 NSString*               urlfile = [NSString stringWithContentsOfFile: fpath];
106                 NSArray*                lines = [urlfile componentsSeparatedByString: @"\n"];
107                 NSString*               urlString = [lines lastObject];   // Either this is the only line, or the line following [InternetShortcut]
108                 
109                 if( [urlString characterAtIndex: [urlString length] -1] == '/'          // Directory path? Append bundle identifier and .plist to get an actual file path to download.
110                         || [urlString characterAtIndex: [urlString length] -1] == '=' ) // CGI parameter?
111                         urlString = [[urlString stringByAppendingString: [[NSBundle mainBundle] bundleIdentifier]] stringByAppendingString: @".plist"];
112         
113                 return [NSDictionary dictionaryWithContentsOfURL: [NSURL URLWithString: urlString]];    // Download info from that URL.
114         }
115         else    // Old-style UKUpdateChecker stuff:
116         {
117                 NSURL*                  versDictURL = [NSURL URLWithString: NSLocalizedString(@"UPDATE_PLIST_URL", @"URL where the plist with the latest version numbers is.")];
118                 NSDictionary*   allVersionsDict = [NSDictionary dictionaryWithContentsOfURL: versDictURL];
119                 return [allVersionsDict objectForKey: [[NSBundle mainBundle] bundleIdentifier]];
120         }
124 -(void)         checkForUpdatesAndNotifyIfUnsuccessful: (BOOL)doNotify
126         // Load a .plist of application version info from a web URL:
127         NSString         *  appName = [[NSFileManager defaultManager] displayNameAtPath: [[NSBundle mainBundle] bundlePath]]; 
128     NSDictionary *  appVersionDict = [self latestVersionsDictionary];
129         BOOL                    succeeded = NO;
130     
131     if( appVersionDict != nil )         // We were able to download a dictionary?
132         {
133                 // Extract version number and URL from dictionary:
134                 NSString *newVersion = [appVersionDict valueForKey: UKUpdateCheckerVersionPlistKey];
135         NSString *newUrl = [appVersionDict valueForKey: UKUpdateCheckerURLPlistKey];
136         
137                 if( !newVersion || !newUrl )    // Dictionary doesn't contain new MacPAD stuff? Use old UKUpdateChecker stuff instead.
138                 {
139                         newVersion = [appVersionDict valueForKey:UKUpdateCheckerOldVersionPlistKey];
140                         newUrl = [appVersionDict valueForKey:UKUpdateCheckerOldURLPlistKey];
141                 }
142                 
143                 // Is it current? Then tell the user, or just quietly go on, depending on doNotify:
144         if( [newVersion isLessThanOrEqualTo: [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"]]  )
145                 {
146             if( doNotify )
147                                 NSRunAlertPanel(NSLocalizedStringFromTable(@"UP_TO_DATE_TITLE", @"UKUpdateChecker", @"When soft is up-to-date - dialog title"),
148                                                                 NSLocalizedStringFromTable(@"UP_TO_DATE_TEXT", @"UKUpdateChecker", @"When soft is up-to-date - dialog text"),
149                                                                 NSLocalizedStringFromTable(@"OK", @"UKUpdateChecker", @""), nil, nil, appName );
150                         succeeded = YES;
151         }
152                 else if( newVersion != nil )    // If there's an entry for this app:
153                 {
154                         // Ask user whether they'd like to open the URL for the new version:
155             int button = NSRunAlertPanel(
156                             NSLocalizedStringFromTable(@"NEW_VERSION_TITLE", @"UKUpdateChecker", @"A New Version is Available - dialog title"),
157                             NSLocalizedStringFromTable(@"NEW_VERSION_TEXT", @"UKUpdateChecker", @"A New Version is Available - dialog text"),
158                                                         NSLocalizedStringFromTable(@"OK", @"UKUpdateChecker", @""), NSLocalizedStringFromTable(@"Cancel", @"UKUpdateChecker", @""), nil,
159                                                         appName, newVersion );
160             if(NSOKButton == button)    // Yes?
161                 [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:newUrl]];   //Open!
163             succeeded = YES;    // Otherwise, it's still a success.
164         }
165     }
166         
167         // Failed? File not found, no internet, there is no entry for our app?
168         if( !succeeded && doNotify )
169                 NSRunAlertPanel(NSLocalizedStringFromTable(@"UPDATE_ERROR_TITLE", @"UKUpdateChecker", @"When update test failed - dialog title"),
170                                                 NSLocalizedStringFromTable(@"UPDATE_ERROR_TEXT", @"UKUpdateChecker", @"When update test failed - dialog text"),
171                                                 @"OK", nil, nil, appName);
175 -(IBAction)             takeBoolFromObject: (id)sender
177         if( [sender respondsToSelector: @selector(boolValue)] )
178                 [self setCheckAtStartup: [sender boolValue]];
179         else
180                 [self setCheckAtStartup: [sender state]];
184 -(void)                 setCheckAtStartup: (BOOL)shouldCheck
186         NSNumber*               doCheck = [NSNumber numberWithBool: shouldCheck];
187         [[NSUserDefaults standardUserDefaults] setObject: doCheck forKey: @"UKUpdateChecker:CheckAtStartup"];
188         
189         [prefsButton setState: shouldCheck];
190         [[NSUserDefaults standardUserDefaults] setObject: [NSNumber numberWithDouble: 0] forKey: @"UKUpdateChecker:LastCheckDate"];
194 -(BOOL)                 checkAtStartup
196         NSNumber        *   doCheck = [[NSUserDefaults standardUserDefaults] objectForKey: @"UKUpdateChecker:CheckAtStartup"];
197         
198         if( doCheck )
199                 return [doCheck boolValue];
200         else
201                 return YES;
205 @end