    {-# LANGUAGE OverloadedStrings #-}
    -- | This module handles building multipart/form-data. Example usage:
    --
    -- > {-# LANGUAGE OverloadedStrings #-}
    -- > import Network
    -- > import Network.HTTP.Client
    -- > import Network.HTTP.Client.MultipartFormData
    -- >
    -- > import Data.Text.Encoding as TE
    -- >
    -- > import Control.Monad
    -- >
    -- > main = void $ withManager defaultManagerSettings $ \m -> do
    -- >     req1 <- parseRequest "http://random-cat-photo.net/cat.jpg"
    -- >     res <- httpLbs req1 m
    -- >     req2 <- parseRequest "http://example.org/~friedrich/blog/addPost.hs"
    -- >     flip httpLbs m =<<
    -- >         (formDataBody [partBS "title" "Bleaurgh"
    -- >                       ,partBS "text" $ TE.encodeUtf8 "矢田矢田矢田矢田矢田"
    -- >                       ,partFileSource "file1" "/home/friedrich/Photos/MyLittlePony.jpg"
    -- >                       ,partFileRequestBody "file2" "cat.jpg" $ RequestBodyLBS $ responseBody res]
    -- >             req2)
    module Network.HTTP.Client.MultipartFormData
        (
        -- * Part type
         Part
        ,PartM
        ,partName
        ,partFilename
        ,partContentType
        ,partHeaders
        ,partGetBody
        -- * Constructing parts
        ,partBS
        ,partLBS
        ,partFile
        ,partFileSource
        ,partFileSourceChunked
        ,partFileRequestBody
        ,partFileRequestBodyM
        -- * Headers
        ,addPartHeaders
        -- * Building form data
        ,formDataBody
        ,formDataBodyWithBoundary
        -- * Boundary
        ,webkitBoundary
        ,webkitBoundaryPure
        -- * Misc
        ,renderParts
        ,renderPart
        ) where

    import Network.HTTP.Client hiding (streamFile)
    import Network.Mime
    import Network.HTTP.Types (hContentType, methodPost, Header())
    import Data.Monoid ((<>))
    import Data.Foldable (foldMap)

    import Blaze.ByteString.Builder

    import Data.Text
    import qualified Data.Text.Encoding as TE
    import qualified Data.ByteString.Lazy as BL
    import qualified Data.ByteString as BS

    import qualified Data.CaseInsensitive as CI

    import Control.Monad.Trans.State.Strict (state, runState)
    import Control.Monad.IO.Class
    import System.FilePath
    import System.Random
    import Data.Array.Base
    import System.IO
    import Data.Bits
    import Data.Word
    import Data.Monoid (Monoid(..))
    import Control.Monad
    import Data.ByteString.Lazy.Internal (defaultChunkSize)

    type Part = PartM IO

    -- | A single part of a multipart message.
    data PartM m = Part
        { forall (m :: * -> *). PartM m -> Text
    partName :: Text -- ^ Name of the corresponding \<input\>
        , forall (m :: * -> *). PartM m -> Maybe String
    partFilename :: Maybe String -- ^ A file name, if this is an attached file
        , forall (m :: * -> *). PartM m -> Maybe MimeType
    partContentType :: Maybe MimeType -- ^ Content type
        , forall (m :: * -> *). PartM m -> [Header]
    partHeaders :: [Header] -- ^ List of additional headers
        , forall (m :: * -> *). PartM m -> m RequestBody
    partGetBody :: m RequestBody -- ^ Action in m which returns the body
                                       -- of a message.
        }

    instance Show (PartM m) where
        showsPrec :: Int -> PartM m -> ShowS
    showsPrec Int
    d (Part Text
    n Maybe String
    f Maybe MimeType
    c [Header]
    h m RequestBody
    _) =
            Bool -> ShowS -> ShowS
    showParen (Int
    dInt -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    >=Int
    11) (ShowS -> ShowS) -> ShowS -> ShowS
    forall a b. (a -> b) -> a -> b
    $ String -> ShowS
    showString String
    "Part "
                ShowS -> ShowS -> ShowS
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Int -> Text -> ShowS
    forall a. Show a => Int -> a -> ShowS
    showsPrec Int
    11 Text
    n
                ShowS -> ShowS -> ShowS
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . String -> ShowS
    showString String
    " "
                ShowS -> ShowS -> ShowS
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Int -> Maybe String -> ShowS
    forall a. Show a => Int -> a -> ShowS
    showsPrec Int
    11 Maybe String
    f
                ShowS -> ShowS -> ShowS
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . String -> ShowS
    showString String
    " "
                ShowS -> ShowS -> ShowS
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Int -> Maybe MimeType -> ShowS
    forall a. Show a => Int -> a -> ShowS
    showsPrec Int
    11 Maybe MimeType
    c
                ShowS -> ShowS -> ShowS
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . String -> ShowS
    showString String
    " "
                ShowS -> ShowS -> ShowS
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Int -> [Header] -> ShowS
    forall a. Show a => Int -> a -> ShowS
    showsPrec Int
    11 [Header]
    h
                ShowS -> ShowS -> ShowS
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . String -> ShowS
    showString String
    " "
                ShowS -> ShowS -> ShowS
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . String -> ShowS
    showString String
    "<m (RequestBody m)>"

    -- | Make a 'Part' whose content is a strict 'BS.ByteString'.
    --
    -- The 'Part' does not have a file name or content type associated
    -- with it.
    partBS :: Applicative m
           => Text              -- ^ Name of the corresponding \<input\>.
           -> BS.ByteString     -- ^ The body for this 'Part'.
           -> PartM m
    partBS :: forall (m :: * -> *). Applicative m => Text -> MimeType -> PartM m
    partBS Text
    n MimeType
    b = Text
    -> Maybe String
    -> Maybe MimeType
    -> [Header]
    -> m RequestBody
    -> PartM m
    forall (m :: * -> *).
    Text
    -> Maybe String
    -> Maybe MimeType
    -> [Header]
    -> m RequestBody
    -> PartM m
    Part Text
    n Maybe String
    forall a. Monoid a => a
    Data.Monoid.mempty Maybe MimeType
    forall a. Monoid a => a
    mempty [Header]
    forall a. Monoid a => a
    mempty (m RequestBody -> PartM m) -> m RequestBody -> PartM m
    forall a b. (a -> b) -> a -> b
    $ RequestBody -> m RequestBody
    forall a. a -> m a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure (RequestBody -> m RequestBody) -> RequestBody -> m RequestBody
    forall a b. (a -> b) -> a -> b
    $ MimeType -> RequestBody
    RequestBodyBS MimeType
    b

    -- | Make a 'Part' whose content is a lazy 'BL.ByteString'.
    --
    -- The 'Part' does not have a file name or content type associated
    -- with it.
    partLBS :: Applicative m
            => Text             -- ^ Name of the corresponding \<input\>.
            -> BL.ByteString    -- ^ The body for this 'Part'.
            -> PartM m
    partLBS :: forall (m :: * -> *).
    Applicative m =>
    Text -> ByteString -> PartM m
    partLBS Text
    n ByteString
    b = Text
    -> Maybe String
    -> Maybe MimeType
    -> [Header]
    -> m RequestBody
    -> PartM m
    forall (m :: * -> *).
    Text
    -> Maybe String
    -> Maybe MimeType
    -> [Header]
    -> m RequestBody
    -> PartM m
    Part Text
    n Maybe String
    forall a. Monoid a => a
    mempty Maybe MimeType
    forall a. Monoid a => a
    mempty [Header]
    forall a. Monoid a => a
    mempty (m RequestBody -> PartM m) -> m RequestBody -> PartM m
    forall a b. (a -> b) -> a -> b
    $ RequestBody -> m RequestBody
    forall a. a -> m a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure (RequestBody -> m RequestBody) -> RequestBody -> m RequestBody
    forall a b. (a -> b) -> a -> b
    $ ByteString -> RequestBody
    RequestBodyLBS ByteString
    b

    -- | Make a 'Part' from a file.
    --
    -- The entire file will reside in memory at once.  If you want
    -- constant memory usage, use 'partFileSource'.
    --
    -- The 'FilePath' supplied will be used as the file name of the
    -- 'Part'. If you do not want to reveal this name to the server, you
    -- must remove it prior to uploading.
    --
    -- The 'Part' does not have a content type associated with it.
    partFile :: Text            -- ^ Name of the corresponding \<input\>.
             -> FilePath        -- ^ The name of the local file to upload.
             -> Part
    partFile :: Text -> String -> Part
    partFile Text
    n String
    f =
        Text -> String -> IO RequestBody -> Part
    forall (m :: * -> *). Text -> String -> m RequestBody -> PartM m
    partFileRequestBodyM Text
    n String
    f (IO RequestBody -> Part) -> IO RequestBody -> Part
    forall a b. (a -> b) -> a -> b
    $ do
            (MimeType -> RequestBody) -> IO MimeType -> IO RequestBody
    forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
    liftM MimeType -> RequestBody
    RequestBodyBS (IO MimeType -> IO RequestBody) -> IO MimeType -> IO RequestBody
    forall a b. (a -> b) -> a -> b
    $ IO MimeType -> IO MimeType
    forall a. IO a -> IO a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO MimeType -> IO MimeType) -> IO MimeType -> IO MimeType
    forall a b. (a -> b) -> a -> b
    $ String -> IO MimeType
    BS.readFile String
    f

    -- | Stream a 'Part' from a file.
    --
    -- The 'FilePath' supplied will be used as the file name of the
    -- 'Part'. If you do not want to reveal this name to the server, you
    -- must remove it prior to uploading.
    --
    -- The 'Part' does not have a content type associated with it.
    partFileSource :: Text      -- ^ Name of the corresponding \<input\>.
                   -> FilePath  -- ^ The name of the local file to upload.
                   -> Part
    partFileSource :: Text -> String -> Part
    partFileSource Text
    n String
    f =
        Text -> String -> IO RequestBody -> Part
    forall (m :: * -> *). Text -> String -> m RequestBody -> PartM m
    partFileRequestBodyM Text
    n String
    f (IO RequestBody -> Part) -> IO RequestBody -> Part
    forall a b. (a -> b) -> a -> b
    $ do
            size <- IO Integer -> IO Integer
    forall a. IO a -> IO a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO Integer -> IO Integer) -> IO Integer -> IO Integer
    forall a b. (a -> b) -> a -> b
    $ String -> IOMode -> (Handle -> IO Integer) -> IO Integer
    forall r. String -> IOMode -> (Handle -> IO r) -> IO r
    withBinaryFile String
    f IOMode
    ReadMode Handle -> IO Integer
    hFileSize
            return $ RequestBodyStream (fromInteger size) $ streamFile f

    streamFile :: FilePath -> GivesPopper ()
    streamFile :: String -> GivesPopper ()
    streamFile String
    fp NeedsPopper ()
    np =
        String -> IOMode -> (Handle -> IO ()) -> IO ()
    forall r. String -> IOMode -> (Handle -> IO r) -> IO r
    withFile String
    fp IOMode
    ReadMode ((Handle -> IO ()) -> IO ()) -> (Handle -> IO ()) -> IO ()
    forall a b. (a -> b) -> a -> b
    $ NeedsPopper ()
    np NeedsPopper () -> (Handle -> IO MimeType) -> Handle -> IO ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Handle -> IO MimeType
    go
      where
        go :: Handle -> IO MimeType
    go Handle
    h = Handle -> Int -> IO MimeType
    BS.hGetSome Handle
    h Int
    defaultChunkSize

    -- | 'partFileSourceChunked' will read a file and send it in chunks.
    --
    -- Note that not all servers support this. Only use 'partFileSourceChunked'
    -- if you know the server you're sending to supports chunked request bodies.
    --
    -- The 'FilePath' supplied will be used as the file name of the
    -- 'Part'. If you do not want to reveal this name to the server, you
    -- must remove it prior to uploading.
    --
    -- The 'Part' does not have a content type associated with it.
    partFileSourceChunked :: Text -> FilePath -> Part
    partFileSourceChunked :: Text -> String -> Part
    partFileSourceChunked Text
    n String
    f =
        Text -> String -> RequestBody -> Part
    forall (m :: * -> *).
    Applicative m =>
    Text -> String -> RequestBody -> PartM m
    partFileRequestBody Text
    n String
    f (RequestBody -> Part) -> RequestBody -> Part
    forall a b. (a -> b) -> a -> b
    $ do
            GivesPopper () -> RequestBody
    RequestBodyStreamChunked (GivesPopper () -> RequestBody) -> GivesPopper () -> RequestBody
    forall a b. (a -> b) -> a -> b
    $ String -> GivesPopper ()
    streamFile String
    f

    -- | Construct a 'Part' from form name, filepath and a 'RequestBody'
    --
    -- > partFileRequestBody "who_calls" "caller.json" $ RequestBodyBS "{\"caller\":\"Jason J Jason\"}"
    --
    -- > -- empty upload form
    -- > partFileRequestBody "file" mempty mempty
    --
    -- The 'Part' does not have a content type associated with it.
    partFileRequestBody :: Applicative m
                        => Text        -- ^ Name of the corresponding \<input\>.
                        -> FilePath    -- ^ File name to supply to the server.
                        -> RequestBody -- ^ Data to upload.
                        -> PartM m
    partFileRequestBody :: forall (m :: * -> *).
    Applicative m =>
    Text -> String -> RequestBody -> PartM m
    partFileRequestBody Text
    n String
    f RequestBody
    rqb =
        Text -> String -> m RequestBody -> PartM m
    forall (m :: * -> *). Text -> String -> m RequestBody -> PartM m
    partFileRequestBodyM Text
    n String
    f (m RequestBody -> PartM m) -> m RequestBody -> PartM m
    forall a b. (a -> b) -> a -> b
    $ RequestBody -> m RequestBody
    forall a. a -> m a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure RequestBody
    rqb

    -- | Construct a 'Part' from action returning the 'RequestBody'
    --
    -- > partFileRequestBodyM "cat_photo" "haskell-the-cat.jpg" $ do
    -- >     size <- fromInteger <$> withBinaryFile "haskell-the-cat.jpg" ReadMode hFileSize
    -- >     return $ RequestBodySource size $ CB.sourceFile "haskell-the-cat.jpg" $= CL.map fromByteString
    --
    -- The 'Part' does not have a content type associated with it.
    partFileRequestBodyM :: Text        -- ^ Name of the corresponding \<input\>.
                         -> FilePath    -- ^ File name to supply to the server.
                         -> m RequestBody -- ^ Action that will supply data to upload.
                         -> PartM m
    partFileRequestBodyM :: forall (m :: * -> *). Text -> String -> m RequestBody -> PartM m
    partFileRequestBodyM Text
    n String
    f m RequestBody
    rqb =
        Text
    -> Maybe String
    -> Maybe MimeType
    -> [Header]
    -> m RequestBody
    -> PartM m
    forall (m :: * -> *).
    Text
    -> Maybe String
    -> Maybe MimeType
    -> [Header]
    -> m RequestBody
    -> PartM m
    Part Text
    n (String -> Maybe String
    forall a. a -> Maybe a
    Just String
    f) (MimeType -> Maybe MimeType
    forall a. a -> Maybe a
    Just (MimeType -> Maybe MimeType) -> MimeType -> Maybe MimeType
    forall a b. (a -> b) -> a -> b
    $ Text -> MimeType
    defaultMimeLookup (Text -> MimeType) -> Text -> MimeType
    forall a b. (a -> b) -> a -> b
    $ String -> Text
    pack String
    f) [Header]
    forall a. Monoid a => a
    mempty m RequestBody
    rqb

    {-# INLINE cp #-}
    cp :: BS.ByteString -> RequestBody
    cp :: MimeType -> RequestBody
    cp MimeType
    bs = Int64 -> Builder -> RequestBody
    RequestBodyBuilder (Int -> Int64
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (Int -> Int64) -> Int -> Int64
    forall a b. (a -> b) -> a -> b
    $ MimeType -> Int
    BS.length MimeType
    bs) (Builder -> RequestBody) -> Builder -> RequestBody
    forall a b. (a -> b) -> a -> b
    $ MimeType -> Builder
    copyByteString MimeType
    bs

    -- | Add a list of additional headers to this 'Part'.
    addPartHeaders :: PartM m -> [Header] -> PartM m
    addPartHeaders :: forall (m :: * -> *). PartM m -> [Header] -> PartM m
    addPartHeaders PartM m
    p [Header]
    hs = PartM m
    p { partHeaders = partHeaders p <> hs }

    renderPart :: Functor m
               => BS.ByteString     -- ^ Boundary between parts.
               -> PartM m -> m RequestBody
    renderPart :: forall (m :: * -> *).
    Functor m =>
    MimeType -> PartM m -> m RequestBody
    renderPart MimeType
    boundary (Part Text
    name Maybe String
    mfilename Maybe MimeType
    mcontenttype [Header]
    hdrs m RequestBody
    get) = RequestBody -> RequestBody
    render (RequestBody -> RequestBody) -> m RequestBody -> m RequestBody
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> m RequestBody
    get
      where render :: RequestBody -> RequestBody
    render RequestBody
    renderBody =
                MimeType -> RequestBody
    cp MimeType
    "--" RequestBody -> RequestBody -> RequestBody
    forall a. Semigroup a => a -> a -> a
    <> MimeType -> RequestBody
    cp MimeType
    boundary RequestBody -> RequestBody -> RequestBody
    forall a. Semigroup a => a -> a -> a
    <> MimeType -> RequestBody
    cp MimeType
    "\r\n"
             RequestBody -> RequestBody -> RequestBody
    forall a. Semigroup a => a -> a -> a
    <> MimeType -> RequestBody
    cp MimeType
    "Content-Disposition: form-data; name=\""
             RequestBody -> RequestBody -> RequestBody
    forall a. Semigroup a => a -> a -> a
    <> MimeType -> RequestBody
    RequestBodyBS (Text -> MimeType
    TE.encodeUtf8 Text
    name)
             RequestBody -> RequestBody -> RequestBody
    forall a. Semigroup a => a -> a -> a
    <> (case Maybe String
    mfilename of
                     Just String
    f -> MimeType -> RequestBody
    cp MimeType
    "\"; filename=\""
                            RequestBody -> RequestBody -> RequestBody
    forall a. Semigroup a => a -> a -> a
    <> MimeType -> RequestBody
    RequestBodyBS (Text -> MimeType
    TE.encodeUtf8 (Text -> MimeType) -> Text -> MimeType
    forall a b. (a -> b) -> a -> b
    $ String -> Text
    pack (String -> Text) -> String -> Text
    forall a b. (a -> b) -> a -> b
    $ ShowS
    takeFileName String
    f)
                     Maybe String
    _ -> RequestBody
    forall a. Monoid a => a
    mempty)
             RequestBody -> RequestBody -> RequestBody
    forall a. Semigroup a => a -> a -> a
    <> MimeType -> RequestBody
    cp MimeType
    "\""
             RequestBody -> RequestBody -> RequestBody
    forall a. Semigroup a => a -> a -> a
    <> (case Maybe MimeType
    mcontenttype of
                    Just MimeType
    ct -> MimeType -> RequestBody
    cp MimeType
    "\r\n"
                            RequestBody -> RequestBody -> RequestBody
    forall a. Semigroup a => a -> a -> a
    <> MimeType -> RequestBody
    cp MimeType
    "Content-Type: "
                            RequestBody -> RequestBody -> RequestBody
    forall a. Semigroup a => a -> a -> a
    <> MimeType -> RequestBody
    cp MimeType
    ct
                    Maybe MimeType
    _ -> RequestBody
    forall a. Monoid a => a
    mempty)
             RequestBody -> RequestBody -> RequestBody
    forall a. Semigroup a => a -> a -> a
    <> (Header -> RequestBody) -> [Header] -> RequestBody
    forall m a. Monoid m => (a -> m) -> [a] -> m
    forall (t :: * -> *) m a.
    (Foldable t, Monoid m) =>
    (a -> m) -> t a -> m
    Data.Foldable.foldMap (\(CI MimeType
    k, MimeType
    v) ->
                   MimeType -> RequestBody
    cp MimeType
    "\r\n"
                RequestBody -> RequestBody -> RequestBody
    forall a. Semigroup a => a -> a -> a
    <> MimeType -> RequestBody
    cp (CI MimeType -> MimeType
    forall s. CI s -> s
    CI.original CI MimeType
    k)
                RequestBody -> RequestBody -> RequestBody
    forall a. Semigroup a => a -> a -> a
    <> MimeType -> RequestBody
    cp MimeType
    ": "
                RequestBody -> RequestBody -> RequestBody
    forall a. Semigroup a => a -> a -> a
    <> MimeType -> RequestBody
    cp MimeType
    v) [Header]
    hdrs
             RequestBody -> RequestBody -> RequestBody
    forall a. Semigroup a => a -> a -> a
    <> MimeType -> RequestBody
    cp MimeType
    "\r\n\r\n"
             RequestBody -> RequestBody -> RequestBody
    forall a. Semigroup a => a -> a -> a
    <> RequestBody
    renderBody RequestBody -> RequestBody -> RequestBody
    forall a. Semigroup a => a -> a -> a
    <> MimeType -> RequestBody
    cp MimeType
    "\r\n"

    -- | Combine the 'Part's to form multipart/form-data body
    renderParts :: Applicative m
                => BS.ByteString    -- ^ Boundary between parts.
                -> [PartM m] -> m RequestBody
    renderParts :: forall (m :: * -> *).
    Applicative m =>
    MimeType -> [PartM m] -> m RequestBody
    renderParts MimeType
    boundary [PartM m]
    parts = (RequestBody -> RequestBody
    fin (RequestBody -> RequestBody)
    -> ([RequestBody] -> RequestBody) -> [RequestBody] -> RequestBody
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . [RequestBody] -> RequestBody
    forall a. Monoid a => [a] -> a
    mconcat) ([RequestBody] -> RequestBody) -> m [RequestBody] -> m RequestBody
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> (PartM m -> m RequestBody) -> [PartM m] -> m [RequestBody]
    forall (t :: * -> *) (f :: * -> *) a b.
    (Traversable t, Applicative f) =>
    (a -> f b) -> t a -> f (t b)
    forall (f :: * -> *) a b.
    Applicative f =>
    (a -> f b) -> [a] -> f [b]
    traverse (MimeType -> PartM m -> m RequestBody
    forall (m :: * -> *).
    Functor m =>
    MimeType -> PartM m -> m RequestBody
    renderPart MimeType
    boundary) [PartM m]
    parts
      where fin :: RequestBody -> RequestBody
    fin = (RequestBody -> RequestBody -> RequestBody
    forall a. Semigroup a => a -> a -> a
    <> MimeType -> RequestBody
    cp MimeType
    "--" RequestBody -> RequestBody -> RequestBody
    forall a. Semigroup a => a -> a -> a
    <> MimeType -> RequestBody
    cp MimeType
    boundary RequestBody -> RequestBody -> RequestBody
    forall a. Semigroup a => a -> a -> a
    <> MimeType -> RequestBody
    cp MimeType
    "--\r\n")

    -- | Generate a boundary simillar to those generated by WebKit-based browsers.
    webkitBoundary :: IO BS.ByteString
    webkitBoundary :: IO MimeType
    webkitBoundary = (StdGen -> (MimeType, StdGen)) -> IO MimeType
    forall (m :: * -> *) a. MonadIO m => (StdGen -> (a, StdGen)) -> m a
    getStdRandom StdGen -> (MimeType, StdGen)
    forall g. RandomGen g => g -> (MimeType, g)
    webkitBoundaryPure

    webkitBoundaryPure :: RandomGen g => g -> (BS.ByteString, g)
    webkitBoundaryPure :: forall g. RandomGen g => g -> (MimeType, g)
    webkitBoundaryPure g
    g = (State g MimeType -> g -> (MimeType, g)
    forall s a. State s a -> s -> (a, s)
    `runState` g
    g) (State g MimeType -> (MimeType, g))
    -> State g MimeType -> (MimeType, g)
    forall a b. (a -> b) -> a -> b
    $ do
        ([[Word8]] -> MimeType)
    -> StateT g Identity [[Word8]] -> State g MimeType
    forall a b. (a -> b) -> StateT g Identity a -> StateT g Identity b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap (MimeType -> MimeType -> MimeType
    BS.append MimeType
    prefix (MimeType -> MimeType)
    -> ([[Word8]] -> MimeType) -> [[Word8]] -> MimeType
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . [Word8] -> MimeType
    BS.pack ([Word8] -> MimeType)
    -> ([[Word8]] -> [Word8]) -> [[Word8]] -> MimeType
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . [[Word8]] -> [Word8]
    forall (t :: * -> *) a. Foldable t => t [a] -> [a]
    Prelude.concat) (StateT g Identity [[Word8]] -> State g MimeType)
    -> StateT g Identity [[Word8]] -> State g MimeType
    forall a b. (a -> b) -> a -> b
    $ Int -> StateT g Identity [Word8] -> StateT g Identity [[Word8]]
    forall (m :: * -> *) a. Applicative m => Int -> m a -> m [a]
    replicateM Int
    4 (StateT g Identity [Word8] -> StateT g Identity [[Word8]])
    -> StateT g Identity [Word8] -> StateT g Identity [[Word8]]
    forall a b. (a -> b) -> a -> b
    $ do
            randomness <- (g -> (Int, g)) -> StateT g Identity Int
    forall (m :: * -> *) s a. Monad m => (s -> (a, s)) -> StateT s m a
    state ((g -> (Int, g)) -> StateT g Identity Int)
    -> (g -> (Int, g)) -> StateT g Identity Int
    forall a b. (a -> b) -> a -> b
    $ g -> (Int, g)
    forall g. RandomGen g => g -> (Int, g)
    forall a g. (Random a, RandomGen g) => g -> (a, g)
    random
            return [unsafeAt alphaNumericEncodingMap $ randomness `shiftR` 24 .&. 0x3F
                   ,unsafeAt alphaNumericEncodingMap $ randomness `shiftR` 16 .&. 0x3F
                   ,unsafeAt alphaNumericEncodingMap $ randomness `shiftR` 8 .&. 0x3F
                   ,unsafeAt alphaNumericEncodingMap $ randomness .&. 0x3F]
      where
        prefix :: MimeType
    prefix = MimeType
    "----WebKitFormBoundary"
        alphaNumericEncodingMap :: UArray Int Word8
        alphaNumericEncodingMap :: UArray Int Word8
    alphaNumericEncodingMap = (Int, Int) -> [Word8] -> UArray Int Word8
    forall (a :: * -> * -> *) e i.
    (IArray a e, Ix i) =>
    (i, i) -> [e] -> a i e
    listArray (Int
    0, Int
    63)
            [Word8
    0x41, Word8
    0x42, Word8
    0x43, Word8
    0x44, Word8
    0x45, Word8
    0x46, Word8
    0x47, Word8
    0x48,
             Word8
    0x49, Word8
    0x4A, Word8
    0x4B, Word8
    0x4C, Word8
    0x4D, Word8
    0x4E, Word8
    0x4F, Word8
    0x50,
             Word8
    0x51, Word8
    0x52, Word8
    0x53, Word8
    0x54, Word8
    0x55, Word8
    0x56, Word8
    0x57, Word8
    0x58,
             Word8
    0x59, Word8
    0x5A, Word8
    0x61, Word8
    0x62, Word8
    0x63, Word8
    0x64, Word8
    0x65, Word8
    0x66,
             Word8
    0x67, Word8
    0x68, Word8
    0x69, Word8
    0x6A, Word8
    0x6B, Word8
    0x6C, Word8
    0x6D, Word8
    0x6E,
             Word8
    0x6F, Word8
    0x70, Word8
    0x71, Word8
    0x72, Word8
    0x73, Word8
    0x74, Word8
    0x75, Word8
    0x76,
             Word8
    0x77, Word8
    0x78, Word8
    0x79, Word8
    0x7A, Word8
    0x30, Word8
    0x31, Word8
    0x32, Word8
    0x33,
             Word8
    0x34, Word8
    0x35, Word8
    0x36, Word8
    0x37, Word8
    0x38, Word8
    0x39, Word8
    0x41, Word8
    0x42]

    -- | Add form data to the 'Request'.
    --
    -- This sets a new 'requestBody', adds a content-type request header and changes the method to POST.
    formDataBody :: MonadIO m => [Part] -> Request -> m Request
    formDataBody :: forall (m :: * -> *). MonadIO m => [Part] -> Request -> m Request
    formDataBody [Part]
    a Request
    b = IO Request -> m Request
    forall a. IO a -> m a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO Request -> m Request) -> IO Request -> m Request
    forall a b. (a -> b) -> a -> b
    $ do
        boundary <- IO MimeType
    webkitBoundary
        formDataBodyWithBoundary boundary a b

    -- | Add form data with supplied boundary
    formDataBodyWithBoundary :: Applicative m => BS.ByteString -> [PartM m] -> Request -> m Request
    formDataBodyWithBoundary :: forall (m :: * -> *).
    Applicative m =>
    MimeType -> [PartM m] -> Request -> m Request
    formDataBodyWithBoundary MimeType
    boundary [PartM m]
    parts Request
    req = do
        (\ RequestBody
    body -> Request
    req
            { method = methodPost
            , requestHeaders =
                (hContentType, "multipart/form-data; boundary=" <> boundary)
              : Prelude.filter (\(CI MimeType
    x, MimeType
    _) -> CI MimeType
    x CI MimeType -> CI MimeType -> Bool
    forall a. Eq a => a -> a -> Bool
    /= CI MimeType
    hContentType) (requestHeaders req)
            , requestBody = body
            }) (RequestBody -> Request) -> m RequestBody -> m Request
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> MimeType -> [PartM m] -> m RequestBody
    forall (m :: * -> *).
    Applicative m =>
    MimeType -> [PartM m] -> m RequestBody
    renderParts MimeType
    boundary [PartM m]
    parts