download 0.1 → 0.2
raw patch · 2 files changed
+98/−52 lines, 2 filesdep +feeddep +xmldep ~base
Dependencies added: feed, xml
Dependency ranges changed: base
Files
- Network/Download.hsc +81/−37
- download.cabal +17/−15
Network/Download.hsc view
@@ -1,3 +1,8 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE ForeignFunctionInterface #-}+{-# LANGUAGE EmptyDataDecls #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+ -------------------------------------------------------------------- -- | -- Module : Network.Download@@ -8,21 +13,27 @@ -- Stability : provisional -- Portability: posix ----- A binding to libdownload, a efficient, high‐level library for+-- A binding to libdownload, an efficient, high level library for -- retrieving files using Uniform Resource Locators (URLs). This--- provides simple, uniform access to file, ftp and http resources.--- Content may be retrieved as a string, bytestring or as parsed tags.------ Example:+-- provides simple, uniform access to file, FTP and HTTP resources.+-- Content may be retrieved as a strings, "ByteString" or parsed+-- as HTML tags, XML or RSS and Atom feeds. ----- > s <- openURI "http://haskell.org"+-- Error handling is encapsulated in the "Either" type. -- -------------------------------------------------------------------- module Network.Download (++ -- * The basic interface to network content openURI , openURIString- , parseURI++ -- * Parsers for common formats+ , parseTags+ , parseXML+ , parseFeed+ ) where import Foreign@@ -37,33 +48,34 @@ import System.IO.Unsafe import Control.Exception -import qualified Data.ByteString as S-import qualified Data.ByteString.Unsafe as S import qualified Data.ByteString.Internal as S- import qualified Data.ByteString.Char8 as Char8-import Text.HTML.TagSoup +-- Parsers+import qualified Text.HTML.TagSoup as TagSoup+import qualified Text.XML.Light as XML+import qualified Text.Feed.Import as Feed+import qualified Text.Feed.Types as Feed+ #include "download.h" --------------------------------------------------------------------------- Some API ideas: -- | Download content specified by url (in RFC1738 form), using either--- ftp, http or file protocols, returning the content as a strict--- 'ByteString'.+-- FTP, HTTP or file protocols, returning the content as a strict+-- "ByteString". ----- If the url is malformed, a 'Left' value is returned.--- Similarly, if an error occurs, 'Left' is returned, with a+-- If the url is malformed, a "Left" value is returned.+-- Similarly, if an error occurs, "Left" is returned, with a -- protocol-specific error string. -- -- If the file protocol is used, documents will be retrieved from the -- local filesystem. If the ftp scheme is used, the FTP protocol -- (RFC959) is used. If no user name or passoword are provided,--- anonymous login, with user name "anonymous" and password "anonymous@<hostname>".+-- anonymous login, with user name 'anonymous' and password 'anonymous' -- will be attempted. ----- If the http method is used, HTTP/1.1 will be used.+-- If the http method is used, HTTP\/1.1 will be used. -- -- Examples: --@@ -74,21 +86,46 @@ Nothing -> return $ Left $ "Malformed url: "++ s Just url -> do e <- getFile url []- case e of- Left err -> return $ Left $ "Failed to connect: " ++ err- Right s -> return $ Right s+ return $ case e of+ Left err -> Left $ "Failed to connect: " ++ err+ Right src -> Right src -- | Like openURI, but returns the result as a 'String' --+-- Examples:+--+-- > openURIString "http://haskell.org"+-- openURIString :: String -> IO (Either String String) openURIString s = (fmap Char8.unpack) `fmap` openURI s --- | Download the content via openURI, but return it as a list of parsed--- tags using the tagsoup html parser.+------------------------------------------------------------------------+-- Parser interface:++-- | Download the content as for "openURI", but return it as a list of+-- parsed tags using the tagsoup html parser. ---parseURI :: String -> IO (Either String [Tag])-parseURI s = (fmap parseTags) `fmap` openURIString s+parseTags:: String -> IO (Either String [TagSoup.Tag])+parseTags s = (fmap TagSoup.parseTags) `fmap` openURIString s +-- | Download the content as for "openURI", but return it as parsed XML,+-- using the xml-light parser.+--+parseXML:: String -> IO (Either String [XML.Content])+parseXML s = (fmap XML.parseXML) `fmap` openURIString s++-- | Download the content as for "openURI", but return it as parsed RSS+-- or Atom content, using the feed library parser.+--+parseFeed :: String -> IO (Either String Feed.Feed)+parseFeed s = do+ e <- openURIString s+ return $ case e of+ Left err -> Left err -- gluing Either -> Maybe+ Right src -> case Feed.parseFeedString src of+ Nothing -> Left "Unable to parse feed"+ Just src' -> Right src'+ ------------------------------------------------------------------------ -- Internal: @@ -98,7 +135,7 @@ data URL = URL {-# UNPACK #-} !(ForeignPtr URL_) deriving (Eq, Ord, Show) -data URL_ = URL_+data URL_ -- | Takes a URL in the form of a String and splits it into its -- components function according to the Common Internet Scheme Syntax@@ -149,8 +186,8 @@ -- scheme‐dependent, and is detailed in the appropriate section below. -- getFile :: URL -> [Flag] -> IO (Either String S.ByteString)-getFile (URL fp) flags = do- withForeignPtr fp $ \c_url ->+getFile (URL url_fp) flags = do+ withForeignPtr url_fp $ \c_url -> withCString (map encodeFlag flags) $ \c_flags -> bracket (do sp <- c_get c_url c_flags@@ -243,21 +280,24 @@ ------------------------------------------------------------------------ +{- version :: String version = #const_str USER_AGENT_STRING+-} ------------------------------------------------------------------------ -type URLLen = Int--#{enum URLLen,- , url_schemelen = URL_SCHEMELEN- , url_userlen = URL_USERLEN- , url_pwdlen = URL_PWDLEN- }+-- type URLLen = Int+-- +-- #{enum URLLen,+-- , url_schemelen = URL_SCHEMELEN+-- , url_userlen = URL_USERLEN+-- , url_pwdlen = URL_PWDLEN+-- } ------------------------------------------------------------------------ +{- newtype Scheme = Scheme { unScheme :: String } deriving (Eq, Show) @@ -266,14 +306,18 @@ scheme_http = Scheme #const_str SCHEME_HTTP scheme_https = Scheme #const_str SCHEME_HTTPS scheme_file = Scheme #const_str SCHEME_FILE+-} ------------------------------------------------------------------------ -newtype DLError = DLError { unDLError :: CInt }+newtype DLError = DLError CInt deriving (Eq, Show) #{enum DLError, DLError , dlerr_none = DLERR_NONE+ }++{- , dlerr_abort = DLERR_ABORT , dlerr_auth = DLERR_AUTH , dlerr_down = DLERR_DOWN@@ -293,4 +337,4 @@ , dlerr_unknown = DLERR_UNKNOWN , dlerr_url = DLERR_URL , dlerr_verbose = DLERR_VERBOSE- }+-}
download.cabal view
@@ -1,11 +1,13 @@ name: download-version: 0.1+version: 0.2 homepage: http://code.haskell.org/~dons/code/download synopsis: High-level file download based on URLs-description: High-level File download based on URLs+description: High-level file download based on URLs .- Download content as bytestrings, strings or parsed- tags, via ftp, http or file protocols.+ Download web content as strict bytestring, strings,+ HTML tags, XML, RSS or Atom feeds or JSON, via HTTP,+ FTP or file protocols, using a URL interface.+ . category: Network license: BSD3 license-file: LICENSE@@ -20,17 +22,25 @@ -- description: Build with an external libdownload -- default: False --- flag small_base--- description: Build with new smaller base library+flag small_base+ description: Build with new smaller base library library exposed-modules: Network.Download extensions: CPP, ForeignFunctionInterface,+ EmptyDataDecls, GeneralizedNewtypeDeriving+ ghc-options: -Wall -fvia-C- build-depends: base, bytestring, tagsoup + if flag(small_base)+ build-depends: base >= 3, bytestring+ else+ build-depends: base > 3++ build-depends: tagsoup, feed, xml+ ------------------------------------------------------------------------ -- Building libdownload --@@ -45,17 +55,9 @@ -- else cc-options: -O2- -pipe -DINET6 -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64- -Wall- -Wstrict-prototypes- -Wsign-compare- -Wchar-subscripts- -Wpointer-arith- -Wcast-align- -Wsign-compare -UDEBUG c-sources: cbits/download.c