Converted password change window to use NSGridView.
Errors are displayed if a KeePass database is selected as key file. Password and key errors are now displayed separatly
This commit is contained in:
parent
e4fadce3d0
commit
5457d4dde0
|
@ -1,17 +1,18 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="15705" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="17701" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
|
||||
<dependencies>
|
||||
<deployment identifier="macosx"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="15705"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="17701"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<customObject id="-2" userLabel="File's Owner" customClass="MPPasswordEditWindowController">
|
||||
<connections>
|
||||
<outlet property="changePasswordButton" destination="68" id="85"/>
|
||||
<outlet property="errorTextField" destination="12" id="79"/>
|
||||
<outlet property="hasPasswordSwitchButton" destination="yKc-I9-uzv" id="aUH-R4-WwP"/>
|
||||
<outlet property="keyErrorTextField" destination="ibK-Px-Fvt" id="l7h-qa-idf"/>
|
||||
<outlet property="keyfilePathControl" destination="4" id="63"/>
|
||||
<outlet property="passwordErrorTextField" destination="12" id="79"/>
|
||||
<outlet property="passwordRepeatTextField" destination="11" id="62"/>
|
||||
<outlet property="passwordTextField" destination="9" id="61"/>
|
||||
<outlet property="togglePasswordButton" destination="7" id="64"/>
|
||||
|
@ -23,99 +24,14 @@
|
|||
<window title="Change Password" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" visibleAtLaunch="NO" animationBehavior="default" id="1">
|
||||
<windowStyleMask key="styleMask" titled="YES" closable="YES"/>
|
||||
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
|
||||
<rect key="contentRect" x="196" y="240" width="403" height="219"/>
|
||||
<rect key="contentRect" x="196" y="240" width="307" height="211"/>
|
||||
<rect key="screenRect" x="0.0" y="0.0" width="2560" height="1417"/>
|
||||
<view key="contentView" id="2">
|
||||
<rect key="frame" x="0.0" y="0.0" width="403" height="210"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="369" height="231"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<pathControl verticalHuggingPriority="750" allowsExpansionToolTips="YES" translatesAutoresizingMaskIntoConstraints="NO" id="4" customClass="MPPathControl">
|
||||
<rect key="frame" x="105" y="87" width="242" height="25"/>
|
||||
<pathCell key="cell" selectable="YES" editable="YES" alignment="left" pathStyle="popUp" id="23" customClass="MPPathCell">
|
||||
<font key="font" metaFont="system"/>
|
||||
</pathCell>
|
||||
</pathControl>
|
||||
<textField verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="5">
|
||||
<rect key="frame" x="53" y="91" width="49" height="16"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Keyfile:" id="22">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="6">
|
||||
<rect key="frame" x="108" y="60" width="236" height="23"/>
|
||||
<buttonCell key="cell" type="roundTextured" title="Generate Keyfile" bezelStyle="texturedRounded" alignment="center" state="on" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="21">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="generateKey:" target="-2" id="66"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="7">
|
||||
<rect key="frame" x="352" y="145" width="31" height="23"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="31" id="59"/>
|
||||
</constraints>
|
||||
<buttonCell key="cell" type="roundTextured" bezelStyle="texturedRounded" image="NSQuickLookTemplate" imagePosition="only" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="20">
|
||||
<behavior key="behavior" pushIn="YES" changeContents="YES" lightByContents="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
</button>
|
||||
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="8">
|
||||
<rect key="frame" x="352" y="89" width="31" height="23"/>
|
||||
<buttonCell key="cell" type="roundTextured" bezelStyle="texturedRounded" image="NSStopProgressTemplate" imagePosition="only" alignment="center" state="on" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="19">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="clearKey:" target="-2" id="65"/>
|
||||
</connections>
|
||||
</button>
|
||||
<secureTextField verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="9" customClass="HNHUISecureTextField">
|
||||
<rect key="frame" x="108" y="148" width="236" height="20"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" relation="greaterThanOrEqual" constant="200" id="Gin-yR-DMk"/>
|
||||
</constraints>
|
||||
<secureTextFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" borderStyle="bezel" placeholderString="Enter Password" drawsBackground="YES" usesSingleLineMode="YES" id="18">
|
||||
<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>
|
||||
</secureTextField>
|
||||
<textField verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="10">
|
||||
<rect key="frame" x="51" y="121" width="51" height="16"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Repeat:" id="16">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<secureTextField verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="11" customClass="HNHUISecureTextField">
|
||||
<rect key="frame" x="108" y="118" width="236" height="20"/>
|
||||
<secureTextFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" borderStyle="bezel" placeholderString="Repeat Password" drawsBackground="YES" usesSingleLineMode="YES" id="15">
|
||||
<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>
|
||||
</secureTextField>
|
||||
<textField verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="12">
|
||||
<rect key="frame" x="161" y="176" width="131" height="14"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Mismatching Passwords" id="14">
|
||||
<font key="font" metaFont="smallSystem"/>
|
||||
<color key="textColor" red="1" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="68">
|
||||
<rect key="frame" x="240" y="13" width="149" height="32"/>
|
||||
<rect key="frame" x="206" y="13" width="149" height="32"/>
|
||||
<buttonCell key="cell" type="push" title="Change Password" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="69">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
|
@ -125,7 +41,7 @@
|
|||
</connections>
|
||||
</button>
|
||||
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="72">
|
||||
<rect key="frame" x="158" y="13" width="82" height="32"/>
|
||||
<rect key="frame" x="124" y="13" width="82" height="32"/>
|
||||
<buttonCell key="cell" type="push" title="Cancel" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="73">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
|
@ -137,59 +53,167 @@ Gw
|
|||
<action selector="cancel:" target="-2" id="84"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button horizontalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="yKc-I9-uzv">
|
||||
<rect key="frame" x="18" y="150" width="84" height="18"/>
|
||||
<buttonCell key="cell" type="check" title="Password:" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="OQz-DA-SoY">
|
||||
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
</button>
|
||||
<gridView xPlacement="leading" yPlacement="bottom" rowAlignment="none" translatesAutoresizingMaskIntoConstraints="NO" id="0Iv-td-ACj">
|
||||
<rect key="frame" x="20" y="67" width="329" height="144"/>
|
||||
<rows>
|
||||
<gridRow id="Ljm-xA-9NW"/>
|
||||
<gridRow id="Dv9-ND-6rX"/>
|
||||
<gridRow id="mNb-JP-3YX"/>
|
||||
<gridRow id="vQK-bD-mNH"/>
|
||||
<gridRow id="DIe-Hz-bd0"/>
|
||||
<gridRow id="TQt-iq-lMT"/>
|
||||
</rows>
|
||||
<columns>
|
||||
<gridColumn xPlacement="trailing" id="uaf-ph-2zN"/>
|
||||
<gridColumn xPlacement="fill" id="7oF-Xq-5de"/>
|
||||
<gridColumn xPlacement="fill" id="clB-mU-Eba"/>
|
||||
</columns>
|
||||
<gridCells>
|
||||
<gridCell row="Ljm-xA-9NW" column="uaf-ph-2zN" id="1U3-Im-v9n"/>
|
||||
<gridCell row="Ljm-xA-9NW" column="7oF-Xq-5de" id="2bp-dG-V6t">
|
||||
<textField key="contentView" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="12">
|
||||
<rect key="frame" x="90" y="130" width="204" height="14"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="PASSWORD_ERROR" id="14">
|
||||
<font key="font" metaFont="smallSystem"/>
|
||||
<color key="textColor" red="1" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
</gridCell>
|
||||
<gridCell row="Ljm-xA-9NW" column="clB-mU-Eba" id="blk-az-oHS"/>
|
||||
<gridCell row="Dv9-ND-6rX" column="uaf-ph-2zN" id="JUU-XQ-60P">
|
||||
<button key="contentView" horizontalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="yKc-I9-uzv">
|
||||
<rect key="frame" x="4" y="102" width="84" height="18"/>
|
||||
<buttonCell key="cell" type="check" title="Password:" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="OQz-DA-SoY">
|
||||
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
</button>
|
||||
</gridCell>
|
||||
<gridCell row="Dv9-ND-6rX" column="7oF-Xq-5de" id="cw2-er-epO">
|
||||
<secureTextField key="contentView" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="9" customClass="HNHUISecureTextField">
|
||||
<rect key="frame" x="92" y="104" width="200" height="20"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" relation="greaterThanOrEqual" constant="200" id="Gin-yR-DMk"/>
|
||||
</constraints>
|
||||
<secureTextFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" borderStyle="bezel" placeholderString="Enter Password" drawsBackground="YES" usesSingleLineMode="YES" id="18">
|
||||
<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>
|
||||
</secureTextField>
|
||||
</gridCell>
|
||||
<gridCell row="Dv9-ND-6rX" column="clB-mU-Eba" id="ykQ-xV-MfJ"/>
|
||||
<gridCell row="mNb-JP-3YX" column="uaf-ph-2zN" id="DTm-fw-duK">
|
||||
<textField key="contentView" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="10">
|
||||
<rect key="frame" x="37" y="76" width="51" height="16"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Repeat:" id="16">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
</gridCell>
|
||||
<gridCell row="mNb-JP-3YX" column="7oF-Xq-5de" id="OBv-b8-DJs">
|
||||
<secureTextField key="contentView" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="11" customClass="HNHUISecureTextField">
|
||||
<rect key="frame" x="92" y="76" width="200" height="20"/>
|
||||
<secureTextFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" borderStyle="bezel" placeholderString="Repeat Password" drawsBackground="YES" usesSingleLineMode="YES" id="15">
|
||||
<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>
|
||||
</secureTextField>
|
||||
</gridCell>
|
||||
<gridCell row="mNb-JP-3YX" column="clB-mU-Eba" id="erv-Ur-nvi">
|
||||
<button key="contentView" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="7">
|
||||
<rect key="frame" x="298" y="75" width="31" height="23"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="31" id="59"/>
|
||||
</constraints>
|
||||
<buttonCell key="cell" type="roundTextured" bezelStyle="texturedRounded" image="NSQuickLookTemplate" imagePosition="only" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="20">
|
||||
<behavior key="behavior" pushIn="YES" changeContents="YES" lightByContents="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
</button>
|
||||
</gridCell>
|
||||
<gridCell row="vQK-bD-mNH" column="uaf-ph-2zN" id="5U0-j9-rrv"/>
|
||||
<gridCell row="vQK-bD-mNH" column="7oF-Xq-5de" id="8JE-Wh-Sad">
|
||||
<textField key="contentView" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="ibK-Px-Fvt">
|
||||
<rect key="frame" x="90" y="56" width="204" height="14"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="KEY_ERROR" id="EOD-dE-TFa">
|
||||
<font key="font" metaFont="smallSystem"/>
|
||||
<color key="textColor" red="1" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
</gridCell>
|
||||
<gridCell row="vQK-bD-mNH" column="clB-mU-Eba" id="fyu-1E-DpO"/>
|
||||
<gridCell row="DIe-Hz-bd0" column="uaf-ph-2zN" id="Pjk-hs-Pb5">
|
||||
<textField key="contentView" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="5">
|
||||
<rect key="frame" x="39" y="28" width="49" height="16"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Keyfile:" id="22">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
</gridCell>
|
||||
<gridCell row="DIe-Hz-bd0" column="7oF-Xq-5de" id="o9J-f7-adq">
|
||||
<pathControl key="contentView" verticalHuggingPriority="750" allowsExpansionToolTips="YES" translatesAutoresizingMaskIntoConstraints="NO" id="4" customClass="MPPathControl">
|
||||
<rect key="frame" x="89" y="24" width="206" height="25"/>
|
||||
<pathCell key="cell" selectable="YES" editable="YES" alignment="left" pathStyle="popUp" id="23" customClass="MPPathCell">
|
||||
<font key="font" metaFont="system"/>
|
||||
</pathCell>
|
||||
</pathControl>
|
||||
</gridCell>
|
||||
<gridCell row="DIe-Hz-bd0" column="clB-mU-Eba" id="miK-hQ-pkN">
|
||||
<button key="contentView" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="8">
|
||||
<rect key="frame" x="298" y="27" width="31" height="23"/>
|
||||
<buttonCell key="cell" type="roundTextured" bezelStyle="texturedRounded" image="NSStopProgressTemplate" imagePosition="only" alignment="center" state="on" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="19">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="clearKey:" target="-2" id="65"/>
|
||||
</connections>
|
||||
</button>
|
||||
</gridCell>
|
||||
<gridCell row="TQt-iq-lMT" column="uaf-ph-2zN" id="nAI-ge-Vjb"/>
|
||||
<gridCell row="TQt-iq-lMT" column="7oF-Xq-5de" id="dT5-pB-M7d">
|
||||
<button key="contentView" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="6">
|
||||
<rect key="frame" x="92" y="-1" width="200" height="23"/>
|
||||
<buttonCell key="cell" type="roundTextured" title="Generate Keyfile" bezelStyle="texturedRounded" alignment="center" state="on" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="21">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="generateKey:" target="-2" id="66"/>
|
||||
</connections>
|
||||
</button>
|
||||
</gridCell>
|
||||
<gridCell row="TQt-iq-lMT" column="clB-mU-Eba" id="zle-AC-ZGd"/>
|
||||
</gridCells>
|
||||
</gridView>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="9" firstAttribute="top" secondItem="12" secondAttribute="bottom" constant="8" symbolic="YES" id="26"/>
|
||||
<constraint firstItem="4" firstAttribute="leading" secondItem="5" secondAttribute="trailing" constant="8" symbolic="YES" id="27"/>
|
||||
<constraint firstItem="10" firstAttribute="baseline" secondItem="11" secondAttribute="baseline" id="29"/>
|
||||
<constraint firstItem="7" firstAttribute="leading" secondItem="9" secondAttribute="trailing" constant="8" symbolic="YES" id="30"/>
|
||||
<constraint firstItem="4" firstAttribute="top" secondItem="11" secondAttribute="bottom" constant="8" symbolic="YES" id="35"/>
|
||||
<constraint firstItem="7" firstAttribute="top" secondItem="9" secondAttribute="top" id="36"/>
|
||||
<constraint firstItem="11" firstAttribute="leading" secondItem="10" secondAttribute="trailing" constant="8" symbolic="YES" id="37"/>
|
||||
<constraint firstItem="6" firstAttribute="top" secondItem="4" secondAttribute="bottom" constant="8" symbolic="YES" id="39"/>
|
||||
<constraint firstItem="12" firstAttribute="centerX" secondItem="9" secondAttribute="centerX" id="40"/>
|
||||
<constraint firstItem="8" firstAttribute="centerY" secondItem="4" secondAttribute="centerY" id="41"/>
|
||||
<constraint firstItem="4" firstAttribute="bottom" secondItem="5" secondAttribute="bottom" id="43"/>
|
||||
<constraint firstItem="12" firstAttribute="top" secondItem="2" secondAttribute="top" constant="20" symbolic="YES" id="53"/>
|
||||
<constraint firstAttribute="trailing" secondItem="8" secondAttribute="trailing" constant="20" symbolic="YES" id="56"/>
|
||||
<constraint firstAttribute="trailing" secondItem="7" secondAttribute="trailing" constant="20" symbolic="YES" id="57"/>
|
||||
<constraint firstAttribute="trailing" secondItem="68" secondAttribute="trailing" constant="20" symbolic="YES" id="71"/>
|
||||
<constraint firstItem="68" firstAttribute="leading" secondItem="72" secondAttribute="trailing" constant="12" symbolic="YES" id="75"/>
|
||||
<constraint firstItem="72" firstAttribute="top" secondItem="6" secondAttribute="bottom" constant="20" symbolic="YES" id="76"/>
|
||||
<constraint firstAttribute="bottom" secondItem="72" secondAttribute="bottom" constant="20" symbolic="YES" id="77"/>
|
||||
<constraint firstAttribute="bottom" secondItem="68" secondAttribute="bottom" constant="20" symbolic="YES" id="78"/>
|
||||
<constraint firstItem="5" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="2" secondAttribute="leading" constant="20" symbolic="YES" id="4Yq-mp-X3O"/>
|
||||
<constraint firstItem="4" firstAttribute="width" secondItem="11" secondAttribute="width" id="55p-Rc-8jw"/>
|
||||
<constraint firstItem="0Iv-td-ACj" firstAttribute="leading" secondItem="2" secondAttribute="leading" constant="20" symbolic="YES" id="4Gf-qW-X3R"/>
|
||||
<constraint firstItem="72" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="2" secondAttribute="leading" constant="20" symbolic="YES" id="5JM-Ve-z5Y"/>
|
||||
<constraint firstItem="8" firstAttribute="leading" secondItem="4" secondAttribute="trailing" constant="8" id="7GY-2X-nJn"/>
|
||||
<constraint firstItem="4" firstAttribute="leading" secondItem="5" secondAttribute="trailing" constant="8" id="7eR-m5-mhQ"/>
|
||||
<constraint firstItem="9" firstAttribute="baseline" secondItem="yKc-I9-uzv" secondAttribute="baseline" id="DrZ-BA-xPv"/>
|
||||
<constraint firstItem="7" firstAttribute="leading" secondItem="9" secondAttribute="trailing" constant="8" id="IqJ-u6-6jk"/>
|
||||
<constraint firstItem="yKc-I9-uzv" firstAttribute="leading" secondItem="2" secondAttribute="leading" constant="20" symbolic="YES" id="OdM-OO-kNS"/>
|
||||
<constraint firstItem="7" firstAttribute="leading" secondItem="9" secondAttribute="trailing" constant="8" symbolic="YES" id="PnG-bb-nYQ"/>
|
||||
<constraint firstItem="11" firstAttribute="top" secondItem="9" secondAttribute="bottom" constant="10" symbolic="YES" id="Qe9-z3-Wa6"/>
|
||||
<constraint firstItem="yKc-I9-uzv" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="2" secondAttribute="leading" constant="20" symbolic="YES" id="R8d-VG-2we"/>
|
||||
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="6" secondAttribute="trailing" constant="20" symbolic="YES" id="TUn-PZ-fb5"/>
|
||||
<constraint firstItem="10" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="2" secondAttribute="leading" constant="20" symbolic="YES" id="UHJ-Fx-Kkf"/>
|
||||
<constraint firstItem="6" firstAttribute="width" secondItem="11" secondAttribute="width" id="V37-mo-ah1"/>
|
||||
<constraint firstItem="9" firstAttribute="leading" secondItem="yKc-I9-uzv" secondAttribute="trailing" constant="8" symbolic="YES" id="f8B-Dm-rGD"/>
|
||||
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="12" secondAttribute="trailing" constant="20" symbolic="YES" id="hmt-qe-o3D"/>
|
||||
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="11" secondAttribute="trailing" constant="20" symbolic="YES" id="nDO-Oh-tGz"/>
|
||||
<constraint firstItem="6" firstAttribute="leading" secondItem="4" secondAttribute="leading" id="tie-Hu-X1C"/>
|
||||
<constraint firstItem="12" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="2" secondAttribute="leading" constant="20" symbolic="YES" id="ukY-Gg-KY2"/>
|
||||
<constraint firstItem="11" firstAttribute="width" secondItem="9" secondAttribute="width" id="wEk-Sj-XCb"/>
|
||||
<constraint firstItem="6" firstAttribute="leading" secondItem="11" secondAttribute="leading" id="xV3-et-ECG"/>
|
||||
<constraint firstItem="6" firstAttribute="leading" secondItem="9" secondAttribute="leading" id="zeJ-6i-fY3"/>
|
||||
<constraint firstItem="0Iv-td-ACj" firstAttribute="top" secondItem="2" secondAttribute="top" constant="20" symbolic="YES" id="FVY-mT-b2G"/>
|
||||
<constraint firstAttribute="trailing" secondItem="0Iv-td-ACj" secondAttribute="trailing" constant="20" symbolic="YES" id="q2z-sU-YCn"/>
|
||||
<constraint firstItem="68" firstAttribute="top" relation="greaterThanOrEqual" secondItem="0Iv-td-ACj" secondAttribute="bottom" constant="20" symbolic="YES" id="s84-KY-RXX"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<point key="canvasLocation" x="-8" y="-14"/>
|
||||
<point key="canvasLocation" x="73" y="-137"/>
|
||||
</window>
|
||||
</objects>
|
||||
<resources>
|
||||
|
|
|
@ -39,13 +39,15 @@
|
|||
|
||||
@interface MPPasswordEditWindowController : HNHUISheetWindowController <NSTextFieldDelegate>
|
||||
|
||||
@property (weak) IBOutlet HNHUISecureTextField *passwordTextField;
|
||||
@property (weak) IBOutlet HNHUISecureTextField *passwordRepeatTextField;
|
||||
@property (weak) IBOutlet NSPathControl *keyfilePathControl;
|
||||
@property (weak) IBOutlet NSButton *togglePasswordButton;
|
||||
@property (weak) IBOutlet NSTextField *errorTextField;
|
||||
@property (weak) IBOutlet NSButton *changePasswordButton;
|
||||
@property (weak) IBOutlet NSButton *hasPasswordSwitchButton;
|
||||
@property (strong) IBOutlet HNHUISecureTextField *passwordTextField;
|
||||
@property (strong) IBOutlet HNHUISecureTextField *passwordRepeatTextField;
|
||||
@property (strong) IBOutlet NSPathControl *keyfilePathControl;
|
||||
@property (strong) IBOutlet NSButton *togglePasswordButton;
|
||||
@property (strong) IBOutlet NSTextField *passwordErrorTextField;
|
||||
@property (strong) IBOutlet NSTextField *keyErrorTextField;
|
||||
@property (strong) IBOutlet NSButton *changePasswordButton;
|
||||
@property (strong) IBOutlet NSButton *hasPasswordSwitchButton;
|
||||
@property (strong) IBOutlet NSGridView *gridView;
|
||||
|
||||
- (IBAction)clearKey:(id)sender;
|
||||
- (IBAction)generateKey:(id)sender;
|
||||
|
|
|
@ -22,17 +22,34 @@
|
|||
|
||||
#import "MPPasswordEditWindowController.h"
|
||||
#import "MPDocument.h"
|
||||
#import "MPPathControl.h"
|
||||
|
||||
#import "HNHUi/HNHUi.h"
|
||||
|
||||
#import "KeePassKit/KeePassKit.h"
|
||||
|
||||
typedef NS_ENUM(NSUInteger, MPPasswordEditPasswordError) {
|
||||
MPPasswordEditPasswordErrorNone,
|
||||
MPPasswordEditPasswordErrorNoPassword,
|
||||
MPPasswordEditPasswordErrorRepeatMissmatch
|
||||
};
|
||||
|
||||
typedef NS_ENUM(NSUInteger, MPPasswordEditKeyError) {
|
||||
MPPasswordEditKeyErrorNone,
|
||||
MPPasswordEditKeyErrorNoKey,
|
||||
MPPasswordEditKeyErrorNotReachable,
|
||||
MPPasswordEditKeyErrorIsCurrentDatabase,
|
||||
MPPasswordEditKeyErrorIsKeePassDatabase,
|
||||
};
|
||||
|
||||
|
||||
@interface MPPasswordEditWindowController ()
|
||||
|
||||
@property (nonatomic, assign) BOOL showPassword;
|
||||
@property (nonatomic, assign) BOOL enablePassword;
|
||||
@property (nonatomic, assign) BOOL hasValidPasswordOrKey;
|
||||
@property (nonatomic, weak) NSURL *keyURL;
|
||||
@property (weak) NSGridRow *passwordErrorGridRow;
|
||||
@property (weak) NSGridRow *keyErrorGridRow;
|
||||
|
||||
@end
|
||||
|
||||
|
@ -53,10 +70,14 @@
|
|||
|
||||
- (void)windowDidLoad {
|
||||
[super windowDidLoad];
|
||||
[NSNotificationCenter.defaultCenter addObserver:self selector:@selector(_didChangeKeyURL:) name:MPPathControlDidSetURLNotification object:self.keyfilePathControl];
|
||||
[self.togglePasswordButton bind:NSValueBinding toObject:self withKeyPath:NSStringFromSelector(@selector(showPassword)) options:nil];
|
||||
self.window.defaultButtonCell = self.changePasswordButton.cell;
|
||||
MPDocument *document = self.document;
|
||||
self.enablePassword = [document.compositeKey hasKeyOfClass:KPKPasswordKey.class];
|
||||
|
||||
self.passwordErrorGridRow = [self.gridView cellForView:self.passwordErrorTextField].row;
|
||||
self.keyErrorGridRow = [self.gridView cellForView:self.keyErrorTextField].row;
|
||||
}
|
||||
|
||||
- (void)updateView {
|
||||
|
@ -77,9 +98,8 @@
|
|||
[self.togglePasswordButton bind:NSEnabledBinding toObject:self withKeyPath:enablePasswordKeyPath options:nil];
|
||||
[self.passwordRepeatTextField bind:NSEnabledBinding toObject:self withKeyPath:showPasswordKeyPath options:negateOption];
|
||||
[self.passwordRepeatTextField bind:NSEnabledBinding toObject:self withKeyPath:enablePasswordKeyPath options:nil];
|
||||
[self.errorTextField bind:NSHiddenBinding toObject:self withKeyPath:hasValidPasswordOrKeyKeyPath options:nil];
|
||||
|
||||
[self.changePasswordButton bind:NSEnabledBinding toObject:self withKeyPath:hasValidPasswordOrKeyKeyPath options:nil];
|
||||
[self.keyfilePathControl bind:NSValueBinding toObject:self withKeyPath:NSStringFromSelector(@selector(keyURL)) options:nil];
|
||||
|
||||
self.passwordRepeatTextField.delegate = self;
|
||||
self.passwordTextField.delegate = self;
|
||||
|
@ -98,10 +118,7 @@
|
|||
[self _verifyPasswordAndKey];
|
||||
}
|
||||
}
|
||||
- (void)setKeyURL:(NSURL *)keyURL {
|
||||
_keyURL = keyURL;
|
||||
[self _verifyPasswordAndKey];
|
||||
}
|
||||
|
||||
- (void)setEnablePassword:(BOOL)enablePassword {
|
||||
if(_enablePassword != enablePassword) {
|
||||
_enablePassword = enablePassword;
|
||||
|
@ -110,6 +127,7 @@
|
|||
NSString *repeatPlaceHolder = _enablePassword ? NSLocalizedString(@"PASSWORD_INPUT_REPEAT_PASSWORD", "Placeholder for the repeat password field to aks for the repeated password") : NSLocalizedString(@"PASSWORD_INPUT_NO_PASSWORD", "Placeholder for the repeat password input if passwords are disabled");
|
||||
self.passwordTextField.placeholderString = passwordPlaceHolder;
|
||||
self.passwordRepeatTextField.placeholderString = repeatPlaceHolder;
|
||||
[self _verifyPasswordAndKey];
|
||||
}
|
||||
|
||||
#pragma mark Actions
|
||||
|
@ -126,7 +144,7 @@
|
|||
}
|
||||
|
||||
- (IBAction)clearKey:(id)sender {
|
||||
self.keyURL = nil;
|
||||
self.keyfilePathControl.URL = nil;
|
||||
}
|
||||
|
||||
- (IBAction)generateKey:(id)sender {
|
||||
|
@ -143,7 +161,7 @@
|
|||
NSError *error;
|
||||
BOOL saveOk = [data writeToURL:keyURL options:NSDataWritingAtomic error:&error];
|
||||
if(saveOk) {
|
||||
self.keyURL = keyURL;
|
||||
self.keyfilePathControl.URL = keyURL;
|
||||
}
|
||||
}
|
||||
}];
|
||||
|
@ -155,43 +173,125 @@
|
|||
[self _verifyPasswordAndKey];
|
||||
}
|
||||
|
||||
- (void)_verifyPasswordAndKey {
|
||||
NSString *password = self.passwordTextField.stringValue;
|
||||
NSString *repeat = self.passwordRepeatTextField.stringValue;
|
||||
BOOL hasKey = (self.keyURL != nil);
|
||||
BOOL keyOk = YES;
|
||||
if(hasKey) {
|
||||
keyOk = [self.keyURL checkResourceIsReachableAndReturnError:nil];
|
||||
}
|
||||
BOOL hasPassword = password.kpk_isNotEmpty;
|
||||
if(!self.showPassword) {
|
||||
hasPassword |= repeat.kpk_isNotEmpty;
|
||||
}
|
||||
BOOL passwordOk = YES;
|
||||
if(hasPassword ) {
|
||||
passwordOk = [password isEqualToString:repeat] || self.showPassword;
|
||||
}
|
||||
BOOL hasPasswordOrKey = (hasKey || hasPassword);
|
||||
keyOk = hasKey ? keyOk : YES;
|
||||
passwordOk = hasPassword ? passwordOk : YES;
|
||||
self.hasValidPasswordOrKey = hasPasswordOrKey && passwordOk && keyOk;
|
||||
|
||||
if(!hasPasswordOrKey) {
|
||||
self.errorTextField.textColor = NSColor.controlTextColor;
|
||||
self.errorTextField.stringValue = NSLocalizedString(@"WARNING_NO_PASSWORD_OR_KEYFILE", "No Key or Password");
|
||||
return; // all done
|
||||
}
|
||||
self.errorTextField.textColor = NSColor.redColor;
|
||||
if(!passwordOk && !keyOk ) {
|
||||
self.errorTextField.stringValue = NSLocalizedString(@"ERROR_PASSWORD_MISSMATCH_INVALID_KEYFILE", "Passwords do not match, keyfile is invalid");
|
||||
}
|
||||
else if(!passwordOk) {
|
||||
self.errorTextField.stringValue = NSLocalizedString(@"ERROR_PASSWORD_MISSMATCH", "Passwords do not match");
|
||||
}
|
||||
else {
|
||||
self.errorTextField.stringValue = NSLocalizedString(@"ERROR_INVALID_KEYFILE", "Keyfile not valid");
|
||||
#pragma mark Notifications
|
||||
- (void)_didChangeKeyURL:(NSNotification *)notification {
|
||||
if(notification.object != self.keyfilePathControl) {
|
||||
return;
|
||||
}
|
||||
[self _verifyPasswordAndKey];
|
||||
}
|
||||
|
||||
|
||||
#pragma mark UI update
|
||||
- (void)_verifyPasswordAndKey {
|
||||
self.passwordErrorGridRow.hidden = YES;
|
||||
self.keyErrorGridRow.hidden = YES;
|
||||
|
||||
self.keyErrorTextField.stringValue = @"";
|
||||
self.passwordErrorTextField.stringValue = @"";
|
||||
|
||||
MPPasswordEditKeyError keyError = [self _verifyKey];
|
||||
MPPasswordEditPasswordError passwordError = [self _verifyPassword];
|
||||
|
||||
self.keyErrorTextField.textColor = NSColor.controlColor;
|
||||
self.passwordErrorTextField.textColor = NSColor.controlColor;
|
||||
|
||||
if(keyError == MPPasswordEditKeyErrorNoKey && passwordError == MPPasswordEditPasswordErrorNoPassword) {
|
||||
|
||||
self.passwordErrorTextField.stringValue = NSLocalizedString(@"WARNING_NO_PASSWORD", "No Key or Password");
|
||||
self.passwordErrorGridRow.hidden = NO;
|
||||
|
||||
self.keyErrorTextField.stringValue = NSLocalizedString(@"WARNING_NO_KEYFILE", "No key file is set");
|
||||
self.keyErrorGridRow.hidden = NO;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
switch(keyError) {
|
||||
case MPPasswordEditKeyErrorNotReachable:
|
||||
self.keyErrorTextField.stringValue = NSLocalizedString(@"ERROR_KEYFILE_NOT_FOUND", "Keyfile was not found");
|
||||
self.keyErrorGridRow.hidden = NO;
|
||||
self.keyErrorTextField.textColor = NSColor.redColor;
|
||||
break;
|
||||
case MPPasswordEditKeyErrorIsCurrentDatabase:
|
||||
self.keyErrorTextField.stringValue = NSLocalizedString(@"ERROR_KEYFILE_IS_CURRENT_DATABASE", "The new key file is the current database.");
|
||||
self.keyErrorGridRow.hidden = NO;
|
||||
self.keyErrorTextField.textColor = NSColor.redColor;
|
||||
break;
|
||||
case MPPasswordEditKeyErrorIsKeePassDatabase:
|
||||
self.keyErrorTextField.stringValue = NSLocalizedString(@"ERROR_KEYFILE_IS_KEEPASS_FILE", "Keyfile is a KeePass database.");
|
||||
self.keyErrorGridRow.hidden = NO;
|
||||
self.keyErrorTextField.textColor = NSColor.redColor;
|
||||
break;
|
||||
case MPPasswordEditKeyErrorNoKey:
|
||||
if(!self.enablePassword) {
|
||||
self.keyErrorTextField.stringValue = NSLocalizedString(@"WARNING_NO_KEYFILE", "No key file is set");
|
||||
self.keyErrorGridRow.hidden = NO;
|
||||
}
|
||||
case MPPasswordEditKeyErrorNone:
|
||||
break;
|
||||
}
|
||||
|
||||
switch(passwordError) {
|
||||
case MPPasswordEditPasswordErrorRepeatMissmatch:
|
||||
self.passwordErrorTextField.stringValue = NSLocalizedString(@"ERROR_PASSWORD_MISSMATCH", "Passwords do not match");
|
||||
self.passwordErrorGridRow.hidden = NO;
|
||||
break;
|
||||
case MPPasswordEditPasswordErrorNone:
|
||||
case MPPasswordEditPasswordErrorNoPassword:
|
||||
break;
|
||||
}
|
||||
|
||||
self.hasValidPasswordOrKey = (passwordError == MPPasswordEditPasswordErrorNone && keyError == MPPasswordEditKeyErrorNone);
|
||||
}
|
||||
|
||||
- (MPPasswordEditKeyError)_verifyKey {
|
||||
NSURL *keyURL = self.keyfilePathControl.URL;
|
||||
if(!keyURL) {
|
||||
return MPPasswordEditKeyErrorNoKey;
|
||||
}
|
||||
|
||||
if(![keyURL checkResourceIsReachableAndReturnError:nil]) {
|
||||
return MPPasswordEditKeyErrorNotReachable;
|
||||
}
|
||||
/* TODO: exten KPKFileKey to do database checks internally */
|
||||
NSDocument *document = (NSDocument *)self.document;
|
||||
NSData *keyFileData = [NSData dataWithContentsOfURL:keyURL];
|
||||
KPKFileVersion keyFileVersion = [KPKFormat.sharedFormat fileVersionForData:keyFileData];
|
||||
if(keyFileVersion.format != KPKDatabaseFormatUnknown) {
|
||||
if([document.fileURL isEqual:keyURL]) {
|
||||
return MPPasswordEditKeyErrorIsCurrentDatabase;
|
||||
}
|
||||
return MPPasswordEditKeyErrorIsKeePassDatabase;
|
||||
}
|
||||
/* FIXME: check xml key */
|
||||
return MPPasswordEditKeyErrorNone;
|
||||
}
|
||||
|
||||
- (MPPasswordEditPasswordError)_verifyPassword {
|
||||
|
||||
if(!self.enablePassword) {
|
||||
return MPPasswordEditPasswordErrorNone;
|
||||
}
|
||||
|
||||
NSString *password = self.passwordTextField.stringValue;
|
||||
NSString *repeat = self.passwordRepeatTextField.stringValue;
|
||||
|
||||
if(self.showPassword) {
|
||||
if(password.kpk_isNotEmpty) {
|
||||
return MPPasswordEditPasswordErrorNone;
|
||||
}
|
||||
return MPPasswordEditPasswordErrorNoPassword;
|
||||
}
|
||||
|
||||
if(!password.kpk_isNotEmpty && !repeat.kpk_isNotEmpty) {
|
||||
return MPPasswordEditPasswordErrorNoPassword;
|
||||
}
|
||||
|
||||
if(![password isEqualToString:repeat]) {
|
||||
return MPPasswordEditPasswordErrorRepeatMissmatch;
|
||||
}
|
||||
return MPPasswordEditPasswordErrorNone;
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
Loading…
Reference in New Issue