pem (empty) → 0.1.0
raw patch · 8 files changed
+224/−0 lines, 8 filesdep +QuickCheckdep +attoparsecdep +basesetup-changed
Dependencies added: QuickCheck, attoparsec, base, base64-bytestring, bytestring, cereal, mtl, pem, test-framework, test-framework-quickcheck2
Files
- Data/PEM.hs +18/−0
- Data/PEM/Parser.hs +59/−0
- Data/PEM/Types.hs +20/−0
- Data/PEM/Writer.hs +50/−0
- LICENSE +27/−0
- README.md +4/−0
- Setup.hs +2/−0
- pem.cabal +44/−0
+ Data/PEM.hs view
@@ -0,0 +1,18 @@+-- |+-- Module : Data.PEM+-- License : BSD-style+-- Maintainer : Vincent Hanquez <vincent@snarc.org>+-- Stability : experimental+-- Portability : portable+--+-- Read and write PEM files+--+module Data.PEM+ ( module Data.PEM.Types+ , module Data.PEM.Writer+ , module Data.PEM.Parser+ ) where++import Data.PEM.Types+import Data.PEM.Writer+import Data.PEM.Parser
+ Data/PEM/Parser.hs view
@@ -0,0 +1,59 @@+{-# LANGUAGE OverloadedStrings #-}+-- |+-- Module : Data.PEM.Parser+-- License : BSD-style+-- Maintainer : Vincent Hanquez <vincent@snarc.org>+-- Stability : experimental+-- Portability : portable+--+-- Parse PEM content.+--+-- A PEM contains contains from one to many PEM sections.+-- Each section contains an optional key-value pair header+-- and a binary content encoded in base64.+-- +module Data.PEM.Parser+ ( pemParser+ , pemParseBS+ , pemParseLBS+ ) where++import Control.Applicative+import Data.Attoparsec+import qualified Data.Attoparsec.Lazy as AttoLazy+import Data.Attoparsec.Char8 (space)++import Data.PEM.Types++import Data.ByteString (ByteString)+import qualified Data.ByteString.Char8 as BC+import qualified Data.ByteString.Lazy as L+import qualified Data.ByteString.Base64 as Base64++import Prelude hiding (takeWhile)+import Data.Serialize.Builder+import Data.Monoid++-- | parser to get PEM sections+pemParser :: Parser [PEM]+pemParser = many contextSection+ where+ beginMarker = string "-----BEGIN " >> return ()+ endMarker = string "-----END " >> return ()+ skipLine = skipWhile (/= 0xa) >> space >> return ()+ eatLine = takeWhile (/= 0xa) <* space+ contextSection = manyTill skipLine beginMarker *> section+ section = do+ -- begin marker has already been eaten by contextSection+ name <- takeWhile (/= 0x2d) <* (string "-----" *> space)+ l <- manyTill eatLine endMarker+ let content = toByteString $ mconcat $ map (fromByteString . Base64.decodeLenient) l+ return $ PEM { pemName = BC.unpack name, pemHeader = [], pemContent = content }++-- | parse a PEM content using a strict bytestring+pemParseBS :: ByteString -> Either String [PEM]+pemParseBS = parseOnly pemParser++-- | parse a PEM content using a dynamic bytestring+pemParseLBS :: L.ByteString -> Either String [PEM]+pemParseLBS = AttoLazy.eitherResult . AttoLazy.parse pemParser
+ Data/PEM/Types.hs view
@@ -0,0 +1,20 @@+-- |+-- Module : Data.PEM.Types+-- License : BSD-style+-- Maintainer : Vincent Hanquez <vincent@snarc.org>+-- Stability : experimental+-- Portability : portable+--+module Data.PEM.Types where++import Data.ByteString (ByteString)++-- | Represent one PEM section+--+-- for now headers are not serialized at all.+-- this is just available here as a placeholder for a later implementation.+data PEM = PEM+ { pemName :: String -- ^ the name of the section, found after the dash BEGIN tag.+ , pemHeader :: [(String, ByteString)] -- ^ optionals key value pair header+ , pemContent :: ByteString -- ^ binary content of the section+ } deriving (Show,Eq)
+ Data/PEM/Writer.hs view
@@ -0,0 +1,50 @@+{-# LANGUAGE OverloadedStrings #-}+-- |+-- Module : Data.PEM.Writer+-- License : BSD-style+-- Maintainer : Vincent Hanquez <vincent@snarc.org>+-- Stability : experimental+-- Portability : portable+--+module Data.PEM.Writer+ ( pemWriteBuilder+ , pemWriteLBS+ , pemWriteBS+ ) where++import Data.PEM.Types+import Data.ByteString (ByteString)+import qualified Data.ByteString as B+import qualified Data.ByteString.Char8 as BC+import qualified Data.ByteString.Lazy as L+import qualified Data.ByteString.Base64 as Base64+import Data.Serialize.Builder+import Data.Monoid+import Data.List++-- | write a PEM structure to a builder+pemWriteBuilder :: PEM -> Builder+pemWriteBuilder pem = mconcat $ intersperse eol $ concat ([begin]:header:section:[end]:[[empty]])+ where begin = mconcat $ map fromByteString ["-----BEGIN ", sectionName, "-----" ]+ end = mconcat $ map fromByteString ["-----END ", sectionName, "-----" ]+ section = map fromByteString $ (splitChunks $ Base64.encode $ pemContent pem)+ header = if null $ pemHeader pem+ then []+ else concatMap toHeader (pemHeader pem) ++ [empty]+ toHeader (k,v) = [ mconcat $ map fromByteString [ bk, ":", v ] ]+ where bk = BC.pack k+ -- expect only ASCII. need to find a type to represent it.+ sectionName = BC.pack $ pemName pem++ splitChunks b+ | B.length b > 64 = let (x,y) = B.splitAt 64 b in x : splitChunks y+ | otherwise = [b]+ eol = fromByteString $ B.singleton 0x0a++-- | convert a PEM structure to a bytestring+pemWriteBS :: PEM -> ByteString+pemWriteBS = toByteString . pemWriteBuilder++-- | convert a PEM structure to a lazy bytestring+pemWriteLBS :: PEM -> L.ByteString+pemWriteLBS = toLazyByteString . pemWriteBuilder
+ LICENSE view
@@ -0,0 +1,27 @@+Copyright (c) 2010-2012 Vincent Hanquez <vincent@snarc.org>++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions+are met:+1. Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.+2. Redistributions in binary form must reproduce the above copyright+ notice, this list of conditions and the following disclaimer in the+ documentation and/or other materials provided with the distribution.+3. Neither the name of the author nor the names of his contributors+ may be used to endorse or promote products derived from this software+ without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE+ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF+SUCH DAMAGE.
+ README.md view
@@ -0,0 +1,4 @@+PEM haskell library+===================++Handle Privacy Enhanced Message (PEM) format.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ pem.cabal view
@@ -0,0 +1,44 @@+Name: pem+Version: 0.1.0+Description: Privacy Enhanced Mail (PEM) format reader and writer.+License: BSD3+License-file: LICENSE+Copyright: Vincent Hanquez <vincent@snarc.org>+Author: Vincent Hanquez <vincent@snarc.org>+Maintainer: Vincent Hanquez <vincent@snarc.org>+Synopsis: Privacy Enhanced Mail (PEM) format reader and writer.+Build-Type: Simple+Category: Data+stability: experimental+Cabal-Version: >=1.8+Homepage: http://github.com/vincenthz/hs-pem+data-files: README.md++Library+ Build-Depends: base >= 3 && < 5+ , mtl+ , bytestring+ , attoparsec+ , cereal+ , base64-bytestring+ Exposed-modules: Data.PEM+ Other-modules: Data.PEM.Parser+ Data.PEM.Writer+ Data.PEM.Types+ ghc-options: -Wall++Test-Suite test-pem+ type: exitcode-stdio-1.0+ hs-source-dirs: Tests+ main-is: pem.hs+ build-depends: base+ , bytestring+ , test-framework >= 0.3.3 && < 0.6+ , test-framework-quickcheck2 >= 0.2.9 && < 0.3+ , QuickCheck >= 2.4.0.1+ , pem++source-repository head+ type: git+ location: git://github.com/vincenthz/hs-pem+