Skip to content

Commit a7cc028

Browse files
committed
2 parents 70c5772 + 8714292 commit a7cc028

1 file changed

Lines changed: 52 additions & 1 deletion

File tree

PFMoveApplication.m

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ + (NSBundle *)bundle {
4949
static BOOL MoveInProgress = NO;
5050

5151
// Helper functions
52+
static NSURL * GetOriginalBundleURL(void);
5253
static NSString *PreferredInstallLocation(BOOL *isUserDirectory);
5354
static BOOL IsInApplicationsFolder(NSString *path);
5455
static BOOL IsInDownloadsFolder(NSString *path);
@@ -78,7 +79,7 @@ void PFMoveToApplicationsFolderIfNecessary(void) {
7879
if ([[NSUserDefaults standardUserDefaults] boolForKey:AlertSuppressKey]) return;
7980

8081
// Path of the bundle
81-
NSString *bundlePath = [[NSBundle mainBundle] bundlePath];
82+
NSString *bundlePath = GetOriginalBundleURL().path;
8283

8384
// Check if the bundle is embedded in another application
8485
BOOL isNestedApplication = IsApplicationAtPathNested(bundlePath);
@@ -239,6 +240,56 @@ BOOL PFMoveIsInProgress() {
239240
#pragma mark -
240241
#pragma mark Helper Functions
241242

243+
/// Gets the real bundle path of the application, not the Translocated one if applicable
244+
static NSURL * GetOriginalBundleURL(void) {
245+
246+
NSURL * bundleURL = [NSBundle mainBundle].bundleURL;
247+
NSLog(@"%s: Foundation says bundle URL is %@", __FUNCTION__, bundleURL);
248+
249+
// #define NSAppKitVersionNumber10_11 1404
250+
if (floor(NSAppKitVersionNumber) <= 1404) {
251+
return bundleURL;
252+
}
253+
254+
void * handle = dlopen("/System/Library/Frameworks/Security.framework/Security", RTLD_LAZY);
255+
if (handle == NULL) {
256+
return bundleURL;
257+
}
258+
259+
bool isTranslocated = false;
260+
261+
// Get (undocumented?) function symbols for looking up app translocation info
262+
// Note: <Security/SecTranslocation.h> was available in the macOS 10.12 beta SDKs but seems to have been removed as of Xcode 8.1
263+
// see https://opensource.apple.com/source/Security/Security-58286.70.7/OSX/libsecurity_translocate/lib/SecTranslocate.h.auto.html
264+
265+
typedef Boolean (*SecTranslocateIsTranslocatedURL_t)(CFURLRef path, bool *isTranslocated, CFErrorRef * __nullable error);
266+
SecTranslocateIsTranslocatedURL_t mySecTranslocateIsTranslocatedURL = (SecTranslocateIsTranslocatedURL_t)dlsym(handle, "SecTranslocateIsTranslocatedURL");
267+
268+
typedef CFURLRef __nullable(*SecTranslocateCreateOriginalPathForURL_t)(CFURLRef translocatedPath, CFErrorRef * __nullable error);
269+
SecTranslocateCreateOriginalPathForURL_t mySecTranslocateCreateOriginalPathForURL = (SecTranslocateCreateOriginalPathForURL_t)dlsym(handle, "SecTranslocateCreateOriginalPathForURL");
270+
271+
dlclose(handle);
272+
273+
if (mySecTranslocateIsTranslocatedURL == NULL || mySecTranslocateCreateOriginalPathForURL == NULL) {
274+
NSLog(@"%s: We're running on macOS >= 10.12 but the SecTranslocate functions are not available", __FUNCTION__);
275+
return bundleURL;
276+
}
277+
278+
if (mySecTranslocateIsTranslocatedURL((__bridge CFURLRef)bundleURL, &isTranslocated, NULL) && isTranslocated)
279+
{
280+
CFURLRef originalURL = mySecTranslocateCreateOriginalPathForURL((__bridge CFURLRef)bundleURL, NULL);
281+
if (originalURL != NULL)
282+
{
283+
NSURL * result = CFBridgingRelease(originalURL);
284+
NSLog(@"%s: Security says bundle is Translocated from %@", __FUNCTION__, result);
285+
return result;
286+
}
287+
}
288+
289+
NSLog(@"%s: Translocation not in effect", __FUNCTION__);
290+
return bundleURL;
291+
}
292+
242293
static NSString *PreferredInstallLocation(BOOL *isUserDirectory) {
243294
// Return the preferred install location.
244295
// Assume that if the user has a ~/Applications folder, they'd prefer their

0 commit comments

Comments
 (0)