From 38e7a5f0b9c919fcaab39520655cd46e14fafafd Mon Sep 17 00:00:00 2001 From: Michael Starke Date: Thu, 25 Oct 2018 16:34:35 +0200 Subject: [PATCH] More progress on import plugin support --- MacPass/Base.lproj/MainMenu.xib | 4 ++++ MacPass/MPAppDelegate.h | 9 ++++---- MacPass/MPAppDelegate.m | 12 +++++++++++ MacPass/MPDocument.h | 1 + MacPass/MPDocument.m | 11 +++++++--- MacPass/MPDocumentWindowController.h | 1 + MacPass/MPDocumentWindowController.m | 25 ++++++++++++++++++++++ MacPass/MPPlugin.h | 29 ++++++++++++++++++++++++-- MacPass/MPPluginHost.h | 11 +++++++--- MacPass/MPPluginHost.m | 31 ++++++++++++++++------------ 10 files changed, 109 insertions(+), 25 deletions(-) diff --git a/MacPass/Base.lproj/MainMenu.xib b/MacPass/Base.lproj/MainMenu.xib index 4083822c..c608076c 100644 --- a/MacPass/Base.lproj/MainMenu.xib +++ b/MacPass/Base.lproj/MainMenu.xib @@ -162,6 +162,9 @@ + + + @@ -350,6 +353,7 @@ CA + diff --git a/MacPass/MPAppDelegate.h b/MacPass/MPAppDelegate.h index 0e2c1315..4bffe3f1 100644 --- a/MacPass/MPAppDelegate.h +++ b/MacPass/MPAppDelegate.h @@ -26,10 +26,11 @@ APPKIT_EXTERN NSString *const MPDidChangeStoredKeyFilesSettings; @interface MPAppDelegate : NSObject -@property (weak) IBOutlet NSMenuItem *saveMenuItem; -@property (weak) IBOutlet NSMenuItem *fixAutotypeMenuItem; -@property (weak) IBOutlet NSMenuItem *fileNewMenuItem; -@property (weak) IBOutlet NSMenu *itemMenu; +@property (strong) IBOutlet NSMenuItem *saveMenuItem; +@property (strong) IBOutlet NSMenuItem *fixAutotypeMenuItem; +@property (strong) IBOutlet NSMenuItem *fileNewMenuItem; +@property (strong) IBOutlet NSMenu *itemMenu; +@property (strong) IBOutlet NSMenu *importMenu; @property (nonatomic, assign) BOOL isAllowedToStoreKeyFile; diff --git a/MacPass/MPAppDelegate.m b/MacPass/MPAppDelegate.m index eeae01e5..ce8ba892 100644 --- a/MacPass/MPAppDelegate.m +++ b/MacPass/MPAppDelegate.m @@ -40,6 +40,7 @@ #import "MPValueTransformerHelper.h" #import "MPUserNotificationCenterDelegate.h" #import "MPWelcomeViewController.h" +#import "MPPlugin.h" #import "NSApplication+MPAdditions.h" @@ -208,6 +209,17 @@ NSString *const MPDidChangeStoredKeyFilesSettings = @"com.hicknhack.macpass.MPDi [menu addItem:item]; } } + if(menu == self.importMenu) { + NSMenuItem *exportXML = menu.itemArray.firstObject; + [menu removeAllItems]; + for(MPPlugin * plugin in MPPluginHost.sharedHost.importPlugins) { + NSMenuItem *importItem = [[NSMenuItem alloc] init]; + [plugin prepareImportMenuItem:importItem]; + importItem.target = nil; + importItem.action = @selector(importFromPlugin:); + } + [menu insertItem:exportXML atIndex:0]; + } } #pragma mark - diff --git a/MacPass/MPDocument.h b/MacPass/MPDocument.h index 104e299b..29f46d2f 100644 --- a/MacPass/MPDocument.h +++ b/MacPass/MPDocument.h @@ -149,6 +149,7 @@ FOUNDATION_EXPORT NSString *const MPDocumentGroupKey; - (BOOL)shouldEnforcePasswordChange; - (BOOL)shouldRecommendPasswordChange; +- (void)importTree:(KPKTree *)tree; - (void)writeXMLToURL:(NSURL *)url; - (void)readXMLfromURL:(NSURL *)url; - (void)mergeWithContentsFromURL:(NSURL *)url key:(KPKCompositeKey *)key; diff --git a/MacPass/MPDocument.m b/MacPass/MPDocument.m index 11572ea6..64632dd1 100644 --- a/MacPass/MPDocument.m +++ b/MacPass/MPDocument.m @@ -329,6 +329,12 @@ NSString *const MPDocumentGroupKey = @"MPDocumentGrou // else do nothing! } +- (void)importTree:(KPKTree *)tree { + self.tree = tree; + self.compositeKey = nil; + self.encryptedData = nil; +} + - (void)writeXMLToURL:(NSURL *)url { NSData *xmlData = [self.tree xmlData]; NSError *error; @@ -339,9 +345,8 @@ NSString *const MPDocumentGroupKey = @"MPDocumentGrou - (void)readXMLfromURL:(NSURL *)url { NSError *error; - self.tree = [[KPKTree alloc] initWithXmlContentsOfURL:url error:&error]; - self.compositeKey = nil; - self.encryptedData = nil; + KPKTree *tree = [[KPKTree alloc] initWithXmlContentsOfURL:url error:&error]; + [self importTree:tree]; } - (void)mergeWithContentsFromURL:(NSURL *)url key:(KPKCompositeKey *)key { diff --git a/MacPass/MPDocumentWindowController.h b/MacPass/MPDocumentWindowController.h index af8ce884..406c8dfd 100644 --- a/MacPass/MPDocumentWindowController.h +++ b/MacPass/MPDocumentWindowController.h @@ -58,6 +58,7 @@ - (IBAction)exportAsXML:(id)sender; - (IBAction)mergeWithOther:(id)sender; - (IBAction)importFromXML:(id)sender; +- (IBAction)importFromPlugin:(id)sender; - (IBAction)lock:(id)sender; - (IBAction)createGroup:(id)sender; diff --git a/MacPass/MPDocumentWindowController.m b/MacPass/MPDocumentWindowController.m index afd4d0c3..b216a609 100644 --- a/MacPass/MPDocumentWindowController.m +++ b/MacPass/MPDocumentWindowController.m @@ -40,6 +40,9 @@ #import "MPToolbarDelegate.h" #import "MPTitlebarColorAccessoryViewController.h" +#import "MPPluginHost.h" +#import "MPPlugin.h" + #import "KeePassKit/KeePassKit.h" typedef NS_ENUM(NSUInteger, MPAlertContext) { @@ -274,6 +277,28 @@ typedef void (^MPPasswordChangedBlock)(BOOL didChangePassword); }]; } +- (void)importFromPlugin:(id)sender { + if(![sender isKindOfClass:NSMenuItem.class]) { + return; + } + NSMenuItem *menuItem = sender; + if(![menuItem.representedObject isKindOfClass:NSDictionary.class]) { + return; + } + + NSWindow *sheetWindow = ((MPDocument *)self.document).windowForSheet; + if(!sheetWindow) { + return; + } + MPPlugin *importPlugin; + NSOpenPanel *openPanel = NSOpenPanel.openPanel; + [importPlugin prepareOpenPanel:openPanel]; + [openPanel beginSheetModalForWindow:sheetWindow completionHandler:^(NSModalResponse result) { + KPKTree *importedTree = [importPlugin treeForRunningOpenPanel:openPanel withResponse:result]; + [self.document importTree:importedTree]; + }]; +} + - (void)mergeWithOther:(id)sender { NSOpenPanel *openPanel = [NSOpenPanel openPanel]; MPDocument *document = self.document; diff --git a/MacPass/MPPlugin.h b/MacPass/MPPlugin.h index f0cd7d3f..90584901 100644 --- a/MacPass/MPPlugin.h +++ b/MacPass/MPPlugin.h @@ -89,8 +89,33 @@ FOUNDATION_EXPORT NSString *const MPPluginUnkownVersion; @protocol MPImportPlugin @required -@property (readonly, copy) NSArray *supportedUTIs; -- (KPKTree *)importTreeWithContentsOfURL:(NSURL *)url; +/** + Called by the Host to upate a menu item for importing. + You are supposed to update the title to something meaningfull. + target and action will get set by host, so do not rely on them + + @param item MenuItem that will be used to import via the plugin + */ +- (void)prepareImportMenuItem:(NSMenuItem *)item; +/** + Called by the host when an import is about to happen. + Update the panel to allow work for all the files and formats you can open. + + Host will simply run the panel with - beginSheetModalForWindow:completionHandler: + and will call treeForRunningOpenPanel:withResponse: afterwards to handle the result. + + @param panel The open panel that will be displayed to the user for importing files + */ +- (void)prepareOpenPanel:(NSOpenPanel *)panel; +/** + This will get called when the open panel is closed by the user. + You should retrieve any results from the panel and act accordingly. + + @param panel The open panel used for selecting what file(s) to import + @param response The response for of the user for running the panel + @return The tree constructed from the selected input file(s) + */ +- (KPKTree *)treeForRunningOpenPanel:(NSOpenPanel *)panel withResponse:(NSModalResponse)response; @end @interface MPPlugin (Deprecated) diff --git a/MacPass/MPPluginHost.h b/MacPass/MPPluginHost.h index 96a5202e..f763f422 100644 --- a/MacPass/MPPluginHost.h +++ b/MacPass/MPPluginHost.h @@ -23,8 +23,8 @@ #import /* Notifications for loading plugins */ -FOUNDATION_EXPORT NSString *const MPPluginHostWillLoadPlugin; -FOUNDATION_EXPORT NSString *const MPPluginHostDidLoadPlugin; +FOUNDATION_EXPORT NSString *const MPPluginHostWillLoadPluginNotification; +FOUNDATION_EXPORT NSString *const MPPluginHostDidLoadPluginNotification; /* Keys used in info dictionary on notifications */ FOUNDATION_EXPORT NSString *const MPPluginHostPluginBundleIdentifiyerKey; @@ -37,7 +37,6 @@ FOUNDATION_EXPORT NSString *const MPPluginHostPluginBundleIdentifiyerKey; /* List of all plugins known to the plugin manager. Disabled plugins are also present! */ @property (readonly, copy) NSArray *plugins; -@property (readonly, copy) NSArray *importPlugins; @property (nonatomic, readonly, copy) NSString *version; + (instancetype)sharedHost; @@ -54,3 +53,9 @@ FOUNDATION_EXPORT NSString *const MPPluginHostPluginBundleIdentifiyerKey; - (MPPlugin *)pluginWithBundleIdentifier:(NSString *)identifer; - (NSArray *)avilableMenuItemsForEntries:(NSArray *)entries; @end + +@interface MPPluginHost (MPImportPluginSupport) + +@property (readonly, copy) NSArray __kindof*> *importPlugins; + +@end diff --git a/MacPass/MPPluginHost.m b/MacPass/MPPluginHost.m index 6fb611a4..f8a63b55 100644 --- a/MacPass/MPPluginHost.m +++ b/MacPass/MPPluginHost.m @@ -38,8 +38,8 @@ #import "KeePassKit/KeePassKit.h" -NSString *const MPPluginHostWillLoadPlugin = @"com.hicknhack.macpass.MPPluginHostWillLoadPlugin"; -NSString *const MPPluginHostDidLoadPlugin = @"comt.hicknhack.macpass.MPPluginHostDidLoadPlugin"; +NSString *const MPPluginHostWillLoadPluginNotification = @"com.hicknhack.macpass.MPPluginHostWillLoadPlugin"; +NSString *const MPPluginHostDidLoadPluginNotification = @"comt.hicknhack.macpass.MPPluginHostDidLoadPlugin"; NSString *const MPPluginHostPluginBundleIdentifiyerKey = @"MPPluginHostPluginBundleIdentifiyerKey"; @@ -87,13 +87,6 @@ NSString *const MPPluginHostPluginBundleIdentifiyerKey = @"MPPluginHostPluginBun return [self.mutablePlugins copy]; } -- (NSArray *)importPlugins { - NSPredicate *filterPredicate = [NSPredicate predicateWithBlock:^BOOL(id _Nullable evaluatedObject, NSDictionary * _Nullable bindings) { - return ([evaluatedObject conformsToProtocol:@protocol(MPImportPlugin)]); - }]; - return [self.mutablePlugins filteredArrayUsingPredicate:filterPredicate]; -} - - (BOOL)installPluginAtURL:(NSURL *)url error:(NSError *__autoreleasing *)error { if(![self _isValidPluginURL:url]) { if(error) { @@ -267,11 +260,11 @@ NSString *const MPPluginHostPluginBundleIdentifiyerKey = @"MPPluginHostPluginBun if(plugin) { NSLog(@"Loaded plugin instance %@", pluginBundle.principalClass); - [[NSNotificationCenter defaultCenter] postNotificationName:MPPluginHostWillLoadPlugin + [[NSNotificationCenter defaultCenter] postNotificationName:MPPluginHostWillLoadPluginNotification object:self userInfo:@{ MPPluginHostPluginBundleIdentifiyerKey : plugin.identifier }]; [self _addPlugin:plugin]; - [[NSNotificationCenter defaultCenter] postNotificationName:MPPluginHostDidLoadPlugin + [[NSNotificationCenter defaultCenter] postNotificationName:MPPluginHostDidLoadPluginNotification object:self userInfo:@{ MPPluginHostPluginBundleIdentifiyerKey : plugin.identifier }]; } @@ -414,6 +407,18 @@ NSString *const MPPluginHostPluginBundleIdentifiyerKey = @"MPPluginHostPluginBun [context.plugin performActionForMenuItem:item withEntries:context.entries]; } - - @end + +NSString *const MPPluginBundleIdentifierKey = @"MPPluginBundleIdentifierKey"; +NSString *const MPImportPluginUTIKey = @"MPImportPluginUTIKey"; + +@implementation MPPluginHost (MPImportPluginSupport) + +- (NSArray *)importPlugins { + NSPredicate *filterPredicate = [NSPredicate predicateWithBlock:^BOOL(id _Nullable evaluatedObject, NSDictionary * _Nullable bindings) { + return ([evaluatedObject conformsToProtocol:@protocol(MPImportPlugin)]); + }]; + return [self.mutablePlugins filteredArrayUsingPredicate:filterPredicate]; +} +@end +