packages feed

DAV 0.1 → 0.2

raw patch · 4 files changed

+110/−7 lines, 4 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

+ Network.Protocol.HTTP.DAV: getProps :: String -> ByteString -> ByteString -> IO Document
+ Network.Protocol.HTTP.DAV: makeCollection :: String -> ByteString -> ByteString -> IO Bool
+ Network.Protocol.HTTP.DAV: moveContent :: String -> ByteString -> ByteString -> ByteString -> IO ()
- Network.Protocol.HTTP.DAV: allowedMethods :: Lens (DAVContext a_a78E) (DAVContext a_a78E) [ByteString] [ByteString]
+ Network.Protocol.HTTP.DAV: allowedMethods :: Lens (DAVContext a_a7eD) (DAVContext a_a7eD) [ByteString] [ByteString]
- Network.Protocol.HTTP.DAV: baseRequest :: Lens (DAVContext a_a78E) (DAVContext a_a7OW) (Request a_a78E) (Request a_a7OW)
+ Network.Protocol.HTTP.DAV: baseRequest :: Lens (DAVContext a_a7eD) (DAVContext a_a7UV) (Request a_a7eD) (Request a_a7UV)
- Network.Protocol.HTTP.DAV: basicpassword :: Lens (DAVContext a_a78E) (DAVContext a_a78E) ByteString ByteString
+ Network.Protocol.HTTP.DAV: basicpassword :: Lens (DAVContext a_a7eD) (DAVContext a_a7eD) ByteString ByteString
- Network.Protocol.HTTP.DAV: basicusername :: Lens (DAVContext a_a78E) (DAVContext a_a78E) ByteString ByteString
+ Network.Protocol.HTTP.DAV: basicusername :: Lens (DAVContext a_a7eD) (DAVContext a_a7eD) ByteString ByteString
- Network.Protocol.HTTP.DAV: complianceClasses :: Lens (DAVContext a_a78E) (DAVContext a_a78E) [ByteString] [ByteString]
+ Network.Protocol.HTTP.DAV: complianceClasses :: Lens (DAVContext a_a7eD) (DAVContext a_a7eD) [ByteString] [ByteString]
- Network.Protocol.HTTP.DAV: httpManager :: Lens (DAVContext a_a78E) (DAVContext a_a78E) Manager Manager
+ Network.Protocol.HTTP.DAV: httpManager :: Lens (DAVContext a_a7eD) (DAVContext a_a7eD) Manager Manager
- Network.Protocol.HTTP.DAV: lockToken :: Lens (DAVContext a_a78E) (DAVContext a_a78E) (Maybe ByteString) (Maybe ByteString)
+ Network.Protocol.HTTP.DAV: lockToken :: Lens (DAVContext a_a7eD) (DAVContext a_a7eD) (Maybe ByteString) (Maybe ByteString)

Files

