Added view to edit and display entry passwords

This commit is contained in:
Michael Starke
2021-10-19 00:57:11 +02:00
parent f28bcb527a
commit 83f8158b21
9 changed files with 210 additions and 31 deletions

View File

@@ -286,6 +286,8 @@
4CE5B54B173AFBA700207B39 /* MPDocument.m in Sources */ = {isa = PBXBuildFile; fileRef = 4CE5B549173AFBA700207B39 /* MPDocument.m */; }; 4CE5B54B173AFBA700207B39 /* MPDocument.m in Sources */ = {isa = PBXBuildFile; fileRef = 4CE5B549173AFBA700207B39 /* MPDocument.m */; };
4CE8246F16E2E93400573141 /* MPOverlayWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4CE8246E16E2E93400573141 /* MPOverlayWindowController.m */; }; 4CE8246F16E2E93400573141 /* MPOverlayWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4CE8246E16E2E93400573141 /* MPOverlayWindowController.m */; };
4CE8247516E2F2B900573141 /* MPOverlayView.m in Sources */ = {isa = PBXBuildFile; fileRef = 4CE8247416E2F2B900573141 /* MPOverlayView.m */; }; 4CE8247516E2F2B900573141 /* MPOverlayView.m in Sources */ = {isa = PBXBuildFile; fileRef = 4CE8247416E2F2B900573141 /* MPOverlayView.m */; };
4CE84903271E10AC00EBAB0C /* MPEntryPasswordAttributeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4CE84901271E10AC00EBAB0C /* MPEntryPasswordAttributeViewController.m */; };
4CE84904271E10AC00EBAB0C /* MPEntryPasswordAttributeViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4CE84902271E10AC00EBAB0C /* MPEntryPasswordAttributeViewController.xib */; };
4CE88B9717BA651C0042E078 /* contextTriangleTemplate.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 4CE88B9617BA651C0042E078 /* contextTriangleTemplate.pdf */; }; 4CE88B9717BA651C0042E078 /* contextTriangleTemplate.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 4CE88B9617BA651C0042E078 /* contextTriangleTemplate.pdf */; };
4CEE46DD181C301D006BF1E5 /* MPAutotypeDaemon.m in Sources */ = {isa = PBXBuildFile; fileRef = 4CEE46DC181C301D006BF1E5 /* MPAutotypeDaemon.m */; }; 4CEE46DD181C301D006BF1E5 /* MPAutotypeDaemon.m in Sources */ = {isa = PBXBuildFile; fileRef = 4CEE46DC181C301D006BF1E5 /* MPAutotypeDaemon.m */; };
4CEED1C617D7BD0E007180F1 /* NSError+Messages.m in Sources */ = {isa = PBXBuildFile; fileRef = 4CEED1C517D7BD0E007180F1 /* NSError+Messages.m */; }; 4CEED1C617D7BD0E007180F1 /* NSError+Messages.m in Sources */ = {isa = PBXBuildFile; fileRef = 4CEED1C517D7BD0E007180F1 /* NSError+Messages.m */; };
@@ -880,6 +882,9 @@
4CE8246E16E2E93400573141 /* MPOverlayWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPOverlayWindowController.m; sourceTree = "<group>"; }; 4CE8246E16E2E93400573141 /* MPOverlayWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPOverlayWindowController.m; sourceTree = "<group>"; };
4CE8247316E2F2B900573141 /* MPOverlayView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPOverlayView.h; sourceTree = "<group>"; }; 4CE8247316E2F2B900573141 /* MPOverlayView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPOverlayView.h; sourceTree = "<group>"; };
4CE8247416E2F2B900573141 /* MPOverlayView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPOverlayView.m; sourceTree = "<group>"; }; 4CE8247416E2F2B900573141 /* MPOverlayView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPOverlayView.m; sourceTree = "<group>"; };
4CE84900271E10AC00EBAB0C /* MPEntryPasswordAttributeViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MPEntryPasswordAttributeViewController.h; sourceTree = "<group>"; };
4CE84901271E10AC00EBAB0C /* MPEntryPasswordAttributeViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MPEntryPasswordAttributeViewController.m; sourceTree = "<group>"; };
4CE84902271E10AC00EBAB0C /* MPEntryPasswordAttributeViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = MPEntryPasswordAttributeViewController.xib; sourceTree = "<group>"; };
4CE88B9617BA651C0042E078 /* contextTriangleTemplate.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = contextTriangleTemplate.pdf; sourceTree = "<group>"; }; 4CE88B9617BA651C0042E078 /* contextTriangleTemplate.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = contextTriangleTemplate.pdf; sourceTree = "<group>"; };
4CE88C2417C163FE00BFD195 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = System/Library/Frameworks/CoreFoundation.framework; sourceTree = SDKROOT; }; 4CE88C2417C163FE00BFD195 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = System/Library/Frameworks/CoreFoundation.framework; sourceTree = SDKROOT; };
4CE88C3317C1647400BFD195 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 4CE88C3317C1647400BFD195 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
@@ -1442,6 +1447,9 @@
4CC0192B271836CD00459789 /* MPEntryAttributeViewController.h */, 4CC0192B271836CD00459789 /* MPEntryAttributeViewController.h */,
4CC0192C271836CD00459789 /* MPEntryAttributeViewController.m */, 4CC0192C271836CD00459789 /* MPEntryAttributeViewController.m */,
4CC0192D271836CD00459789 /* MPEntryAttributeViewController.xib */, 4CC0192D271836CD00459789 /* MPEntryAttributeViewController.xib */,
4CE84900271E10AC00EBAB0C /* MPEntryPasswordAttributeViewController.h */,
4CE84901271E10AC00EBAB0C /* MPEntryPasswordAttributeViewController.m */,
4CE84902271E10AC00EBAB0C /* MPEntryPasswordAttributeViewController.xib */,
); );
name = Inspector; name = Inspector;
sourceTree = "<group>"; sourceTree = "<group>";
@@ -2073,6 +2081,7 @@
4C701CBC178618A000581B88 /* 12_RemoteTemplate.pdf in Resources */, 4C701CBC178618A000581B88 /* 12_RemoteTemplate.pdf in Resources */,
4CF29BF417879D0000851B60 /* 26_FileSaveTemplate.pdf in Resources */, 4CF29BF417879D0000851B60 /* 26_FileSaveTemplate.pdf in Resources */,
4C7BD07619FE94C900C7AA5C /* Assets.xcassets in Resources */, 4C7BD07619FE94C900C7AA5C /* Assets.xcassets in Resources */,
4CE84904271E10AC00EBAB0C /* MPEntryPasswordAttributeViewController.xib in Resources */,
4CA182781F96523600DD4A4A /* DuplicateEntryOptionsWindow.xib in Resources */, 4CA182781F96523600DD4A4A /* DuplicateEntryOptionsWindow.xib in Resources */,
4C52A88E1788628B00868229 /* 06_BlockDeviceTemplate.pdf in Resources */, 4C52A88E1788628B00868229 /* 06_BlockDeviceTemplate.pdf in Resources */,
4C52A88F1788628B00868229 /* 13_KeysTemplate.pdf in Resources */, 4C52A88F1788628B00868229 /* 13_KeysTemplate.pdf in Resources */,
@@ -2270,6 +2279,7 @@
4CCEDE2A179F203B008402BE /* MPOutlineView.m in Sources */, 4CCEDE2A179F203B008402BE /* MPOutlineView.m in Sources */,
4CB33F861EAF54A000C9341E /* KPKNode+MPIsHistory.m in Sources */, 4CB33F861EAF54A000C9341E /* KPKNode+MPIsHistory.m in Sources */,
4CCEDE2E179F213B008402BE /* MPNotifications.m in Sources */, 4CCEDE2E179F213B008402BE /* MPNotifications.m in Sources */,
4CE84903271E10AC00EBAB0C /* MPEntryPasswordAttributeViewController.m in Sources */,
4C17D8E517A1C780006C8C1E /* MPDocumentWindowDelegate.m in Sources */, 4C17D8E517A1C780006C8C1E /* MPDocumentWindowDelegate.m in Sources */,
4C63B8FB17A3154D0091BD72 /* MPContextButton.m in Sources */, 4C63B8FB17A3154D0091BD72 /* MPContextButton.m in Sources */,
4C1E9885185F71A800943563 /* MPContextBarViewController.m in Sources */, 4C1E9885185F71A800943563 /* MPContextBarViewController.m in Sources */,

