diff options
author | Sam T <pxqr.sta@gmail.com> | 2013-06-07 03:37:11 +0400 |
---|---|---|
committer | Sam T <pxqr.sta@gmail.com> | 2013-06-07 03:37:11 +0400 |
commit | 095f22bba763aba8303322b104ae39e2ff2807c2 (patch) | |
tree | 2743e5c025e6934b247cee593fd693c23bb01892 /src/Data/Torrent.hs | |
parent | 558616b7dcc8955ab08fe8b194cdd5e128aba3f4 (diff) |
~ Fix bug in torrent bencode instance.
Also add encoding tests for torrent module.
Diffstat (limited to 'src/Data/Torrent.hs')
-rw-r--r-- | src/Data/Torrent.hs | 59 |
1 files changed, 44 insertions, 15 deletions
diff --git a/src/Data/Torrent.hs b/src/Data/Torrent.hs index 16b94828..3175e151 100644 --- a/src/Data/Torrent.hs +++ b/src/Data/Torrent.hs | |||
@@ -17,6 +17,7 @@ | |||
17 | -- <https://wiki.theory.org/BitTorrentSpecification#Metainfo_File_Structure> | 17 | -- <https://wiki.theory.org/BitTorrentSpecification#Metainfo_File_Structure> |
18 | -- | 18 | -- |
19 | {-# OPTIONS -fno-warn-orphans #-} | 19 | {-# OPTIONS -fno-warn-orphans #-} |
20 | {-# LANGUAGE CPP #-} | ||
20 | {-# LANGUAGE FlexibleInstances #-} | 21 | {-# LANGUAGE FlexibleInstances #-} |
21 | {-# LANGUAGE OverloadedStrings #-} | 22 | {-# LANGUAGE OverloadedStrings #-} |
22 | {-# LANGUAGE RecordWildCards #-} | 23 | {-# LANGUAGE RecordWildCards #-} |
@@ -24,6 +25,7 @@ | |||
24 | module Data.Torrent | 25 | module Data.Torrent |
25 | ( -- * Torrent | 26 | ( -- * Torrent |
26 | Torrent(..), ContentInfo(..), FileInfo(..) | 27 | Torrent(..), ContentInfo(..), FileInfo(..) |
28 | , torrent, simpleTorrent | ||
27 | , fromFile | 29 | , fromFile |
28 | 30 | ||
29 | -- * Files layout | 31 | -- * Files layout |
@@ -32,15 +34,21 @@ module Data.Torrent | |||
32 | , isSingleFile, isMultiFile | 34 | , isSingleFile, isMultiFile |
33 | 35 | ||
34 | -- * Info hash | 36 | -- * Info hash |
35 | , InfoHash, ppInfoHash | 37 | #if defined (TESTING) |
36 | , hash, hashlazy | 38 | , InfoHash(..) |
39 | #else | ||
40 | , InfoHash | ||
41 | #endif | ||
42 | , ppInfoHash | ||
37 | , addHashToURI | 43 | , addHashToURI |
38 | 44 | ||
39 | -- * Extra | 45 | -- * Extra |
40 | , sizeInBase | 46 | , sizeInBase |
41 | 47 | ||
48 | #if defined (TESTING) | ||
42 | -- * Internal | 49 | -- * Internal |
43 | , InfoHash(..) | 50 | , hash, hashlazy |
51 | #endif | ||
44 | ) where | 52 | ) where |
45 | 53 | ||
46 | import Prelude hiding (sum) | 54 | import Prelude hiding (sum) |
@@ -79,6 +87,10 @@ data Torrent = Torrent { | |||
79 | , tAnnounce :: URI | 87 | , tAnnounce :: URI |
80 | -- ^ The URL of the tracker. | 88 | -- ^ The URL of the tracker. |
81 | 89 | ||
90 | -- NOTE: out of lexicographic order! | ||
91 | , tInfo :: ContentInfo | ||
92 | -- ^ Info about each content file. | ||
93 | |||
82 | , tAnnounceList :: Maybe [[URI]] | 94 | , tAnnounceList :: Maybe [[URI]] |
83 | -- ^ Announce list add multiple tracker support. | 95 | -- ^ Announce list add multiple tracker support. |
84 | -- | 96 | -- |
@@ -97,9 +109,6 @@ data Torrent = Torrent { | |||
97 | -- ^ String encoding format used to generate the pieces part of | 109 | -- ^ String encoding format used to generate the pieces part of |
98 | -- the info dictionary in the .torrent metafile. | 110 | -- the info dictionary in the .torrent metafile. |
99 | 111 | ||
100 | , tInfo :: ContentInfo | ||
101 | -- ^ Info about each content file. | ||
102 | |||
103 | , tPublisher :: Maybe URI | 112 | , tPublisher :: Maybe URI |
104 | -- ^ Containing the RSA public key of the publisher of the torrent. | 113 | -- ^ Containing the RSA public key of the publisher of the torrent. |
105 | -- Private counterpart of this key that has the authority to allow | 114 | -- Private counterpart of this key that has the authority to allow |
@@ -109,7 +118,26 @@ data Torrent = Torrent { | |||
109 | , tSignature :: Maybe ByteString | 118 | , tSignature :: Maybe ByteString |
110 | -- ^ The RSA signature of the info dictionary (specifically, | 119 | -- ^ The RSA signature of the info dictionary (specifically, |
111 | -- the encrypted SHA-1 hash of the info dictionary). | 120 | -- the encrypted SHA-1 hash of the info dictionary). |
112 | } deriving Show | 121 | } deriving (Show, Eq) |
122 | |||
123 | {- note that info hash is actually reduntant field | ||
124 | but it's better to keep it here to avoid heavy recomputations | ||
125 | -} | ||
126 | |||
127 | -- | Smart constructor for 'Torrent' which compute info hash. | ||
128 | torrent :: URI -> ContentInfo | ||
129 | -> Maybe [[URI]] -> Maybe Text -> Maybe ByteString | ||
130 | -> Maybe Time -> Maybe ByteString -> Maybe URI | ||
131 | -> Maybe URI -> Maybe ByteString | ||
132 | -> Torrent | ||
133 | torrent announce info = Torrent (hashlazy (BE.encoded info)) announce info | ||
134 | |||
135 | -- | A simple torrent contains only required fields. | ||
136 | simpleTorrent :: URI -> ContentInfo -> Torrent | ||
137 | simpleTorrent announce info = torrent announce info | ||
138 | Nothing Nothing Nothing | ||
139 | Nothing Nothing Nothing | ||
140 | Nothing Nothing | ||
113 | 141 | ||
114 | -- | Info part of the .torrent file contain info about each content file. | 142 | -- | Info part of the .torrent file contain info about each content file. |
115 | data ContentInfo = | 143 | data ContentInfo = |
@@ -133,8 +161,9 @@ data ContentInfo = | |||
133 | -- ^ Concatenation of all 20-byte SHA1 hash values. | 161 | -- ^ Concatenation of all 20-byte SHA1 hash values. |
134 | 162 | ||
135 | , ciPrivate :: Maybe Bool | 163 | , ciPrivate :: Maybe Bool |
136 | -- ^ If set the client MUST publish its presence to get other peers ONLY | 164 | -- ^ If set the client MUST publish its presence to get other |
137 | -- via the trackers explicity described in the metainfo file. | 165 | -- peers ONLY via the trackers explicity described in the |
166 | -- metainfo file. | ||
138 | -- | 167 | -- |
139 | -- BEP 27: <http://www.bittorrent.org/beps/bep_0027.html> | 168 | -- BEP 27: <http://www.bittorrent.org/beps/bep_0027.html> |
140 | } | 169 | } |
@@ -162,10 +191,10 @@ data FileInfo = FileInfo { | |||
162 | -- Used by third-party tools, not by bittorrent protocol itself. | 191 | -- Used by third-party tools, not by bittorrent protocol itself. |
163 | 192 | ||
164 | , fiPath :: [ByteString] | 193 | , fiPath :: [ByteString] |
165 | -- ^ One or more string elements that together represent the path and | 194 | -- ^ One or more string elements that together represent the |
166 | -- filename. Each element in the list corresponds to either a directory | 195 | -- path and filename. Each element in the list corresponds to |
167 | -- name or (in the case of the last element) the filename. | 196 | -- either a directory name or (in the case of the last |
168 | -- For example, the file | 197 | -- element) the filename. For example, the file: |
169 | -- | 198 | -- |
170 | -- > "dir1/dir2/file.ext" | 199 | -- > "dir1/dir2/file.ext" |
171 | -- | 200 | -- |
@@ -201,15 +230,15 @@ instance BEncodable Torrent where | |||
201 | fromBEncode (BDict d) | Just info <- M.lookup "info" d = | 230 | fromBEncode (BDict d) | Just info <- M.lookup "info" d = |
202 | Torrent <$> pure (hashlazy (BE.encode info)) -- WARN | 231 | Torrent <$> pure (hashlazy (BE.encode info)) -- WARN |
203 | <*> d >-- "announce" | 232 | <*> d >-- "announce" |
233 | <*> d >-- "info" | ||
204 | <*> d >--? "announce-list" | 234 | <*> d >--? "announce-list" |
205 | <*> d >--? "comment" | 235 | <*> d >--? "comment" |
206 | <*> d >--? "created by" | 236 | <*> d >--? "created by" |
207 | <*> d >--? "creation date" | 237 | <*> d >--? "creation date" |
208 | <*> d >--? "encoding" | 238 | <*> d >--? "encoding" |
209 | <*> d >-- "info" | ||
210 | <*> d >--? "publisher" | 239 | <*> d >--? "publisher" |
211 | <*> d >--? "publisher-url" | 240 | <*> d >--? "publisher-url" |
212 | <*> d >--? "singature" | 241 | <*> d >--? "signature" |
213 | 242 | ||
214 | fromBEncode _ = decodingError "Torrent" | 243 | fromBEncode _ = decodingError "Torrent" |
215 | 244 | ||