77 Commits

Author SHA1 Message Date
michael starke
9ced3fce0b Changed password/keyfile requesting. No password/keyfile is enforced until you want to save the file. 2013-07-22 00:02:14 +02:00
michael starke
acc800c9e6 Fixed #59 Password length input is nu read only. Not a nice solution but for now working
Attachments for Kdb and Kdbx Databases are now supported. Save, Add, Delete
2013-07-21 23:23:45 +02:00
michael starke
45cb4a2652 Updated Credits 2013-07-21 14:41:37 +02:00
michael starke
1f94a626bb Create new on activate disabled. There's a annoying bug in there :( 2013-07-21 14:22:44 +02:00
michael starke
a6afe0bcf4 Fixed #29 Application now stores the last open database by itself. If window restoration in OS X is disabled, the app also reopens the last db. 2013-07-21 14:14:05 +02:00
michael starke
1fd89bfab6 Updated submodules 2013-07-21 04:29:22 +02:00
michael starke
db0640840f Updated Submodules 2013-07-21 01:01:23 +02:00
michael starke
fb735d9e41 Reduced PDF file sizes 2013-07-21 00:54:19 +02:00
michael starke
862cbe839e Updated Submodule 2013-07-20 20:00:16 +02:00
michael starke
cb5a71dfee Updated submodule 2013-07-20 19:46:31 +02:00
michael starke
30697648b9 Updated localization
Fixed an issue that automatically set the first group to be the trashcan
2013-07-20 17:04:13 +02:00
michael starke
e5e8d01dff Removed unused Code 2013-07-20 16:42:35 +02:00
michael starke
030dbd5be7 Fixed #46 Binaries get now deleted when entries are delete on trans cleaning
MenuEntries are validated and disabled to fix #58. Model still doesn't do any testing
2013-07-20 16:31:20 +02:00
michael starke
e306b2b3f2 Updated submodule 2013-07-20 12:26:53 +02:00
michael starke
0fe99cda97 Updated Submodules 2013-07-20 12:23:19 +02:00
michael starke
c207b2b24a Experiments with token filed in Inspector 2013-07-20 03:23:18 +02:00
michael starke
dc51c60c19 Attachments on Kdb1 Entries are now supported. Saving not implemented. Attach/detach works. 2013-07-19 23:30:45 +02:00
michael starke
86d983f776 Subbed Kdb3 Entry attachment handling. 2013-07-19 22:45:04 +02:00
michael starke
efa727eaba Settings now work with KDB1 Files and do not trap the Application in the modal dialog
Added user base settings to hide/show passwords at KDB1 field. The settings are stored but not considered ;)
2013-07-19 22:25:40 +02:00
michael starke
5e6d2bed3d Removed commented code 2013-07-19 18:42:18 +02:00
michael starke
5e6e31fb47 Fixed Issue with non-initalized password repeat filed on first load of the databaseSettings window 2013-07-19 18:26:42 +02:00
michael starke
8d34f77a1f Bumped Version
Updated Credits
2013-07-19 03:21:47 +02:00
michael starke
859fe5ede8 Default fields are now respected too in validation 2013-07-19 03:14:41 +02:00
michael starke
fef291df88 Added custom string field validation. Still needs testing for default keys 2013-07-19 03:06:29 +02:00
michael starke
c1b47bdb77 Enhanced password input to check and verify
Added repeat password input in settings
New databases without password request on (it's not changed on file until the saved)
2013-07-19 01:39:52 +02:00
michael starke
0e102d3f0f Saving last state of Inspector (last document wins) 2013-07-18 21:23:32 +02:00
michael starke
d4c7d49d6f Fixed issue with window restoration 2013-07-18 21:16:56 +02:00
michael starke
0144e3c21f Bumped Build number 2013-07-18 04:36:45 +02:00
michael starke
dd5eef4e60 Fixed missing delete button on custom fields 2013-07-18 04:29:17 +02:00
michael starke
bfc610a25e Added "reopen last database" featuer
Removed standard open new db on activate
Enabled windows state restoration
Enabled table column state restoration
Menu items should be validated better
2013-07-18 04:21:23 +02:00
michael starke
0986271199 Updated Submodules
Extracted TabelViewDelegates for Attachments and Custom Fields
2013-07-18 02:55:09 +02:00
michael starke
63c3c83eb8 Updated Screenshots
Fixed some localization errors
2013-07-17 01:34:57 +02:00
michael starke
0a42e55f0e Added custom-field copy to the context menu on entries. It's not fully functional as it's not correctly using the click but always the selected entry! 2013-07-17 01:02:02 +02:00
michael starke
442d16e297 Updated submodules 2013-07-17 00:03:24 +02:00
michael starke
6f92b70039 Updated Submodules 2013-07-16 02:07:11 +02:00
michael starke
8496140f9c XML Export now uses pretty print option 2013-07-16 01:07:11 +02:00
michael starke
d814556376 Merge branch 'master' of https://github.com/mstarke/MacPass 2013-07-15 22:10:32 +02:00
michael starke
c0051f852e Added export to XML action for Version2 Databases
Small updates to Database Settings window
2013-07-15 22:10:27 +02:00
Michael Starke
726f8846b8 Merge branch 'master' of https://github.com/mstarke/MacPass 2013-07-15 17:37:43 +02:00
Michael Starke
c50da8f0ac Changed file encodings 2013-07-15 17:37:18 +02:00
michael starke
f4c67ea603 Updated Submodules 2013-07-15 10:36:22 +02:00
Michael Starke
99163ab84c Updated submodules 2013-07-14 22:54:14 +02:00
michael starke
3ae08796a1 Updated KeePassKit 2013-07-14 15:03:22 +02:00
michael starke
665dad02ac Updated KeePassKit 2013-07-14 12:05:29 +02:00
michael starke
2630dc8778 Added shared Schemes to transfer Build Incremente script 2013-07-14 12:04:54 +02:00
michael starke
9836d3c194 Updated KeePassKit 2013-07-14 01:51:09 +02:00
michael starke
55d0eddbf8 Merge branch 'master' of https://github.com/mstarke/MacPass
Conflicts:
	MacPass/MacPass-Info.plist
2013-07-14 01:50:31 +02:00
michael starke
03c5f78960 Updated build 2013-07-14 01:49:17 +02:00
Michael Starke
1d688293af Updated KeePassKit 2013-07-13 23:02:30 +02:00
michael starke
6b14f84afb Experimenting with edit mode for the Inspector 2013-07-13 18:45:32 +02:00
michael starke
a31e287ec8 Fixed Tests
Fixed error that lead to trying to create and array with nil object
2013-07-13 00:00:51 +02:00
michael starke
860d6bb21c Added KeePassKit to start rewrite of MiniKeePassLib 2013-07-12 01:07:06 +02:00
michael starke
3d14904640 Key/Password set/reset test 2013-07-11 01:51:20 +02:00
michael starke
3d4c183bdb Updated tests 2013-07-11 00:25:20 +02:00
michael starke
00eec52781 Merge branch 'master' of https://github.com/mstarke/MacPass 2013-07-11 00:23:43 +02:00
michael starke
ab0199e3dd Setup for UnitTests 2013-07-11 00:23:30 +02:00
Michael Starke
910c89288f Added IRC channel information 2013-07-10 23:17:59 +02:00
Michael Starke
eaa072f298 Update README.md 2013-07-10 19:34:10 +02:00
Michael Starke
d0b6927a5e Update README.md 2013-07-10 19:33:31 +02:00
Michael Starke
b7d15f7e49 Restructured and updated Readme. Added more alternatives. 2013-07-10 10:40:26 +02:00
michael starke
515190a74e Added humanized Date formatting (simple)
Fixed errors that would occur if undo was mixed with emptying the trash
Updated localizations
Added localized descriptions
Fixed #31 Database name is displayed, if none is given fallback is used
2013-07-10 03:37:31 +02:00
michael starke
75c9aa6873 Temporarily disabled drag and drop until it's working properly
Fixed issues with clearing the trash
2013-07-10 01:20:08 +02:00
michael starke
c34d840e35 Fixed wrong names for redo-actions 2013-07-09 23:50:38 +02:00
michael starke
fb0887ebf0 Refactored Undo/Redo 2013-07-09 21:58:28 +02:00
michael starke
6ba8b1445d Updated to new HNHRoundedSecureTextField 2013-07-09 03:04:55 +02:00
michael starke
79a8c05e95 Updated views to new Password input. 2013-07-09 02:41:22 +02:00
michael starke
a98720a00c experiments with password toggle input 2013-07-07 23:39:06 +02:00
michael starke
c674745103 Updated references 2013-07-07 22:09:21 +02:00
michael starke
d3cdc4d574 Added 4 more icons. Updated HNHUi 2013-07-07 14:04:43 +02:00
michael starke
dfb8c7936a Updated HNHUi 2013-07-06 12:13:38 +02:00
michael starke
02f54d2c35 Updated HNHUi 2013-07-06 12:11:01 +02:00
michael starke
1db5bd0e12 Bumped Version to 0.3.1 2013-07-06 04:22:08 +02:00
michael starke
cadfd3fdca Fixed issue that occurred in no reset on Database settings after cancle 2013-07-06 04:20:36 +02:00
michael starke
f55e78349e Reworked DatabaseSettings to be cancelable
Moved Password edit to Database settings
2013-07-06 04:18:10 +02:00
michael starke
005bab7380 Updated HNHUi 2013-07-06 04:16:56 +02:00
michael starke
f0e4def758 Added better save to disk icon 2013-07-06 01:05:45 +02:00
michael starke
58abad34a1 Updated HNHUi 2013-07-06 01:05:24 +02:00
122 changed files with 8252 additions and 3995 deletions

3
.gitmodules vendored
View File

@@ -10,3 +10,6 @@
[submodule "CocoaHTTPServer"]
path = CocoaHTTPServer
url = git://github.com/robbiehanson/CocoaHTTPServer.git
[submodule "KeePassKit"]
path = KeePassKit
url = https://mstarke@github.com/mstarke/KeePassKit

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 120 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 102 KiB

After

Width:  |  Height:  |  Size: 110 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 66 KiB

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 109 KiB

After

Width:  |  Height:  |  Size: 105 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 163 KiB

After

Width:  |  Height:  |  Size: 159 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB

2
HNHUi

Submodule HNHUi updated: 332586b554...c32f87da30

1
KeePassKit Submodule

Submodule KeePassKit added at 4e8693c89c

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,121 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0460"
version = "1.7">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "4C77E36115B84A240093A587"
BuildableName = "MacPass.app"
BlueprintName = "MacPass"
ReferencedContainer = "container:MacPass.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
buildConfiguration = "Debug">
<Testables>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "4C45FB19178E09ED0010007D"
BuildableName = "MacPassTests.octest"
BlueprintName = "MacPassTests"
ReferencedContainer = "container:MacPass.xcodeproj">
</BuildableReference>
</TestableReference>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "4C77E36115B84A240093A587"
BuildableName = "MacPass.app"
BlueprintName = "MacPass"
ReferencedContainer = "container:MacPass.xcodeproj">
</BuildableReference>
</MacroExpansion>
</TestAction>
<LaunchAction
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
buildConfiguration = "Debug"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
allowLocationSimulation = "YES">
<BuildableProductRunnable>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "4C77E36115B84A240093A587"
BuildableName = "MacPass.app"
BlueprintName = "MacPass"
ReferencedContainer = "container:MacPass.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<CommandLineArguments>
<CommandLineArgument
argument = "-NSConstraintBasedLayoutVisualizeMutuallyExclusiveConstraints YES"
isEnabled = "NO">
</CommandLineArgument>
</CommandLineArguments>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
buildConfiguration = "Release"
debugDocumentVersioning = "YES">
<BuildableProductRunnable>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "4C77E36115B84A240093A587"
BuildableName = "MacPass.app"
BlueprintName = "MacPass"
ReferencedContainer = "container:MacPass.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
<PreActions>
<ExecutionAction
ActionType = "Xcode.IDEStandardExecutionActionsCore.ExecutionActionType.ShellScriptAction">
<ActionContent
title = "Run Script"
scriptText = "PLIST_FILE=$PROJECT_DIR/$INFOPLIST_FILE&#10;VERSION=$(/usr/libexec/PlistBuddy -c &quot;Print CFBundleVersion&quot; $PLIST_FILE)&#10;VERSION=$(($VERSION + 1))&#10;/usr/libexec/PlistBuddy -c &quot;Set :CFBundleVersion $VERSION&quot; $PLIST_FILE"
shellToInvoke = "/bin/bash">
<EnvironmentBuildable>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "4C77E36115B84A240093A587"
BuildableName = "MacPass.app"
BlueprintName = "MacPass"
ReferencedContainer = "container:MacPass.xcodeproj">
</BuildableReference>
</EnvironmentBuildable>
</ActionContent>
</ExecutionAction>
</PreActions>
</ArchiveAction>
</Scheme>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -235,6 +235,15 @@
<reference key="NSOnImage" ref="35465992"/>
<reference key="NSMixedImage" ref="502551668"/>
</object>
<object class="NSMenuItem" id="919874146">
<reference key="NSMenu" ref="720053764"/>
<string key="NSTitle">Lock</string>
<string key="NSKeyEquiv">L</string>
<int key="NSKeyEquivModMask">262144</int>
<int key="NSMnemonicLoc">2147483647</int>
<reference key="NSOnImage" ref="35465992"/>
<reference key="NSMixedImage" ref="502551668"/>
</object>
<object class="NSMenuItem" id="776162233">
<reference key="NSMenu" ref="720053764"/>
<string key="NSTitle">Close</string>
@@ -253,6 +262,24 @@
<reference key="NSOnImage" ref="35465992"/>
<reference key="NSMixedImage" ref="502551668"/>
</object>
<object class="NSMenuItem" id="663106531">
<reference key="NSMenu" ref="720053764"/>
<string key="NSTitle">Save As…</string>
<string key="NSKeyEquiv">S</string>
<int key="NSKeyEquivModMask">1048576</int>
<int key="NSMnemonicLoc">2147483647</int>
<reference key="NSOnImage" ref="35465992"/>
<reference key="NSMixedImage" ref="502551668"/>
</object>
<object class="NSMenuItem" id="438377242">
<reference key="NSMenu" ref="720053764"/>
<string key="NSTitle">Export As XML…</string>
<string key="NSKeyEquiv">E</string>
<int key="NSKeyEquivModMask">1048576</int>
<int key="NSMnemonicLoc">2147483647</int>
<reference key="NSOnImage" ref="35465992"/>
<reference key="NSMixedImage" ref="502551668"/>
</object>
<object class="NSMenuItem" id="579971712">
<reference key="NSMenu" ref="720053764"/>
<string key="NSTitle">Revert to Saved</string>
@@ -274,7 +301,7 @@
</object>
<object class="NSMenuItem" id="544639599">
<reference key="NSMenu" ref="720053764"/>
<string key="NSTitle">Document Settings…</string>
<string key="NSTitle">Database Settings…</string>
<string key="NSKeyEquiv"/>
<int key="NSMnemonicLoc">2147483647</int>
<reference key="NSOnImage" ref="35465992"/>
@@ -282,7 +309,7 @@
</object>
<object class="NSMenuItem" id="915918141">
<reference key="NSMenu" ref="720053764"/>
<string key="NSTitle">Change Password…</string>
<string key="NSTitle">Change Master Password…</string>
<string key="NSKeyEquiv"/>
<int key="NSMnemonicLoc">2147483647</int>
<reference key="NSOnImage" ref="35465992"/>
@@ -788,11 +815,35 @@
</object>
<object class="IBConnectionRecord">
<object class="IBActionConnection" key="connection">
<string key="label">showDocumentSettings:</string>
<string key="label">showDatabaseSettings:</string>
<reference key="source" ref="1014"/>
<reference key="destination" ref="544639599"/>
</object>
<int key="connectionID">1233</int>
<int key="connectionID">1234</int>
</object>
<object class="IBConnectionRecord">
<object class="IBActionConnection" key="connection">
<string key="label">saveDocumentAs:</string>
<reference key="source" ref="1014"/>
<reference key="destination" ref="663106531"/>
</object>
<int key="connectionID">1255</int>
</object>
<object class="IBConnectionRecord">
<object class="IBActionConnection" key="connection">
<string key="label">exportDatabase:</string>
<reference key="source" ref="1014"/>
<reference key="destination" ref="438377242"/>
</object>
<int key="connectionID">1260</int>
</object>
<object class="IBConnectionRecord">
<object class="IBActionConnection" key="connection">
<string key="label">lock:</string>
<reference key="source" ref="1014"/>
<reference key="destination" ref="919874146"/>
</object>
<int key="connectionID">1263</int>
</object>
<object class="IBConnectionRecord">
<object class="IBActionConnection" key="connection">
@@ -896,6 +947,9 @@
<reference ref="1010469920"/>
<reference ref="915918141"/>
<reference ref="544639599"/>
<reference ref="663106531"/>
<reference ref="438377242"/>
<reference ref="919874146"/>
</array>
<reference key="parent" ref="379814623"/>
</object>
@@ -1226,6 +1280,21 @@
<reference key="object" ref="544639599"/>
<reference key="parent" ref="720053764"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">1243</int>
<reference key="object" ref="663106531"/>
<reference key="parent" ref="720053764"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">1259</int>
<reference key="object" ref="438377242"/>
<reference key="parent" ref="720053764"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">1261</int>
<reference key="object" ref="919874146"/>
<reference key="parent" ref="720053764"/>
</object>
</array>
</object>
<dictionary class="NSMutableDictionary" key="flattenedProperties">
@@ -1241,8 +1310,11 @@
<string key="1203.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="1231.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="124.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="1243.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="125.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="1259.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="126.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="1261.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="129.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="130.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="131.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
@@ -1298,7 +1370,7 @@
<nil key="activeLocalization"/>
<dictionary class="NSMutableDictionary" key="localizations"/>
<nil key="sourceID"/>
<int key="maxID">1233</int>
<int key="maxID">1263</int>
</object>
<object class="IBClassDescriber" key="IBDocument.Classes">
<array class="NSMutableArray" key="referencedPartialClassDescriptions">
@@ -1358,15 +1430,25 @@
<string key="superclassName">NSWindowController</string>
<dictionary class="NSMutableDictionary" key="actions">
<string key="editPassword:">id</string>
<string key="showDocumentSettings:">id</string>
<string key="exportDatabase:">id</string>
<string key="lock:">id</string>
<string key="showDatabaseSettings:">id</string>
</dictionary>
<dictionary class="NSMutableDictionary" key="actionInfosByName">
<object class="IBActionInfo" key="editPassword:">
<string key="name">editPassword:</string>
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo" key="showDocumentSettings:">
<string key="name">showDocumentSettings:</string>
<object class="IBActionInfo" key="exportDatabase:">
<string key="name">exportDatabase:</string>
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo" key="lock:">
<string key="name">lock:</string>
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo" key="showDatabaseSettings:">
<string key="name">showDatabaseSettings:</string>
<string key="candidateClassName">id</string>
</object>
</dictionary>

View File

@@ -1,947 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="8.00">
<data>
<int key="IBDocument.SystemTarget">1080</int>
<string key="IBDocument.SystemVersion">12E55</string>
<string key="IBDocument.InterfaceBuilderVersion">3084</string>
<string key="IBDocument.AppKitVersion">1187.39</string>
<string key="IBDocument.HIToolboxVersion">626.00</string>
<object class="NSMutableDictionary" key="IBDocument.PluginVersions">
<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="NS.object.0">3084</string>
</object>
<array key="IBDocument.IntegratedClassDependencies">
<string>IBNSLayoutConstraint</string>
<string>NSButton</string>
<string>NSButtonCell</string>
<string>NSCustomObject</string>
<string>NSCustomView</string>
<string>NSPathCell</string>
<string>NSPathControl</string>
<string>NSSecureTextField</string>
<string>NSSecureTextFieldCell</string>
<string>NSTextField</string>
<string>NSTextFieldCell</string>
</array>
<array key="IBDocument.PluginDependencies">
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
</array>
<object class="NSMutableDictionary" key="IBDocument.Metadata">
<string key="NS.key.0">PluginDependencyRecalculationVersion</string>
<integer value="1" key="NS.object.0"/>
</object>
<array class="NSMutableArray" key="IBDocument.RootObjects" id="1000">
<object class="NSCustomObject" id="1001">
<string key="NSClassName">MPPasswordEditViewController</string>
</object>
<object class="NSCustomObject" id="1003">
<string key="NSClassName">FirstResponder</string>
</object>
<object class="NSCustomObject" id="1004">
<string key="NSClassName">NSApplication</string>
</object>
<object class="NSCustomView" id="595834490">
<reference key="NSNextResponder"/>
<int key="NSvFlags">268</int>
<array class="NSMutableArray" key="NSSubviews">
<object class="NSTextField" id="762740216">
<reference key="NSNextResponder" ref="595834490"/>
<int key="NSvFlags">268</int>
<string key="NSFrame">{{99, 157}, {164, 17}}</string>
<reference key="NSSuperview" ref="595834490"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="847623533"/>
<string key="NSReuseIdentifierKey">_NS:1535</string>
<bool key="NSEnabled">YES</bool>
<object class="NSTextFieldCell" key="NSCell" id="79241474">
<int key="NSCellFlags">68157504</int>
<int key="NSCellFlags2">272630784</int>
<string key="NSContents">Change Password/Keyfile</string>
<object class="NSFont" key="NSSupport" id="385477987">
<string key="NSName">LucidaGrande</string>
<double key="NSSize">13</double>
<int key="NSfFlags">1044</int>
</object>
<string key="NSCellIdentifier">_NS:1535</string>
<reference key="NSControlView" ref="762740216"/>
<object class="NSColor" key="NSBackgroundColor" id="515490923">
<int key="NSColorSpace">6</int>
<string key="NSCatalogName">System</string>
<string key="NSColorName">controlColor</string>
<object class="NSColor" key="NSColor">
<int key="NSColorSpace">3</int>
<bytes key="NSWhite">MC42NjY2NjY2NjY3AA</bytes>
</object>
</object>
<object class="NSColor" key="NSTextColor" id="504890084">
<int key="NSColorSpace">6</int>
<string key="NSCatalogName">System</string>
<string key="NSColorName">controlTextColor</string>
<object class="NSColor" key="NSColor" id="354127501">
<int key="NSColorSpace">3</int>
<bytes key="NSWhite">MAA</bytes>
</object>
</object>
</object>
<bool key="NSAllowsLogicalLayoutDirection">NO</bool>
</object>
<object class="NSButton" id="256981522">
<reference key="NSNextResponder" ref="595834490"/>
<int key="NSvFlags">268</int>
<string key="NSFrame">{{113, 13}, {82, 32}}</string>
<reference key="NSSuperview" ref="595834490"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="771851607"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<bool key="NSEnabled">YES</bool>
<object class="NSButtonCell" key="NSCell" id="69579583">
<int key="NSCellFlags">67108864</int>
<int key="NSCellFlags2">134217728</int>
<string key="NSContents">Cancel</string>
<reference key="NSSupport" ref="385477987"/>
<string key="NSCellIdentifier">_NS:9</string>
<reference key="NSControlView" ref="256981522"/>
<int key="NSButtonFlags">-2038284288</int>
<int key="NSButtonFlags2">129</int>
<string key="NSAlternateContents"/>
<string type="base64-UTF8" key="NSKeyEquivalent">Gw</string>
<int key="NSPeriodicDelay">200</int>
<int key="NSPeriodicInterval">25</int>
</object>
<bool key="NSAllowsLogicalLayoutDirection">NO</bool>
</object>
<object class="NSPathControl" id="679285412">
<reference key="NSNextResponder" ref="595834490"/>
<int key="NSvFlags">268</int>
<set class="NSMutableSet" key="NSDragTypes">
<string>Apple URL pasteboard type</string>
<string>NSFilenamesPboardType</string>
</set>
<string key="NSFrame">{{83, 57}, {197, 22}}</string>
<reference key="NSSuperview" ref="595834490"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="256981522"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<bool key="NSEnabled">YES</bool>
<object class="NSPathCell" key="NSCell" id="902994558">
<int key="NSCellFlags">337641473</int>
<int key="NSCellFlags2">131072</int>
<object class="NSFont" key="NSSupport">
<string key="NSName">LucidaGrande</string>
<double key="NSSize">11</double>
<int key="NSfFlags">3100</int>
</object>
<string key="NSCellIdentifier">_NS:9</string>
<reference key="NSControlView" ref="679285412"/>
<array class="NSMutableArray" key="NSPathComponentCells"/>
<int key="NSPathStyle">2</int>
<reference key="NSDelegate" ref="679285412"/>
</object>
<bool key="NSAllowsLogicalLayoutDirection">NO</bool>
</object>
<object class="NSSecureTextField" id="670734441">
<reference key="NSNextResponder" ref="595834490"/>
<int key="NSvFlags">268</int>
<string key="NSFrame">{{86, 86}, {191, 22}}</string>
<reference key="NSSuperview" ref="595834490"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="365869599"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<bool key="NSEnabled">YES</bool>
<object class="NSSecureTextFieldCell" key="NSCell" id="656181976">
<int key="NSCellFlags">342884416</int>
<int key="NSCellFlags2">272630848</int>
<string key="NSContents"/>
<reference key="NSSupport" ref="385477987"/>
<string key="NSCellIdentifier">_NS:9</string>
<reference key="NSControlView" ref="670734441"/>
<bool key="NSDrawsBackground">YES</bool>
<object class="NSColor" key="NSBackgroundColor">
<int key="NSColorSpace">6</int>
<string key="NSCatalogName">System</string>
<string key="NSColorName">textBackgroundColor</string>
<object class="NSColor" key="NSColor">
<int key="NSColorSpace">3</int>
<bytes key="NSWhite">MQA</bytes>
</object>
</object>
<object class="NSColor" key="NSTextColor">
<int key="NSColorSpace">6</int>
<string key="NSCatalogName">System</string>
<string key="NSColorName">textColor</string>
<reference key="NSColor" ref="354127501"/>
</object>
<array key="NSAllowedInputLocales">
<string>NSAllRomanInputSourcesLocaleIdentifier</string>
</array>
</object>
<bool key="NSAllowsLogicalLayoutDirection">NO</bool>
</object>
<object class="NSTextField" id="847623533">
<reference key="NSNextResponder" ref="595834490"/>
<int key="NSvFlags">268</int>
<string key="NSFrame">{{17, 89}, {64, 17}}</string>
<reference key="NSSuperview" ref="595834490"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="670734441"/>
<string key="NSReuseIdentifierKey">_NS:1535</string>
<bool key="NSEnabled">YES</bool>
<object class="NSTextFieldCell" key="NSCell" id="792960157">
<int key="NSCellFlags">68157504</int>
<int key="NSCellFlags2">272630784</int>
<string key="NSContents">Password</string>
<reference key="NSSupport" ref="385477987"/>
<string key="NSCellIdentifier">_NS:1535</string>
<reference key="NSControlView" ref="847623533"/>
<reference key="NSBackgroundColor" ref="515490923"/>
<reference key="NSTextColor" ref="504890084"/>
</object>
<bool key="NSAllowsLogicalLayoutDirection">NO</bool>
</object>
<object class="NSTextField" id="365869599">
<reference key="NSNextResponder" ref="595834490"/>
<int key="NSvFlags">268</int>
<string key="NSFrame">{{35, 62}, {46, 17}}</string>
<reference key="NSSuperview" ref="595834490"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="679285412"/>
<string key="NSReuseIdentifierKey">_NS:1535</string>
<bool key="NSEnabled">YES</bool>
<object class="NSTextFieldCell" key="NSCell" id="324335303">
<int key="NSCellFlags">68157504</int>
<int key="NSCellFlags2">272630784</int>
<string key="NSContents">Keyfile</string>
<reference key="NSSupport" ref="385477987"/>
<string key="NSCellIdentifier">_NS:1535</string>
<reference key="NSControlView" ref="365869599"/>
<reference key="NSBackgroundColor" ref="515490923"/>
<reference key="NSTextColor" ref="504890084"/>
</object>
<bool key="NSAllowsLogicalLayoutDirection">NO</bool>
</object>
<object class="NSButton" id="771851607">
<reference key="NSNextResponder" ref="595834490"/>
<int key="NSvFlags">268</int>
<string key="NSFrame">{{195, 13}, {88, 32}}</string>
<reference key="NSSuperview" ref="595834490"/>
<reference key="NSWindow"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<string key="NSHuggingPriority">{250, 250}</string>
<bool key="NSEnabled">YES</bool>
<object class="NSButtonCell" key="NSCell" id="251779948">
<int key="NSCellFlags">67108864</int>
<int key="NSCellFlags2">134217728</int>
<string key="NSContents">Change</string>
<reference key="NSSupport" ref="385477987"/>
<string key="NSCellIdentifier">_NS:9</string>
<reference key="NSControlView" ref="771851607"/>
<int key="NSButtonFlags">-2038284288</int>
<int key="NSButtonFlags2">129</int>
<string key="NSAlternateContents"/>
<string type="base64-UTF8" key="NSKeyEquivalent">DQ</string>
<int key="NSPeriodicDelay">200</int>
<int key="NSPeriodicInterval">25</int>
</object>
<bool key="NSAllowsLogicalLayoutDirection">NO</bool>
</object>
</array>
<string key="NSFrameSize">{363, 194}</string>
<reference key="NSSuperview"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="762740216"/>
<string key="NSAntiCompressionPriority">{751, 750}</string>
<string key="NSClassName">NSView</string>
</object>
</array>
<object class="IBObjectContainer" key="IBDocument.Objects">
<array class="NSMutableArray" key="connectionRecords">
<object class="IBConnectionRecord">
<object class="IBOutletConnection" key="connection">
<string key="label">view</string>
<reference key="source" ref="1001"/>
<reference key="destination" ref="595834490"/>
</object>
<int key="connectionID">52</int>
</object>
<object class="IBConnectionRecord">
<object class="IBOutletConnection" key="connection">
<string key="label">passwordTextField</string>
<reference key="source" ref="1001"/>
<reference key="destination" ref="670734441"/>
</object>
<int key="connectionID">53</int>
</object>
<object class="IBConnectionRecord">
<object class="IBOutletConnection" key="connection">
<string key="label">keyfilePathControl</string>
<reference key="source" ref="1001"/>
<reference key="destination" ref="679285412"/>
</object>
<int key="connectionID">54</int>
</object>
<object class="IBConnectionRecord">
<object class="IBActionConnection" key="connection">
<string key="label">_change:</string>
<reference key="source" ref="1001"/>
<reference key="destination" ref="771851607"/>
</object>
<int key="connectionID">55</int>
</object>
<object class="IBConnectionRecord">
<object class="IBActionConnection" key="connection">
<string key="label">_cancel:</string>
<reference key="source" ref="1001"/>
<reference key="destination" ref="256981522"/>
</object>
<int key="connectionID">56</int>
</object>
</array>
<object class="IBMutableOrderedSet" key="objectRecords">
<array key="orderedObjects">
<object class="IBObjectRecord">
<int key="objectID">0</int>
<array key="object" id="0"/>
<reference key="children" ref="1000"/>
<nil key="parent"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">-2</int>
<reference key="object" ref="1001"/>
<reference key="parent" ref="0"/>
<string key="objectName">File's Owner</string>
</object>
<object class="IBObjectRecord">
<int key="objectID">-1</int>
<reference key="object" ref="1003"/>
<reference key="parent" ref="0"/>
<string key="objectName">First Responder</string>
</object>
<object class="IBObjectRecord">
<int key="objectID">-3</int>
<reference key="object" ref="1004"/>
<reference key="parent" ref="0"/>
<string key="objectName">Application</string>
</object>
<object class="IBObjectRecord">
<int key="objectID">2</int>
<reference key="object" ref="595834490"/>
<array class="NSMutableArray" key="children">
<reference ref="365869599"/>
<reference ref="679285412"/>
<reference ref="670734441"/>
<reference ref="847623533"/>
<reference ref="771851607"/>
<object class="IBNSLayoutConstraint" id="501931119">
<reference key="firstItem" ref="771851607"/>
<int key="firstAttribute">10</int>
<int key="relation">0</int>
<reference key="secondItem" ref="256981522"/>
<int key="secondAttribute">10</int>
<float key="multiplier">1</float>
<object class="IBLayoutConstant" key="constant">
<double key="value">0.0</double>
</object>
<float key="priority">1000</float>
<reference key="containingView" ref="595834490"/>
<int key="scoringType">9</int>
<float key="scoringTypeFloat">40</float>
<int key="contentType">2</int>
</object>
<object class="IBNSLayoutConstraint" id="1024015372">
<reference key="firstItem" ref="771851607"/>
<int key="firstAttribute">5</int>
<int key="relation">0</int>
<reference key="secondItem" ref="256981522"/>
<int key="secondAttribute">6</int>
<float key="multiplier">1</float>
<object class="IBNSLayoutSymbolicConstant" key="constant">
<double key="value">12</double>
</object>
<float key="priority">1000</float>
<reference key="containingView" ref="595834490"/>
<int key="scoringType">6</int>
<float key="scoringTypeFloat">24</float>
<int key="contentType">3</int>
</object>
<object class="IBNSLayoutConstraint" id="381133690">
<reference key="firstItem" ref="771851607"/>
<int key="firstAttribute">3</int>
<int key="relation">0</int>
<reference key="secondItem" ref="679285412"/>
<int key="secondAttribute">4</int>
<float key="multiplier">1</float>
<object class="IBNSLayoutSymbolicConstant" key="constant">
<double key="value">20</double>
</object>
<float key="priority">1000</float>
<reference key="containingView" ref="595834490"/>
<int key="scoringType">9</int>
<float key="scoringTypeFloat">40</float>
<int key="contentType">3</int>
</object>
<object class="IBNSLayoutConstraint" id="629412806">
<reference key="firstItem" ref="771851607"/>
<int key="firstAttribute">6</int>
<int key="relation">0</int>
<reference key="secondItem" ref="679285412"/>
<int key="secondAttribute">6</int>
<float key="multiplier">1</float>
<object class="IBLayoutConstant" key="constant">
<double key="value">0.0</double>
</object>
<float key="priority">1000</float>
<reference key="containingView" ref="595834490"/>
<int key="scoringType">6</int>
<float key="scoringTypeFloat">24</float>
<int key="contentType">2</int>
</object>
<object class="IBNSLayoutConstraint" id="176392839">
<reference key="firstItem" ref="595834490"/>
<int key="firstAttribute">4</int>
<int key="relation">1</int>
<reference key="secondItem" ref="771851607"/>
<int key="secondAttribute">4</int>
<float key="multiplier">1</float>
<object class="IBNSLayoutSymbolicConstant" key="constant">
<double key="value">20</double>
</object>
<float key="priority">1000</float>
<reference key="containingView" ref="595834490"/>
<int key="scoringType">9</int>
<float key="scoringTypeFloat">40</float>
<int key="contentType">3</int>
</object>
<object class="IBNSLayoutConstraint" id="340048519">
<reference key="firstItem" ref="679285412"/>
<int key="firstAttribute">5</int>
<int key="relation">0</int>
<reference key="secondItem" ref="365869599"/>
<int key="secondAttribute">6</int>
<float key="multiplier">1</float>
<object class="IBNSLayoutSymbolicConstant" key="constant">
<double key="value">8</double>
</object>
<float key="priority">1000</float>
<reference key="containingView" ref="595834490"/>
<int key="scoringType">6</int>
<float key="scoringTypeFloat">24</float>
<int key="contentType">3</int>
</object>
<object class="IBNSLayoutConstraint" id="33581314">
<reference key="firstItem" ref="679285412"/>
<int key="firstAttribute">6</int>
<int key="relation">0</int>
<reference key="secondItem" ref="670734441"/>
<int key="secondAttribute">6</int>
<float key="multiplier">1</float>
<object class="IBLayoutConstant" key="constant">
<double key="value">0.0</double>
</object>
<float key="priority">1000</float>
<reference key="containingView" ref="595834490"/>
<int key="scoringType">6</int>
<float key="scoringTypeFloat">24</float>
<int key="contentType">2</int>
</object>
<object class="IBNSLayoutConstraint" id="481322683">
<reference key="firstItem" ref="679285412"/>
<int key="firstAttribute">5</int>
<int key="relation">0</int>
<reference key="secondItem" ref="670734441"/>
<int key="secondAttribute">5</int>
<float key="multiplier">1</float>
<object class="IBLayoutConstant" key="constant">
<double key="value">0.0</double>
</object>
<float key="priority">1000</float>
<reference key="containingView" ref="595834490"/>
<int key="scoringType">6</int>
<float key="scoringTypeFloat">24</float>
<int key="contentType">2</int>
</object>
<object class="IBNSLayoutConstraint" id="966743814">
<reference key="firstItem" ref="679285412"/>
<int key="firstAttribute">3</int>
<int key="relation">0</int>
<reference key="secondItem" ref="670734441"/>
<int key="secondAttribute">4</int>
<float key="multiplier">1</float>
<object class="IBNSLayoutSymbolicConstant" key="constant">
<double key="value">8</double>
</object>
<float key="priority">1000</float>
<reference key="containingView" ref="595834490"/>
<int key="scoringType">9</int>
<float key="scoringTypeFloat">40</float>
<int key="contentType">3</int>
</object>
<object class="IBNSLayoutConstraint" id="379216952">
<reference key="firstItem" ref="595834490"/>
<int key="firstAttribute">10</int>
<int key="relation">0</int>
<reference key="secondItem" ref="670734441"/>
<int key="secondAttribute">10</int>
<float key="multiplier">1</float>
<object class="IBLayoutConstant" key="constant">
<double key="value">0.0</double>
</object>
<float key="priority">1000</float>
<reference key="containingView" ref="595834490"/>
<int key="scoringType">9</int>
<float key="scoringTypeFloat">40</float>
<int key="contentType">2</int>
</object>
<object class="IBNSLayoutConstraint" id="612132939">
<reference key="firstItem" ref="670734441"/>
<int key="firstAttribute">5</int>
<int key="relation">0</int>
<reference key="secondItem" ref="847623533"/>
<int key="secondAttribute">6</int>
<float key="multiplier">1</float>
<object class="IBNSLayoutSymbolicConstant" key="constant">
<double key="value">8</double>
</object>
<float key="priority">1000</float>
<reference key="containingView" ref="595834490"/>
<int key="scoringType">9</int>
<float key="scoringTypeFloat">40</float>
<int key="contentType">3</int>
</object>
<object class="IBNSLayoutConstraint" id="485639451">
<reference key="firstItem" ref="595834490"/>
<int key="firstAttribute">9</int>
<int key="relation">0</int>
<reference key="secondItem" ref="670734441"/>
<int key="secondAttribute">9</int>
<float key="multiplier">1</float>
<object class="IBLayoutConstant" key="constant">
<double key="value">0.0</double>
</object>
<float key="priority">1000</float>
<reference key="containingView" ref="595834490"/>
<int key="scoringType">9</int>
<float key="scoringTypeFloat">40</float>
<int key="contentType">2</int>
</object>
<object class="IBNSLayoutConstraint" id="51218896">
<reference key="firstItem" ref="670734441"/>
<int key="firstAttribute">10</int>
<int key="relation">0</int>
<reference key="secondItem" ref="847623533"/>
<int key="secondAttribute">10</int>
<float key="multiplier">1</float>
<object class="IBLayoutConstant" key="constant">
<double key="value">0.0</double>
</object>
<float key="priority">1000</float>
<reference key="containingView" ref="595834490"/>
<int key="scoringType">6</int>
<float key="scoringTypeFloat">24</float>
<int key="contentType">2</int>
</object>
<object class="IBNSLayoutConstraint" id="910263208">
<reference key="firstItem" ref="365869599"/>
<int key="firstAttribute">11</int>
<int key="relation">0</int>
<reference key="secondItem" ref="679285412"/>
<int key="secondAttribute">11</int>
<float key="multiplier">1</float>
<object class="IBLayoutConstant" key="constant">
<double key="value">0.0</double>
</object>
<float key="priority">1000</float>
<reference key="containingView" ref="595834490"/>
<int key="scoringType">6</int>
<float key="scoringTypeFloat">24</float>
<int key="contentType">2</int>
</object>
<object class="IBNSLayoutConstraint" id="575391720">
<reference key="firstItem" ref="762740216"/>
<int key="firstAttribute">3</int>
<int key="relation">0</int>
<reference key="secondItem" ref="595834490"/>
<int key="secondAttribute">3</int>
<float key="multiplier">1</float>
<object class="IBNSLayoutSymbolicConstant" key="constant">
<double key="value">20</double>
</object>
<float key="priority">1000</float>
<reference key="containingView" ref="595834490"/>
<int key="scoringType">8</int>
<float key="scoringTypeFloat">29</float>
<int key="contentType">3</int>
</object>
<object class="IBNSLayoutConstraint" id="335749536">
<reference key="firstItem" ref="762740216"/>
<int key="firstAttribute">9</int>
<int key="relation">0</int>
<reference key="secondItem" ref="670734441"/>
<int key="secondAttribute">9</int>
<float key="multiplier">1</float>
<object class="IBLayoutConstant" key="constant">
<double key="value">0.0</double>
</object>
<float key="priority">1000</float>
<reference key="containingView" ref="595834490"/>
<int key="scoringType">6</int>
<float key="scoringTypeFloat">24</float>
<int key="contentType">2</int>
</object>
<object class="IBNSLayoutConstraint" id="426619093">
<reference key="firstItem" ref="847623533"/>
<int key="firstAttribute">5</int>
<int key="relation">1</int>
<reference key="secondItem" ref="595834490"/>
<int key="secondAttribute">5</int>
<float key="multiplier">1</float>
<object class="IBNSLayoutSymbolicConstant" key="constant">
<double key="value">20</double>
</object>
<float key="priority">1000</float>
<reference key="containingView" ref="595834490"/>
<int key="scoringType">9</int>
<float key="scoringTypeFloat">40</float>
<int key="contentType">3</int>
</object>
<reference ref="762740216"/>
<reference ref="256981522"/>
</array>
<reference key="parent" ref="0"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">5</int>
<reference key="object" ref="256981522"/>
<array class="NSMutableArray" key="children">
<reference ref="69579583"/>
</array>
<reference key="parent" ref="595834490"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">6</int>
<reference key="object" ref="365869599"/>
<array class="NSMutableArray" key="children">
<reference ref="324335303"/>
</array>
<reference key="parent" ref="595834490"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">7</int>
<reference key="object" ref="679285412"/>
<array class="NSMutableArray" key="children">
<reference ref="902994558"/>
</array>
<reference key="parent" ref="595834490"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">8</int>
<reference key="object" ref="670734441"/>
<array class="NSMutableArray" key="children">
<object class="IBNSLayoutConstraint" id="318411198">
<reference key="firstItem" ref="670734441"/>
<int key="firstAttribute">7</int>
<int key="relation">0</int>
<nil key="secondItem"/>
<int key="secondAttribute">0</int>
<float key="multiplier">1</float>
<object class="IBLayoutConstant" key="constant">
<double key="value">191</double>
</object>
<float key="priority">1000</float>
<reference key="containingView" ref="670734441"/>
<int key="scoringType">9</int>
<float key="scoringTypeFloat">40</float>
<int key="contentType">1</int>
</object>
<reference ref="656181976"/>
</array>
<reference key="parent" ref="595834490"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">9</int>
<reference key="object" ref="847623533"/>
<array class="NSMutableArray" key="children">
<reference ref="792960157"/>
</array>
<reference key="parent" ref="595834490"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">10</int>
<reference key="object" ref="771851607"/>
<array class="NSMutableArray" key="children">
<reference ref="251779948"/>
</array>
<reference key="parent" ref="595834490"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">14</int>
<reference key="object" ref="426619093"/>
<reference key="parent" ref="595834490"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">17</int>
<reference key="object" ref="51218896"/>
<reference key="parent" ref="595834490"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">18</int>
<reference key="object" ref="485639451"/>
<reference key="parent" ref="595834490"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">19</int>
<reference key="object" ref="612132939"/>
<reference key="parent" ref="595834490"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">20</int>
<reference key="object" ref="379216952"/>
<reference key="parent" ref="595834490"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">22</int>
<reference key="object" ref="910263208"/>
<reference key="parent" ref="595834490"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">23</int>
<reference key="object" ref="966743814"/>
<reference key="parent" ref="595834490"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">24</int>
<reference key="object" ref="481322683"/>
<reference key="parent" ref="595834490"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">25</int>
<reference key="object" ref="33581314"/>
<reference key="parent" ref="595834490"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">26</int>
<reference key="object" ref="340048519"/>
<reference key="parent" ref="595834490"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">28</int>
<reference key="object" ref="176392839"/>
<reference key="parent" ref="595834490"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">29</int>
<reference key="object" ref="629412806"/>
<reference key="parent" ref="595834490"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">30</int>
<reference key="object" ref="381133690"/>
<reference key="parent" ref="595834490"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">31</int>
<reference key="object" ref="1024015372"/>
<reference key="parent" ref="595834490"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">32</int>
<reference key="object" ref="251779948"/>
<reference key="parent" ref="771851607"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">33</int>
<reference key="object" ref="792960157"/>
<reference key="parent" ref="847623533"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">34</int>
<reference key="object" ref="318411198"/>
<reference key="parent" ref="670734441"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">35</int>
<reference key="object" ref="656181976"/>
<reference key="parent" ref="670734441"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">36</int>
<reference key="object" ref="902994558"/>
<reference key="parent" ref="679285412"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">37</int>
<reference key="object" ref="324335303"/>
<reference key="parent" ref="365869599"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">38</int>
<reference key="object" ref="69579583"/>
<reference key="parent" ref="256981522"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">45</int>
<reference key="object" ref="762740216"/>
<array class="NSMutableArray" key="children">
<reference ref="79241474"/>
</array>
<reference key="parent" ref="595834490"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">46</int>
<reference key="object" ref="79241474"/>
<reference key="parent" ref="762740216"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">48</int>
<reference key="object" ref="335749536"/>
<reference key="parent" ref="595834490"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">49</int>
<reference key="object" ref="575391720"/>
<reference key="parent" ref="595834490"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">59</int>
<reference key="object" ref="501931119"/>
<reference key="parent" ref="595834490"/>
</object>
</array>
</object>
<dictionary class="NSMutableDictionary" key="flattenedProperties">
<string key="-1.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="-2.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="-3.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<boolean value="NO" key="10.IBNSViewMetadataTranslatesAutoresizingMaskIntoConstraints"/>
<string key="10.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="14.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="17.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="18.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="19.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<array class="NSMutableArray" key="2.IBNSViewMetadataConstraints">
<reference ref="426619093"/>
<reference ref="335749536"/>
<reference ref="575391720"/>
<reference ref="910263208"/>
<reference ref="51218896"/>
<reference ref="485639451"/>
<reference ref="612132939"/>
<reference ref="379216952"/>
<reference ref="966743814"/>
<reference ref="481322683"/>
<reference ref="33581314"/>
<reference ref="340048519"/>
<reference ref="176392839"/>
<reference ref="629412806"/>
<reference ref="381133690"/>
<reference ref="1024015372"/>
<reference ref="501931119"/>
</array>
<boolean value="NO" key="2.IBNSViewMetadataLastInspectedTranslatesAutoresizingMaskIntoConstraints"/>
<boolean value="NO" key="2.IBNSViewMetadataTranslatesAutoresizingMaskIntoConstraints"/>
<string key="2.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="20.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="22.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="23.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="24.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="25.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="26.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="28.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="29.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="30.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="31.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="32.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="33.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="34.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="35.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="36.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="37.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="38.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<boolean value="NO" key="45.IBNSViewMetadataTranslatesAutoresizingMaskIntoConstraints"/>
<string key="45.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="46.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="48.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="49.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<boolean value="NO" key="5.IBNSViewMetadataTranslatesAutoresizingMaskIntoConstraints"/>
<string key="5.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="59.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<boolean value="NO" key="6.IBNSViewMetadataTranslatesAutoresizingMaskIntoConstraints"/>
<string key="6.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<boolean value="NO" key="7.IBNSViewMetadataTranslatesAutoresizingMaskIntoConstraints"/>
<string key="7.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<array class="NSMutableArray" key="8.IBNSViewMetadataConstraints">
<reference ref="318411198"/>
</array>
<boolean value="NO" key="8.IBNSViewMetadataTranslatesAutoresizingMaskIntoConstraints"/>
<string key="8.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<boolean value="NO" key="9.IBNSViewMetadataTranslatesAutoresizingMaskIntoConstraints"/>
<string key="9.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
</dictionary>
<dictionary class="NSMutableDictionary" key="unlocalizedProperties"/>
<nil key="activeLocalization"/>
<dictionary class="NSMutableDictionary" key="localizations"/>
<nil key="sourceID"/>
<int key="maxID">59</int>
</object>
<object class="IBClassDescriber" key="IBDocument.Classes">
<array class="NSMutableArray" key="referencedPartialClassDescriptions">
<object class="IBPartialClassDescription">
<string key="className">MPPasswordEditViewController</string>
<string key="superclassName">MPViewController</string>
<dictionary class="NSMutableDictionary" key="actions">
<string key="_cancel:">id</string>
<string key="_change:">id</string>
</dictionary>
<dictionary class="NSMutableDictionary" key="actionInfosByName">
<object class="IBActionInfo" key="_cancel:">
<string key="name">_cancel:</string>
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo" key="_change:">
<string key="name">_change:</string>
<string key="candidateClassName">id</string>
</object>
</dictionary>
<dictionary class="NSMutableDictionary" key="outlets">
<string key="keyfilePathControl">NSPathControl</string>
<string key="passwordTextField">NSSecureTextField</string>
</dictionary>
<dictionary class="NSMutableDictionary" key="toOneOutletInfosByName">
<object class="IBToOneOutletInfo" key="keyfilePathControl">
<string key="name">keyfilePathControl</string>
<string key="candidateClassName">NSPathControl</string>
</object>
<object class="IBToOneOutletInfo" key="passwordTextField">
<string key="name">passwordTextField</string>
<string key="candidateClassName">NSSecureTextField</string>
</object>
</dictionary>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBProjectSource</string>
<string key="minorKey">./Classes/MPPasswordEditViewController.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">MPViewController</string>
<string key="superclassName">NSViewController</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBProjectSource</string>
<string key="minorKey">./Classes/MPViewController.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSLayoutConstraint</string>
<string key="superclassName">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBProjectSource</string>
<string key="minorKey">./Classes/NSLayoutConstraint.h</string>
</object>
</object>
</array>
</object>
<int key="IBDocument.localizationMode">0</int>
<string key="IBDocument.TargetRuntimeIdentifier">IBCocoaFramework</string>
<bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>
<int key="IBDocument.defaultPropertyAccessControl">3</int>
<bool key="IBDocument.UseAutolayout">YES</bool>
</data>
</archive>

File diff suppressed because it is too large Load Diff

View File

@@ -36,7 +36,7 @@
<object class="NSWindowTemplate" id="1005">
<int key="NSWindowStyleMask">15</int>
<int key="NSWindowBacking">2</int>
<string key="NSWindowRect">{{196, 240}, {560, 490}}</string>
<string key="NSWindowRect">{{196, 240}, {700, 500}}</string>
<int key="NSWTFlags">1618477056</int>
<string key="NSWindowTitle">Window</string>
<string key="NSWindowClass">NSWindow</string>
@@ -46,23 +46,26 @@
<reference key="NSNextResponder"/>
<int key="NSvFlags">256</int>
<array class="NSMutableArray" key="NSSubviews"/>
<string key="NSFrameSize">{560, 490}</string>
<string key="NSFrameSize">{700, 500}</string>
<reference key="NSSuperview"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView"/>
</object>
<string key="NSScreenRect">{{0, 0}, {1920, 1058}}</string>
<string key="NSScreenRect">{{0, 0}, {2560, 1418}}</string>
<string key="NSMaxSize">{10000000000000, 10000000000000}</string>
<string key="NSFrameAutosaveName">DatabaseWindow</string>
<bool key="NSWindowIsRestorable">YES</bool>
</object>
<object class="NSSplitView" id="903506498">
<nil key="NSNextResponder"/>
<reference key="NSNextResponder"/>
<int key="NSvFlags">268</int>
<array class="NSMutableArray" key="NSSubviews"/>
<string key="NSFrameSize">{560, 194}</string>
<reference key="NSSuperview"/>
<reference key="NSWindow"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<bool key="NSIsVertical">YES</bool>
<int key="NSDividerStyle">2</int>
<string key="NSAutosaveName"/>
</object>
</array>
<object class="IBObjectContainer" key="IBDocument.Objects">
@@ -158,15 +161,20 @@
<string key="superclassName">NSWindowController</string>
<dictionary class="NSMutableDictionary" key="actions">
<string key="editPassword:">id</string>
<string key="showDocumentSettings:">id</string>
<string key="exportDatabase:">id</string>
<string key="showDatabaseSettings:">id</string>
</dictionary>
<dictionary class="NSMutableDictionary" key="actionInfosByName">
<object class="IBActionInfo" key="editPassword:">
<string key="name">editPassword:</string>
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo" key="showDocumentSettings:">
<string key="name">showDocumentSettings:</string>
<object class="IBActionInfo" key="exportDatabase:">
<string key="name">exportDatabase:</string>
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo" key="showDatabaseSettings:">
<string key="name">showDatabaseSettings:</string>
<string key="candidateClassName">id</string>
</object>
</dictionary>

View File

@@ -57,6 +57,7 @@
<int key="NSvFlags">268</int>
<string key="NSFrame">{{7, 5}, {32, 19}}</string>
<reference key="NSSuperview" ref="163272962"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<bool key="NSEnabled">YES</bool>
@@ -85,8 +86,9 @@
<bool key="NSAllowsLogicalLayoutDirection">NO</bool>
</object>
</array>
<string key="NSFrameSize">{684, 30}</string>
<string key="NSFrameSize">{694, 30}</string>
<reference key="NSSuperview" ref="997686550"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="276578969"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<string key="NSClassName">HNHGradientView</string>
@@ -103,8 +105,9 @@
<reference key="NSNextResponder" ref="262664416"/>
<int key="NSvFlags">256</int>
<array class="NSMutableArray" key="NSSubviews"/>
<string key="NSFrameSize">{684, 548}</string>
<string key="NSFrameSize">{694, 548}</string>
<reference key="NSSuperview" ref="262664416"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="788738248"/>
<string key="NSReuseIdentifierKey">_NS:13</string>
<bool key="NSEnabled">YES</bool>
@@ -113,8 +116,9 @@
<object class="NSTableHeaderView" key="NSHeaderView" id="253618752">
<reference key="NSNextResponder" ref="736877784"/>
<int key="NSvFlags">256</int>
<string key="NSFrameSize">{684, 17}</string>
<string key="NSFrameSize">{694, 17}</string>
<reference key="NSSuperview" ref="736877784"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="262664416"/>
<reference key="NSTableView" ref="528076956"/>
</object>
@@ -272,7 +276,7 @@
<reference key="NSTableView" ref="528076956"/>
</object>
<object class="NSTableColumn" id="683421605">
<double key="NSWidth">188</double>
<double key="NSWidth">198</double>
<double key="NSMinWidth">10</double>
<double key="NSMaxWidth">3.4028234663852886e+38</double>
<object class="NSTableHeaderCell" key="NSHeaderCell">
@@ -325,8 +329,9 @@
<int key="NSTableViewGroupRowStyle">1</int>
</object>
</array>
<string key="NSFrame">{{0, 17}, {684, 548}}</string>
<string key="NSFrame">{{0, 17}, {694, 548}}</string>
<reference key="NSSuperview" ref="613995671"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="528076956"/>
<string key="NSReuseIdentifierKey">_NS:11</string>
<reference key="NSDocView" ref="528076956"/>
@@ -338,6 +343,7 @@
<int key="NSvFlags">-2147483392</int>
<string key="NSFrame">{{224, 17}, {15, 102}}</string>
<reference key="NSSuperview" ref="613995671"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="802411427"/>
<string key="NSReuseIdentifierKey">_NS:58</string>
<bool key="NSAllowsLogicalLayoutDirection">NO</bool>
@@ -350,6 +356,7 @@
<int key="NSvFlags">-2147483392</int>
<string key="NSFrame">{{0, 310}, {480, 16}}</string>
<reference key="NSSuperview" ref="613995671"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="163272962"/>
<string key="NSReuseIdentifierKey">_NS:60</string>
<bool key="NSAllowsLogicalLayoutDirection">NO</bool>
@@ -364,16 +371,18 @@
<array class="NSMutableArray" key="NSSubviews">
<reference ref="253618752"/>
</array>
<string key="NSFrameSize">{684, 17}</string>
<string key="NSFrameSize">{694, 17}</string>
<reference key="NSSuperview" ref="613995671"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="253618752"/>
<reference key="NSDocView" ref="253618752"/>
<reference key="NSBGColor" ref="136901388"/>
<int key="NScvFlags">4</int>
</object>
</array>
<string key="NSFrame">{{0, 30}, {684, 565}}</string>
<string key="NSFrame">{{0, 30}, {694, 565}}</string>
<reference key="NSSuperview" ref="997686550"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="736877784"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<int key="NSsFlags">133680</int>
@@ -387,8 +396,9 @@
<double key="NSMagnification">1</double>
</object>
</array>
<string key="NSFrameSize">{684, 594}</string>
<string key="NSFrameSize">{694, 594}</string>
<reference key="NSSuperview"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="613995671"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<string key="NSClassName">NSView</string>
@@ -646,7 +656,7 @@
<object class="NSTextField" id="488604658">
<reference key="NSNextResponder" ref="954630866"/>
<int key="NSvFlags">266</int>
<string key="NSFrameSize">{188, 17}</string>
<string key="NSFrameSize">{198, 17}</string>
<reference key="NSSuperview" ref="954630866"/>
<reference key="NSNextKeyView" ref="1037276411"/>
<string key="NSAntiCompressionPriority">{250, 750}</string>
@@ -663,7 +673,7 @@
<bool key="NSAllowsLogicalLayoutDirection">NO</bool>
</object>
</array>
<string key="NSFrame">{{494, 1}, {188, 17}}</string>
<string key="NSFrame">{{494, 1}, {198, 17}}</string>
<reference key="NSNextKeyView" ref="488604658"/>
</object>
<reference key="destination" ref="488604658"/>
@@ -1565,7 +1575,7 @@
<reference key="parent" ref="276578969"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">790</int>
<int key="objectID">834</int>
<reference key="object" ref="244975730"/>
<reference key="parent" ref="163272962"/>
</object>
@@ -1705,7 +1715,7 @@
<string key="678.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="679.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="683.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<array class="NSMutableArray" key="690.IBNSViewMetadataConstraints">
<array key="690.IBNSViewMetadataConstraints">
<reference ref="337191559"/>
<reference ref="187301323"/>
<reference ref="244975730"/>
@@ -1725,15 +1735,117 @@
<string key="733.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="741.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="743.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="790.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="834.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
</dictionary>
<dictionary class="NSMutableDictionary" key="unlocalizedProperties"/>
<nil key="activeLocalization"/>
<dictionary class="NSMutableDictionary" key="localizations"/>
<nil key="sourceID"/>
<int key="maxID">801</int>
<int key="maxID">834</int>
</object>
<object class="IBClassDescriber" key="IBDocument.Classes">
<array class="NSMutableArray" key="referencedPartialClassDescriptions">
<object class="IBPartialClassDescription">
<string key="className">HNHGradientView</string>
<string key="superclassName">NSView</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBProjectSource</string>
<string key="minorKey">./Classes/HNHGradientView.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">MPEntryViewController</string>
<string key="superclassName">MPViewController</string>
<dictionary class="NSMutableDictionary" key="outlets">
<string key="addEntryButton">NSButton</string>
<string key="bottomBar">HNHGradientView</string>
<string key="entryTable">NSTableView</string>
<string key="filterBar">NSView</string>
<string key="filterDoneButton">NSButton</string>
<string key="filterLabelTextField">NSTextField</string>
<string key="filterSearchField">NSSearchField</string>
<string key="filterTitleButton">NSButton</string>
<string key="filterURLButton">NSButton</string>
<string key="filterUsernameButton">NSButton</string>
<string key="tableToTop">NSLayoutConstraint</string>
</dictionary>
<dictionary class="NSMutableDictionary" key="toOneOutletInfosByName">
<object class="IBToOneOutletInfo" key="addEntryButton">
<string key="name">addEntryButton</string>
<string key="candidateClassName">NSButton</string>
</object>
<object class="IBToOneOutletInfo" key="bottomBar">
<string key="name">bottomBar</string>
<string key="candidateClassName">HNHGradientView</string>
</object>
<object class="IBToOneOutletInfo" key="entryTable">
<string key="name">entryTable</string>
<string key="candidateClassName">NSTableView</string>
</object>
<object class="IBToOneOutletInfo" key="filterBar">
<string key="name">filterBar</string>
<string key="candidateClassName">NSView</string>
</object>
<object class="IBToOneOutletInfo" key="filterDoneButton">
<string key="name">filterDoneButton</string>
<string key="candidateClassName">NSButton</string>
</object>
<object class="IBToOneOutletInfo" key="filterLabelTextField">
<string key="name">filterLabelTextField</string>
<string key="candidateClassName">NSTextField</string>
</object>
<object class="IBToOneOutletInfo" key="filterSearchField">
<string key="name">filterSearchField</string>
<string key="candidateClassName">NSSearchField</string>
</object>
<object class="IBToOneOutletInfo" key="filterTitleButton">
<string key="name">filterTitleButton</string>
<string key="candidateClassName">NSButton</string>
</object>
<object class="IBToOneOutletInfo" key="filterURLButton">
<string key="name">filterURLButton</string>
<string key="candidateClassName">NSButton</string>
</object>
<object class="IBToOneOutletInfo" key="filterUsernameButton">
<string key="name">filterUsernameButton</string>
<string key="candidateClassName">NSButton</string>
</object>
<object class="IBToOneOutletInfo" key="tableToTop">
<string key="name">tableToTop</string>
<string key="candidateClassName">NSLayoutConstraint</string>
</object>
</dictionary>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBProjectSource</string>
<string key="minorKey">./Classes/MPEntryViewController.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">MPTableView</string>
<string key="superclassName">NSTableView</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBProjectSource</string>
<string key="minorKey">./Classes/MPTableView.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">MPViewController</string>
<string key="superclassName">NSViewController</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBProjectSource</string>
<string key="minorKey">./Classes/MPViewController.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSLayoutConstraint</string>
<string key="superclassName">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBProjectSource</string>
<string key="minorKey">./Classes/NSLayoutConstraint.h</string>
</object>
</object>
</array>
</object>
<object class="IBClassDescriber" key="IBDocument.Classes"/>
<int key="IBDocument.localizationMode">0</int>
<string key="IBDocument.TargetRuntimeIdentifier">IBCocoaFramework</string>
<bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,18 @@
//
// Kdb3Entry+KVOAdditions.h
// MacPass
//
// Created by Michael Starke on 19.07.13.
// Copyright (c) 2013 HicknHack Software GmbH. All rights reserved.
//
#import "Kdb3Node.h"
@interface Kdb3Entry (KVOAdditions)
- (NSUInteger)countOfBinaries;
- (id)objectInBinariesAtIndex:(NSUInteger)index;
- (void)removeObjectFromBinariesAtIndex:(NSUInteger)index;
- (void)insertObject:(id)binary inBinariesAtIndex:(NSUInteger)index;
@end

View File

@@ -0,0 +1,31 @@
//
// Kdb3Entry+KVOAdditions.m
// MacPass
//
// Created by Michael Starke on 19.07.13.
// Copyright (c) 2013 HicknHack Software GmbH. All rights reserved.
//
#import "Kdb3Entry+KVOAdditions.h"
@implementation Kdb3Entry (KVOAdditions)
- (NSUInteger)countOfBinaries {
return (self.binary != nil ? 1 : 0);
}
- (id)objectInBinariesAtIndex:(NSUInteger)index {
return self.binary;
}
- (void)removeObjectFromBinariesAtIndex:(NSUInteger)index {
if(self.binary ) {
self.binary = nil;
self.binaryDesc = nil;
}
}
- (void)insertObject:(id)binary inBinariesAtIndex:(NSUInteger)index {
return;//
}
@end

View File

@@ -18,32 +18,32 @@
tree.root = rootGroup;
KdbGroup *parentGroup = [tree createGroup:rootGroup];
parentGroup.name = @"General";
parentGroup.name = NSLocalizedString(@"GENERAL", "General");
parentGroup.image = 48;
[rootGroup addGroup:parentGroup];
KdbGroup *group = [tree createGroup:parentGroup];
group.name = @"Windows";
group.name = NSLocalizedString(@"WINDOWS", "Windows");
group.image = 38;
[parentGroup addGroup:group];
group = [tree createGroup:parentGroup];
group.name = @"Network";
group.name = NSLocalizedString(@"NETWORK", "Network");
group.image = 3;
[parentGroup addGroup:group];
group = [tree createGroup:parentGroup];
group.name = @"Internet";
group.name = NSLocalizedString(@"INTERNET", "Internet");
group.image = 1;
[parentGroup addGroup:group];
group = [tree createGroup:parentGroup];
group.name = @"eMail";
group.name = NSLocalizedString(@"EMAIL", "EMail");
group.image = 19;
[parentGroup addGroup:group];
group = [tree createGroup:parentGroup];
group.name = @"Homebanking";
group.name = NSLocalizedString(@"HOMEBANKING", "Homebanking");
group.image = 37;
[parentGroup addGroup:group];

View File

@@ -0,0 +1,15 @@
//
// Kdb4Entry+MPAdditions.h
// MacPass
//
// Created by Michael Starke on 19.07.13.
// Copyright (c) 2013 HicknHack Software GmbH. All rights reserved.
//
#import "Kdb4Node.h"
@interface Kdb4Entry (MPAdditions)
- (NSString *)uniqueKeyForProposal:(NSString *)key;
@end

View File

@@ -0,0 +1,34 @@
//
// Kdb4Entry+MPAdditions.m
// MacPass
//
// Created by Michael Starke on 19.07.13.
// Copyright (c) 2013 HicknHack Software GmbH. All rights reserved.
//
#import "Kdb4Entry+MPAdditions.h"
@implementation Kdb4Entry (MPAdditions)
- (NSString *)uniqueKeyForProposal:(NSString *)key {
/*
FIXME: Introduce some cachin behaviour. We iterate over after every single edit
*/
NSArray *defaultKeys = @[ FIELD_TITLE,
FIELD_USER_NAME,
FIELD_PASSWORD,
FIELD_URL,
FIELD_NOTES ];
NSMutableSet *keys = [[NSMutableSet alloc] initWithArray:defaultKeys];
for(StringField *field in self.stringFields) {
[keys addObject:field.key];
}
NSUInteger counter = 1;
NSString *base = key;
while([keys containsObject:key]) {
key = [NSString stringWithFormat:@"%@-%ld", base, counter++];
}
return key;
}
@end

View File

@@ -15,7 +15,7 @@
Kdb4Tree *tree = [[Kdb4Tree alloc] init];
tree.generator = @"MacPass";
tree.databaseName = NSLocalizedString(@"NEW_DATABASE", "Name for a newly created Database");
tree.databaseName = NSLocalizedString(@"DATABASE", "");
tree.databaseNameChanged = currentTime;
tree.databaseDescription = @"";
tree.databaseDescriptionChanged = currentTime;
@@ -42,32 +42,32 @@
tree.lastTopVisibleGroup = [UUID nullUuid];
KdbGroup *parentGroup = [tree createGroup:nil];
parentGroup.name = @"General";
parentGroup.name = NSLocalizedString(@"GENERAL", "General");
parentGroup.image = 48;
tree.root = parentGroup;
KdbGroup *group = [tree createGroup:parentGroup];
group.name = @"Windows";
group.name = NSLocalizedString(@"WINDOWS", "Windows");
group.image = 38;
[parentGroup addGroup:group];
group = [tree createGroup:parentGroup];
group.name = @"Network";
group.name = NSLocalizedString(@"NETWORK", "Network");
group.image = 3;
[parentGroup addGroup:group];
group = [tree createGroup:parentGroup];
group.name = @"Internet";
group.name = NSLocalizedString(@"INTERNET", "Internet");
group.image = 1;
[parentGroup addGroup:group];
group = [tree createGroup:parentGroup];
group.name = @"eMail";
group.name = NSLocalizedString(@"EMAIL", "EMail");
group.image = 19;
[parentGroup addGroup:group];
group = [tree createGroup:parentGroup];
group.name = @"Homebanking";
group.name = NSLocalizedString(@"HOMEBANKING", "Homebanking");
group.image = 37;
[parentGroup addGroup:group];

View File

@@ -17,8 +17,6 @@ APPKIT_EXTERN NSString *const MPEntryNotesUndoableKey;
@interface KdbEntry (Undo)
+ (NSUndoManager *)undoManager;
- (NSString *)titleUndoable;
- (NSString *)usernameUndoable;
- (NSString *)passwordUndoable;
@@ -31,4 +29,8 @@ APPKIT_EXTERN NSString *const MPEntryNotesUndoableKey;
- (void)setUrlUndoable:(NSString *)url;
- (void)setNotesUndoable:(NSString *)notes;
- (void)deleteUndoable;
- (void)moveToGroupUndoable:(KdbGroup *)group atIndex:(NSUInteger)index;
- (void)moveToTrashUndoable:(KdbGroup *)trash atIndex:(NSUInteger)index;
@end

View File

@@ -7,6 +7,8 @@
//
#import "KdbEntry+Undo.h"
#import "KdbGroup+Undo.h"
#import "KdbGroup+KVOAdditions.h"
#import "KdbGroup+MPTreeTools.h"
NSString *const MPEntryTitleUndoableKey = @"titleUndoable";
@@ -15,9 +17,16 @@ NSString *const MPEntryPasswordUndoableKey = @"passwordUndoable";
NSString *const MPEntryUrlUndoableKey = @"urlUndoable";
NSString *const MPEntryNotesUndoableKey = @"notesUndoable";
#ifndef MPSetActionName
#define MPSetActionName(key, comment) \
if(![[self undoManager] isUndoing]) {\
[[self undoManager] setActionName:[[NSBundle mainBundle] localizedStringForKey:(key) value:@"" table:nil]];\
}
#endif
@implementation KdbEntry (Undo)
+ (NSUndoManager *)undoManager {
- (NSUndoManager *)undoManager {
return [[[NSDocumentController sharedDocumentController] currentDocument] undoManager];
}
@@ -41,40 +50,110 @@ NSString *const MPEntryNotesUndoableKey = @"notesUndoable";
return [self notes];
}
- (void)setTitleUndoable:(NSString *)title {
[[KdbEntry undoManager] registerUndoWithTarget:self selector:@selector(setTitleUndoable:) object:self.title];
[[KdbEntry undoManager] setActionName:NSLocalizedString(@"UNDO_SET_TITLE", "Undo set title")];
[[self undoManager] registerUndoWithTarget:self selector:@selector(setTitleUndoable:) object:self.title];
if(![[self undoManager] isUndoing]) {
[[self undoManager] setActionName:NSLocalizedString(@"SET_TITLE", "Set Title")];
}
[self setLastModificationTime:[NSDate date]];
[self setTitle:title];
}
- (void)setUsernameUndoable:(NSString *)username {
[[KdbEntry undoManager] registerUndoWithTarget:self selector:@selector(setUsernameUndoable:) object:self.username];
[[KdbEntry undoManager] setActionName:NSLocalizedString(@"UNDO_SET_USERNAME", "Undo set username")];
[[self undoManager] registerUndoWithTarget:self selector:@selector(setUsernameUndoable:) object:self.username];
if(![[self undoManager] isUndoing]) {
[[self undoManager] setActionName:NSLocalizedString(@"SET_USERNAME", "Undo set username")];
}
[self setLastModificationTime:[NSDate date]];
[self setUsername:username];
}
- (void)setPasswordUndoable:(NSString *)password {
[[KdbEntry undoManager] registerUndoWithTarget:self selector:@selector(setPasswordUndoable:) object:self.password];
[[KdbEntry undoManager] setActionName:NSLocalizedString(@"UNDO_SET_PASSWORT", "Undo set password")];
[[self undoManager] registerUndoWithTarget:self selector:@selector(setPasswordUndoable:) object:self.password];
MPSetActionName(@"SET_PASSWORT", "Undo set password");
if(![[self undoManager] isUndoing]) {
[[self undoManager] setActionName:NSLocalizedString(@"SET_TITLE", "Set Title")];
}
[self setLastModificationTime:[NSDate date]];
[self setPassword:password];
}
- (void)setUrlUndoable:(NSString *)url {
[[KdbEntry undoManager] registerUndoWithTarget:self selector:@selector(setUrlUndoable:) object:self.url];
[[KdbEntry undoManager] setActionName:NSLocalizedString(@"UNDO_SET_URL", "Undo set URL")];
[[self undoManager] registerUndoWithTarget:self selector:@selector(setUrlUndoable:) object:self.url];
MPSetActionName(@"SET_URL", "Undo set URL");
if(![[self undoManager] isUndoing]) {
[[self undoManager] setActionName:NSLocalizedString(@"SET_TITLE", "Set Title")];
}
[self setLastModificationTime:[NSDate date]];
[self setUrl:url];
}
- (void)setNotesUndoable:(NSString *)notes {
[[KdbEntry undoManager] registerUndoWithTarget:self selector:@selector(setNotesUndoable:) object:self.notes];
[[KdbEntry undoManager] setActionName:NSLocalizedString(@"UNDO_SET_NOTES", "Undo set notes")];
[[self undoManager] registerUndoWithTarget:self selector:@selector(setNotesUndoable:) object:self.notes];
MPSetActionName(@"SET_NOTES", "Set Notes");
if(![[self undoManager] isUndoing]) {
[[self undoManager] setActionName:NSLocalizedString(@"SET_TITLE", "Set Title")];
}
[self setLastModificationTime:[NSDate date]];
[self setNotes:notes];
}
- (void)deleteUndoable {
if(!self.parent) {
return; // No parent to be removed from
}
NSUInteger oldIndex = [self.parent.entries indexOfObject:self];
if(oldIndex == NSNotFound) {
return; // We're not in our parents entries list
}
[[[self undoManager] prepareWithInvocationTarget:self.parent] addEntryUndoable:self atIndex:oldIndex];
if(![[self undoManager] isUndoing]) {
[[self undoManager] setActionName:NSLocalizedString(@"DELETE_ENTRY", "Set Title")];
}
//[[NSNotificationCenter defaultCenter] postNotificationName:@"" object:self userInfo:nil];
[self.parent removeObjectFromEntriesAtIndex:oldIndex];
}
- (void)moveToGroupUndoable:(KdbGroup *)group atIndex:(NSUInteger)index {
[self _moveToGroup:group atIndex:index actionName:NSLocalizedString(@"MOVE_ENTRY", "Move Group")];
}
- (void)moveToTrashUndoable:(KdbGroup *)trash atIndex:(NSUInteger)index {
[self _moveToGroup:trash atIndex:index actionName:NSLocalizedString(@"TRASH_ENTRY", "Move Entry to Trash")];
}
- (void)_moveToGroup:(KdbGroup *)group atIndex:(NSUInteger)index actionName:(NSString *)name {
if(!group || !self.parent) {
return; // Nothing to be moved about
}
NSUInteger oldIndex = [self.parent.entries indexOfObject:self];
if(oldIndex == NSNotFound) {
return; // Not found in entries of parent!
}
[[[self undoManager] prepareWithInvocationTarget:self] _moveToGroup:self.parent atIndex:oldIndex actionName:name];
if(![[self undoManager] isUndoing]) {
[[self undoManager] setActionName:name];
}
[self.parent removeObjectFromEntriesAtIndex:oldIndex];
// Old indices might be wrong, correct them if necessary
index = MIN(index, [group.entries count]);
[group insertObject:self inEntriesAtIndex:index];
}
@end

View File

@@ -20,4 +20,6 @@
/* Returns the group with the UUID */
- (KdbGroup *)groupForUUID:(UUID *)uuid;
- (BOOL)isAnchestorOfGroup:(KdbGroup *)group;
@end

View File

@@ -49,4 +49,18 @@
return [filteredGroups lastObject];
}
- (BOOL)isAnchestorOfGroup:(KdbGroup *)group {
if(group == nil) {
return NO;
}
KdbGroup *ancestor = self.parent;
while(ancestor.parent) {
if(group == self) {
return YES;
}
ancestor = ancestor.parent;
}
return NO;
}
@end