View File

@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="17701" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES"> <document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="18122" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<dependencies> <dependencies>
<deployment identifier="macosx"/> <deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="17701"/> <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="18122"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies> </dependencies>
<objects> <objects>
@@ -97,7 +97,7 @@
<rect key="frame" x="20" y="26" width="233" height="396"/> <rect key="frame" x="20" y="26" width="233" height="396"/>
<clipView key="contentView" drawsBackground="NO" copiesOnScroll="NO" id="F3N-QI-Di5"> <clipView key="contentView" drawsBackground="NO" copiesOnScroll="NO" id="F3N-QI-Di5">
<rect key="frame" x="1" y="1" width="231" height="394"/> <rect key="frame" x="1" y="1" width="231" height="394"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews> <subviews>
<tableView verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="lastColumnOnly" multipleSelection="NO" autosaveColumns="NO" rowHeight="36" rowSizeStyle="automatic" viewBased="YES" id="137"> <tableView verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="lastColumnOnly" multipleSelection="NO" autosaveColumns="NO" rowHeight="36" rowSizeStyle="automatic" viewBased="YES" id="137">
<rect key="frame" x="0.0" y="0.0" width="231" height="394"/> <rect key="frame" x="0.0" y="0.0" width="231" height="394"/>
@@ -792,7 +792,7 @@
<tableColumnResizingMask key="resizingMask" resizeWithTable="YES"/> <tableColumnResizingMask key="resizingMask" resizeWithTable="YES"/>
<prototypeCellViews> <prototypeCellViews>
<tableCellView identifier="SelectedCell" translatesAutoresizingMaskIntoConstraints="NO" id="196" customClass="MPCustomFieldTableCellView"> <tableCellView identifier="SelectedCell" translatesAutoresizingMaskIntoConstraints="NO" id="196" customClass="MPCustomFieldTableCellView">
<rect key="frame" x="1" y="1" width="227" height="53"/> <rect key="frame" x="0.0" y="0.0" width="227" height="53"/>
<subviews> <subviews>
<textField verticalHuggingPriority="750" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="199" customClass="HNHUISecureTextField"> <textField verticalHuggingPriority="750" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="199" customClass="HNHUISecureTextField">
<rect key="frame" x="3" y="10" width="114" height="21"/> <rect key="frame" x="3" y="10" width="114" height="21"/>

