{-# LANGUAGE CPP #-}
{-# LANGUAGE OverloadedStrings #-}
module Data.PEM.Writer
( pemWriteBS
, pemWriteLBS
) where
#if MIN_VERSION_base64(1,0,0)
import Data.Base64.Types ( extractBase64 )
#endif
import Data.ByteString ( ByteString )
import qualified Data.ByteString as B
import Data.ByteString.Base64 ( encodeBase64' )
import qualified Data.ByteString.Char8 as BC
import qualified Data.ByteString.Lazy as L
import Data.PEM.Types ( PEM (..) )
encodeBase64 :: ByteString -> ByteString
#if MIN_VERSION_base64(1,0,0)
encodeBase64 :: ByteString -> ByteString
encodeBase64 = Base64 'StdPadded ByteString -> ByteString
forall (k :: Alphabet) a. Base64 k a -> a
extractBase64 (Base64 'StdPadded ByteString -> ByteString)
-> (ByteString -> Base64 'StdPadded ByteString)
-> ByteString
-> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Base64 'StdPadded ByteString
encodeBase64'
#else
encodeBase64 = encodeBase64'
#endif
pemWrite :: PEM -> L.ByteString
pemWrite :: PEM -> ByteString
pemWrite PEM
pem = [ByteString] -> ByteString
L.fromChunks ([ByteString
begin, ByteString
header] [ByteString] -> [ByteString] -> [ByteString]
forall a. [a] -> [a] -> [a]
++ [ByteString]
section [ByteString] -> [ByteString] -> [ByteString]
forall a. [a] -> [a] -> [a]
++ [ByteString
end])
where
begin :: ByteString
begin = [ByteString] -> ByteString
B.concat [ByteString
"-----BEGIN ", ByteString
sectionName, ByteString
"-----\n"]
end :: ByteString
end = [ByteString] -> ByteString
B.concat [ByteString
"-----END ", ByteString
sectionName, ByteString
"-----\n" ]
section :: [ByteString]
section :: [ByteString]
section = (ByteString -> ByteString) -> [ByteString] -> [ByteString]
forall a b. (a -> b) -> [a] -> [b]
map ByteString -> ByteString
encodeLine ([ByteString] -> [ByteString]) -> [ByteString] -> [ByteString]
forall a b. (a -> b) -> a -> b
$ ByteString -> [ByteString]
splitChunks (ByteString -> [ByteString]) -> ByteString -> [ByteString]
forall a b. (a -> b) -> a -> b
$ PEM -> ByteString
pemContent PEM
pem
header :: ByteString
header :: ByteString
header = if [(String, ByteString)] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null ([(String, ByteString)] -> Bool) -> [(String, ByteString)] -> Bool
forall a b. (a -> b) -> a -> b
$ PEM -> [(String, ByteString)]
pemHeader PEM
pem
then ByteString
B.empty
else [ByteString] -> ByteString
B.concat (((String, ByteString) -> [ByteString])
-> [(String, ByteString)] -> [ByteString]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (String, ByteString) -> [ByteString]
toHeader (PEM -> [(String, ByteString)]
pemHeader PEM
pem) [ByteString] -> [ByteString] -> [ByteString]
forall a. [a] -> [a] -> [a]
++ [ByteString
"\n"])
toHeader :: (String, ByteString) -> [ByteString]
toHeader :: (String, ByteString) -> [ByteString]
toHeader (String
k,ByteString
v) = [ String -> ByteString
BC.pack String
k, ByteString
":", ByteString
v, ByteString
"\n" ]
sectionName :: ByteString
sectionName = String -> ByteString
BC.pack (String -> ByteString) -> String -> ByteString
forall a b. (a -> b) -> a -> b
$ PEM -> String
pemName PEM
pem
encodeLine :: ByteString -> ByteString
encodeLine ByteString
l = ByteString -> ByteString
encodeBase64 ByteString
l ByteString -> ByteString -> ByteString
`B.append` ByteString
"\n"
splitChunks :: ByteString -> [ByteString]
splitChunks ByteString
b
| ByteString -> Int
B.length ByteString
b Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
48 = let (ByteString
x,ByteString
y) = Int -> ByteString -> (ByteString, ByteString)
B.splitAt Int
48 ByteString
b in ByteString
x ByteString -> [ByteString] -> [ByteString]
forall a. a -> [a] -> [a]
: ByteString -> [ByteString]
splitChunks ByteString
y
| Bool
otherwise = [ByteString
b]
pemWriteBS :: PEM -> ByteString
pemWriteBS :: PEM -> ByteString
pemWriteBS = [ByteString] -> ByteString
B.concat ([ByteString] -> ByteString)
-> (PEM -> [ByteString]) -> PEM -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> [ByteString]
L.toChunks (ByteString -> [ByteString])
-> (PEM -> ByteString) -> PEM -> [ByteString]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PEM -> ByteString
pemWrite
pemWriteLBS :: PEM -> L.ByteString
pemWriteLBS :: PEM -> ByteString
pemWriteLBS = PEM -> ByteString
pemWrite