View File

@@ -17,4 +17,10 @@ APPKIT_EXTERN NSString *const MPGroupNameUndoableKey;
- (NSString *)nameUndoable;
- (void)setNameUndoable:(NSString *)newName;
- (void)deleteUndoable;
- (void)addGroupUndoable:(KdbGroup *)group atIndex:(NSUInteger)index;
- (void)addEntryUndoable:(KdbEntry *)entry atIndex:(NSUInteger)index;
- (void)moveToGroupUndoable:(KdbGroup *)group atIndex:(NSUInteger)index;
- (void)moveToTrashUndoable:(KdbGroup *)trash atIndex:(NSUInteger)index;
@end

View File

@@ -8,6 +8,7 @@
#import "KdbGroup+Undo.h"
#import "KdbGroup+KVOAdditions.h"
#import "KdbEntry+Undo.h"
NSString *const MPGroupNameUndoableKey = @"nameUndoable";
@@ -23,8 +24,85 @@ NSString *const MPGroupNameUndoableKey = @"nameUndoable";
- (void)setNameUndoable:(NSString *)newName {
[[self undoManager] registerUndoWithTarget:self selector:@selector(setNameUndoable:) object:self.name];
[[self undoManager] setActionName:NSLocalizedString(@"UNDO_SET_NAME", "Undo set name")];
if(![[self undoManager] isUndoing]) {
[[self undoManager] setActionName:NSLocalizedString(@"SET_NAME", "Set Name")];
}
self.name = newName;
}
- (void)deleteUndoable {
if(!self.parent) {
return;
}
NSUInteger oldIndex = [self.parent.groups indexOfObject:self];
if(oldIndex == NSNotFound) {
return; // Inconsistent data
}
[[[self undoManager] prepareWithInvocationTarget:self.parent] addGroupUndoable:self atIndex:oldIndex];
if(![[self undoManager] isUndoing]) {
[[self undoManager] setActionName:NSLocalizedString(@"DELETE_GROUP", "Delete Group")];
}
[self.parent removeObjectFromGroupsAtIndex:oldIndex];
}
- (void)addGroupUndoable:(KdbGroup *)group atIndex:(NSUInteger)index {
if(!group) {
return;
}
[[[self undoManager] prepareWithInvocationTarget:group] deleteUndoable];
if(![[self undoManager] isUndoing]) {
[[self undoManager] setActionName:NSLocalizedString(@"ADD_GROUP", "Add Group")];
}
index = MIN(index, [group.groups count]);
[self insertObject:group inGroupsAtIndex:index];
}
- (void)addEntryUndoable:(KdbEntry *)entry atIndex:(NSUInteger)index {
if(!entry) {
return;
}
index = MIN(index, [self.entries count]);
[[[self undoManager] prepareWithInvocationTarget:entry] deleteUndoable];
if(![[self undoManager] isUndoing]) {
[[self undoManager] setActionName:NSLocalizedString(@"ADD_ENTRY", "Add Entry")];
}
[self insertObject:entry inEntriesAtIndex:index];
}
- (void)moveToGroupUndoable:(KdbGroup *)group atIndex:(NSUInteger)index {
[self _moveToGroup:group atIndex:index actionName:NSLocalizedString(@"MOVE_GROUP", "Move Group" )];
}
- (void)moveToTrashUndoable:(KdbGroup *)trash atIndex:(NSUInteger)index {
[self _moveToGroup:trash atIndex:index actionName:NSLocalizedString(@"TRASH_GROUP", "Move Group to Trash")];
}
- (void)_moveToGroup:(KdbGroup *)group atIndex:(NSUInteger)index actionName:(NSString *)actionName {
if(!self.parent || !group) {
return; // No target or origin
}
NSUInteger oldIndex = [self.parent.groups indexOfObject:self];
if(oldIndex == NSNotFound) {
return; // We aren't in our parents groups list.
}
[[[self undoManager] prepareWithInvocationTarget:self] moveToGroupUndoable:self.parent atIndex:oldIndex];
if(![[self undoManager] isUndoing]) {
[[self undoManager] setActionName:actionName];
}
[self.parent removeObjectFromGroupsAtIndex:oldIndex];
index = MIN(index, [group.groups count]);
[group insertObject:self inGroupsAtIndex:index];
}
@end

