X-Git-Url: http://git.cielonegro.org/gitweb.cgi?a=blobdiff_plain;f=Network%2FHTTP%2FLucu%2FAuthorization.hs;h=64183ff1c86ef1317efd3352d94ff051fa6cd429;hb=c7a8bc012b1b70353d567bfab86fc6e849d60c20;hp=b0b0e06c2d36deb8a7e66135976411eba5454375;hpb=2321c55149b4fd126835b1d2f708007ca1ffcb85;p=Lucu.git diff --git a/Network/HTTP/Lucu/Authorization.hs b/Network/HTTP/Lucu/Authorization.hs index b0b0e06..64183ff 100644 --- a/Network/HTTP/Lucu/Authorization.hs +++ b/Network/HTTP/Lucu/Authorization.hs @@ -1,4 +1,8 @@ --- #prune +{-# LANGUAGE + OverloadedStrings + , UnicodeSyntax + #-} +{-# OPTIONS_HADDOCK prune #-} -- |Manipulation of WWW authorization. module Network.HTTP.Lucu.Authorization @@ -8,15 +12,19 @@ module Network.HTTP.Lucu.Authorization , UserID , Password + , printAuthChallenge , authCredentialP -- private ) where - -import qualified Codec.Binary.Base64 as B64 -import Data.Maybe -import Network.HTTP.Lucu.Parser -import Network.HTTP.Lucu.Parser.Http -import Network.HTTP.Lucu.Utils +import Data.Ascii (Ascii) +import qualified Data.Ascii as A +import Data.Attoparsec.Char8 +import qualified Data.ByteString.Base64 as B64 +import qualified Data.ByteString.Char8 as C8 +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 @@ -26,7 +34,7 @@ data AuthChallenge deriving (Eq) -- |'Realm' is just a string which must not contain any non-ASCII letters. -type Realm = String +type Realm = Ascii -- |Authorization credential to be sent by client with -- \"Authorization\" header. See @@ -37,31 +45,37 @@ data AuthCredential -- |'UserID' is just a string which must not contain colon and any -- non-ASCII letters. -type UserID = String +type UserID = Ascii -- |'Password' is just a string which must not contain any non-ASCII -- letters. -type Password = String - +type Password = Ascii -instance Show AuthChallenge where - show (BasicAuthChallenge realm) - = "Basic realm=" ++ quoteStr realm +-- |Convert an 'AuthChallenge' to 'Ascii'. +printAuthChallenge ∷ AuthChallenge → Ascii +printAuthChallenge (BasicAuthChallenge realm) + = A.fromAsciiBuilder $ + A.toAsciiBuilder "Basic realm=" ⊕ quoteStr realm +authCredentialP ∷ Parser AuthCredential +authCredentialP + = try $ + do _ ← string "Basic" + skipMany1 lws + b64 ← takeWhile1 base64 + case C8.break (≡ ':') (B64.decodeLenient b64) of + (user, cPassword) + | C8.null cPassword + → fail "no colons in the basic auth credential" + | otherwise + → do u ← asc user + p ← asc (C8.tail cPassword) + return (BasicAuthCredential u p) + where + base64 ∷ Char → Bool + base64 = inClass "a-zA-Z0-9+/=" -authCredentialP :: Parser AuthCredential -authCredentialP = allowEOF $! - do string "Basic" - many1 lws - b64 <- many1 - $ satisfy (\ c -> (c >= 'a' && c <= 'z') || - (c >= 'A' && c <= 'Z') || - (c >= '0' && c <= '9') || - c == '+' || - c == '/' || - c == '=') - let decoded = map (toEnum . fromEnum) (fromJust $ B64.decode b64) - case break (== ':') decoded of - (uid, ':' : password) - -> return (BasicAuthCredential uid password) - _ -> failP + asc ∷ C8.ByteString → Parser Ascii + asc bs = case A.fromByteString bs of + Just as → return as + Nothing → fail "Non-ascii character in auth credential"