84 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
michael starke
628fbbfeda Removal off attachments included 2013-07-05 20:50:38 +02:00
michael starke
9c3a62bef6 Added support to save and load Attachemnts on KeePass2 Databases.
Support for Keepass1 DBs is still missing
2013-07-05 20:09:17 +02:00
michael starke
7feb2517dd Added a default Database name
Minor changes
Updtaed KeePassLib
2013-07-05 16:37:35 +02:00
michael starke
59db224a35 OutlineView group now displays the database name if a KeePass 2 database is used 2013-07-05 01:06:02 +02:00
michael starke
c32003d7c6 Merge branch 'master' of https://github.com/mstarke/MacPass 2013-07-04 23:55:21 +02:00
michael starke
1a095ce1d7 Added Icon supplied by Iiro Jäppinen
Added more KeePass Icon replacements
2013-07-04 23:54:45 +02:00
Michael Starke
7b8ce088fe Updated releases 2013-07-04 00:09:07 +02:00
160 changed files with 8989 additions and 4021 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

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 140 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 140 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 396 KiB

BIN
Assets/App icon/PSD.zip Normal file

Binary file not shown.

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.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

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

@@ -15,5 +15,9 @@
- (void)removeObjectFromStringFieldsAtIndex:(NSUInteger)anIndex;
- (void)insertObject:(StringField *)stringfield inStringFieldsAtIndex:(NSUInteger)anIndex;
- (NSUInteger)countOfBinaries;
- (BinaryRef *)objectInBinariesAtIndex:(NSUInteger)index;
- (void)removeObjectFromBinariesAtIndex:(NSUInteger)index;
- (void)insertObject:(BinaryRef *)binary inBinariesAtIndex:(NSUInteger)index;
@end

View File

@@ -10,6 +10,7 @@
@implementation Kdb4Entry (KVOAdditions)
/* Entries */
- (NSUInteger)countOfStringFields {
return [self.stringFields count];
}
@@ -26,4 +27,21 @@
[self.stringFields removeObjectAtIndex:anIndex];
}
/* Binaries */
- (NSUInteger)countOfBinaries {
return [self.binaries count];
}
- (BinaryRef *)objectInBinariesAtIndex:(NSUInteger)index {
return (self.binaries)[index];
}
- (void)insertObject:(BinaryRef *)binary inBinariesAtIndex:(NSUInteger)index {
[self.binaries insertObject:binary atIndex:index];
}
- (void)removeObjectFromBinariesAtIndex:(NSUInteger)index {
[self.binaries removeObjectAtIndex:index];
}
@end

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

@@ -11,5 +11,6 @@
@interface Kdb4Tree (NewTree)
+(Kdb4Tree *)templateTree;
+(Kdb4Tree *)demoTree;
@end

View File