View File

@@ -9,9 +9,9 @@
#import <Foundation/Foundation.h>
typedef NS_ENUM(NSUInteger, MPActionType) {
MPUnkownAction, // Netural element to be used for returns
MPActionAddEntry, // Add an new entry
MPActionAddGroup, // Add a new group
MPActionEdit, // Edit entry or group
MPActionDelete, // Delete entry or group
MPActionCopyUsername, // copy username to pasteboard
MPActionCopyPassword, // copy password to pasteboard
@@ -25,5 +25,6 @@ typedef NS_ENUM(NSUInteger, MPActionType) {
@interface MPActionHelper : NSObject
+ (SEL)actionOfType:(MPActionType)type;
+ (MPActionType)typeForAction:(SEL)action;
@end

View File

@@ -10,25 +10,42 @@
@implementation MPActionHelper
+ (SEL)actionOfType:(MPActionType)type {
+ (NSDictionary *)_actionDictionary {
static NSDictionary *actionDict;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
actionDict = @{
@(MPActionAddEntry) : @"createEntry:",
@(MPActionAddGroup) : @"createGroup:",
@(MPActionCopyPassword) : @"copyPassword:",
@(MPActionCopyURL) : @"copyURL:",
@(MPActionCopyUsername) : @"copyUsername:",
@(MPActionDelete) : @"deleteNode:",
@(MPActionEdit) : @"editEntry:",
@(MPActionOpenURL) : @"openURL:",
@(MPActionToggleInspector) : @"toggleInspector:",
@(MPActionLock) : @"lock:",
@(MPActionEmptyTrash) : @"emptyTrash:"
};
@(MPActionAddEntry) : @"createEntry:",
@(MPActionAddGroup) : @"createGroup:",
@(MPActionCopyPassword) : @"copyPassword:",
@(MPActionCopyURL) : @"copyURL:",
@(MPActionCopyUsername) : @"copyUsername:",
@(MPActionDelete) : @"deleteNode:",
@(MPActionOpenURL) : @"openURL:",
@(MPActionToggleInspector) : @"toggleInspector:",
@(MPActionLock) : @"lock:",
@(MPActionEmptyTrash) : @"emptyTrash:"
};
});
return actionDict;
}
+ (SEL)actionOfType:(MPActionType)type {
NSDictionary *actionDict = [self _actionDictionary];
return NSSelectorFromString(actionDict[@(type)]);
}
+ (MPActionType)typeForAction:(SEL)action {
NSString *selectorString = NSStringFromSelector(action);
NSArray *selectors = [[self _actionDictionary] allValues];
NSUInteger index = [selectors indexOfObject:selectorString];
if(index == NSNotFound) {
return MPUnkownAction;
}
NSArray *keys = [[self _actionDictionary] allKeysForObject:selectorString];
NSAssert([keys count] == 1, @"There should only be one object for the specified key");
return [[keys lastObject] integerValue];
}
@end

View File

@@ -38,16 +38,31 @@
[MPStringLengthValueTransformer registerTransformer];
}
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (BOOL)applicationShouldOpenUntitledFile:(NSApplication *)sender {
return [[NSUserDefaults standardUserDefaults] boolForKey:kMPSettingsKeyOpenEmptyDatabaseOnLaunch];
}
- (void)applicationWillFinishLaunching:(NSNotification *)notification {
BOOL reopen = [[NSUserDefaults standardUserDefaults] boolForKey:kMPSettingsKeyReopenLastDatabaseOnLaunch];
if(reopen) {
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(_applicationDidFinishRestoringWindows:)
name:NSApplicationDidFinishRestoringWindowsNotification
object:nil];
}
}
- (void)applicationDidFinishLaunching:(NSNotification *)notification {
serverDaemon = [[MPServerDaemon alloc] init];
lockDaemon = [[MPLockDaemon alloc] init];
}
- (NSString *)applicationName {
return [[NSBundle mainBundle] infoDictionary][@"CFBundleName"];
}
@@ -93,4 +108,26 @@
}
}
- (void)_applicationDidFinishRestoringWindows:(NSNotification *)notification {
NSDocumentController *documentController = [NSDocumentController sharedDocumentController];
NSArray *documents = [documentController documents];
NSArray *recentDocuments = [documentController recentDocumentURLs];
if([documents count] > 0 ) {
return; // There's already a document restored
}
NSURL *documentUrl;
if([recentDocuments count] > 0) {
documentUrl = recentDocuments[0];
}
else {
NSString *lastPath = [[NSUserDefaults standardUserDefaults] stringForKey:kMPSettingsKeyLastDatabasePath];
documentUrl = [NSURL URLWithString:lastPath];
}
if([documentUrl isFileURL]) {
[documentController openDocumentWithContentsOfURL:documentUrl display:YES
completionHandler:^(NSDocument *document, BOOL documentWasAlreadyOpen, NSError *error) {}];
}
}
@end

View File

@@ -0,0 +1,17 @@
//
// MPAttachmentTableViewDelegate.h
// MacPass
//
// Created by Michael Starke on 17.07.13.
// Copyright (c) 2013 HicknHack Software GmbH. All rights reserved.
//
#import <Foundation/Foundation.h>
@class MPInspectorViewController;
@interface MPAttachmentTableViewDelegate : NSObject <NSTableViewDelegate>
@property (nonatomic, weak) MPInspectorViewController *viewController;
@end

View File

@@ -0,0 +1,75 @@
//
// MPAttachmentTableViewDelegate.m
// MacPass
//
// Created by Michael Starke on 17.07.13.
// Copyright (c) 2013 HicknHack Software GmbH. All rights reserved.
//
#import "MPAttachmentTableViewDelegate.h"
#import "MPInspectorViewController.h"
#import "MPSelectedAttachmentTableCellView.h"
#import "Kdb4Node.h"
#import "Kdb3Node.h"
#import "HNHTableRowView.h"
@implementation MPAttachmentTableViewDelegate
- (void)tableViewSelectionDidChange:(NSNotification *)notification {
NSTableView *tableView = [notification object];
NSIndexSet *allColumns = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, [[tableView tableColumns] count])];
if([self.viewController.selectedEntry isKindOfClass:[Kdb4Entry class]]) {
Kdb4Entry *entryv4 = (Kdb4Entry *)self.viewController.selectedEntry;
NSIndexSet *indexSet = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, [entryv4.binaries count] )];
[tableView reloadDataForRowIndexes:indexSet columnIndexes:allColumns];
}
if([self.viewController.selectedEntry isKindOfClass:[Kdb3Entry class]]) {
Kdb3Entry *entryv3 = (Kdb3Entry *)self.viewController.selectedEntry;
NSIndexSet *indexSet = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, (entryv3.binary ? 1 : 0 ))];
[tableView reloadDataForRowIndexes:indexSet columnIndexes:allColumns];
}
}
- (NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
/* Decide what view to use */
NSIndexSet *selectedIndexes = [tableView selectedRowIndexes];
NSTableCellView *view;
if([selectedIndexes containsIndex:row]) {
MPSelectedAttachmentTableCellView *cellView = [tableView makeViewWithIdentifier:@"SelectedCell" owner:tableView];
[cellView.saveButton setTag:row];
[cellView.saveButton setAction:@selector(saveAttachment:)];
[cellView.saveButton setTarget:self.viewController];
[cellView.removeButton setTag:row];
[cellView.removeButton setAction:@selector(removeAttachment:)];
[cellView.removeButton setTarget:self.viewController];
view = cellView;
}
else {
view = [tableView makeViewWithIdentifier:@"NormalCell" owner:tableView];
}
/* Bind view */
if([self.viewController.selectedEntry isKindOfClass:[Kdb4Entry class]]) {
Kdb4Entry *entry = (Kdb4Entry *)self.viewController.selectedEntry;
BinaryRef *binaryRef = entry.binaries[row];
[[view textField] bind:NSValueBinding toObject:binaryRef withKeyPath:@"key" options:nil];
[[view imageView] setImage:[[NSWorkspace sharedWorkspace] iconForFileType:[binaryRef.key pathExtension]]];
}
else {
Kdb3Entry *entry= (Kdb3Entry *)self.viewController.selectedEntry;
[[view textField] bind:NSValueBinding toObject:entry withKeyPath:@"binaryDesc" options:nil];
[[view imageView] setImage:[[NSWorkspace sharedWorkspace] iconForFileType:[entry.binaryDesc pathExtension]]];
}
return view;
}
- (NSTableRowView *)tableView:(NSTableView *)tableView rowViewForRow:(NSInteger)row {
HNHTableRowView *view = nil;
view = [[HNHTableRowView alloc] init];
view.selectionCornerRadius = 7;
return view;
}
@end

View File

@@ -0,0 +1,17 @@
//
// MPCustomFieldTableDelegate.h
// MacPass
//
// Created by Michael Starke on 17.07.13.
// Copyright (c) 2013 HicknHack Software GmbH. All rights reserved.
//
#import <Foundation/Foundation.h>
@class MPInspectorViewController;
@interface MPCustomFieldTableViewDelegate : NSObject <NSTableViewDelegate>
@property (nonatomic, weak) MPInspectorViewController *viewController;
@end

View File

@@ -0,0 +1,42 @@
//
// MPCustomFieldTableDelegate.m
// MacPass
//
// Created by Michael Starke on 17.07.13.
// Copyright (c) 2013 HicknHack Software GmbH. All rights reserved.
//
#import "MPCustomFieldTableViewDelegate.h"
#import "MPInspectorViewController.h"
#import "MPCustomFieldTableCellView.h"
#import "Kdb4Node.h"
#import "StringField+Undo.h"
@implementation MPCustomFieldTableViewDelegate
- (NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
if(![self.viewController.selectedEntry isKindOfClass:[Kdb4Entry class]]) {
return nil;
}
Kdb4Entry *entry = (Kdb4Entry *)self.viewController.selectedEntry;
MPCustomFieldTableCellView *view = [tableView makeViewWithIdentifier:@"SelectedCell" owner:tableView];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_customFieldFrameChanged:) name:NSViewFrameDidChangeNotification object:view];
if([self.viewController.selectedEntry isKindOfClass:[Kdb4Entry class]]) {
StringField *stringField = entry.stringFields[row];
NSDictionary *validateOptions = @{ NSValidatesImmediatelyBindingOption: @YES };
[view.labelTextField bind:NSValueBinding toObject:stringField withKeyPath:MPStringFieldKeyUndoableKey options:validateOptions];
[view.valueTextField bind:NSValueBinding toObject:stringField withKeyPath:MPStringFieldValueUndoableKey options:nil];
[view.removeButton setTarget:self.viewController];
[view.removeButton setAction:@selector(removeCustomField:)];
[view.removeButton setTag:row];
}
return view;
}
- (void)_customFieldFrameChanged:(NSNotification *)notification {
// NSView *sender = [notification object];
// NSLog(@"didChangeFrameFor: %@ to: %@", sender, NSStringFromRect([sender frame]));
}
@end

View File

@@ -0,0 +1,17 @@
//
// MPDatabaseSettingsDelegate.h
// MacPass
//
// Created by Michael Starke on 21.07.13.
// Copyright (c) 2013 HicknHack Software GmbH. All rights reserved.
//
#import <Foundation/Foundation.h>
@protocol MPDatabaseSettingsDelegate <NSObject>
@optional
- (void)didCancelDatabaseSettings;
- (void)didSaveDatabaseSettings;
@end

View File

