summaryrefslogtreecommitdiffstats
path: root/Plugins/BuiltInFunctions/LiBuiltInFunctions.m
diff options
context:
space:
mode:
authorBrian Cully <bjc@kublai.com>2008-04-14 21:45:08 -0400
committerBrian Cully <github.20.shmit@spamgourmet.com>2008-04-14 21:45:08 -0400
commit17349a5e426dc7acf1216a3767a22f69974cbca0 (patch)
tree20029d02f07ab6257cccec36d34fb312f796e1d1 /Plugins/BuiltInFunctions/LiBuiltInFunctions.m
downloadliaison-17349a5e426dc7acf1216a3767a22f69974cbca0.tar.gz
liaison-17349a5e426dc7acf1216a3767a22f69974cbca0.zip
Initial commit.
Diffstat (limited to 'Plugins/BuiltInFunctions/LiBuiltInFunctions.m')
-rw-r--r--Plugins/BuiltInFunctions/LiBuiltInFunctions.m1027
1 files changed, 1027 insertions, 0 deletions
diff --git a/Plugins/BuiltInFunctions/LiBuiltInFunctions.m b/Plugins/BuiltInFunctions/LiBuiltInFunctions.m
new file mode 100644
index 0000000..a7c3fed
--- /dev/null
+++ b/Plugins/BuiltInFunctions/LiBuiltInFunctions.m
@@ -0,0 +1,1027 @@
+//
+// LiBuiltInFunctions.m
+// Liaison
+//
+// Created by Brian Cully on Tue May 13 2003.
+// Copyright (c) 2003 Brian Cully. All rights reserved.
+//
+
+#import "LiBuiltInFunctions.h"
+
+#import "FileSizeFormatter.h"
+#import "InspectorViewController.h"
+#import "NaturalDateFormatter.h"
+
+#import "IconFamily.h"
+
+static NSString *
+myLocalizedString(NSString *aString)
+{
+ return NSLocalizedStringFromTableInBundle(aString, @"BuiltInFunctions",
+ [LiBuiltInFunctions bundle], @"");
+}
+
+static NSString *
+myLocalizedErrorString(NSString *aString)
+{
+ return NSLocalizedStringFromTableInBundle(aString, @"ErrorMessages",
+ [LiBuiltInFunctions bundle], @"");
+}
+
+@implementation LiBuiltInFunctions
+static NSBundle *theBundle = nil;
+
++ (NSBundle *)bundle
+{
+ return theBundle;
+}
+
++ (void)setBundle: (NSBundle *)aBundle
+{
+ [aBundle retain];
+ [theBundle release];
+ theBundle = aBundle;
+}
+
+- (void)convertGroupDict: (NSDictionary *)someGroups
+{
+ NSArray *groupNames;
+ NSMutableDictionary *defaultGroups;
+ NSMutableSet *myGroups;
+ NSString *libraryName;
+
+ libraryName = [someGroups objectForKey: @"name"];
+ groupNames = [someGroups objectForKey: @"children"];
+
+ myGroups = [NSMutableSet setWithArray: groupNames];
+
+ if (libraryName != nil)
+ [[self fileStore] setName: libraryName];
+
+ defaultGroups = [NSMutableDictionary dictionaryWithObject: myGroups forKey: LiGroupsAttribute];
+ [self setDefaultAttributes: defaultGroups];
+}
+
+- (void)loadDefaultAttrs
+{
+ NSDictionary *defaultAttrDict;
+
+ defaultAttrDict = [NSDictionary dictionaryWithContentsOfFile: [[Preferences sharedPreferences] groupPath]];
+ if (defaultAttrDict != nil) {
+ NSNumber *versionNumber;
+
+ versionNumber = [defaultAttrDict objectForKey: @"LiDBVersion"];
+ if ([versionNumber intValue] == 1) {
+ NSDictionary *flattenedDefaults;
+ NSEnumerator *defaultEnum;
+ NSMutableDictionary *myDefaults;
+ NSString *attr;
+
+ [LiLog logAsDebug: @"Load my version group dict"];
+ myDefaults = [NSMutableDictionary dictionary];
+ flattenedDefaults = [defaultAttrDict objectForKey: @"LiDefaultAttributes"];
+ defaultEnum = [flattenedDefaults keyEnumerator];
+ while ((attr = [defaultEnum nextObject]) != nil) {
+ NSMutableSet *values;
+
+ values = [NSMutableSet setWithArray: [flattenedDefaults objectForKey: attr]];
+ [myDefaults setObject: values forKey: attr];
+ }
+ [self setDefaultAttributes: myDefaults];
+ } else {
+ [self convertGroupDict: defaultAttrDict];
+ }
+ }
+}
+
+- (BOOL)synchronizeDefaultAttrs
+{
+ NSDictionary *defaultDict;
+ NSEnumerator *defaultEnum;
+ NSMutableDictionary *flattenedDefaults;
+ NSString *attr;
+
+ flattenedDefaults = [NSMutableDictionary dictionary];
+ defaultEnum = [[self defaultAttributes] keyEnumerator];
+ while ((attr = [defaultEnum nextObject]) != nil) {
+ NSArray *values;
+
+ values = [[[self defaultAttributes] objectForKey: attr] allObjects];
+ [flattenedDefaults setObject: values forKey: attr];
+ }
+
+ defaultDict = [NSDictionary dictionaryWithObjects:
+ [NSArray arrayWithObjects: [NSNumber numberWithInt: 1], flattenedDefaults, nil]
+ forKeys:
+ [NSArray arrayWithObjects: @"LiDBVersion", @"LiDefaultAttributes", nil]];
+
+ return [defaultDict writeToFile: [[Preferences sharedPreferences] groupPath] atomically: YES];
+}
+
+- (id)init
+{
+ NSImage *image;
+ NSString *iconPath;
+
+ self = [super init];
+
+ [self loadDefaultAttrs];
+
+ // Register often-used images.
+ iconPath = [[NSBundle bundleForClass: [self class]] pathForResource: @"NotThere" ofType: @"icns"];
+ image = [[NSImage alloc] initWithContentsOfFile: iconPath];
+ [image setName: @"LiBuiltInFunctions NotThereImage"];
+
+ iconPath = [[NSBundle bundleForClass: [self class]] pathForResource: @"local" ofType: @"tiff"];
+ image = [[NSImage alloc] initWithContentsOfFile: iconPath];
+ [image setName: @"LiBuiltInFunctions FileStoreIcon"];
+
+ return self;
+}
+
+- (void)dealloc
+{
+ NSImage *image;
+
+ [self setDefaultAttributes: nil];
+
+ // XXX - should this be done this way?
+ image = [NSImage imageNamed: @"LiBuiltInFunctions NotThereImage"];
+ [image setName: nil];
+ [image release];
+ image = [NSImage imageNamed: @"LiBuiltInFunctions FileStoreIcon"];
+ [image setName: nil];
+ [image release];
+
+ [super dealloc];
+}
+
+- (LiBrowserColumn *)columnForIcon
+{
+ LiBrowserColumn *col;
+
+ col = [[[LiBrowserColumn alloc] init] autorelease];
+ [col setIdentifier: @"icon"];
+ [col setName: myLocalizedString(@"IconHeader")];
+ [col setCell: [[[NSImageCell alloc] init] autorelease]];
+ [col setWidth: [NSNumber numberWithFloat: 16.0]];
+ [col setEditable: NO];
+ [col setResizable: NO];
+ [col setShowsHeader: NO];
+ [col setGetMethod: @selector(icon)];
+
+ return col;
+}
+
+- (LiBrowserColumn *)columnForFilename
+{
+ LiBrowserColumn *col;
+ NSCell *cell;
+
+ col = [[[LiBrowserColumn alloc] init] autorelease];
+ [col setIdentifier: @"filename"];
+ [col setName: myLocalizedString(@"FilenameHeader")];
+ cell = [[[NSTextFieldCell alloc] init] autorelease];
+ [cell setEditable: YES];
+ [col setCell: cell];
+ [col setEditable: YES];
+ [col setShowsHeader: YES];
+ [col setGetMethod: @selector(filename)];
+ [col setSetMethod: @selector(setFilename:)];
+ [col setCompareMethod: @selector(caseInsensitiveCompare:)];
+
+ return col;
+}
+
+- (LiFilterDescription *)descriptionForFilename
+{
+ LiFilterDescription *description;
+ NSCell *cell;
+ NSDictionary *compareOps;
+
+ compareOps = [NSDictionary dictionaryWithObjects:
+ [NSArray arrayWithObjects: @"isEqualToString:",
+ @"containsString:", nil]
+ forKeys:
+ [NSArray arrayWithObjects: myLocalizedString(@"LiEqualsOperator"),
+ myLocalizedString(@"LiContainsOperator"), nil]];
+ cell = [[[NSTextFieldCell alloc] init] autorelease];
+ [cell setEditable: YES];
+ description = [LiFilterDescription descriptionForMethod: @selector(filename)
+ name: myLocalizedString(LiFilenameAttribute)
+ compareOperators: compareOps
+ valueEditorCell: cell];
+
+ return description;
+}
+
+- (LiBrowserColumn *)columnForType
+{
+ LiBrowserColumn *col;
+ NSCell *cell;
+
+ col = [[[LiBrowserColumn alloc] init] autorelease];
+ [col setIdentifier: @"type"];
+ [col setName: myLocalizedString(@"TypeHeader")];
+ cell = [[[NSTextFieldCell alloc] init] autorelease];
+ [cell setEditable: YES];
+ [col setCell: cell];
+ [col setEditable: YES];
+ [col setShowsHeader: YES];
+ [col setGetMethod: @selector(type)];
+ [col setSetMethod: @selector(setType:)];
+ [col setCompareMethod: @selector(caseInsensitiveCompare:)];
+
+ return col;
+}
+
+- (LiBrowserColumn *)columnForLastModified
+{
+ LiBrowserColumn *col;
+ NSCell *cell;
+
+ col = [[[LiBrowserColumn alloc] init] autorelease];
+ [col setIdentifier: @"lastModified"];
+ [col setName: myLocalizedString(@"LastModifiedTimeHeader")];
+ cell = [[[NSTextFieldCell alloc] init] autorelease];
+ [cell setFormatter: [[[NaturalDateFormatter alloc] initWithNaturalLanguage: YES] autorelease]];
+ [cell setEditable: YES];
+ [cell setAlignment: NSRightTextAlignment];
+ [col setCell: cell];
+ [col setEditable: YES];
+ [col setShowsHeader: YES];
+ [col setGetMethod: @selector(lastModifiedTime)];
+ [col setSetMethod: @selector(setLastModifiedTime:)];
+ [col setCompareMethod: @selector(compare:)];
+
+ return col;
+}
+
+- (LiBrowserColumn *)columnForCreation
+{
+ LiBrowserColumn *col;
+ NSCell *cell;
+
+ col = [[[LiBrowserColumn alloc] init] autorelease];
+ [col setIdentifier: @"creation"];
+ [col setName: myLocalizedString(@"CreatedTimeHeader")];
+ cell = [[[NSTextFieldCell alloc] init] autorelease];
+ [cell setFormatter: [[[NaturalDateFormatter alloc] initWithNaturalLanguage: YES] autorelease]];
+ [cell setEditable: YES];
+ [cell setAlignment: NSRightTextAlignment];
+ [col setCell: cell];
+ [col setEditable: YES];
+ [col setShowsHeader: YES];
+ [col setGetMethod: @selector(creationTime)];
+ [col setSetMethod: @selector(setCreationTime:)];
+ [col setCompareMethod: @selector(compare:)];
+
+ return col;
+}
+
+- (LiBrowserColumn *)columnForSize
+{
+ LiBrowserColumn *col;
+ FileSizeFormatter *cellFormatter;
+ NSCell *cell;
+
+ col = [[[LiBrowserColumn alloc] init] autorelease];
+ [col setIdentifier: @"size"];
+ [col setName: myLocalizedString(@"FileSizeHeader")];
+ cell = [[[NSTextFieldCell alloc] init] autorelease];
+ cellFormatter = [[[FileSizeFormatter alloc] init] autorelease];
+ [cellFormatter setAllowsFloats: NO];
+ [cell setFormatter: cellFormatter];
+ [cell setAlignment: NSRightTextAlignment];
+ [col setCell: cell];
+ [col setEditable: NO];
+ [col setShowsHeader: YES];
+ [col setGetMethod: @selector(fileSize)];
+ [col setCompareMethod: @selector(compare:)];
+
+ return col;
+}
+
+- (NSArray *)columns
+{
+ NSArray *columns;
+
+ columns = [NSArray arrayWithObjects:
+ [self columnForIcon], [self columnForFilename], [self columnForType],
+ [self columnForLastModified], [self columnForCreation],
+ [self columnForSize], nil];
+
+ return columns;
+}
+
+- (NSDictionary *)filterDescriptions
+{
+ NSDictionary *descriptions;
+
+ descriptions = [NSDictionary dictionaryWithObjects:
+ [NSArray arrayWithObjects: [self descriptionForFilename], nil]
+ forKeys:
+ [NSArray arrayWithObjects: LiFilenameAttribute, nil]];
+
+ return descriptions;
+}
+
+- (LiInspectorView *)viewForFile
+{
+ LiInspectorView *view;
+
+ view = [[[LiInspectorView alloc] init] autorelease];
+ [view setIdentifier: @"file"];
+ [view setName: @"File"];
+ [view setImage: nil];
+ [view setView: [[self viewController] fileView]];
+ [view setIsVerticallyResizable: NO];
+ [view setIsHorizontallyResizable: YES];
+ [view setViewSize: [[view view] frame].size];
+
+ return view;
+}
+
+- (LiInspectorView *)viewForHFS
+{
+ LiInspectorView *view;
+
+ view = [[[LiInspectorView alloc] init] autorelease];
+ [view setIdentifier: @"hfs"];
+ [view setName: @"HFS"];
+ [view setImage: nil];
+ [view setIsVerticallyResizable: NO];
+ [view setIsHorizontallyResizable: NO];
+ [view setView: [[self viewController] hfsView]];
+ [view setViewSize: [[view view] frame].size];
+
+ return view;
+}
+
+- (NSArray *)allInspectorViews
+{
+ return [NSArray arrayWithObjects: [self viewForFile], [self viewForHFS], nil];
+}
+
+- (NSArray *)inspectorViewsForFile: (LiFileHandle *)aFile
+{
+ if (aFile != nil) {
+ NSMutableArray *viewArray;
+
+ viewArray = [NSMutableArray arrayWithObject: [self viewForFile]];
+ [viewArray addObject: [self viewForHFS]];
+ return viewArray;
+ }
+ return nil;
+}
+
+- (void)setFile: (LiFileHandle *)aFile
+{
+ if (aFile != nil) {
+ [[self viewController] setFile: aFile];
+ }
+}
+
+//
+// File store delegate stuff.
+//
+- (void)openFileHandle: (LiFileHandle *)aFileHandle
+{
+ NSString *path;
+
+ path = [aFileHandle path];
+ if (path != nil) {
+ [[NSWorkspace sharedWorkspace] openFile: [aFileHandle path]];
+ [[NSDocumentController sharedDocumentController] noteNewRecentDocumentURL: [NSURL fileURLWithPath: [aFileHandle path]]];
+ } else {
+ [LiLog alertWithHeader: @"Couldn't locate file" contents: @"This message sucks and will be changed so you can locate the file again."];
+ }
+}
+
+- (void)copyFile: (LiFileHandle *)aFileHandle
+{
+ [LiLog logAsDebug: @"should copy %@", [aFileHandle filename]];
+}
+
+- (NSDictionary *)fileSystemAttributesForPath: (NSString *)aPath
+{
+ NSMutableDictionary *tmpAttributes;
+
+ tmpAttributes = nil;
+ if (aPath != nil) {
+ BDAlias *alias;
+ NSString *filename, *filetype, *dir;
+
+ // Set the attributes that are valid for every file with a path.
+ tmpAttributes = [NSMutableDictionary dictionary];
+ filename = [[aPath lastPathComponent] stringByDeletingPathExtension];
+ filetype = [aPath pathExtension];
+ dir = [aPath stringByDeletingLastPathComponent];
+ [tmpAttributes setObject: filename forKey: LiFilenameAttribute];
+ [tmpAttributes setObject: filetype forKey: LiTypeAttribute];
+ [tmpAttributes setObject: dir forKey: LiDirectoryAttribute];
+
+ // Test if the file is resolvable by getting its alias.
+ alias = [BDAlias aliasWithPath: aPath];
+ if (alias != nil) {
+ NSDate *modifiedTime, *createdTime;
+ NSDictionary *fileAttrs;
+ NSFileWrapper *file;
+ NSNumber *fileSize, *hfsCreator, *hfsType;
+ NSString *application;
+
+ [tmpAttributes setObject: [alias aliasData]
+ forKey: LiAliasDataAttribute];
+
+ file = [[NSFileWrapper alloc] initWithPath: aPath];
+ fileAttrs = [[NSFileManager defaultManager] fileAttributesAtPath: aPath traverseLink: YES];
+
+ // Load attributes from disk.
+ modifiedTime = [fileAttrs objectForKey: NSFileModificationDate];
+ createdTime = [fileAttrs objectForKey: NSFileCreationDate];
+ fileSize = [fileAttrs objectForKey: NSFileSize];
+ hfsCreator = [fileAttrs objectForKey: NSFileHFSCreatorCode];
+ hfsType = [fileAttrs objectForKey: NSFileHFSTypeCode];
+ [[NSWorkspace sharedWorkspace] getInfoForFile: aPath
+ application: &application
+ type: &filetype];
+ if (modifiedTime != nil)
+ [tmpAttributes setObject: modifiedTime
+ forKey: LiLastModifiedDateAttribute];
+ if (createdTime != nil)
+ [tmpAttributes setObject: createdTime
+ forKey: LiCreationDateAttribute];
+ if (fileSize != nil)
+ [tmpAttributes setObject: fileSize
+ forKey: LiFileSizeAttribute];
+ if (application != nil)
+ [tmpAttributes setObject: application
+ forKey: LiApplicationAttribute];
+ if (hfsCreator != nil)
+ [tmpAttributes setObject: hfsCreator
+ forKey: LiHFSCreatorAttribute];
+ if (hfsType != nil)
+ [tmpAttributes setObject: hfsType
+ forKey: LiHFSTypeAttribute];
+ [tmpAttributes setObject: [NSNumber numberWithBool: YES]
+ forKey: LiIsEditableAttribute];
+
+ [file release];
+ } else {
+ [tmpAttributes setObject: [NSNumber numberWithBool: NO]
+ forKey: LiIsEditableAttribute];
+ }
+ }
+
+ return tmpAttributes;
+}
+
+- (NSDictionary *)fileSystemAttributesForAliasData: (NSData *)aliasData
+{
+ BDAlias *alias;
+
+ alias = [BDAlias aliasWithData: aliasData];
+ return [self fileSystemAttributesForPath: [alias fullPath]];
+}
+
+- (void)convertFirstVersionDict: (NSDictionary *)fileDict
+ fileStore: (LiFileStore *)aFileStore
+{
+ NSDictionary *filesInDict, *attrDict;
+ NSEnumerator *fileEnum;
+
+ filesInDict = [fileDict objectForKey: @"files"];
+ fileEnum = [filesInDict objectEnumerator];
+ while ((attrDict = [fileEnum nextObject]) != nil) {
+ NSData *fileAlias;
+ NSDictionary *fileAttrs;
+ NSEnumerator *groupEnum;
+ NSMutableArray *fileGroups;
+ NSMutableDictionary *myFileAttrs;
+ NSNumber *fileHandle;
+ NSString *groupname;
+
+ fileHandle = [attrDict objectForKey: @"filehandle"];
+ fileAlias = [attrDict objectForKey: @"alias"];
+
+ fileAttrs = [self fileSystemAttributesForAliasData:
+ fileAlias];
+ if (fileAttrs == nil) {
+ [LiLog logAsWarning: @"Couldn't load attributes for %@: abandoning.",
+ [attrDict objectForKey: @"path"]];
+ }
+ myFileAttrs = [NSMutableDictionary dictionaryWithDictionary: fileAttrs];
+ [myFileAttrs setObject: fileHandle forKey: LiFileHandleAttribute];
+
+ fileGroups = [NSMutableArray array];
+ groupEnum = [[attrDict objectForKey: @"groups"] objectEnumerator];
+ while ((groupname = [groupEnum nextObject]) != nil) {
+ if ([groupname isEqualToString: @"/"] == NO)
+ [fileGroups addObject: groupname];
+ }
+ [myFileAttrs setObject: fileGroups forKey: LiGroupsAttribute];
+
+ [aFileStore addFileWithAttributes: myFileAttrs];
+ }
+}
+
+- (BOOL)loadFileStore: (LiFileStore *)aFileStore
+{
+ NSDictionary *fileStoreDict;
+
+ // Make sure we have the right indexes.
+ [aFileStore addIndexForAttribute: LiGroupsAttribute];
+ [aFileStore addIndexForAttribute: LiAliasDataAttribute];
+
+ fileStoreDict = [NSDictionary dictionaryWithContentsOfFile: [[Preferences sharedPreferences] libraryPath]];
+ if (fileStoreDict != nil) {
+ NSNumber *versionNumber;
+
+ versionNumber = [fileStoreDict objectForKey: @"LiDBVersion"];
+ if ([versionNumber intValue] == 1) {
+ NSArray *allFiles;
+ NSDictionary *fileDict;
+
+ allFiles = [fileStoreDict objectForKey: @"LiFileStore"];
+ for (fileDict in allFiles) {
+ BDAlias *alias;
+ NSMutableDictionary *baseAttrs;
+
+ baseAttrs = [[NSMutableDictionary alloc] initWithDictionary: fileDict];
+
+ alias = [[BDAlias alloc] initWithData: [fileDict objectForKey: LiAliasDataAttribute]];
+ if ([alias fullPath] == nil) {
+ NSString *path, *filename, *directory;
+
+ directory = [fileDict objectForKey: LiDirectoryAttribute];
+ filename = [[fileDict objectForKey: LiFilenameAttribute] stringByAppendingPathExtension: [fileDict objectForKey: LiTypeAttribute]];
+ path = [directory stringByAppendingPathComponent: filename];
+
+ [LiLog logAsDebug: @"Couldn't locate file: %@ - (dir: %@, path: %@)", filename, directory, path];
+
+ alias = [[BDAlias alloc] initWithPath: path];
+ if ([alias fullPath] != nil) {
+ [baseAttrs setObject: [[alias fullPath] stringByDeletingLastPathComponent] forKey: LiDirectoryAttribute];
+ [baseAttrs setObject: [alias aliasData] forKey: LiAliasDataAttribute];
+ }
+ }
+
+ if ([alias aliasData] == nil) {
+ [baseAttrs setObject: [NSNumber numberWithBool: NO] forKey: LiIsEditableAttribute];
+ } else {
+ [baseAttrs setObject: [NSNumber numberWithBool: YES] forKey: LiIsEditableAttribute];
+ }
+
+ [aFileStore addFileWithAttributes: baseAttrs];
+
+ [baseAttrs release];
+ [alias release];
+ }
+ } else {
+ [self convertFirstVersionDict: fileStoreDict
+ fileStore: aFileStore];
+ }
+ }
+
+ [aFileStore synchronize];
+ return YES;
+}
+
+- (BOOL)synchronizeFileStore
+{
+ LiFileHandle *fileHandle;
+ NSArray *allFileHandles;
+ NSMutableArray *allFiles;
+ NSDictionary *fileDict;
+ NSString *path;
+
+ [LiLog logAsDebug: @"[LiBuiltInFunctions synchronizeFileStore]"];
+ [LiLog indentDebugLog];
+
+ path = [[Preferences sharedPreferences] libraryPath];
+
+ allFiles = [NSMutableArray array];
+ allFileHandles = [[self fileStore] allFileHandles];
+ for (fileHandle in allFileHandles) {
+ NSMutableDictionary *filteredAttrs;
+
+ filteredAttrs = [NSMutableDictionary dictionaryWithDictionary:
+ [fileHandle dictionary]];
+ [allFiles addObject: filteredAttrs];
+ }
+
+ fileDict = [NSDictionary dictionaryWithObjects:
+ [NSArray arrayWithObjects:
+ [NSNumber numberWithInt: 1], allFiles, nil]
+ forKeys:
+ [NSArray arrayWithObjects:
+ @"LiDBVersion", @"LiFileStore", nil]];
+ [LiLog logAsDebug: @"writing to: %@", path];
+ [fileDict writeToFile: path atomically: YES];
+ [LiLog logAsDebug: @"done!"];
+
+ [LiLog unindentDebugLog];
+ return YES;
+}
+
+- (void)synchronizeFileHandle: (LiFileHandle *)aFileHandle
+ withNewAttributes: (NSMutableDictionary *)someAttributes
+{
+ NSDictionary *fileAttrDict;
+ NSEnumerator *attrEnum;
+ NSMutableDictionary *fileAttrs;
+ NSSet *pathSet;
+ NSString *attr;
+ BOOL pathDone;
+
+ [LiLog logAsDebug: @"[LiBuiltInFunctions synchronizeFileHandle: (fh) withNewAttributes: %@]", someAttributes];
+ [LiLog indentDebugLog];
+
+ pathDone = NO;
+ pathSet = [NSSet setWithArray:
+ [NSArray arrayWithObjects:
+ LiDirectoryAttribute, LiFilenameAttribute, LiTypeAttribute, nil]];
+ fileAttrDict = [NSDictionary dictionaryWithObjects:
+ [NSArray arrayWithObjects:
+ NSFileModificationDate, NSFileCreationDate,
+ NSFileHFSCreatorCode, NSFileHFSTypeCode,
+ nil]
+ forKeys:
+ [NSArray arrayWithObjects:
+ LiLastModifiedDateAttribute, LiCreationDateAttribute,
+ LiHFSCreatorAttribute, LiHFSTypeAttribute,
+ nil]];
+
+ fileAttrs = [NSMutableDictionary dictionary];
+ attrEnum = [someAttributes keyEnumerator];
+ while ((attr = [attrEnum nextObject]) != nil) {
+ if (pathDone == NO && [pathSet containsObject: attr]) {
+ NSString *filename, *type;
+ NSString *path, *oldPath;
+
+ filename = [someAttributes objectForKey: LiFilenameAttribute];
+ if (filename == nil)
+ filename = [aFileHandle filename];
+
+ type = [someAttributes objectForKey: LiTypeAttribute];
+ if (type == nil)
+ type = [aFileHandle type];
+
+ path = [someAttributes objectForKey: LiDirectoryAttribute];
+ if (path == nil)
+ path = [aFileHandle directory];
+
+ if (type && [type length] > 0) {
+ filename = [filename stringByAppendingPathExtension: type];
+ }
+ path = [path stringByAppendingPathComponent: filename];
+
+ oldPath = [[aFileHandle alias] fullPath];
+ if ([oldPath isEqualToString: path] == NO) {
+ int rc;
+
+ rc = 0;
+ rc = rename([oldPath UTF8String], [path UTF8String]);
+ if (rc == -1) {
+ NSString *header, *contents;
+
+ switch (errno) {
+ case ENOENT:
+ header = myLocalizedErrorString(@"LiBadFilenameErrorHeader");
+ contents = myLocalizedErrorString(@"LiBadFilenameErrorContents");
+ break;
+
+ case EROFS:
+ header = myLocalizedErrorString(@"LiReadOnlyFileSytemErrorHeader");
+ contents = myLocalizedErrorString(@"LiReadOnlyFileSytemErrorContents");
+ break;
+
+ case EPERM:
+ case EACCES:
+ header = myLocalizedErrorString(@"LiPermissionDeniedErrorHeader");
+ contents = myLocalizedErrorString(@"LiPermissionDeniedErrorContents");
+ break;
+
+ default:
+ header = myLocalizedErrorString(@"LiGenericRenameErrorHeader");
+ contents = myLocalizedErrorString(@"LiGenericRenameErrorContents");
+ }
+ [LiLog alertWithHeader: header contents: contents];
+ }
+ }
+
+ pathDone = YES;
+ } else if ([fileAttrDict objectForKey: attr] != nil) {
+ [fileAttrs setObject: [someAttributes objectForKey: attr]
+ forKey: attr];
+ }
+ }
+
+ if ([fileAttrs count] > 0) {
+ NSFileManager *defaultManager;
+
+ defaultManager = [NSFileManager defaultManager];
+ [defaultManager changeFileAttributes: fileAttrs
+ atPath: [[aFileHandle alias] fullPath]];
+ }
+
+ // XXX - should flag to see if the icon needs updating and
+ // do it here, since we can't scan for that change.
+
+ [LiLog unindentDebugLog];
+}
+
+- (BOOL)shouldUpdateFileHandle: (LiFileHandle *)aFileHandle
+{
+ NSDate *handleDate, *fileDate;
+ NSFileWrapper *file;
+ NSString *newPath;
+
+ newPath = [[aFileHandle alias] fullPath];
+ if ([newPath compare: [aFileHandle path]] != 0)
+ return YES;
+
+ file = [[[NSFileWrapper alloc] initWithPath: newPath] autorelease];
+ fileDate = [[file fileAttributes] objectForKey:
+ NSFileModificationDate];
+ handleDate = [aFileHandle lastModifiedTime];
+
+ if ([fileDate compare: handleDate] == 0)
+ return NO;
+ else
+ return YES;
+}
+
+- (void)updateFileHandle: (LiFileHandle *)aFileHandle
+{
+ NSMutableDictionary *fileAttrs;
+
+ [LiLog logAsDebug: @"[LiBuiltInFunctions updateFileHandle: %@]", [aFileHandle description]];
+ fileAttrs = [NSMutableDictionary dictionaryWithDictionary:
+ [self fileSystemAttributesForAliasData:
+ [aFileHandle valueForAttribute: LiAliasDataAttribute]]];
+ [LiLog logAsDebug: @"fileAttrs: %@", [fileAttrs description]];
+
+ // Attempt path resolution if alias resolution fails.
+ if ([fileAttrs count] == 0) {
+ NSString *filePath, *filename;
+
+ filename = [[aFileHandle filename] stringByAppendingPathExtension: [aFileHandle type]];
+ filePath = [[aFileHandle directory] stringByAppendingPathComponent: filename];
+ [LiLog logAsDebug: @"Attempting to resolve path %@ to alias", filePath];
+ fileAttrs = [NSMutableDictionary dictionaryWithDictionary:
+ [self fileSystemAttributesForPath: filePath]];
+ [LiLog logAsDebug: @"\tresolved to: %@", fileAttrs];
+ }
+
+ if (fileAttrs != nil) {
+ NSDictionary *myAttrs;
+ NSEnumerator *keyEnum;
+ NSString *key;
+
+ myAttrs = [[aFileHandle fileStore] attributesForFileHandle:
+ aFileHandle];
+ keyEnum = [fileAttrs keyEnumerator];
+ while ((key = [keyEnum nextObject]) != nil) {
+ id myValue;
+
+ myValue = [myAttrs objectForKey: key];
+ if (myValue != nil) {
+ id value;
+
+ value = [fileAttrs objectForKey: key];
+ if (myValue == value) {
+ [fileAttrs removeObjectForKey: key];
+ } else {
+ if ([myValue respondsToSelector: @selector(compare:)]) {
+ if ([myValue performSelector: @selector(compare:) withObject: value] == 0) {
+ [fileAttrs removeObjectForKey: key];
+ }
+ } else {
+ // XXX
+ // Disabled because the icon keeps changing
+ // on every check.
+ [fileAttrs removeObjectForKey: key];
+ }
+ }
+ }
+ }
+
+ if ([fileAttrs count] > 0) {
+ [LiLog logAsDebug: @"fileAttrs: %@", [fileAttrs description]];
+ [[aFileHandle fileStore] updateFileHandle: aFileHandle
+ withAttributes: fileAttrs];
+ }
+ }
+}
+
+- (LiFileHandle *)addURL: (NSURL *)anURL
+ toFileStore: (LiFileStore *)aFileStore
+{
+ if ([anURL isFileURL] == YES) {
+ BDAlias *alias;
+ NSArray *existingFiles;
+ NSDictionary *fileAttrs;
+
+ // Attempt resolution of the file handle to determine uniqueness.
+ // If it's not there, it's automatically unique.
+ alias = [BDAlias aliasWithPath: [anURL path]];
+ if (alias != nil) {
+ LiFilter *filter;
+
+ filter = [LiFilter filterWithAttribute: LiAliasDataAttribute
+ compareSelector: @selector(isEqual:)
+ value: [alias aliasData]];
+
+ existingFiles = [[self fileStore] filesMatchingFilter: filter];
+ if ([existingFiles count] > 0) {
+ return [existingFiles objectAtIndex: 0];
+ }
+ }
+
+ fileAttrs = [self fileSystemAttributesForPath: [anURL path]];
+ return [[self fileStore] addFileWithAttributes: fileAttrs];
+ }
+ return nil;
+}
+
+- (NSURL *)urlForFileHandle: (LiFileHandle *)aFileHandle
+{
+ NSString *path;
+ NSURL *url;
+
+ url = nil;
+ path = [aFileHandle path];
+ if (path != nil)
+ url = [NSURL fileURLWithPath: path];
+ return url;
+}
+
+- (NSArray *)defaultValuesForAttribute: (NSString *)anAttribute
+{
+ NSMutableSet *values;
+
+ values = [[self defaultAttributes] objectForKey: anAttribute];
+ return [values allObjects];
+}
+
+- (BOOL)addDefaultAttribute: (NSDictionary *)anAttribute toFileStore: (LiFileStore *)aFileStore
+{
+ NSEnumerator *attrEnum;
+ NSMutableDictionary *defaultAttrs;
+ NSMutableSet *values;
+ NSString *attr;
+
+ [LiLog logAsDebug: @"[LiBuiltInFunctions addDefaultAttribute: %@ toFileStore: %@]", anAttribute, aFileStore];
+ [LiLog indentDebugLog];
+ defaultAttrs = [self defaultAttributes];
+ attrEnum = [anAttribute keyEnumerator];
+ while ((attr = [attrEnum nextObject]) != nil) {
+ values = [defaultAttrs objectForKey: attr];
+ if (values == nil) {
+ values = [NSMutableSet set];
+ [defaultAttrs setObject: values forKey: attr];
+ }
+ [values addObject: [anAttribute objectForKey: attr]];
+ }
+
+ [LiLog unindentDebugLog];
+
+ return [self synchronizeDefaultAttrs];
+}
+
+- (BOOL)changeDefaultValueForAttribute: (NSDictionary *)anAttribute toValue: (id)aValue inFileStore: (LiFileStore *)aFileStore
+{
+ NSEnumerator *attrEnum;
+ NSMutableDictionary *defaultAttrs;
+ NSMutableSet *values;
+ NSString *attr;
+
+ defaultAttrs = [self defaultAttributes];
+ attrEnum = [anAttribute keyEnumerator];
+ while ((attr = [attrEnum nextObject]) != nil) {
+ values = [defaultAttrs objectForKey: attr];
+ if (values == nil) {
+ return NO;
+ }
+ [values removeObject: [anAttribute objectForKey: attr]];
+ [values addObject: aValue];
+ }
+
+ return [self synchronizeDefaultAttrs];
+}
+
+- (BOOL)removeDefaultAttribute: (NSDictionary *)anAttribute fromFileStore: (LiFileStore *)aFileStore
+{
+ NSEnumerator *attrEnum;
+ NSMutableDictionary *defaultAttrs;
+ NSMutableSet *values;
+ NSString *attr;
+
+ defaultAttrs = [self defaultAttributes];
+ attrEnum = [anAttribute keyEnumerator];
+ while ((attr = [attrEnum nextObject]) != nil) {
+ values = [defaultAttrs objectForKey: attr];
+ [values removeObject: [anAttribute objectForKey: attr]];
+ }
+
+ return [self synchronizeDefaultAttrs];
+}
+
+- (void)initFileStore
+{
+ LiFileStore *tmpStore;
+
+ tmpStore = [LiFileStore fileStoreWithName: myLocalizedString(@"LiLibraryName")];
+ [tmpStore setEditable: YES];
+ [tmpStore setIcon: [NSImage imageNamed: @"LiBuiltInFunctions FileStoreIcon"]];
+ [tmpStore setDelegate: self];
+ [self setFileStore: tmpStore];
+ [self loadFileStore: [self fileStore]];
+}
+
+- (LiFileStore *)fileStore
+{
+ return theFileStore;
+}
+@synthesize theController;
+@synthesize theDefaultAttributes;
+@synthesize theFileStore;
+@end
+
+@implementation LiBuiltInFunctions (Accessors)
+- (void)setFileStore: (LiFileStore *)aFileStore
+{
+ [aFileStore retain];
+ [theFileStore release];
+ theFileStore = aFileStore;
+
+ [theFileStore setDelegate: self];
+}
+
+- (InspectorViewController *)viewController
+{
+ if (theController == nil) {
+ if ([NSBundle loadNibNamed: @"InspectorViews.nib" owner: self] == NO) {
+ [LiLog logAsError: @"Couldn't open inspector view nib file."];
+ return nil;
+ }
+ }
+ return theController;
+}
+
+- (NSMutableDictionary *)defaultAttributes
+{
+ return theDefaultAttributes;
+}
+
+- (void)setDefaultAttributes: (NSMutableDictionary *)someAttributes
+{
+ [someAttributes retain];
+ [theDefaultAttributes release];
+ theDefaultAttributes = someAttributes;
+}
+@end
+
+@implementation LiFileHandle (LiBuiltInFunctions)
+- (NSImage *)icon
+{
+ NSImage *icon;
+ NSURL *myURL;
+
+ myURL = [self url];
+ if ([myURL isFileURL] == YES)
+ icon = [[NSWorkspace sharedWorkspace] iconForFile: [self path]];
+ else if (myURL == nil)
+ icon = [NSImage imageNamed: @"LiBuiltInFunctions NotThereImage"];
+ else
+ icon = [[NSWorkspace sharedWorkspace] iconForFileType: [self type]];
+ return icon;
+}
+
+- (BDAlias *)alias
+{
+ BDAlias *tmpAlias;
+
+ tmpAlias = [BDAlias aliasWithData:
+ [self valueForAttribute: LiAliasDataAttribute]];
+
+ return tmpAlias;
+}
+
+- (void)setAlias: (BDAlias *)anAlias
+{
+ [self setValue: [anAlias aliasData]
+ forAttribute: LiAliasDataAttribute];
+}
+
+- (NSString *)path
+{
+ return [[self alias] fullPath];
+}
+
+- (NSString *)directory
+{
+ return [self valueForAttribute: LiDirectoryAttribute];
+}
+@end \ No newline at end of file