diff options
Diffstat (limited to 'src/Data')
-rw-r--r-- | src/Data/Torrent/InfoHash.hs | 24 |
1 files changed, 24 insertions, 0 deletions
diff --git a/src/Data/Torrent/InfoHash.hs b/src/Data/Torrent/InfoHash.hs index 448e9a5a..b2ca44ee 100644 --- a/src/Data/Torrent/InfoHash.hs +++ b/src/Data/Torrent/InfoHash.hs | |||
@@ -1,5 +1,6 @@ | |||
1 | module Data.Torrent.InfoHash | 1 | module Data.Torrent.InfoHash |
2 | ( InfoHash (getInfoHash) | 2 | ( InfoHash (getInfoHash) |
3 | , addHashToURI | ||
3 | 4 | ||
4 | -- ^ Construction | 5 | -- ^ Construction |
5 | , hash, hashlazy | 6 | , hash, hashlazy |
@@ -10,6 +11,8 @@ module Data.Torrent.InfoHash | |||
10 | 11 | ||
11 | import Control.Applicative | 12 | import Control.Applicative |
12 | import Data.Foldable | 13 | import Data.Foldable |
14 | import Data.List as L | ||
15 | import Data.Char | ||
13 | import Data.ByteString (ByteString) | 16 | import Data.ByteString (ByteString) |
14 | import qualified Data.ByteString as B | 17 | import qualified Data.ByteString as B |
15 | import qualified Data.ByteString.Char8 as BC | 18 | import qualified Data.ByteString.Char8 as BC |
@@ -18,6 +21,9 @@ import qualified Data.ByteString.Builder.Prim as B | |||
18 | import qualified Data.ByteString.Lazy as Lazy | 21 | import qualified Data.ByteString.Lazy as Lazy |
19 | import Data.Serialize | 22 | import Data.Serialize |
20 | import qualified Crypto.Hash.SHA1 as C | 23 | import qualified Crypto.Hash.SHA1 as C |
24 | import Network.URI | ||
25 | import Numeric | ||
26 | |||
21 | 27 | ||
22 | -- | Exactly 20 bytes long SHA1 hash. | 28 | -- | Exactly 20 bytes long SHA1 hash. |
23 | newtype InfoHash = InfoHash { getInfoHash :: ByteString } | 29 | newtype InfoHash = InfoHash { getInfoHash :: ByteString } |
@@ -39,3 +45,21 @@ hashlazy = InfoHash . C.hashlazy | |||
39 | ppHex :: InfoHash -> ByteString | 45 | ppHex :: InfoHash -> ByteString |
40 | ppHex = Lazy.toStrict . B.toLazyByteString . | 46 | ppHex = Lazy.toStrict . B.toLazyByteString . |
41 | foldMap (B.primFixed B.word8HexFixed) . B.unpack . getInfoHash | 47 | foldMap (B.primFixed B.word8HexFixed) . B.unpack . getInfoHash |
48 | |||
49 | addHashToURI :: URI -> InfoHash -> URI | ||
50 | addHashToURI uri s = uri { | ||
51 | uriQuery = uriQuery uri ++ mkPref (uriQuery uri) ++ | ||
52 | "info_hash=" ++ rfc1738Encode (BC.unpack (getInfoHash s)) | ||
53 | } | ||
54 | where | ||
55 | mkPref [] = "?" | ||
56 | mkPref ('?' : _) = "&" | ||
57 | mkPref _ = error "addHashToURI" | ||
58 | |||
59 | rfc1738Encode = L.concatMap (\c -> if unreservedS c then [c] else encodeHex c) | ||
60 | where | ||
61 | unreservedS = (`L.elem` chars) | ||
62 | chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_./" | ||
63 | encodeHex c = '%' : pHex c | ||
64 | pHex c = let p = (showHex . ord $ c) "" | ||
65 | in if L.length p == 1 then '0' : p else p | ||