@@ -0,0 +1,74 @@
//
// MPDocumentSettingsWindowController.h
// MacPass
//
// Created by Michael Starke on 26.06.13.
// Copyright (c) 2013 HicknHack Software GmbH. All rights reserved.
//
#import <Cocoa/Cocoa.h>
#import "MPDatabaseSettingsDelegate.h"
typedef NS_ENUM(NSUInteger, MPDatabaseSettingsTab) {
MPDatabaseSettingsTabGeneral,
MPDatabaseSettingsTabPassword,
MPDatabaseSettingsTabDisplay,
MPDatabaseSettingsTabAdvanced,
MPDatabaseSettingsTemplatesTab,
};
@class MPDocument;
@class HNHRoundendTextField;
@class HNHRoundedSecureTextField;
@interface MPDatabaseSettingsWindowController : NSWindowController <NSTextFieldDelegate, NSTabViewDelegate>
@property (nonatomic,weak) id<MPDatabaseSettingsDelegate> delegate;
@property (weak) IBOutlet NSTabView *sectionTabView;
@property (weak) IBOutlet NSButton *saveButton;
@property (weak) IBOutlet NSButton *cancelButton;
/* General Tab */
@property (weak) IBOutlet NSTextField *databaseNameTextField;
@property (unsafe_unretained) IBOutlet NSTextView *databaseDescriptionTextView;
/* Protection */
@property (weak) IBOutlet HNHRoundedSecureTextField *passwordTextField;
@property (weak) IBOutlet HNHRoundedSecureTextField *passwordRepeatTextField;
@property (weak) IBOutlet NSPathControl *keyfilePathControl;
@property (weak) IBOutlet NSButton *togglePasswordButton;
@property (weak) IBOutlet NSTextField *errorTextField;
- (IBAction)clearKey:(id)sender;
- (IBAction)generateKey:(id)sender;
/* Display Tab */
@property (weak) IBOutlet NSButton *protectTitleCheckButton;
@property (weak) IBOutlet NSButton *protectUserNameCheckButton;
@property (weak) IBOutlet NSButton *protectPasswortCheckButton;
@property (weak) IBOutlet NSButton *protectURLCheckButton;
@property (weak) IBOutlet NSButton *protectNotesCheckButton;
/* Advanced Tab*/
@property (weak) IBOutlet NSButton *enableRecycleBinCheckButton;
@property (weak) IBOutlet NSButton *emptyRecycleBinOnQuitCheckButton;
@property (weak) IBOutlet NSPopUpButton *selectRecycleBinGroupPopUpButton;
/* Templates Tab */
@property (weak) IBOutlet HNHRoundendTextField *defaultUsernameTextField;
@property (weak) IBOutlet NSPopUpButton *templateGroupPopUpButton;
- (id)initWithDocument:(MPDocument *)document;
- (void)showSettingsTab:(MPDatabaseSettingsTab)tab;
- (void)update;
@end

View File

@@ -0,0 +1,399 @@
//
// MPDocumentSettingsWindowController.m
// MacPass
//
// Created by Michael Starke on 26.06.13.
// Copyright (c) 2013 HicknHack Software GmbH. All rights reserved.
//
#import "MPDatabaseSettingsWindowController.h"
#import "MPDocument.h"
#import "MPDocumentWindowController.h"
#import "MPDatabaseVersion.h"
#import "MPIconHelper.h"
#import "MPSettingsHelper.h"
#import "HNHRoundedTextField.h"
#import "HNHRoundedSecureTextField.h"
#import "NSString+Empty.h"
#import "Kdb.h"
#import "Kdb4Node.h"
#import "KdbGroup+MPAdditions.h"
@interface MPDatabaseSettingsWindowController () {
MPDocument *_document;
NSString *_missingFeature;
}
@property (nonatomic,assign) BOOL trashEnabled;
@property (nonatomic,assign) BOOL showPassword;
@property (nonatomic,assign) BOOL hasValidPasswordOrKey;
@property (nonatomic,weak) NSURL *keyURL;
@end
@implementation MPDatabaseSettingsWindowController
- (id)init {
return [self initWithDocument:nil];
}
- (id)initWithDocument:(MPDocument *)document {
self = [super initWithWindowNibName:@"DatabaseSettingsWindow"];
if(self) {
_document = document;
_showPassword = NO;
_hasValidPasswordOrKey = NO;
_missingFeature = NSLocalizedString(@"KDBX_ONLX_FEATURE", "Feature only available in kdbx databases");
}
return self;
}
- (void)windowDidLoad {
[super windowDidLoad];
NSAssert(_document != nil, @"Document needs to be present");
[self.saveButton bind:NSEnabledBinding toObject:self withKeyPath:@"hasValidPasswordOrKey" options:nil];
[self.sectionTabView setDelegate:self];
[self update];
}
- (void)setDelegate:(id<MPDatabaseSettingsDelegate>)delegate {
if(_delegate != delegate) {
if([delegate conformsToProtocol:@protocol(MPDatabaseSettingsDelegate)]) {
_delegate = delegate;
}
else{
NSAssert(NO, @"Delegate needs to conform to MPDatabaseSettingsDelegate protocoll");
}
}
}
- (IBAction)save:(id)sender {
/* Protection */
_document.password = [self.passwordTextField stringValue];
_document.key = [self.keyfilePathControl URL];
/* General */
_document.treeV4.databaseDescription = [self.databaseDescriptionTextView string];
_document.treeV4.databaseName = [self.databaseNameTextField stringValue];
/* Display */
/* Advanced */
_document.treeV4.recycleBinEnabled = self.trashEnabled;
NSMenuItem *trashMenuItem = [self.selectRecycleBinGroupPopUpButton selectedItem];
KdbGroup *trashGroup = [trashMenuItem representedObject];
[_document useGroupAsTrash:trashGroup];
NSMenuItem *templateMenuItem = [self.templateGroupPopUpButton selectedItem];
KdbGroup *templateGroup = [templateMenuItem representedObject];
[_document useGroupAsTemplate:templateGroup];
BOOL protectNotes = [self.protectNotesCheckButton state] == NSOnState;
BOOL protectPassword = [self.protectPasswortCheckButton state] == NSOnState;
BOOL protectTitle = [self.protectTitleCheckButton state] == NSOnState;
BOOL protectURL = [self.protectURLCheckButton state] == NSOnState;
BOOL protectUsername = [self.protectUserNameCheckButton state] == NSOnState;
if(_document.version == MPDatabaseVersion4) {
_document.treeV4.protectNotes = protectNotes;
_document.treeV4.protectPassword = protectPassword;
_document.treeV4.protectTitle = protectTitle;
_document.treeV4.protectUrl = protectURL;
_document.treeV4.protectUserName = protectUsername;
}
else {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setBool:protectNotes forKey:kMPSettingsKeyLegacyHideNotes];
[defaults setBool:protectPassword forKey:kMPSettingsKeyLegacyHidePassword];
[defaults setBool:protectTitle forKey:kMPSettingsKeyLegacyHideTitle];
[defaults setBool:protectURL forKey:kMPSettingsKeyLegacyHideURL];
[defaults setBool:protectUsername forKey:kMPSettingsKeyLegacyHideUsername];
[defaults synchronize];
}
[self closeDidSave:YES];
}
- (IBAction)cancel:(id)sender {
[self closeDidSave:NO];
}
- (void)closeDidSave:(BOOL)didSave {
/* Remove the window first */
[NSApp endSheet:[self window]];
[[self window] orderOut:nil];
/* Then notify the delegate */
if(self.delegate) {
if(didSave && [self.delegate respondsToSelector:@selector(didSaveDatabaseSettings)]) {
[self.delegate didSaveDatabaseSettings];
}
else if(!didSave && [self.delegate respondsToSelector:@selector(didCancelDatabaseSettings)]) {
[self.delegate didCancelDatabaseSettings];
}
}
}
- (void)update {
/* Update all stuff that might have changed */
Kdb4Tree *tree = _document.treeV4;
[self _setupPasswordTab:tree];
[self _setupDatabase:tree];
[self _setupProtectionTab:tree];
[self _setupAdvancedTab:tree];
[self _setupTemplatesTab:tree];
}
- (void)showSettingsTab:(MPDatabaseSettingsTab)tab {
/*
We need to make sure the window is loaded
so we just call the the getter and led teh loading commence
*/
if(![self window]) {
return;
}
self.showPassword = NO;
NSTabViewItem *tabViewItem = [self.sectionTabView tabViewItemAtIndex:tab];
BOOL canSelectTab = [self tabView:self.sectionTabView shouldSelectTabViewItem:tabViewItem];
if(!canSelectTab) {
[self.sectionTabView selectTabViewItemAtIndex:MPDatabaseSettingsTabPassword];
}
[self.sectionTabView selectTabViewItemAtIndex:tab];
}
- (void)setShowPassword:(BOOL)showPassword {
if(_showPassword != showPassword) {
_showPassword = showPassword;
[self.passwordRepeatTextField setStringValue:@""];
[self _verifyPasswordAndKey];
}
}
- (void)setKeyURL:(NSURL *)keyURL {
_keyURL = keyURL;
[self _verifyPasswordAndKey];
}
#pragma mark Actions
- (IBAction)clearKey:(id)sender {
self.keyURL = nil;
}
- (IBAction)generateKey:(id)sender {
}
#pragma mark NSTextFieldDelegate
- (void)controlTextDidChange:(NSNotification *)obj {
[self _verifyPasswordAndKey];
}
#pragma mark NSTableViewDelegate
- (BOOL)tabView:(NSTabView *)tabView shouldSelectTabViewItem:(NSTabViewItem *)tabViewItem {
NSUInteger index = [tabView indexOfTabViewItem:tabViewItem];
switch ((MPDatabaseSettingsTab)index) {
case MPDatabaseSettingsTabPassword:
case MPDatabaseSettingsTabDisplay:
return YES;
case MPDatabaseSettingsTabAdvanced:
case MPDatabaseSettingsTabGeneral:
case MPDatabaseSettingsTemplatesTab:
return (_document.version == MPDatabaseVersion4);
default:
return NO;
}
}
#pragma mark Private Helper
- (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 = ![NSString isEmptyString:password];
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 setStringValue:NSLocalizedString(@"ERROR_NO_PASSWORD_OR_KEYFILE", "Missing Key or Password")];
return; // alldone
}
if(!passwordOk && !keyOk ) {
[self.errorTextField setStringValue:NSLocalizedString(@"ERROR_PASSWORD_MISSMATCH_INVALID_KEYFILE", "Passwords do not match, keyfile is invalid")];
}
else if(!passwordOk) {
[self.errorTextField setStringValue:NSLocalizedString(@"ERROR_PASSWORD_MISSMATCH", "Passwords do not match")];
}
else {
[self.errorTextField setStringValue:NSLocalizedString(@"ERROR_INVALID_KEYFILE", "Keyfile not valid")];
}
}
- (void)_setupDatabase:(Kdb4Tree *)tree {
BOOL isKdbx = (nil != tree);
[self.databaseDescriptionTextView setEditable:isKdbx];
[self.databaseNameTextField setEnabled:isKdbx];
if(isKdbx) {
[self.databaseNameTextField setStringValue:tree.databaseName];
[self.databaseDescriptionTextView setString:tree.databaseDescription];
}
else {
[self.databaseNameTextField setStringValue:_missingFeature];
[self.databaseDescriptionTextView setString:_missingFeature];
}
}
- (void)_setupProtectionTab:(Kdb4Tree *)tree {
BOOL isKdbX = (nil != tree);
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
BOOL protectNotes = isKdbX ? tree.protectNotes : [defaults boolForKey:kMPSettingsKeyLegacyHideNotes];
BOOL protectPassword = isKdbX ? tree.protectPassword : [defaults boolForKey:kMPSettingsKeyLegacyHidePassword];
BOOL protectTitle = isKdbX ? tree.protectTitle : [defaults boolForKey:kMPSettingsKeyLegacyHideTitle];
BOOL protectUrl = isKdbX ? tree.protectUrl : [defaults boolForKey:kMPSettingsKeyLegacyHideURL];
BOOL protectUsername = isKdbX ? tree.protectUserName : [defaults boolForKey:kMPSettingsKeyLegacyHideUsername];
[self.protectNotesCheckButton setState:protectNotes ? NSOnState : NSOffState ];
[self.protectPasswortCheckButton setState:protectPassword ? NSOnState : NSOffState];
[self.protectTitleCheckButton setState:protectTitle ? NSOnState : NSOffState];
[self.protectURLCheckButton setState:protectUrl ? NSOnState : NSOffState];
[self.protectUserNameCheckButton setState:protectUsername ? NSOnState : NSOffState];
}
- (void)_setupAdvancedTab:(Kdb4Tree *)tree {
BOOL isKdbX = (nil != tree);
self.trashEnabled = isKdbX ? tree.recycleBinEnabled : NO;
[self.enableRecycleBinCheckButton bind:NSValueBinding toObject:self withKeyPath:@"trashEnabled" options:nil];
[self.enableRecycleBinCheckButton setEnabled:isKdbX];
[self.selectRecycleBinGroupPopUpButton bind:NSEnabledBinding toObject:self withKeyPath:@"trashEnabled" options:nil];
if(isKdbX) {
[self _updateTrashFolders:tree];
}
}
- (void)_setupPasswordTab:(Kdb4Tree *)tree {
[self.passwordTextField setStringValue:_document.password ? _document.password : @""];
[self.passwordRepeatTextField setStringValue:[self.passwordTextField stringValue]];
self.keyURL = _document.key;
NSDictionary *negateOption = @{ NSValueTransformerNameBindingOption : NSNegateBooleanTransformerName };
[self.passwordTextField bind:@"showPassword" toObject:self withKeyPath:@"showPassword" options:nil];
[self.togglePasswordButton bind:NSValueBinding toObject:self withKeyPath:@"showPassword" options:nil];
[self.passwordRepeatTextField bind:NSEnabledBinding toObject:self withKeyPath:@"showPassword" options:negateOption];
[self.errorTextField bind:NSHiddenBinding toObject:self withKeyPath:@"hasValidPasswordOrKey" options:nil];
[self.keyfilePathControl bind:NSValueBinding toObject:self withKeyPath:@"keyURL" options:nil];
[self.passwordRepeatTextField setDelegate:self];
[self.passwordTextField setDelegate:self];
/* Manually initate the first check */
[self _verifyPasswordAndKey];
}
- (void)_setupTemplatesTab:(Kdb4Tree *)tree {
}
- (void)_updateFirstResponder {
NSTabViewItem *selected = [self.sectionTabView selectedTabViewItem];
MPDatabaseSettingsTab tab = [[self.sectionTabView tabViewItems] indexOfObject:selected];
switch(tab) {
case MPDatabaseSettingsTabAdvanced:
[[self window] makeFirstResponder:self.databaseNameTextField];
break;
case MPDatabaseSettingsTabDisplay:
[[self window] makeFirstResponder:self.protectTitleCheckButton];
break;
case MPDatabaseSettingsTabGeneral:
[[self window] makeFirstResponder:self.databaseNameTextField];
break;
case MPDatabaseSettingsTabPassword:
[[self window] makeFirstResponder:self.passwordTextField];
break;
case MPDatabaseSettingsTemplatesTab:
break;
}
}
- (void)_updateTrashFolders:(Kdb4Tree *)tree {
NSMenu *menu = [self _buildTrashTreeMenu:tree];
[self.selectRecycleBinGroupPopUpButton setMenu:menu];
}
- (void)_updateTemplateGroup:(Kdb4Tree *)tree {
//
}
- (NSMenu *)_buildTrashTreeMenu:(Kdb4Tree *)tree {
NSMenu *menu = [self _buildTreeMenu:tree];
NSMenuItem *selectItem = [[NSMenuItem alloc] initWithTitle:NSLocalizedString(@"AUTOCREATE_TRASH_FOLDER", @"Menu item for automatic trash creation")
action:NULL
keyEquivalent:@""];
[selectItem setEnabled:YES];
[menu insertItem:selectItem atIndex:0];
return menu;
}
- (NSMenu *)_buildTemplateTreeMenu:(Kdb4Tree *)tree {
NSMenu *menu = [self _buildTreeMenu:tree];
NSMenuItem *selectItem = [[NSMenuItem alloc] initWithTitle:NSLocalizedString(@"NO_TEMPLATE_GROUP", @"Menu item to reset the template groups")
action:NULL
keyEquivalent:@""];
[selectItem setEnabled:YES];
[menu insertItem:selectItem atIndex:0];
return menu;
}
- (NSMenu *)_buildTreeMenu:(Kdb4Tree *)tree {
NSMenu *menu = [[NSMenu alloc] init];
[menu setAutoenablesItems:NO];
for(Kdb4Group *group in tree.root.groups) {
NSMenuItem *groupItem = [[NSMenuItem alloc] init];
[groupItem setImage:group.icon];
[groupItem setTitle:group.name];
[groupItem setRepresentedObject:group];
[groupItem setEnabled:YES];
if([group.uuid isEqual:tree.recycleBinUuid]) {
[groupItem setState:NSOnState];
}
[menu addItem:groupItem];
}
return menu;
}
@end

View File

