X-Git-Url: http://git.cielonegro.org/gitweb.cgi?a=blobdiff_plain;f=Network%2FHTTP%2FLucu%2FAuthorization.hs;h=64183ff1c86ef1317efd3352d94ff051fa6cd429;hb=c7a8bc012b1b70353d567bfab86fc6e849d60c20;hp=6b0e1c268323150607da4f5ea2be37a92ea9ff58;hpb=70bf5bd248aa426ca4e410b3fb9a0529354aedaf;p=Lucu.git diff --git a/Network/HTTP/Lucu/Authorization.hs b/Network/HTTP/Lucu/Authorization.hs index 6b0e1c2..64183ff 100644 --- a/Network/HTTP/Lucu/Authorization.hs +++ b/Network/HTTP/Lucu/Authorization.hs @@ -1,5 +1,6 @@ {-# LANGUAGE - UnicodeSyntax + OverloadedStrings + , UnicodeSyntax #-} {-# OPTIONS_HADDOCK prune #-} @@ -11,12 +12,16 @@ module Network.HTTP.Lucu.Authorization , UserID , Password + , printAuthChallenge , authCredentialP -- private ) where +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 Network.HTTP.Lucu.Parser +import Data.Monoid.Unicode import Network.HTTP.Lucu.Parser.Http import Network.HTTP.Lucu.Utils import Prelude.Unicode @@ -29,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 @@ -40,32 +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 - = 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 ≡ '=') - case break (≡ ':') (decode b64) of - (uid, ':' : password) - → return (BasicAuthCredential uid password) - _ → failP + = 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 - decode ∷ String → String - decode = C8.unpack ∘ B64.decodeLenient ∘ C8.pack + base64 ∷ Char → Bool + 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"