diff --git a/pdfinfo.cabal b/pdfinfo.cabal
--- a/pdfinfo.cabal
+++ b/pdfinfo.cabal
@@ -1,21 +1,30 @@
 name:                pdfinfo
-version:             0.1.3.3
+version:             1.5.4
 synopsis:            Wrapper around the pdfinfo command.
-description:         Just a wrapper around the pdfinfo command. See man pdfinfo.
+description:         Just a wrapper around the pdfinfo command (for collecting PDF file info). See man pdfinfo.
 license:             BSD3
 license-file:        LICENSE
 author:              Chris Done
 maintainer:          chrisdone@gmail.com
-copyright:           2010 Chris Done
+copyright:           2013 Chris Done
 category:            Text
 build-type:          Simple
-cabal-version:       >=1.2
+cabal-version:       >=1.8
+homepage:            https://github.com/chrisdone/pdfinfo
+
+source-repository head
+  type:              git
+  location:          git@github.com:chrisdone/pdfinfo.git
+
 library
-  ghc-options:        -O2 -Wall
+  ghc-options:       -O2 -Wall
   exposed-modules:   Text.PDF.Info
   hs-source-dirs:    src/
   build-depends:     base >= 4 && < 5,
-                     old-locale >= 1.0.0.0 && < 1.1,
-                     time >= 1.1 && < 1.5,
-                     process >= 1.0 && < 1.2,
-                     mtl >= 1.1 && < 2.2
+                     old-locale,
+                     time >= 1.1,
+                     time-locale-compat,
+                     process-extras,
+                     text,
+                     -- mtl-2.1 contains a severe bug
+                     mtl >= 1.1 && < 2.1 || >= 2.1.1
diff --git a/src/Text/PDF/Info.hs b/src/Text/PDF/Info.hs
--- a/src/Text/PDF/Info.hs
+++ b/src/Text/PDF/Info.hs
@@ -1,11 +1,15 @@
-{-# LANGUAGE GeneralizedNewtypeDeriving, MultiParamTypeClasses, ViewPatterns #-}
 {-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE ViewPatterns #-}
+{-# LANGUAGE OverloadedStrings #-}
 {-# OPTIONS -Wall #-}
+
 module Text.PDF.Info
     (-- * Reading PDF info
      pdfInfo
     ,PDFInfo(..)
     ,PDFSize(..)
+    ,PDFEncryptionInfo(..)
     ,PDFInfoError(..)
     -- * Internals
     ,ParsePDFInfo
@@ -13,49 +17,69 @@
     ,parse
     ,parseSize
     ,parseDate
+    ,parseEncrypted
     ,readRight)
     where
 
-import Prelude
-import Control.Monad.Error
-import System.Process
-import Control.Applicative
-import Control.Arrow
-import Data.Char
-import Data.Time
-import System.Locale
-import Control.Exception as E
+import           Control.Applicative
+import           Control.Arrow
+import           Control.Exception as E
+import           Control.Monad.Error
 
+import           Data.Char (isSpace)
+import           Data.Text (Text)
+import qualified Data.Text as T
+import           Data.Time (UTCTime,parseTime)
+import           Data.Time.Locale.Compat (defaultTimeLocale)
+import           Prelude
+import           System.Exit
+import           System.Process.Text
+
 -- | A type representing the output from the pdfinfo command.
 data PDFInfo = PDFInfo {
-    pdfInfoTitle        :: Maybe String  -- ^ Title
-  , pdfInfoSubject      :: Maybe String  -- ^ Subject
-  , pdfInfoAuthor       :: Maybe String  -- ^ Author: E.g. Chris Done
-  , pdfInfoCreator      :: Maybe String  -- ^ Creator: E.g. Microsoft Office Word 2007
-  , pdfInfoProducer     :: Maybe String  -- ^ Producer: E.g. Microsoft Office Word 2007
-  , pdfInfoCreationDate :: Maybe UTCTime -- ^ Creation Date
-  , pdfInfoModDate      :: Maybe UTCTime -- ^ Modification Date
-  , pdfInfoTagged       :: Maybe Bool    -- ^ Tagged?
-  , pdfInfoPages        :: Maybe Integer -- ^ Pages: E.g. 238
-  , pdfInfoEncrypted    :: Maybe Bool    -- ^ Encrypted?
-  , pdfInfoPageSize     :: Maybe PDFSize -- ^ Page: E.g. 595.32 x 841.92 pts (A4)
-  , pdfInfoFileSize     :: Maybe Integer -- ^ File: E.g. 4061737 bytes
-  , pdfInfoOptimized    :: Maybe Bool    -- ^ Optimized?
-  , pdfInfoPDFVersion   :: Maybe Double  -- ^ PDF: E.g. 1.5
+    pdfInfoTitle        :: !(Maybe Text)    -- ^ Title
+  , pdfInfoSubject      :: !(Maybe Text)    -- ^ Subject
+  , pdfInfoAuthor       :: !(Maybe Text)    -- ^ Author: E.g. Chris Done
+  , pdfInfoCreator      :: !(Maybe Text)    -- ^ Creator: E.g. Microsoft Office Word 2007
+  , pdfInfoProducer     :: !(Maybe Text)    -- ^ Producer: E.g. Microsoft Office Word 2007
+  , pdfInfoCreationDate :: !(Maybe UTCTime) -- ^ Creation Date
+  , pdfInfoModDate      :: !(Maybe UTCTime) -- ^ Modification Date
+  , pdfInfoTagged       :: !(Maybe Bool)    -- ^ Tagged?
+  , pdfInfoPages        :: !(Maybe Integer) -- ^ Pages: E.g. 238
+  , pdfInfoEncrypted    :: !(Maybe PDFEncryptionInfo) -- ^ Encryption information
+  , pdfInfoPageSize     :: !(Maybe PDFSize) -- ^ Page: E.g. 595.32 x 841.92 pts (A4)
+  , pdfInfoFileSize     :: !(Maybe Integer) -- ^ File: E.g. 4061737 bytes
+  , pdfInfoOptimized    :: !(Maybe Bool)    -- ^ Optimized?
+  , pdfInfoPDFVersion   :: !(Maybe Double)  -- ^ PDF: E.g. 1.5
   } deriving Show
 
 -- | Possible things that can go wrong while reading the info.
-data PDFInfoError =
-    ParseError String        -- ^ Couldn't parse a property value.
-  | ProcessError IOException -- ^ Error to do with the pdfinfo process.
-  | NoMessage                -- ^ No message given.
-  | SomeError String         -- ^ Some nonspecific error.
+data PDFInfoError
+  = ParseError !String        -- ^ Couldn't parse a property value.
+  | ProcessFailure !Text      -- ^ Process exited with this stderr.
+  | ProcessError !IOException -- ^ Error to do with the pdfinfo process.
+  | NoMessage                 -- ^ No message given.
+  | SomeError String          -- ^ Some nonspecific error.
   deriving Show
 
 -- | Size of the PDF in pts.
-data PDFSize = PDFSize { pdfSizeW :: Float, pdfSizeH :: Float }
+data PDFSize = PDFSize { pdfSizeW :: !Float, pdfSizeH :: !Float }
   deriving (Eq,Show)
 
+-- | Encryption and restricted permissions
+data PDFEncryptionInfo
+  -- | Not encrypted
+  = PDFNoEncryption
+  -- | Encrypted with possible permission restrictions
+  | PDFEncryption {
+      pdfCanPrint            :: !(Maybe Bool) -- ^ Can the file be printed?
+    , pdfCanCopy             :: !(Maybe Bool) -- ^ Can the file be copied?
+    , pdfCanChange           :: !(Maybe Bool) -- ^ Can the file be changed?
+    , pdfCanAddNotes         :: !(Maybe Bool) -- ^ Can notes be added?
+    , pdfEncryptionAlgorithm :: !(Maybe Text) -- ^ Encryption algorithm: e.g. unknown, RC4, AES, AES-256
+    }
+  deriving (Eq,Show)
+
 instance Error PDFInfoError where noMsg = NoMessage; strMsg = SomeError
 newtype ParsePDFInfo a = ParsePDFInfo { runParse :: Either PDFInfoError a }
   deriving (Monad,Functor,MonadError PDFInfoError)
@@ -65,68 +89,92 @@
 -- running the process.
 pdfInfo :: MonadIO m => FilePath -> m (Either PDFInfoError PDFInfo)
 pdfInfo path = liftIO $ loadInfo `E.catch` ioErrorHandler where
-  loadInfo = parse <$> readProcess "pdfinfo" [path] ""
+  loadInfo = do (code,out,err) <- readProcessWithExitCode "pdfinfo" ["-enc","UTF-8",path] ""
+                case code of
+                  ExitSuccess -> return (parse out)
+                  ExitFailure{} -> return (Left (ProcessFailure err))
   ioErrorHandler = return . Left . ProcessError
 
 -- | Parse PDFInfo's output.
-parse :: String -> Either PDFInfoError PDFInfo
+parse :: Text -> Either PDFInfoError PDFInfo
 parse out = runParse $
-  PDFInfo <$> string "Title"
-          <*> string "Subject"
-          <*> string "Author"
-          <*> string "Creator"
-          <*> string "Producer"
+  PDFInfo <$> string props "Title"
+          <*> string props "Subject"
+          <*> string props "Author"
+          <*> string props "Creator"
+          <*> string props "Producer"
           <*> date "CreationDate"
           <*> date "ModDate"
-          <*> bool "Tagged"
+          <*> bool props "Tagged"
           <*> integer "Pages"
-          <*> bool "Encrypted"
+          <*> encrypted "Encrypted"
           <*> size "Page size"
           <*> integer "File size"
-          <*> bool "Optimized"
+          <*> bool props "Optimized"
           <*> floating "PDF version"
-
-    where string = get id
-          date = get (>>= parseDate)
-          size = get (>>= parseSize)
-          bool = get $ fmap $ \yes -> yes == "yes"
+    where date = get parseDate
+          size = get parseSize
+          encrypted = get parseEncrypted
           floating = readIt
           integer = readIt
-          readIt :: Read a => String -> ParsePDFInfo (Maybe a)
-          readIt = get (>>= readRight)
+          readIt :: Read a => Text -> ParsePDFInfo (Maybe a)
+          readIt = get readRight
+          props = map split . T.lines $ out
+          get = withProps props
 
-          properties = map split . lines $ out
-          get f name =
-            case lookup name properties of
-              Just ok -> catchError (Just <$> (f $ return $ trim ok))
-                                    (\_ -> return Nothing)
-              Nothing -> return Nothing
+type Props = [(Text,Text)]
 
-          split = second (drop 2) . span (/=':')
-          trim = bi reverse (dropWhile isSpace) . dropWhile isSpace
+-- | Look up a name in a finite map of "properties" and apply a (parsing)
+-- function.
+withProps :: Props -> (Text -> ParsePDFInfo a) -> Text -> ParsePDFInfo (Maybe a)
+withProps properties f name =
+  case lookup name properties of
+    Just ok -> catchError (Just <$> (f $ T.strip ok))
+                          (\_ -> return Nothing)
+    Nothing -> return Nothing
 
+split :: Text -> (Text, Text)
+split = second (T.drop 1) . T.span (/=':')
+
+string :: Props -> Text -> ParsePDFInfo (Maybe Text)
+string props = withProps props return
+
+bool :: Props -> Text -> ParsePDFInfo (Maybe Bool)
+bool props = withProps props $ \yes -> return $ yes == "yes"
+
 -- | Parse a page size. This is loosely defined.
-parseSize :: String -> ParsePDFInfo PDFSize
+parseSize :: Text -> ParsePDFInfo PDFSize
 parseSize s =
-  case words s of
+  case T.words s of
     ((readRight -> Right x):"x":(readRight -> Right y):_) ->
         return $ PDFSize x y
     _ -> throwError $ ParseError $ "Unable to read size: " ++ show s
 
 -- | Parse a date according to pdfinfo's format.
-parseDate :: String -> ParsePDFInfo UTCTime
+parseDate :: Text -> ParsePDFInfo UTCTime
 parseDate s =
-  case parseTime defaultTimeLocale "%a %b %e %H:%M:%S %Y" s of
+  case parseTime defaultTimeLocale "%a %b %e %H:%M:%S %Y" (T.unpack s) of
     Just ok -> return ok
     Nothing -> throwError $ ParseError $ "Unable to parse date: " ++ show s
 
+-- | Parse encryption information according to pdfinfo's format.
+parseEncrypted :: Text -> ParsePDFInfo PDFEncryptionInfo
+parseEncrypted s =
+  case T.break isSpace s of
+    ("yes",rest) ->
+      PDFEncryption <$> bool props "print"
+                    <*> bool props "copy"
+                    <*> bool props "change"
+                    <*> bool props "addNotes"
+                    <*> string props "algorithm"
+      where
+        props = map split $ T.words $ T.filter (flip notElem ['(',')']) rest
+    ("no",_) -> return PDFNoEncryption
+    _ -> throwError $ ParseError $ "Unable to parse encryption: " ++ show s
+
 -- | Read a value, maybe, allow misc trailing data.
-readRight :: (MonadError PDFInfoError m,Read a) => String -> m a
+readRight :: (MonadError PDFInfoError m,Read a) => Text -> m a
 readRight s =
-  case reads s of
+  case reads (T.unpack s) of
     [(v,_)] -> return v
     _ -> throwError $ ParseError $ "Couldn't read value: " ++ show s
-
--- | Untwist a value, apply a function, twist it back.
-bi :: (c1 -> c) -> (c -> c1) -> c1 -> c
-bi g f = g . f . g