@@ -12,6 +12,7 @@
#import "NSData+Gzip.h"
#import "Kdb3Node.h"
#import "Kdb3Entry+KVOAdditions.h"
#import "Kdb4Node.h"
#import "Kdb4Entry+KVOAdditions.h"
@@ -31,14 +32,14 @@
}
entry.binary = binaryData;
entry.binaryDesc = fileName;
[entry insertObject:@"" inBinariesAtIndex:1];
}
if( [anEntry isKindOfClass:[Kdb4Entry class]]) {
Kdb4Entry *entry = (Kdb4Entry *)anEntry;
NSStringEncoding encoding;
NSString *fileContents = [NSString stringWithContentsOfURL:location usedEncoding:&encoding error:&error];
if(!fileContents) {
NSData *fileData = [NSData dataWithContentsOfURL:location options:NSDataReadingMappedIfSafe error:&error];
if(!fileData) {
[NSApp presentError:error];
fileContents = nil;
fileData = nil;
error = nil;
return; // failed
}
@@ -51,7 +52,6 @@
binary.binaryId = nextId;
binary.compressed = (self.treeV4.compressionAlgorithm != KPLCompressionNone);
NSData *encodedData;
NSData *fileData = [fileContents dataUsingEncoding:encoding];
if(binary.compressed) {
switch(self.treeV4.compressionAlgorithm) {
case KPLCompressionGzip: {
@@ -70,7 +70,7 @@
else {
encodedData = fileData;
}
binary.data = [[NSString alloc] initWithData:encodedData encoding:NSASCIIStringEncoding];
binary.data = [[NSString alloc] initWithData:encodedData encoding:NSUTF8StringEncoding];
[self.treeV4.binaries addObject:binary];
BinaryRef *ref = [[BinaryRef alloc] init];
@@ -80,17 +80,6 @@
}
}
- (void)saveAttachmentFromEntry:(KdbEntry *)anEntry toLocation:(NSURL *)location {
if([anEntry isKindOfClass:[Kdb3Entry class]]) {
Kdb3Entry *entry = (Kdb3Entry *)anEntry;
NSError *error = nil;
if(! [entry.binary writeToURL:location options:NSDataWritingWithoutOverwriting error:&error] ) {
[NSApp presentError:error];
}
}
return; //
}
- (void)removeAttachment:(BinaryRef *)reference fromEntry:(KdbEntry *)anEntry {
if(self.version != MPDatabaseVersion4) {
return; // Wrong Database version;
@@ -105,6 +94,14 @@
[self.treeV4.binaries removeObject:binary];
}
- (void)removeAttachmentFromEntry:(KdbEntry *)anEntry {
if(self.version != MPDatabaseVersion3) {
return;
}
Kdb3Entry *entry = (Kdb3Entry *)anEntry;
[entry removeObjectFromBinariesAtIndex:0];
}
- (Binary *)findBinary:(BinaryRef *)reference {
if(self.version != MPDatabaseVersion4) {
return nil;
@@ -117,22 +114,35 @@
return [filteredBinary lastObject];
}
- (void)saveAttachment:(BinaryRef *)reference toLocation:(NSURL *)location {
Binary *binary = [self findBinary:reference];
NSData *rawData = nil;
if(binary) {
if(binary.compressed) {
rawData = [NSMutableData mutableDataWithBase64DecodedData:[binary.data dataUsingEncoding:NSASCIIStringEncoding]];
rawData = [rawData gzipInflate];
}
else {
rawData = [NSMutableData mutableDataWithBase64DecodedData:[binary.data dataUsingEncoding:NSASCIIStringEncoding]];
}
- (void)saveAttachmentForItem:(id)item toLocation:(NSURL *)location {
if([item isKindOfClass:[Kdb3Entry class]]) {
Kdb3Entry *entry = (Kdb3Entry *)item;
NSError *error = nil;
if( ![rawData writeToURL:location options:0 error:&error] ) {
if(! [entry.binary writeToURL:location options:NSDataWritingAtomic error:&error] ) {
[NSApp presentError:error];
}
}
else if([item isKindOfClass:[BinaryRef class]]) {
Binary *binary = [self findBinary:item];
NSData *rawData = nil;
if(binary) {
if(binary.compressed) {
rawData = [NSMutableData mutableDataWithBase64DecodedData:[binary.data dataUsingEncoding:NSUTF8StringEncoding]];
rawData = [rawData gzipInflate];
}
else {
rawData = [NSMutableData mutableDataWithBase64DecodedData:[binary.data dataUsingEncoding:NSUTF8StringEncoding]];
}
NSError *error = nil;
if( ![rawData writeToURL:location options:NSDataWritingAtomic error:&error] ) {
[NSApp presentError:error];
}
}
}
else {
NSAssert(NO, @"Item is neither BinaryRef nor Kdb3Entry");
return;
}
}
- (NSUInteger)nextBinaryId {

View File

@@ -19,6 +19,8 @@ APPKIT_EXTERN NSString *const MPDocumentDidRevertNotifiation;
APPKIT_EXTERN NSString *const MPDocumentEntryKey;
APPKIT_EXTERN NSString *const MPDocumentGroupKey;
APPKIT_EXTERN NSString *const MPDocumentRequestPasswordSaveNotification;
@class KdbGroup;
@class KdbEntry;
@class KdbTree;
@@ -34,22 +36,28 @@ APPKIT_EXTERN NSString *const MPDocumentGroupKey;
@interface MPDocument : NSDocument
/* true, if password and/or keyfile are set */
@property (assign, readonly, getter = isSecured) BOOL secured;
@property (assign, readonly) BOOL hasPasswordOrKey;
/* true, if lock screen is present (no phyiscal locking) */
@property (assign, getter = isLocked) BOOL locked;
/* true, if document is loaded and decrypted (tree is loaded) */
@property (assign, readonly, getter = isDecrypted) BOOL decrypted;
@property (assign, nonatomic) BOOL locked;
@property (assign, readonly) BOOL decrypted;
@property (strong, readonly, nonatomic) KdbTree *tree;
@property (weak, readonly, nonatomic) KdbGroup *root;
@property (readonly, strong) MPRootAdapter *rootAdapter;
@property (nonatomic, strong) NSString *password;
@property (weak, readonly) KdbGroup *trash;
@property (nonatomic, copy) NSString *password;
@property (nonatomic, strong) NSURL *key;
@property (assign, readonly) MPDatabaseVersion version;
@property (assign, readonly, getter = isReadOnly) BOOL readOnly;
- (id)initWithVersion:(MPDatabaseVersion)version;
- (BOOL)decryptWithPassword:(NSString *)password keyFileURL:(NSURL *)keyFileURL;
#pragma mark Lock/Decrypt
- (void)lockDatabase:(id)sender;
- (BOOL)unlockWithPassword:(NSString *)password keyFileURL:(NSURL *)keyFileURL;
#pragma mark Data Lookup
/*
@@ -62,7 +70,12 @@ APPKIT_EXTERN NSString *const MPDocumentGroupKey;
- (Kdb3Tree *)treeV3;
- (void)useGroupAsTrash:(KdbGroup *)group;
- (void)useGroupAsTemplate:(KdbGroup *)group;
- (BOOL)isItemTrashed:(id)item;
#pragma mark Export
- (void)writeXMLToURL:(NSURL *)url;
#pragma mark Undo Data Manipulation
/* Undoable Intiialization of elements */
@@ -74,17 +87,12 @@ APPKIT_EXTERN NSString *const MPDocumentGroupKey;
All non-setter undoable actions
*/
- (void)moveGroup:(KdbGroup *)group toGroup:(KdbGroup *)target index:(NSInteger)index;
- (BOOL)group:(KdbGroup *)group isMoveableToGroup:(KdbGroup *)target;
- (void)moveEntry:(KdbEntry *)entry toGroup:(KdbGroup *)target index:(NSInteger)index;
/* TODO in UNDO auslagen */
- (void)addStringField:(StringField *)field toEntry:(Kdb4Entry *)entry atIndex:(NSUInteger)index;
- (void)removeStringField:(StringField *)field formEntry:(Kdb4Entry *)entry;
- (void)group:(KdbGroup *)group addEntry:(KdbEntry *)entry atIndex:(NSUInteger)index;
- (void)group:(KdbGroup *)group addGroup:(KdbGroup *)aGroup atIndex:(NSUInteger)index;
- (void)group:(KdbGroup *)group removeEntry:(KdbEntry *)entry;
- (void)group:(KdbGroup *)group removeGroup:(KdbGroup *)aGroup;
- (void)entry:(Kdb4Entry *)entry addStringField:(StringField *)field atIndex:(NSUInteger)index;
- (void)entry:(Kdb4Entry *)entry removeStringField:(StringField *)field;
- (void)deleteGroup:(KdbGroup *)group;
- (void)deleteEntry:(KdbEntry *)entry;
- (void)emptyTrash:(id)sender;
@@ -93,9 +101,12 @@ APPKIT_EXTERN NSString *const MPDocumentGroupKey;
@interface MPDocument (Attachments)
- (void)addAttachment:(NSURL *)location toEntry:(KdbEntry *)anEntry;
- (void)saveAttachmentFromEntry:(KdbEntry *)anEntry toLocation:(NSURL *)location;
- (void)saveAttachment:(BinaryRef *)reference toLocation:(NSURL *)location;
/**
item can be either a BinaryRef or an Kdb3Entry.
*/
- (void)saveAttachmentForItem:(id)item toLocation:(NSURL *)location;
- (void)removeAttachment:(BinaryRef *)reference fromEntry:(KdbEntry *)anEntry;
- (void)removeAttachmentFromEntry:(KdbEntry *)anEntry;
- (NSUInteger)nextBinaryId;
- (Binary *)findBinary:(BinaryRef *)reference;

View File

@@ -13,33 +13,46 @@
#import "MPRootAdapter.h"
#import "MPIconHelper.h"
#import "MPActionHelper.h"
#import "MPSettingsHelper.h"
#import "KdbLib.h"
#import "Kdb3Node.h"
#import "Kdb4Node.h"
#import "Kdb4Persist.h"
#import "KdbPassword.h"
#import "KdbGroup+Undo.h"
#import "KdbGroup+KVOAdditions.h"
#import "Kdb4Entry+KVOAdditions.h"
#import "KdbGroup+MPTreeTools.h"
#import "KdbGroup+MPAdditions.h"
#import "KdbEntry+Undo.h"
#import "KdbGroup+Undo.h"
#import "Kdb3Tree+NewTree.h"
#import "Kdb4Tree+NewTree.h"
#import "Kdb4Entry+MPAdditions.h"
#import "KdbGroup+MPTreeTools.h"
#import "KdbGroup+MPAdditions.h"
NSString *const MPDocumentDidAddGroupNotification = @"com.hicknhack.macpass.MPDocumentDidAddGroupNotification";
NSString *const MPDocumentWillDelteGroupNotification = @"com.hicknhack.macpass.MPDocumentDidDelteGroupNotification";
NSString *const MPDocumentDidAddEntryNotification = @"com.hicknhack.macpass.MPDocumentDidAddEntryNotification";
NSString *const MPDocumentWillDeleteEntryNotification = @"com.hicknhack.macpass.MPDocumentDidDeleteEntryNotification";
NSString *const MPDocumentDidRevertNotifiation = @"com.hicknhack.macpass.MPDocumentDidRevertNotifiation";
#import "DataOutputStream.h"
NSString *const MPDocumentEntryKey = @"MPDocumentEntryKey";
NSString *const MPDocumentGroupKey = @"MPDocumentGroupKey";
#import "DDXMLNode.h"
NSString *const MPDocumentDidAddGroupNotification = @"com.hicknhack.macpass.MPDocumentDidAddGroupNotification";
NSString *const MPDocumentWillDelteGroupNotification = @"com.hicknhack.macpass.MPDocumentDidDelteGroupNotification";
NSString *const MPDocumentDidAddEntryNotification = @"com.hicknhack.macpass.MPDocumentDidAddEntryNotification";
NSString *const MPDocumentWillDeleteEntryNotification = @"com.hicknhack.macpass.MPDocumentDidDeleteEntryNotification";
NSString *const MPDocumentDidRevertNotifiation = @"com.hicknhack.macpass.MPDocumentDidRevertNotifiation";
NSString *const MPDocumentRequestPasswordSaveNotification = @"com.hicknhack.macpass.MPDocumentRequestPasswordSaveNotification";
NSString *const MPDocumentEntryKey = @"MPDocumentEntryKey";
NSString *const MPDocumentGroupKey = @"MPDocumentGroupKey";
@interface MPDocument () {
@private
BOOL _didLockFile;
NSData *_fileData;
}
@@ -48,14 +61,15 @@ NSString *const MPDocumentGroupKey = @"MPDocumentGroupKey";
@property (weak, nonatomic, readonly) KdbPassword *passwordHash;
@property (assign) MPDatabaseVersion version;
@property (assign, nonatomic) BOOL secured;
@property (assign, nonatomic) BOOL hasPasswordOrKey;
@property (assign) BOOL decrypted;
@property (assign) BOOL readOnly;
@property (strong) NSURL *lockFileURL;
@property (readonly) BOOL useTrash;
@property (weak, readonly) KdbGroup *trash;
@property (strong) IBOutlet NSView *warningView;
@property (weak) IBOutlet NSImageView *warningViewImage;
@end
@@ -70,9 +84,10 @@ NSString *const MPDocumentGroupKey = @"MPDocumentGroupKey";
- (id)initWithVersion:(MPDatabaseVersion)version {
self = [super init];
if(self) {
_fileData = nil;
_didLockFile = NO;
_decrypted = YES;
_secured = NO;
_hasPasswordOrKey = NO;
_locked = NO;
_readOnly = NO;
_rootAdapter = [[MPRootAdapter alloc] init];
@@ -119,16 +134,21 @@ NSString *const MPDocumentGroupKey = @"MPDocumentGroupKey";
- (BOOL)readFromURL:(NSURL *)url ofType:(NSString *)typeName error:(NSError **)outError {
/* FIXME: Logfile handling
self.lockFileURL = [url URLByAppendingPathExtension:@"lock"];
if([[NSFileManager defaultManager] fileExistsAtPath:[_lockFileURL path]]) {
self.readOnly = YES;
}
else {
[[NSFileManager defaultManager] createFileAtPath:[_lockFileURL path] contents:nil attributes:nil];
_didLockFile = YES;
self.readOnly = NO;
}
self.lockFileURL = [url URLByAppendingPathExtension:@"lock"];
if([[NSFileManager defaultManager] fileExistsAtPath:[_lockFileURL path]]) {
self.readOnly = YES;
}
else {
[[NSFileManager defaultManager] createFileAtPath:[_lockFileURL path] contents:nil attributes:nil];
_didLockFile = YES;
self.readOnly = NO;
}
*/
/*
Delete our old Tree, and just grab the data
*/
self.tree = nil;
_fileData = [NSData dataWithContentsOfURL:url options:NSDataReadingUncached error:outError];
self.decrypted = NO;
return YES;
}
@@ -148,12 +168,26 @@ NSString *const MPDocumentGroupKey = @"MPDocumentGroupKey";
- (void)close {
[self _cleanupLock];
/*
We store the last url. Restored windows are automatically handeld.
If closeAllDocuments is set, all docs get this messgae
*/
if([[self fileURL] isFileURL]) {
[[NSUserDefaults standardUserDefaults] setObject:[self.fileURL absoluteString] forKey:kMPSettingsKeyLastDatabasePath];
}
[super close];
}
#pragma mark Protection
- (void)writeXMLToURL:(NSURL *)url {
DataOutputStream *outputStream = [[DataOutputStream alloc] init];
Kdb4Persist *persist = [[Kdb4Persist alloc] initWithTree:self.treeV4 outputStream:outputStream randomStream:nil];
[persist persistWithOptions:DDXMLNodeCompactEmptyElement|DDXMLNodePrettyPrint];
[outputStream.data writeToURL:url atomically:YES];
}
- (BOOL)decryptWithPassword:(NSString *)password keyFileURL:(NSURL *)keyFileURL {
#pragma mark Lock/Unlock/Decrypt
- (BOOL)unlockWithPassword:(NSString *)password keyFileURL:(NSURL *)keyFileURL {
self.key = keyFileURL;
self.password = [password length] > 0 ? password : nil;
@try {
@@ -173,17 +207,26 @@ NSString *const MPDocumentGroupKey = @"MPDocumentGroupKey";
return YES;
}
- (void)lockDatabase:(id)sender {
// Persist Tree into data
self.tree = nil;
self.locked = YES;
}
#pragma mark Custom Setter
- (void)setPassword:(NSString *)password {
if(![_password isEqualToString:password]) {
_password = password;
_secured |= ([_password length] > 0);
_password = [password copy];
[self _updateIsSecured];
}
}
- (void)setKey:(NSURL *)key {
if(![[_key absoluteString] isEqualToString:[key absoluteString]]) {
_key = key;
_secured |= (_key != nil);
[self _updateIsSecured];
}
}
@@ -197,6 +240,23 @@ NSString *const MPDocumentGroupKey = @"MPDocumentGroupKey";
return NO;
}
- (void)saveDocument:(id)sender {
if(self.hasPasswordOrKey) {
[super saveDocument:sender];
}
else {
[[NSNotificationCenter defaultCenter] postNotificationName:MPDocumentRequestPasswordSaveNotification object:self userInfo:nil];
}
}
- (BOOL)prepareSavePanel:(NSSavePanel *)savePanel {
if(self.hasPasswordOrKey) {
[savePanel setAccessoryView:nil];
return YES;
}
return NO;
}
#pragma mark Data Accesors
- (void)setTree:(KdbTree *)tree {
if(_tree != tree) {
@@ -220,7 +280,7 @@ NSString *const MPDocumentGroupKey = @"MPDocumentGroupKey";
- (Kdb3Tree *)treeV3 {
switch (_version) {
case MPDatabaseVersion3:
NSAssert([self.tree isKindOfClass:[Kdb3Tree class]], @"Tree has to be Version3");
NSAssert(self.tree == nil || [self.tree isKindOfClass:[Kdb3Tree class]], @"Tree has to be Version3");
return (Kdb3Tree *)self.tree;
case MPDatabaseVersion4:
return nil;
@@ -234,7 +294,7 @@ NSString *const MPDocumentGroupKey = @"MPDocumentGroupKey";
case MPDatabaseVersion3:
return nil;
case MPDatabaseVersion4:
NSAssert([self.tree isKindOfClass:[Kdb4Tree class]], @"Tree has to be Version4");
NSAssert(self.tree == nil || [self.tree isKindOfClass:[Kdb4Tree class]], @"Tree has to be Version4");
return (Kdb4Tree *)self.tree;
default:
return nil;
@@ -260,6 +320,26 @@ NSString *const MPDocumentGroupKey = @"MPDocumentGroupKey";
return nil;
}
- (BOOL)isItemTrashed:(id)item {
BOOL validItem = [item isKindOfClass:[KdbEntry class]] || [item isKindOfClass:[KdbGroup class]];
if(!item) {
return NO;
}
if(item == self.trash) {
return NO; // No need to look further as this is the trashcan
}
if(validItem) {
BOOL isTrashed = NO;
id parent = [item parent];
while( parent && !isTrashed ) {
isTrashed = (parent == self.trash);
parent = [parent parent];
}
return isTrashed;
}
return NO;
}
- (void)useGroupAsTrash:(KdbGroup *)group {
if(self.useTrash) {
Kdb4Group *groupv4 = (Kdb4Group *)group;
@@ -269,17 +349,30 @@ NSString *const MPDocumentGroupKey = @"MPDocumentGroupKey";
}
}
- (void)useGroupAsTemplate:(KdbGroup *)group {
Kdb4Group *groupv4 = (Kdb4Group *)group;
if([self.treeV4.entryTemplatesGroup isEqual:groupv4.uuid]) {
self.treeV4.entryTemplatesGroup = groupv4.uuid;
}
}
#pragma mark Data manipulation
- (KdbEntry *)createEntry:(KdbGroup *)parent {
if(!parent) {
return nil; // No parent
}
if(parent == self.trash) {
return nil; // no new Groups in trash
}
if([self isItemTrashed:parent]) {
return nil;
}
KdbEntry *newEntry = [self.tree createEntry:parent];
newEntry.title = NSLocalizedString(@"DEFAULT_ENTRY_TITLE", @"Title for a newly created entry");
if(self.treeV4 && ([self.treeV4.defaultUserName length] > 0)) {
newEntry.title = self.treeV4.defaultUserName;
}
[self group:parent addEntry:newEntry atIndex:[parent.entries count]];
[parent addEntryUndoable:newEntry atIndex:[parent.entries count]];
NSDictionary *userInfo = @{ MPDocumentEntryKey : newEntry };
[[NSNotificationCenter defaultCenter] postNotificationName:MPDocumentDidAddEntryNotification object:self userInfo:userInfo];
return newEntry;
@@ -289,10 +382,16 @@ NSString *const MPDocumentGroupKey = @"MPDocumentGroupKey";
if(!parent) {
return nil; // no parent!
}
if(parent == self.trash) {
return nil; // no new Groups in trash
}
if([self isItemTrashed:parent]) {
return nil;
}
KdbGroup *newGroup = [self.tree createGroup:parent];
newGroup.name = NSLocalizedString(@"DEFAULT_GROUP_NAME", @"Title for a newly created group");
newGroup.image = MPIconFolder;
[self group:parent addGroup:newGroup atIndex:[parent.groups count]];
[parent addGroupUndoable:newGroup atIndex:[parent.groups count]];
NSDictionary *userInfo = @{ MPDocumentGroupKey : newGroup };
[[NSNotificationCenter defaultCenter] postNotificationName:MPDocumentDidAddGroupNotification object:self userInfo:userInfo];
return newGroup;
@@ -306,154 +405,104 @@ NSString *const MPDocumentGroupKey = @"MPDocumentGroupKey";
Kdb4Entry *entryV4 = (Kdb4Entry *)entry;
NSString *title = NSLocalizedString(@"DEFAULT_CUSTOM_FIELD_TITLE", @"Default Titel for new Custom-Fields");
NSString *value = NSLocalizedString(@"DEFAULT_CUSTOM_FIELD_VALUE", @"Default Value for new Custom-Fields");
title = [entryV4 uniqueKeyForProposal:title];
StringField *newStringField = [StringField stringFieldWithKey:title andValue:value];
[self entry:entryV4 addStringField:newStringField atIndex:[entryV4.stringFields count]];
[self addStringField:newStringField toEntry:entryV4 atIndex:[entryV4.stringFields count]];
return newStringField;
}
- (void)moveGroup:(KdbGroup *)group toGroup:(KdbGroup *)target index:(NSInteger)index {
NSInteger oldIndex = [group.parent.groups indexOfObject:group];
if(group.parent == target && oldIndex == index) {
return; // No changes
}
[[[self undoManager] prepareWithInvocationTarget:self] moveGroup:group toGroup:group.parent index:oldIndex];
if(self.trash == target) {
[[self undoManager] setActionName:@"UNDO_DELETE_GROUP"];
}
else {
[[self undoManager] setActionName:@"MOVE_GROUP"];
}
[group.parent removeObjectFromGroupsAtIndex:oldIndex];
if(index < 0 || index > [target.groups count] ) {
index = [target.groups count];
}
[target insertObject:group inGroupsAtIndex:index];
}
- (BOOL)group:(KdbGroup *)group isMoveableToGroup:(KdbGroup *)target {
if(target == nil) {
return NO;
}
BOOL isMovable = YES;
KdbGroup *ancestor = target.parent;
while(ancestor.parent) {
if(ancestor == group) {
isMovable = NO;
break;
}
ancestor = ancestor.parent;
}
return isMovable;
}
- (void)moveEntry:(KdbEntry *)entry toGroup:(KdbGroup *)target index:(NSInteger)index {
NSInteger oldIndex = [entry.parent.entries indexOfObject:entry];
if(entry.parent == target && oldIndex == index) {
return; // No changes
}
[[[self undoManager] prepareWithInvocationTarget:self] moveEntry:entry toGroup:entry.parent index:oldIndex];
if(self.trash == target || self.trash == entry.parent) {
[[self undoManager] setActionName:@"UNDO_DELETE_ENTRY"];
}
else {
[[self undoManager] setActionName:@"MOVE_ENTRY"];
}
[entry.parent removeObjectFromEntriesAtIndex:oldIndex];
if(index < 0 || index > [target.groups count] ) {
index = [target.groups count];
}
[target insertObject:entry inEntriesAtIndex:index];
}
- (void)group:(KdbGroup *)group addEntry:(KdbEntry *)entry atIndex:(NSUInteger)index {
[[[self undoManager] prepareWithInvocationTarget:self] group:group removeEntry:entry];
[[self undoManager] setActionName:NSLocalizedString(@"UNDO_ADD_ENTRY", "Undo adding of entry")];
[group insertObject:entry inEntriesAtIndex:index];
}
- (void)group:(KdbGroup *)group addGroup:(KdbGroup *)aGroup atIndex:(NSUInteger)index {
[[[self undoManager] prepareWithInvocationTarget:self] group:group removeGroup:aGroup];
[[self undoManager] setActionName:NSLocalizedString(@"UNDO_ADD_GROUP", @"Create Group Undo")];
[group insertObject:aGroup inGroupsAtIndex:index];
}
- (void)group:(KdbGroup *)group removeEntry:(KdbEntry *)entry {
NSInteger index = [group.entries indexOfObject:entry];
if(NSNotFound == index) {
return; // No object found;
}
- (void)deleteEntry:(KdbEntry *)entry {
if(self.useTrash) {
if(!self.trash) {
[self _createTrashGroup];
}
[self moveEntry:entry toGroup:self.trash index:[self.trash.entries count]];
return;
if([self isItemTrashed:entry]) {
return; // Entry is already trashed
}
[entry moveToTrashUndoable:self.trash atIndex:[self.trash.entries count]];
}
else {
[entry deleteUndoable];
}
[[[self undoManager] prepareWithInvocationTarget:self] group:group addEntry:entry atIndex:index];
[[self undoManager] setActionName:NSLocalizedString(@"UNDO_DELETE_ENTRY", "Undo deleting of entry")];
[group removeObjectFromEntriesAtIndex:index];
}
- (void)group:(KdbGroup *)group removeGroup:(KdbGroup *)aGroup {
NSInteger index = [group.groups indexOfObject:aGroup];
if(NSNotFound == index) {
return; // No object found
}
if(self.trash == aGroup) {
return;
// delete Trash?
}
/*
Cleaning the recyclebin is not undoable
So we do this in a separate action
*/
- (void)deleteGroup:(KdbGroup *)group {
if(self.useTrash) {
if(!self.trash) {
[self _createTrashGroup];
}
[self moveGroup:aGroup toGroup:self.trash index:[self.trash.groups count]];
return; // Done!
if( (group == self.trash) || [self isItemTrashed:group] ) {
return; //Groups already trashed cannot be deleted
}
[group moveToTrashUndoable:self.trash atIndex:[self.trash.groups count]];
}
else {
[group deleteUndoable];
}
[[[self undoManager] prepareWithInvocationTarget:self] group:group addGroup:aGroup atIndex:index];
[[self undoManager] setActionName:NSLocalizedString(@"UNDO_DELETE_GROUP", @"Delete Group Undo")];
[group removeObjectFromGroupsAtIndex:index];
}
- (void)entry:(Kdb4Entry *)entry addStringField:(StringField *)field atIndex:(NSUInteger)index {
[[[self undoManager] prepareWithInvocationTarget:self] entry:entry removeStringField:field];
#pragma mark CustomFields
- (void)addStringField:(StringField *)field toEntry:(Kdb4Entry *)entry atIndex:(NSUInteger)index {
[[[self undoManager] prepareWithInvocationTarget:self] removeStringField:field formEntry:entry];
[[self undoManager] setActionName:NSLocalizedString(@"UNDO_ADD_STRING_FIELD", @"Add Stringfield Undo")];
field.entry = entry;
[entry insertObject:field inStringFieldsAtIndex:index];
}
- (void)entry:(Kdb4Entry *)entry removeStringField:(StringField *)field {
- (void)removeStringField:(StringField *)field formEntry:(Kdb4Entry *)entry {
NSInteger index = [entry.stringFields indexOfObject:field];
if(NSNotFound == index) {
return; // Nothing found to be removed
}
[[[self undoManager] prepareWithInvocationTarget:self] entry:entry addStringField:field atIndex:index];
[[[self undoManager] prepareWithInvocationTarget:self] addStringField:field toEntry:entry atIndex:index];
[[self undoManager] setActionName:NSLocalizedString(@"UNDO_DELETE_STRING_FIELD", @"Delte Stringfield undo")];
field.entry = nil;
[entry removeObjectFromStringFieldsAtIndex:index];
}
#pragma mark Actions
- (void)emptyTrash:(id)sender {
[[self undoManager] setActionIsDiscardable:YES];
[self.trash clear];
if(self.version != MPDatabaseVersion4) {
return; // We have no trash on those file types
}
NSAlert *alert = [[NSAlert alloc] init];
[alert setAlertStyle:NSWarningAlertStyle];
[alert setMessageText:NSLocalizedString(@"WARNING_ON_EMPTY_TRASH_TITLE", "")];
[alert setInformativeText:NSLocalizedString(@"WARNING_ON_EMPTY_TRASH_DESCRIPTION", "Informative Text displayed when clearing the Trash")];
[alert addButtonWithTitle:NSLocalizedString(@"EMPTY_TRASH", "Empty Trash")];
[alert addButtonWithTitle:NSLocalizedString(@"CANCEL", "Cancel")];
[[alert buttons][1] setKeyEquivalent:[NSString stringWithFormat:@"%c", 0x1b]];
NSWindow *window = [[self windowControllers][0] window];
[alert beginSheetModalForWindow:window modalDelegate:self didEndSelector:@selector(alertDidEnd:returnCode:contextInfo:) contextInfo:NULL];
}
- (BOOL)validateMenuItem:(NSMenuItem *)menuItem {
if([menuItem action] == [MPActionHelper actionOfType:MPActionEmptyTrash]) {
- (void) alertDidEnd:(NSAlert *)alert returnCode:(NSInteger)returnCode contextInfo:(void *)contextInfo {
if(returnCode == NSAlertFirstButtonReturn) {
[self _emptyTrash];
}
}
- (BOOL)validateUserInterfaceItem:(id<NSValidatedUserInterfaceItem>)anItem {
if([anItem action] == [MPActionHelper actionOfType:MPActionEmptyTrash]) {
BOOL hasGroups = [self.trash.groups count] > 0;
BOOL hasEntries = [self.trash.entries count] > 0;
return (hasEntries || hasGroups);
}
return YES;
return [super validateUserInterfaceItem:anItem];
}
#pragma mark Private
- (void)_updateIsSecured {
BOOL securePassword = ([self.password length] > 0);
BOOL secureKey = (nil != self.key);
self.hasPasswordOrKey = (secureKey || securePassword);
}
- (void)_cleanupLock {
if(_didLockFile) {
[[NSFileManager defaultManager] removeItemAtURL:_lockFileURL error:nil];
@@ -468,7 +517,7 @@ NSString *const MPDocumentGroupKey = @"MPDocumentGroupKey";
}
else if(self.version == MPDatabaseVersion4) {
KdbGroup *trash = [self.tree createGroup:self.tree.root];
trash.name = NSLocalizedString(@"TRASH_GROUP", @"Name for the trash group");
trash.name = NSLocalizedString(@"TRASH", @"Name for the trash group");
trash.image = MPIconTrash;
[self.tree.root insertObject:trash inGroupsAtIndex:[self.tree.root.groups count]];
self.treeV4.recycleBinUuid = ((Kdb4Group *)trash).uuid;
@@ -480,4 +529,31 @@ NSString *const MPDocumentGroupKey = @"MPDocumentGroupKey";
}
}
- (void)_emptyTrash {
for(KdbEntry *entry in [self.trash childEntries]) {
[[self undoManager] removeAllActionsWithTarget:entry];
}
for(KdbGroup *group in [self.trash childGroups]) {
[[self undoManager] removeAllActionsWithTarget:group];
}
[self _cleanTrashedBinaries];
[self.trash clear];
}
- (void)_cleanTrashedBinaries {
NSMutableSet *clearKeys = [[NSMutableSet alloc] initWithCapacity:20];
NSMutableArray *clearBinaries = [[NSMutableArray alloc] initWithCapacity:[self.treeV4.binaries count]];
for(Kdb4Entry *entry in [self.trash childEntries]) {
for(BinaryRef *binaryRef in entry.binaries) {
[clearKeys addObject:@(binaryRef.ref)];
}
}
for(Binary *binary in self.treeV4.binaries) {
if([clearKeys containsObject:@(binary.binaryId)]) {
[clearBinaries addObject:binary];
}
}
[self.treeV4.binaries removeObjectsInArray:clearBinaries];
}
@end

View File

@@ -1,42 +0,0 @@
//
// MPDocumentSettingsWindowController.h
// MacPass
//
// Created by Michael Starke on 26.06.13.
// Copyright (c) 2013 HicknHack Software GmbH. All rights reserved.
//
#import <Cocoa/Cocoa.h>
@class MPDocument;
@interface MPDocumentSettingsWindowController : NSWindowController
@property (weak) IBOutlet NSTabView *sectionTabView;
/* General Tab */
@property (weak) IBOutlet NSTextField *databaseNameTextField;
@property (unsafe_unretained) IBOutlet NSTextView *databaseDescriptionTextView;
/* Protection */
@property (weak) IBOutlet NSTextField *passwordTextField;
@property (weak) IBOutlet NSPathControl *keyfilePathControl;
/* Display Tab */
@property (weak) IBOutlet NSButton *protectTitleCheckButton;
@property (weak) IBOutlet NSButton *protectUserNameCheckButton;
@property (weak) IBOutlet NSButton *protectPasswortCheckButton;
@property (weak) IBOutlet NSButton *protectURLCheckButton;
@property (weak) IBOutlet NSButton *protectNotesCheckButton;
/* Advanced Tab*/
@property (weak) IBOutlet NSButton *enableRecycleBinCheckButton;
@property (weak) IBOutlet NSButton *emptyRecycleBinOnQuitCheckButton;
@property (weak) IBOutlet NSPopUpButton *selectRecycleBinGroupPopUpButton;
- (id)initWithDocument:(MPDocument *)document;
- (void)update;
@end

View File

@@ -1,128 +0,0 @@
//
// MPDocumentSettingsWindowController.m
// MacPass
//
// Created by Michael Starke on 26.06.13.
// Copyright (c) 2013 HicknHack Software GmbH. All rights reserved.
//
#import "MPDocumentSettingsWindowController.h"
#import "MPDocument.h"
#import "MPDocumentWindowController.h"
#import "MPDatabaseVersion.h"
#import "MPIconHelper.h"
#import "Kdb.h"
#import "Kdb4Node.h"
#import "KdbGroup+MPAdditions.h"
@interface MPDocumentSettingsWindowController () {
MPDocument *_document;
}
@end
@implementation MPDocumentSettingsWindowController
- (id)init {
return [self initWithDocument:nil];
}
- (id)initWithDocument:(MPDocument *)document {
self = [super initWithWindowNibName:@"DocumentSettingsWindow"];
if(self) {
_document = document;
}
return self;
}
- (void)windowDidLoad {
[super windowDidLoad];
NSAssert(_document != nil, @"Document needs to be present");
Kdb4Tree *tree = _document.treeV4;
if( tree ) {
[self _setupDatabase:tree];
[self _setupProtectionTab:tree];
[self _setupAdvancedTab:tree];
[self _setupPasswordTab:tree];
}
else {
// Switch to KdbV3 View
}
}
- (IBAction)close:(id)sender {
[NSApp endSheet:[self window]];
[[self window] orderOut:nil];
}
- (void)update {
/* Update all stuff that might have changed */
Kdb4Tree *tree = _document.treeV4;
if(tree) {
[self _updateTrashFolders:tree];
}
}
#pragma mark Private Helper
- (void)_setupDatabase:(Kdb4Tree *)tree {
[self.databaseNameTextField bind:NSValueBinding toObject:tree withKeyPath:@"databaseName" options:nil];
[self.databaseDescriptionTextView bind:NSValueBinding toObject:tree withKeyPath:@"databaseDescription" options:nil];
}
- (void)_setupProtectionTab:(Kdb4Tree *)tree {
[self.protectNotesCheckButton bind:NSValueBinding toObject:tree withKeyPath:@"protectNotes" options:nil];
[self.protectPasswortCheckButton bind:NSValueBinding toObject:tree withKeyPath:@"protectPassword" options:nil];
[self.protectTitleCheckButton bind:NSValueBinding toObject:tree withKeyPath:@"protectTitle" options:nil];
[self.protectURLCheckButton bind:NSValueBinding toObject:tree withKeyPath:@"protectUrl" options:nil];
[self.protectUserNameCheckButton bind:NSValueBinding toObject:tree withKeyPath:@"protectUserName" options:nil];
}
- (void)_setupAdvancedTab:(Kdb4Tree *)tree {
[self.enableRecycleBinCheckButton bind:NSValueBinding toObject:tree withKeyPath:@"recycleBinEnabled" options:nil];
[self.selectRecycleBinGroupPopUpButton bind:NSEnabledBinding toObject:tree withKeyPath:@"recycleBinEnabled" options:nil];
[self _updateTrashFolders:tree];
}
- (void)_setupPasswordTab:(Kdb4Tree *)tree {
}
- (void)_didSelectTrashFolder:(id)sender {
NSMenuItem *menuItem = sender;
/* if we do not get a group, use nil to reset the trash */
KdbGroup *group = [menuItem representedObject];
[_document useGroupAsTrash:group];
}
- (void)_updateTrashFolders:(Kdb4Tree *)tree {
NSMenu *menu = [self _buildTreeMenu:tree];
[self.selectRecycleBinGroupPopUpButton setMenu:menu];
}
- (NSMenu *)_buildTreeMenu:(Kdb4Tree *)tree {
NSMenu *menu = [[NSMenu alloc] init];
for(Kdb4Group *group in tree.root.groups) {
NSMenuItem *groupItem = [[NSMenuItem alloc] init];
[groupItem setImage:group.icon];
[groupItem setTitle:group.name];
[groupItem setAction:@selector(_didSelectTrashFolder:)];
[groupItem setTarget:self];
[groupItem setRepresentedObject:group];
if([group.uuid isEqual:tree.recycleBinUuid]) {
[groupItem setState:NSOnState];
}
[menu addItem:groupItem];
}
NSMenuItem *selectItem = [[NSMenuItem alloc] initWithTitle:NSLocalizedString(@"SELECT_RECYCLEBIN", @"Menu item if no reycleBin is selected") action:NULL keyEquivalent:@""];
[selectItem setAction:@selector(_didSelectTrashFolder:)];
[selectItem setTarget:self];
[menu insertItem:selectItem atIndex:0];
return menu;
}
@end

View File

@@ -7,11 +7,11 @@
//
#import <Cocoa/Cocoa.h>
#import "MPDatabaseSettingsDelegate.h"
@class MPViewController;
@class MPEntryViewController;
@class MPInspectorViewController;
@class MPPasswordEditViewController;
@class MPPasswordInputController;
@class MPOutlineViewController;
@@ -20,10 +20,9 @@
APPKIT_EXTERN NSString *const MPCurrentItemChangedNotification;
@interface MPDocumentWindowController : NSWindowController <NSWindowDelegate>
@interface MPDocumentWindowController : NSWindowController <NSWindowDelegate, MPDatabaseSettingsDelegate>
@property (readonly, strong) MPPasswordInputController *passwordInputController;
@property (readonly, strong) MPPasswordEditViewController *passwordEditController;
@property (readonly, strong) MPEntryViewController *entryViewController;
@property (readonly, strong) MPOutlineViewController *outlineViewController;
@property (readonly, strong) MPInspectorViewController *inspectorViewController;
@@ -34,14 +33,21 @@ APPKIT_EXTERN NSString *const MPCurrentItemChangedNotification;
@property (readonly, unsafe_unretained) KdbGroup *currentGroup;
@property (readonly, unsafe_unretained) KdbEntry *currentEntry;
/**
@param action The action that should be validatet
@param item The item that the action affects. Pass nil to fall back for default item
@returns YES if the action is valid, NO otherwise
*/
- (BOOL)validateAction:(SEL)action forItem:(id)item;
- (void)showEntries;
- (void)showPasswordInput;
- (void)performFindPanelAction:(id)sender;
- (IBAction)editPassword:(id)sender;
- (IBAction)showDocumentSettings:(id)sender;
- (IBAction)showDatabaseSettings:(id)sender;
- (IBAction)exportDatabase:(id)sender;
- (void)lock:(id)sender;
- (IBAction)lock:(id)sender;
- (void)createGroup:(id)sender;
- (void)toggleInspector:(id)sender;

View File

@@ -10,20 +10,21 @@
#import "MPDocument.h"
#import "MPPasswordInputController.h"
#import "MPEntryViewController.h"
#import "MPPasswordEditViewController.h"
#import "MPToolbarDelegate.h"
#import "MPOutlineViewController.h"
#import "MPInspectorViewController.h"
#import "MPAppDelegate.h"
#import "MPActionHelper.h"
#import "MPDocumentSettingsWindowController.h"
#import "MPDatabaseSettingsWindowController.h"
#import "MPConstants.h"
#import "MPSettingsHelper.h"
NSString *const MPCurrentItemChangedNotification = @"com.hicknhack.macpass.MPCurrentItemChangedNotification";
@interface MPDocumentWindowController () {
@private
id _firstResponder;
BOOL _saveAfterPasswordEdit; // Flag to indicat that the document needs to be saved after password edit did finish
}
@property (strong) IBOutlet NSSplitView *splitView;
@@ -34,11 +35,10 @@ NSString *const MPCurrentItemChangedNotification = @"com.hicknhack.macpass.MPCur
@property (unsafe_unretained) KdbEntry *currentEntry;
@property (strong) MPPasswordInputController *passwordInputController;
@property (strong) MPPasswordEditViewController *passwordEditController;
@property (strong) MPEntryViewController *entryViewController;
@property (strong) MPOutlineViewController *outlineViewController;
@property (strong) MPInspectorViewController *inspectorViewController;
@property (strong) MPDocumentSettingsWindowController *documentSettingsWindowController;
@property (strong) MPDatabaseSettingsWindowController *documentSettingsWindowController;
@property (strong) MPToolbarDelegate *toolbarDelegate;
@@ -52,10 +52,10 @@ NSString *const MPCurrentItemChangedNotification = @"com.hicknhack.macpass.MPCur
_firstResponder = nil;
_toolbarDelegate = [[MPToolbarDelegate alloc] init];
_outlineViewController = [[MPOutlineViewController alloc] init];
_passwordEditController = [[MPPasswordEditViewController alloc] init];
_entryViewController = [[MPEntryViewController alloc] init];
_inspectorViewController = [[MPInspectorViewController alloc] init];
_currentItem = nil;
_saveAfterPasswordEdit = NO;
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_updateCurrentItem:) name:MPOutlineViewDidChangeGroupSelection object:_outlineViewController];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_updateCurrentItem:) name:MPDidChangeSelectedEntryNotification object:_entryViewController];
@@ -65,15 +65,13 @@ NSString *const MPCurrentItemChangedNotification = @"com.hicknhack.macpass.MPCur
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
#pragma mark View Handling
- (void)windowDidLoad {
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_didRevertDocument:) name:MPDocumentDidRevertNotifiation object:[self document]];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_setPasswordAndSave) name:MPDocumentRequestPasswordSaveNotification object:[self document]];
[_entryViewController setupNotifications:self];
[_inspectorViewController setupNotifications:self];
@@ -97,15 +95,22 @@ NSString *const MPCurrentItemChangedNotification = @"com.hicknhack.macpass.MPCur
[_splitView setHoldingPriority:NSLayoutPriorityDefaultLow+2 forSubviewAtIndex:0];
[_splitView setHoldingPriority:NSLayoutPriorityDefaultLow+1 forSubviewAtIndex:2];
BOOL showInspector = [[NSUserDefaults standardUserDefaults] boolForKey:kMPSettingsKeyShowInspector];
if(!showInspector) {
[inspectorView removeFromSuperview];
}
[[self window] setDelegate:self];
MPDocument *document = [self document];
if(!document.isDecrypted) {
if(!document.decrypted) {
[self showPasswordInput];
}
else {
[self showEntries];
}
[_splitView setAutosaveName:@"SplitView"];
}
- (void)_setContentViewController:(MPViewController *)viewController {
@@ -165,34 +170,93 @@ NSString *const MPCurrentItemChangedNotification = @"com.hicknhack.macpass.MPCur
}
#pragma mark Actions
- (void)exportDatabase:(id)sender {
NSSavePanel *savePanel = [NSSavePanel savePanel];
[savePanel setAllowsOtherFileTypes:YES];
[savePanel beginSheetModalForWindow:self.window completionHandler:^(NSInteger result) {
if(result == NSFileHandlingPanelOKButton) {
[[self document] writeXMLToURL:savePanel.URL];
}
}];
}
- (void)performFindPanelAction:(id)sender {
[self.entryViewController showFilter:sender];
}
- (BOOL)validateMenuItem:(NSMenuItem *)menuItem {
MPDocument *document = [self document];
return !( document.isLocked || document.isReadOnly );
SEL itemAction = [menuItem action];
if(itemAction == @selector(showDatabaseSettings:)
|| itemAction == @selector(editPassword:)) {
return document.decrypted && !document.isLocked;
}
BOOL enabled = YES;
if(itemAction == @selector(exportDatabase:)) {
enabled = (nil != document.treeV4);
}
if(itemAction == [MPActionHelper actionOfType:MPActionDelete]) {
enabled &= (nil != _currentItem) && (_currentItem != document.trash);
}
enabled &= !( !document.decrypted || document.isLocked || document.isReadOnly );
return enabled;
}
- (BOOL)validateToolbarItem:(NSToolbarItem *)theItem {
MPDocument *document = [self document];
if(document.isLocked || document.isReadOnly) {
if(!document.decrypted || document.isLocked || document.isReadOnly) {
return NO;
}
SEL itemAction = [theItem action];
if( itemAction == [MPActionHelper actionOfType:MPActionLock]) {
return document.isSecured;
MPActionType actionType = [MPActionHelper typeForAction:[theItem action]];
switch (actionType) {
case MPActionAddGroup:
case MPActionAddEntry:
return (nil != _outlineViewController.selectedGroup);
case MPActionDelete: {
BOOL valid = (nil != _currentItem);
valid &= (_currentItem != document.trash);
valid &= ![document isItemTrashed:_currentItem];
return valid;
}
case MPActionLock:
return document.hasPasswordOrKey;
case MPActionToggleInspector:
return (nil != [_splitView superview]);
default:
return YES;
}
if(itemAction == [MPActionHelper actionOfType:MPActionAddEntry]) {
return (nil != _outlineViewController.selectedGroup);
return YES;
}
- (BOOL)validateAction:(SEL)action forItem:(id)item {
MPDocument *document = [self document];
if(!document.decrypted || document.isLocked || document.isReadOnly) {
return NO;
}
if(itemAction == [MPActionHelper actionOfType:MPActionDelete]) {
return (nil != _currentItem);
MPActionType actionType = [MPActionHelper typeForAction:action];
switch (actionType) {
case MPActionAddGroup:
case MPActionAddEntry:
// test if Group is in trash
return (nil != _outlineViewController.selectedGroup);
case MPActionDelete: {
BOOL valid = (nil != _currentItem);
valid &= (_currentItem != document.trash);
valid &= ![document isItemTrashed:_currentItem];
return valid;
}
case MPActionLock:
return document.hasPasswordOrKey;
case MPActionToggleInspector:
return (nil != [_splitView superview]);
default:
return YES;
}
if(itemAction == [MPActionHelper actionOfType:MPActionToggleInspector]) {
return (nil != [_splitView superview]);
}
return YES;
}
@@ -205,23 +269,16 @@ NSString *const MPCurrentItemChangedNotification = @"com.hicknhack.macpass.MPCur
}
- (void)editPassword:(id)sender {
if(!self.passwordEditController) {
_passwordEditController = [[MPPasswordEditViewController alloc] init];
}
[self _setContentViewController:self.passwordEditController];
[self _showDatabaseSetting:MPDatabaseSettingsTabPassword saveDocument:NO];
}
- (void)showDocumentSettings:(id)sender {
if(!self.documentSettingsWindowController) {
_documentSettingsWindowController = [[MPDocumentSettingsWindowController alloc] initWithDocument:[self document]];
}
[_documentSettingsWindowController update];
[[NSApplication sharedApplication] beginSheet:[_documentSettingsWindowController window] modalForWindow:[self window] modalDelegate:nil didEndSelector:NULL contextInfo:NULL];
- (void)showDatabaseSettings:(id)sender {
[self _showDatabaseSetting:MPDatabaseSettingsTabGeneral saveDocument:NO];
}
- (void)lock:(id)sender {
- (IBAction)lock:(id)sender {
MPDocument *document = [self document];
if(!document.isSecured) {
if(!document.hasPasswordOrKey) {
return; // Document needs a password/keyfile to be lockable
}
if(document.isLocked) {
@@ -241,18 +298,21 @@ NSString *const MPCurrentItemChangedNotification = @"com.hicknhack.macpass.MPCur
- (void)toggleInspector:(id)sender {
NSView *inspectorView = [_inspectorViewController view];
BOOL inspectorVisible = NO;
if([inspectorView superview]) {
//[inspectorView animator]
[inspectorView removeFromSuperview];
}
else {
// Remove contraint on view removal.
inspectorVisible = YES;
[_splitView addSubview:inspectorView];
[_splitView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"[inspectorView(>=200)]"
options:0
metrics:nil
views:NSDictionaryOfVariableBindings(inspectorView)]];
}
[[NSUserDefaults standardUserDefaults] setBool:inspectorVisible forKey:kMPSettingsKeyShowInspector];
}
- (void)showEntries {
@@ -264,7 +324,7 @@ NSString *const MPCurrentItemChangedNotification = @"com.hicknhack.macpass.MPCur
[[contentView subviews][0] removeFromSuperviewWithoutNeedingDisplay];
}
[contentView addSubview:_splitView];
[_splitView adjustSubviews];
//[_splitView adjustSubviews];
NSView *outlineView = [_outlineViewController view];
NSView *inspectorView = [_inspectorViewController view];
NSView *entryView = [_entryViewController view];
@@ -310,7 +370,7 @@ NSString *const MPCurrentItemChangedNotification = @"com.hicknhack.macpass.MPCur
if(removeInspector) {
[inspectorView removeFromSuperview];
}
[contentView layout];
[contentView layoutSubtreeIfNeeded];
MPDocument *document = [self document];
document.locked = NO;
@@ -321,6 +381,7 @@ NSString *const MPCurrentItemChangedNotification = @"com.hicknhack.macpass.MPCur
[_outlineViewController showOutline];
}
#pragma mark NSWindowDelegate
- (void)windowDidUpdate:(NSNotification *)notification {
id firstResonder = [[self window] firstResponder];
@@ -333,8 +394,51 @@ NSString *const MPCurrentItemChangedNotification = @"com.hicknhack.macpass.MPCur
}
}
//- (void)windowDidBecomeKey:(NSNotification *)notification {
// if(!_requestPassword) {
// return; // Nothing to do;
// }
// MPDocument *document = [self document];
// if(!document.hasPasswordOrKey && document.decrypted) {
// _requestPassword = NO;
// [self performSelector:@selector(editPassword:) withObject:nil afterDelay:0.5];
// }
//}
#pragma mark MPDatabaseSettingsDelegate
- (void)didCancelDatabaseSettings {
_saveAfterPasswordEdit = NO; // Just Reset the flag
}
- (void)didSaveDatabaseSettings {
if (_saveAfterPasswordEdit) {
_saveAfterPasswordEdit = NO;
}
[[self document] saveDocument:nil];
}
#pragma mark Helper
- (void)_setPasswordAndSave {
_saveAfterPasswordEdit = YES;
[self editPassword:nil];
}
- (void)_showDatabaseSetting:(MPDatabaseSettingsTab)tab saveDocument:(BOOL)save{
if(!self.documentSettingsWindowController) {
_documentSettingsWindowController = [[MPDatabaseSettingsWindowController alloc] initWithDocument:[self document]];
[_documentSettingsWindowController setDelegate:self];
}
[self.documentSettingsWindowController update];
[self.documentSettingsWindowController showSettingsTab:tab];
[[NSApplication sharedApplication] beginSheet:[self.documentSettingsWindowController window]
modalForWindow:[self window]
modalDelegate:nil
didEndSelector:NULL
contextInfo:NULL];
}
- (NSSearchField *)locateToolbarSearchField {
for(NSToolbarItem *toolbarItem in [[self.window toolbar] items]) {
NSView *view = [toolbarItem view];

View File

@@ -0,0 +1,16 @@
//
// MPEntryMenuDelegate.h
// MacPass
//
// Created by Michael Starke on 17.07.13.
// Copyright (c) 2013 HicknHack Software GmbH. All rights reserved.
//
#import <Foundation/Foundation.h>
@class MPEntryViewController;
@interface MPEntryMenuDelegate : NSObject <NSMenuDelegate>
@property (weak) MPEntryViewController *viewController;
@end

View File

@@ -0,0 +1,54 @@
//
// MPEntryMenuDelegate.m
// MacPass
//
// Created by Michael Starke on 17.07.13.
// Copyright (c) 2013 HicknHack Software GmbH. All rights reserved.
//
#import "MPEntryMenuDelegate.h"
#import "MPEntryViewController.h"
#import "Kdb4Node.h"
static NSUInteger const kMPCustomFieldMenuItem = 1000;
static NSUInteger const kMPAttachmentsMenuItem = 2000;
@implementation MPEntryMenuDelegate
- (void)menuNeedsUpdate:(NSMenu *)menu {
NSMenuItem *fieldsMenu = [menu itemWithTag:kMPCustomFieldMenuItem];
NSMenuItem *attachmentsMenu = [menu itemWithTag:kMPAttachmentsMenuItem];
if(fieldsMenu) {
[menu removeItem:fieldsMenu];
}
if(attachmentsMenu) {
[menu removeItem:attachmentsMenu];
}
NSMenuItem *lastItem = [[menu itemArray] lastObject];
if([lastItem isSeparatorItem]) {
[menu removeItem:lastItem];
}
if([self.viewController.selectedEntry isKindOfClass:[Kdb4Entry class]]) {
Kdb4Entry *entry = (Kdb4Entry *)self.viewController.selectedEntry;
if([entry.stringFields count] > 0) {
[menu addItem:[NSMenuItem separatorItem]];
NSMenuItem *customFieldsItem = [[NSMenuItem alloc] init];
NSMenu *submenu = [[NSMenu alloc] initWithTitle:@"Fields"];
[customFieldsItem setTitle:NSLocalizedString(@"COPY_CUSTOM_FIELDS", "Submenu to Copy custom fields")];
[customFieldsItem setTag:kMPCustomFieldMenuItem];
for (StringField *field in entry.stringFields) {
NSString *title = [NSString stringWithFormat:NSLocalizedString(@"COPY_FIELD_%@", "Mask for title to copy field value"), field.key];
NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:title action:@selector(copyCustomField:) keyEquivalent:@""];
[item setTag:[entry.stringFields indexOfObject:field]];
[submenu addItem:item];
}
[customFieldsItem setSubmenu:submenu];
[menu addItem:customFieldsItem];
}
}
}
@end

View File

@@ -48,9 +48,11 @@ typedef NS_ENUM( NSUInteger, MPCopyContentTypeTag) {
/* Copy/Paste */
- (void)copyUsername:(id)sender;
- (void)copyPassword:(id)sender;
- (void)copyCustomField:(id)sender;
- (void)copyURL:(id)sender;
- (void)openURL:(id)sender;
/* Entry Handling*/
- (void)deleteNode:(id)sender;

View File

@@ -20,10 +20,12 @@
#import "MPConstants.h"
#import "MPEntryTableDataSource.h"
#import "MPStringLengthValueTransformer.h"
#import "MPEntryMenuDelegate.h"
#import "HNHTableHeaderCell.h"
#import "HNHGradientView.h"
#import "Kdb4Node.h"
#import "KdbGroup+MPTreeTools.h"
#import "KdbGroup+Undo.h"
#import "KdbEntry+Undo.h"
@@ -43,6 +45,7 @@ typedef NS_ENUM(NSUInteger,MPOVerlayInfoType) {
MPOverlayInfoPassword,
MPOverlayInfoUsername,
MPOverlayInfoURL,
MPOverlayInfoCustom
};
NSString *const MPEntryTableUserNameColumnIdentifier = @"MPUserNameColumnIdentifier";
@@ -59,7 +62,9 @@ NSString *const _toggleFilterURLButton = @"SearchURL";
NSString *const _toggleFilterTitleButton = @"SearchTitle";
NSString *const _toggleFilterUsernameButton = @"SearchUsername";
@interface MPEntryViewController ()
@interface MPEntryViewController () {
MPEntryMenuDelegate *_menuDelegate;
}
@property (strong) NSArrayController *entryArrayController;
@property (strong) NSArray *filteredEntries;
@@ -103,6 +108,9 @@ NSString *const _toggleFilterUsernameButton = @"SearchUsername";
_entryArrayController = [[NSArrayController alloc] init];
_dataSource = [[MPEntryTableDataSource alloc] init];
_dataSource.viewController = self;
_menuDelegate = [[MPEntryMenuDelegate alloc] init];
_menuDelegate.viewController = self;
_selectedEntry = nil;
}
return self;
@@ -124,7 +132,7 @@ NSString *const _toggleFilterUsernameButton = @"SearchUsername";
[self.entryTable setDoubleAction:@selector(_columnDoubleClick:)];
[self.entryTable setTarget:self];
[self.entryTable setFloatsGroupRows:NO];
[self.entryTable registerForDraggedTypes:@[MPPasteBoardType]];
//[self.entryTable registerForDraggedTypes:@[MPPasteBoardType]];
[self _setupEntryMenu];
NSTableColumn *parentColumn = [self.entryTable tableColumns][0];
@@ -140,6 +148,9 @@ NSString *const _toggleFilterUsernameButton = @"SearchUsername";
[passwordColumn setIdentifier:MPEntryTablePasswordColumnIdentifier];
[urlColumn setIdentifier:MPEntryTableURLColumnIdentifier];
[self.entryTable setAutosaveName:@"EntryTable"];
[self.entryTable setAutosaveTableColumns:YES];
NSSortDescriptor *titleColumSortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"title" ascending:YES selector:@selector(compare:)];
NSSortDescriptor *userNameSortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"username" ascending:YES selector:@selector(compare:)];
NSSortDescriptor *urlSortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"url" ascending:YES selector:@selector(compare:)];
@@ -159,13 +170,14 @@ NSString *const _toggleFilterUsernameButton = @"SearchUsername";
[self.entryTable setDataSource:_dataSource];
[parentColumn setHidden:YES];
}
- (void)setupNotifications:(MPDocumentWindowController *)windowController {
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(_didChangeCurrentItem:)
name:MPCurrentItemChangedNotification
object:windowController];
object:windowController];
}
#pragma mark NSTableViewDelgate
@@ -395,7 +407,7 @@ NSString *const _toggleFilterUsernameButton = @"SearchUsername";
}
}
- (void)_copyToPasteboard:(NSString *)data overlayInfo:(MPOVerlayInfoType)overlayInfoType {
- (void)_copyToPasteboard:(NSString *)data overlayInfo:(MPOVerlayInfoType)overlayInfoType name:(NSString *)name{
if(data) {
[[MPPasteBoardController defaultController] copyObjects:@[ data ]];
}
@@ -416,6 +428,11 @@ NSString *const _toggleFilterUsernameButton = @"SearchUsername";
infoImage = [[NSBundle mainBundle] imageForResource:@"09_IdentityTemplate"];
infoText = NSLocalizedString(@"COPIED_USERNAME", @"Username was copied to the pasteboard");
break;
case MPOverlayInfoCustom:
infoImage = [[NSBundle mainBundle] imageForResource:@"00_PasswordTemplate"];
infoText = [NSString stringWithFormat:NSLocalizedString(@"COPIED_FIELD_%@", "Field nam that was copied to the pasteboard"), name];
break;
}
[[MPOverlayWindowController sharedController] displayOverlayImage:infoImage label:infoText atView:self.view];
}
@@ -429,7 +446,9 @@ NSString *const _toggleFilterUsernameButton = @"SearchUsername";
for(NSMenuItem *item in items) {
[menu addItem:item];
}
[menu setDelegate:_menuDelegate];
[self.entryTable setMenu:menu];
}
#pragma makr Action Helper
@@ -451,21 +470,32 @@ NSString *const _toggleFilterUsernameButton = @"SearchUsername";
- (void)copyPassword:(id)sender {
KdbEntry *selectedEntry = [self _clickedOrSelectedEntry];
if(selectedEntry) {
[self _copyToPasteboard:selectedEntry.password overlayInfo:MPOverlayInfoPassword];
[self _copyToPasteboard:selectedEntry.password overlayInfo:MPOverlayInfoPassword name:nil];
}
}
- (void)copyUsername:(id)sender {
KdbEntry *selectedEntry = [self _clickedOrSelectedEntry];
if(selectedEntry) {
[self _copyToPasteboard:selectedEntry.username overlayInfo:MPOverlayInfoUsername];
[self _copyToPasteboard:selectedEntry.username overlayInfo:MPOverlayInfoUsername name:nil];
}
}
- (void)copyCustomField:(id)sender {
KdbEntry *selectedEntry = [self _clickedOrSelectedEntry];
if(selectedEntry && [selectedEntry isKindOfClass:[Kdb4Entry class]]) {
Kdb4Entry *entry = (Kdb4Entry *)selectedEntry;
NSUInteger index = [sender tag];
NSAssert((index >= 0) && (index < [entry.stringFields count]), @"Index for custom field needs to be valid");
StringField *field = entry.stringFields[index];
[self _copyToPasteboard:field.value overlayInfo:MPOverlayInfoCustom name:field.key];
}
}
- (void)copyURL:(id)sender {
KdbEntry *selectedEntry = [self _clickedOrSelectedEntry];
if(selectedEntry) {
[self _copyToPasteboard:selectedEntry.url overlayInfo:MPOverlayInfoURL];
[self _copyToPasteboard:selectedEntry.url overlayInfo:MPOverlayInfoURL name:nil];
}
}
@@ -480,7 +510,12 @@ NSString *const _toggleFilterUsernameButton = @"SearchUsername";
- (void)deleteNode:(id)sender {
KdbEntry *entry =[self _clickedOrSelectedEntry];
MPDocument *document = [[self windowController] document];
[document group:entry.parent removeEntry:entry];
[document deleteEntry:entry];
}
#pragma mark Validation
- (BOOL)validateMenuItem:(NSMenuItem *)menuItem {
return YES;
}
- (void)_toggleFilterSpace:(id)sender {

View File

@@ -1,16 +0,0 @@
//
// MPFirstResonderNotification.h
// MacPass
//
// Created by Michael Starke on 20.06.13.
// Copyright (c) 2013 HicknHack Software GmbH. All rights reserved.
//
#import <Foundation/Foundation.h>
@protocol MPFirstResonderNotification <NSObject>
@required
- (BOOL)becomeFirstResponder;
@end

View File

@@ -16,5 +16,7 @@
@property (weak) IBOutlet NSPopUpButton *clearPasteboardTimeoutPopup;
@property (weak) IBOutlet NSPopUpButton *idleTimeOutPopup;
@property (weak) IBOutlet NSButton *lockOnSleepCheckButton;
@property (weak) IBOutlet NSButton *reopenLastDatabase;
@property (weak) IBOutlet NSButton *createUntitledOnActivation;
@end

View File

@@ -32,6 +32,8 @@ NSString *const MPGeneralSetingsIdentifier = @"GeneralSettingsTab";
- (void)didLoadView {
NSUserDefaultsController *defaultsController = [NSUserDefaultsController sharedUserDefaultsController];
NSString *reopenLastFilePath = [NSString stringWithFormat:@"values.%@", kMPSettingsKeyReopenLastDatabaseOnLaunch];
//NSString *createUntitledOnActivatePaht = [NSString stringWithFormat:@"values.%@", kMPSettingsKeyOpenEmptyDatabaseOnLaunch];
NSString *clearPasteboardKeyPath = [NSString stringWithFormat:@"values.%@", kMPSettingsKeyClearPasteboardOnQuit];
NSString *clearPasteboardTimeOutKeyPath = [NSString stringWithFormat:@"values.%@", kMPSettingsKeyPasteboardClearTimeout];
NSString *idleTimeOutKeyPath = [NSString stringWithFormat:@"values.%@", kMPSettingsKeyIdleLockTimeOut];
@@ -40,5 +42,8 @@ NSString *const MPGeneralSetingsIdentifier = @"GeneralSettingsTab";
[self.clearPasteboardTimeoutPopup bind:NSSelectedTagBinding toObject:defaultsController withKeyPath:clearPasteboardTimeOutKeyPath options:nil];
[self.lockOnSleepCheckButton bind:NSValueBinding toObject:defaultsController withKeyPath:lockOnSleepKeyPath options:nil];
[self.idleTimeOutPopup bind:NSSelectedTagBinding toObject:defaultsController withKeyPath:idleTimeOutKeyPath options:nil];
[self.reopenLastDatabase bind:NSValueBinding toObject:defaultsController withKeyPath:reopenLastFilePath options:nil];
[self.createUntitledOnActivation setState:NSOffState];
//[self.createUntitledOnActivation bind:NSValueBinding toObject:defaultsController withKeyPath:createUntitledOnActivatePaht options:nil];
}
@end

View File

@@ -15,14 +15,19 @@ typedef NS_ENUM(NSUInteger, MPIconType) {
MPIconServer,
MPIconKlipper,
MPIconLanguages,
MPIconBlockDevice,
MPIconNotepad,
MPIconSocket,
MPIconIdentity,
MPIconContact,
MPIconCamera,
MPIconRemote,
MPIconKeys,
MPIconDisplay = 18,
MPIconFileSave = 26,
MPIconTrash = 43,
MPIconFolder = 48,
MPIconPhone = 68,
/* Custom Icons not used in Database */
MPIconInfo = 1000,
MPIconAddFolder,

View File

@@ -41,16 +41,25 @@ static NSDictionary *icons;
@(MPIconServer): @"03_ServerTemplate",
@(MPIconKlipper): @"04_KlipperTemplate",
@(MPIconLanguages): @"05_LanguagesTemplate",
@(MPIconBlockDevice): @"06_BlockDeviceTemplate",
@(MPIconNotepad): @"07_NotepadTemplate",
@(MPIconSocket): @"08_SocketTemplate",
@(MPIconIdentity): @"09_IdentityTemplate",
@(MPIconContact): @"10_ContactTemplate",
@(MPIconCamera): @"11_CameraTemplate",
@(MPIconRemote): @"12_RemoteTemplate",
@(MPIconKeys): @"13_KeysTemplate",
@(MPIconDisplay): @"18_DisplayTemplate",
@(MPIconFileSave): @"26_FileSaveTemplate",
@(MPIconTrash): @"43_TrashTemplate",
@(MPIconFolder): @"48_FolderTemplate",
@(MPIconPhone): @"68_PhoneTemplate",
@(MPIconInfo): @"99_InfoTemplate",
@(MPIconAddFolder): @"99_AddFolderTemplate",
@(MPIconHardDisk): @"99_HarddiskTemplate"

View File

@@ -12,9 +12,10 @@
@class KdbEntry;
@class KdbGroup;
@class HNHGradientView;
@class HNHRoundedSecureTextField;
@class MPDocumentWindowController;
@interface MPInspectorViewController : MPViewController <NSPopoverDelegate, NSTableViewDelegate>
@interface MPInspectorViewController : MPViewController <NSPopoverDelegate>
@property (weak) IBOutlet MPPopupImageView *itemImageView;
@property (weak) IBOutlet NSTextField *itemNameTextfield;
@@ -22,7 +23,7 @@
@property (weak) IBOutlet NSTextField *titleTextField;
@property (weak) IBOutlet NSTextField *usernameTextField;
@property (weak) IBOutlet NSTextField *URLTextField;
@property (weak) IBOutlet NSTextField *passwordTextField;
@property (weak) IBOutlet HNHRoundedSecureTextField *passwordTextField;
@property (weak) IBOutlet NSTextField *titleOrNameLabel;
@property (weak) IBOutlet HNHGradientView *bottomBar;
@property (weak) IBOutlet NSTextField *createdTextField;
@@ -32,8 +33,12 @@
@property (weak) IBOutlet NSTableView *customFieldsTableView;
@property (unsafe_unretained) IBOutlet NSTextView *notesTextView;
@property (weak) IBOutlet NSTextField *customFieldsTextField;
@property (weak) IBOutlet NSButton *togglePassword;
@property (weak, nonatomic, readonly) KdbEntry *selectedEntry;
@property (weak, nonatomic, readonly) KdbGroup *selectedGroup;
/* Seperate call to ensure alle registered objects are in place */
- (void)setupNotifications:(MPDocumentWindowController *)windowController;

View File

@@ -20,6 +20,10 @@
#import "MPDatabaseVersion.h"
#import "MPCustomFieldTableCellView.h"
#import "MPSelectedAttachmentTableCellView.h"
#import "MPAttachmentTableViewDelegate.h"
#import "MPCustomFieldTableViewDelegate.h"
#import "NSDate+Humanized.h"
#import "KdbLib.h"
#import "Kdb4Node.h"
@@ -31,6 +35,8 @@
#import "NSMutableData+Base64.h"
#import "HNHGradientView.h"
#import "HNHTableRowView.h"
#import "HNHRoundedSecureTextField.h"
enum {
MPGeneralTab,
@@ -41,6 +47,10 @@ enum {
@interface MPInspectorViewController () {
BOOL _visible;
NSArrayController *_attachmentsController;
NSArrayController *_customFieldsController;
MPAttachmentTableViewDelegate *_attachmentTableDelegate;
MPCustomFieldTableViewDelegate *_customFieldTableDelegate;
}
@property (weak, nonatomic) KdbEntry *selectedEntry;
@@ -49,19 +59,21 @@ enum {
@property (strong) NSPopover *activePopover;
@property (weak) IBOutlet NSButton *generatePasswordButton;
@property (nonatomic, weak) NSDate *modificationDate;
@property (nonatomic, weak) NSDate *creationDate;
@property (nonatomic, strong) NSDate *modificationDate;
@property (nonatomic, strong) NSDate *creationDate;
@property (nonatomic, assign) BOOL showPassword;
@property (nonatomic, assign) NSUInteger activeTab;
@property (weak) IBOutlet NSTabView *tabView;
@property (strong) NSArrayController *attachmentsController;
@property (strong) NSArrayController *customFieldsController;
- (IBAction)addCustomField:(id)sender;
- (IBAction)removeCustomField:(id)sender;
- (IBAction)saveAttachment:(id)sender;
- (IBAction)addAttachment:(id)sender;
- (IBAction)removeAttachment:(id)sender;
- (IBAction)edit:(id)sender;
- (IBAction)finishEdit:(id)sender;
@end
@@ -74,10 +86,15 @@ enum {
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
_showPassword = NO;
_selectedEntry = nil;
_selectedGroup = nil;
_attachmentsController = [[NSArrayController alloc] init];
_customFieldsController = [[NSArrayController alloc] init];
_attachmentTableDelegate = [[MPAttachmentTableViewDelegate alloc] init];
_attachmentTableDelegate.viewController = self;
_customFieldTableDelegate = [[MPCustomFieldTableViewDelegate alloc] init];
_customFieldTableDelegate.viewController = self;
_activeTab = MPGeneralTab;
}
return self;
@@ -98,12 +115,15 @@ enum {
/* Set background to clearcolor so we can draw in the scrollview */
[_attachmentTableView setBackgroundColor:[NSColor clearColor]];
[_attachmentTableView bind:NSContentBinding toObject:self.attachmentsController withKeyPath:@"arrangedObjects" options:nil];
[_attachmentTableView setDelegate:self];
[_attachmentTableView bind:NSContentBinding toObject:_attachmentsController withKeyPath:@"arrangedObjects" options:nil];
[_attachmentTableView setDelegate:_attachmentTableDelegate];
/* Set background to clearcolor so we can draw in the scrollview */
[_customFieldsTableView setBackgroundColor:[NSColor clearColor]];
[_customFieldsTableView bind:NSContentBinding toObject:self.customFieldsController withKeyPath:@"arrangedObjects" options:nil];
[_customFieldsTableView setDelegate:self];
[_customFieldsTableView bind:NSContentBinding toObject:_customFieldsController withKeyPath:@"arrangedObjects" options:nil];
[_customFieldsTableView setDelegate:_customFieldTableDelegate];
[self.passwordTextField bind:@"showPassword" toObject:self withKeyPath:@"showPassword" options:nil];
[self.togglePassword bind:NSValueBinding toObject:self withKeyPath:@"showPassword" options:nil];
[self _clearContent];
}
@@ -117,21 +137,32 @@ enum {
}
- (void)setModificationDate:(NSDate *)modificationDate {
NSString *modificationString = [NSDateFormatter localizedStringFromDate:modificationDate
dateStyle:NSDateFormatterShortStyle
timeStyle:NSDateFormatterShortStyle];
NSString *modifedAtTemplate = NSLocalizedString(@"MODIFED_AT_%@", @"Modifed at template string. %@ is replaced by locaized date and time");
[self.modifiedTextField setStringValue:[NSString stringWithFormat:modifedAtTemplate, modificationString]];
_modificationDate = modificationDate;
[self _updateDateStrings];
}
- (void)setCreationDate:(NSDate *)creationDate {
NSString *creationString = [NSDateFormatter localizedStringFromDate:creationDate
dateStyle:NSDateFormatterShortStyle
timeStyle:NSDateFormatterShortStyle];
_creationDate = creationDate;
[self _updateDateStrings];
}
- (void)_updateDateStrings {
if(!self.creationDate || !self.modificationDate ) {
[self.modifiedTextField setStringValue:@""];
[self.createdTextField setStringValue:@""];
return; // No dates, just clear
}
NSString *creationString = [self.creationDate humanized];
NSString *modificationString = [self.modificationDate humanized];
NSString *modifedAtTemplate = NSLocalizedString(@"MODIFED_AT_%@", @"Modifed at template string. %@ is replaced by locaized date and time");
NSString *createdAtTemplate = NSLocalizedString(@"CREATED_AT_%@", @"Created at template string. %@ is replaced by locaized date and time");
[self.modifiedTextField setStringValue:[NSString stringWithFormat:modifedAtTemplate, modificationString]];
[self.createdTextField setStringValue:[NSString stringWithFormat:createdAtTemplate, creationString]];
}
- (void)_updateContent {
@@ -151,26 +182,26 @@ enum {
- (void)_updateAttachments {
if(self.selectedEntry) {
if([self.selectedEntry isKindOfClass:[Kdb4Entry class]]) {
[self.attachmentsController bind:NSContentArrayBinding toObject:self.selectedEntry withKeyPath:@"binaries" options:nil];
[_attachmentsController bind:NSContentArrayBinding toObject:self.selectedEntry withKeyPath:@"binaries" options:nil];
}
else {
/* Use binary from Kdb3Entry */
[_attachmentsController bind:NSContentArrayBinding toObject:self.selectedEntry withKeyPath:@"binaries" options:nil];
}
}
else if([self.attachmentsController content] != nil){
[self.attachmentsController unbind:NSContentArrayBinding];
[self.attachmentsController setContent:nil];
else if([_attachmentsController content] != nil){
[_attachmentsController unbind:NSContentArrayBinding];
[_attachmentsController setContent:nil];
}
}
- (void)_updateCustomFields {
if(self.selectedEntry && [self.selectedEntry isKindOfClass:[Kdb4Entry class]]) {
[self.customFieldsController bind:NSContentArrayBinding toObject:self.selectedEntry withKeyPath:@"stringFields" options:nil];
[_customFieldsController bind:NSContentArrayBinding toObject:self.selectedEntry withKeyPath:@"stringFields" options:nil];
}
else if([self.customFieldsController content] != nil){
[self.customFieldsController unbind:NSContentArrayBinding];
[self.customFieldsController setContent:nil];
else if([_customFieldsController content] != nil){
[_customFieldsController unbind:NSContentArrayBinding];
[_customFieldsController setContent:nil];
}
}
@@ -254,6 +285,7 @@ enum {
enabled &= (self.selectedEntry != nil);
[self.passwordTextField setEnabled:enabled];
[self.togglePassword setEnabled:enabled];
[self.usernameTextField setEnabled:enabled];
[self.URLTextField setEnabled:enabled];
[self.generatePasswordButton setEnabled:enabled];
@@ -314,22 +346,30 @@ enum {
MPDocument *document = [[self windowController] document];
NSUInteger index = [sender tag];
Kdb4Entry *entry = (Kdb4Entry *)self.selectedEntry;
[document entry:entry removeStringField:(entry.stringFields)[index]];
[document removeStringField:(entry.stringFields)[index] formEntry:entry];
}
- (IBAction)saveAttachment:(id)sender {
Kdb4Entry *entry = (Kdb4Entry *)self.selectedEntry;
BinaryRef *reference = entry.binaries[[sender tag]];
BOOL isVersion4 = [self.selectedEntry isKindOfClass:[Kdb4Entry class]];
id item = self.selectedEntry;
NSString *fileName = nil;
if(isVersion4) {
Kdb4Entry *entry= (Kdb4Entry *)self.selectedEntry;
item = entry.binaries[[sender tag]];
fileName = ((BinaryRef *)item).key;
}
else {
fileName = ((Kdb3Entry *)item).binaryDesc;
}
NSSavePanel *savePanel = [NSSavePanel savePanel];
[savePanel setCanCreateDirectories:YES];
[savePanel setNameFieldStringValue:reference.key];
[savePanel setNameFieldStringValue:fileName];
[savePanel beginSheetModalForWindow:[[self windowController] window] completionHandler:^(NSInteger result) {
if(result == NSFileHandlingPanelOKButton) {
MPDocument *document = [[self windowController] document];
[document saveAttachment:reference toLocation:[savePanel URL]];
[document saveAttachmentForItem:item toLocation:[savePanel URL]];
}
}];
}
@@ -352,15 +392,30 @@ enum {
- (IBAction)removeAttachment:(id)sender {
MPDocument *document = [[self windowController] document];
if(document.version == MPDatabaseVersion3) {
// Uhhhh :D
[document removeAttachmentFromEntry:self.selectedEntry];
}
if(document.version == MPDatabaseVersion4) {
else if(document.version == MPDatabaseVersion4) {
Kdb4Entry *entry = (Kdb4Entry *)self.selectedEntry;
BinaryRef *reference = entry.binaries[[sender tag]];
[document removeAttachment:reference fromEntry:self.selectedEntry];
}
}
- (IBAction)edit:(id)sender {
[self.titleTextField setEditable:YES];
[self.usernameTextField setEditable:YES];
[[[[self windowController] document] undoManager] beginUndoGrouping];
}
- (IBAction)finishEdit:(id)sender {
NSUndoManager *undoManger = [[[self windowController] document] undoManager];
[undoManger setActionName:@"Edit"];
[undoManger endUndoGrouping];
[self.titleTextField setEditable:NO];
[self.usernameTextField setEditable:NO];
}
#pragma mark Notificiations
- (void)_didChangeCurrentItem:(NSNotification *)notification {
MPDocumentWindowController *sender = [notification object];
@@ -380,69 +435,4 @@ enum {
[self _updateContent];
}
#pragma mark NSTableViewDelegate
/* TODO: Divide this into single delegates */
- (NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
if(tableView == self.attachmentTableView) {
return [self _viewForAttachmentTableColumn:tableColumn row:row];
}
return [self _viewForCustomFieldTableColumn:tableColumn row:row];
}
- (void)tableViewSelectionDidChange:(NSNotification *)notification {
if([notification object] == self.attachmentTableView) {
NSIndexSet *allColumns = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, [[self.attachmentTableView tableColumns] count])];
Kdb4Entry *entryv4 = (Kdb4Entry *)self.selectedEntry;
NSIndexSet *indexSet = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, [entryv4.binaries count] )];
[self.attachmentTableView reloadDataForRowIndexes:indexSet columnIndexes:allColumns];
}
}
- (NSView *)_viewForAttachmentTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
/* Decide what view to use */
NSIndexSet *selectedIndexes = [self.attachmentTableView selectedRowIndexes];
NSTableCellView *view;
if([selectedIndexes containsIndex:row]) {
MPSelectedAttachmentTableCellView *cellView = [_attachmentTableView makeViewWithIdentifier:@"SelectedCell" owner:_attachmentTableView];
[cellView.saveButton setTag:row];
[cellView.saveButton setAction:@selector(saveAttachment:)];
[cellView.saveButton setTarget:self];
[cellView.removeButton setTag:row];
[cellView.removeButton setAction:@selector(removeAttachment:)];
[cellView.removeButton setTarget:self];
view = cellView;
}
else {
view = [_attachmentTableView makeViewWithIdentifier:@"NormalCell" owner:_attachmentTableView];
}
/* Bind view */
if([self.selectedEntry isKindOfClass:[Kdb4Entry class]]) {
Kdb4Entry *entry = (Kdb4Entry *)self.selectedEntry;
BinaryRef *binaryRef = entry.binaries[row];
[[view textField] bind:NSValueBinding toObject:binaryRef withKeyPath:@"key" options:nil];
[[view imageView] setImage:[[NSWorkspace sharedWorkspace] iconForFileType:[binaryRef.key pathExtension]]];
}
return view;
}
- (NSView *)_viewForCustomFieldTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
MPCustomFieldTableCellView *view = [_customFieldsTableView makeViewWithIdentifier:[tableColumn identifier] owner:_customFieldsTableView];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_customFieldFrameChanged:) name:NSViewFrameDidChangeNotification object:view];
if([self.selectedEntry isKindOfClass:[Kdb4Entry class]]) {
Kdb4Entry *entry = (Kdb4Entry *)self.selectedEntry;
StringField *stringField = entry.stringFields[row];
[view.labelTextField bind:NSValueBinding toObject:stringField withKeyPath:MPStringFieldKeyUndoableKey options:nil];
[view.valueTextField bind:NSValueBinding toObject:stringField withKeyPath:MPStringFieldValueUndoableKey options:nil];
[view.removeButton setTarget:self];
[view.removeButton setAction:@selector(removeCustomField:)];
[view.removeButton setTag:row];
}
return view;
}
- (void)_customFieldFrameChanged:(NSNotification *)notification {
// NSView *sender = [notification object];
// NSLog(@"didChangeFrameFor: %@ to: %@", sender, NSStringFromRect([sender frame]));
}
@end

View File

@@ -13,6 +13,7 @@
#import "KdbLib.h"
#import "KdbGroup+Undo.h"
#import "KdbEntry+Undo.h"
#import "KdbGroup+MPTreeTools.h"
#import "KdbEntry+MPTreeTools.h"
@@ -76,10 +77,9 @@
accepted &= index != NSOutlineViewDropOnItemIndex;
accepted &= index != [_draggedItem.parent.groups indexOfObject:_draggedItem];
}
MPDocument *document = [[[outlineView window] windowController] document];
accepted = [document group:_draggedItem isMoveableToGroup:target];
accepted = ![_draggedItem isAnchestorOfGroup:target];
if( accepted ) {
[document moveGroup:_draggedItem toGroup:target index:index];
[_draggedItem moveToGroupUndoable:target atIndex:index];
}
info.animatesToDestination = !accepted;
return accepted;
@@ -94,7 +94,7 @@
KdbEntry *draggedEntry = [rootGroup entryForUUID:uuid];
if(draggedEntry) {
if(draggedEntry.parent != target && index == NSOutlineViewDropOnItemIndex) {
[document moveEntry:draggedEntry toGroup:target index:index];
[draggedEntry moveToGroupUndoable:target atIndex:index];
return YES;
}
}

View File

@@ -19,7 +19,7 @@ APPKIT_EXTERN NSString *const MPOutlineViewDidChangeGroupSelection;
@property (readonly, weak) NSOutlineView *outlineView;
@property (weak) IBOutlet HNHGradientView *bottomBar;
@property (weak, readonly) KdbGroup *selectedGroup;
@property (weak, readonly, nonatomic) KdbGroup *selectedGroup;
- (void)clearSelection;
- (void)showOutline;

View File

@@ -33,12 +33,14 @@ NSString *const _MPOutlinveViewHeaderViewIdentifier = @"HeaderCell";
}
@property (weak) IBOutlet NSOutlineView *outlineView;
@property (weak) IBOutlet NSButton *addGroupButton;
@property (weak) KdbGroup *selectedGroup;
@property (nonatomic, weak) KdbGroup *selectedGroup;
@property (strong) NSTreeController *treeController;
@property (strong) MPOutlineDataSource *datasource;
@property (strong) NSMenu *menu;
@property (copy, nonatomic) NSString *databaseNameWrapper;
@end
@implementation MPOutlineViewController
@@ -53,6 +55,7 @@ NSString *const _MPOutlinveViewHeaderViewIdentifier = @"HeaderCell";
_treeController = [[NSTreeController alloc] init];
_bindingEstablished = NO;
_datasource = [[MPOutlineDataSource alloc] init];
_databaseNameWrapper = NSLocalizedString(@"NEW_DATABASE", "Name for a newly created Database");
}
return self;
@@ -64,7 +67,7 @@ NSString *const _MPOutlinveViewHeaderViewIdentifier = @"HeaderCell";
[_outlineView setMenu:[self _contextMenu]];
[_outlineView setAllowsEmptySelection:YES];
[_outlineView setFloatsGroupRows:NO];
[_outlineView registerForDraggedTypes:@[ MPPasteBoardType ]];
//[_outlineView registerForDraggedTypes:@[ MPPasteBoardType ]];
[_outlineView setDraggingSourceOperationMask:NSDragOperationEvery forLocal:YES];
[_bottomBar setBorderType:HNHBorderTop];
[_addGroupButton setAction:[MPActionHelper actionOfType:MPActionAddGroup]];
@@ -76,6 +79,9 @@ NSString *const _MPOutlinveViewHeaderViewIdentifier = @"HeaderCell";
[_treeController setChildrenKeyPath:@"groups"];
[_treeController bind:NSContentBinding toObject:document withKeyPath:@"rootAdapter" options:nil];
[_outlineView bind:NSContentBinding toObject:_treeController withKeyPath:@"arrangedObjects" options:nil];
if([document.tree respondsToSelector:@selector(databaseName)]) {
[self bind:@"databaseNameWrapper" toObject:document.tree withKeyPath:@"databaseName" options:nil];
}
[_outlineView setDataSource:self.datasource];
_bindingEstablished = YES;
}
@@ -83,7 +89,30 @@ NSString *const _MPOutlinveViewHeaderViewIdentifier = @"HeaderCell";
[_outlineView expandItem:node expandChildren:YES];
}
#pragma makr Notifications
#pragma mark Custom Setter/Getter
- (void)setDatabaseNameWrapper:(NSString *)databaseNameWrapper {
if(![_databaseNameWrapper isEqualToString:databaseNameWrapper]) {
if([databaseNameWrapper length] == 0) {
_databaseNameWrapper = NSLocalizedString(@"DATABASE", "Default name database");
}
else {
_databaseNameWrapper= [databaseNameWrapper copy];
}
}
}
//- (void)setSelectedGroup:(KdbGroup *)selectedGroup {
// if(_selectedGroup != selectedGroup) {
// _selectedGroup = selectedGroup;
// if([selectedGroup isKindOfClass:[Kdb4Group class]]) {
// MPDocument *document = [[self windowController] document];
// document.treeV4.lastSelectedGroup = ((Kdb4Group *)selectedGroup).uuid;
// }
// }
//}
#pragma mark Notifications
- (void)setupNotifications:(MPDocumentWindowController *)windowController {
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_didCreateGroup:) name:MPDocumentDidAddGroupNotification object:[windowController document]];
}
@@ -108,6 +137,29 @@ NSString *const _MPOutlinveViewHeaderViewIdentifier = @"HeaderCell";
}
}
#pragma mark Validation
- (BOOL)validateMenuItem:(NSMenuItem *)menuItem {
MPActionType actionType = [MPActionHelper typeForAction:[menuItem action]];
switch(actionType) {
case MPActionAddEntry:
case MPActionAddGroup:
case MPActionDelete: {
MPDocument *document = [[self windowController] document];
id selected = [self _clickedOrSelectedGroup];
if(!selected) {
return NO;
}
if(selected == document.trash) {
return NO;
}
return ![document isItemTrashed:selected];
}
default:
return YES; // We are only validated for three targets
}
}
#pragma mark -
#pragma mark Actions
@@ -121,18 +173,12 @@ NSString *const _MPOutlinveViewHeaderViewIdentifier = @"HeaderCell";
}
- (void)createEntry:(id)sender {
KdbGroup *group = [self _clickedOrSelectedGroup];
if(group) {
MPDocument *document = [[self windowController] document];
[document createEntry:group];
}
MPDocument *document = [[self windowController] document];
[document createEntry:[self _clickedOrSelectedGroup]];
}
- (void)deleteNode:(id)sender {
KdbGroup *group = [self _clickedOrSelectedGroup];
if(group && group.parent) {
[[[self windowController] document] group:group.parent removeGroup:group];
}
[[[self windowController] document] deleteGroup:[self _clickedOrSelectedGroup]];
}
#pragma mark NSOutlineViewDelegate
@@ -141,13 +187,7 @@ NSString *const _MPOutlinveViewHeaderViewIdentifier = @"HeaderCell";
if( [self _itemIsRootNodeAdapter:item] ) {
//NSDictionary *options = @{ NSValueTransformerBindingOption : [NSValueTransformer valueTransformerForName:MPUppsercaseStringValueTransformerName] };
view = [outlineView makeViewWithIdentifier:_MPOutlinveViewHeaderViewIdentifier owner:self];
MPRootAdapter *rootNode = [item representedObject];
if([rootNode.tree respondsToSelector:@selector(databaseName)]) {
[view.textField bind:NSValueBinding toObject:rootNode.tree withKeyPath:@"databaseName" options:nil];
}
else {
[view.textField setStringValue:NSLocalizedString(@"GROUPS", @"")];
}
[view.textField bind:NSValueBinding toObject:self withKeyPath:@"databaseNameWrapper" options:nil];
}
else {
KdbGroup *group = [item representedObject];

View File

@@ -1,13 +0,0 @@
//
// MPPasswordEditViewController.h
// MacPass
//
// Created by Michael Starke on 29.04.13.
// Copyright (c) 2013 HicknHack Software GmbH. All rights reserved.
//
#import "MPViewController.h"
@interface MPPasswordEditViewController : MPViewController
@end

View File

@@ -1,67 +0,0 @@
//
// MPPasswordEditViewController.m
// MacPass
//
// Created by Michael Starke on 29.04.13.
// Copyright (c) 2013 HicknHack Software GmbH. All rights reserved.
//
#import "MPPasswordEditViewController.h"
#import "MPKeyfilePathControlDelegate.h"
#import "MPDocumentWindowController.h"
#import "MPDocument.h"
@interface MPPasswordEditViewController ()
@property (weak) IBOutlet NSSecureTextField *passwordTextField;
@property (weak) IBOutlet NSPathControl *keyfilePathControl;
@property (strong) MPKeyfilePathControlDelegate *pathControlDelegate;
- (IBAction)_change:(id)sender;
- (IBAction)_cancel:(id)sender;
@end
@implementation MPPasswordEditViewController
- (id)init {
return [self initWithNibName:@"PasswordEditView" bundle:nil];
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if(self) {
_pathControlDelegate = [[MPKeyfilePathControlDelegate alloc] init];
}
return self;
}
- (NSResponder *)reconmendedFirstResponder {
return self.passwordTextField;
}
- (void)didLoadView {
[self.keyfilePathControl setDelegate:self.pathControlDelegate];
}
- (IBAction)_change:(id)sender {
MPDocument *document = [[self windowController] document];
if(document) {
document.key = [self.keyfilePathControl URL];
NSString *password = [self.passwordTextField stringValue];
if([password length] > 0) {
document.password = password;
}
else {
document.password = nil;
}
}
id mainWindowController = [[[self view] window] windowController];
[mainWindowController showEntries];
}
- (IBAction)_cancel:(id)sender {
id mainWindowController = [[[self view] window] windowController];
[mainWindowController showEntries];
}
@end

View File

@@ -11,15 +11,20 @@
#import "MPDocument.h"
#import "MPKeyfilePathControlDelegate.h"
#import "HNHRoundedSecureTextField.h"
@interface MPPasswordInputController ()
@property (weak) IBOutlet NSTextField *passwordTextField;
@property (weak) IBOutlet HNHRoundedSecureTextField *passwordTextField;
@property (weak) IBOutlet NSPathControl *keyPathControl;
@property (strong) MPKeyfilePathControlDelegate *pathControlDelegate;
@property (weak) IBOutlet NSImageView *errorImageView;
@property (weak) IBOutlet NSTextField *errorInfoTextField;
@property (weak) IBOutlet NSButton *togglePasswordButton;
@property (assign) BOOL showPassword;
- (IBAction)_decrypt:(id)sender;
- (IBAction)_clearKey:(id)sender;
@end
@@ -33,6 +38,8 @@
- (void)didLoadView {
[self.keyPathControl setDelegate:self.pathControlDelegate];
[self.errorImageView setImage:[NSImage imageNamed:NSImageNameCaution]];
[self.passwordTextField bind:@"showPassword" toObject:self withKeyPath:@"showPassword" options:nil];
[self.togglePasswordButton bind:NSValueBinding toObject:self withKeyPath:@"showPassword" options:nil];
[self _reset];
}
@@ -44,13 +51,16 @@
// show Warnign if read-only mode!
[self _reset];
}
#pragma mark NSTextViewDelegate
#pragma mark -
#pragma mark Private
- (IBAction)_decrypt:(id)sender {
id windowController = [[[self view] window] windowController];
MPDocument *document = [windowController document];
if(document) {
BOOL isOk = NO;
if(document.isDecrypted) {
if(document.decrypted) {
// TODO: Fix unlocking to actually test
BOOL noPassword = !document.password && [[self.passwordTextField stringValue] length] == 0;
BOOL passwordOk = [document.password isEqualToString:[self.passwordTextField stringValue]];
@@ -59,7 +69,7 @@
isOk = (noPassword || passwordOk) && (noKey || keyOk);
}
else {
isOk = [document decryptWithPassword:[self.passwordTextField stringValue] keyFileURL:[self.keyPathControl URL]];
isOk = [document unlockWithPassword:[self.passwordTextField stringValue] keyFileURL:[self.keyPathControl URL]];
}
if(!isOk) {
[self _showError];
@@ -70,7 +80,12 @@
}
}
- (IBAction)_clearKey:(id)sender {
[self.keyPathControl setURL:nil];
}
- (void)_reset {
self.showPassword = NO;
[self.passwordTextField setStringValue:@""];
[self.keyPathControl setURL:nil];
[self.errorInfoTextField setHidden:YES];

View File

@@ -0,0 +1,13 @@
//
// MPPasswordStringFormatter.h
// MacPass
//
// Created by Michael Starke on 06.07.13.
// Copyright (c) 2013 HicknHack Software GmbH. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface MPPasswordStringFormatter : NSFormatter
@end

View File

@@ -0,0 +1,13 @@
//
// MPPasswordStringFormatter.m
// MacPass
//
// Created by Michael Starke on 06.07.13.
// Copyright (c) 2013 HicknHack Software GmbH. All rights reserved.
//
#import "MPPasswordStringFormatter.h"
@implementation MPPasswordStringFormatter
@end

View File

@@ -1,15 +0,0 @@
//
// MPResponderQuery.h
// MacPass
//
// Created by Michael Starke on 11.06.13.
// Copyright (c) 2013 HicknHack Software GmbH. All rights reserved.
//
#import <Foundation/Foundation.h>
@protocol MPResponderQuery <NSObject>
@required
- (BOOL)containsFirstResponder;
@end

View File

@@ -21,7 +21,12 @@
- (void)setTree:(KdbTree *)tree {
if(_tree != tree) {
_tree = tree;
self.groups = @[_tree.root];
if(_tree) {
self.groups = @[_tree.root];
}
else {
self.groups = nil;
}
}
}

View File

@@ -15,6 +15,7 @@ APPKIT_EXTERN NSString *const kMPSettingsKeyClearPasteboardOnQuit;
/* Behaviour */
APPKIT_EXTERN NSString *const kMPSettingsKeyPasswordEncoding;
APPKIT_EXTERN NSString *const kMPSettingsKeyOpenEmptyDatabaseOnLaunch;
APPKIT_EXTERN NSString *const kMPSettingsKeyReopenLastDatabaseOnLaunch;
/* Server Settings */
APPKIT_EXTERN NSString *const kMPSettingsKeyHttpPort;
@@ -25,6 +26,22 @@ APPKIT_EXTERN NSString *const kMPSettingsKeyShowMenuItem;
APPKIT_EXTERN NSString *const kMPSettingsKeyLockOnSleep;
APPKIT_EXTERN NSString *const kMPSettingsKeyIdleLockTimeOut;
/* Autosaving states */
APPKIT_EXTERN NSString *const kMPSettingsKeyShowInspector;
/* Kdb Hide/Show settings */
APPKIT_EXTERN NSString *const kMPSettingsKeyLegacyHideTitle;
APPKIT_EXTERN NSString *const kMPSettingsKeyLegacyHideUsername;
APPKIT_EXTERN NSString *const kMPSettingsKeyLegacyHidePassword;
APPKIT_EXTERN NSString *const kMPSettingsKeyLegacyHideNotes;
APPKIT_EXTERN NSString *const kMPSettingsKeyLegacyHideURL;
/* Document/Key Location store */
APPKIT_EXTERN NSString *const kMPSettingsKeyLastDatabasePath;
/*
APPKIT_EXTERN NSString *const kMPSettingsKeyLastKeyURL;
APPKIT_EXTERN NSString *const kMPSettingsKeyRememberLastKey;
*/
typedef NS_ENUM(NSUInteger, MPPasswordEncoding) {
MPPasswordEncodingUTF8,

View File

@@ -11,11 +11,21 @@
NSString *const kMPSettingsKeyPasteboardClearTimeout = @"ClipboardClearTimeout";
NSString *const kMPSettingsKeyClearPasteboardOnQuit = @"ClearClipboardOnQuit";
NSString *const kMPSettingsKeyOpenEmptyDatabaseOnLaunch = @"OpenEmptyDatabaseOnLaunch";
NSString *const kMPSettingsKeyReopenLastDatabaseOnLaunch = @"ReopenLastDatabaseOnLaunch";
NSString *const kMPSettingsKeyHttpPort =@"HttpPort";
NSString *const kMPSettingsKeyEnableHttpServer = @"EnableHttpServer";
NSString *const kMPSettingsKeyShowMenuItem = @"ShowMenuItem";
NSString *const kMPSettingsKeyLockOnSleep = @"LockOnSleep";
NSString *const kMPSettingsKeyIdleLockTimeOut = @"IdleLockTimeOut";
NSString *const kMPSettingsKeyShowInspector = @"ShowInspector";
NSString *const kMPSettingsKeyLegacyHideTitle = @"LegacyHideTitle";
NSString *const kMPSettingsKeyLegacyHideUsername = @"LegacyHideUsername ";
NSString *const kMPSettingsKeyLegacyHidePassword = @"LegacyHidePassword";
NSString *const kMPSettingsKeyLegacyHideNotes = @"LegacyHideNotes";
NSString *const kMPSettingsKeyLegacyHideURL = @"LegacyHideURL";
NSString *const kMPSettingsKeyLastDatabasePath = @"MPLastDatabasePath";
@implementation MPSettingsHelper
@@ -25,14 +35,21 @@ NSString *const kMPSettingsKeyIdleLockTimeOut = @"IdleLockTimeOut";
+ (NSDictionary *)_standardDefaults {
return @{
kMPSettingsKeyShowInspector: @YES, // Show the Inspector by default
kMPSettingsKeyPasteboardClearTimeout: @30, // 30 seconds
kMPSettingsKeyClearPasteboardOnQuit: @YES,
kMPSettingsKeyOpenEmptyDatabaseOnLaunch: @YES,
kMPSettingsKeyOpenEmptyDatabaseOnLaunch: @NO,
kMPSettingsKeyReopenLastDatabaseOnLaunch: @YES,
kMPSettingsKeyHttpPort: @19455,
kMPSettingsKeyEnableHttpServer: @NO,
kMPSettingsKeyShowMenuItem: @YES,
kMPSettingsKeyLockOnSleep: @YES,
kMPSettingsKeyIdleLockTimeOut: @0 // 5 minutes
kMPSettingsKeyIdleLockTimeOut: @0, // 5 minutes
kMPSettingsKeyLegacyHideNotes: @NO,
kMPSettingsKeyLegacyHidePassword: @YES,
kMPSettingsKeyLegacyHideTitle: @NO,
kMPSettingsKeyLegacyHideURL: @NO,
kMPSettingsKeyLegacyHideUsername: @NO
};
}

View File

@@ -17,7 +17,6 @@
NSString *const MPToolbarItemLock = @"TOOLBAR_LOCK";
NSString *const MPToolbarItemAddGroup = @"TOOLBAR_ADD_GROUP";
NSString *const MPToolbarItemAddEntry = @"TOOLBAR_ADD_ENTRY";
NSString *const MPToolbarItemEdit = @"TOOLBAR_EDIT";
NSString *const MPToolbarItemDelete =@"TOOLBAR_DELETE";
NSString *const MPToolbarItemAction = @"TOOLBAR_ACTION";
NSString *const MPToolbarItemInspector = @"TOOLBAR_INSPECTOR";
@@ -135,7 +134,6 @@ NSString *const MPToolbarItemInspector = @"TOOLBAR_INSPECTOR";
MPToolbarItemAddEntry: NSLocalizedString(@"ADD_ENTRY", @""),
MPToolbarItemAddGroup: NSLocalizedString(@"ADD_GROUP", @""),
MPToolbarItemDelete: NSLocalizedString(@"DELETE", @""),
MPToolbarItemEdit: NSLocalizedString(@"EDIT", @""),
MPToolbarItemInspector: NSLocalizedString(@"INSPECTOR", @"")
};
return labelDict[identifier];
@@ -146,7 +144,6 @@ NSString *const MPToolbarItemInspector = @"TOOLBAR_INSPECTOR";
MPToolbarItemAddEntry: @(MPActionAddEntry),
MPToolbarItemAddGroup: @(MPActionAddGroup),
MPToolbarItemDelete: @(MPActionDelete),
MPToolbarItemEdit: @(MPActionEdit),
MPToolbarItemInspector: @(MPActionToggleInspector)
};
MPActionType actionType = (MPActionType)[actionDict[identifier] integerValue];

View File

@@ -44,11 +44,11 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>0.3</string>
<string>0.3.7</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1960</string>
<string>2521</string>
<key>LSMinimumSystemVersion</key>
<string>${MACOSX_DEPLOYMENT_TARGET}</string>
<key>NSHumanReadableCopyright</key>

View File

@@ -0,0 +1,16 @@
//
// NSDate+Humanized.h
// MacPass
//
// Created by Michael Starke on 10.07.13.
// Copyright (c) 2013 HicknHack Software GmbH. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface NSDate (Humanized)
+ (NSString *)humanizedDate:(NSDate *)date;
- (NSString *)humanized;
@end

View File

@@ -0,0 +1,62 @@
//
// NSDate+Humanized.m
// MacPass
//
// Created by Michael Starke on 10.07.13.
// Copyright (c) 2013 HicknHack Software GmbH. All rights reserved.
//
#import "NSDate+Humanized.h"
@implementation NSDate (Humanized)
+ (NSString *)humanizedDate:(NSDate *)date {
return [date humanized];
}
- (NSString *)humanized {
NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *components = [calendar components:NSMinuteCalendarUnit|NSHourCalendarUnit|NSDayCalendarUnit|NSWeekCalendarUnit|NSMonthCalendarUnit fromDate:self toDate:[NSDate date] options:0];
/* More than one month in the past, give full date */
if([components month] > 1) {
return [NSDateFormatter localizedStringFromDate:self
dateStyle:NSDateFormatterShortStyle
timeStyle:NSDateFormatterShortStyle];
}
NSUInteger weeks = [components week];
/* More than one week, less than a month */
if(weeks > 1) {
NSString *weekTemplate = NSLocalizedString(@"%ld_WEEKS_AGO", "% Weeks ago");
return [NSString stringWithFormat:weekTemplate, weeks];
}
/* One week or more */
if( weeks == 1) {
return NSLocalizedString(@"ONE_WEEK_AGO", "one week ago");
}
/* Last week */
NSUInteger days = [components day];
if(days > 3) {
return NSLocalizedString(@"LAST_WEEK", "last week");
}
/* 1-3 days */
if(days > 1 ) {
NSString *daysTemplate = NSLocalizedString(@"%ld_DAYS_AGO", "% days ago");
return [NSString stringWithFormat:daysTemplate, days];
}
/* Yesterday */
if(days == 1) {
return NSLocalizedString(@"YESTERDAY", "Yesterday");
}
/* Hours ago */
if([components hour] > 1) {
NSString *hourTemplate = NSLocalizedString(@"%ld_HOURS_AGO", "% Hours ago");
return [NSString stringWithFormat:hourTemplate, [components hour]];
}
NSInteger minutes = [components minute];
if(minutes > 1) {
NSString *minuteTemplate = NSLocalizedString(@"%ld_MINUTES_AGO", "% Minutes ago");
return [NSString stringWithFormat:minuteTemplate, minutes];
}
return NSLocalizedString(@"JUST_NOW", "Just now");
}
@end

View File

@@ -1,23 +0,0 @@
//
// NSString+MPPasswordAnalysis.h
// MacPass
//
// Created by Michael Starke on 29.03.13.
// Copyright (c) 2013 HicknHack Software GmbH. All rights reserved.
//
#import <Foundation/Foundation.h>
typedef NS_ENUM(NSUInteger, MPPasswordStrength) {
MPPasswordWeak,
MPPasswordOK,
MPPasswordGood,
MPPasswordStrong,
MPPasswordExcelent,
};
@interface NSString (MPPasswordAnalysis)
- (MPPasswordStrength)passwordStrenght;
@end

View File

@@ -0,0 +1,17 @@
//
// NSString+MPPasswordAnalysis.h
// MacPass
//
// Created by Michael Starke on 29.03.13.
// Copyright (c) 2013 HicknHack Software GmbH. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface NSString (PasswordStrenght)
- (NSUInteger)passwordStrenght;
@end

View File

@@ -6,12 +6,12 @@
// Copyright (c) 2013 HicknHack Software GmbH. All rights reserved.
//
#import "NSString+MPPasswordAnalysis.h"
#import "NSString+PasswordStrength.h"
@implementation NSString (MPPasswordAnalysis)
@implementation NSString (PasswordStrenght)
- (MPPasswordStrength)passwordStrenght {
return MPPasswordOK;
- (NSUInteger)passwordStrenght {
return 0;
}
@end

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="8.00">
<data>
<int key="IBDocument.SystemTarget">1070</int>
<int key="IBDocument.SystemTarget">1080</int>
<string key="IBDocument.SystemVersion">12E55</string>
<string key="IBDocument.InterfaceBuilderVersion">3084</string>
<string key="IBDocument.AppKitVersion">1187.39</string>
@@ -381,8 +381,8 @@
<string key="NSReuseIdentifierKey">_NS:9</string>
<bool key="NSEnabled">YES</bool>
<object class="NSTextFieldCell" key="NSCell" id="608946496">
<int key="NSCellFlags">-1804599231</int>
<int key="NSCellFlags2">272630784</int>
<int key="NSCellFlags">-2075131840</int>
<int key="NSCellFlags2">-1874852864</int>
<string key="NSContents"/>
<reference key="NSSupport" ref="510117885"/>
<string key="NSCellIdentifier">_NS:9</string>
@@ -1189,6 +1189,7 @@
<object class="IBObjectRecord">
<int key="objectID">183</int>
<reference key="object" ref="608946496"/>
<array class="NSMutableArray" key="children"/>
<reference key="parent" ref="240019321"/>
</object>
<object class="IBObjectRecord">
@@ -1987,7 +1988,7 @@
<nil key="activeLocalization"/>
<dictionary class="NSMutableDictionary" key="localizations"/>
<nil key="sourceID"/>
<int key="maxID">623</int>
<int key="maxID">626</int>
</object>
<object class="IBClassDescriber" key="IBDocument.Classes">
<array class="NSMutableArray" key="referencedPartialClassDescriptions">
@@ -2003,11 +2004,16 @@
<string key="className">MPPasswordCreatorViewController</string>
<string key="superclassName">MPViewController</string>
<dictionary class="NSMutableDictionary" key="actions">
<string key="_cancel:">id</string>
<string key="_generatePassword:">id</string>
<string key="_toggleCharacters:">id</string>
<string key="_usePassword:">id</string>
</dictionary>
<dictionary class="NSMutableDictionary" key="actionInfosByName">
<object class="IBActionInfo" key="_cancel:">
<string key="name">_cancel:</string>
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo" key="_generatePassword:">
<string key="name">_generatePassword:</string>
<string key="candidateClassName">id</string>
@@ -2022,7 +2028,6 @@
</object>
</dictionary>
<dictionary class="NSMutableDictionary" key="outlets">
<string key="_cancel">NSButton</string>
<string key="addPasswordToPasteboardButton">NSButton</string>
<string key="customButton">NSButton</string>
<string key="customCharactersTextField">NSTextField</string>
@@ -2035,10 +2040,6 @@
<string key="upperCaseButton">NSButton</string>
</dictionary>
<dictionary class="NSMutableDictionary" key="toOneOutletInfosByName">
<object class="IBToOneOutletInfo" key="_cancel">
<string key="name">_cancel</string>
<string key="candidateClassName">NSButton</string>
</object>
<object class="IBToOneOutletInfo" key="addPasswordToPasteboardButton">
<string key="name">addPasswordToPasteboardButton</string>
<string key="candidateClassName">NSButton</string>
@@ -2105,9 +2106,9 @@
</object>
<int key="IBDocument.localizationMode">0</int>
<string key="IBDocument.TargetRuntimeIdentifier">IBCocoaFramework</string>
<object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDependencies">
<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin.macosx</string>
<integer value="1070" key="NS.object.0"/>
<object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDevelopmentDependencies">
<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin.InterfaceBuilder3</string>
<real value="4600" key="NS.object.0"/>
</object>
<bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>
<int key="IBDocument.defaultPropertyAccessControl">3</int>

View File

@@ -0,0 +1,13 @@
//
// StringField+Validation.h
// MacPass
//
// Created by Michael Starke on 19.07.13.
// Copyright (c) 2013 HicknHack Software GmbH. All rights reserved.
//
#import "Kdb4Node.h"
@interface StringField (Validation)
@end

View File

@@ -0,0 +1,19 @@
//
// StringField+Validation.m
// MacPass
//
// Created by Michael Starke on 19.07.13.
// Copyright (c) 2013 HicknHack Software GmbH. All rights reserved.
//
#import "StringField+Validation.h"
#import "Kdb4Entry+MPAdditions.h"
@implementation StringField (Validation)
- (BOOL)validateValue:(inout __autoreleasing id *)ioValue forKey:(NSString *)inKey error:(out NSError *__autoreleasing *)outError {
*ioValue = [self.entry uniqueKeyForProposal:*ioValue];
return YES;
}
@end

View File

@@ -0,0 +1,434 @@
<?xml version="1.0" encoding="UTF-8"?>
<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="8.00">
<data>
<int key="IBDocument.SystemTarget">1080</int>
<string key="IBDocument.SystemVersion">12E55</string>
<string key="IBDocument.InterfaceBuilderVersion">3084</string>
<string key="IBDocument.AppKitVersion">1187.39</string>
<string key="IBDocument.HIToolboxVersion">626.00</string>
<object class="NSMutableDictionary" key="IBDocument.PluginVersions">
<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="NS.object.0">3084</string>
</object>
<array key="IBDocument.IntegratedClassDependencies">
<string>IBNSLayoutConstraint</string>
<string>NSCustomObject</string>
<string>NSCustomView</string>
<string>NSImageCell</string>
<string>NSImageView</string>
<string>NSTextField</string>
<string>NSTextFieldCell</string>
</array>
<array key="IBDocument.PluginDependencies">
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
</array>
<object class="NSMutableDictionary" key="IBDocument.Metadata">
<string key="NS.key.0">PluginDependencyRecalculationVersion</string>
<integer value="1" key="NS.object.0"/>
</object>
<array class="NSMutableArray" key="IBDocument.RootObjects" id="1000">
<object class="NSCustomObject" id="1001">
<string key="NSClassName">MPDocument</string>
</object>
<object class="NSCustomObject" id="1003">
<string key="NSClassName">FirstResponder</string>
</object>
<object class="NSCustomObject" id="1004">
<string key="NSClassName">NSApplication</string>
</object>
<object class="NSCustomView" id="1005">
<reference key="NSNextResponder"/>
<int key="NSvFlags">268</int>
<array class="NSMutableArray" key="NSSubviews">
<object class="NSImageView" id="914116063">
<reference key="NSNextResponder" ref="1005"/>
<int key="NSvFlags">268</int>
<set class="NSMutableSet" key="NSDragTypes">
<string>Apple PDF pasteboard type</string>
<string>Apple PICT pasteboard type</string>
<string>Apple PNG pasteboard type</string>
<string>NSFilenamesPboardType</string>
<string>NeXT Encapsulated PostScript v1.2 pasteboard type</string>
<string>NeXT TIFF v4.0 pasteboard type</string>
</set>
<string key="NSFrame">{{36, 19}, {32, 32}}</string>
<reference key="NSSuperview" ref="1005"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="724782086"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<bool key="NSEnabled">YES</bool>
<object class="NSImageCell" key="NSCell" id="869029655">
<int key="NSCellFlags">134217728</int>
<int key="NSCellFlags2">33554432</int>
<object class="NSCustomResource" key="NSContents">
<string key="NSClassName">NSImage</string>
<string key="NSResourceName">02_MessageBoxWarningTemplate</string>
</object>
<string key="NSCellIdentifier">_NS:9</string>
<int key="NSAlign">0</int>
<int key="NSScale">3</int>
<int key="NSStyle">0</int>
<bool key="NSAnimates">NO</bool>
</object>
<bool key="NSAllowsLogicalLayoutDirection">NO</bool>
<bool key="NSEditable">YES</bool>
</object>
<object class="NSTextField" id="724782086">
<reference key="NSNextResponder" ref="1005"/>
<int key="NSvFlags">268</int>
<string key="NSFrame">{{73, 27}, {162, 17}}</string>
<reference key="NSSuperview" ref="1005"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView"/>
<string key="NSReuseIdentifierKey">_NS:1535</string>
<bool key="NSEnabled">YES</bool>
<object class="NSTextFieldCell" key="NSCell" id="470987877">
<int key="NSCellFlags">68157504</int>
<int key="NSCellFlags2">272630784</int>
<string key="NSContents">Database is unprotected!</string>
<object class="NSFont" key="NSSupport">
<string key="NSName">LucidaGrande</string>
<double key="NSSize">13</double>
<int key="NSfFlags">1044</int>
</object>
<string key="NSCellIdentifier">_NS:1535</string>
<reference key="NSControlView" ref="724782086"/>
<object class="NSColor" key="NSBackgroundColor">
<int key="NSColorSpace">6</int>
<string key="NSCatalogName">System</string>
<string key="NSColorName">controlColor</string>
<object class="NSColor" key="NSColor">
<int key="NSColorSpace">3</int>
<bytes key="NSWhite">MC42NjY2NjY2NjY3AA</bytes>
</object>
</object>
<object class="NSColor" key="NSTextColor">
<int key="NSColorSpace">6</int>
<string key="NSCatalogName">System</string>
<string key="NSColorName">controlTextColor</string>
<object class="NSColor" key="NSColor">
<int key="NSColorSpace">3</int>
<bytes key="NSWhite">MAA</bytes>
</object>
</object>
</object>
<bool key="NSAllowsLogicalLayoutDirection">NO</bool>
</object>
</array>
<string key="NSFrameSize">{307, 71}</string>
<reference key="NSSuperview"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="914116063"/>
<string key="NSClassName">NSView</string>
</object>
</array>
<object class="IBObjectContainer" key="IBDocument.Objects">
<array class="NSMutableArray" key="connectionRecords">
<object class="IBConnectionRecord">
<object class="IBOutletConnection" key="connection">
<string key="label">warningView</string>
<reference key="source" ref="1001"/>
<reference key="destination" ref="1005"/>
</object>
<int key="connectionID">24</int>
</object>
<object class="IBConnectionRecord">
<object class="IBOutletConnection" key="connection">
<string key="label">warningViewImage</string>
<reference key="source" ref="1001"/>
<reference key="destination" ref="914116063"/>
</object>
<int key="connectionID">36</int>
</object>
</array>
<object class="IBMutableOrderedSet" key="objectRecords">
<array key="orderedObjects">
<object class="IBObjectRecord">
<int key="objectID">0</int>
<array key="object" id="0"/>
<reference key="children" ref="1000"/>
<nil key="parent"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">-2</int>
<reference key="object" ref="1001"/>
<reference key="parent" ref="0"/>
<string key="objectName">File's Owner</string>
</object>
<object class="IBObjectRecord">
<int key="objectID">-1</int>
<reference key="object" ref="1003"/>
<reference key="parent" ref="0"/>
<string key="objectName">First Responder</string>
</object>
<object class="IBObjectRecord">
<int key="objectID">-3</int>
<reference key="object" ref="1004"/>
<reference key="parent" ref="0"/>
<string key="objectName">Application</string>
</object>
<object class="IBObjectRecord">
<int key="objectID">1</int>
<reference key="object" ref="1005"/>
<array class="NSMutableArray" key="children">
<reference ref="724782086"/>
<object class="IBNSLayoutConstraint" id="723389949">
<reference key="firstItem" ref="724782086"/>
<int key="firstAttribute">5</int>
<int key="relation">0</int>
<reference key="secondItem" ref="914116063"/>
<int key="secondAttribute">6</int>
<float key="multiplier">1</float>
<object class="IBNSLayoutSymbolicConstant" key="constant">
<double key="value">8</double>
</object>
<float key="priority">1000</float>
<reference key="containingView" ref="1005"/>
<int key="scoringType">6</int>
<float key="scoringTypeFloat">24</float>
<int key="contentType">3</int>
</object>
<object class="IBNSLayoutConstraint" id="108837154">
<reference key="firstItem" ref="724782086"/>
<int key="firstAttribute">9</int>
<int key="relation">0</int>
<reference key="secondItem" ref="1005"/>
<int key="secondAttribute">9</int>
<float key="multiplier">1</float>
<object class="IBLayoutConstant" key="constant">
<double key="value">0.0</double>
</object>
<float key="priority">1000</float>
<reference key="containingView" ref="1005"/>
<int key="scoringType">9</int>
<float key="scoringTypeFloat">40</float>
<int key="contentType">2</int>
</object>
<object class="IBNSLayoutConstraint" id="165398105">
<reference key="firstItem" ref="914116063"/>
<int key="firstAttribute">3</int>
<int key="relation">0</int>
<reference key="secondItem" ref="1005"/>
<int key="secondAttribute">3</int>
<float key="multiplier">1</float>
<object class="IBNSLayoutSymbolicConstant" key="constant">
<double key="value">20</double>
</object>
<float key="priority">1000</float>
<reference key="containingView" ref="1005"/>
<int key="scoringType">8</int>
<float key="scoringTypeFloat">29</float>
<int key="contentType">3</int>
</object>
<object class="IBNSLayoutConstraint" id="560291886">
<reference key="firstItem" ref="914116063"/>
<int key="firstAttribute">10</int>
<int key="relation">0</int>
<reference key="secondItem" ref="724782086"/>
<int key="secondAttribute">10</int>
<float key="multiplier">1</float>
<object class="IBLayoutConstant" key="constant">
<double key="value">0.0</double>
</object>
<float key="priority">1000</float>
<reference key="containingView" ref="1005"/>
<int key="scoringType">6</int>
<float key="scoringTypeFloat">24</float>
<int key="contentType">2</int>
</object>
<object class="IBNSLayoutConstraint" id="425703234">
<reference key="firstItem" ref="914116063"/>
<int key="firstAttribute">5</int>
<int key="relation">1</int>
<reference key="secondItem" ref="1005"/>
<int key="secondAttribute">5</int>
<float key="multiplier">1</float>
<object class="IBNSLayoutSymbolicConstant" key="constant">
<double key="value">20</double>
</object>
<float key="priority">1000</float>
<reference key="containingView" ref="1005"/>
<int key="scoringType">9</int>
<float key="scoringTypeFloat">40</float>
<int key="contentType">3</int>
</object>
<reference ref="914116063"/>
</array>
<reference key="parent" ref="0"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">2</int>
<reference key="object" ref="724782086"/>
<array class="NSMutableArray" key="children">
<reference ref="470987877"/>
</array>
<reference key="parent" ref="1005"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">4</int>
<reference key="object" ref="108837154"/>
<reference key="parent" ref="1005"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">3</int>
<reference key="object" ref="470987877"/>
<reference key="parent" ref="724782086"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">25</int>
<reference key="object" ref="914116063"/>
<array class="NSMutableArray" key="children">
<reference ref="869029655"/>
<object class="IBNSLayoutConstraint" id="622632481">
<reference key="firstItem" ref="914116063"/>
<int key="firstAttribute">8</int>
<int key="relation">0</int>
<nil key="secondItem"/>
<int key="secondAttribute">0</int>
<float key="multiplier">1</float>
<object class="IBLayoutConstant" key="constant">
<double key="value">32</double>
</object>
<float key="priority">1000</float>
<reference key="containingView" ref="914116063"/>
<int key="scoringType">3</int>
<float key="scoringTypeFloat">9</float>
<int key="contentType">1</int>
</object>
<object class="IBNSLayoutConstraint" id="939990693">
<reference key="firstItem" ref="914116063"/>
<int key="firstAttribute">7</int>
<int key="relation">0</int>
<nil key="secondItem"/>
<int key="secondAttribute">0</int>
<float key="multiplier">1</float>
<object class="IBLayoutConstant" key="constant">
<double key="value">32</double>
</object>
<float key="priority">1000</float>
<reference key="containingView" ref="914116063"/>
<int key="scoringType">3</int>
<float key="scoringTypeFloat">9</float>
<int key="contentType">1</int>
</object>
</array>
<reference key="parent" ref="1005"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">26</int>
<reference key="object" ref="869029655"/>
<reference key="parent" ref="914116063"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">35</int>
<reference key="object" ref="425703234"/>
<reference key="parent" ref="1005"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">38</int>
<reference key="object" ref="939990693"/>
<reference key="parent" ref="914116063"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">39</int>
<reference key="object" ref="622632481"/>
<reference key="parent" ref="914116063"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">41</int>
<reference key="object" ref="560291886"/>
<reference key="parent" ref="1005"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">42</int>
<reference key="object" ref="165398105"/>
<reference key="parent" ref="1005"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">43</int>
<reference key="object" ref="723389949"/>
<reference key="parent" ref="1005"/>
</object>
</array>
</object>
<dictionary class="NSMutableDictionary" key="flattenedProperties">
<string key="-1.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="-2.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="-3.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<array class="NSMutableArray" key="1.IBNSViewMetadataConstraints">
<reference ref="425703234"/>
<reference ref="560291886"/>
<reference ref="165398105"/>
<reference ref="108837154"/>
<reference ref="723389949"/>
</array>
<string key="1.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<boolean value="NO" key="2.IBNSViewMetadataTranslatesAutoresizingMaskIntoConstraints"/>
<string key="2.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<array class="NSMutableArray" key="25.IBNSViewMetadataConstraints">
<reference ref="939990693"/>
<reference ref="622632481"/>
</array>
<boolean value="NO" key="25.IBNSViewMetadataTranslatesAutoresizingMaskIntoConstraints"/>
<string key="25.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="26.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="3.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="35.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="38.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="39.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="4.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="41.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="42.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="43.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
</dictionary>
<dictionary class="NSMutableDictionary" key="unlocalizedProperties"/>
<nil key="activeLocalization"/>
<dictionary class="NSMutableDictionary" key="localizations"/>
<nil key="sourceID"/>
<int key="maxID">43</int>
</object>
<object class="IBClassDescriber" key="IBDocument.Classes">
<array class="NSMutableArray" key="referencedPartialClassDescriptions">
<object class="IBPartialClassDescription">
<string key="className">MPDocument</string>
<string key="superclassName">NSDocument</string>
<dictionary class="NSMutableDictionary" key="outlets">
<string key="warningView">NSView</string>
<string key="warningViewImage">NSImageView</string>
</dictionary>
<dictionary class="NSMutableDictionary" key="toOneOutletInfosByName">
<object class="IBToOneOutletInfo" key="warningView">
<string key="name">warningView</string>
<string key="candidateClassName">NSView</string>
</object>
<object class="IBToOneOutletInfo" key="warningViewImage">
<string key="name">warningViewImage</string>
<string key="candidateClassName">NSImageView</string>
</object>
</dictionary>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBProjectSource</string>
<string key="minorKey">./Classes/MPDocument.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSLayoutConstraint</string>
<string key="superclassName">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBProjectSource</string>
<string key="minorKey">./Classes/NSLayoutConstraint.h</string>
</object>
</object>
</array>
</object>
<int key="IBDocument.localizationMode">0</int>
<string key="IBDocument.TargetRuntimeIdentifier">IBCocoaFramework</string>
<bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>
<int key="IBDocument.defaultPropertyAccessControl">3</int>
<object class="NSMutableDictionary" key="IBDocument.LastKnownImageSizes">
<string key="NS.key.0">02_MessageBoxWarningTemplate</string>
<string key="NS.object.0">{128, 128}</string>
</object>
<bool key="IBDocument.UseAutolayout">YES</bool>
</data>
</archive>

View File

@@ -1,7 +1,7 @@
{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf390
{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
{\colortbl;\red255\green255\blue255;\red52\green110\blue183;\red38\green38\blue38;}
\paperw11900\paperh16840\vieww28040\viewh7240\viewkind0
\paperw11900\paperh16840\vieww19440\viewh14240\viewkind0
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720
\f0\b\fs24 \cf0 Projekt Webseite:\
@@ -37,6 +37,7 @@ You should have received a copy of the GNU General Public License along with thi
\b0 \cf3 \
Copyright \'a9 2012 Robbie Hanson. Alle Rechte vorbehalten.\
\
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720
{\field{\*\fldinst{HYPERLINK "https://github.com/MiniKeePass/MiniKeePass"}}{\fldrslt \cf2 MiniKeePass}}\
Copyright \'a9 2011 Jason Rush und John Flanagan. Alle Rechte vorbehalten.\
\
@@ -50,9 +51,20 @@ Copyright \'a9 2011, Alex Rozanski. Alle Rechte vorbehalten.\
\
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720
{\field{\*\fldinst{HYPERLINK "http://stackoverflow.com/questions/11386876/how-to-encode-and-decode-files-as-base64-in-cocoa-objective-c"}}{\fldrslt \cf3 Base64 Encoding Category}}\
Copyright @2013, {\field{\*\fldinst{HYPERLINK "http://stackoverflow.com/users/200321/denis2342"}}{\fldrslt denis2342}}\
Copyright \'a92013, {\field{\*\fldinst{HYPERLINK "http://stackoverflow.com/users/200321/denis2342"}}{\fldrslt denis2342}}\
\
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720
{\field{\*\fldinst{HYPERLINK "http://www.cocoadev.com/index.pl?NSDataCategory"}}{\fldrslt \cf3 NSData+Gzip}}\
Basierend auf dem Code im CocoaDev Wiki\
}
\
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720
{\field{\*\fldinst{HYPERLINK "https://github.com/karelia/SecurityInterface"}}{\fldrslt \cf3 KSPasswordField}}\cf3 \kerning1\expnd0\expndtw3
\
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720
\cf3 \kerning1\expnd0\expndtw0 Quelltext wird in HNHRoundedSecureTextField verwendet\cf3 \kerning1\expnd0\expndtw3
\
\cf3 \kerning1\expnd0\expndtw0 Copyright \'a92012 Mike Abdullah, Karelia Software. Alle Rechte vorbehalten.\
\
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720
{\field{\*\fldinst{HYPERLINK "https://github.com/AlanQuatermain/aqtoolkit"}}{\fldrslt \cf3 NSData+CommonCrypto}}\
Copyright \'a92008-2009 Jim Dovey, Alle Rechte vorbehalten.}

Binary file not shown.

View File

@@ -1,30 +1,48 @@
/* Class = "NSMenu"; title = "OtherViews"; ObjectID = "421"; */
"421.title" = "OtherViews";
/* Class = "NSMenu"; title = "ClipboardClearInterval"; ObjectID = "421"; */
"421.title" = "ClipboardClearInterval";
/* Class = "NSMenuItem"; title = "10 Seconds"; ObjectID = "422"; */
"422.title" = "10 Sekunden";
/* Class = "NSMenuItem"; title = "after 10 Seconds"; ObjectID = "422"; */
"422.title" = "nach 10 Sekunden";
/* Class = "NSMenuItem"; title = "30 Seconds"; ObjectID = "423"; */
"423.title" = "30 Sekunden";
/* Class = "NSMenuItem"; title = "after 30 Seconds"; ObjectID = "423"; */
"423.title" = "nach 30 Sekunden";
/* Class = "NSMenuItem"; title = "1 Minute"; ObjectID = "424"; */
"424.title" = "1 Minute";
/* Class = "NSMenuItem"; title = "after 1 Minute"; ObjectID = "424"; */
"424.title" = "nach 1 Minute";
/* Class = "NSMenuItem"; title = "Never"; ObjectID = "429"; */
"429.title" = "Nie";
/* Class = "NSTextFieldCell"; title = "Clear Copied Items"; ObjectID = "432"; */
"432.title" = "Zwischenablage Leere";
"432.title" = "Leere Zwischenablage";
/* Class = "NSButtonCell"; title = "Clear Clipboard on Quit"; ObjectID = "448"; */
"448.title" = "Zwischenablage beim Beenden leeren";
/* Class = "NSBox"; title = "Clipboard"; ObjectID = "465"; */
"465.title" = "Zwischenablage";
/* Class = "NSBox"; title = "Security"; ObjectID = "465"; */
"465.title" = "Sicherheit";
/* Class = "NSButtonCell"; title = "Open empty database on launch"; ObjectID = "527"; */
"527.title" = "Leere Datenbank beim Programmstart öffnen";
/* Class = "NSButtonCell"; title = "Reopen last Database after Launch"; ObjectID = "531"; */
"531.title" = "Letzte Datenbank beim Start wieder öffnen";
/* Class = "NSButtonCell"; title = "Open empty database on activate"; ObjectID = "531"; */
"531.title" = "Lerre Datenbank beim Aktiveren öffnen";
/* Class = "NSMenu"; title = "LockTimes"; ObjectID = "586"; */
"586.title" = "LockTimes";
/* Class = "NSMenuItem"; title = "for 1 Minute"; ObjectID = "588"; */
"588.title" = "für 1 Minute";
/* Class = "NSMenuItem"; title = "for 5 Minutes"; ObjectID = "589"; */
"589.title" = "für 5 Minuten";
/* Class = "NSMenuItem"; title = "for 15 Minutes"; ObjectID = "603"; */
"603.title" = "für 15 Minuten";
/* Class = "NSButtonCell"; title = "Lock after sleep"; ObjectID = "631"; */
"631.title" = "Datenbank im Ruhezustand sperren";
/* Class = "NSMenuItem"; title = "Never"; ObjectID = "804"; */
"804.title" = "Nie";
/* Class = "NSTextFieldCell"; title = "Lock while idle"; ObjectID = "806"; */
"806.title" = "Sperren nach Inaktivität";

Binary file not shown.

View File

@@ -120,19 +120,22 @@
"298.title" = "Customize Toolbar…";
/* Class = "NSMenuItem"; title = "Help"; ObjectID = "490"; */
"490.title" = "Help";
"490.title" = "Hilfe";
/* Class = "NSMenu"; title = "Help"; ObjectID = "491"; */
"491.title" = "Help";
"491.title" = "Hilfe";
/* Class = "NSMenuItem"; title = "MacPass Help"; ObjectID = "492"; */
"492.title" = "MacPass Help";
"492.title" = "MacPass Hilfe";
/* Class = "NSMenuItem"; title = "Toggle Inspector"; ObjectID = "1181"; */
"1181.title" = "Toggle Inspector";
"1181.title" = "Inspector umschalten";
/* Class = "NSMenuItem"; title = "Show Password Creator"; ObjectID = "1200"; */
"1200.title" = "Passwortgenerator anzeigen…";
"1200.title" = "Passwortgenerator";
/* Class = "NSMenuItem"; title = "Change Password…"; ObjectID = "1203"; */
"1203.title" = "Hautpassword ändern…";
/* Class = "NSMenuItem"; title = "Change Master Password…"; ObjectID = "1203"; */
"1203.title" = "Hauptpassword ändern…";
/* Class = "NSMenuItem"; title = "Database Settings…"; ObjectID = "1231"; */
"1231.title" = "Datenbankeinstellungen…";

View File

@@ -1,15 +0,0 @@
/* Class = "NSButtonCell"; title = "Change"; ObjectID = "32"; */
"32.title" = "Password ändern";
/* Class = "NSTextFieldCell"; title = "Password"; ObjectID = "33"; */
"33.title" = "Passwort";
/* Class = "NSTextFieldCell"; title = "Keyfile"; ObjectID = "37"; */
"37.title" = "Schlüsseldatei";
/* Class = "NSButtonCell"; title = "Cancel"; ObjectID = "38"; */
"38.title" = "Abbrechen";
/* Class = "NSTextFieldCell"; title = "Change Password/Keyfile"; ObjectID = "46"; */
"46.title" = "Password/Schlüssel ändern!";

View File

@@ -40,6 +40,7 @@ You should have received a copy of the GNU General Public License along with thi
{\field{\*\fldinst{HYPERLINK "https://github.com/robbiehanson/KissXML"}}{\fldrslt \cf2 KissXML}}\cf3 \
Copyright \'a9 2012 Robbie Hanson. All rights reserved.\
\
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720
{\field{\*\fldinst{HYPERLINK "https://github.com/MiniKeePass/MiniKeePass"}}{\fldrslt \cf2 MiniKeePass}}\
Copyright \'a9 2011 Jason Rush and John Flanagan. All rights reserved.\
\
@@ -53,9 +54,17 @@ Copyright \'a9 2011, Alex Rozanski. All rights reserved.\
\
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720
{\field{\*\fldinst{HYPERLINK "http://stackoverflow.com/questions/11386876/how-to-encode-and-decode-files-as-base64-in-cocoa-objective-c"}}{\fldrslt \cf3 NSData+Base64}}\
Copyright @2013, {\field{\*\fldinst{HYPERLINK "http://stackoverflow.com/users/200321/denis2342"}}{\fldrslt denis2342}}\
Copyright \'a92013, {\field{\*\fldinst{HYPERLINK "http://stackoverflow.com/users/200321/denis2342"}}{\fldrslt denis2342}}\
\
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720
{\field{\*\fldinst{HYPERLINK "http://www.cocoadev.com/index.pl?NSDataCategory"}}{\fldrslt \cf3 NSData+Gzip}}\
Extracted from code on the CocoaDev Wiki\
}
\
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720
{\field{\*\fldinst{HYPERLINK "https://github.com/karelia/SecurityInterface"}}{\fldrslt \cf3 KSPasswordField}}\
Code reused in HNHRoundedSecureTextField\
Copyright \'a92012 Mike Abdullah, Karelia Software. All rights reserved.\
\
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720
{\field{\*\fldinst{HYPERLINK "https://github.com/AlanQuatermain/aqtoolkit"}}{\fldrslt \cf3 NSData+CommonCrypto}}\
Copyright \'a92008-2009 Jim Dovey, All rights reserved.}

Binary file not shown.

View File

@@ -2,14 +2,14 @@
/* Class = "NSMenu"; title = "ClipboardClearInterval"; ObjectID = "421"; */
"421.title" = "ClipboardClearInterval";
/* Class = "NSMenuItem"; title = "10 Seconds"; ObjectID = "422"; */
"422.title" = "10 Seconds";
/* Class = "NSMenuItem"; title = "after 10 Seconds"; ObjectID = "422"; */
"422.title" = "after 10 Seconds";
/* Class = "NSMenuItem"; title = "30 Seconds"; ObjectID = "423"; */
"423.title" = "30 Seconds";
/* Class = "NSMenuItem"; title = "after 30 Seconds"; ObjectID = "423"; */
"423.title" = "after 30 Seconds";
/* Class = "NSMenuItem"; title = "1 Minute"; ObjectID = "424"; */
"424.title" = "1 Minute";
/* Class = "NSMenuItem"; title = "after 1 Minute"; ObjectID = "424"; */
"424.title" = "after 1 Minute";
/* Class = "NSMenuItem"; title = "Never"; ObjectID = "429"; */
"429.title" = "Never";
@@ -23,26 +23,26 @@
/* Class = "NSBox"; title = "Security"; ObjectID = "465"; */
"465.title" = "Security";
/* Class = "NSButtonCell"; title = "Open empty database on launch"; ObjectID = "527"; */
"527.title" = "Open empty database on launch";
/* Class = "NSButtonCell"; title = "Open empty database on activate"; ObjectID = "531"; */
"531.title" = "Open empty database on activate";
/* Class = "NSButtonCell"; title = "Reopen last Database after Launch"; ObjectID = "531"; */
"531.title" = "Reopen last Database after Launch";
/* Class = "NSMenu"; title = "LockTimes"; ObjectID = "586"; */
"586.title" = "LockTimes";
/* Class = "NSMenuItem"; title = "1 Minute"; ObjectID = "588"; */
"588.title" = "1 Minute";
/* Class = "NSMenuItem"; title = "for 1 Minute"; ObjectID = "588"; */
"588.title" = "for 1 Minute";
/* Class = "NSMenuItem"; title = "5 Minutes"; ObjectID = "589"; */
"589.title" = "5 Minutes";
/* Class = "NSMenuItem"; title = "for 5 Minutes"; ObjectID = "589"; */
"589.title" = "for 5 Minutes";
/* Class = "NSMenuItem"; title = "15 Minutes"; ObjectID = "603"; */
"603.title" = "15 Minutes";
/* Class = "NSButtonCell"; title = "Lock while idle for"; ObjectID = "606"; */
"606.title" = "Lock while idle for";
/* Class = "NSMenuItem"; title = "for 15 Minutes"; ObjectID = "603"; */
"603.title" = "for 15 Minutes";
/* Class = "NSButtonCell"; title = "Lock after sleep"; ObjectID = "631"; */
"631.title" = "Lock after sleep";
/* Class = "NSMenuItem"; title = "Never"; ObjectID = "804"; */
"804.title" = "Never";
/* Class = "NSTextFieldCell"; title = "Lock while idle"; ObjectID = "806"; */
"806.title" = "Lock while idle";

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More