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
@@ -7222,6 +7204,26 @@ AAEAAQAAAT0AAwAAAAEAAgAAAVIAAwAAAAEAAQAAAVMAAwAAAAIAAQABAAAAAA
6464
+
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