@@ -15,7 +15,7 @@
Kdb4Tree *tree = [[Kdb4Tree alloc] init];
tree.generator = @"MacPass";
tree.databaseName = @"";
tree.databaseName = NSLocalizedString(@"DATABASE", "");
tree.databaseNameChanged = currentTime;
tree.databaseDescription = @"";
tree.databaseDescriptionChanged = currentTime;
@@ -41,35 +41,81 @@
tree.lastSelectedGroup = [UUID nullUuid];
tree.lastTopVisibleGroup = [UUID nullUuid];
KdbGroup *parentGroup = [tree createGroup:nil];
parentGroup.name = NSLocalizedString(@"GENERAL", "General");
parentGroup.image = 48;
tree.root = parentGroup;
KdbGroup *group = [tree createGroup:parentGroup];
group.name = NSLocalizedString(@"WINDOWS", "Windows");
group.image = 38;
[parentGroup addGroup:group];
group = [tree createGroup:parentGroup];
group.name = NSLocalizedString(@"NETWORK", "Network");
group.image = 3;
[parentGroup addGroup:group];
group = [tree createGroup:parentGroup];
group.name = NSLocalizedString(@"INTERNET", "Internet");
group.image = 1;
[parentGroup addGroup:group];
group = [tree createGroup:parentGroup];
group.name = NSLocalizedString(@"EMAIL", "EMail");
group.image = 19;
[parentGroup addGroup:group];
group = [tree createGroup:parentGroup];
group.name = NSLocalizedString(@"HOMEBANKING", "Homebanking");
group.image = 37;
[parentGroup addGroup:group];
return tree;
}
+ (Kdb4Tree *)demoTree {
NSDate *currentTime = [NSDate date];
Kdb4Tree *tree = [[Kdb4Tree alloc] init];
tree.generator = @"MacPass";
tree.databaseName = @"Icon Demonstation";
tree.databaseNameChanged = currentTime;
tree.databaseDescription = @"This database just has all default icons as groups in the tree";
tree.databaseDescriptionChanged = currentTime;
tree.defaultUserName = @"";
tree.defaultUserNameChanged = currentTime;
tree.maintenanceHistoryDays = 365;
tree.color = @"";
tree.masterKeyChanged = currentTime;
tree.masterKeyChangeRec = -1;
tree.masterKeyChangeForce = -1;
tree.protectTitle = NO;
tree.protectUserName = NO;
tree.protectPassword = YES;
tree.protectUrl = NO;
tree.protectNotes = NO;
tree.recycleBinEnabled = YES;
tree.recycleBinUuid = [UUID nullUuid];
tree.recycleBinChanged = currentTime;
tree.entryTemplatesGroup = [UUID nullUuid];
tree.entryTemplatesGroupChanged = currentTime;
tree.historyMaxItems = 10;
tree.historyMaxSize = 6 * 1024 * 1024; // 6 MB
tree.lastSelectedGroup = [UUID nullUuid];
tree.lastTopVisibleGroup = [UUID nullUuid];
KdbGroup *parentGroup = [tree createGroup:nil];
parentGroup.name = @"General";
parentGroup.image = 48;
tree.root = parentGroup;
for(NSUInteger iImageIndex = 0; iImageIndex < 69; iImageIndex++) {
KdbGroup *group = [tree createGroup:parentGroup];
group.name = @"Windows";
group.image = 38;
[parentGroup addGroup:group];
group = [tree createGroup:parentGroup];
group.name = @"Network";
group.image = 3;
[parentGroup addGroup:group];
group = [tree createGroup:parentGroup];
group.name = @"Internet";
group.image = 1;
[parentGroup addGroup:group];
group = [tree createGroup:parentGroup];
group.name = @"eMail";
group.image = 19;
[parentGroup addGroup:group];
group = [tree createGroup:parentGroup];
group.name = @"Homebanking";
group.image = 37;
group.name = [NSString stringWithFormat:@"Group %ld", iImageIndex];
group.image = iImageIndex;
[parentGroup addGroup:group];
}
return tree;
}

View File

@@ -7,6 +7,8 @@
//
#import "KdbEntry+MPAdditions.h"
#import "Kdb3Node.h"
#import "Kdb4Node.h"
#import "MPIconHelper.h"

View File

@@ -17,4 +17,5 @@
return NSNotFound;
}
@end

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

@@ -8,6 +8,9 @@
#import "Kdb.h"
@class BinaryRef;
@class Binary;
@interface KdbTree (MPAdditions)
- (NSArray *)allEntries;

View File

