Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 230 lines (198 sloc) 7.721 kb
98832c4 @andymatuschak Beginnings of insane SUHost-based refactoring to get rid of NSBundle+…
andymatuschak authored
1 //
2 // SUHost.m
3 // Sparkle
4 //
5 // Copyright 2008 Andy Matuschak. All rights reserved.
6 //
7
f815eec @andymatuschak Fixes 243884
andymatuschak authored
8 #import "SUHost.h"
9
10 #import "SUSystemProfiler.h"
3146ffb @andymatuschak Fixes 248929, 244738
andymatuschak authored
11 #import <sys/mount.h> // For statfs for isRunningOnReadOnlyVolume
98832c4 @andymatuschak Beginnings of insane SUHost-based refactoring to get rid of NSBundle+…
andymatuschak authored
12
13 @implementation SUHost
14
15 - (id)initWithBundle:(NSBundle *)aBundle
16 {
17 if (aBundle == nil) aBundle = [NSBundle mainBundle];
18 if ((self = [super init]))
19 {
20 bundle = [aBundle retain];
874660f @andymatuschak Added a warning log message for bundles which don't have a CFBundleId…
andymatuschak authored
21 if (![bundle bundleIdentifier])
f2a7b4b Fixed deprecated APIs to use replacements.
August Joki authored
22 NSLog(@"Sparkle Error: the bundle being updated at %@ has no CFBundleIdentifier! This will cause preference read/write to not work properly.", bundle);
98832c4 @andymatuschak Beginnings of insane SUHost-based refactoring to get rid of NSBundle+…
andymatuschak authored
23 }
24 return self;
25 }
26
27 - (void)dealloc
28 {
29 [bundle release];
30 [super dealloc];
31 }
32
c386b70 @andymatuschak Partial fix for 245277: basic descriptions for some Sparkle classes. …
andymatuschak authored
33 - (NSString *)description { return [NSString stringWithFormat:@"%@ <%@>", [self class], [self bundlePath]]; }
34
98832c4 @andymatuschak Beginnings of insane SUHost-based refactoring to get rid of NSBundle+…
andymatuschak authored
35 - (NSBundle *)bundle
36 {
37 return bundle;
38 }
39
40 - (NSString *)bundlePath
41 {
42 return [bundle bundlePath];
43 }
44
45 - (NSString *)name
46 {
47 NSString *name = [bundle objectForInfoDictionaryKey:@"CFBundleDisplayName"];
48 if (name) return name;
49
50 name = [self objectForInfoDictionaryKey:@"CFBundleName"];
51 if (name) return name;
52
53 return [[[NSFileManager defaultManager] displayNameAtPath:[bundle bundlePath]] stringByDeletingPathExtension];
54 }
55
56 - (NSString *)version
57 {
7071142 @andymatuschak Improving Sparkle's robustness against apps without a CFBundleVersion.
andymatuschak authored
58 NSString *version = [bundle objectForInfoDictionaryKey:@"CFBundleVersion"];
59 if (!version || [version isEqualToString:@""])
60 [NSException raise:@"SUNoVersionException" format:@"This host (%@) has no CFBundleVersion! This attribute is required.", [self bundlePath]];
61 return version;
98832c4 @andymatuschak Beginnings of insane SUHost-based refactoring to get rid of NSBundle+…
andymatuschak authored
62 }
63
64 - (NSString *)displayVersion
65 {
66 NSString *shortVersionString = [bundle objectForInfoDictionaryKey:@"CFBundleShortVersionString"];
67 if (shortVersionString)
68 return shortVersionString;
69 else
70 return [self version]; // Fall back on the normal version string.
71 }
72
73 - (NSImage *)icon
74 {
75 // Cache the application icon.
76 NSString *iconPath = [bundle pathForResource:[bundle objectForInfoDictionaryKey:@"CFBundleIconFile"] ofType:@"icns"];
77 // According to the OS X docs, "CFBundleIconFile - This key identifies the file containing
78 // the icon for the bundle. The filename you specify does not need to include the .icns
79 // extension, although it may."
80 //
81 // However, if it *does* include the '.icns' the above method fails (tested on OS X 10.3.9) so we'll also try:
82 if (!iconPath)
83 iconPath = [bundle pathForResource:[bundle objectForInfoDictionaryKey:@"CFBundleIconFile"] ofType: nil];
84 NSImage *icon = [[[NSImage alloc] initWithContentsOfFile:iconPath] autorelease];
85 // Use a default icon if none is defined.
8c092c7 @andymatuschak Fixing 316105: "Icon defaults to app icon, also for non-app bundles"
andymatuschak authored
86 if (!icon) { icon = [[NSWorkspace sharedWorkspace] iconForFileType:NSFileTypeForHFSTypeCode(bundle == [NSBundle mainBundle] ? kGenericApplicationIcon : UTGetOSTypeFromString(CFSTR("BNDL")))]; }
98832c4 @andymatuschak Beginnings of insane SUHost-based refactoring to get rid of NSBundle+…
andymatuschak authored
87 return icon;
88 }
89
3146ffb @andymatuschak Fixes 248929, 244738
andymatuschak authored
90 - (BOOL)isRunningOnReadOnlyVolume
98832c4 @andymatuschak Beginnings of insane SUHost-based refactoring to get rid of NSBundle+…
andymatuschak authored
91 {
3146ffb @andymatuschak Fixes 248929, 244738
andymatuschak authored
92 struct statfs statfs_info;
93 statfs([[bundle bundlePath] fileSystemRepresentation], &statfs_info);
94 return (statfs_info.f_flags & MNT_RDONLY);
98832c4 @andymatuschak Beginnings of insane SUHost-based refactoring to get rid of NSBundle+…
andymatuschak authored
95 }
96
c42e3a3 @andymatuschak Fixed 251010
andymatuschak authored
97 - (BOOL)isBackgroundApplication
98 {
d73b374 @andymatuschak Fixes 268756
andymatuschak authored
99 ProcessSerialNumber PSN;
100 GetCurrentProcess(&PSN);
101 NSDictionary * processInfo = (NSDictionary *)ProcessInformationCopyDictionary(&PSN, kProcessDictionaryIncludeAllInformationMask);
102 BOOL isElement = [[processInfo objectForKey:@"LSUIElement"] boolValue];
103 if (processInfo)
104 CFRelease(processInfo);
105 return isElement;
c42e3a3 @andymatuschak Fixed 251010
andymatuschak authored
106 }
107
98832c4 @andymatuschak Beginnings of insane SUHost-based refactoring to get rid of NSBundle+…
andymatuschak authored
108 - (NSString *)publicDSAKey
109 {
110 // Maybe the key is just a string in the Info.plist.
111 NSString *key = [bundle objectForInfoDictionaryKey:SUPublicDSAKeyKey];
112 if (key) { return key; }
113
114 // More likely, we've got a reference to a Resources file by filename:
115 NSString *keyFilename = [self objectForInfoDictionaryKey:SUPublicDSAKeyFileKey];
116 if (!keyFilename) { return nil; }
f186aa6 @andymatuschak Fixed some deprecated method use which caused warnings with new versi…
andymatuschak authored
117 NSError *ignoreErr;
118 return [NSString stringWithContentsOfFile:[bundle pathForResource:keyFilename ofType:nil] encoding:NSASCIIStringEncoding error: &ignoreErr];
98832c4 @andymatuschak Beginnings of insane SUHost-based refactoring to get rid of NSBundle+…
andymatuschak authored
119 }
120
121 - (NSArray *)systemProfile
122 {
123 return [[SUSystemProfiler sharedSystemProfiler] systemProfileArrayForHost:self];
124 }
125
126 - (id)objectForInfoDictionaryKey:(NSString *)key
127 {
128 return [bundle objectForInfoDictionaryKey:key];
129 }
130
131 - (BOOL)boolForInfoDictionaryKey:(NSString *)key
132 {
133 return [[self objectForInfoDictionaryKey:key] boolValue];
134 }
135
136 - (id)objectForUserDefaultsKey:(NSString *)defaultName
137 {
138 // Under Tiger, CFPreferencesCopyAppValue doesn't get values from NSRegistratioDomain, so anything
139 // passed into -[NSUserDefaults registerDefaults:] is ignored. The following line falls
7228235 @andymatuschak Fixes 253929
andymatuschak authored
140 // back to using NSUserDefaults, but only if the host bundle is the main bundle.
141 if (bundle == [NSBundle mainBundle])
142 return [[NSUserDefaults standardUserDefaults] objectForKey:defaultName];
143
144 CFPropertyListRef obj = CFPreferencesCopyAppValue((CFStringRef)defaultName, (CFStringRef)[bundle bundleIdentifier]);
85eb5a7 @andymatuschak Fixing #314047: "Wrong version check in SUHost code"
andymatuschak authored
145 #if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_4
98832c4 @andymatuschak Beginnings of insane SUHost-based refactoring to get rid of NSBundle+…
andymatuschak authored
146 return [NSMakeCollectable(obj) autorelease];
147 #else
148 return [(id)obj autorelease];
149 #endif
150 }
151
152 - (void)setObject:(id)value forUserDefaultsKey:(NSString *)defaultName;
153 {
32a804e @andymatuschak Sparkle now uses Cocoa for user defaults for .apps and CF for user de…
andymatuschak authored
154 // If we're using a .app, we'll use the standard user defaults mechanism; otherwise, we have to get CF-y.
155 if (bundle == [NSBundle mainBundle])
156 {
157 [[NSUserDefaults standardUserDefaults] setObject:value forKey:defaultName];
158 }
159 else
160 {
161 CFPreferencesSetValue((CFStringRef)defaultName, value, (CFStringRef)[bundle bundleIdentifier], kCFPreferencesCurrentUser, kCFPreferencesAnyHost);
162 CFPreferencesSynchronize((CFStringRef)[bundle bundleIdentifier], kCFPreferencesCurrentUser, kCFPreferencesAnyHost);
163 }
98832c4 @andymatuschak Beginnings of insane SUHost-based refactoring to get rid of NSBundle+…
andymatuschak authored
164 }
165
166 - (BOOL)boolForUserDefaultsKey:(NSString *)defaultName
167 {
a31dc3a @andymatuschak Fixes BOOL user defaults lookup for registered defaults on Tiger.
andymatuschak authored
168 if (bundle == [NSBundle mainBundle])
169 return [[NSUserDefaults standardUserDefaults] boolForKey:defaultName];
170
98832c4 @andymatuschak Beginnings of insane SUHost-based refactoring to get rid of NSBundle+…
andymatuschak authored
171 BOOL value;
172 CFPropertyListRef plr = CFPreferencesCopyAppValue((CFStringRef)defaultName, (CFStringRef)[bundle bundleIdentifier]);
173 if (plr == NULL)
174 value = NO;
a31dc3a @andymatuschak Fixes BOOL user defaults lookup for registered defaults on Tiger.
andymatuschak authored
175 else
176 {
98832c4 @andymatuschak Beginnings of insane SUHost-based refactoring to get rid of NSBundle+…
andymatuschak authored
177 value = (BOOL)CFBooleanGetValue((CFBooleanRef)plr);
178 CFRelease(plr);
179 }
180 return value;
181 }
182
183 - (void)setBool:(BOOL)value forUserDefaultsKey:(NSString *)defaultName
184 {
32a804e @andymatuschak Sparkle now uses Cocoa for user defaults for .apps and CF for user de…
andymatuschak authored
185 // If we're using a .app, we'll use the standard user defaults mechanism; otherwise, we have to get CF-y.
186 if (bundle == [NSBundle mainBundle])
187 {
188 [[NSUserDefaults standardUserDefaults] setBool:value forKey:defaultName];
189 }
190 else
191 {
192 CFPreferencesSetValue((CFStringRef)defaultName, (CFBooleanRef)[NSNumber numberWithBool:value], (CFStringRef)[bundle bundleIdentifier], kCFPreferencesCurrentUser, kCFPreferencesAnyHost);
193 CFPreferencesSynchronize((CFStringRef)[bundle bundleIdentifier], kCFPreferencesCurrentUser, kCFPreferencesAnyHost);
194 }
98832c4 @andymatuschak Beginnings of insane SUHost-based refactoring to get rid of NSBundle+…
andymatuschak authored
195 }
196
5b38483 @andymatuschak Fixes 245723
andymatuschak authored
197 - (id)objectForKey:(NSString *)key {
a032358 @andymatuschak Removing GNU-style ?: operators. Thanks for the report, Uli.
andymatuschak authored
198 return [self objectForUserDefaultsKey:key] ? [self objectForUserDefaultsKey:key] : [self objectForInfoDictionaryKey:key];
5b38483 @andymatuschak Fixes 245723
andymatuschak authored
199 }
200
201 - (BOOL)boolForKey:(NSString *)key {
ec7f38d @andymatuschak Fixes 258547
andymatuschak authored
202 return [self objectForUserDefaultsKey:key] ? [self boolForUserDefaultsKey:key] : [self boolForInfoDictionaryKey:key];
5b38483 @andymatuschak Fixes 245723
andymatuschak authored
203 }
204
de9be8b @andymatuschak Fixes 244428
andymatuschak authored
205 + (NSString *)systemVersionString
206 {
207 // This returns a version string of the form X.Y.Z
208 // There may be a better way to deal with the problem that gestaltSystemVersionMajor
209 // et al. are not defined in 10.3, but this is probably good enough.
210 NSString* verStr = nil;
211 #if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_4
212 SInt32 major, minor, bugfix;
213 OSErr err1 = Gestalt(gestaltSystemVersionMajor, &major);
214 OSErr err2 = Gestalt(gestaltSystemVersionMinor, &minor);
215 OSErr err3 = Gestalt(gestaltSystemVersionBugFix, &bugfix);
216 if (!err1 && !err2 && !err3)
217 {
218 verStr = [NSString stringWithFormat:@"%d.%d.%d", major, minor, bugfix];
219 }
220 else
221 #endif
222 {
223 NSString *versionPlistPath = @"/System/Library/CoreServices/SystemVersion.plist";
f259b5e Return an autoreleased object as callers expect rather than leaking t…
Mark Rowe authored
224 verStr = [[NSDictionary dictionaryWithContentsOfFile:versionPlistPath] objectForKey:@"ProductVersion"];
de9be8b @andymatuschak Fixes 244428
andymatuschak authored
225 }
226 return verStr;
227 }
228
98832c4 @andymatuschak Beginnings of insane SUHost-based refactoring to get rid of NSBundle+…
andymatuschak authored
229 @end
Something went wrong with that request. Please try again.