File: Post.hs

package info (click to toggle)
haskell-curl 1.3.8-15
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 264 kB
  • sloc: haskell: 1,528; ansic: 33; makefile: 2
file content (125 lines) | stat: -rw-r--r-- 3,726 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
{-# LANGUAGE ForeignFunctionInterface #-}
--------------------------------------------------------------------
-- |
-- Module    : Network.Curl.Post
-- Copyright : (c) Galois Inc 2007-2009
-- License   : BSD3
--
-- Maintainer: Sigbjorn Finne <sof@galois.com>
-- Stability : provisional
-- Portability: portable
--
-- Representing and marshalling formdata (as part of POST uploads\/submissions.)
-- If you are only looking to submit a sequence of name=value pairs,
-- you are better off using the CurlPostFields constructor; much simpler.
--
--------------------------------------------------------------------
module Network.Curl.Post where

import Network.Curl.Types

import Control.Monad
import Foreign.Ptr
import Foreign.Storable
import Foreign.Marshal.Alloc
import Foreign.C.Types
import Foreign.C.String

type Header = String

data HttpPost
 = HttpPost
     { postName     :: String
     , contentType  :: Maybe String
     , content      :: Content
     , extraHeaders :: [Header]
-- not yet:     , extraEntries :: [HttpPost]
     , showName     :: Maybe String
     } deriving ( Eq, Show )

data Content
 = ContentFile   FilePath
 | ContentBuffer (Ptr CChar) Long -- byte arrays also?
 | ContentString String
   deriving ( Eq, Show )

multiformString :: String -> String -> HttpPost
multiformString x y = 
  HttpPost { postName      = x
           , content       = ContentString y
           , contentType   = Nothing
           , extraHeaders  = []
           , showName      = Nothing
           } 

-- lower-level marshalling code.

sizeof_httppost :: Int
sizeof_httppost = 12 * sizeOf (nullPtr :: Ptr CChar)

marshallPosts :: [HttpPost] -> IO (Ptr HttpPost)
marshallPosts [] = return nullPtr
marshallPosts ps = do
  ms <- mapM marshallPost ps
  case ms of
    [] -> return nullPtr
    (x:xs) -> do
      linkUp x xs
      return x
 where
  linkUp p [] = pokeByteOff p 0 nullPtr
  linkUp p (x:xs) = do
    pokeByteOff p 0 x
    linkUp x xs
  
marshallPost :: HttpPost -> IO (Ptr HttpPost)
marshallPost p = do
  php <- mallocBytes sizeof_httppost
  pokeByteOff php 0 nullPtr
  newCString (postName p) >>= pokeByteOff php (ptrIndex 1)
  pokeByteOff php (ptrIndex 2) (length (postName p))
  case content p of
    ContentFile f -> do
      newCString f >>= pokeByteOff php (ptrIndex 3)
      pokeByteOff php (ptrIndex 4) (length f)
      pokeByteOff php (ptrIndex 5) nullPtr
      pokeByteOff php (ptrIndex 6) nullPtr
      pokeByteOff php (ptrIndex 10) (0x1 :: Long)
    ContentBuffer ptr len -> do
      pokeByteOff php (ptrIndex 3) nullPtr
      pokeByteOff php (ptrIndex 4) nullPtr
      pokeByteOff php (ptrIndex 5) ptr 
      pokeByteOff php (ptrIndex 6) len
      pokeByteOff php (ptrIndex 10) (0x10 :: Long)
    ContentString s -> do
      newCString s >>= pokeByteOff php (ptrIndex 3)
      pokeByteOff php (ptrIndex 4) (length s)
      pokeByteOff php (ptrIndex 5) nullPtr
      pokeByteOff php (ptrIndex 6) nullPtr
      pokeByteOff php (ptrIndex 10) (0x4 :: Long)
  
  cs1 <- case contentType p of
    Nothing -> return nullPtr
    Just s  -> newCString s
  pokeByteOff php (ptrIndex 7) cs1
  cs2 <- mapM newCString (extraHeaders p)
  ip <- foldM curl_slist_append nullPtr cs2
  pokeByteOff php (ptrIndex 8) ip
  pokeByteOff php (ptrIndex 9) nullPtr
  case showName p of
    Nothing -> pokeByteOff php (ptrIndex 11) nullPtr
    Just s  -> newCString s >>= pokeByteOff php (ptrIndex 11)
  return php
 where
  ptrIndex n = n * sizeOf nullPtr


foreign import ccall
  "curl_slist_append" curl_slist_append :: Ptr Slist_ -> CString -> IO (Ptr Slist_)
foreign import ccall
  "curl_slist_free_all" curl_slist_free :: Ptr Slist_ -> IO ()

foreign import ccall
  "curl_formfree" curl_formfree :: Ptr a -> IO ()