Skip to content

Commit

Permalink
Check whether the app is running under Translocation on macOS Sierra …
Browse files Browse the repository at this point in the history
…and uses the original application path instead of the path the app is running from. This fixes DMG and Download folder detection, which is broken when running from a Translocated path.
  • Loading branch information
JeremyAgost committed Dec 2, 2016
1 parent ff2fada commit e60633c
Showing 1 changed file with 47 additions and 1 deletion.
48 changes: 47 additions & 1 deletion PFMoveApplication.m
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@


// Helper functions
static NSURL * GetOriginalBundleURL(void);
static NSString *PreferredInstallLocation(BOOL *isUserDirectory);
static BOOL IsInApplicationsFolder(NSString *path);
static BOOL IsInDownloadsFolder(NSString *path);
Expand All @@ -61,7 +62,7 @@ void PFMoveToApplicationsFolderIfNecessary(void) {
if ([[NSUserDefaults standardUserDefaults] boolForKey:AlertSuppressKey]) return;

// Path of the bundle
NSString *bundlePath = [[NSBundle mainBundle] bundlePath];
NSString *bundlePath = GetOriginalBundleURL().path;

// Check if the bundle is embedded in another application
BOOL isNestedApplication = IsApplicationAtPathNested(bundlePath);
Expand Down Expand Up @@ -210,6 +211,51 @@ void PFMoveToApplicationsFolderIfNecessary(void) {
#pragma mark -
#pragma mark Helper Functions

/// Gets the real bundle path of the application, not the Translocated one if applicable
static NSURL * GetOriginalBundleURL(void) {

NSURL * bundleURL = [NSBundle mainBundle].bundleURL;
NSLog(@"%s: Foundation says bundle URL is %@", __FUNCTION__, bundleURL);

// #define NSAppKitVersionNumber10_11 1404
if (floor(NSAppKitVersionNumber) <= 1404) {
return bundleURL;
}

void * handle = dlopen("/System/Library/Frameworks/Security.framework/Security", RTLD_LAZY);
if (handle == NULL) {
return bundleURL;
}

bool isTranslocated = false;

// Get (undocumented?) function symbols for looking up app translocation info
// Note: <Security/SecTranslocation.h> was available in the macOS 10.12 beta SDKs but seems to have been removed as of Xcode 8.1
Boolean(*mySecTranslocateIsTranslocatedURL)(CFURLRef path, bool *isTranslocated, CFErrorRef * __nullable error) = dlsym(handle, "SecTranslocateIsTranslocatedURL");
CFURLRef __nullable(*mySecTranslocateCreateOriginalPathForURL)(CFURLRef translocatedPath, CFErrorRef * __nullable error) = dlsym(handle, "SecTranslocateCreateOriginalPathForURL");

dlclose(handle);

if (mySecTranslocateIsTranslocatedURL == NULL || mySecTranslocateCreateOriginalPathForURL == NULL) {
NSLog(@"%s: We're running on macOS >= 10.12 but the SecTranslocate functions are not available", __FUNCTION__);
return bundleURL;
}

if (mySecTranslocateIsTranslocatedURL((__bridge CFURLRef)bundleURL, &isTranslocated, NULL) && isTranslocated)
{
CFURLRef originalURL = mySecTranslocateCreateOriginalPathForURL((__bridge CFURLRef)bundleURL, NULL);
if (originalURL != NULL)
{
NSURL * result = CFBridgingRelease(originalURL);
NSLog(@"%s: Security says bundle is Translocated from %@", __FUNCTION__, result);
return result;
}
}

NSLog(@"%s: Translocation not in effect", __FUNCTION__);
return bundleURL;
}

static NSString *PreferredInstallLocation(BOOL *isUserDirectory) {
// Return the preferred install location.
// Assume that if the user has a ~/Applications folder, they'd prefer their
Expand Down

0 comments on commit e60633c

Please sign in to comment.