1{
2 lib,
3 stdenv,
4 fetchurl,
5 unzip,
6 mono,
7 makeWrapper,
8 icoutils,
9 replaceVars,
10 xsel,
11 xorg,
12 xdotool,
13 coreutils,
14 unixtools,
15 glib,
16 gtk2,
17 makeDesktopItem,
18 plugins ? [ ],
19}:
20
21stdenv.mkDerivation (finalAttrs: {
22 pname = "keepass";
23 version = "2.57.1";
24
25 src = fetchurl {
26 url = "mirror://sourceforge/keepass/KeePass-${finalAttrs.version}-Source.zip";
27 hash = "sha256-97ZX1EzhMv4B3YZ3HoUqlGTEMsQn3cmNGr+uvS6AKYY=";
28 };
29
30 sourceRoot = ".";
31
32 nativeBuildInputs = [
33 unzip
34 mono
35 makeWrapper
36 ];
37 buildInputs = [ icoutils ];
38
39 patches = [
40 (replaceVars ./fix-paths.patch {
41 xsel = "${xsel}/bin/xsel";
42 xprop = "${xorg.xprop}/bin/xprop";
43 xdotool = "${xdotool}/bin/xdotool";
44 uname = "${coreutils}/bin/uname";
45 whereis = "${unixtools.whereis}/bin/whereis";
46 gsettings = "${glib}/bin/gsettings";
47 })
48 ];
49
50 # KeePass looks for plugins in under directory in which KeePass.exe is
51 # located. It follows symlinks where looking for that directory, so
52 # buildEnv is not enough to bring KeePass and plugins together.
53 #
54 # This derivation patches KeePass to search for plugins in specified
55 # plugin derivations in the Nix store and nowhere else.
56 pluginLoadPathsPatch =
57 let
58 inherit (builtins) toString;
59 inherit (lib.strings)
60 readFile
61 concatStrings
62 replaceStrings
63 unsafeDiscardStringContext
64 ;
65 inherit (lib.lists) map length;
66 inherit (lib) add;
67
68 outputLc = toString (add 7 (length plugins));
69 patchTemplate = readFile ./keepass-plugins.patch;
70 loadTemplate = readFile ./keepass-plugins-load.patch;
71 loads = concatStrings (
72 map (
73 p: replaceStrings [ "$PATH$" ] [ (unsafeDiscardStringContext (toString p)) ] loadTemplate
74 ) plugins
75 );
76 in
77 replaceStrings [ "$OUTPUT_LC$" "$DO_LOADS$" ] [ outputLc loads ] patchTemplate;
78
79 passAsFile = [ "pluginLoadPathsPatch" ];
80 postPatch = ''
81 sed -i 's/\r*$//' KeePass/Forms/MainForm.cs
82 patch -p1 <$pluginLoadPathsPatchPath
83 '';
84
85 configurePhase = ''
86 runHook preConfigure
87
88 rm -rvf Build/*
89 find . -name "*.sln" -print -exec sed -i 's/Format Version 10.00/Format Version 11.00/g' {} \;
90 find . -name "*.csproj" -print -exec sed -i '
91 s#ToolsVersion="3.5"#ToolsVersion="4.0"#g
92 s#<TargetFrameworkVersion>.*</TargetFrameworkVersion>##g
93 s#<PropertyGroup>#<PropertyGroup><TargetFrameworkVersion>v4.5</TargetFrameworkVersion>#g
94 s#<SignAssembly>.*$#<SignAssembly>false</SignAssembly>#g
95 s#<PostBuildEvent>.*sgen.exe.*$##
96 ' {} \;
97
98 runHook postConfigure
99 '';
100
101 buildPhase = ''
102 runHook preBuild
103
104 xbuild /p:Configuration=Release
105
106 runHook postBuild
107 '';
108
109 outputFiles = [
110 "Build/KeePass/Release/*"
111 "Build/KeePassLib/Release/*"
112 "Ext/KeePass.config.xml" # contains <PreferUserConfiguration>true</PreferUserConfiguration>
113 ];
114
115 # plgx plugin like keefox requires mono to compile at runtime
116 # after loading. It is brought into plugins bin/ directory using
117 # buildEnv in the plugin derivation. Wrapper below makes sure it
118 # is found and does not pollute output path.
119 binPaths = lib.concatStringsSep ":" (map (x: x + "/bin") plugins);
120
121 dynlibPath = lib.makeLibraryPath [ gtk2 ];
122
123 installPhase = ''
124 runHook preInstall
125
126 target="$out/lib/dotnet/keepass"
127 mkdir -p "$target"
128
129 cp -rv $outputFiles "$target"
130
131 makeWrapper \
132 "${mono}/bin/mono" \
133 "$out/bin/keepass" \
134 --add-flags "$target/KeePass.exe" \
135 --prefix PATH : "$binPaths" \
136 --prefix LD_LIBRARY_PATH : "$dynlibPath"
137
138 # setup desktop item with icon
139 mkdir -p "$out/share/applications"
140 cp $desktopItem/share/applications/* $out/share/applications
141
142 ${./extractWinRscIconsToStdFreeDesktopDir.sh} \
143 "./Translation/TrlUtil/Resources/KeePass.ico" \
144 '[^\.]+_[0-9]+_([0-9]+x[0-9]+)x[0-9]+\.png' \
145 '\1' \
146 '([^\.]+).+' \
147 'keepass' \
148 "$out" \
149 "./tmp"
150 runHook postInstall
151 '';
152
153 desktopItem = makeDesktopItem {
154 name = "keepass";
155 exec = "keepass";
156 comment = "Password manager";
157 icon = "keepass";
158 desktopName = "Keepass";
159 genericName = "Password manager";
160 categories = [ "Utility" ];
161 mimeTypes = [ "application/x-keepass2" ];
162 };
163
164 meta = {
165 description = "GUI password manager with strong cryptography";
166 homepage = "http://www.keepass.info/";
167 maintainers = with lib.maintainers; [
168 obadz
169 ];
170 platforms = with lib.platforms; all;
171 license = lib.licenses.gpl2;
172 mainProgram = "keepass";
173 };
174})