+ AUTHORS view
@@ -0,0 +1,2 @@+Clint Adams <clint@gnu.org>+Joey Hess <joey@kitenet.net>
DAV.cabal view
@@ -1,5 +1,5 @@ name:                DAV-version:             0.1+version:             0.2 synopsis:            RFC 4918 WebDAV support description:    This is a library for the Web Distributed Authoring and Versioning@@ -19,6 +19,7 @@ category:            Web build-type:          Simple cabal-version:       >=1.8+extra-source-files:  AUTHORS  library   exposed-modules:  Network.Protocol.HTTP.DAV@@ -56,3 +57,13 @@                      , transformers >= 0.3                      , xml-conduit >= 1.0          && <= 1.1                      , xml-hamlet >= 0.4           && <= 0.5++source-repository head+  type:     git+  location: git://anonscm.debian.org/users/clint/DAV.git+  branch:   master++source-repository this+  type:     git+  location: git://anonscm.debian.org/users/clint/DAV.git+  tag:      DAV/0.2
Network/Protocol/HTTP/DAV.hs view
@@ -21,9 +21,12 @@ module Network.Protocol.HTTP.DAV (     DAVState   , DAVContext(..)+  , getProps   , getPropsAndContent   , putContentAndProps   , deleteContent+  , moveContent+  , makeCollection   , module Network.Protocol.HTTP.DAV.TH ) where @@ -44,7 +47,7 @@ import Data.Maybe (fromMaybe)  import Network.HTTP.Conduit (httpLbs, parseUrl, applyBasicAuth, Request(..), RequestBody(..), Response(..), newManager, closeManager, ManagerSettings(..), def, HttpException(..))-import Network.HTTP.Types (hContentType, Method, RequestHeaders, unauthorized401)+import Network.HTTP.Types (hContentType, Method, Status, RequestHeaders, unauthorized401, conflict409)  import qualified Text.XML as XML import Text.XML.Cursor (($/), (&/), element, node, fromDocument, checkName)@@ -73,14 +76,16 @@     ctx <- get     let req = (ctx ^. baseRequest) { method = meth, requestHeaders = (mk "User-Agent", "hDav 9.0"):addlhdrs, requestBody = rbody }     let authreq = applyBasicAuth (ctx ^. basicusername) (ctx ^. basicpassword) req-    resp <- lift (catchJust (is401Exception)+    resp <- lift (catchJust (matchStatusCodeException unauthorized401)                             (httpLbs req (ctx ^. httpManager))                             (\_ -> httpLbs authreq (ctx ^. httpManager)))     return resp -is401Exception :: HttpException -> Maybe ()-is401Exception (StatusCodeException s _) = if s == unauthorized401 then Just () else Nothing-is401Exception _ = Nothing+matchStatusCodeException :: Status -> HttpException -> Maybe ()+matchStatusCodeException want (StatusCodeException s _)+    | s == want = Just ()+    | otherwise = Nothing+matchStatusCodeException _ _ = Nothing  emptyBody :: RequestBody m emptyBody = RequestBodyLBS BL.empty@@ -141,6 +146,17 @@     _ <- davRequest "DELETE" [] emptyBody     return () +mvContent :: MonadResourceBase m => B.ByteString -> DAVState m ()+mvContent newurl = do+    let ahs = [ (mk "Destination", newurl) ]+    _ <- davRequest "MOVE" ahs emptyBody+    return ()++mkCol :: MonadResourceBase m => DAVState m ()+mkCol = do+    _ <- davRequest "MKCOL" [] emptyBody+    return ()+ parenthesize :: B.ByteString -> B.ByteString parenthesize x = B.concat ["(", x, ")"] @@ -174,6 +190,9 @@                    , "{DAV:}supportedlock"                    ] +getProps :: String -> B.ByteString -> B.ByteString -> IO XML.Document+getProps url username password = withDS url username password getAllProps+ getPropsAndContent :: String -> B.ByteString -> B.ByteString -> IO (XML.Document, (Maybe B.ByteString, BL.ByteString)) getPropsAndContent url username password = withDS url username password $ do     getOptions@@ -199,6 +218,22 @@     -- a successful delete destroys locks, so only unlock on error     let unlock = when (supportsLocking o) (unlockResource)     bracketOnError lock (\_ -> unlock) (\_ -> delContent)++moveContent :: String -> B.ByteString -> B.ByteString -> B.ByteString -> IO ()+moveContent url newurl username password = withDS url username password $+    mvContent newurl++-- | Creates a WebDAV collection, which is similar to a directory.+--+-- Returns False if the collection could not be made due to an intermediate+-- collection not existing. (Ie, collection /a/b/c/d cannot be made until+-- collection /a/b/c exists.)+makeCollection :: String -> B.ByteString -> B.ByteString -> IO Bool+makeCollection url username password = withDS url username password $+    catchJust+        (matchStatusCodeException conflict409)+        (mkCol >> return True)+        (\_ -> return False)  propname :: XML.Document propname = XML.Document (XML.Prologue [] Nothing []) root []
hdav.hs view
@@ -21,12 +21,17 @@ import Paths_DAV (version) import Data.Version (showVersion) import Data.Maybe (fromMaybe, fromJust)+import Control.Monad (unless)+import Text.XML (renderLBS, def)+import qualified Data.ByteString.Lazy.Char8 as B  import Network (withSocketsDo) +import Network.URI (normalizePathSegments)+ import qualified System.Console.CmdArgs.Explicit as CA -import Network.Protocol.HTTP.DAV (getPropsAndContent, putContentAndProps, deleteContent)+import Network.Protocol.HTTP.DAV (getProps, getPropsAndContent, putContentAndProps, deleteContent, moveContent, makeCollection)  doCopy :: [(String, String)] -> IO () doCopy as = do@@ -46,10 +51,48 @@      let password = BC8.pack . fromMaybe "" . lookup "password" $ as      deleteContent url username password +doMove :: [(String, String)] -> IO ()+doMove as = do+     let url1 = fromJust . lookup "sourceurl" $ as+     let url2 = fromJust . lookup "targeturl" $ as+     let username = BC8.pack . fromMaybe "" . lookup "username" $ as+     let password = BC8.pack . fromMaybe "" . lookup "password" $ as+     moveContent url1 (BC8.pack url2) username password++doMakeCollection :: [(String, String)] -> IO ()+doMakeCollection as = do+     let url = fromJust . lookup "url" $ as+     go url+  where+     username = BC8.pack . fromMaybe "" . lookup "username" $ as+     password = BC8.pack . fromMaybe "" . lookup "password" $ as++     go url = do+       ok <- makeCollection url username password+       unless ok $ do+         go (parent url)+         ok' <- makeCollection url username password+         unless ok' $+           error $ "failed creating " ++ url++     parent url = reverse $ dropWhile (== '/')$ reverse $+        normalizePathSegments (url ++ "/..")++doGetProps :: [(String, String)] -> IO ()+doGetProps as = do+     let url = fromJust . lookup "url" $ as+     let username = BC8.pack . fromMaybe "" . lookup "username" $ as+     let password = BC8.pack . fromMaybe "" . lookup "password" $ as+     doc <- getProps url username password+     B.putStrLn (renderLBS def doc)+ dispatch :: String -> [(String, String)] -> IO () dispatch m as     | m == "copy" = doCopy as+    | m == "move" = doMove as     | m == "delete" = doDelete as+    | m == "makecollection" = doMakeCollection as+    | m == "getprops" = doGetProps as     | otherwise = fail "Unexpected condition."  showHelp :: IO ()@@ -77,7 +120,19 @@ 		, CA.flagReq ["target-username"] (upd "target-username") "USERNAME" "username for target URL" 		, CA.flagReq ["target-password"] (upd "target-password") "PASSWORD" "password for target URL" 		, CA.flagHelpSimple (("help",""):)]) { CA.modeArgs = ([(CA.flagArg (upd "sourceurl") "SOURCEURL") { CA.argRequire = True }, (CA.flagArg (upd "targeturl") "TARGETURL") { CA.argRequire = True }], Nothing) }+              , (CA.mode "move" [("mode", "move")] "move" (CA.flagArg (upd "sourceurl") "SOURCEURL") [+	          CA.flagReq ["username"] (upd "username") "USERNAME" "username for source and target URL"+		, CA.flagReq ["password"] (upd "password") "PASSWORD" "password for source and target URL"+		, CA.flagHelpSimple (("help",""):)]) { CA.modeArgs = ([(CA.flagArg (upd "sourceurl") "SOURCEURL") { CA.argRequire = True }, (CA.flagArg (upd "targeturl") "TARGETURL") { CA.argRequire = True }], Nothing) }               , (CA.mode "delete" [("mode", "delete")] "delete" (CA.flagArg (upd "url") "URL") [+	          CA.flagReq ["username"] (upd "username") "USERNAME" "username for URL"+		, CA.flagReq ["password"] (upd "password") "PASSWORD" "password for URL"+		, CA.flagHelpSimple (("help",""):)]) { CA.modeArgs = ([(CA.flagArg (upd "url") "URL") { CA.argRequire = True }], Nothing) }+              , (CA.mode "makecollection" [("mode", "makecollection")] "makecollecton" (CA.flagArg (upd "url") "URL") [+	          CA.flagReq ["username"] (upd "username") "USERNAME" "username for URL"+		, CA.flagReq ["password"] (upd "password") "PASSWORD" "password for URL"+		, CA.flagHelpSimple (("help",""):)]) { CA.modeArgs = ([(CA.flagArg (upd "url") "URL") { CA.argRequire = True }], Nothing) }+              , (CA.mode "getprops" [("mode", "getprops")] "getprops" (CA.flagArg (upd "url") "URL") [ 	          CA.flagReq ["username"] (upd "username") "USERNAME" "username for URL" 		, CA.flagReq ["password"] (upd "password") "PASSWORD" "password for URL" 		, CA.flagHelpSimple (("help",""):)]) { CA.modeArgs = ([(CA.flagArg (upd "url") "URL") { CA.argRequire = True }], Nothing) }