diff --git a/Cartfile b/Cartfile index bbf934ea..afb54188 100644 --- a/Cartfile +++ b/Cartfile @@ -1,4 +1,4 @@ github "sparkle-project/Sparkle" ~> 1.22 github "MacPass/TransformerKit" "a8b5bb73cc327ec6798569b865c32fec5eb2289f" -github "MacPass/KeePassKit" ~> 3.0 +github "MacPass/KeePassKit" "8ce0fda4ca10c41f022da3d9e3539e1686aa4460" github "mstarke/HNHUi" ~> 4.0 diff --git a/Cartfile.resolved b/Cartfile.resolved index cda0156a..8e79e517 100644 --- a/Cartfile.resolved +++ b/Cartfile.resolved @@ -1,4 +1,4 @@ -github "MacPass/KeePassKit" "3.0.0" +github "MacPass/KeePassKit" "8ce0fda4ca10c41f022da3d9e3539e1686aa4460" github "MacPass/KissXML" "933f04fe5ad95c2be07ec0c2f801e140007f20fa" github "MacPass/TransformerKit" "a8b5bb73cc327ec6798569b865c32fec5eb2289f" github "mstarke/HNHUi" "4.0.4" diff --git a/MacPass.xcodeproj/project.pbxproj b/MacPass.xcodeproj/project.pbxproj index 9c69df1d..b32a8a07 100644 --- a/MacPass.xcodeproj/project.pbxproj +++ b/MacPass.xcodeproj/project.pbxproj @@ -244,6 +244,8 @@ 4CBA2ABA17074C07006D8139 /* MPSettingsHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 4CBA2AB917074C07006D8139 /* MPSettingsHelper.m */; }; 4CBC5DDD23C61C8900D14B92 /* TransformerKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CBC5DDB23C61C8300D14B92 /* TransformerKit.framework */; }; 4CBC5DDE23C61C8900D14B92 /* TransformerKit.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4CBC5DDB23C61C8300D14B92 /* TransformerKit.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 4CC0192E271836CD00459789 /* MPEntryAttributeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4CC0192C271836CD00459789 /* MPEntryAttributeViewController.m */; }; + 4CC0192F271836CD00459789 /* MPEntryAttributeViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4CC0192D271836CD00459789 /* MPEntryAttributeViewController.xib */; }; 4CC0D2CE17974A47000B4BDA /* MPCustomFieldTableViewDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 4CC0D2CD17974A47000B4BDA /* MPCustomFieldTableViewDelegate.m */; }; 4CC0D2D117974A5A000B4BDA /* MPAttachmentTableViewDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 4CC0D2D017974A5A000B4BDA /* MPAttachmentTableViewDelegate.m */; }; 4CC281891C0F675B00B9174D /* HNHUi.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CC281881C0F675B00B9174D /* HNHUi.framework */; }; @@ -550,6 +552,7 @@ 4C45FB2F178E0CE20010007D /* MPTestDocument.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPTestDocument.m; sourceTree = ""; }; 4C46B88317063A070046109A /* NSString+MPPasswordCreation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSString+MPPasswordCreation.h"; sourceTree = ""; }; 4C46B88417063A070046109A /* NSString+MPPasswordCreation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSString+MPPasswordCreation.m"; sourceTree = ""; }; + 4C47090727184AC8003777EB /* MPInspectorEditor.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MPInspectorEditor.h; sourceTree = ""; }; 4C473A8518AFD7250073FD2E /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; 4C49CFD424252389004092E7 /* KPKEntry+MPTags.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "KPKEntry+MPTags.h"; sourceTree = ""; }; 4C49CFD524252389004092E7 /* KPKEntry+MPTags.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "KPKEntry+MPTags.m"; sourceTree = ""; }; @@ -806,6 +809,9 @@ 4CBA2AB617074B59006D8139 /* MPSettingsHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPSettingsHelper.h; sourceTree = ""; }; 4CBA2AB917074C07006D8139 /* MPSettingsHelper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPSettingsHelper.m; sourceTree = ""; }; 4CBC5DDB23C61C8300D14B92 /* TransformerKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = TransformerKit.framework; path = Carthage/Build/Mac/TransformerKit.framework; sourceTree = ""; }; + 4CC0192B271836CD00459789 /* MPEntryAttributeViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MPEntryAttributeViewController.h; sourceTree = ""; }; + 4CC0192C271836CD00459789 /* MPEntryAttributeViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MPEntryAttributeViewController.m; sourceTree = ""; }; + 4CC0192D271836CD00459789 /* MPEntryAttributeViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = MPEntryAttributeViewController.xib; sourceTree = ""; }; 4CC0D2CC17974A47000B4BDA /* MPCustomFieldTableViewDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPCustomFieldTableViewDelegate.h; sourceTree = ""; }; 4CC0D2CD17974A47000B4BDA /* MPCustomFieldTableViewDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPCustomFieldTableViewDelegate.m; sourceTree = ""; }; 4CC0D2CF17974A5A000B4BDA /* MPAttachmentTableViewDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPAttachmentTableViewDelegate.h; sourceTree = ""; }; @@ -1433,6 +1439,9 @@ 4C2892A5257103F9003C7732 /* MPTOTPViewController.h */, 4C2892A6257103F9003C7732 /* MPTOTPViewController.m */, 4C2892A7257103F9003C7732 /* MPTOTPViewController.xib */, + 4CC0192B271836CD00459789 /* MPEntryAttributeViewController.h */, + 4CC0192C271836CD00459789 /* MPEntryAttributeViewController.m */, + 4CC0192D271836CD00459789 /* MPEntryAttributeViewController.xib */, ); name = Inspector; sourceTree = ""; @@ -1751,6 +1760,7 @@ 4C7679BC1D75E690001F33D6 /* MPModelChangeObserving.h */, 4CA0B30D15BCB6FD00654E32 /* MPPreferencesTab.h */, 4C2B0B7419F66F6400E48913 /* MPTargetNodeResolving.h */, + 4C47090727184AC8003777EB /* MPInspectorEditor.h */, ); name = Protocolls; sourceTree = ""; @@ -2058,6 +2068,7 @@ 4C3826B81AD04D8E007D7D67 /* 44_NotesTemplate.pdf in Resources */, 4C3826C41AD04D8E007D7D67 /* 57_TextViewTemplate.pdf in Resources */, 6021FE9818E1650F00C3BC51 /* DatabaseSettingsWindow.xib in Resources */, + 4CC0192F271836CD00459789 /* MPEntryAttributeViewController.xib in Resources */, 4C6D1D25178579570014C5A5 /* 48_FolderTemplate.pdf in Resources */, 4C701CBC178618A000581B88 /* 12_RemoteTemplate.pdf in Resources */, 4CF29BF417879D0000851B60 /* 26_FileSaveTemplate.pdf in Resources */, @@ -2238,6 +2249,7 @@ 4C0C59F118B17F10009C7B76 /* DDHotKeyUtilities.m in Sources */, 4CEE46DD181C301D006BF1E5 /* MPAutotypeDaemon.m in Sources */, 4C50CC041F6C18830095629D /* MPCollectionViewItem.m in Sources */, + 4CC0192E271836CD00459789 /* MPEntryAttributeViewController.m in Sources */, 4CA78C001FD58C92003C8560 /* MPPluginRepository.m in Sources */, 4CAD8AA622CF397B0090B2DD /* MPAutotypeDoctorReportViewController.m in Sources */, 4C8990F71EE978EB0043B48D /* MPDuplicateEntryOptionsWindowController.m in Sources */, diff --git a/MacPass/MPEntryAttributeViewController.h b/MacPass/MPEntryAttributeViewController.h new file mode 100644 index 00000000..b0df58c3 --- /dev/null +++ b/MacPass/MPEntryAttributeViewController.h @@ -0,0 +1,24 @@ +// +// MPEntryAttributeViewController.h +// MacPass +// +// Created by Michael Starke on 14.10.21. +// Copyright © 2021 HicknHack Software GmbH. All rights reserved. +// + +#import +#import +#import "MPInspectorEditor.h" + + +NS_ASSUME_NONNULL_BEGIN + + +/// View controller to show and edit KPKAttributes of KPKEntries. +/// Set the represented object to the KPKAttribute the editor shoudl show/edit +/// The editor can be set to edit or view +@interface MPEntryAttributeViewController : NSViewController + +@end + +NS_ASSUME_NONNULL_END diff --git a/MacPass/MPEntryAttributeViewController.m b/MacPass/MPEntryAttributeViewController.m new file mode 100644 index 00000000..bcce6f88 --- /dev/null +++ b/MacPass/MPEntryAttributeViewController.m @@ -0,0 +1,151 @@ +// +// MPEntryAttributeViewController.m +// MacPass +// +// Created by Michael Starke on 14.10.21. +// Copyright © 2021 HicknHack Software GmbH. All rights reserved. +// + +#import "MPEntryAttributeViewController.h" +#import +#import +#import "MPPasteBoardController.h" + +@interface MPEntryAttributeViewController () { + BOOL _isDefaultAttribute; +} +@property (strong) IBOutlet NSTextField *keyTextField; +@property (strong) IBOutlet HNHUITextField *valueTextField; +@property (readonly, nullable, strong) KPKAttribute *representedAttribute; + +@end + +@implementation MPEntryAttributeViewController + +@synthesize isEditor = _isEditor; + +- (instancetype)initWithNibName:(NSNibName)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { + self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; + if(self) { + _isEditor = NO; + _isDefaultAttribute = NO; + } + return self; +} + +- (instancetype)initWithCoder:(NSCoder *)coder { + self = [super initWithCoder:coder]; + // set editor to false? + return self; +} + +- (void)viewDidLoad { + NSString *placeHolder = NSLocalizedString(@"NONE", "Placeholder text for input fields if no entry or group is selected"); + self.keyTextField.placeholderString = placeHolder; + self.valueTextField.placeholderString = placeHolder; + + [super viewDidLoad]; + [self _updateValues]; + [self _updateEditing]; + + __weak MPEntryAttributeViewController *welf = self; + self.valueTextField.copyActionBlock = ^void(NSTextField *tf) { + NSText *text = [welf.view.window fieldEditor:NO forObject:welf.valueTextField]; + if([text isKindOfClass:NSTextView.class]) { + [welf textField:welf.valueTextField textView:(NSTextView *)text performAction:@selector(copy:)]; + } + }; +} + +- (KPKAttribute *)representedAttribute { + if([self.representedObject isKindOfClass:KPKAttribute.class]) { + return (KPKAttribute *)self.representedObject; + } + return nil; +} + +- (void)setIsEditor:(BOOL)isEditor { + _isEditor = isEditor; + [self _updateEditing]; +} + +- (void)setRepresentedObject:(id)representedObject { + if(self.representedAttribute) { + [NSNotificationCenter.defaultCenter removeObserver:self name:KPKWillChangeAttributeNotification object:self.representedObject]; + [NSNotificationCenter.defaultCenter removeObserver:self name:KPKDidChangeAttributeNotification object:self.representedObject]; + } + super.representedObject = representedObject; + if(self.representedAttribute) { + [NSNotificationCenter.defaultCenter addObserver:self + selector:(@selector(_willChangeAttribute:)) + name:KPKWillChangeAttributeNotification + object:self.representedAttribute]; + [NSNotificationCenter.defaultCenter addObserver:self + selector:(@selector(_didChangeAttribute:)) + name:KPKDidChangeAttributeNotification + object:self.representedAttribute]; + + } + _isDefaultAttribute = self.representedAttribute.isDefault; + [self _updateValues]; +} + +- (BOOL)textField:(NSTextField *)textField textView:(NSTextView *)textView performAction:(SEL)action { + if(action != @selector(copy:)) { + return YES; + } + + + // Only copy action + MPPasteboardOverlayInfoType info = MPPasteboardOverlayInfoCustom; + NSMutableString *selectedValue = [[NSMutableString alloc] init]; + for(NSValue *rangeValue in textView.selectedRanges) { + [selectedValue appendString:[textView.string substringWithRange:rangeValue.rangeValue]]; + } + if(selectedValue.length == 0) { + [selectedValue setString:textView.string]; + } + NSString *name = @""; + if([self.representedAttribute.key isEqual:kKPKUsernameKey]) { + info = MPPasteboardOverlayInfoUsername; + } + else if([self.representedAttribute.key isEqual:kKPKPasswordKey]) { + info = MPPasteboardOverlayInfoPassword; + } + else if([self.representedAttribute.key isEqual:kKPKURLKey]) { + info = MPPasteboardOverlayInfoURL; + } + else if([self.representedAttribute.key isEqual:kKPKTitleKey]) { + name = NSLocalizedString(@"TITLE", "Displayed name when title field was copied"); + } + else { + name = self.representedAttribute.key; + } + [MPPasteBoardController.defaultController copyObject:selectedValue overlayInfo:info name:name atView:self.view]; + return NO; +} + + +- (void)_willChangeAttribute:(NSNotification *)notification { + // nothing to d +} + +- (void)_didChangeAttribute:(NSNotification *)notification { + [self _updateValues]; +} + +- (void)_updateValues { + self.view.hidden = (!self.isEditor && self.representedAttribute.value.length == 0); + self.keyTextField.stringValue = self.representedAttribute.key ? self.representedAttribute.key : @""; + self.valueTextField.stringValue = self.representedAttribute.value ? self.representedAttribute.value : @""; +} + +- (void)_updateEditing { + self.keyTextField.editable = !_isDefaultAttribute && self.isEditor; + self.valueTextField.editable = self.isEditor; + self.keyTextField.selectable = YES; + self.valueTextField.selectable = YES; +} + +@end + diff --git a/MacPass/MPEntryAttributeViewController.xib b/MacPass/MPEntryAttributeViewController.xib new file mode 100644 index 00000000..fcec34be --- /dev/null +++ b/MacPass/MPEntryAttributeViewController.xib @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/MacPass/MPEntryInspectorViewController.m b/MacPass/MPEntryInspectorViewController.m index 10699b72..6e487150 100644 --- a/MacPass/MPEntryInspectorViewController.m +++ b/MacPass/MPEntryInspectorViewController.m @@ -33,6 +33,7 @@ #import "MPReferenceBuilderViewController.h" #import "MPTOTPViewController.h" #import "MPTOTPSetupViewController.h" +#import "MPEntryAttributeViewController.h" #import "MPPrettyPasswordTransformer.h" #import "NSString+MPPasswordCreation.h" @@ -75,6 +76,7 @@ typedef NS_ENUM(NSUInteger, MPEntryTab) { MPWindowTitleComboBoxDelegate *_windowTitleMenuDelegate; MPTagsTokenFieldDelegate *_tagTokenFieldDelegate; MPAddCustomFieldContextMenuDelegate *_addCustomFieldContextMenuDelegate; + NSMutableArray *_attributeEditorViewControllers; } @property (nonatomic, assign) BOOL showPassword; @@ -111,6 +113,7 @@ typedef NS_ENUM(NSUInteger, MPEntryTab) { _customFieldTableDelegate.viewController = self; _addCustomFieldContextMenuDelegate.viewController = self; + _attributeEditorViewControllers = [[NSMutableArray alloc] init]; _activeTab = MPEntryTabGeneral; } return self; @@ -130,6 +133,9 @@ typedef NS_ENUM(NSUInteger, MPEntryTab) { } super.representedObject = representedObject; self.totpViewController.representedObject = self.representedObject; + + //[self _updateAttributeEditors]; + /* only register for a single entry! */ if(self.representedEntry) { [NSNotificationCenter.defaultCenter addObserver:self selector:@selector(_willChangeEntry:) name:KPKWillChangeEntryNotification object:self.representedEntry]; @@ -195,9 +201,12 @@ typedef NS_ENUM(NSUInteger, MPEntryTab) { self.tagsTokenField.delegate = _tagTokenFieldDelegate; [self _setupTOPTView]; + + //[self _setupAttributeEditors]; + //[self _updateAttributeEditors]; + [self _setupCustomFieldsButton]; [self _setupViewBindings]; - [self _updateFieldVisibilty]; } - (void)registerNotificationsForDocument:(MPDocument *)document { @@ -607,8 +616,20 @@ typedef NS_ENUM(NSUInteger, MPEntryTab) { //[self.addCustomFieldButton setEnabled:NO forSegment:MPContextButtonSegmentContextButton]; } -- (void)_updateFieldVisibilty { - +- (void)_setupAttributeEditors { + for(NSUInteger index = 0; index < kKPKDefaultEntryKeysCount; index++) { + MPEntryAttributeViewController *vc = [[MPEntryAttributeViewController alloc] init]; + vc.isEditor = NO; + [_attributeEditorViewControllers addObject:vc]; + [self.fieldsStackView addArrangedSubview:vc.view]; + } +} + +- (void)_updateAttributeEditors { + _attributeEditorViewControllers[0].representedObject = [self.representedEntry attributeWithKey:kKPKTitleKey]; + _attributeEditorViewControllers[1].representedObject = [self.representedEntry attributeWithKey:kKPKUsernameKey]; + _attributeEditorViewControllers[2].representedObject = [self.representedEntry attributeWithKey:kKPKPasswordKey]; + _attributeEditorViewControllers[3].representedObject = [self.representedEntry attributeWithKey:kKPKURLKey]; } - (void)_setupTOPTView { @@ -716,7 +737,11 @@ typedef NS_ENUM(NSUInteger, MPEntryTab) { } - (void)_didChangeEntry:(NSNotification *)notification { - NSLog(@"didChangeEntry"); + if(notification.object != self.representedObject) { + NSLog(@"Skipping: didChangeEntry:%@, we do not need this change!", notification.object); + return; + } + NSLog(@"didChangeEntry:%@", notification.object); [self _updateEntryValues]; } diff --git a/MacPass/MPInspectorEditor.h b/MacPass/MPInspectorEditor.h new file mode 100644 index 00000000..7869bce8 --- /dev/null +++ b/MacPass/MPInspectorEditor.h @@ -0,0 +1,23 @@ +// +// MPInspectorEditor.h +// MacPass +// +// Created by Michael Starke on 14.10.21. +// Copyright © 2021 HicknHack Software GmbH. All rights reserved. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +/// The InpsectorEditor protocoll that should be implemented by editors used in the inspector +/// Individual editors shoudl adopt different APIs to accomodate their needs +/// The preferred way to set model data is to use the representedObject +@protocol MPInspectorEditor + +@required +@property (nonatomic) BOOL isEditor; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MacPass/MPTOTPSetupViewController.m b/MacPass/MPTOTPSetupViewController.m index fe580494..d24eb2ef 100644 --- a/MacPass/MPTOTPSetupViewController.m +++ b/MacPass/MPTOTPSetupViewController.m @@ -21,6 +21,8 @@ @property (strong) IBOutlet NSGridView *gridView; @property (strong) IBOutlet NSPopUpButton *typePopUpButton; +@property (nonatomic, readonly) KPKEntry *representedEntry; + @property NSInteger timeSlice; @end @@ -43,19 +45,17 @@ typedef NS_ENUM(NSUInteger, MPOTPType) { @implementation MPTOTPSetupViewController -- (void)viewDidLoad { - [super viewDidLoad]; - NSAssert([self.representedObject isKindOfClass:KPKEntry.class], @"represented object needs to be a KPKEntry"); - - [self _setupView]; - [self _updateView:MPOTPUpdateSourceEntry]; +- (KPKEntry *)representedEntry { + if([self.representedObject isKindOfClass:KPKEntry.class]) { + return (KPKEntry *)self.representedObject; + } + return nil; } -- (IBAction)toggleDisclosure:(id)sender { - for(NSInteger row = 1; row < self.gridView.numberOfRows; row++) { - NSGridRow *gridRow = [self.gridView rowAtIndex:row]; - gridRow.hidden = !gridRow.hidden; - } +- (void)viewDidLoad { + [super viewDidLoad]; + [self _setupView]; + [self _updateView:MPOTPUpdateSourceEntry]; } - (IBAction)changeType:(id)sender { @@ -131,6 +131,14 @@ typedef NS_ENUM(NSUInteger, MPOTPType) { [self.timeStepTextField bind:NSValueBinding toObject:self withKeyPath:NSStringFromSelector(@selector(timeSlice)) options:nil]; [self.timeStepStepper bind:NSValueBinding toObject:self withKeyPath:NSStringFromSelector(@selector(timeSlice)) options:nil]; + + KPKEntry *entry = self.representedEntry; + if(entry.hasTimeOTP) { + KPKTimeOTPGenerator *generator = [[KPKTimeOTPGenerator alloc] initWithAttributes:self.representedEntry.attributes]; + if(generator.isRFC6238) { + [self.typePopUpButton selectItemWithTag:MPOTPTypeRFC]; + } + } } - (void)_updateView:(MPOTPUpdateSource)source { @@ -151,12 +159,15 @@ typedef NS_ENUM(NSUInteger, MPOTPType) { NSString *qrCodeString = self.qrCodeImageView.image.QRCodeString; NSURL *otpURL = [NSURL URLWithString:qrCodeString]; self.urlTextField.stringValue = otpURL.absoluteString; - // fallthroug + generator = [[KPKTimeOTPGenerator alloc] initWithURL:self.urlTextField.stringValue]; + break; } case MPOTPUpdateSourceURL: generator = [[KPKTimeOTPGenerator alloc] initWithURL:self.urlTextField.stringValue]; break; + case MPOTPUpdateSourceSecret: + generator.key = [NSData dataWithBase32EncodedString:self.secretTextField.stringValue]; break; case MPOTPUpdateSourceAlgorithm: break; diff --git a/MacPass/MPTOTPViewController.m b/MacPass/MPTOTPViewController.m index 71b2c1c3..2bfd34f6 100644 --- a/MacPass/MPTOTPViewController.m +++ b/MacPass/MPTOTPViewController.m @@ -61,7 +61,6 @@ return NO; } return YES; - } diff --git a/MacPass/MPTOTPViewController.xib b/MacPass/MPTOTPViewController.xib index 64af502f..18421d43 100644 --- a/MacPass/MPTOTPViewController.xib +++ b/MacPass/MPTOTPViewController.xib @@ -1,8 +1,8 @@ - + - + @@ -94,7 +94,7 @@ - +