diff --git a/MacPass/MPAutotypePaste.m b/MacPass/MPAutotypePaste.m index abcdac6f..c9dfacd1 100644 --- a/MacPass/MPAutotypePaste.m +++ b/MacPass/MPAutotypePaste.m @@ -51,9 +51,9 @@ } - (void)execute { - if([self.pasteData length] > 0) { + if(self.pasteData.length > 0) { [MPPasteBoardController.defaultController stashObjects]; - [MPPasteBoardController.defaultController copyObjectsWithoutTimeout:@[self.pasteData]]; + [MPPasteBoardController.defaultController copyObjectWithoutTimeout:self.pasteData]; [MPKeyTyper sendPaste]; usleep(0.2 * NSEC_PER_MSEC); // on 10.10 we need to wait a bit before restoring the pasteboard contents [MPPasteBoardController.defaultController restoreObjects]; diff --git a/MacPass/MPEntryInspectorViewController.m b/MacPass/MPEntryInspectorViewController.m index 0efc4a50..a11b6120 100644 --- a/MacPass/MPEntryInspectorViewController.m +++ b/MacPass/MPEntryInspectorViewController.m @@ -628,7 +628,7 @@ typedef NS_ENUM(NSUInteger, MPEntryTab) { name = [_customFieldsController.arrangedObjects[index] key]; } } - [MPPasteBoardController.defaultController copyObjects:@[selectedValue] overlayInfo:info name:name atView:self.view]; + [MPPasteBoardController.defaultController copyObject:selectedValue overlayInfo:info name:name atView:self.view]; return NO; } return YES; diff --git a/MacPass/MPEntryViewController.m b/MacPass/MPEntryViewController.m index d072d8c5..35fd5239 100644 --- a/MacPass/MPEntryViewController.m +++ b/MacPass/MPEntryViewController.m @@ -647,7 +647,7 @@ NSString *const _MPTableSecurCellView = @"PasswordCell"; KPKEntry *selectedEntry = nodes.count == 1 ? [nodes.firstObject asEntry] : nil; NSString *value = [selectedEntry.password kpk_finalValueForEntry:selectedEntry]; if(value) { - [MPPasteBoardController.defaultController copyObjects:@[value] overlayInfo:MPPasteboardOverlayInfoPassword name:nil atView:self.view]; + [MPPasteBoardController.defaultController copyObject:value overlayInfo:MPPasteboardOverlayInfoPassword name:nil atView:self.view]; } } @@ -656,7 +656,7 @@ NSString *const _MPTableSecurCellView = @"PasswordCell"; KPKEntry *selectedEntry = nodes.count == 1 ? [nodes.firstObject asEntry] : nil; NSString *value = [selectedEntry.username kpk_finalValueForEntry:selectedEntry]; if(value) { - [MPPasteBoardController.defaultController copyObjects:@[value] overlayInfo:MPPasteboardOverlayInfoUsername name:nil atView:self.view]; + [MPPasteBoardController.defaultController copyObject:value overlayInfo:MPPasteboardOverlayInfoUsername name:nil atView:self.view]; } } @@ -669,7 +669,7 @@ NSString *const _MPTableSecurCellView = @"PasswordCell"; KPKAttribute *attribute = selectedEntry.customAttributes[index]; NSString *value = attribute.evaluatedValue; if(value) { - [MPPasteBoardController.defaultController copyObjects:@[value] overlayInfo:MPPasteboardOverlayInfoCustom name:attribute.key atView:self.view]; + [MPPasteBoardController.defaultController copyObject:value overlayInfo:MPPasteboardOverlayInfoCustom name:attribute.key atView:self.view]; } } } @@ -679,7 +679,7 @@ NSString *const _MPTableSecurCellView = @"PasswordCell"; KPKEntry *selectedEntry = nodes.count == 1 ? [nodes.firstObject asEntry] : nil; NSString *value = [selectedEntry.url kpk_finalValueForEntry:selectedEntry]; if(value) { - [MPPasteBoardController.defaultController copyObjects:@[value] overlayInfo:MPPasteboardOverlayInfoURL name:nil atView:self.view]; + [MPPasteBoardController.defaultController copyObject:value overlayInfo:MPPasteboardOverlayInfoURL name:nil atView:self.view]; } } @@ -727,7 +727,7 @@ NSString *const _MPTableSecurCellView = @"PasswordCell"; KPKEntry *selectedEntry = nodes.count == 1 ? [nodes.firstObject asEntry] : nil; if(referencesField && selectedEntry) { NSString *value = [NSString stringWithFormat:@"{%@%@@%@:%@}", kKPKReferencePrefix, referencesField, kKPKReferenceUUIDKey, selectedEntry.uuid.UUIDString]; - [MPPasteBoardController.defaultController copyObjects:@[value] overlayInfo:MPPasteboardOverlayInfoReference name:references[referencesField] atView:self.view]; + [MPPasteBoardController.defaultController copyObject:value overlayInfo:MPPasteboardOverlayInfoReference name:references[referencesField] atView:self.view]; } } diff --git a/MacPass/MPInspectorViewController.m b/MacPass/MPInspectorViewController.m index 2dec627a..3472b739 100644 --- a/MacPass/MPInspectorViewController.m +++ b/MacPass/MPInspectorViewController.m @@ -154,7 +154,7 @@ typedef NS_ENUM(NSUInteger, MPContentTab) { if(textView == self.notesTextView) { name = NSLocalizedString(@"NOTES", "Displayed name when notes or part of notes was copied"); } - [[MPPasteBoardController defaultController] copyObjects:@[selectedString] overlayInfo:info name:name atView:self.view]; + [MPPasteBoardController.defaultController copyObject:selectedString overlayInfo:info name:name atView:self.view]; return NO; } return YES; diff --git a/MacPass/MPPasswordCreatorViewController.m b/MacPass/MPPasswordCreatorViewController.m index cc844cca..92a98705 100644 --- a/MacPass/MPPasswordCreatorViewController.m +++ b/MacPass/MPPasswordCreatorViewController.m @@ -193,7 +193,7 @@ typedef NS_ENUM(NSUInteger, MPPasswordRating) { - (IBAction)_usePassword:(id)sender { if(self.shouldCopyPasswordToPasteboardButton.state == NSOnState) { - [MPPasteBoardController.defaultController copyObjects:@[self.password]]; + [MPPasteBoardController.defaultController copyObject:self.password]; } KPKEntry *entry = self.representedObject; if(entry && self.password.length > 0) { diff --git a/MacPass/MPPasteBoardController.h b/MacPass/MPPasteBoardController.h index 6d026fef..1d53b1dc 100644 --- a/MacPass/MPPasteBoardController.h +++ b/MacPass/MPPasteBoardController.h @@ -55,8 +55,8 @@ FOUNDATION_EXPORT NSString *const MPPasteBoardControllerDidClearClipboard; - (void)stashObjects; - (void)restoreObjects; -- (void)copyObjects:(NSArray> *)objects; -- (void)copyObjectsWithoutTimeout:(NSArray> *)objects; +- (void)copyObject:(id)objects; +- (void)copyObjectWithoutTimeout:(id)objects; /** The pastboard controller will copy the object to the clipboard, display an appropriate overlay image @@ -65,11 +65,11 @@ FOUNDATION_EXPORT NSString *const MPPasteBoardControllerDidClearClipboard; to the clipboard. If the clipboard is used internally (e.g. for autotype) you should call copyObjects: or even copyObjectsWithoutTimeout: - @param objects object so be copied + @param object object so be copied @param overlayInfoType infotype discribing what is copied @param name a custom name @param view the view that initiated the copy action */ -- (void)copyObjects:(NSArray> *)objects overlayInfo:(MPPasteboardOverlayInfoType)overlayInfoType name:(NSString *)name atView:(NSView *)view; +- (void)copyObject:(id)object overlayInfo:(MPPasteboardOverlayInfoType)overlayInfoType name:(NSString *)name atView:(NSView *)view; @end diff --git a/MacPass/MPPasteBoardController.m b/MacPass/MPPasteBoardController.m index 3321b18b..93be81f0 100644 --- a/MacPass/MPPasteBoardController.m +++ b/MacPass/MPPasteBoardController.m @@ -28,6 +28,14 @@ NSString *const MPPasteBoardControllerDidCopyObjects = @"com.hicknhack.macpass.MPPasteBoardControllerDidCopyObjects"; NSString *const MPPasteBoardControllerDidClearClipboard = @"com.hicknhack.macpass.MPPasteBoardControllerDidClearClipboard"; +/* + Pasteboard types. See NSPasteboard.org for refernce + */ +NSString *const MPPasteBoardTypeTransient = @"org.nspasteboard.TransientType"; +NSString *const MPPasteBoardTypeConcealed = @"org.nspasteboard.ConcealedType"; +NSString *const MPPasteBoardTypeAutoGenerated = @"org.nspasteboard.AutoGeneratedType"; +NSString *const MPPasteBoardTypeSource = @"org.nspasteboard.source"; + @interface MPPasteBoardController () @property (assign) BOOL isEmpty; @@ -72,6 +80,9 @@ NSString *const MPPasteBoardControllerDidClearClipboard = @"com.hicknhack.macpas - (void)stashObjects { self.stashedObjects = [NSMutableArray array]; for(NSPasteboardItem *item in NSPasteboard.generalPasteboard.pasteboardItems) { + if(![self _shouldStashPasteboardItem:item]) { + continue; // skip item we should not stash + } NSPasteboardItem *newItem = [[NSPasteboardItem alloc] init]; for (NSString *type in item.types) { /* mutable copy to ensure actual deep copy */ @@ -93,9 +104,11 @@ NSString *const MPPasteBoardControllerDidClearClipboard = @"com.hicknhack.macpas } } -- (void)copyObjects:(NSArray> *)objects { - [self copyObjectsWithoutTimeout:objects]; +- (void)copyObject:(id)object { + [self copyObjectWithoutTimeout:object]; if(self.clearTimeout != 0) { + /* add transient since we do clear after delay */ + [NSPasteboard.generalPasteboard setData:nil forType:MPPasteBoardTypeTransient]; [NSNotificationCenter.defaultCenter postNotificationName:MPPasteBoardControllerDidCopyObjects object:self]; /* cancel old timer */ [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(_clearPasteboardContents) object:nil]; @@ -104,18 +117,20 @@ NSString *const MPPasteBoardControllerDidClearClipboard = @"com.hicknhack.macpas } } -- (void)copyObjectsWithoutTimeout:(NSArray> *)objects { +- (void)copyObjectWithoutTimeout:(id)object { NSPasteboardContentsOptions options = [NSUserDefaults.standardUserDefaults boolForKey:kMPSettingsKeyPreventUniversalClipboard] ? NSPasteboardContentsCurrentHostOnly : 0; [NSPasteboard.generalPasteboard prepareForNewContentsWithOptions:options]; - [NSPasteboard.generalPasteboard writeObjects:objects]; + [NSPasteboard.generalPasteboard writeObjects:@[object]]; + [NSPasteboard.generalPasteboard setData:nil forType:MPPasteBoardTypeConcealed]; // mark as concealed + [NSPasteboard.generalPasteboard setString:NSRunningApplication.currentApplication.bundleIdentifier forType:MPPasteBoardTypeSource]; // set source self.isEmpty = NO; } -- (void)copyObjects:(NSArray> *)objects overlayInfo:(MPPasteboardOverlayInfoType)overlayInfoType name:(NSString *)name atView:(NSView *)view{ - if(!objects) { +- (void)copyObject:(id)object overlayInfo:(MPPasteboardOverlayInfoType)overlayInfoType name:(NSString *)name atView:(NSView *)view{ + if(!object) { return; } - [MPPasteBoardController.defaultController copyObjects:objects]; + [MPPasteBoardController.defaultController copyObject:object]; NSImage *infoImage = nil; NSString *infoText = nil; switch(overlayInfoType) { @@ -185,4 +200,22 @@ NSString *const MPPasteBoardControllerDidClearClipboard = @"com.hicknhack.macpas options:nil]; } +- (BOOL)_shouldStashPasteboardItem:(NSPasteboardItem *)item { + for(NSString *type in item.types) { + if([type isEqualToString:MPPasteBoardTypeConcealed]) { + return NO; + } + if([type isEqualToString:MPPasteBoardTypeTransient]) { + return NO; + } + if([type isEqualToString:MPPasteBoardTypeSource]) { + NSString *sourceBundle = [item stringForType:type]; + if([NSRunningApplication.currentApplication.bundleIdentifier isEqualToString:sourceBundle]) { + return NO; + } + } + } + return YES; +} + @end