diff --git a/examples/cURLv3/post_form.lua b/examples/cURLv3/post_form.lua
new file mode 100644
index 0000000..ce3a8f8
--- /dev/null
+++ b/examples/cURLv3/post_form.lua
@@ -0,0 +1,87 @@
+local cURL = require "cURL"
+
+-- Stream class
+local Stream = {} do
+Stream.__index = Stream
+
+function Stream:new(ch, length)
+ local o = setmetatable({}, self)
+ o._len = length
+ o._ch = ch
+ o._pos = 0
+ o._step = 7
+ return o
+end
+
+function Stream:length()
+ return self._len
+end
+
+function Stream:read()
+ local n = self._len - self._pos
+ if n <= 0 then return '' end -- eof
+ if n > self._step then n = self._step end
+ self._pos = self._pos + n
+ return self._ch:rep(n)
+end
+
+end
+
+-- returns size and reader
+local function make_stream(ch, n, m)
+ local size = n * m
+ local i = -1
+ return size, function()
+ i = i + 1
+ if i < m then
+ return (tostring(ch)):rep(n - 2) .. '\r\n'
+ end
+ return nil
+ end
+end
+
+local length, stream = make_stream("a", 10, 4)
+
+c = cURL.easy{
+ url = "http://posttestserver.com/post.php",
+ -- url = "http://httpbin.org/post",
+ post = true,
+ httppost = cURL.form{
+
+ -- file form filesystem
+ name01 = {
+ file = "post_form.lua",
+ type = "text/plain",
+ name = "post.lua",
+ },
+
+ -- file form string
+ name02 = {
+ data = "bold",
+ name = "dummy.html",
+ type = "text/html",
+ },
+
+ -- file form stream object
+ name03 = {
+ stream = Stream:new('8', 25),
+ name = "stream1.txt",
+ type = "text/plain",
+ headers = {
+ "X-Test-Char : 8",
+ "X-Test-length : 25",
+ }
+ },
+
+ -- file form stream function
+ name04 = {
+ stream = stream,
+ length = length,
+ name = "stream2.txt",
+ type = "text/plain",
+ },
+
+ },
+}
+
+c:perform()
diff --git a/src/lua/cURL/impl/cURL.lua b/src/lua/cURL/impl/cURL.lua
index 066d212..f444eb5 100644
--- a/src/lua/cURL/impl/cURL.lua
+++ b/src/lua/cURL/impl/cURL.lua
@@ -12,6 +12,12 @@
-- Implementation of Lua-cURL http://msva.github.io/lua-curl
--
+local function clone(t, o)
+ o = o or {}
+ for k,v in pairs(t) do o[k]=v end
+ return o
+end
+
local function wrap_function(k)
return function(self, ...)
local ok, err = self._handle[k](self._handle, ...)
@@ -94,6 +100,80 @@ local function make_iterator(self, perform)
end
end
+
+-- name = ///
+--
+-- = {
+-- stream = function/object
+-- length = ?number
+-- name = ?string
+-- type = ?string
+-- headers = ?table
+-- }
+--
+-- = {
+-- file = string
+-- type = ?string
+-- name = ?string
+-- headers = ?table
+-- }
+--
+-- = {
+-- data = string
+-- name = string
+-- type = ?string
+-- headers = ?table
+-- }
+--
+local function form_add_element(form, name, value)
+ local vt = type(value)
+ if vt == "string" then return form:add_content(name, value) end
+
+ assert(type(name) == "string")
+ assert(vt == "table")
+ assert((value.name == nil) or (type(value.name) == 'string'))
+ assert((value.type == nil) or (type(value.type) == 'string'))
+ assert((value.headrs == nil) or (type(value.type) == 'string'))
+
+ if value.stream then
+ local vst = type(value.stream)
+
+ if vst == 'function' then
+ assert(type(value.length) == 'number')
+ local length = value.length
+ return form:add_stream(name, value.name, value.type, value.headers, length, value.stream)
+ end
+
+ if (vst == 'table') or (vst == 'userdata') then
+ local length = value.length or assert(value.stream:length())
+ assert(type(length) == 'number')
+ return form:add_stream(name, value.name, value.type, value.headers, length, value.stream)
+ end
+
+ error("Unsupported stream type: " .. vst)
+ end
+
+ if value.file then
+ assert(type(value.file) == 'string')
+ return form:add_file(name, value.file, value.type, value.filename, value.headers)
+ end
+
+ if value.data then
+ assert(type(value.data) == 'string')
+ assert(type(value.name) == 'string')
+ return form:add_buffer(name, value.name, value.data, value.type, value.headers)
+ end
+end
+
+local function form_add(form, data)
+ for k, v in pairs(data) do
+ local ok, err = form_add_element(form, k, v)
+ if not ok then return nil, err end
+ end
+
+ return form
+end
+
local function class(ctor)
local C = {}
C.__index = function(self, k)
@@ -334,6 +414,21 @@ end
local function Load_cURLv3(cURL, curl)
+-------------------------------------------
+local Form = class(curl.form) do
+
+function Form:__init(opt)
+ if opt then return self:add(opt) end
+ return self
+end
+
+function Form:add(data)
+ return form_add(self, data)
+end
+
+end
+-------------------------------------------
+
-------------------------------------------
local Easy = class(curl.easy) do
@@ -352,6 +447,33 @@ function Easy:perform(opt)
return perform(self)
end
+local setopt_httppost = wrap_function("setopt_httppost")
+function Easy:setopt_httppost(form)
+ return setopt_httppost(self, form:handle())
+end
+
+local setopt = wrap_function("setopt")
+function Easy:setopt(k, v)
+ if type(k) == 'table' then
+ local t = k
+
+ local hpost = t.httppost or t[curl.OPT_HTTPPOST]
+ if hpost and hpost._handle then
+ t = clone(t)
+ if t.httppost then t.httppost = hpost:handle() end
+ if t[curl.OPT_HTTPPOST] then t[curl.OPT_HTTPPOST] = hpost:handle() end
+ end
+
+ return setopt(self, t)
+ end
+
+ if k == curl.OPT_HTTPPOST then
+ return self:setopt_httppost(v)
+ end
+
+ return setopt(self, k, v)
+end
+
end
-------------------------------------------
@@ -409,6 +531,8 @@ end
setmetatable(cURL, {__index = curl})
+function cURL.form(...) return Form:new(...) end
+
function cURL.easy(...) return Easy:new(...) end
function cURL.multi(...) return Multi:new(...) end
diff --git a/src/lua/cURL/utils.lua b/src/lua/cURL/utils.lua
index 438d7b2..045e9fc 100644
--- a/src/lua/cURL/utils.lua
+++ b/src/lua/cURL/utils.lua
@@ -35,7 +35,7 @@ local function find_ca_bundle(name)
end
if env.SSL_CERT_DIR and path.isdir(env.SSL_CERT_DIR) then
- return false, env.SSL_CERT_DIR
+ return nil, env.SSL_CERT_DIR
end
if env.SSL_CERT_FILE and path.isfile(env.SSL_CERT_FILE) then