@@ -9,6 +9,10 @@
#import "KdbTree+MPAdditions.h"
#import "KdbGroup+MPTreeTools.h"
#import "NSMutableData+Base64.h"
#import "Kdb3Node.h"
#import "Kdb4Node.h"
@implementation KdbTree (MPAdditions)
- (NSArray *)allGroups {

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,7 +10,7 @@
@implementation MPActionHelper
+ (SEL)actionOfType:(MPActionType)type {
+ (NSDictionary *)_actionDictionary {
static NSDictionary *actionDict;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
@@ -21,14 +21,31 @@
@(MPActionCopyURL) : @"copyURL:",
@(MPActionCopyUsername) : @"copyUsername:",
@(MPActionDelete) : @"deleteNode:",
@(MPActionEdit) : @"editEntry:",
@(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

@@ -10,8 +10,8 @@
@interface MPCustomFieldTableCellView : NSTableCellView
@property (weak) IBOutlet NSTextField *labelTextField;
@property (weak) IBOutlet NSTextField *valueTextField;
@property (weak) IBOutlet NSButton *removeButton;
@property (nonatomic, weak) IBOutlet NSTextField *labelTextField;
@property (nonatomic, weak) IBOutlet NSTextField *valueTextField;
@property (nonatomic, weak) IBOutlet NSButton *removeButton;
@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

@@ -0,0 +1,159 @@
//
// MPDocument+Attachments.m
// MacPass
//
// Created by Michael Starke on 05.07.13.
// Copyright (c) 2013 HicknHack Software GmbH. All rights reserved.
//
#import "MPDocument.h"
#import "NSMutableData+Base64.h"
#import "NSData+Gzip.h"
#import "Kdb3Node.h"
#import "Kdb3Entry+KVOAdditions.h"
#import "Kdb4Node.h"
#import "Kdb4Entry+KVOAdditions.h"
@implementation MPDocument (Attachments)
- (void)addAttachment:(NSURL *)location toEntry:(KdbEntry *)anEntry {
NSError *error = nil;
NSString *fileName = [location lastPathComponent];
if([anEntry isKindOfClass:[Kdb3Entry class]]) {
Kdb3Entry *entry = (Kdb3Entry *)anEntry;
NSData *binaryData = [NSData dataWithContentsOfURL:location options:NSDataReadingUncached error:&error];
if(!binaryData) {
[NSApp presentError:error];
binaryData = nil;
error = nil;
return; // failed
}
entry.binary = binaryData;
entry.binaryDesc = fileName;
[entry insertObject:@"" inBinariesAtIndex:1];
}
if( [anEntry isKindOfClass:[Kdb4Entry class]]) {
Kdb4Entry *entry = (Kdb4Entry *)anEntry;
NSData *fileData = [NSData dataWithContentsOfURL:location options:NSDataReadingMappedIfSafe error:&error];
if(!fileData) {
[NSApp presentError:error];
fileData = nil;
error = nil;
return; // failed
}
Binary *binary = [[Binary alloc] init];
NSUInteger nextId = [self nextBinaryId];
if(nextId == NSNotFound) {
binary = nil;
return; // No id found. Something went wrong
}
binary.binaryId = nextId;
binary.compressed = (self.treeV4.compressionAlgorithm != KPLCompressionNone);
NSData *encodedData;
if(binary.compressed) {
switch(self.treeV4.compressionAlgorithm) {
case KPLCompressionGzip: {
NSData *compressedData = [fileData gzipDeflate];
encodedData = [NSMutableData mutableDataWithBase64EncodedData:compressedData];
break;
}
default:
NSAssert(NO, @"Unsupported Compression Algorithm");
binary = nil;
encodedData = nil;
fileData = nil;
return;
}
}
else {
encodedData = fileData;
}
binary.data = [[NSString alloc] initWithData:encodedData encoding:NSUTF8StringEncoding];
[self.treeV4.binaries addObject:binary];
BinaryRef *ref = [[BinaryRef alloc] init];
ref.key = fileName;
ref.ref = binary.binaryId;
[entry insertObject:ref inBinariesAtIndex:[entry.binaries count]];
}
}
- (void)removeAttachment:(BinaryRef *)reference fromEntry:(KdbEntry *)anEntry {
if(self.version != MPDatabaseVersion4) {
return; // Wrong Database version;
}
Binary *binary = [self findBinary:reference];
Kdb4Entry *entry = (Kdb4Entry *)anEntry;
NSUInteger index = [entry.binaries indexOfObject:reference];
if(index == NSNotFound) {
return; // No Reference for this entry found
}
[entry removeObjectFromBinariesAtIndex:index];
[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;
}
NSPredicate *filterPredicate = [NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary *bindings) {
Binary *binaryFile = evaluatedObject;
return (binaryFile.binaryId == reference.ref);
}];
NSArray *filteredBinary = [self.treeV4.binaries filteredArrayUsingPredicate:filterPredicate];
return [filteredBinary lastObject];
}
- (void)saveAttachmentForItem:(id)item toLocation:(NSURL *)location {
if([item isKindOfClass:[Kdb3Entry class]]) {
Kdb3Entry *entry = (Kdb3Entry *)item;
NSError *error = nil;
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 {
if(self.version != MPDatabaseVersion4) {
return NSNotFound;
}
NSUInteger maxKey = 0;
for(Binary *binary in self.treeV4.binaries) {
maxKey = MAX(binary.binaryId, maxKey);
}
return (maxKey + 1);
}
@end

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
/*
@@ -57,16 +65,17 @@ APPKIT_EXTERN NSString *const MPDocumentGroupKey;
*/
- (KdbEntry *)findEntry:(UUID *)uuid;
- (KdbGroup *)findGroup:(UUID *)uuid;
/*
Return the Binary for the given BinaryRef. nil if none was found
*/
- (Binary *)binaryForRef:(BinaryRef *)binaryRef;
- (Kdb4Tree *)treeV4;
- (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 */
@@ -78,18 +87,27 @@ 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;
@end
@interface MPDocument (Attachments)
- (void)addAttachment:(NSURL *)location toEntry:(KdbEntry *)anEntry;
/**
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;
@end

View File

@@ -13,25 +13,37 @@
#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"
#import "DataOutputStream.h"
#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";
@@ -40,6 +52,7 @@ 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];
@@ -83,6 +98,7 @@ NSString *const MPDocumentGroupKey = @"MPDocumentGroupKey";
break;
case MPDatabaseVersion4:
self.tree = [Kdb4Tree templateTree];
//self.tree = [Kdb4Tree demoTree];
break;
default:
self = nil;
@@ -117,6 +133,7 @@ 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;
@@ -126,6 +143,12 @@ NSString *const MPDocumentGroupKey = @"MPDocumentGroupKey";
_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;
}
@@ -145,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 {
@@ -170,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];
}
}
@@ -194,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) {
@@ -214,23 +277,10 @@ NSString *const MPDocumentGroupKey = @"MPDocumentGroupKey";
return [self.root groupForUUID:uuid];
}
- (Binary *)binaryForRef:(BinaryRef *)binaryRef {
if(self.version != MPDatabaseVersion4) {
return nil;
}
NSPredicate *filterPredicate = [NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary *bindings) {
Binary *binaryFile = evaluatedObject;
return (binaryFile.binaryId == binaryRef.ref);
}];
Kdb4Tree *tree = (Kdb4Tree *)self.tree;
NSArray *filteredBinary = [tree.binaries filteredArrayUsingPredicate:filterPredicate];
return [filteredBinary lastObject];
}
- (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;
@@ -244,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;
@@ -270,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;
@@ -279,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;
@@ -299,9 +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");
[self group:parent addGroup:newGroup atIndex:[parent.groups count]];
newGroup.image = MPIconFolder;
[parent addGroupUndoable:newGroup atIndex:[parent.groups count]];
NSDictionary *userInfo = @{ MPDocumentGroupKey : newGroup };
[[NSNotificationCenter defaultCenter] postNotificationName:MPDocumentDidAddGroupNotification object:self userInfo:userInfo];
return newGroup;
@@ -315,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];
@@ -477,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;
@@ -489,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;
}
if(itemAction == [MPActionHelper actionOfType:MPActionAddEntry]) {
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;
}
if(itemAction == [MPActionHelper actionOfType:MPActionDelete]) {
return (nil != _currentItem);
}
if(itemAction == [MPActionHelper actionOfType:MPActionToggleInspector]) {
case MPActionLock:
return document.hasPasswordOrKey;
case MPActionToggleInspector:
return (nil != [_splitView superview]);
default:
return YES;
}
return YES;
}
- (BOOL)validateAction:(SEL)action forItem:(id)item {
MPDocument *document = [self document];
if(!document.decrypted || document.isLocked || document.isReadOnly) {
return NO;
}
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;
}
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,6 +170,7 @@ NSString *const _toggleFilterUsernameButton = @"SearchUsername";
[self.entryTable setDataSource:_dataSource];
[parentColumn setHidden:YES];
}
- (void)setupNotifications:(MPDocumentWindowController *)windowController {
@@ -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,13 +15,23 @@ typedef NS_ENUM(NSUInteger, MPIconType) {
MPIconServer,
MPIconKlipper,
MPIconLanguages,
MPIconBlockDevice,
MPIconNotepad,
MPIconSocket,
MPIconIdentity,
MPIconContact,
MPIconCamera,
MPIconTrash,
MPIconInfo
MPIconRemote,
MPIconKeys,
MPIconDisplay = 18,
MPIconFileSave = 26,
MPIconTrash = 43,
MPIconFolder = 48,
MPIconPhone = 68,
/* Custom Icons not used in Database */
MPIconInfo = 1000,
MPIconAddFolder,
MPIconHardDisk,
};
@interface MPIconHelper : NSObject

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