X-Git-Url: http://git.cielonegro.org/gitweb.cgi?p=Lucu.git;a=blobdiff_plain;f=Network%2FHTTP%2FLucu%2FAuthentication.hs;h=69223f2e1bb82c878c2f1174cc007a44a850f90e;hp=74791881d68a7bd8449ca1495be7ba108d52cc34;hb=67f9e87;hpb=0aa4f6d758fc12fba468f7cd399bbcc48f693d1e diff --git a/Network/HTTP/Lucu/Authentication.hs b/Network/HTTP/Lucu/Authentication.hs index 7479188..69223f2 100644 --- a/Network/HTTP/Lucu/Authentication.hs +++ b/Network/HTTP/Lucu/Authentication.hs @@ -1,63 +1,73 @@ {-# LANGUAGE - OverloadedStrings + FlexibleInstances + , MultiParamTypeClasses + , OverloadedStrings + , TemplateHaskell , UnicodeSyntax #-} --- |Manipulation of WWW authentication. +-- |An internal module for HTTP authentication. module Network.HTTP.Lucu.Authentication ( AuthChallenge(..) , AuthCredential(..) , Realm , UserID , Password - - , printAuthChallenge - , authCredentialP + , authCredential ) where -import Data.Ascii (Ascii) -import qualified Data.Ascii as A +import Control.Monad +import Data.Ascii (Ascii, AsciiBuilder) +import Data.Attempt import Data.Attoparsec.Char8 import qualified Data.ByteString.Base64 as B64 import qualified Data.ByteString.Char8 as C8 +import Data.Convertible.Base +import Data.Convertible.Instances.Ascii () +import Data.Convertible.Utils import Data.Monoid.Unicode import Network.HTTP.Lucu.Parser.Http import Network.HTTP.Lucu.Utils import Prelude.Unicode --- |Authorization challenge to be sent to client with --- \"WWW-Authenticate\" header. See --- 'Network.HTTP.Lucu.Resource.setWWWAuthenticate'. +-- |Authentication challenge to be sent to clients with +-- \"WWW-Authenticate\" header field. See +-- 'Network.HTTP.Lucu.setWWWAuthenticate'. data AuthChallenge = BasicAuthChallenge !Realm deriving (Eq) --- |'Realm' is just a string which must not contain any non-ASCII letters. +-- |'Realm' is just an 'Ascii' string. type Realm = Ascii -- |Authorization credential to be sent by client with --- \"Authorization\" header. See --- 'Network.HTTP.Lucu.Resource.getAuthorization'. +-- \"Authorization\" header. See 'Network.HTTP.Lucu.getAuthorization'. data AuthCredential = BasicAuthCredential !UserID !Password deriving (Show, Eq) --- |'UserID' is just a string which must not contain colon and any --- non-ASCII letters. -type UserID = Ascii +-- |'UserID' is just an 'Ascii' string containing no colons (\':\'). +type UserID = Ascii --- |'Password' is just a string which must not contain any non-ASCII --- letters. +-- |'Password' is just an 'Ascii' string. type Password = Ascii --- |Convert an 'AuthChallenge' to 'Ascii'. -printAuthChallenge ∷ AuthChallenge → Ascii -printAuthChallenge (BasicAuthChallenge realm) - = A.fromAsciiBuilder $ - A.toAsciiBuilder "Basic realm=" ⊕ quoteStr realm +instance ConvertSuccess AuthChallenge Ascii where + {-# INLINE convertSuccess #-} + convertSuccess = convertSuccessVia ((⊥) ∷ AsciiBuilder) + +instance ConvertSuccess AuthChallenge AsciiBuilder where + {-# INLINE convertSuccess #-} + convertSuccess (BasicAuthChallenge realm) + = cs ("Basic realm=" ∷ Ascii) ⊕ quoteStr realm + +deriveAttempts [ ([t| AuthChallenge |], [t| Ascii |]) + , ([t| AuthChallenge |], [t| AsciiBuilder |]) + ] -authCredentialP ∷ Parser AuthCredential -authCredentialP - = do _ ← string "Basic" +-- |'Parser' for an 'AuthCredential'. +authCredential ∷ Parser AuthCredential +authCredential + = do void $ string "Basic" skipMany1 lws b64 ← takeWhile1 base64 case C8.break (≡ ':') (B64.decodeLenient b64) of @@ -73,6 +83,6 @@ authCredentialP base64 = inClass "a-zA-Z0-9+/=" asc ∷ C8.ByteString → Parser Ascii - asc bs = case A.fromByteString bs of - Just as → return as - Nothing → fail "Non-ascii character in auth credential" + asc bs = case ca bs of + Success as → return as + Failure _ → fail "Non-ascii character in auth credential"