summaryrefslogtreecommitdiff
path: root/src/Data
diff options
context:
space:
mode:
Diffstat (limited to 'src/Data')
-rw-r--r--src/Data/Torrent/InfoHash.hs24
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 @@
1module Data.Torrent.InfoHash 1module 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
11import Control.Applicative 12import Control.Applicative
12import Data.Foldable 13import Data.Foldable
14import Data.List as L
15import Data.Char
13import Data.ByteString (ByteString) 16import Data.ByteString (ByteString)
14import qualified Data.ByteString as B 17import qualified Data.ByteString as B
15import qualified Data.ByteString.Char8 as BC 18import qualified Data.ByteString.Char8 as BC
@@ -18,6 +21,9 @@ import qualified Data.ByteString.Builder.Prim as B
18import qualified Data.ByteString.Lazy as Lazy 21import qualified Data.ByteString.Lazy as Lazy
19import Data.Serialize 22import Data.Serialize
20import qualified Crypto.Hash.SHA1 as C 23import qualified Crypto.Hash.SHA1 as C
24import Network.URI
25import Numeric
26
21 27
22-- | Exactly 20 bytes long SHA1 hash. 28-- | Exactly 20 bytes long SHA1 hash.
23newtype InfoHash = InfoHash { getInfoHash :: ByteString } 29newtype InfoHash = InfoHash { getInfoHash :: ByteString }
@@ -39,3 +45,21 @@ hashlazy = InfoHash . C.hashlazy
39ppHex :: InfoHash -> ByteString 45ppHex :: InfoHash -> ByteString
40ppHex = Lazy.toStrict . B.toLazyByteString . 46ppHex = Lazy.toStrict . B.toLazyByteString .
41 foldMap (B.primFixed B.word8HexFixed) . B.unpack . getInfoHash 47 foldMap (B.primFixed B.word8HexFixed) . B.unpack . getInfoHash
48
49addHashToURI :: URI -> InfoHash -> URI
50addHashToURI 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