View File

@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="17701" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES"> <document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="18122" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<dependencies> <dependencies>
<deployment identifier="macosx"/> <deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="17701"/> <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="18122"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies> </dependencies>
<objects> <objects>
@@ -83,7 +83,7 @@
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews> <subviews>
<textField verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="2985"> <textField verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="2985">
<rect key="frame" x="82" y="194" width="115" height="23"/> <rect key="frame" x="82" y="194" width="116" height="24"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="No Selection" id="2986"> <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="No Selection" id="2986">
<font key="font" metaFont="system" size="20"/> <font key="font" metaFont="system" size="20"/>
<color key="textColor" name="controlShadowColor" catalog="System" colorSpace="catalog"/> <color key="textColor" name="controlShadowColor" catalog="System" colorSpace="catalog"/>

View File

@@ -19,6 +19,13 @@ NS_ASSUME_NONNULL_BEGIN
/// The editor can be set to edit or view /// The editor can be set to edit or view
@interface MPEntryAttributeViewController : NSViewController <MPInspectorEditor, HNHUITextFieldDelegate> @interface MPEntryAttributeViewController : NSViewController <MPInspectorEditor, HNHUITextFieldDelegate>
@property (strong) IBOutlet NSTextField *keyTextField;
@property (strong) IBOutlet HNHUITextField *valueTextField;
- (void)updateValues;
- (void)updateEditing;
@end @end
NS_ASSUME_NONNULL_END NS_ASSUME_NONNULL_END

