How to deserialize the IPXDefaultLibraryURLBookmark of the Photos plist

218 Views Asked by At

So, I've been trying to deserialize the IPXDefaultLibraryURLBookmark of the com.apple.Photos defaults (defaults read com.apple.Photos IPXDefaultLibraryURLBookmark) but no luck. Ideally I'd like a programmatic way in c++ to deserialize that value to retrieve the last known location of the photo

bookd0xUsersmateuscbPicturesPhotos Library.photoslibrary 0@˜ì5$r$Éò|åú¨A∫˙æJ   file:///Macintosh HDÇ1tA∫‘}•$6465C0A4-1771-3C89-9055-147CEDFBBF2EÅÔ/∆72cd528f2dcfb4b3434986cf3caa02cc946333b8;00000000;00000000;0000000000000020;com.apple.app-sandbox.read-write;00000001;01000004;0000000002980783;/users/mateuscb/pictures/photos library.photoslibrary¥˛ˇˇˇdº‰@‘ î   H ( 8  t0 †–Ä®

I know its not a bplist, since the first format specifier denotes bookd.

But I have no clue what that is. I'm somewhat new to OSX development, so this may be something very basic I'm missing.

I want to retrieve the: /users/mateuscb/pictures/photos library.photoslibrary portion so I can find the defaults photoslibrary.

Unless there is another way to retrieve the default photoslibrary path?

1

There are 1 best solutions below

0
On BEST ANSWER

I figured out how to retrieve the path to the .photoslibrary. I used CFURLCreateByResolvingBookmarkData to get a CFURLRef from the plist then used CFURLGetFileSystemRepresentation to get the full path as a string.

Help from this sample to retrieve sandbox preferences: https://gist.github.com/glebd/4759724

Here is my full solution:

int main(int argc, const char * argv[]) {
    bool success = FALSE;
    UInt8 photosUrlString[PATH_MAX];

    struct passwd *pwd = getpwuid(getuid());
    if (pwd ==  NULL){
        Log("Unable to retrieve current user");
        return 0;
    }

    const char *home = pwd->pw_dir;
    if (home ==  NULL){
        Log("Unable to retrieve current user directory");
        return 0;
    }


    CFMutableStringRef preferencesPath = CFStringCreateMutable(NULL, 0);
    if (preferencesPath) {
        CFStringAppend(preferencesPath, CFStringCreateWithCStringNoCopy(NULL, home, kCFStringEncodingUTF8, NULL));
        CFStringAppend(preferencesPath, CFSTR("/Library/Containers/com.apple.Photos/Data/Library/Preferences/com.apple.Photos"));
    } else {
        Log("Unable to create CFString of user directory");
        return 0;
    }

    CFPropertyListRef photosUrlPrefs = CFPreferencesCopyValue(CFSTR("IPXDefaultLibraryURLBookmark"), preferencesPath, kCFPreferencesCurrentUser, kCFPreferencesCurrentHost);
    CFRelease(preferencesPath);

    if (photosUrlPrefs) {
        CFTypeID prefsType = CFGetTypeID(photosUrlPrefs);
        if (CFDataGetTypeID() == prefsType) {
            CFDataRef photosUrlData = (CFDataRef) photosUrlPrefs;
            CFErrorRef urlResolveError = nil;
            CFURLRef photosUrl = CFURLCreateByResolvingBookmarkData(kCFAllocatorDefault, photosUrlData, NULL, NULL, NULL, NULL, &urlResolveError);
            if (photosUrl == NULL) {
                if(urlResolveError != NULL) {
                    CFStringRef resolveErrorString = CFErrorCopyDescription(urlResolveError);
                    if (resolveErrorString != NULL) {
                        char resolveErrorCString[PATH_MAX];
                        if (CFStringGetCString((CFStringRef) resolveErrorString, resolveErrorCString, sizeof(resolveErrorCString), kCFStringEncodingUTF8)) {
                            Log("Error resolving URL: %s", resolveErrorCString);
                        }
                        CFRelease(resolveErrorString);
                    }
                } else {
                    Log("Error resolving URL, no resolveError");
                }
            } else {
                success = CFURLGetFileSystemRepresentation(photosUrl, false, photosUrlString, sizeof(photosUrlString));
                CFRelease(photosUrl);
            }
        } else {
            Log("Url plist value is not CFData");
        }

        if (photosUrlPrefs != NULL) {
            CFRelease(photosUrlPrefs);
        }
    }

    if(success) {
        Log("path: %s", photosUrlString);
    }

    return 0;
}