From ddd8bfdb07496f3d5a24221cf95f19609a518290 Mon Sep 17 00:00:00 2001 From: emsquared Date: Tue, 26 Jun 2012 12:44:05 -0400 Subject: [PATCH] Security scoped bookmarks on Macs that support it. --- .../Preferences/TDCPreferencesController.m | 74 ++++++---- Classes/Headers/TPCPreferences.h | 3 +- Classes/IRC/IRCClient.m | 2 +- Classes/Library/TLOFileLogger.m | 4 + Classes/Preferences/TPCPreferences.m | 111 ++++++++++---- Resources/Info.plist | 4 +- .../English.lproj/TDCPreferences.xib | 139 +++++------------- Textual.entitlements | 2 + 8 files changed, 176 insertions(+), 163 deletions(-) diff --git a/Classes/Dialogs/Preferences/TDCPreferencesController.m b/Classes/Dialogs/Preferences/TDCPreferencesController.m index 47bdd24397..60cff204cf 100755 --- a/Classes/Dialogs/Preferences/TDCPreferencesController.m +++ b/Classes/Dialogs/Preferences/TDCPreferencesController.m @@ -67,7 +67,7 @@ - (NSArray *)toolbarDefaultItemIdentifiers:(NSToolbar *)toolbar NSString *addonID = ((NSObjectIsNotEmpty(self.world.bundlesWithPreferences)) ? @"13" : @"10"); return @[@"0", NSToolbarFlexibleSpaceItemIdentifier, @"3", @"1", - @"4", @"2", @"9", NSToolbarFlexibleSpaceItemIdentifier, addonID, @"11"]; + @"4", @"2", @"9", NSToolbarFlexibleSpaceItemIdentifier, addonID, @"11"]; } - (void)setUpToolbarItemsAndMenus @@ -346,21 +346,21 @@ - (NSMutableArray *)sounds - (void)updateTranscriptFolder { - if ([TPCPreferences sandboxEnabled]) { - [self.transcriptFolderButton setHidden:YES]; + NSString *path = [[TPCPreferences transcriptFolder] stringByExpandingTildeInPath]; + + if (NSObjectIsEmpty(path)) { + NSMenuItem *item = [self.transcriptFolderButton itemAtIndex:0]; - return; + [item setTitle:TXTLS(@"NoLogLocationDefinedMenuItem")]; + } else { + NSImage *icon = [_NSWorkspace() iconForFile:path]; + [icon setSize:NSMakeSize(16, 16)]; + + NSMenuItem *item = [self.transcriptFolderButton itemAtIndex:0]; + + [item setTitle:[[path lastPathComponent] decodeURIFragement]]; + [item setImage:icon]; } - - NSString *path = [[TPCPreferences transcriptFolder] stringByExpandingTildeInPath]; - - NSImage *icon = [_NSWorkspace() iconForFile:path]; - [icon setSize:NSMakeSize(16, 16)]; - - NSMenuItem *item = [self.transcriptFolderButton itemAtIndex:0]; - - [item setTitle:[[path lastPathComponent] decodeURIFragement]]; - [item setImage:icon]; } - (void)onTranscriptFolderChanged:(id)sender @@ -373,16 +373,32 @@ - (void)onTranscriptFolderChanged:(id)sender [d setCanChooseDirectories:YES]; [d setAllowsMultipleSelection:NO]; [d setCanCreateDirectories:YES]; - - [d beginSheetModalForWindow:[NSApp keyWindow] completionHandler:^(NSInteger returnCode) { + + [d beginSheetModalForWindow:self.window completionHandler:^(NSInteger returnCode) { [self.transcriptFolderButton selectItem:[self.transcriptFolderButton itemAtIndex:0]]; if (returnCode == NSOKButton) { NSURL *pathURL = [d.URLs safeObjectAtIndex:0]; - - NSString *path = [pathURL path]; - - [TPCPreferences setTranscriptFolder:[path stringByAbbreviatingWithTildeInPath]]; + + if ([TPCPreferences sandboxEnabled] && [TPCPreferences securityScopedBookmarksAvailable]) { + NSData *bookmark = nil; + + NSError *error = nil; + + bookmark = [pathURL bookmarkDataWithOptions:NSURLBookmarkCreationWithSecurityScope + includingResourceValuesForKeys:nil + relativeToURL:nil + error:&error]; + if (error) { + NSLog(@"Error creating bookmark for URL (%@): %@", pathURL, error); + } else { + [TPCPreferences setTranscriptFolder:bookmark]; + } + } else { + NSString *path = [pathURL path]; + + [TPCPreferences setTranscriptFolder:[path stringByAbbreviatingWithTildeInPath]]; + } [self updateTranscriptFolder]; } @@ -642,20 +658,18 @@ - (void)onDownloadExtraAddons:(id)sender { NSString *version = @"No%20Sandbox"; - if ([TPCPreferences featureAvailableToOSXLion]) { - if ([TPCPreferences sandboxEnabled]) { + if ([TPCPreferences sandboxEnabled]) { + if ([TPCPreferences featureAvailableToOSXLion]) { version = @"Lion"; - } - } - - if ([TPCPreferences featureAvailableToOSXMountainLion]) { - if ([TPCPreferences sandboxEnabled]) { + } + + if ([TPCPreferences featureAvailableToOSXMountainLion]) { version = @"Mountain%20Lion"; } - } - + } + NSMutableString *download = [NSMutableString string]; - + [download appendString:@"https://github.com/Codeux/Textual/blob/master/Resources/All%20Scripts/Sandbox%20Exceptions/Installers/Textual%20Extras%20%28"]; [download appendString:version]; [download appendString:@"%29.pkg?raw=true"]; diff --git a/Classes/Headers/TPCPreferences.h b/Classes/Headers/TPCPreferences.h index 62848efdc1..9b5c9340b9 100755 --- a/Classes/Headers/TPCPreferences.h +++ b/Classes/Headers/TPCPreferences.h @@ -47,6 +47,7 @@ typedef enum TXHostmaskBanFormat : NSInteger { @interface TPCPreferences : NSObject + (BOOL)sandboxEnabled; ++ (BOOL)securityScopedBookmarksAvailable; + (NSInteger)startTime; + (NSInteger)totalRunTime; @@ -89,7 +90,7 @@ typedef enum TXHostmaskBanFormat : NSInteger { + (NSString *)whereMainApplicationBundle; + (NSString *)transcriptFolder; -+ (void)setTranscriptFolder:(NSString *)value; ++ (void)setTranscriptFolder:(id)value; + (NSDictionary *)commandIndexList; + (NSInteger)indexOfIRCommand:(NSString *)command; diff --git a/Classes/IRC/IRCClient.m b/Classes/IRC/IRCClient.m index cea6beb498..ff17191814 100755 --- a/Classes/IRC/IRCClient.m +++ b/Classes/IRC/IRCClient.m @@ -1182,7 +1182,7 @@ -(void)executeTextualCmdScript:(NSDictionary *)details NSString *userScriptsPath = [TPCPreferences whereScriptsUnsupervisedPath]; if (NSObjectIsNotEmpty(userScriptsPath)) { - if ([scriptPath contains:[TPCPreferences whereScriptsUnsupervisedPath]]) { + if ([scriptPath contains:userScriptsPath]) { MLNonsandboxedScript = YES; } } diff --git a/Classes/Library/TLOFileLogger.m b/Classes/Library/TLOFileLogger.m index 4e232a6617..8f7656f753 100755 --- a/Classes/Library/TLOFileLogger.m +++ b/Classes/Library/TLOFileLogger.m @@ -58,6 +58,10 @@ - (void)reopenIfNeeded - (void)open { [self close]; + + if ([TPCPreferences transcriptFolder] == nil) { + return; + } self.filename = [self buildFileName]; diff --git a/Classes/Preferences/TPCPreferences.m b/Classes/Preferences/TPCPreferences.m index 7fa046c97d..2c34a96345 100755 --- a/Classes/Preferences/TPCPreferences.m +++ b/Classes/Preferences/TPCPreferences.m @@ -218,7 +218,7 @@ + (NSString *)whereScriptsPath if ([_NSFileManager() fileExistsAtPath:dest] == NO) { [_NSFileManager() createDirectoryAtPath:dest withIntermediateDirectories:YES attributes:nil error:NULL]; } - + return dest; } @@ -292,29 +292,70 @@ + (NSString *)whereMainApplicationBundle #pragma mark - #pragma mark Logging -+ (NSString *)transcriptFolder +static NSURL *transcriptFolderResolvedBookmark; + ++ (void)stopUsingTranscriptFolderBookmarkResources { - if ([self sandboxEnabled]) { - NSString *dest = [NSHomeDirectory() stringByAppendingPathComponent:@"Logs"]; + if (NSObjectIsNotEmpty(transcriptFolderResolvedBookmark)) { + [transcriptFolderResolvedBookmark stopAccessingSecurityScopedResource]; - if ([_NSFileManager() fileExistsAtPath:dest] == NO) { - [_NSFileManager() createDirectoryAtPath:dest withIntermediateDirectories:YES attributes:nil error:NULL]; + transcriptFolderResolvedBookmark = nil; + } +} + ++ (NSString *)transcriptFolder +{ + if ([self sandboxEnabled] && [TPCPreferences securityScopedBookmarksAvailable]) { + if (NSObjectIsNotEmpty(transcriptFolderResolvedBookmark)) { + return [transcriptFolderResolvedBookmark path]; + } else { + NSData *bookmark = [_NSUserDefaults() dataForKey:@"LogTranscriptDestinationSecurityBookmark"]; + + if (NSObjectIsNotEmpty(bookmark)) { + NSError *error; + + NSURL *resolvedBookmark = [NSURL URLByResolvingBookmarkData:bookmark + options:NSURLBookmarkResolutionWithSecurityScope + relativeToURL:nil + bookmarkDataIsStale:NO + error:&error]; + + if (error) { + NSLog(@"Error creating bookmark for URL: %@", error); + } else { + [resolvedBookmark startAccessingSecurityScopedResource]; + + transcriptFolderResolvedBookmark = resolvedBookmark; + + return [transcriptFolderResolvedBookmark path]; + } + } } - - return dest; + + return nil; } else { - NSString *base; - - base = [_NSUserDefaults() objectForKey:@"LogTranscriptDestination"]; - base = [base stringByExpandingTildeInPath]; - - return base; + NSString *base = [_NSUserDefaults() objectForKey:@"LogTranscriptDestination"]; + + return [base stringByExpandingTildeInPath]; } } -+ (void)setTranscriptFolder:(NSString *)value ++ (void)setTranscriptFolder:(id)value { - [_NSUserDefaults() setObject:value forKey:@"LogTranscriptDestination"]; + // "value" can either be returned as an absolute path on non-sandboxed + // versions of Textual or as an NSData object on sandboxed versions. + + if ([self sandboxEnabled]) { + if ([TPCPreferences securityScopedBookmarksAvailable] == NO) { + return; + } + + [self stopUsingTranscriptFolderBookmarkResources]; + + [_NSUserDefaults() setObject:value forKey:@"LogTranscriptDestinationSecurityBookmark"]; + } else { + [_NSUserDefaults() setObject:value forKey:@"LogTranscriptDestination"]; + } } #pragma mark - @@ -327,6 +368,23 @@ + (BOOL)sandboxEnabled return [NSHomeDirectory() hasSuffix:suffix]; } ++ (BOOL)securityScopedBookmarksAvailable +{ + if ([TPCPreferences featureAvailableToOSXLion] == NO) { + return NO; + } + + if ([TPCPreferences featureAvailableToOSXMountainLion]) { + return YES; + } + + NSString *osxversion = systemVersionPlist[@"ProductVersion"]; + + NSArray *matches = @[@"10.7", @"10.7.0", @"10.7.1", @"10.7.2"]; + + return ([matches containsObject:osxversion] == NO); +} + #pragma mark - #pragma mark Default Identity @@ -998,13 +1056,13 @@ + (void)defaultIRCClientSheetCallback:(NSNumber *)returnCode NSString *bundleID = [TPCPreferences applicationBundleIdentifier]; OSStatus changeResult; - + changeResult = LSSetDefaultHandlerForURLScheme((__bridge CFStringRef)@"irc", (__bridge CFStringRef)(bundleID)); changeResult = LSSetDefaultHandlerForURLScheme((__bridge CFStringRef)@"ircs", (__bridge CFStringRef)(bundleID)); - + #pragma unused(changeResult) } } @@ -1017,7 +1075,7 @@ + (void)defaultIRCClientPrompt CFURLRef appURL = NULL; OSStatus status = LSGetApplicationForURL((__bridge CFURLRef)baseURL, kLSRolesAll, NULL, &appURL); - + if (status == noErr) { NSBundle *mainBundle = [NSBundle mainBundle]; NSBundle *baseBundle = [NSBundle bundleWithURL:CFBridgingRelease(appURL)]; @@ -1042,7 +1100,7 @@ + (void)defaultIRCClientPrompt + (void)initPreferences { NSInteger numberOfRuns = 0; - + numberOfRuns = [_NSUserDefaults() integerForKey:@"TXRunCount"]; numberOfRuns += 1; @@ -1113,20 +1171,20 @@ + (void)initPreferences [d setDouble:1.0 forKey:@"MainWindowTransparencyLevel"]; // ====================================================== // - + [TPCPreferencesMigrationAssistant convertExistingGlobalPreferences]; - + [_NSUserDefaults() registerDefaults:d]; [_NSUserDefaults() addObserver:(id)self forKeyPath:@"Highlight List -> Primary Matches" options:NSKeyValueObservingOptionNew context:NULL]; [_NSUserDefaults() addObserver:(id)self forKeyPath:@"Highlight List -> Excluded Matches" options:NSKeyValueObservingOptionNew context:NULL]; systemVersionPlist = [NSDictionary dictionaryWithContentsOfFile:@"/System/Library/CoreServices/ServerVersion.plist"]; - + if (NSObjectIsEmpty(systemVersionPlist)) { systemVersionPlist = [NSDictionary dictionaryWithContentsOfFile:@"/System/Library/CoreServices/SystemVersion.plist"]; } - + if (NSObjectIsEmpty(systemVersionPlist)) { exit(10); } @@ -1139,7 +1197,8 @@ + (void)initPreferences /* Sandbox Check */ - [_NSUserDefaults() setBool:[TPCPreferences sandboxEnabled] forKey:@"Security -> Sandbox Enabled"]; + [_NSUserDefaults() setBool:[TPCPreferences sandboxEnabled] forKey:@"Security -> Sandbox Enabled"]; + [_NSUserDefaults() setBool:[TPCPreferences securityScopedBookmarksAvailable] forKey:@"Security -> Scoped Bookmarks Available"]; /* Font Check */ @@ -1151,7 +1210,7 @@ + (void)initPreferences NSString *themeName = [TPCViewTheme extractThemeName:[TPCPreferences themeName]]; NSString *themePath; - + themePath = [TPCPreferences whereThemesPath]; themePath = [themePath stringByAppendingPathComponent:themeName]; diff --git a/Resources/Info.plist b/Resources/Info.plist index 187bfdb9f9..46ea78c576 100755 --- a/Resources/Info.plist +++ b/Resources/Info.plist @@ -45,8 +45,8 @@ NSPrincipalClass NSApplication TXBundleBuildNumber - 11457 + 11484 TXBundleBuildReference - 2.1.1-188-g0b797db-stdbuild,llvm4.0 + 2.1.1-189-g884c37d-debug,llvm4.0 diff --git a/Resources/Localization/English.lproj/TDCPreferences.xib b/Resources/Localization/English.lproj/TDCPreferences.xib index 6c53a13910..814aba2673 100755 --- a/Resources/Localization/English.lproj/TDCPreferences.xib +++ b/Resources/Localization/English.lproj/TDCPreferences.xib @@ -174,9 +174,12 @@ Addons - + 268 {{3, 14}, {43, 32}} + + + 13 YES @@ -190,6 +193,7 @@ -2044182528 2 + 400 @@ -357,9 +361,12 @@ Advanced - + 268 {{8, 14}, {43, 32}} + + + 11 YES @@ -464,6 +471,7 @@ YES + 1 YES 2 YES @@ -3581,7 +3589,7 @@ AAEAAQAAAT0AAwAAAAEAAgAAAVIAAwAAAAEAAQAAAVMAAwAAAAIAAQABAAAAAA NSView - + 268 @@ -3589,6 +3597,7 @@ AAEAAQAAAT0AAwAAAAEAAgAAAVIAAwAAAAEAAQAAAVMAAwAAAAIAAQABAAAAAA 256 {{252, 21}, {230, 22}} + YES -2076180416 @@ -3678,32 +3687,12 @@ AAEAAQAAAT0AAwAAAAEAAgAAAVIAAwAAAAEAAQAAAVMAAwAAAAIAAQABAAAAAA NO - - - 268 - {{192, 25}, {123, 16}} - - - _NS:1560 - YES - - 68157504 - 272761856 - to sandboxed folder - - _NS:1560 - - - - - NO - 256 {{84, 23}, {110, 18}} - + YES 67108864 @@ -3724,6 +3713,7 @@ AAEAAQAAAT0AAwAAAAEAAgAAAVIAAwAAAAEAAQAAAVMAAwAAAAIAAQABAAAAAA {534, 61} + NSView @@ -4907,7 +4897,6 @@ AAEAAQAAAT0AAwAAAAEAAgAAAVIAAwAAAAEAAQAAAVMAAwAAAAIAAQABAAAAAA 12 {{10, 10}, {515, 418}} - @@ -4921,7 +4910,6 @@ AAEAAQAAAT0AAwAAAAEAAgAAAVIAAwAAAAEAAQAAAVMAAwAAAAIAAQABAAAAAA 256 {{11, 341}, {250, 18}} - YES @@ -4946,7 +4934,6 @@ AAEAAQAAAT0AAwAAAAEAAgAAAVIAAwAAAAEAAQAAAVMAAwAAAAIAAQABAAAAAA 268 {{11, 313}, {349, 18}} - YES @@ -4971,7 +4958,6 @@ AAEAAQAAAT0AAwAAAAEAAgAAAVIAAwAAAAEAAQAAAVMAAwAAAAIAAQABAAAAAA 268 {{11, 285}, {264, 18}} - YES @@ -4996,7 +4982,6 @@ AAEAAQAAAT0AAwAAAAEAAgAAAVIAAwAAAAEAAQAAAVMAAwAAAAIAAQABAAAAAA 256 {{11, 257}, {341, 18}} - YES @@ -5021,7 +5006,6 @@ AAEAAQAAAT0AAwAAAAEAAgAAAVIAAwAAAAEAAQAAAVMAAwAAAAIAAQABAAAAAA 268 {{10, 229}, {357, 18}} - _NS:239 YES @@ -5046,7 +5030,6 @@ AAEAAQAAAT0AAwAAAAEAAgAAAVIAAwAAAAEAAQAAAVMAAwAAAAIAAQABAAAAAA {{10, 25}, {495, 380}} - General @@ -5647,7 +5630,6 @@ AAEAAQAAAT0AAwAAAAEAAgAAAVIAAwAAAAEAAQAAAVMAAwAAAAIAAQABAAAAAA {534, 442} - NSView @@ -7222,6 +7204,26 @@ AAEAAQAAAT0AAwAAAAEAAgAAAVIAAwAAAAEAAQAAAVMAAwAAAAIAAQABAAAAAA 6464 + + + hidden: values.Security -> Scoped Bookmarks Available + + + + + + hidden: values.Security -> Scoped Bookmarks Available + hidden + values.Security -> Scoped Bookmarks Available + + NSValueTransformerName + NSNegateBoolean + + 2 + + + 7254 + displayPatternValue1: themeChannelViewFontName @@ -7524,7 +7526,7 @@ AAEAAQAAAT0AAwAAAAEAAgAAAVIAAwAAAAEAAQAAAVMAAwAAAAIAAQABAAAAAA enabled: values.LogTranscript - + enabled: values.LogTranscript @@ -7535,59 +7537,6 @@ AAEAAQAAAT0AAwAAAAEAAgAAAVIAAwAAAAEAAQAAAVMAAwAAAAIAAQABAAAAAA 7234 - - - hidden: values.Security -> Sandbox Enabled - - - - - - hidden: values.Security -> Sandbox Enabled - hidden - values.Security -> Sandbox Enabled - - 2 - - - 7235 - - - - hidden: values.Security -> Sandbox Enabled - - - - - - hidden: values.Security -> Sandbox Enabled - hidden - values.Security -> Sandbox Enabled - 2 - - - 7226 - - - - hidden: values.Security -> Sandbox Enabled - - - - - - hidden: values.Security -> Sandbox Enabled - hidden - values.Security -> Sandbox Enabled - - NSValueTransformerName - NSNegateBoolean - - 2 - - - 7225 - value: values.UUIDBasedNicknameColorHashing @@ -8129,7 +8078,6 @@ AAEAAQAAAT0AAwAAAAEAAgAAAVIAAwAAAAEAAQAAAVMAAwAAAAIAAQABAAAAAA - @@ -10236,19 +10184,6 @@ AAEAAQAAAT0AAwAAAAEAAgAAAVIAAwAAAAEAAQAAAVMAAwAAAAIAAQABAAAAAA - - 6789 - - - - - - - - 6790 - - - 6784 @@ -11479,8 +11414,6 @@ AAEAAQAAAT0AAwAAAAEAAgAAAVIAAwAAAAEAAQAAAVMAAwAAAAIAAQABAAAAAA com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin @@ -11634,7 +11567,7 @@ AAEAAQAAAT0AAwAAAAEAAgAAAVIAAwAAAAEAAQAAAVMAAwAAAAIAAQABAAAAAA - 7252 + 7254 0 diff --git a/Textual.entitlements b/Textual.entitlements index c9665eb2ec..db431b51c2 100644 --- a/Textual.entitlements +++ b/Textual.entitlements @@ -8,6 +8,8 @@ com.apple.security.network.client + com.apple.security.files.user-selected.read-write + NSFileProtectionComplete com.apple.security.temporary-exception.files.home-relative-path.read-write /Library/Containers/com.codeux.irc.textual/ com.apple.security.temporary-exception.apple-events