packages feed

h-gpgme-0.1.0.0: src/Crypto/Gpgme/Internal.hs

module Crypto.Gpgme.Internal where

import Bindings.Gpgme
import Control.Monad (unless)
import qualified Data.ByteString as BS
import Foreign (allocaBytes, castPtr, peek)
import Foreign.C.String (peekCString)
import System.IO.Unsafe (unsafePerformIO)

import Crypto.Gpgme.Types

collectFprs :: C'gpgme_invalid_key_t -> [InvalidKey]
collectFprs result = unsafePerformIO $ peek result >>= go
    where go :: C'_gpgme_invalid_key -> IO [InvalidKey]
          go invalid = do
            fpr <- peekCString (c'_gpgme_invalid_key'fpr invalid)
            let reason = fromIntegral (c'_gpgme_invalid_key'reason invalid)
            rest <- go (c'_gpgme_invalid_key'next invalid)
            return ((fpr, reason) : rest)

collectResult :: C'gpgme_data_t -> BS.ByteString
collectResult dat' = unsafePerformIO $ do
    -- make sure we start at the beginning
    _ <- c'gpgme_data_seek dat' 0 seekSet
    go dat'
  where go :: C'gpgme_data_t -> IO BS.ByteString
        go dat = allocaBytes 1 $ \buf -> 
                    do read_bytes <- c'gpgme_data_read dat buf 1
                       if read_bytes == 1
                          then do byte <- peek (castPtr buf)
                                  rest <- go dat
                                  return (byte `BS.cons` rest)
                          else return BS.empty
        seekSet = 0

check_error :: String -> C'gpgme_error_t -> IO ()
check_error fun gpgme_err =
    unless (gpgme_err == noError) $
           do errstr <- c'gpgme_strerror gpgme_err
              str <- peekCString errstr
              srcstr <- c'gpgme_strsource gpgme_err
              src <- peekCString srcstr
              error ("Fun: " ++ fun ++
                     ", Error: " ++ str ++ 
                     ", Source: " ++ show src)

noError :: Num a => a
noError = 0