packages feed

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 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