3 import qualified Data.ByteString.Char8 as BC
4 import qualified Data.Map as M
5 import qualified Data.List as List
6 import qualified Network.HTTP as HTTP
7 import qualified Network.HTTP.Base as HB
8 import qualified Bencode as Benc
9 import qualified Crypto.Hash.SHA1 as SHA1
10 import qualified Data.ByteString.Base16 as B16
11 import qualified Utils as U
18 -- >>> urlEncodeHash $ BC.pack "123456789abcdef123456789abcdef123456789a"
19 -- "%124vx%9a%bc%de%f1%23Eg%89%ab%cd%ef%124Vx%9a"
20 urlEncodeHash :: BC.ByteString -> String
21 urlEncodeHash bs = concatMap (encode . BC.unpack) (U.splitN 2 bs)
22 where encode b@[c1, c2] = let c = chr (read ("0x" ++ b))
26 escape i c1 c2 | i `elem` nonSpecialChars = [i]
27 | otherwise = "%" ++ [c1] ++ [c2]
28 where nonSpecialChars = ['A'..'Z'] ++
33 infoHash :: M.Map Benc.BVal Benc.BVal -> BC.ByteString
34 infoHash m = let info = m M.! Benc.Bstr (BC.pack "info")
35 in (SHA1.hash . BC.pack . Benc.encode) info
37 prepareRequest :: Benc.InfoDict -> String -> Integer -> String
38 prepareRequest d peer_id len =
39 let p = [("info_hash", urlEncodeHash ((B16.encode . infoHash) d)),
40 ("peer_id", HB.urlEncode peer_id),
48 List.intercalate "&" [f ++ "=" ++ s | (f,s) <- p]
50 connect :: Url -> String -> IO String
51 connect baseurl qstr = let url = baseurl ++ "?" ++ qstr
52 in HTTP.simpleHTTP (HTTP.getRequest url) >>=