{-# LANGUAGE OverloadedStrings #-}
module Codec.Encryption.OpenPGP.ASCIIArmor.Decode (
parseArmor
, decode
, decodeLazy
) where
import Codec.Encryption.OpenPGP.ASCIIArmor.Types
import Codec.Encryption.OpenPGP.ASCIIArmor.Utils
import Control.Applicative (many, (<|>), (<$>), (<*), (<*>), (*>), optional)
import Data.Attoparsec.ByteString (Parser, many1, string, inClass, notInClass, satisfy, word8, (<?>))
import qualified Data.Attoparsec.ByteString as AS
import qualified Data.Attoparsec.ByteString.Lazy as AL
import Data.Attoparsec.ByteString.Char8 (isDigit_w8, anyChar)
import Data.Bits (shiftL)
import Data.ByteString.Lazy (ByteString)
import qualified Data.ByteString as B
import qualified Data.ByteString.Lazy as BL
import qualified Data.ByteString.Char8 as BC8
import qualified Data.ByteString.Base64 as Base64
import Data.Digest.CRC24 (crc24)
import Data.Binary.Get (Get, runGetOrFail, getWord8)
import Data.Functor (($>))
import Data.String (IsString, fromString)
import Data.Word (Word32)
decode :: IsString e => B.ByteString -> Either e [Armor]
decode :: forall e. IsString e => ByteString -> Either e [Armor]
decode ByteString
bs = IResult ByteString [Armor] -> Either e [Armor]
forall {a} {b}. IsString a => IResult ByteString b -> Either a b
go (Parser [Armor] -> ByteString -> IResult ByteString [Armor]
forall a. Parser a -> ByteString -> Result a
AS.parse Parser [Armor]
parseArmors ByteString
bs)
where
go :: IResult ByteString b -> Either a b
go (AS.Fail ByteString
_ [[Char]]
_ [Char]
e) = a -> Either a b
forall a b. a -> Either a b
Left ([Char] -> a
forall a. IsString a => [Char] -> a
fromString [Char]
e)
go (AS.Partial ByteString -> IResult ByteString b
cont) = IResult ByteString b -> Either a b
go (ByteString -> IResult ByteString b
cont ByteString
B.empty)
go (AS.Done ByteString
_ b
r) = b -> Either a b
forall a b. b -> Either a b
Right b
r
decodeLazy :: IsString e => BL.ByteString -> Either e [Armor]
decodeLazy :: forall e. IsString e => ByteString -> Either e [Armor]
decodeLazy ByteString
bs = Result [Armor] -> Either e [Armor]
forall {a} {b}. IsString a => Result b -> Either a b
go (Parser [Armor] -> ByteString -> Result [Armor]
forall a. Parser a -> ByteString -> Result a
AL.parse Parser [Armor]
parseArmors ByteString
bs)
where
go :: Result b -> Either a b
go (AL.Fail ByteString
_ [[Char]]
_ [Char]
e) = a -> Either a b
forall a b. a -> Either a b
Left ([Char] -> a
forall a. IsString a => [Char] -> a
fromString [Char]
e)
go (AL.Done ByteString
_ b
r) = b -> Either a b
forall a b. b -> Either a b
Right b
r
parseArmors :: Parser [Armor]
parseArmors :: Parser [Armor]
parseArmors = Parser ByteString Armor -> Parser [Armor]
forall a. Parser ByteString a -> Parser ByteString [a]
forall (f :: * -> *) a. Alternative f => f a -> f [a]
many Parser ByteString Armor
parseArmor
parseArmor :: Parser Armor
parseArmor :: Parser ByteString Armor
parseArmor = Parser ByteString Armor -> Parser ByteString Armor
forall a. Parser a -> Parser a
prefixed (Parser ByteString Armor
clearsigned Parser ByteString Armor
-> Parser ByteString Armor -> Parser ByteString Armor
forall a.
Parser ByteString a -> Parser ByteString a -> Parser ByteString a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser ByteString Armor
armor) Parser ByteString Armor -> [Char] -> Parser ByteString Armor
forall i a. Parser i a -> [Char] -> Parser i a
<?> [Char]
"armor"
clearsigned :: Parser Armor
clearsigned :: Parser ByteString Armor
clearsigned = do
ByteString
_ <- ByteString -> Parser ByteString
string ByteString
"-----BEGIN PGP SIGNED MESSAGE-----" Parser ByteString -> [Char] -> Parser ByteString
forall i a. Parser i a -> [Char] -> Parser i a
<?> [Char]
"clearsign header"
ByteString
_ <- Parser ByteString
lineEnding Parser ByteString -> [Char] -> Parser ByteString
forall i a. Parser i a -> [Char] -> Parser i a
<?> [Char]
"line ending"
[([Char], [Char])]
headers <- Parser [([Char], [Char])]
armorHeaders Parser [([Char], [Char])] -> [Char] -> Parser [([Char], [Char])]
forall i a. Parser i a -> [Char] -> Parser i a
<?> [Char]
"clearsign headers"
ByteString
_ <- Parser ByteString
blankishLine Parser ByteString -> [Char] -> Parser ByteString
forall i a. Parser i a -> [Char] -> Parser i a
<?> [Char]
"blank line"
ByteString
cleartext <- Parser ByteString
dashEscapedCleartext
Armor
sig <- Parser ByteString Armor
armor
Armor -> Parser ByteString Armor
forall a. a -> Parser ByteString a
forall (m :: * -> *) a. Monad m => a -> m a
return (Armor -> Parser ByteString Armor)
-> Armor -> Parser ByteString Armor
forall a b. (a -> b) -> a -> b
$ [([Char], [Char])] -> ByteString -> Armor -> Armor
ClearSigned [([Char], [Char])]
headers ByteString
cleartext Armor
sig
armor :: Parser Armor
armor :: Parser ByteString Armor
armor = do
ArmorType
atype <- Parser ArmorType
beginLine Parser ArmorType -> [Char] -> Parser ArmorType
forall i a. Parser i a -> [Char] -> Parser i a
<?> [Char]
"begin line"
[([Char], [Char])]
headers <- Parser [([Char], [Char])]
armorHeaders Parser [([Char], [Char])] -> [Char] -> Parser [([Char], [Char])]
forall i a. Parser i a -> [Char] -> Parser i a
<?> [Char]
"headers"
ByteString
_ <- Parser ByteString
blankishLine Parser ByteString -> [Char] -> Parser ByteString
forall i a. Parser i a -> [Char] -> Parser i a
<?> [Char]
"blank line"
ByteString
payload <- Parser ByteString
base64Data Parser ByteString -> [Char] -> Parser ByteString
forall i a. Parser i a -> [Char] -> Parser i a
<?> [Char]
"base64 data"
ByteString
_ <- ArmorType -> Parser ByteString
endLine ArmorType
atype Parser ByteString -> [Char] -> Parser ByteString
forall i a. Parser i a -> [Char] -> Parser i a
<?> [Char]
"end line"
Armor -> Parser ByteString Armor
forall a. a -> Parser ByteString a
forall (m :: * -> *) a. Monad m => a -> m a
return (Armor -> Parser ByteString Armor)
-> Armor -> Parser ByteString Armor
forall a b. (a -> b) -> a -> b
$ ArmorType -> [([Char], [Char])] -> ByteString -> Armor
Armor ArmorType
atype [([Char], [Char])]
headers ByteString
payload
beginLine :: Parser ArmorType
beginLine :: Parser ArmorType
beginLine = do
ByteString
_ <- ByteString -> Parser ByteString
string ByteString
"-----BEGIN PGP " Parser ByteString -> [Char] -> Parser ByteString
forall i a. Parser i a -> [Char] -> Parser i a
<?> [Char]
"leading minus-hyphens"
ArmorType
atype <- Parser ArmorType
pubkey Parser ArmorType -> Parser ArmorType -> Parser ArmorType
forall a.
Parser ByteString a -> Parser ByteString a -> Parser ByteString a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser ArmorType
privkey Parser ArmorType -> Parser ArmorType -> Parser ArmorType
forall a.
Parser ByteString a -> Parser ByteString a -> Parser ByteString a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser ArmorType
parts Parser ArmorType -> Parser ArmorType -> Parser ArmorType
forall a.
Parser ByteString a -> Parser ByteString a -> Parser ByteString a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser ArmorType
message Parser ArmorType -> Parser ArmorType -> Parser ArmorType
forall a.
Parser ByteString a -> Parser ByteString a -> Parser ByteString a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser ArmorType
signature
ByteString
_ <- ByteString -> Parser ByteString
string ByteString
"-----" Parser ByteString -> [Char] -> Parser ByteString
forall i a. Parser i a -> [Char] -> Parser i a
<?> [Char]
"trailing minus-hyphens"
[Word8]
_ <- Parser ByteString Word8 -> Parser ByteString [Word8]
forall a. Parser ByteString a -> Parser ByteString [a]
forall (f :: * -> *) a. Alternative f => f a -> f [a]
many ((Word8 -> Bool) -> Parser ByteString Word8
satisfy ([Char] -> Word8 -> Bool
inClass [Char]
" \t")) Parser ByteString [Word8] -> [Char] -> Parser ByteString [Word8]
forall i a. Parser i a -> [Char] -> Parser i a
<?> [Char]
"whitespace"
ByteString
_ <- Parser ByteString
lineEnding Parser ByteString -> [Char] -> Parser ByteString
forall i a. Parser i a -> [Char] -> Parser i a
<?> [Char]
"line ending"
ArmorType -> Parser ArmorType
forall a. a -> Parser ByteString a
forall (m :: * -> *) a. Monad m => a -> m a
return ArmorType
atype
where
message :: Parser ArmorType
message = ByteString -> Parser ByteString
string ByteString
"MESSAGE" Parser ByteString -> ArmorType -> Parser ArmorType
forall (f :: * -> *) a b. Functor f => f a -> b -> f b
$> ArmorType
ArmorMessage
pubkey :: Parser ArmorType
pubkey = ByteString -> Parser ByteString
string ByteString
"PUBLIC KEY BLOCK" Parser ByteString -> ArmorType -> Parser ArmorType
forall (f :: * -> *) a b. Functor f => f a -> b -> f b
$> ArmorType
ArmorPublicKeyBlock
privkey :: Parser ArmorType
privkey = ByteString -> Parser ByteString
string ByteString
"PRIVATE KEY BLOCK" Parser ByteString -> ArmorType -> Parser ArmorType
forall (f :: * -> *) a b. Functor f => f a -> b -> f b
$> ArmorType
ArmorPrivateKeyBlock
signature :: Parser ArmorType
signature = ByteString -> Parser ByteString
string ByteString
"SIGNATURE" Parser ByteString -> ArmorType -> Parser ArmorType
forall (f :: * -> *) a b. Functor f => f a -> b -> f b
$> ArmorType
ArmorSignature
parts :: Parser ArmorType
parts = ByteString -> Parser ByteString
string ByteString
"MESSAGE, PART " Parser ByteString -> Parser ArmorType -> Parser ArmorType
forall a b.
Parser ByteString a -> Parser ByteString b -> Parser ByteString b
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> (Parser ArmorType
partsdef Parser ArmorType -> Parser ArmorType -> Parser ArmorType
forall a.
Parser ByteString a -> Parser ByteString a -> Parser ByteString a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser ArmorType
partsindef)
partsdef :: Parser ArmorType
partsdef = do
[Word8]
firstnum <- Parser ByteString [Word8]
num
Word8
_ <- Word8 -> Parser ByteString Word8
word8 (Int -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> Word8) -> (Char -> Int) -> Char -> Word8
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> Int
forall a. Enum a => a -> Int
fromEnum (Char -> Word8) -> Char -> Word8
forall a b. (a -> b) -> a -> b
$ Char
'/')
[Word8]
secondnum <- Parser ByteString [Word8]
num
ArmorType -> Parser ArmorType
forall a. a -> Parser ByteString a
forall (m :: * -> *) a. Monad m => a -> m a
return (ArmorType -> Parser ArmorType) -> ArmorType -> Parser ArmorType
forall a b. (a -> b) -> a -> b
$ ByteString -> ByteString -> ArmorType
ArmorSplitMessage ([Word8] -> ByteString
BL.pack [Word8]
firstnum) ([Word8] -> ByteString
BL.pack [Word8]
secondnum)
partsindef :: Parser ArmorType
partsindef = ByteString -> ArmorType
ArmorSplitMessageIndefinite (ByteString -> ArmorType)
-> ([Word8] -> ByteString) -> [Word8] -> ArmorType
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Word8] -> ByteString
BL.pack ([Word8] -> ArmorType)
-> Parser ByteString [Word8] -> Parser ArmorType
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser ByteString [Word8]
num
num :: Parser ByteString [Word8]
num = Parser ByteString Word8 -> Parser ByteString [Word8]
forall (f :: * -> *) a. Alternative f => f a -> f [a]
many1 ((Word8 -> Bool) -> Parser ByteString Word8
satisfy Word8 -> Bool
isDigit_w8) Parser ByteString [Word8] -> [Char] -> Parser ByteString [Word8]
forall i a. Parser i a -> [Char] -> Parser i a
<?> [Char]
"number"
lineEnding :: Parser B.ByteString
lineEnding :: Parser ByteString
lineEnding = ByteString -> Parser ByteString
string ByteString
"\n" Parser ByteString -> Parser ByteString -> Parser ByteString
forall a.
Parser ByteString a -> Parser ByteString a -> Parser ByteString a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> ByteString -> Parser ByteString
string ByteString
"\r\n"
armorHeaders :: Parser [(String, String)]
= Parser ByteString ([Char], [Char]) -> Parser [([Char], [Char])]
forall a. Parser ByteString a -> Parser ByteString [a]
forall (f :: * -> *) a. Alternative f => f a -> f [a]
many Parser ByteString ([Char], [Char])
armorHeader
armorHeader :: Parser (String, String)
= do
[Word8]
key <- Parser ByteString Word8 -> Parser ByteString [Word8]
forall (f :: * -> *) a. Alternative f => f a -> f [a]
many1 ((Word8 -> Bool) -> Parser ByteString Word8
satisfy ([Char] -> Word8 -> Bool
inClass [Char]
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"))
ByteString
_ <- ByteString -> Parser ByteString
string ByteString
": "
[Word8]
val <- Parser ByteString Word8 -> Parser ByteString [Word8]
forall (f :: * -> *) a. Alternative f => f a -> f [a]
many1 ((Word8 -> Bool) -> Parser ByteString Word8
satisfy ([Char] -> Word8 -> Bool
notInClass [Char]
"\n\r"))
ByteString
_ <- Parser ByteString
lineEnding
([Char], [Char]) -> Parser ByteString ([Char], [Char])
forall a. a -> Parser ByteString a
forall (m :: * -> *) a. Monad m => a -> m a
return ([Word8] -> [Char]
w8sToString [Word8]
key, [Word8] -> [Char]
w8sToString [Word8]
val)
where
w8sToString :: [Word8] -> [Char]
w8sToString = ByteString -> [Char]
BC8.unpack (ByteString -> [Char])
-> ([Word8] -> ByteString) -> [Word8] -> [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Word8] -> ByteString
B.pack
blankishLine :: Parser B.ByteString
blankishLine :: Parser ByteString
blankishLine = Parser ByteString Word8 -> Parser ByteString [Word8]
forall a. Parser ByteString a -> Parser ByteString [a]
forall (f :: * -> *) a. Alternative f => f a -> f [a]
many ((Word8 -> Bool) -> Parser ByteString Word8
satisfy ([Char] -> Word8 -> Bool
inClass [Char]
" \t")) Parser ByteString [Word8] -> Parser ByteString -> Parser ByteString
forall a b.
Parser ByteString a -> Parser ByteString b -> Parser ByteString b
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Parser ByteString
lineEnding
endLine :: ArmorType -> Parser B.ByteString
endLine :: ArmorType -> Parser ByteString
endLine ArmorType
atype = do
ByteString
_ <- ByteString -> Parser ByteString
string (ByteString -> Parser ByteString)
-> ByteString -> Parser ByteString
forall a b. (a -> b) -> a -> b
$ ByteString
"-----END PGP " ByteString -> ByteString -> ByteString
`B.append` ArmorType -> ByteString
aType ArmorType
atype ByteString -> ByteString -> ByteString
`B.append` ByteString
"-----"
Parser ByteString
lineEnding
aType :: ArmorType -> B.ByteString
aType :: ArmorType -> ByteString
aType ArmorType
ArmorMessage = [Char] -> ByteString
BC8.pack [Char]
"MESSAGE"
aType ArmorType
ArmorPublicKeyBlock = [Char] -> ByteString
BC8.pack [Char]
"PUBLIC KEY BLOCK"
aType ArmorType
ArmorPrivateKeyBlock = [Char] -> ByteString
BC8.pack [Char]
"PRIVATE KEY BLOCK"
aType (ArmorSplitMessage ByteString
x ByteString
y) = [Char] -> ByteString
BC8.pack [Char]
"MESSAGE, PART " ByteString -> ByteString -> ByteString
`B.append` ByteString -> ByteString
l2s ByteString
x ByteString -> ByteString -> ByteString
`B.append` Char -> ByteString
BC8.singleton Char
'/' ByteString -> ByteString -> ByteString
`B.append` ByteString -> ByteString
l2s ByteString
y
aType (ArmorSplitMessageIndefinite ByteString
x) = [Char] -> ByteString
BC8.pack [Char]
"MESSAGE, PART " ByteString -> ByteString -> ByteString
`B.append` ByteString -> ByteString
l2s ByteString
x
aType ArmorType
ArmorSignature = [Char] -> ByteString
BC8.pack [Char]
"SIGNATURE"
l2s :: BL.ByteString -> B.ByteString
l2s :: ByteString -> ByteString
l2s = [ByteString] -> ByteString
B.concat ([ByteString] -> ByteString)
-> (ByteString -> [ByteString]) -> ByteString -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> [ByteString]
BL.toChunks
base64Data :: Parser ByteString
base64Data :: Parser ByteString
base64Data = do
[ByteString]
ls <- Parser ByteString -> Parser ByteString [ByteString]
forall (f :: * -> *) a. Alternative f => f a -> f [a]
many1 Parser ByteString
base64Line
ByteString
cksum <- Parser ByteString
checksumLine
let payload :: ByteString
payload = [ByteString] -> ByteString
B.concat [ByteString]
ls
let ourcksum :: Word32
ourcksum = ByteString -> Word32
crc24 ByteString
payload
case Get Word32
-> ByteString
-> Either
(ByteString, ByteOffset, [Char]) (ByteString, ByteOffset, Word32)
forall a.
Get a
-> ByteString
-> Either
(ByteString, ByteOffset, [Char]) (ByteString, ByteOffset, a)
runGetOrFail Get Word32
d24 (ByteString -> ByteString
BL.fromStrict ByteString
cksum) of
Left (ByteString
_,ByteOffset
_,[Char]
err) -> [Char] -> Parser ByteString
forall a. [Char] -> Parser ByteString a
forall (m :: * -> *) a. MonadFail m => [Char] -> m a
fail [Char]
err
Right (ByteString
_,ByteOffset
_,Word32
theircksum) -> if Word32
theircksum Word32 -> Word32 -> Bool
forall a. Eq a => a -> a -> Bool
== Word32
ourcksum then ByteString -> Parser ByteString
forall a. a -> Parser ByteString a
forall (m :: * -> *) a. Monad m => a -> m a
return (ByteString -> ByteString
BL.fromStrict ByteString
payload) else [Char] -> Parser ByteString
forall a. [Char] -> Parser ByteString a
forall (m :: * -> *) a. MonadFail m => [Char] -> m a
fail ([Char]
"CRC24 mismatch: " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Word8] -> [Char]
forall a. Show a => a -> [Char]
show (ByteString -> [Word8]
B.unpack ByteString
cksum) [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"/" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Word32 -> [Char]
forall a. Show a => a -> [Char]
show Word32
theircksum [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" vs. " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Word32 -> [Char]
forall a. Show a => a -> [Char]
show Word32
ourcksum)
where
base64Line :: Parser B.ByteString
base64Line :: Parser ByteString
base64Line = do
[Word8]
b64 <- Parser ByteString Word8 -> Parser ByteString [Word8]
forall (f :: * -> *) a. Alternative f => f a -> f [a]
many1 ((Word8 -> Bool) -> Parser ByteString Word8
satisfy ([Char] -> Word8 -> Bool
inClass [Char]
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"))
[Word8]
pad <- Parser ByteString Word8 -> Parser ByteString [Word8]
forall a. Parser ByteString a -> Parser ByteString [a]
forall (f :: * -> *) a. Alternative f => f a -> f [a]
many (Word8 -> Parser ByteString Word8
word8 (Int -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> Word8) -> (Char -> Int) -> Char -> Word8
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> Int
forall a. Enum a => a -> Int
fromEnum (Char -> Word8) -> Char -> Word8
forall a b. (a -> b) -> a -> b
$ Char
'='))
ByteString
_ <- Parser ByteString
lineEnding
let line :: ByteString
line = [Word8] -> ByteString
B.pack [Word8]
b64 ByteString -> ByteString -> ByteString
`B.append` [Word8] -> ByteString
B.pack [Word8]
pad
case ByteString -> Either [Char] ByteString
Base64.decode ByteString
line of
Left [Char]
err -> [Char] -> Parser ByteString
forall a. [Char] -> Parser ByteString a
forall (m :: * -> *) a. MonadFail m => [Char] -> m a
fail [Char]
err
Right ByteString
bs -> ByteString -> Parser ByteString
forall a. a -> Parser ByteString a
forall (m :: * -> *) a. Monad m => a -> m a
return ByteString
bs
checksumLine :: Parser B.ByteString
checksumLine :: Parser ByteString
checksumLine = do
Word8
_ <- Word8 -> Parser ByteString Word8
word8 (Int -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> Word8) -> (Char -> Int) -> Char -> Word8
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> Int
forall a. Enum a => a -> Int
fromEnum (Char -> Word8) -> Char -> Word8
forall a b. (a -> b) -> a -> b
$ Char
'=')
[Word8]
b64 <- Parser ByteString Word8 -> Parser ByteString [Word8]
forall (f :: * -> *) a. Alternative f => f a -> f [a]
many1 ((Word8 -> Bool) -> Parser ByteString Word8
satisfy ([Char] -> Word8 -> Bool
inClass [Char]
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"))
ByteString
_ <- Parser ByteString
lineEnding
let line :: ByteString
line = [Word8] -> ByteString
B.pack [Word8]
b64
case ByteString -> Either [Char] ByteString
Base64.decode ByteString
line of
Left [Char]
err -> [Char] -> Parser ByteString
forall a. [Char] -> Parser ByteString a
forall (m :: * -> *) a. MonadFail m => [Char] -> m a
fail [Char]
err
Right ByteString
bs -> ByteString -> Parser ByteString
forall a. a -> Parser ByteString a
forall (m :: * -> *) a. Monad m => a -> m a
return ByteString
bs
d24 :: Get Word32
d24 :: Get Word32
d24 = do
Word8
a <- Get Word8
getWord8
Word8
b <- Get Word8
getWord8
Word8
c <- Get Word8
getWord8
Word32 -> Get Word32
forall a. a -> Get a
forall (m :: * -> *) a. Monad m => a -> m a
return (Word32 -> Get Word32) -> Word32 -> Get Word32
forall a b. (a -> b) -> a -> b
$ Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
shiftL (Word8 -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
a :: Word32) Int
16 Word32 -> Word32 -> Word32
forall a. Num a => a -> a -> a
+ Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
shiftL (Word8 -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
b :: Word32) Int
8 Word32 -> Word32 -> Word32
forall a. Num a => a -> a -> a
+ (Word8 -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
c :: Word32)
prefixed :: Parser a -> Parser a
prefixed :: forall a. Parser a -> Parser a
prefixed Parser a
end = Parser a
end Parser a -> Parser a -> Parser a
forall a.
Parser ByteString a -> Parser ByteString a -> Parser ByteString a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser Char
anyChar Parser Char -> Parser a -> Parser a
forall a b.
Parser ByteString a -> Parser ByteString b -> Parser ByteString b
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Parser a -> Parser a
forall a. Parser a -> Parser a
prefixed Parser a
end
dashEscapedCleartext :: Parser ByteString
dashEscapedCleartext :: Parser ByteString
dashEscapedCleartext = do
[ByteString]
ls <- Parser ByteString -> Parser ByteString [ByteString]
forall (f :: * -> *) a. Alternative f => f a -> f [a]
many1 ((Parser ByteString
deLine Parser ByteString -> Parser ByteString -> Parser ByteString
forall a.
Parser ByteString a -> Parser ByteString a -> Parser ByteString a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser ByteString
unescapedLine) Parser ByteString -> Parser ByteString -> Parser ByteString
forall a b.
Parser ByteString a -> Parser ByteString b -> Parser ByteString a
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Parser ByteString
lineEnding)
ByteString -> Parser ByteString
forall a. a -> Parser ByteString a
forall (m :: * -> *) a. Monad m => a -> m a
return (ByteString -> Parser ByteString)
-> (ByteString -> ByteString) -> ByteString -> Parser ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> ByteString
BL.fromStrict (ByteString -> Parser ByteString)
-> ByteString -> Parser ByteString
forall a b. (a -> b) -> a -> b
$ [ByteString] -> ByteString
crlfUnlines [ByteString]
ls
where
deLine :: Parser B.ByteString
deLine :: Parser ByteString
deLine = [Word8] -> ByteString
B.pack ([Word8] -> ByteString)
-> Parser ByteString [Word8] -> Parser ByteString
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (ByteString -> Parser ByteString
string ByteString
"- " Parser ByteString
-> Parser ByteString [Word8] -> Parser ByteString [Word8]
forall a b.
Parser ByteString a -> Parser ByteString b -> Parser ByteString b
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Parser ByteString Word8 -> Parser ByteString [Word8]
forall a. Parser ByteString a -> Parser ByteString [a]
forall (f :: * -> *) a. Alternative f => f a -> f [a]
many ((Word8 -> Bool) -> Parser ByteString Word8
satisfy ([Char] -> Word8 -> Bool
notInClass [Char]
"\n\r")))
unescapedLine :: Parser B.ByteString
unescapedLine :: Parser ByteString
unescapedLine = ByteString
-> ([Word8] -> ByteString) -> Maybe [Word8] -> ByteString
forall b a. b -> (a -> b) -> Maybe a -> b
maybe ByteString
B.empty [Word8] -> ByteString
B.pack (Maybe [Word8] -> ByteString)
-> Parser ByteString (Maybe [Word8]) -> Parser ByteString
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser ByteString [Word8] -> Parser ByteString (Maybe [Word8])
forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
optional ((:) (Word8 -> [Word8] -> [Word8])
-> Parser ByteString Word8
-> Parser ByteString ([Word8] -> [Word8])
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Word8 -> Bool) -> Parser ByteString Word8
satisfy ([Char] -> Word8 -> Bool
notInClass [Char]
"-\n\r") Parser ByteString ([Word8] -> [Word8])
-> Parser ByteString [Word8] -> Parser ByteString [Word8]
forall a b.
Parser ByteString (a -> b)
-> Parser ByteString a -> Parser ByteString b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser ByteString Word8 -> Parser ByteString [Word8]
forall a. Parser ByteString a -> Parser ByteString [a]
forall (f :: * -> *) a. Alternative f => f a -> f [a]
many ((Word8 -> Bool) -> Parser ByteString Word8
satisfy ([Char] -> Word8 -> Bool
notInClass [Char]
"\n\r")))