View File

@@ -14,8 +14,6 @@
@interface MPEntryAttributeViewController () { @interface MPEntryAttributeViewController () {
BOOL _isDefaultAttribute; BOOL _isDefaultAttribute;
} }
@property (strong) IBOutlet NSTextField *keyTextField;
@property (strong) IBOutlet HNHUITextField *valueTextField;
@property (readonly, nullable, strong) KPKAttribute *representedAttribute; @property (readonly, nullable, strong) KPKAttribute *representedAttribute;
@end @end
@@ -45,8 +43,8 @@
self.valueTextField.placeholderString = placeHolder; self.valueTextField.placeholderString = placeHolder;
[super viewDidLoad]; [super viewDidLoad];
[self _updateValues]; [self updateValues];
[self _updateEditing]; [self updateEditing];
__weak MPEntryAttributeViewController *welf = self; __weak MPEntryAttributeViewController *welf = self;
self.valueTextField.copyActionBlock = ^void(NSTextField *tf) { self.valueTextField.copyActionBlock = ^void(NSTextField *tf) {
@@ -66,7 +64,7 @@
- (void)setIsEditor:(BOOL)isEditor { - (void)setIsEditor:(BOOL)isEditor {
_isEditor = isEditor; _isEditor = isEditor;
[self _updateEditing]; [self updateEditing];
} }
- (void)setRepresentedObject:(id)representedObject { - (void)setRepresentedObject:(id)representedObject {
@@ -87,7 +85,7 @@
} }
_isDefaultAttribute = self.representedAttribute.isDefault; _isDefaultAttribute = self.representedAttribute.isDefault;
[self _updateValues]; [self updateValues];
} }
- (BOOL)textField:(NSTextField *)textField textView:(NSTextView *)textView performAction:(SEL)action { - (BOOL)textField:(NSTextField *)textField textView:(NSTextView *)textView performAction:(SEL)action {
@@ -95,7 +93,6 @@
return YES; return YES;
} }
// Only copy action // Only copy action
MPPasteboardOverlayInfoType info = MPPasteboardOverlayInfoCustom; MPPasteboardOverlayInfoType info = MPPasteboardOverlayInfoCustom;
NSMutableString *selectedValue = [[NSMutableString alloc] init]; NSMutableString *selectedValue = [[NSMutableString alloc] init];
@@ -109,9 +106,10 @@
if([self.representedAttribute.key isEqual:kKPKUsernameKey]) { if([self.representedAttribute.key isEqual:kKPKUsernameKey]) {
info = MPPasteboardOverlayInfoUsername; info = MPPasteboardOverlayInfoUsername;
} }
else if([self.representedAttribute.key isEqual:kKPKPasswordKey]) { /*else if([self.representedAttribute.key isEqual:kKPKPasswordKey]) {
info = MPPasteboardOverlayInfoPassword; info = MPPasteboardOverlayInfoPassword;
} }
*/
else if([self.representedAttribute.key isEqual:kKPKURLKey]) { else if([self.representedAttribute.key isEqual:kKPKURLKey]) {
info = MPPasteboardOverlayInfoURL; info = MPPasteboardOverlayInfoURL;
} }
@@ -131,16 +129,16 @@
} }
- (void)_didChangeAttribute:(NSNotification *)notification { - (void)_didChangeAttribute:(NSNotification *)notification {
[self _updateValues]; [self updateValues];
} }
- (void)_updateValues { - (void)updateValues {
self.view.hidden = (!self.isEditor && self.representedAttribute.value.length == 0); self.view.hidden = (!self.isEditor && self.representedAttribute.value.length == 0);
self.keyTextField.stringValue = self.representedAttribute.key ? self.representedAttribute.key : @""; self.keyTextField.stringValue = self.representedAttribute.key ? self.representedAttribute.key : @"";
self.valueTextField.stringValue = self.representedAttribute.value ? self.representedAttribute.value : @""; self.valueTextField.stringValue = self.representedAttribute.value ? self.representedAttribute.value : @"";
} }
- (void)_updateEditing { - (void)updateEditing {
self.keyTextField.editable = !_isDefaultAttribute && self.isEditor; self.keyTextField.editable = !_isDefaultAttribute && self.isEditor;
self.valueTextField.editable = self.isEditor; self.valueTextField.editable = self.isEditor;
self.keyTextField.selectable = YES; self.keyTextField.selectable = YES;

View File

@@ -0,0 +1,18 @@
//
// MPEntryPasswordAttributeViewController.h
// MacPass
//
// Created by Michael Starke on 18.10.21.
// Copyright © 2021 HicknHack Software GmbH. All rights reserved.
//
#import <Cocoa/Cocoa.h>
#import "MPEntryAttributeViewController.h"
NS_ASSUME_NONNULL_BEGIN
@interface MPEntryPasswordAttributeViewController : MPEntryAttributeViewController
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,37 @@
//
// MPEntryPasswordAttributeViewController.m
// MacPass
//
// Created by Michael Starke on 18.10.21.
// Copyright © 2021 HicknHack Software GmbH. All rights reserved.
//
#import "MPEntryPasswordAttributeViewController.h"
#import <HNHUi/HNHUi.h>
#import <KeePassKit/KeePassKit.h>
@interface MPEntryPasswordAttributeViewController ()
@property (strong) IBOutlet HNHUISecureTextField *passwordTextField;
@property (strong) IBOutlet NSButton *togglePasswordButton;
@property (strong) IBOutlet NSButton *generatePasswordButton;
@property (strong, nullable, readonly) KPKAttribute *representedAttribute;
@end
@implementation MPEntryPasswordAttributeViewController
- (void)updateValues {
self.view.hidden = (!self.isEditor && self.representedAttribute.value.length == 0);
self.passwordTextField.stringValue = self.representedAttribute.value ? self.representedAttribute.value : @"";
}
- (void)updateEditing {
self.generatePasswordButton.hidden = !self.isEditor;
self.passwordTextField.editable = self.isEditor;
self.passwordTextField.selectable = YES;
}
@end

View File

@@ -0,0 +1,104 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="18122" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<dependencies>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="18122"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="MPEntryPasswordAttributeViewController">
<connections>
<outlet property="generatePasswordButton" destination="UlI-yI-Sqn" id="sKR-Rd-2LC"/>
<outlet property="keyTextField" destination="2aN-Ps-z4K" id="ua7-Km-K5o"/>
<outlet property="passwordTextField" destination="tpF-hp-29r" id="2pM-fr-9l0"/>
<outlet property="togglePasswordButton" destination="AY0-XE-8S7" id="IwM-pB-tQn"/>
<outlet property="view" destination="Hz6-mo-xeY" id="0bl-1N-x8E"/>
</connections>
</customObject>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
<customView id="Hz6-mo-xeY">
<rect key="frame" x="0.0" y="0.0" width="480" height="42"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<subviews>
<stackView distribution="fill" orientation="vertical" alignment="leading" horizontalStackHuggingPriority="249.99998474121094" verticalStackHuggingPriority="249.99998474121094" detachesHiddenViews="YES" translatesAutoresizingMaskIntoConstraints="NO" id="jTp-ga-xuT">
<rect key="frame" x="0.0" y="0.0" width="480" height="42"/>
<subviews>
<textField horizontalHuggingPriority="249" verticalHuggingPriority="750" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="2aN-Ps-z4K">
<rect key="frame" x="-2" y="28" width="484" height="14"/>
<textFieldCell key="cell" controlSize="small" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Password" id="Piv-zL-dtc">
<font key="font" metaFont="smallSystem"/>
<color key="textColor" name="disabledControlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<stackView distribution="fill" orientation="horizontal" alignment="centerY" horizontalStackHuggingPriority="249.99998474121094" verticalStackHuggingPriority="249.99998474121094" horizontalHuggingPriority="249" detachesHiddenViews="YES" translatesAutoresizingMaskIntoConstraints="NO" id="XRh-Fs-reW">
<rect key="frame" x="0.0" y="0.0" width="480" height="20"/>
<subviews>
<secureTextField horizontalHuggingPriority="249" verticalHuggingPriority="750" horizontalCompressionResistancePriority="249" allowsCharacterPickerTouchBarItem="YES" contentType="oneTimeCode" translatesAutoresizingMaskIntoConstraints="NO" id="tpF-hp-29r" customClass="HNHUISecureTextField">
<rect key="frame" x="0.0" y="0.0" width="352" height="20"/>
<secureTextFieldCell key="cell" lineBreakMode="truncatingTail" truncatesLastVisibleLine="YES" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" borderStyle="bezel" drawsBackground="YES" usesSingleLineMode="YES" id="CeT-F7-Vb3">
<font key="font" size="13" name="Menlo-Regular"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
<allowedInputSourceLocales>
<string>NSAllRomanInputSourcesLocaleIdentifier</string>
</allowedInputSourceLocales>
</secureTextFieldCell>
<connections>
<outlet property="nextKeyView" destination="AY0-XE-8S7" id="uPk-2E-Bwh"/>
</connections>
</secureTextField>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="AY0-XE-8S7">
<rect key="frame" x="353" y="-7" width="50" height="32"/>
<buttonCell key="cell" type="push" bezelStyle="rounded" image="NSQuickLookTemplate" imagePosition="only" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="NUE-lS-hzr">
<behavior key="behavior" lightByBackground="YES" lightByGray="YES" changeBackground="YES" changeGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<outlet property="nextKeyView" destination="UlI-yI-Sqn" id="6uu-J3-TEc"/>
</connections>
</button>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="UlI-yI-Sqn">
<rect key="frame" x="397" y="-7" width="90" height="32"/>
<buttonCell key="cell" type="push" title="Generate" bezelStyle="rounded" alignment="center" state="on" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="Rx9-ck-eKo">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
</button>
</subviews>
<visibilityPriorities>
<integer value="1000"/>
<integer value="1000"/>
<integer value="1000"/>
</visibilityPriorities>
<customSpacing>
<real value="3.4028234663852886e+38"/>
<real value="3.4028234663852886e+38"/>
<real value="3.4028234663852886e+38"/>
</customSpacing>
</stackView>
</subviews>
<visibilityPriorities>
<integer value="1000"/>
<integer value="1000"/>
</visibilityPriorities>
<customSpacing>
<real value="3.4028234663852886e+38"/>
<real value="3.4028234663852886e+38"/>
</customSpacing>
</stackView>
</subviews>
<constraints>
<constraint firstAttribute="trailing" secondItem="jTp-ga-xuT" secondAttribute="trailing" id="8qT-FW-gVh"/>
<constraint firstItem="jTp-ga-xuT" firstAttribute="leading" secondItem="Hz6-mo-xeY" secondAttribute="leading" id="Hla-na-Bw8"/>
<constraint firstAttribute="bottom" secondItem="jTp-ga-xuT" secondAttribute="bottom" id="pcp-4W-Bvc"/>
<constraint firstItem="jTp-ga-xuT" firstAttribute="top" secondItem="Hz6-mo-xeY" secondAttribute="top" id="wEy-tv-xz0"/>
</constraints>
<point key="canvasLocation" x="173" y="112"/>
</customView>
</objects>
<resources>
<image name="NSQuickLookTemplate" width="21" height="13"/>
</resources>
</document>

View File

@@ -22,6 +22,7 @@
@property (strong) IBOutlet NSPopUpButton *typePopUpButton; @property (strong) IBOutlet NSPopUpButton *typePopUpButton;
@property (nonatomic, readonly) KPKEntry *representedEntry; @property (nonatomic, readonly) KPKEntry *representedEntry;
@property (copy) KPKTimeOTPGenerator *generator;
@property NSInteger timeSlice; @property NSInteger timeSlice;
@@ -134,8 +135,8 @@ typedef NS_ENUM(NSUInteger, MPOTPType) {
KPKEntry *entry = self.representedEntry; KPKEntry *entry = self.representedEntry;
if(entry.hasTimeOTP) { if(entry.hasTimeOTP) {
KPKTimeOTPGenerator *generator = [[KPKTimeOTPGenerator alloc] initWithAttributes:self.representedEntry.attributes]; self.generator = [[KPKTimeOTPGenerator alloc] initWithAttributes:self.representedEntry.attributes];
if(generator.isRFC6238) { if(self.generator.isRFC6238) {
[self.typePopUpButton selectItemWithTag:MPOTPTypeRFC]; [self.typePopUpButton selectItemWithTag:MPOTPTypeRFC];
} }
} }
@@ -152,26 +153,30 @@ typedef NS_ENUM(NSUInteger, MPOTPType) {
MPOTPUpdateSourceEntry MPOTPUpdateSourceEntry
*/ */
KPKTimeOTPGenerator *generator = [[KPKTimeOTPGenerator alloc] initWithAttributes:((KPKEntry *)self.representedObject).attributes]; if(!self.generator) {
self.generator = [[KPKTimeOTPGenerator alloc] initWithAttributes:((KPKEntry *)self.representedObject).attributes];
}
switch(source) { switch(source) {
case MPOTPUpdateSourceQRImage: { case MPOTPUpdateSourceQRImage: {
NSString *qrCodeString = self.qrCodeImageView.image.QRCodeString; NSString *qrCodeString = self.qrCodeImageView.image.QRCodeString;
NSURL *otpURL = [NSURL URLWithString:qrCodeString]; NSURL *otpURL = [NSURL URLWithString:qrCodeString];
self.urlTextField.stringValue = otpURL.absoluteString; self.urlTextField.stringValue = otpURL.absoluteString;
generator = [[KPKTimeOTPGenerator alloc] initWithURL:self.urlTextField.stringValue]; self.generator = [[KPKTimeOTPGenerator alloc] initWithURL:self.urlTextField.stringValue];
break; break;
} }
case MPOTPUpdateSourceURL: case MPOTPUpdateSourceURL:
generator = [[KPKTimeOTPGenerator alloc] initWithURL:self.urlTextField.stringValue]; self.generator = [[KPKTimeOTPGenerator alloc] initWithURL:self.urlTextField.stringValue];
break; break;
case MPOTPUpdateSourceSecret: case MPOTPUpdateSourceSecret:
generator.key = [NSData dataWithBase32EncodedString:self.secretTextField.stringValue]; self.generator.key = [NSData dataWithBase32EncodedString:self.secretTextField.stringValue];
break; break;
case MPOTPUpdateSourceAlgorithm: case MPOTPUpdateSourceAlgorithm:
//self.generator.hashAlgorithm =
break; break;
case MPOTPUpdateSourceTimeSlice: case MPOTPUpdateSourceTimeSlice:
//self.generator.timeSlice =
break; break;
case MPOTPUpdateSourceEntry: case MPOTPUpdateSourceEntry:
break; break;
@@ -194,16 +199,16 @@ typedef NS_ENUM(NSUInteger, MPOTPType) {
self.qrCodeImageView.image = [NSImage QRCodeImageWithString:authURL.absoluteString]; self.qrCodeImageView.image = [NSImage QRCodeImageWithString:authURL.absoluteString];
} }
} }
else {
// generate the URL
}
/* secret */ /* secret */
NSString *secret = [generator.key base32EncodedStringWithOptions:0]; NSString *secret = [self.generator.key base32EncodedStringWithOptions:0];
self.secretTextField.stringValue = secret ? secret : @""; self.secretTextField.stringValue = secret ? secret : @"";
[self.algorithmPopUpButton selectItemWithTag:self.generator.hashAlgorithm];
[self.algorithmPopUpButton selectItemWithTag:generator.hashAlgorithm]; [self.digitCountPopUpButton selectItemWithTag:self.generator.numberOfDigits];
self.timeSlice = self.generator.timeSlice;
[self.digitCountPopUpButton selectItemWithTag:generator.numberOfDigits];
self.timeSlice = generator.timeSlice;
} }