torrent 2007.6.29 → 2007.10.27
raw patch · 2 files changed
+49/−21 lines, 2 filesdep +binarydep ~bencode
Dependencies added: binary
Dependency ranges changed: bencode
Files
- src/Data/Torrent.hs +47/−19
- torrent.cabal +2/−2
src/Data/Torrent.hs view
@@ -1,8 +1,10 @@+{-# OPTIONS -fglasgow-exts #-} module Data.Torrent ( Torrent(..) , TorrentInfo(..) , TorrentFile(..) , readTorrent -- :: ByteString -> Either String Torrent+ , serializeTorrent , torrentSize -- :: Torrent -> Int ) where @@ -10,42 +12,53 @@ import Data.BEncode import Data.BEncode.Parser-import System.FilePath import Data.Torrent.SHA1+import Data.Maybe+import Data.Binary+import Data.Generics import qualified Data.ByteString.Char8 as BS import Data.ByteString (ByteString) +import qualified Data.Map as Map+ data Torrent = Torrent- { tAnnounce :: String- , tAnnounceList :: [String]- , tComment :: String- , tCreatedBy :: Maybe String+ { tAnnounce :: ByteString+ , tAnnounceList :: [ByteString]+ , tComment :: ByteString+ , tCreatedBy :: Maybe ByteString , tInfo :: TorrentInfo , tInfoHash :: ByteString- } deriving Show+ } deriving (Show, Read, Typeable, Data) data TorrentInfo = SingleFile { tLength :: Int- , tName :: String+ , tName :: ByteString , tPieceLength :: Int , tPieces :: ByteString } | MultiFile { tFiles :: [TorrentFile]- , tName :: String+ , tName :: ByteString , tPieceLength :: Int , tPieces :: ByteString- } deriving Show+ } deriving (Show, Read, Typeable, Data) data TorrentFile = TorrentFile { fileLength :: Int- , filePath :: FilePath- } deriving Show+ , filePath :: [ByteString]+ } deriving (Show, Read, Typeable, Data) +instance Binary Torrent where+ put = put . serializeTorrent+ get = do e <- get+ case readTorrent e of+ Left err -> fail $ "Failed to parse torrent: " ++ err+ Right t -> return t + torrentSize :: Torrent -> Int torrentSize torrent = case tInfo torrent of@@ -68,24 +81,39 @@ parseTorrent :: BParser Torrent parseTorrent =- do announce <- bstring $ dict "announce"- creator <- optional $ bstring $ dict "created by"+ do announce <- bbytestring $ dict "announce"+ creator <- optional $ bbytestring $ dict "created by" info <- dict "info" setInput info- name <- bstring $ dict "name"+ name <- bbytestring $ dict "name" pLen <- bint $ dict "piece length"- pieces <- bfaststring $ dict "pieces"+ pieces <- bbytestring $ dict "pieces" torrentInfo <- parseTorrentInfo name pLen pieces let infoHash = sha1 (BS.pack $ bShow info "")- return $ Torrent announce [] "" creator torrentInfo infoHash+ return $ Torrent announce [] BS.empty creator torrentInfo infoHash -parseTorrentInfo :: String -> Int -> ByteString -> BParser TorrentInfo+parseTorrentInfo :: ByteString -> Int -> ByteString -> BParser TorrentInfo parseTorrentInfo name pLen pieces = do len <- bint $ dict "length" return $ SingleFile len name pLen pieces <|> do files <- list "files" $ do len <- bint $ dict "length"- filePaths <- list "path" $ bstring token- return $ TorrentFile len (foldr1 (</>) filePaths)+ filePaths <- list "path" $ bbytestring token+ return $ TorrentFile len filePaths return $ MultiFile files name pLen pieces +serializeTorrent :: Torrent -> BEncode+serializeTorrent torrent+ = BDict $ Map.fromList [("announce",BString $ tAnnounce torrent)+ ,("comment", BString $ tComment torrent)+ ,("info",info)+ ]+ where info = BDict $ Map.fromList $ [("name", BString $ tName (tInfo torrent))+ ,("pieces", BString $ tPieces (tInfo torrent))+ ,("piece length", BInt $ tPieceLength (tInfo torrent))+ ] ++ case tInfo torrent of+ SingleFile len _ _ _ -> [("length", BInt len)]+ MultiFile files _ _ _ -> [("files", BList $ flip map files $ \file ->+ BDict $ Map.fromList [("length", BInt (fileLength file))+ ,("path", BList (map BString $ filePath file))]+ )]
torrent.cabal view
@@ -1,11 +1,11 @@ Name: torrent-Version: 2007.6.29+Version: 2007.10.27 Maintainer: Lemmih (lemmih@gmail.com) Author: Lemmih (lemmih@gmail.com) Copyright: 2005-2007, Lemmih License-File: LICENSE License: BSD3-Build-Depends: base, bencode, filepath, network+Build-Depends: base, binary, bencode >=0.2, filepath, network Category: Network Synopsis: BitTorrent file parser. Tested-with: GHC ==6.6