packages feed

snaplet-customauth-0.3.0: Snap/Snaplet/CustomAuth/Challenge.hs

module Snap.Snaplet.CustomAuth.Challenge where

import Control.Applicative
import Data.Attoparsec.ByteString
import Data.Attoparsec.ByteString.Char8 (char)
import Data.ByteString (ByteString)
import Data.CaseInsensitive (CI, mk)
import Data.Char
import Data.Word
import Prelude hiding (takeWhile)

data WWWAuthenticateChallenge = WWWAuthenticateChallenge
  { challengeScheme :: CI ByteString
  , challengeParams :: [(CI ByteString, ByteString)]
  }
  deriving (Show, Eq)

parseWWWAuthenticateChallenge :: ByteString -> [WWWAuthenticateChallenge]
parseWWWAuthenticateChallenge x = either (const []) id $ flip parseOnly x $
  parseChallenge `sepBy` (char ',' *> spaces)
  where
    f :: (Enum a, Enum b) => a -> b
    f = toEnum . fromEnum
    spaces = skipWhile (isSpace . f)
    parseChallenge =
      WWWAuthenticateChallenge
      <$> (mk <$> takeWhile1 (/= (f ' ')) <* spaces)
      <*> authParam `sepBy1` (char ',' *> spaces)
    authParam =
      (,)
      <$> (mk <$> takeWhile1 (/= f '='))
      <* char '='
      <*> (((char '"' *> takeWhile (/= f '"') <* char '"') <|>
           (takeWhile (isAlphaNum . f))
           ) <|>
           (takeWhile (/= f ' ')))
      <* spaces