Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 208 lines (179 sloc) 6.492 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];
21 }
22 return self;
23 }
24
25 - (void)dealloc
26 {
27 [bundle release];
28 [super dealloc];
29 }
30
31 - (NSBundle *)bundle
32 {
33 return bundle;
34 }
35
36 - (NSString *)bundlePath
37 {
38 return [bundle bundlePath];
39 }
40
41 - (NSString *)name
42 {
43 NSString *name = [bundle objectForInfoDictionaryKey:@"CFBundleDisplayName"];
44 if (name) return name;
45
46 name = [self objectForInfoDictionaryKey:@"CFBundleName"];
47 if (name) return name;
48
49 return [[[NSFileManager defaultManager] displayNameAtPath:[bundle bundlePath]] stringByDeletingPathExtension];
50 }
51
52 - (NSString *)version
53 {
54 return [bundle objectForInfoDictionaryKey:@"CFBundleVersion"];
55 }
56
57 - (NSString *)displayVersion
58 {
59 NSString *shortVersionString = [bundle objectForInfoDictionaryKey:@"CFBundleShortVersionString"];
60 if (shortVersionString)
61 return shortVersionString;
62 else
63 return [self version]; // Fall back on the normal version string.
64 }
65
66 - (NSImage *)icon
67 {
68 // Cache the application icon.
69 NSString *iconPath = [bundle pathForResource:[bundle objectForInfoDictionaryKey:@"CFBundleIconFile"] ofType:@"icns"];
70 // According to the OS X docs, "CFBundleIconFile - This key identifies the file containing
71 // the icon for the bundle. The filename you specify does not need to include the .icns
72 // extension, although it may."
73 //
74 // However, if it *does* include the '.icns' the above method fails (tested on OS X 10.3.9) so we'll also try:
75 if (!iconPath)
76 iconPath = [bundle pathForResource:[bundle objectForInfoDictionaryKey:@"CFBundleIconFile"] ofType: nil];
77 NSImage *icon = [[[NSImage alloc] initWithContentsOfFile:iconPath] autorelease];
78 // Use a default icon if none is defined.
79 if (!icon) { icon = [[NSWorkspace sharedWorkspace] iconForFileType:NSFileTypeForHFSTypeCode(kGenericApplicationIcon)]; }
80 return icon;
81 }
82
3146ffb @andymatuschak Fixes 248929, 244738
andymatuschak authored
83 - (BOOL)isRunningOnReadOnlyVolume
98832c4 @andymatuschak Beginnings of insane SUHost-based refactoring to get rid of NSBundle+…
andymatuschak authored
84 {
3146ffb @andymatuschak Fixes 248929, 244738
andymatuschak authored
85 struct statfs statfs_info;
86 statfs([[bundle bundlePath] fileSystemRepresentation], &statfs_info);
87 return (statfs_info.f_flags & MNT_RDONLY);
98832c4 @andymatuschak Beginnings of insane SUHost-based refactoring to get rid of NSBundle+…
andymatuschak authored
88 }
89
c42e3a3 @andymatuschak Fixed 251010
andymatuschak authored
90 - (BOOL)isBackgroundApplication
91 {
347dd73 @andymatuschak Fixes 253739
andymatuschak authored
92 return [[[NSBundle mainBundle] objectForInfoDictionaryKey:@"LSUIElement"] doubleValue];
c42e3a3 @andymatuschak Fixed 251010
andymatuschak authored
93 }
94
98832c4 @andymatuschak Beginnings of insane SUHost-based refactoring to get rid of NSBundle+…
andymatuschak authored
95 - (NSString *)publicDSAKey
96 {
97 // Maybe the key is just a string in the Info.plist.
98 NSString *key = [bundle objectForInfoDictionaryKey:SUPublicDSAKeyKey];
99 if (key) { return key; }
100
101 // More likely, we've got a reference to a Resources file by filename:
102 NSString *keyFilename = [self objectForInfoDictionaryKey:SUPublicDSAKeyFileKey];
103 if (!keyFilename) { return nil; }
104 return [NSString stringWithContentsOfFile:[bundle pathForResource:keyFilename ofType:nil]];
105 }
106
107 - (NSArray *)systemProfile
108 {
109 return [[SUSystemProfiler sharedSystemProfiler] systemProfileArrayForHost:self];
110 }
111
112 - (id)objectForInfoDictionaryKey:(NSString *)key
113 {
114 return [bundle objectForInfoDictionaryKey:key];
115 }
116
117 - (BOOL)boolForInfoDictionaryKey:(NSString *)key
118 {
119 return [[self objectForInfoDictionaryKey:key] boolValue];
120 }
121
122 - (id)objectForUserDefaultsKey:(NSString *)defaultName
123 {
124 // Under Tiger, CFPreferencesCopyAppValue doesn't get values from NSRegistratioDomain, so anything
125 // passed into -[NSUserDefaults registerDefaults:] is ignored. The following line falls
7228235 @andymatuschak Fixes 253929
andymatuschak authored
126 // back to using NSUserDefaults, but only if the host bundle is the main bundle.
127 if (bundle == [NSBundle mainBundle])
128 return [[NSUserDefaults standardUserDefaults] objectForKey:defaultName];
129
130 CFPropertyListRef obj = CFPreferencesCopyAppValue((CFStringRef)defaultName, (CFStringRef)[bundle bundleIdentifier]);
98832c4 @andymatuschak Beginnings of insane SUHost-based refactoring to get rid of NSBundle+…
andymatuschak authored
131 #if MAC_OS_X_VERSION_MIN_REQUIRED > 1050
132 return [NSMakeCollectable(obj) autorelease];
133 #else
134 return [(id)obj autorelease];
135 #endif
136 }
137
138 - (void)setObject:(id)value forUserDefaultsKey:(NSString *)defaultName;
139 {
32a804e @andymatuschak Sparkle now uses Cocoa for user defaults for .apps and CF for user de…
andymatuschak authored
140 // If we're using a .app, we'll use the standard user defaults mechanism; otherwise, we have to get CF-y.
141 if (bundle == [NSBundle mainBundle])
142 {
143 [[NSUserDefaults standardUserDefaults] setObject:value forKey:defaultName];
144 }
145 else
146 {
147 CFPreferencesSetValue((CFStringRef)defaultName, value, (CFStringRef)[bundle bundleIdentifier], kCFPreferencesCurrentUser, kCFPreferencesAnyHost);
148 CFPreferencesSynchronize((CFStringRef)[bundle bundleIdentifier], kCFPreferencesCurrentUser, kCFPreferencesAnyHost);
149 }
98832c4 @andymatuschak Beginnings of insane SUHost-based refactoring to get rid of NSBundle+…
andymatuschak authored
150 }
151
152 - (BOOL)boolForUserDefaultsKey:(NSString *)defaultName
153 {
a31dc3a @andymatuschak Fixes BOOL user defaults lookup for registered defaults on Tiger.
andymatuschak authored
154 if (bundle == [NSBundle mainBundle])
155 return [[NSUserDefaults standardUserDefaults] boolForKey:defaultName];
156
98832c4 @andymatuschak Beginnings of insane SUHost-based refactoring to get rid of NSBundle+…
andymatuschak authored
157 BOOL value;
158 CFPropertyListRef plr = CFPreferencesCopyAppValue((CFStringRef)defaultName, (CFStringRef)[bundle bundleIdentifier]);
159 if (plr == NULL)
160 value = NO;
a31dc3a @andymatuschak Fixes BOOL user defaults lookup for registered defaults on Tiger.
andymatuschak authored
161 else
162 {
98832c4 @andymatuschak Beginnings of insane SUHost-based refactoring to get rid of NSBundle+…
andymatuschak authored
163 value = (BOOL)CFBooleanGetValue((CFBooleanRef)plr);
164 CFRelease(plr);
165 }
166 return value;
167 }
168
169 - (void)setBool:(BOOL)value forUserDefaultsKey:(NSString *)defaultName
170 {
32a804e @andymatuschak Sparkle now uses Cocoa for user defaults for .apps and CF for user de…
andymatuschak authored
171 // If we're using a .app, we'll use the standard user defaults mechanism; otherwise, we have to get CF-y.
172 if (bundle == [NSBundle mainBundle])
173 {
174 [[NSUserDefaults standardUserDefaults] setBool:value forKey:defaultName];
175 }
176 else
177 {
178 CFPreferencesSetValue((CFStringRef)defaultName, (CFBooleanRef)[NSNumber numberWithBool:value], (CFStringRef)[bundle bundleIdentifier], kCFPreferencesCurrentUser, kCFPreferencesAnyHost);
179 CFPreferencesSynchronize((CFStringRef)[bundle bundleIdentifier], kCFPreferencesCurrentUser, kCFPreferencesAnyHost);
180 }
98832c4 @andymatuschak Beginnings of insane SUHost-based refactoring to get rid of NSBundle+…
andymatuschak authored
181 }
182
de9be8b @andymatuschak Fixes 244428
andymatuschak authored
183 + (NSString *)systemVersionString
184 {
185 // This returns a version string of the form X.Y.Z
186 // There may be a better way to deal with the problem that gestaltSystemVersionMajor
187 // et al. are not defined in 10.3, but this is probably good enough.
188 NSString* verStr = nil;
189 #if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_4
190 SInt32 major, minor, bugfix;
191 OSErr err1 = Gestalt(gestaltSystemVersionMajor, &major);
192 OSErr err2 = Gestalt(gestaltSystemVersionMinor, &minor);
193 OSErr err3 = Gestalt(gestaltSystemVersionBugFix, &bugfix);
194 if (!err1 && !err2 && !err3)
195 {
196 verStr = [NSString stringWithFormat:@"%d.%d.%d", major, minor, bugfix];
197 }
198 else
199 #endif
200 {
201 NSString *versionPlistPath = @"/System/Library/CoreServices/SystemVersion.plist";
202 verStr = [[[NSDictionary dictionaryWithContentsOfFile:versionPlistPath] objectForKey:@"ProductVersion"] retain];
203 }
204 return verStr;
205 }
206
98832c4 @andymatuschak Beginnings of insane SUHost-based refactoring to get rid of NSBundle+…
andymatuschak authored
207 @end
Something went wrong with that request. Please try again.