summaryrefslogtreecommitdiff
path: root/lib/PEM.hs
blob: 003f4fff5290e9f7d795eb8b5fb78c512a78c3d6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE CPP #-}
module PEM where

import Data.Monoid
import qualified Data.ByteString.Lazy as LW
import qualified Data.ByteString.Lazy.Char8 as L
import Control.Monad
import Control.Applicative
#if defined(VERSION_memory)
import qualified Data.ByteString.Char8 as S8
import Data.ByteArray.Encoding
#elif defined(VERSION_dataenc)
import qualified Codec.Binary.Base64 as Base64
#endif
import ScanningParser
import FunctorToMaybe
data PEMBlob = PEMBlob { pemType :: L.ByteString
                       , pemBlob :: L.ByteString
                       }
 deriving (Eq,Show)

pemParser :: Maybe L.ByteString
             -> ScanningParser L.ByteString PEMBlob
pemParser mtyp = ScanningParser (maybe fndany fndtyp mtyp) pbdy
 where
    hdr typ = "-----BEGIN " <> typ <> "-----"
    fndtyp typ bs = if bs==hdr typ then Just typ else Nothing
    fndany bs = do
        guard $ "-----BEGIN " `L.isPrefixOf` bs
        let x0 = L.drop 11 bs
        guard $ "-----" `LW.isSuffixOf` x0
        let typ = L.take (L.length x0 - 5) x0
        return typ

    pbdy typ xs = (mblob, drop 1 rs)
     where
        (ys,rs) = span (/="-----END " <> typ <> "-----") xs
#if defined(VERSION_memory)
        mblob = PEMBlob typ <$> LW.fromStrict <$> (functorToMaybe $ convertFromBase Base64 $ L.toStrict dta)
#elif defined(VERSION_dataenc)
        mblob = PEMBlob typ <$> LW.pack <$> Base64.decode (L.unpack dta)
#endif
        dta = case ys of
                []        -> ""
                dta_lines -> L.concat dta_lines