如何反序列化照片 plist 的 IPXDefaultLibraryURLBookmark

How to deserialize the IPXDefaultLibraryURLBookmark of the Photos plist

所以,我一直在尝试反序列化 com.apple.Photos 默认值 (defaults read com.apple.Photos IPXDefaultLibraryURLBookmark) 的 IPXDefaultLibraryURLBookmark,但没有成功。理想情况下,我希望在 C++ 中以编程方式反序列化该值以检索照片的最后已知位置

bookd0xUsersmateuscbPicturesPhotos Library.photoslibrary 0@˜ì5$r$Éò|åú¨A∫˙æJ   file:///Macintosh HDÇ1tA∫‘}•65C0A4-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 †–Ä®

我知道它不是 bplist,因为第一个格式说明符表示 bookd

但我不知道那是什么。我对 OSX 开发有些陌生,所以这可能是我所缺少的非常基本的东西。

我想检索:/users/mateuscb/pictures/photos library.photoslibrary 部分以便找到默认照片库。

除非有另一种方法来检索默认的照片库路径?

我想出了如何检索 .photoslibrary 的路径。我使用 CFURLCreateByResolvingBookmarkData 从 plist 中获取 CFURLRef,然后使用 CFURLGetFileSystemRepresentation 获取字符串形式的完整路径。

通过此示例帮助检索沙盒首选项:https://gist.github.com/glebd/4759724

这是我的完整解决方案:

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;
}