1 -- This file is part of htalkat
2 -- Copyright (C) 2021 Martin Bays <mbays@sdf.org>
4 -- This program is free software: you can redistribute it and/or modify
5 -- it under the terms of version 3 of the GNU General Public License as
6 -- published by the Free Software Foundation, or any later version.
8 -- You should have received a copy of the GNU General Public License
9 -- along with this program. If not, see http://www.gnu.org/licenses/.
13 import Control
.Monad
(filterM, forM
, forM_
)
14 import Data
.List
((\\))
15 import Data
.Maybe (mapMaybe)
16 import Safe
(maximumMay
, readMay
)
17 import System
.Directory
18 import System
.FileLock
(SharedExclusive
(..), withFileLock
)
19 import System
.FilePath ((</>))
28 #if !(MIN_VERSION_base
(4,11,0))
34 addIncoming
:: FilePath -> Certificate
-> FilePath -> Int -> IO Incoming
35 addIncoming ddir cert sockPath serial
= do
36 let idir
= incomingDir ddir
37 createDirectoryIfMissing
True idir
38 withFileLock
(idir
</> ".lock") Exclusive
$ \_
-> do
40 let n
= head $ [1..] \\ ns
41 let ndir
= idir
</> show n
42 createDirectoryIfMissing
False ndir
43 writeFile (ndir
</> "fp") . showFingerprint
$ spkiFingerprint cert
44 writeFile (ndir
</> "publicName") $ certCN cert
45 writeFile (ndir
</> "sock") sockPath
46 writeFile (ndir
</> "serial") $ show serial
49 cleanAllIncoming
:: FilePath -> IO ()
50 cleanAllIncoming ddir
= do
52 forM_ ns
$ cleanIncoming ddir Nothing
54 cleanIncoming
:: FilePath -> Maybe Int -> Incoming
-> IO ()
55 cleanIncoming ddir mSerial n
=
56 let path
= incomingPath ddir n
57 serialOk | Just s
<- mSerial
=
58 (== Just s
) <$> ignoreIOErrAlt
(readMay
<$> readFile (path
</> "serial"))
59 |
otherwise = pure
True
60 in doesDirectoryExist path
>>? serialOk
>>? removeDirectoryRecursive path
62 incomingDir
:: FilePath -> FilePath
63 incomingDir
= (</> "incoming")
65 incomingNs
:: FilePath -> IO [Int]
66 incomingNs ddir
= mapMaybe readMay
<$> listDirectory
(incomingDir ddir
)
68 incomingPath
:: FilePath -> Incoming
-> FilePath
69 incomingPath ddir n
= incomingDir ddir
</> show n
71 lastIncoming
:: FilePath -> Maybe Fingerprint
-> IO (Maybe Incoming
)
72 lastIncoming ddir mFp
= do
74 maximumMay
<$> filterM checkFp ns
76 checkFp _ | Nothing
<- mFp
= pure
True
77 checkFp n | Just fp
<- mFp
= (== Just fp
) . parseFingerprint
<$>
78 readFile (incomingPath ddir n
</> "fp")
80 listIncoming
:: FilePath -> IO [String]
81 listIncoming ddir
= do
84 let idir
= incomingPath ddir n
85 t
<- getModificationTime idir
86 petname
<- incomingPetname ddir n
87 ((show t
<> ": " <> showPetname petname
) <>) <$> case petname
of
90 Just fp
<- parseFingerprint
<$> readFile (idir
</> "fp")
91 cn
<- readFile (idir
</> "publicName")
92 pure
$ " " <> showFingerprint fp
<>
93 if null cn
then "" else " \"" <> cn
<> "\""
96 incomingPetname
:: FilePath -> Incoming
-> IO Petname
97 incomingPetname ddir n
= do
98 Just fp
<- parseFingerprint
<$> readFile (incomingPath ddir n
</> "fp")
99 lookupOrAddPetname ddir fp