{-# LANGUAGE OverloadedStrings #-}
module Network.DomainAuth.Mail.Mail (
lookupField
, fieldsFrom
, fieldsAfter
, fieldsWith
, fieldValueFolded
, fieldValueUnfolded
, fromBody
, fromBodyWith
, removeTrailingEmptyLine
) where
import Data.ByteString (ByteString)
import Data.ByteString.Builder (Builder)
import qualified Data.ByteString.Builder as BB
import qualified Data.ByteString.Char8 as BS8
import qualified Data.ByteString.Lazy as BL
import qualified Data.Foldable as F (foldr)
import Data.List
import Data.Maybe (catMaybes)
import Data.Sequence (Seq, viewr, ViewR(..), empty)
import Network.DomainAuth.Mail.Types
import qualified Network.DomainAuth.Utils as B (empty)
import Network.DomainAuth.Utils hiding (empty)
lookupField :: FieldKey -> Header -> Maybe Field
lookupField :: ByteString -> Header -> Maybe Field
lookupField ByteString
key Header
hdr = forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Maybe a
find (ByteString
ckey ByteString -> Field -> Bool
`isKeyOf`) Header
hdr
where
ckey :: ByteString
ckey = ByteString -> ByteString
canonicalizeKey ByteString
key
fieldsFrom :: FieldKey -> Header -> Header
fieldsFrom :: ByteString -> Header -> Header
fieldsFrom ByteString
key = forall a. (a -> Bool) -> [a] -> [a]
dropWhile (ByteString
ckey ByteString -> Field -> Bool
`isNotKeyOf`)
where
ckey :: ByteString
ckey = ByteString -> ByteString
canonicalizeKey ByteString
key
fieldsAfter :: FieldKey -> Header -> Header
fieldsAfter :: ByteString -> Header -> Header
fieldsAfter ByteString
key = forall {a}. [a] -> [a]
safeTail forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Header -> Header
fieldsFrom ByteString
key
where
safeTail :: [a] -> [a]
safeTail [] = []
safeTail [a]
xs = forall {a}. [a] -> [a]
tail [a]
xs
fieldsWith :: [CanonFieldKey] -> Header -> Header
fieldsWith :: [ByteString] -> Header -> Header
fieldsWith [ByteString]
kx Header
hx = forall a. [Maybe a] -> [a]
catMaybes forall a b. (a -> b) -> a -> b
$ forall a b. [a] -> [b] -> (a -> b -> Bool) -> [Maybe b]
enm [ByteString]
kx Header
hx (\ByteString
k Field
h -> ByteString
k forall a. Eq a => a -> a -> Bool
== Field -> ByteString
fieldSearchKey Field
h)
enm :: [a] -> [b] -> (a -> b -> Bool) -> [Maybe b]
enm :: forall a b. [a] -> [b] -> (a -> b -> Bool) -> [Maybe b]
enm [] [b]
_ a -> b -> Bool
_ = []
enm [a]
_ [] a -> b -> Bool
_ = []
enm (a
k:[a]
kx) [b]
hs0 a -> b -> Bool
eq = case forall a. (a -> Bool) -> [a] -> Maybe (a, [a])
fnd (a -> b -> Bool
eq a
k) [b]
hs0 of
Maybe (b, [b])
Nothing -> forall a. Maybe a
Nothing forall a. a -> [a] -> [a]
: forall a b. [a] -> [b] -> (a -> b -> Bool) -> [Maybe b]
enm [a]
kx [b]
hs0 a -> b -> Bool
eq
Just (b
x,[b]
hs) -> forall a. a -> Maybe a
Just b
x forall a. a -> [a] -> [a]
: forall a b. [a] -> [b] -> (a -> b -> Bool) -> [Maybe b]
enm [a]
kx [b]
hs a -> b -> Bool
eq
fnd :: (a -> Bool) -> [a] -> Maybe (a,[a])
fnd :: forall a. (a -> Bool) -> [a] -> Maybe (a, [a])
fnd a -> Bool
_ [] = forall a. Maybe a
Nothing
fnd a -> Bool
p (a
x:[a]
xs)
| a -> Bool
p a
x = forall a. a -> Maybe a
Just (a
x, [a]
xs)
| Bool
otherwise = case forall a. (a -> Bool) -> [a] -> Maybe (a, [a])
fnd a -> Bool
p [a]
xs of
Maybe (a, [a])
Nothing -> forall a. Maybe a
Nothing
Just (a
y,[a]
ys) -> forall a. a -> Maybe a
Just (a
y, a
xforall a. a -> [a] -> [a]
:[a]
ys)
isKeyOf :: CanonFieldKey -> Field -> Bool
isKeyOf :: ByteString -> Field -> Bool
isKeyOf ByteString
key Field
fld = Field -> ByteString
fieldSearchKey Field
fld forall a. Eq a => a -> a -> Bool
== ByteString
key
isNotKeyOf :: CanonFieldKey -> Field -> Bool
isNotKeyOf :: ByteString -> Field -> Bool
isNotKeyOf ByteString
key Field
fld = Field -> ByteString
fieldSearchKey Field
fld forall a. Eq a => a -> a -> Bool
/= ByteString
key
fieldValueFolded :: Field -> RawFieldValue
fieldValueFolded :: Field -> ByteString
fieldValueFolded = ByteString -> ByteString
BL.toStrict forall b c a. (b -> c) -> (a -> b) -> a -> c
. Builder -> ByteString
BB.toLazyByteString forall b c a. (b -> c) -> (a -> b) -> a -> c
. [ByteString] -> Builder
concatCRLF forall b c a. (b -> c) -> (a -> b) -> a -> c
. Field -> [ByteString]
fieldValue
fieldValueUnfolded :: Field -> RawFieldValue
fieldValueUnfolded :: Field -> ByteString
fieldValueUnfolded = [ByteString] -> ByteString
BS8.concat forall b c a. (b -> c) -> (a -> b) -> a -> c
. Field -> [ByteString]
fieldValue
fromBody :: Body -> Builder
fromBody :: Body -> Builder
fromBody = (ByteString -> ByteString) -> Body -> Builder
fromBodyWith forall a. a -> a
id
fromBodyWith :: (ByteString -> ByteString) -> Body -> Builder
fromBodyWith :: (ByteString -> ByteString) -> Body -> Builder
fromBodyWith ByteString -> ByteString
modify = forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
F.foldr (forall a. (a -> ByteString) -> a -> Builder -> Builder
appendCRLFWith ByteString -> ByteString
modify) forall a. Monoid a => a
B.empty
removeTrailingEmptyLine :: Body -> Body
removeTrailingEmptyLine :: Body -> Body
removeTrailingEmptyLine = forall a. (a -> Bool) -> Seq a -> Seq a
dropWhileR (forall a. Eq a => a -> a -> Bool
==ByteString
"")
dropWhileR :: (a -> Bool) -> Seq a -> Seq a
dropWhileR :: forall a. (a -> Bool) -> Seq a -> Seq a
dropWhileR a -> Bool
p Seq a
xs = case forall a. Seq a -> ViewR a
viewr Seq a
xs of
ViewR a
EmptyR -> forall a. Seq a
empty
Seq a
xs' :> a
x
| a -> Bool
p a
x -> forall a. (a -> Bool) -> Seq a -> Seq a
dropWhileR a -> Bool
p Seq a
xs'
| Bool
otherwise -> Seq a
xs