1111
1212@implementation QSSharedFileListSource
1313
14+ /* *
15+ * Returns the valid path for an SFL file.
16+ * Tries .sfl3, .sfl2, and .sfl extensions in order.
17+ * @return NSString path, or nil if no valid file exists
18+ */
19+ - (NSString *)validPathForSfl : (NSString *)sflPath
20+ {
21+ NSString *basePath = [sflPath stringByStandardizingPath ];
22+ // Strip any existing .sfl* extension
23+ basePath = [basePath stringByDeletingPathExtension ];
24+
25+ // Try extensions in order: .sfl3, .sfl2, .sfl
26+ NSFileManager *manager = [NSFileManager defaultManager ];
27+ NSArray *extensions = @[@" .sfl3" , @" .sfl2" , @" .sfl" ];
28+ for (NSString *ext in extensions) {
29+ NSString *testPath = [basePath stringByAppendingString: ext];
30+ BOOL isDir = NO ;
31+ if ([manager fileExistsAtPath: testPath isDirectory: &isDir] && !isDir) {
32+ return testPath;
33+ }
34+ }
35+ return nil ;
36+ }
37+
1438- (BOOL )indexIsValidFromDate : (NSDate *)indexDate forEntry : (NSDictionary *)theEntry
1539{
1640 NSDictionary *settings = [theEntry objectForKey: kItemSettings ];
1741 NSString *sflPath = [settings objectForKey: kItemPath ];
1842 if (!sflPath) {
1943 return YES ;
2044 }
21- NSString *path = [sflPath stringByStandardizingPath ];
22- if ([NSApplication isHighSierra ]) {
23- path = [path stringByReplacingOccurrencesOfString: @" .sfl" withString: @" .sfl2" ];
24- }
25- NSFileManager *manager = [NSFileManager defaultManager ];
26- BOOL isDir = NO ;
27- if (![[NSFileManager defaultManager ] fileExistsAtPath: path isDirectory: &isDir] || isDir) {
45+
46+ NSString *path = [self validPathForSfl: sflPath];
47+ if (!path) {
2848 return YES ;
2949 }
50+
51+ NSFileManager *manager = [NSFileManager defaultManager ];
3052 NSDate *modDate = [[manager attributesOfItemAtPath: path error: NULL ] fileModificationDate ];
3153 if ([modDate compare: indexDate] == NSOrderedDescending) {
3254 return NO ;
@@ -39,29 +61,45 @@ - (NSArray *)objectsForEntry:(NSDictionary *)theEntry
3961 NSDictionary *settings = [theEntry objectForKey: kItemSettings ];
4062 NSMutableArray *sflItemArray = [NSMutableArray arrayWithCapacity: 0 ];
4163 NSString *sflPath = [settings objectForKey: kItemPath ];
42- NSString *path = [sflPath stringByStandardizingPath ];
43- if ([NSApplication isHighSierra ]) {
44- path = [path stringByReplacingOccurrencesOfString: @" .sfl" withString: @" .sfl2" ];
45- }
46- BOOL isDir = NO ;
47- if (![[NSFileManager defaultManager ] fileExistsAtPath: path isDirectory: &isDir] || isDir) {
64+
65+ NSString *path = [self validPathForSfl: sflPath];
66+ if (!path) {
4867 return nil ;
4968 }
69+
70+ NSString *extension = [path pathExtension ];
71+
5072 NSDictionary *sflData = [NSKeyedUnarchiver unarchiveObjectWithFile: path];
5173 NSString *kItems = @" items" ;
5274 if (![[sflData allKeys ] containsObject: kItems ]) {
5375 return nil ;
5476 }
55- if ([NSApplication isHighSierra ]) {
77+
78+ // Parse based on file extension: sfl2 and sfl3 use bookmark data, sfl uses SFLListItem
79+ if ([extension isEqualToString: @" sfl2" ] || [extension isEqualToString: @" sfl3" ]) {
5680 return [sflData[kItems ] arrayByEnumeratingArrayUsingBlock: ^id (NSDictionary *item) {
57- NSData *bookmarkData = item[@" Bookmark" ];
81+ // Bookmark data might be direct NSData or wrapped in a dictionary with NS.data key
82+ id bookmarkValue = item[@" Bookmark" ];
83+ NSData *bookmarkData = nil ;
84+
85+ if ([bookmarkValue isKindOfClass: [NSData class ]]) {
86+ bookmarkData = bookmarkValue;
87+ } else if ([bookmarkValue isKindOfClass: [NSDictionary class ]]) {
88+ // Try NS.data key (common in sfl3)
89+ bookmarkData = bookmarkValue[@" NS.data" ];
90+ }
91+
92+ if (!bookmarkData) {
93+ return nil ;
94+ }
95+
5896 NSURL *url = [NSURL URLByResolvingBookmarkData: bookmarkData options: NSURLBookmarkResolutionWithoutUI|NSURLBookmarkResolutionWithoutMounting relativeToURL: nil bookmarkDataIsStale: nil error: nil ];
5997 if ([url isFileURL ]) {
6098 return [QSObject fileObjectWithFileURL: url];
6199 }
62100 return [QSObject URLObjectWithURL: [url absoluteString ] title: item[@" Name" ]];
63101 }];
64- } else {
102+ } else if ([extension isEqualToString: @" sfl " ]) {
65103 for (SFLListItem *item in sflData[kItems ]) {
66104 // item's class is SFLListItem
67105 if ([item URL ]) {
0 commit comments