]> git.rkrishnan.org Git - functorrent.git/blob - src/FuncTorrent/Metainfo.hs
Move things around
[functorrent.git] / src / FuncTorrent / Metainfo.hs
1 module FuncTorrent.Metainfo
2     (Info(..),
3      Metainfo(..),
4      infoHash,
5      mkInfo,
6      mkMetaInfo
7     ) where
8
9 import Prelude hiding (lookup)
10 import Data.ByteString.Char8 (ByteString, unpack)
11 import Data.Map as M ((!), lookup)
12 import Crypto.Hash.SHA1 (hash)
13 import Data.Maybe (maybeToList)
14
15 import FuncTorrent.Bencode (BVal(..), InfoDict, encode, bstrToString)
16
17 -- only single file mode supported for the time being.
18 data Info = Info { pieceLength :: !Integer
19                  , pieces :: !ByteString
20                  , private :: !(Maybe Integer)
21                  , name :: !String
22                  , lengthInBytes :: !Integer
23                  , md5sum :: !(Maybe String)
24                  } deriving (Eq, Show)
25
26 data Metainfo = Metainfo { info :: !Info
27                          , announceList :: ![String]
28                          , creationDate :: !(Maybe String)
29                          , comment :: !(Maybe String)
30                          , createdBy :: !(Maybe String)
31                          , encoding :: !(Maybe String)
32                          } deriving (Eq, Show)
33
34 mkInfo :: BVal -> Maybe Info
35 mkInfo (Bdict m) = let (Bint pieceLength') = m ! "piece length"
36                        (Bstr pieces') = m ! "pieces"
37                        private' = Nothing
38                        (Bstr name') = m ! "name"
39                        (Bint length') = m ! "length"
40                        md5sum' = Nothing
41                    in Just Info { pieceLength = pieceLength'
42                                 , pieces = pieces'
43                                 , private = private'
44                                 , name = unpack name'
45                                 , lengthInBytes = length'
46                                 , md5sum = md5sum'}
47 mkInfo _ = Nothing
48
49 maybeBstrToString :: Maybe BVal -> Maybe String
50 maybeBstrToString (Just (Bstr bs)) = Just $ unpack bs
51 maybeBstrToString _ = Nothing
52
53 mkMetaInfo :: BVal -> Maybe Metainfo
54 mkMetaInfo (Bdict m) = let (Just info') = mkInfo $ m ! "info"
55                            announce' = lookup "announce" m
56                            announceList' = lookup "announce-list" m
57                            -- creationDate = lookup (Bstr (pack "creation date")) m
58                            creationDate' = Nothing
59                            comment' = lookup "comment" m
60                            createdBy' = lookup "created by" m
61                            encoding' = lookup "encoding" m
62                        in Just Metainfo { info = info'
63                                         , announceList = maybeToList (announce' >>= bstrToString)
64                                                          ++ getAnnounceList announceList'
65                                         , creationDate = creationDate'
66                                         , comment = maybeBstrToString comment'
67                                         , createdBy = maybeBstrToString createdBy'
68                                         , encoding = maybeBstrToString encoding'
69                                         }
70 mkMetaInfo _ = Nothing
71
72 getAnnounceList :: Maybe BVal -> [String]
73 getAnnounceList Nothing = []
74 getAnnounceList (Just (Bint _)) = []
75 getAnnounceList (Just (Bstr _)) = []
76 getAnnounceList (Just (Blist l)) = map (\s -> case s of
77                                                (Bstr s') ->  unpack s'
78                                                (Blist s') -> case s' of
79                                                               [Bstr s''] -> unpack s''
80                                                               _ -> ""
81                                                _ -> "") l
82
83 getAnnounceList (Just (Bdict _)) = []
84
85 -- | Info hash is urlencoded 20 byte SHA1 hash of the value of the info key from
86 -- the Metainfo file. Note that the value will be a bencoded dictionary, given
87 -- the definition of the info key above. TODO: `Metainfo -> ByteString`
88 infoHash :: InfoDict -> ByteString
89 infoHash m = hash . encode $ (m ! "info")