This commit is contained in:
zhaozg 2014-09-03 09:45:02 +08:00
commit 95f6140087
13 changed files with 694 additions and 317 deletions

View File

@ -23,7 +23,8 @@ install:
script:
- cd test
- lunit.sh run.lua
- lunit.sh test_easy.lua
- lunit.sh test_safe.lua
after_success:
- coveralls -b .. -r ..

View File

@ -84,6 +84,20 @@ function add_buffer() end
-- @return[1] self
function add_file() end
--- Add new part to form.
--
-- @tparam string name provide the name of this part
-- @tparam[opt] string filename provides the filename field in the content header.
-- @tparam[opt] string type provides the content-type for this part
-- @tparam[opt] table headers specifies extra headers for the form POST section
-- @tparam number size stream size in bytes
-- @tparam function/object reader
-- @param[opt] context reader context
-- @return[1] self
--
-- @see easy:setopt_readfunction
function add_stream() end
--- Serialize multipart/formdata HTTP POST chain.
--
-- @return[1] string serialized data
@ -213,6 +227,16 @@ function close() end
-- }
function setopt() end
--- Reset option to default value.
--
-- @tparam number opt one of `curl.OPT_XXX` constant or options table
-- @treturn easy self
--
-- @usage
-- c:unsetopt(curl.OPT_URL)
-- c:unsetopt(curl.OPT_READFUNCTION)
function unsetopt() end
--- Get information.
--
-- @tparam number info one of `curl.INFO_XXX` constant

26
examples/post_stream.lua Normal file
View File

@ -0,0 +1,26 @@
local curl = require "lcurl"
-- 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
end
end
local form = curl.form()
:add_stream("test1", make_stream("a", 10, 4))
:add_stream("test2", "test2.txt", make_stream("b", 10, 4))
:add_stream("test3", "test3.txt", "text/plain", make_stream("c", 10, 4))
curl.easy{
url = 'http://posttestserver.com/post.php',
writefunction = io.write,
httppost = form,
post = true,
}:perform()

View File

@ -25,7 +25,8 @@ install = target('install', {
})
target('test', install, function()
run_test('run.lua')
run_test('test_easy.lua')
run_test('test_safe.lua')
if not test_summary() then
quit("test fail")

View File

@ -172,6 +172,8 @@ static int lcurl_easy_reset(lua_State *L){
//{ OPTIONS
//{ set
static int lcurl_opt_set_long_(lua_State *L, int opt){
lcurl_easy_t *p = lcurl_geteasy(L);
long val; CURLcode code;
@ -245,7 +247,7 @@ static int lcurl_opt_set_slist_(lua_State *L, int opt, int list_no){
return lcurl_opt_set_long_(L, CURLOPT_##N);\
}
#define OPT_ENTRY(L, N, T, S) LCURL_##T##_OPT(N, S)
#define OPT_ENTRY(L, N, T, S, D) LCURL_##T##_OPT(N, S)
#include "lcopteasy.h"
@ -277,6 +279,8 @@ static int lcurl_easy_set_POSTFIELDS(lua_State *L){
#undef LCURL_LST_OPT
#undef LCURL_LNG_OPT
static int lcurl_hpost_read_callback(char *buffer, size_t size, size_t nitems, void *arg);
static int lcurl_easy_set_HTTPPOST(lua_State *L){
lcurl_easy_t *p = lcurl_geteasy(L);
lcurl_hpost_t *post = lcurl_gethpost_at(L, 2);
@ -287,6 +291,10 @@ static int lcurl_easy_set_HTTPPOST(lua_State *L){
lcurl_storage_preserve_iv(L, p->storage, CURLOPT_HTTPPOST, 2);
if(post->stream){
curl_easy_setopt(p->curl, CURLOPT_READFUNCTION, lcurl_hpost_read_callback);
}
lua_settop(L, 1);
return 1;
}
@ -304,6 +312,182 @@ static int lcurl_easy_set_SHARE(lua_State *L){
lua_settop(L, 1);
return 1;
}
//}
//{ unset
static int lcurl_opt_unset_long_(lua_State *L, int opt, long val){
lcurl_easy_t *p = lcurl_geteasy(L);
CURLcode code;
code = curl_easy_setopt(p->curl, opt, val);
if(code != CURLE_OK){
return lcurl_fail_ex(L, p->err_mode, LCURL_ERROR_EASY, code);
}
lua_settop(L, 1);
return 1;
}
static int lcurl_opt_unset_string_(lua_State *L, int opt, const char *val){
lcurl_easy_t *p = lcurl_geteasy(L);
CURLcode code;
code = curl_easy_setopt(p->curl, opt, val);
if(code != CURLE_OK){
return lcurl_fail_ex(L, p->err_mode, LCURL_ERROR_EASY, code);
}
lcurl_storage_remove_i(L, p->storage, opt);
lua_settop(L, 1);
return 1;
}
static int lcurl_opt_unset_slist_(lua_State *L, int opt, int list_no){
lcurl_easy_t *p = lcurl_geteasy(L);
CURLcode code;
int ref = p->lists[list_no];
code = curl_easy_setopt(p->curl, opt, NULL);
if(code != CURLE_OK){
return lcurl_fail_ex(L, p->err_mode, LCURL_ERROR_EASY, code);
}
if(ref != LUA_NOREF){
struct curl_slist *list = lcurl_storage_remove_slist(L, p->storage, ref);
curl_slist_free_all(list);
p->lists[list_no] = LUA_NOREF;
}
lua_settop(L, 1);
return 1;
}
#define LCURL_STR_OPT(N, S, D) static int lcurl_easy_unset_##N(lua_State *L){\
return lcurl_opt_unset_string_(L, CURLOPT_##N, (D)); \
}
#define LCURL_LST_OPT(N, S, D) static int lcurl_easy_unset_##N(lua_State *L){\
return lcurl_opt_unset_slist_(L, CURLOPT_##N, LCURL_##N##_LIST);\
}
#define LCURL_LNG_OPT(N, S, D) static int lcurl_easy_unset_##N(lua_State *L){\
return lcurl_opt_unset_long_(L, CURLOPT_##N, (D));\
}
#define OPT_ENTRY(L, N, T, S, D) LCURL_##T##_OPT(N, S, D)
#include "lcopteasy.h"
#undef OPT_ENTRY
#undef LCURL_STR_OPT
#undef LCURL_LST_OPT
#undef LCURL_LNG_OPT
static int lcurl_easy_unset_HTTPPOST(lua_State *L){
lcurl_easy_t *p = lcurl_geteasy(L);
CURLcode code = curl_easy_setopt(p->curl, CURLOPT_HTTPPOST, NULL);
if(code != CURLE_OK){
return lcurl_fail_ex(L, p->err_mode, LCURL_ERROR_EASY, code);
}
lcurl_storage_remove_i(L, p->storage, CURLOPT_HTTPPOST);
//! @fixme unset readdata/readfunction for
// curl_easy_setopt(p->curl, CURLOPT_READFUNCTION, 0);
lua_settop(L, 1);
return 1;
}
static int lcurl_easy_unset_SHARE(lua_State *L){
lcurl_easy_t *p = lcurl_geteasy(L);
CURLcode code = curl_easy_setopt(p->curl, CURLOPT_SHARE, NULL);
if(code != CURLE_OK){
return lcurl_fail_ex(L, p->err_mode, LCURL_ERROR_EASY, code);
}
lcurl_storage_remove_i(L, p->storage, CURLOPT_SHARE);
lua_settop(L, 1);
return 1;
}
static int lcurl_easy_unset_WRITEFUNCTION(lua_State *L){
lcurl_easy_t *p = lcurl_geteasy(L);
CURLcode code = curl_easy_setopt(p->curl, CURLOPT_WRITEFUNCTION, NULL);
if(code != CURLE_OK){
return lcurl_fail_ex(L, p->err_mode, LCURL_ERROR_EASY, code);
}
curl_easy_setopt(p->curl, CURLOPT_WRITEDATA, NULL);
lua_settop(L, 1);
return 1;
}
static int lcurl_easy_unset_READFUNCTION(lua_State *L){
lcurl_easy_t *p = lcurl_geteasy(L);
CURLcode code = curl_easy_setopt(p->curl, CURLOPT_READFUNCTION, NULL);
if(code != CURLE_OK){
return lcurl_fail_ex(L, p->err_mode, LCURL_ERROR_EASY, code);
}
curl_easy_setopt(p->curl, CURLOPT_READDATA, NULL);
lua_settop(L, 1);
return 1;
}
static int lcurl_easy_unset_HEADERFUNCTION(lua_State *L){
lcurl_easy_t *p = lcurl_geteasy(L);
CURLcode code = curl_easy_setopt(p->curl, CURLOPT_HEADERFUNCTION, NULL);
if(code != CURLE_OK){
return lcurl_fail_ex(L, p->err_mode, LCURL_ERROR_EASY, code);
}
curl_easy_setopt(p->curl, CURLOPT_HEADERDATA, NULL);
lua_settop(L, 1);
return 1;
}
static int lcurl_easy_unset_PROGRESSFUNCTION(lua_State *L){
lcurl_easy_t *p = lcurl_geteasy(L);
CURLcode code = curl_easy_setopt(p->curl, CURLOPT_PROGRESSFUNCTION, NULL);
if(code != CURLE_OK){
return lcurl_fail_ex(L, p->err_mode, LCURL_ERROR_EASY, code);
}
curl_easy_setopt(p->curl, CURLOPT_PROGRESSDATA, NULL);
#if LCURL_CURL_VER_GE(7,32,0)
curl_easy_setopt(p->curl, CURLOPT_XFERINFOFUNCTION, NULL);
curl_easy_setopt(p->curl, CURLOPT_XFERINFODATA, NULL);
#endif
lua_settop(L, 1);
return 1;
}
static int lcurl_easy_unset_POSTFIELDS(lua_State *L){
lcurl_easy_t *p = lcurl_geteasy(L);
CURLcode code = curl_easy_setopt(p->curl, CURLOPT_POSTFIELDS, NULL);
if(code != CURLE_OK){
return lcurl_fail_ex(L, p->err_mode, LCURL_ERROR_EASY, code);
}
curl_easy_setopt(p->curl, CURLOPT_POSTFIELDSIZE, -1);
lcurl_storage_remove_i(L, p->storage, CURLOPT_POSTFIELDS);
lua_settop(L, 1);
return 1;
}
//}
//}
@ -400,63 +584,12 @@ static int lcurl_easy_set_callback(lua_State *L,
const char *method, void *func
)
{
if(c->ud_ref != LUA_NOREF){
luaL_unref(L, LCURL_LUA_REGISTRY, c->ud_ref);
c->ud_ref = LUA_NOREF;
}
lcurl_set_callback(L, c, 2, method);
if(c->cb_ref != LUA_NOREF){
luaL_unref(L, LCURL_LUA_REGISTRY, c->cb_ref);
c->cb_ref = LUA_NOREF;
}
if(lua_gettop(L) >= 3){// function + context
lua_settop(L, 3);
luaL_argcheck(L, !lua_isnil(L, 2), 2, "no function present");
c->ud_ref = luaL_ref(L, LCURL_LUA_REGISTRY);
c->cb_ref = luaL_ref(L, LCURL_LUA_REGISTRY);
curl_easy_setopt(p->curl, OPT_UD, p);
curl_easy_setopt(p->curl, OPT_CB, func);
assert(1 == lua_gettop(L));
return 1;
}
lua_settop(L, 2);
if(lua_isnoneornil(L, 2)){
lua_pop(L, 1);
assert(1 == lua_gettop(L));
curl_easy_setopt(p->curl, OPT_UD, 0);
curl_easy_setopt(p->curl, OPT_CB, 0);
curl_easy_setopt(p->curl, OPT_CB, (c->cb_ref == LUA_NOREF)?0:func);
curl_easy_setopt(p->curl, OPT_UD, (c->cb_ref == LUA_NOREF)?0:p);
return 1;
}
if(lua_isfunction(L, 2)){
c->cb_ref = luaL_ref(L, LCURL_LUA_REGISTRY);
assert(1 == lua_gettop(L));
curl_easy_setopt(p->curl, OPT_UD, p);
curl_easy_setopt(p->curl, OPT_CB, func);
return 1;
}
if(lua_isuserdata(L, 2) || lua_istable(L, 2)){
lua_getfield(L, 2, method);
luaL_argcheck(L, lua_isfunction(L, -1), 2, "method not found in object");
c->cb_ref = luaL_ref(L, LCURL_LUA_REGISTRY);
c->ud_ref = luaL_ref(L, LCURL_LUA_REGISTRY);
curl_easy_setopt(p->curl, OPT_UD, p);
curl_easy_setopt(p->curl, OPT_CB, func);
assert(1 == lua_gettop(L));
return 1;
}
lua_pushliteral(L, "invalid object type");
return lua_error(L);
}
static int lcurl_write_callback_(lua_State*L,
@ -509,32 +642,32 @@ static int lcurl_easy_set_WRITEFUNCTION(lua_State *L){
//{ Reader
static int lcurl_read_callback(char *buffer, size_t size, size_t nitems, void *arg){
lcurl_easy_t *p = arg;
lua_State *L = p->L;
static int lcurl_read_callback(lua_State *L,
lcurl_callback_t *rd, lcurl_read_buffer_t *rbuffer,
char *buffer, size_t size, size_t nitems
){
const char *data; size_t data_size;
size_t ret = size * nitems;
int n, top = lua_gettop(L);
if(p->rbuffer.ref != LUA_NOREF){
lua_rawgeti(L, LCURL_LUA_REGISTRY, p->rbuffer.ref);
if(rbuffer->ref != LUA_NOREF){
lua_rawgeti(L, LCURL_LUA_REGISTRY, rbuffer->ref);
data = luaL_checklstring(L, -1, &data_size);
lua_pop(L, 1);
data = data + p->rbuffer.off;
data_size -= p->rbuffer.off;
data = data + rbuffer->off;
data_size -= rbuffer->off;
if(data_size > ret){
data_size = ret;
memcpy(buffer, data, data_size);
p->rbuffer.off += data_size;
rbuffer->off += data_size;
}
else{
memcpy(buffer, data, data_size);
luaL_unref(L, LCURL_LUA_REGISTRY, p->rbuffer.ref);
p->rbuffer.ref = LUA_NOREF;
luaL_unref(L, LCURL_LUA_REGISTRY, rbuffer->ref);
rbuffer->ref = LUA_NOREF;
}
lua_settop(L, top);
@ -542,9 +675,9 @@ static int lcurl_read_callback(char *buffer, size_t size, size_t nitems, void *a
}
// buffer is clean
assert(p->rbuffer.ref == LUA_NOREF);
assert(rbuffer->ref == LUA_NOREF);
n = lcurl_util_push_cb(L, &p->rd);
n = lcurl_util_push_cb(L, rd);
lua_pushnumber(L, ret);
if(lua_pcall(L, n, LUA_MULTRET, 0)) return CURL_READFUNC_ABORT;
@ -557,8 +690,8 @@ static int lcurl_read_callback(char *buffer, size_t size, size_t nitems, void *a
if(data_size > ret){
data_size = ret;
p->rbuffer.ref = luaL_ref(L, LCURL_LUA_REGISTRY);
p->rbuffer.off = data_size;
rbuffer->ref = luaL_ref(L, LCURL_LUA_REGISTRY);
rbuffer->off = data_size;
}
memcpy(buffer, data, data_size);
@ -566,11 +699,21 @@ static int lcurl_read_callback(char *buffer, size_t size, size_t nitems, void *a
return data_size;
}
static int lcurl_easy_read_callback(char *buffer, size_t size, size_t nitems, void *arg){
lcurl_easy_t *p = arg;
return lcurl_read_callback(p->L, &p->rd, &p->rbuffer, buffer, size, nitems);
}
static int lcurl_hpost_read_callback(char *buffer, size_t size, size_t nitems, void *arg){
lcurl_hpost_stream_t *p = arg;
return lcurl_read_callback(p->L, &p->rd, &p->rbuffer, buffer, size, nitems);
}
static int lcurl_easy_set_READFUNCTION(lua_State *L){
lcurl_easy_t *p = lcurl_geteasy(L);
return lcurl_easy_set_callback(L, p, &p->rd,
CURLOPT_READFUNCTION, CURLOPT_READDATA,
"read", lcurl_read_callback
"read", lcurl_easy_read_callback
);
}
@ -676,16 +819,39 @@ static int lcurl_easy_setopt(lua_State *L){
opt = luaL_checklong(L, 2);
lua_remove(L, 2);
#define OPT_ENTRY(l, N, T, S) case CURLOPT_##N: return lcurl_easy_set_##N(L);
#define OPT_ENTRY(l, N, T, S, D) case CURLOPT_##N: return lcurl_easy_set_##N(L);
switch(opt){
#include "lcopteasy.h"
OPT_ENTRY(postfields, POSTFIELDS, TTT, 0)
OPT_ENTRY(httppost, HTTPPOST, TTT, 0)
OPT_ENTRY(share, SHARE, TTT, 0)
OPT_ENTRY(writefunction, WRITEFUNCTION, TTT, 0)
OPT_ENTRY(readfunction, READFUNCTION, TTT, 0)
OPT_ENTRY(headerfunction, HEADERFUNCTION, TTT, 0)
OPT_ENTRY(progressfunction, PROGRESSFUNCTION, TTT, 0)
OPT_ENTRY(postfields, POSTFIELDS, TTT, 0, 0)
OPT_ENTRY(httppost, HTTPPOST, TTT, 0, 0)
OPT_ENTRY(share, SHARE, TTT, 0, 0)
OPT_ENTRY(writefunction, WRITEFUNCTION, TTT, 0, 0)
OPT_ENTRY(readfunction, READFUNCTION, TTT, 0, 0)
OPT_ENTRY(headerfunction, HEADERFUNCTION, TTT, 0, 0)
OPT_ENTRY(progressfunction, PROGRESSFUNCTION, TTT, 0, 0)
}
#undef OPT_ENTRY
return lcurl_fail_ex(L, p->err_mode, LCURL_ERROR_EASY, LCURL_E_UNKNOWN_OPTION);
}
static int lcurl_easy_unsetsetopt(lua_State *L){
lcurl_easy_t *p = lcurl_geteasy(L);
long opt;
opt = luaL_checklong(L, 2);
lua_remove(L, 2);
#define OPT_ENTRY(l, N, T, S, D) case CURLOPT_##N: return lcurl_easy_unset_##N(L);
switch(opt){
#include "lcopteasy.h"
OPT_ENTRY(postfields, POSTFIELDS, TTT, 0, 0)
OPT_ENTRY(httppost, HTTPPOST, TTT, 0, 0)
OPT_ENTRY(share, SHARE, TTT, 0, 0)
OPT_ENTRY(writefunction, WRITEFUNCTION, TTT, 0, 0)
OPT_ENTRY(readfunction, READFUNCTION, TTT, 0, 0)
OPT_ENTRY(headerfunction, HEADERFUNCTION, TTT, 0, 0)
OPT_ENTRY(progressfunction, PROGRESSFUNCTION, TTT, 0, 0)
}
#undef OPT_ENTRY
@ -710,15 +876,26 @@ static int lcurl_easy_getinfo(lua_State *L){
static const struct luaL_Reg lcurl_easy_methods[] = {
#define OPT_ENTRY(L, N, T, S) { "setopt_"#L, lcurl_easy_set_##N },
#define OPT_ENTRY(L, N, T, S, D) { "setopt_"#L, lcurl_easy_set_##N },
#include "lcopteasy.h"
OPT_ENTRY(postfields, POSTFIELDS, TTT, 0)
OPT_ENTRY(httppost, HTTPPOST, TTT, 0)
OPT_ENTRY(share, SHARE, TTT, 0)
OPT_ENTRY(writefunction, WRITEFUNCTION, TTT, 0)
OPT_ENTRY(readfunction, READFUNCTION, TTT, 0)
OPT_ENTRY(headerfunction, HEADERFUNCTION, TTT, 0)
OPT_ENTRY(progressfunction, PROGRESSFUNCTION, TTT, 0)
OPT_ENTRY(postfields, POSTFIELDS, TTT, 0, 0)
OPT_ENTRY(httppost, HTTPPOST, TTT, 0, 0)
OPT_ENTRY(share, SHARE, TTT, 0, 0)
OPT_ENTRY(writefunction, WRITEFUNCTION, TTT, 0, 0)
OPT_ENTRY(readfunction, READFUNCTION, TTT, 0, 0)
OPT_ENTRY(headerfunction, HEADERFUNCTION, TTT, 0, 0)
OPT_ENTRY(progressfunction, PROGRESSFUNCTION, TTT, 0, 0)
#undef OPT_ENTRY
#define OPT_ENTRY(L, N, T, S, D) { "unsetopt_"#L, lcurl_easy_unset_##N },
#include "lcopteasy.h"
OPT_ENTRY(postfields, POSTFIELDS, TTT, 0, 0)
OPT_ENTRY(httppost, HTTPPOST, TTT, 0, 0)
OPT_ENTRY(share, SHARE, TTT, 0, 0)
OPT_ENTRY(writefunction, WRITEFUNCTION, TTT, 0, 0)
OPT_ENTRY(readfunction, READFUNCTION, TTT, 0, 0)
OPT_ENTRY(headerfunction, HEADERFUNCTION, TTT, 0, 0)
OPT_ENTRY(progressfunction, PROGRESSFUNCTION, TTT, 0, 0)
#undef OPT_ENTRY
#define OPT_ENTRY(L, N, T, S) { "getinfo_"#L, lcurl_easy_get_##N },
@ -739,16 +916,16 @@ static const struct luaL_Reg lcurl_easy_methods[] = {
static const lcurl_const_t lcurl_easy_opt[] = {
#define OPT_ENTRY(L, N, T, S) { "OPT_"#N, CURLOPT_##N },
#define OPT_ENTRY(L, N, T, S, D) { "OPT_"#N, CURLOPT_##N },
#define FLG_ENTRY(N) { #N, CURL_##N },
#include "lcopteasy.h"
OPT_ENTRY(postfields, POSTFIELDS, TTT, 0)
OPT_ENTRY(httppost, HTTPPOST, TTT, 0)
OPT_ENTRY(share, SHARE, TTT, 0)
OPT_ENTRY(writefunction, WRITEFUNCTION, TTT, 0)
OPT_ENTRY(readfunction, READFUNCTION, TTT, 0)
OPT_ENTRY(headerfunction, HEADERFUNCTION, TTT, 0)
OPT_ENTRY(progressfunction, PROGRESSFUNCTION, TTT, 0)
OPT_ENTRY(postfields, POSTFIELDS, TTT, 0, 0)
OPT_ENTRY(httppost, HTTPPOST, TTT, 0, 0)
OPT_ENTRY(share, SHARE, TTT, 0, 0)
OPT_ENTRY(writefunction, WRITEFUNCTION, TTT, 0, 0)
OPT_ENTRY(readfunction, READFUNCTION, TTT, 0, 0)
OPT_ENTRY(headerfunction, HEADERFUNCTION, TTT, 0, 0)
OPT_ENTRY(progressfunction, PROGRESSFUNCTION, TTT, 0, 0)
#undef OPT_ENTRY
#undef FLG_ENTRY

View File

@ -7,7 +7,7 @@
#define LCURL_LST_INDEX(N) LCURL_##N##_LIST,
#define LCURL_STR_INDEX(N)
#define LCURL_LNG_INDEX(N)
#define OPT_ENTRY(L, N, T, S) LCURL_##T##_INDEX(N)
#define OPT_ENTRY(L, N, T, S, D) LCURL_##T##_INDEX(N)
enum {
LCURL_LIST_DUMMY = -1,
@ -22,11 +22,6 @@ enum {
#undef LCURL_LNG_INDEX
#undef OPT_ENTRY
typedef struct lcurl_read_buffer_tag{
int ref;
int off;
}lcurl_read_buffer_t;
typedef struct lcurl_easy_tag{
lua_State *L;
CURL *curl;

View File

@ -13,6 +13,7 @@ int lcurl_hpost_create(lua_State *L, int error_mode){
p->post = p->last = 0;
p->storage = lcurl_storage_init(L);
p->err_mode = error_mode;
p->stream = 0;
return 1;
}
@ -153,6 +154,130 @@ static int lcurl_hpost_add_file(lua_State *L){
return 1;
}
static lcurl_hpost_stream_t *lcurl_hpost_stream_add(lua_State *L, lcurl_hpost_t *p){
lcurl_hpost_stream_t *ptr = p->stream;
lcurl_hpost_stream_t *stream = malloc(sizeof(lcurl_hpost_stream_t));
if(!stream) return NULL;
stream->L = L;
stream->rbuffer.ref = LUA_NOREF;
stream->rd.cb_ref = stream->rd.ud_ref = LUA_NOREF;
stream->next = NULL;
if(!p->stream) p->stream = stream;
else{
while(ptr->next) ptr = ptr->next;
ptr->next = stream;
}
return stream;
}
static void lcurl_hpost_stream_free(lua_State *L, lcurl_hpost_stream_t *ptr){
if(ptr){
luaL_unref(L, LCURL_LUA_REGISTRY, ptr->rbuffer.ref);
luaL_unref(L, LCURL_LUA_REGISTRY, ptr->rd.cb_ref);
luaL_unref(L, LCURL_LUA_REGISTRY, ptr->rd.ud_ref);
free(ptr);
}
}
static void lcurl_hpost_stream_free_last(lua_State *L, lcurl_hpost_t *p){
lcurl_hpost_stream_t *ptr = p->stream;
if(!ptr) return;
if(!ptr->next){
lcurl_hpost_stream_free(L, ptr);
p->stream = 0;
}
while(ptr->next->next) ptr = ptr->next;
lcurl_hpost_stream_free(L, ptr->next);
ptr->next = NULL;
}
static void lcurl_hpost_stream_free_all(lua_State *L, lcurl_hpost_t *p){
lcurl_hpost_stream_t *ptr = p->stream;
while(ptr){
lcurl_hpost_stream_t *next = ptr->next;
lcurl_hpost_stream_free(L, ptr);
ptr = next;
}
p->stream = 0;
}
static int lcurl_hpost_add_stream(lua_State *L){
// add_stream(name, [filename, [type,]] [headers,] size, reader [,context])
lcurl_hpost_t *p = lcurl_gethpost(L);
size_t name_len; const char *name = luaL_checklstring(L, 2, &name_len);
struct curl_slist *list = NULL; int ilist = 0;
const char *type = 0, *fname = 0;
size_t len;
CURLFORMcode code;
lcurl_callback_t rd = {LUA_NOREF, LUA_NOREF};
lcurl_hpost_stream_t *stream;
int n = 0, i = 3;
struct curl_forms forms[4];
while(1){ // [filename, [type,]] [headers,]
if(lua_isnone(L, i)){
lua_pushliteral(L, "stream size required");
lua_error(L);
}
if(lua_type(L, i) == LUA_TNUMBER){
break;
}
if(lua_type(L, i) == LUA_TTABLE){
ilist = i++;
break;
}
else if(!fname) fname = luaL_checkstring(L, i);
else if(!type) type = luaL_checkstring(L, i);
else{
lua_pushliteral(L, "stream size required");
lua_error(L);
}
++i;
}
len = luaL_checklong(L, i);
lcurl_set_callback(L, &rd, i + 1, "read");
luaL_argcheck(L, rd.cb_ref != LUA_NOREF, i + 1, "function expected");
if(ilist) list = lcurl_util_to_slist(L, ilist);
n = 0;
if(fname){ forms[n].option = CURLFORM_FILENAME; forms[n++].value = fname; }
if(type) { forms[n].option = CURLFORM_CONTENTTYPE; forms[n++].value = type; }
if(list) { forms[n].option = CURLFORM_CONTENTHEADER; forms[n++].value = (char*)list; }
forms[n].option = CURLFORM_END;
stream = lcurl_hpost_stream_add(L, p);
if(!stream){
if(list) curl_slist_free_all(list);
return lcurl_fail_ex(L, p->err_mode, LCURL_ERROR_FORM, CURL_FORMADD_MEMORY);
}
stream->rd = rd;
code = curl_formadd(&p->post, &p->last,
CURLFORM_PTRNAME, name, CURLFORM_NAMELENGTH, name_len,
CURLFORM_STREAM, stream, CURLFORM_CONTENTSLENGTH, len,
CURLFORM_ARRAY, forms,
CURLFORM_END
);
if(code != CURL_FORMADD_OK){
lcurl_hpost_stream_free_last(L, p);
return lcurl_fail_ex(L, p->err_mode, LCURL_ERROR_FORM, code);
}
lcurl_storage_preserve_value(L, p->storage, 2);
if(list) lcurl_storage_preserve_slist (L, p->storage, list);
lua_settop(L, 1);
return 1;
}
static int lcurl_hpost_add_files(lua_State *L){
lcurl_hpost_t *p = lcurl_gethpost(L);
size_t name_len; const char *name = luaL_checklstring(L, 2, &name_len);
@ -364,6 +489,8 @@ static int lcurl_hpost_free(lua_State *L){
p->storage = lcurl_storage_free(L, p->storage);
}
lcurl_hpost_stream_free_all(L, p);
return 0;
}
@ -373,6 +500,7 @@ static const struct luaL_Reg lcurl_hpost_methods[] = {
{"add_content", lcurl_hpost_add_content },
{"add_buffer", lcurl_hpost_add_buffer },
{"add_file", lcurl_hpost_add_file },
{"add_stream", lcurl_hpost_add_stream },
{"add_files", lcurl_hpost_add_files },

View File

@ -2,13 +2,22 @@
#define _LCHTTPPOST_H_
#include "lcurl.h"
#include "lcutils.h"
#include <stdlib.h>
typedef struct lcurl_hpost_stream_tag{
lua_State *L;
lcurl_callback_t rd;
lcurl_read_buffer_t rbuffer;
struct lcurl_hpost_stream_tag *next;
}lcurl_hpost_stream_t;
typedef struct lcurl_hpost_tag{
struct curl_httppost *post;
struct curl_httppost *last;
int storage;
int err_mode;
lcurl_hpost_stream_t *stream;
}lcurl_hpost_t;
int lcurl_hpost_create(lua_State *L, int error_mode);

View File

@ -297,63 +297,12 @@ static int lcurl_multi_set_callback(lua_State *L,
const char *method, void *func
)
{
if(c->ud_ref != LUA_NOREF){
luaL_unref(L, LCURL_LUA_REGISTRY, c->ud_ref);
c->ud_ref = LUA_NOREF;
}
lcurl_set_callback(L, c, 2, method);
if(c->cb_ref != LUA_NOREF){
luaL_unref(L, LCURL_LUA_REGISTRY, c->cb_ref);
c->cb_ref = LUA_NOREF;
}
if(lua_gettop(L) >= 3){// function + context
lua_settop(L, 3);
luaL_argcheck(L, !lua_isnil(L, 2), 2, "no function present");
c->ud_ref = luaL_ref(L, LCURL_LUA_REGISTRY);
c->cb_ref = luaL_ref(L, LCURL_LUA_REGISTRY);
curl_multi_setopt(p->curl, OPT_UD, p);
curl_multi_setopt(p->curl, OPT_CB, func);
assert(1 == lua_gettop(L));
return 1;
}
lua_settop(L, 2);
if(lua_isnoneornil(L, 2)){
lua_pop(L, 1);
assert(1 == lua_gettop(L));
curl_multi_setopt(p->curl, OPT_UD, 0);
curl_multi_setopt(p->curl, OPT_CB, 0);
curl_multi_setopt(p->curl, OPT_CB, (c->cb_ref == LUA_NOREF)?0:func);
curl_multi_setopt(p->curl, OPT_UD, (c->cb_ref == LUA_NOREF)?0:p);
return 1;
}
if(lua_isfunction(L, 2)){
c->cb_ref = luaL_ref(L, LCURL_LUA_REGISTRY);
assert(1 == lua_gettop(L));
curl_multi_setopt(p->curl, OPT_UD, p);
curl_multi_setopt(p->curl, OPT_CB, func);
return 1;
}
if(lua_isuserdata(L, 2) || lua_istable(L, 2)){
lua_getfield(L, 2, method);
luaL_argcheck(L, lua_isfunction(L, -1), 2, "method not found in object");
c->cb_ref = luaL_ref(L, LCURL_LUA_REGISTRY);
c->ud_ref = luaL_ref(L, LCURL_LUA_REGISTRY);
curl_multi_setopt(p->curl, OPT_UD, p);
curl_multi_setopt(p->curl, OPT_CB, func);
assert(1 == lua_gettop(L));
return 1;
}
lua_pushliteral(L, "invalid object type");
return lua_error(L);
}
//{Timer

View File

@ -17,7 +17,7 @@
#endif
#ifndef OPT_ENTRY
# define OPT_ENTRY(a,b,c,d)
# define OPT_ENTRY(a,b,c,d,e)
# define OPT_ENTRY_IS_NULL
#endif
@ -26,214 +26,218 @@
# define FLG_ENTRY_IS_NULL
#endif
OPT_ENTRY( verbose, VERBOSE, LNG, 0 )
OPT_ENTRY( header, HEADER, LNG, 0 )
OPT_ENTRY( noprogress, NOPROGRESS, LNG, 0 )
OPT_ENTRY( nosignal, NOSIGNAL, LNG, 0 )
#ifndef LCURL_DEFAULT_VALUE
# define LCURL_DEFAULT_VALUE 0
#endif
OPT_ENTRY( verbose, VERBOSE, LNG, 0, LCURL_DEFAULT_VALUE )
OPT_ENTRY( header, HEADER, LNG, 0, LCURL_DEFAULT_VALUE )
OPT_ENTRY( noprogress, NOPROGRESS, LNG, 0, 1 )
OPT_ENTRY( nosignal, NOSIGNAL, LNG, 0, LCURL_DEFAULT_VALUE )
#if LCURL_CURL_VER_GE(7,21,0)
OPT_ENTRY( wildcardmatch, WILDCARDMATCH, LNG, 0 )
OPT_ENTRY( wildcardmatch, WILDCARDMATCH, LNG, 0, LCURL_DEFAULT_VALUE )
#endif
OPT_ENTRY( url, URL, STR, LCURL_STORE_STRING )
OPT_ENTRY( failonerror, FAILONERROR, LNG, 0 )
OPT_ENTRY( url, URL, STR, LCURL_STORE_STRING, LCURL_DEFAULT_VALUE )
OPT_ENTRY( failonerror, FAILONERROR, LNG, 0, LCURL_DEFAULT_VALUE )
OPT_ENTRY( protocols, PROTOCOLS, LNG, 0 )
OPT_ENTRY( redir_protocols, REDIR_PROTOCOLS, LNG, 0 )
OPT_ENTRY( proxy, PROXY, STR, LCURL_STORE_STRING )
OPT_ENTRY( proxyport, PROXYPORT, LNG, 0 )
OPT_ENTRY( proxytype, PROXYTYPE, LNG, 0 )
OPT_ENTRY( noproxy, NOPROXY, STR, LCURL_STORE_STRING )
OPT_ENTRY( httpproxytunnel, HTTPPROXYTUNNEL, LNG, 0 )
OPT_ENTRY( socks5_gssapi_service, SOCKS5_GSSAPI_SERVICE, STR, LCURL_STORE_STRING )
OPT_ENTRY( socks5_gssapi_nec, SOCKS5_GSSAPI_NEC, LNG, 0 )
OPT_ENTRY( interface, INTERFACE, STR, LCURL_STORE_STRING )
OPT_ENTRY( localport, LOCALPORT, LNG, 0 )
OPT_ENTRY( localportrange, LOCALPORTRANGE, LNG, 0 )
OPT_ENTRY( dns_cache_timeout, DNS_CACHE_TIMEOUT, LNG, 0 )
OPT_ENTRY( dns_use_global_cache, DNS_USE_GLOBAL_CACHE, LNG, 0 )
OPT_ENTRY( protocols, PROTOCOLS, LNG, 0, CURLPROTO_ALL )
OPT_ENTRY( redir_protocols, REDIR_PROTOCOLS, LNG, 0, CURLPROTO_ALL ) /*! @fixme All protocols except for FILE and SCP */
OPT_ENTRY( proxy, PROXY, STR, LCURL_STORE_STRING, LCURL_DEFAULT_VALUE )
OPT_ENTRY( proxyport, PROXYPORT, LNG, 0, LCURL_DEFAULT_VALUE )
OPT_ENTRY( proxytype, PROXYTYPE, LNG, 0, CURLPROXY_HTTP )
OPT_ENTRY( noproxy, NOPROXY, STR, LCURL_STORE_STRING, LCURL_DEFAULT_VALUE )
OPT_ENTRY( httpproxytunnel, HTTPPROXYTUNNEL, LNG, 0, LCURL_DEFAULT_VALUE )
OPT_ENTRY( socks5_gssapi_service, SOCKS5_GSSAPI_SERVICE, STR, LCURL_STORE_STRING, "rcmd/server-fqdn" )
OPT_ENTRY( socks5_gssapi_nec, SOCKS5_GSSAPI_NEC, LNG, 0, LCURL_DEFAULT_VALUE ) /*! @check doc says nothing */
OPT_ENTRY( interface, INTERFACE, STR, LCURL_STORE_STRING, LCURL_DEFAULT_VALUE )
OPT_ENTRY( localport, LOCALPORT, LNG, 0, LCURL_DEFAULT_VALUE )
OPT_ENTRY( localportrange, LOCALPORTRANGE, LNG, 0, 1 )
OPT_ENTRY( dns_cache_timeout, DNS_CACHE_TIMEOUT, LNG, 0, 60 )
OPT_ENTRY( dns_use_global_cache, DNS_USE_GLOBAL_CACHE, LNG, 0, LCURL_DEFAULT_VALUE )
#if LCURL_CURL_VER_GE(7,25,0)
OPT_ENTRY( dns_servers, DNS_SERVERS, STR, LCURL_STORE_STRING )
OPT_ENTRY( dns_servers, DNS_SERVERS, STR, LCURL_STORE_STRING, LCURL_DEFAULT_VALUE )
#endif
OPT_ENTRY( buffersize, BUFFERSIZE, LNG, 0 )
OPT_ENTRY( port, PORT, LNG, 0 )
OPT_ENTRY( tcp_nodelay, TCP_NODELAY, LNG, 0 )
OPT_ENTRY( address_scope, ADDRESS_SCOPE, LNG, 0 )
OPT_ENTRY( buffersize, BUFFERSIZE, LNG, 0, CURL_MAX_WRITE_SIZE )
OPT_ENTRY( port, PORT, LNG, 0, LCURL_DEFAULT_VALUE )
OPT_ENTRY( tcp_nodelay, TCP_NODELAY, LNG, 0, LCURL_DEFAULT_VALUE )
OPT_ENTRY( address_scope, ADDRESS_SCOPE, LNG, 0, LCURL_DEFAULT_VALUE )
#if LCURL_CURL_VER_GE(7,25,0)
OPT_ENTRY( tcp_keepalive, TCP_KEEPALIVE, LNG, 0 )
OPT_ENTRY( tcp_keepidle, TCP_KEEPIDLE, LNG, 0 )
OPT_ENTRY( tcp_keepintvl, TCP_KEEPINTVL, LNG, 0 )
OPT_ENTRY( tcp_keepalive, TCP_KEEPALIVE, LNG, 0, LCURL_DEFAULT_VALUE )
OPT_ENTRY( tcp_keepidle, TCP_KEEPIDLE, LNG, 0, LCURL_DEFAULT_VALUE ) /*! @check doc says nothing */
OPT_ENTRY( tcp_keepintvl, TCP_KEEPINTVL, LNG, 0, LCURL_DEFAULT_VALUE ) /*! @check doc says nothing */
#endif
OPT_ENTRY( netrc, NETRC, LNG, 0 )
OPT_ENTRY( netrc_file, NETRC_FILE, STR, LCURL_STORE_STRING )
OPT_ENTRY( userpwd, USERPWD, STR, LCURL_STORE_STRING )
OPT_ENTRY( proxyuserpwd, PROXYUSERPWD, STR, LCURL_STORE_STRING )
OPT_ENTRY( username, USERNAME, STR, LCURL_STORE_STRING )
OPT_ENTRY( password, PASSWORD, STR, LCURL_STORE_STRING )
OPT_ENTRY( netrc, NETRC, LNG, 0, CURL_NETRC_IGNORED )
OPT_ENTRY( netrc_file, NETRC_FILE, STR, LCURL_STORE_STRING, LCURL_DEFAULT_VALUE )
OPT_ENTRY( userpwd, USERPWD, STR, LCURL_STORE_STRING, LCURL_DEFAULT_VALUE )
OPT_ENTRY( proxyuserpwd, PROXYUSERPWD, STR, LCURL_STORE_STRING, LCURL_DEFAULT_VALUE )
OPT_ENTRY( username, USERNAME, STR, LCURL_STORE_STRING, LCURL_DEFAULT_VALUE )
OPT_ENTRY( password, PASSWORD, STR, LCURL_STORE_STRING, LCURL_DEFAULT_VALUE )
#if LCURL_CURL_VER_GE(7,31,0)
OPT_ENTRY( login_options, LOGIN_OPTIONS, STR, LCURL_STORE_STRING )
OPT_ENTRY( login_options, LOGIN_OPTIONS, STR, LCURL_STORE_STRING, LCURL_DEFAULT_VALUE )
#endif
OPT_ENTRY( proxyusername, PROXYUSERNAME, STR, LCURL_STORE_STRING )
OPT_ENTRY( proxypassword, PROXYPASSWORD, STR, LCURL_STORE_STRING )
OPT_ENTRY( httpauth, HTTPAUTH, LNG, 0 )
OPT_ENTRY( proxyusername, PROXYUSERNAME, STR, LCURL_STORE_STRING, LCURL_DEFAULT_VALUE )
OPT_ENTRY( proxypassword, PROXYPASSWORD, STR, LCURL_STORE_STRING, LCURL_DEFAULT_VALUE )
OPT_ENTRY( httpauth, HTTPAUTH, LNG, 0, CURLAUTH_BASIC )
#if LCURL_CURL_VER_GE(7,21,4)
OPT_ENTRY( tlsauth_username, TLSAUTH_USERNAME, STR, LCURL_STORE_STRING )
OPT_ENTRY( tlsauth_password, TLSAUTH_PASSWORD, STR, LCURL_STORE_STRING )
OPT_ENTRY( tlsauth_type, TLSAUTH_TYPE, LNG, 0 )
OPT_ENTRY( tlsauth_username, TLSAUTH_USERNAME, STR, LCURL_STORE_STRING, LCURL_DEFAULT_VALUE )
OPT_ENTRY( tlsauth_password, TLSAUTH_PASSWORD, STR, LCURL_STORE_STRING, LCURL_DEFAULT_VALUE )
OPT_ENTRY( tlsauth_type, TLSAUTH_TYPE, LNG, 0, CURL_TLSAUTH_NONE )
#endif
OPT_ENTRY( proxyauth, PROXYAUTH, LNG, 0 )
OPT_ENTRY( proxyauth, PROXYAUTH, LNG, 0, CURLAUTH_BASIC )
#if LCURL_CURL_VER_GE(7,31,0)
OPT_ENTRY( sasl_ir, SASL_IR, LNG, 0 )
OPT_ENTRY( sasl_ir, SASL_IR, LNG, 0, LCURL_DEFAULT_VALUE )
#endif
#if LCURL_CURL_VER_GE(7,33,0)
OPT_ENTRY( xoauth2_bearer, XOAUTH2_BEARER, STR, LCURL_STORE_STRING )
OPT_ENTRY( xoauth2_bearer, XOAUTH2_BEARER, STR, LCURL_STORE_STRING, LCURL_DEFAULT_VALUE )
#endif
OPT_ENTRY( autoreferer, AUTOREFERER, LNG, 0 )
OPT_ENTRY( autoreferer, AUTOREFERER, LNG, 0, LCURL_DEFAULT_VALUE )
#if LCURL_CURL_VER_GE(7,21,6)
OPT_ENTRY( accept_encoding, ACCEPT_ENCODING, STR, LCURL_STORE_STRING )
OPT_ENTRY( transfer_encoding, TRANSFER_ENCODING, LNG, 0 )
OPT_ENTRY( accept_encoding, ACCEPT_ENCODING, STR, LCURL_STORE_STRING, LCURL_DEFAULT_VALUE )
OPT_ENTRY( transfer_encoding, TRANSFER_ENCODING, LNG, 0, LCURL_DEFAULT_VALUE )
#endif
OPT_ENTRY( followlocation, FOLLOWLOCATION, LNG, 0 )
OPT_ENTRY( unrestricted_auth, UNRESTRICTED_AUTH, LNG, 0 )
OPT_ENTRY( maxredirs, MAXREDIRS, LNG, 0 )
OPT_ENTRY( postredir, POSTREDIR, LNG, 0 )
OPT_ENTRY( put, PUT, LNG, 0 )
OPT_ENTRY( post, POST, LNG, 0 )
OPT_ENTRY( referer, REFERER, STR, LCURL_STORE_STRING )
OPT_ENTRY( useragent, USERAGENT, STR, LCURL_STORE_STRING )
OPT_ENTRY( followlocation, FOLLOWLOCATION, LNG, 0, LCURL_DEFAULT_VALUE )
OPT_ENTRY( unrestricted_auth, UNRESTRICTED_AUTH, LNG, 0, LCURL_DEFAULT_VALUE )
OPT_ENTRY( maxredirs, MAXREDIRS, LNG, 0, -1 )
OPT_ENTRY( postredir, POSTREDIR, LNG, 0, LCURL_DEFAULT_VALUE )
OPT_ENTRY( put, PUT, LNG, 0, LCURL_DEFAULT_VALUE )
OPT_ENTRY( post, POST, LNG, 0, LCURL_DEFAULT_VALUE )
OPT_ENTRY( referer, REFERER, STR, LCURL_STORE_STRING, LCURL_DEFAULT_VALUE )
OPT_ENTRY( useragent, USERAGENT, STR, LCURL_STORE_STRING, LCURL_DEFAULT_VALUE )
#if LCURL_CURL_VER_GE(7,37,0)
OPT_ENTRY( headeropt, HEADEROPT, LNG, 0 )
OPT_ENTRY( headeropt, HEADEROPT, LNG, 0, CURLHEADER_UNIFIED )
#endif
OPT_ENTRY( httpheader, HTTPHEADER, LST, 0 )
OPT_ENTRY( httpheader, HTTPHEADER, LST, 0, LCURL_DEFAULT_VALUE )
#if LCURL_CURL_VER_GE(7,37,0)
OPT_ENTRY( proxyheader, PROXYHEADER, LST, 0 )
OPT_ENTRY( proxyheader, PROXYHEADER, LST, 0, LCURL_DEFAULT_VALUE )
#endif
OPT_ENTRY( http200aliases, HTTP200ALIASES, LST, 0 )
OPT_ENTRY( cookie, COOKIE, STR, LCURL_STORE_STRING )
OPT_ENTRY( cookiefile, COOKIEFILE, STR, LCURL_STORE_STRING )
OPT_ENTRY( cookiejar, COOKIEJAR, STR, LCURL_STORE_STRING )
OPT_ENTRY( cookiesession, COOKIESESSION, LNG, 0 )
OPT_ENTRY( cookielist, COOKIELIST, STR, LCURL_STORE_STRING )
OPT_ENTRY( httpget, HTTPGET, LNG, 0 )
OPT_ENTRY( http_version, HTTP_VERSION, LNG, 0 )
OPT_ENTRY( ignore_content_length, IGNORE_CONTENT_LENGTH, LNG, 0 )
OPT_ENTRY( http_content_decoding, HTTP_CONTENT_DECODING, LNG, 0 )
OPT_ENTRY( http_transfer_decoding, HTTP_TRANSFER_DECODING, LNG, 0 )
OPT_ENTRY( http200aliases, HTTP200ALIASES, LST, 0, LCURL_DEFAULT_VALUE )
OPT_ENTRY( cookie, COOKIE, STR, LCURL_STORE_STRING, LCURL_DEFAULT_VALUE )
OPT_ENTRY( cookiefile, COOKIEFILE, STR, LCURL_STORE_STRING, LCURL_DEFAULT_VALUE )
OPT_ENTRY( cookiejar, COOKIEJAR, STR, LCURL_STORE_STRING, LCURL_DEFAULT_VALUE )
OPT_ENTRY( cookiesession, COOKIESESSION, LNG, 0, LCURL_DEFAULT_VALUE )
OPT_ENTRY( cookielist, COOKIELIST, STR, LCURL_STORE_STRING, LCURL_DEFAULT_VALUE )
OPT_ENTRY( httpget, HTTPGET, LNG, 0, LCURL_DEFAULT_VALUE )
OPT_ENTRY( http_version, HTTP_VERSION, LNG, 0, CURL_HTTP_VERSION_NONE )
OPT_ENTRY( ignore_content_length, IGNORE_CONTENT_LENGTH, LNG, 0, LCURL_DEFAULT_VALUE )
OPT_ENTRY( http_content_decoding, HTTP_CONTENT_DECODING, LNG, 0, 1 )
OPT_ENTRY( http_transfer_decoding, HTTP_TRANSFER_DECODING, LNG, 0, 1 )
#if LCURL_CURL_VER_GE(7,36,0)
OPT_ENTRY( expect_100_timeout_ms, EXPECT_100_TIMEOUT_MS, LNG, 0 )
OPT_ENTRY( expect_100_timeout_ms, EXPECT_100_TIMEOUT_MS, LNG, 0, 1000 )
#endif
#if LCURL_CURL_VER_GE(7,20,0)
OPT_ENTRY( mail_from, MAIL_FROM, STR, LCURL_STORE_STRING )
OPT_ENTRY( mail_rcpt, MAIL_RCPT, STR, LCURL_STORE_STRING )
OPT_ENTRY( mail_from, MAIL_FROM, STR, LCURL_STORE_STRING, LCURL_DEFAULT_VALUE ) /*! @check doc says `blank` */
OPT_ENTRY( mail_rcpt, MAIL_RCPT, STR, LCURL_STORE_STRING, LCURL_DEFAULT_VALUE )
#endif
#if LCURL_CURL_VER_GE(7,25,0)
OPT_ENTRY( mail_auth, MAIL_AUTH, STR, LCURL_STORE_STRING )
OPT_ENTRY( mail_auth, MAIL_AUTH, STR, LCURL_STORE_STRING, LCURL_DEFAULT_VALUE )
#endif
OPT_ENTRY( tftp_blksize, TFTP_BLKSIZE, LNG, 0 )
OPT_ENTRY( tftp_blksize, TFTP_BLKSIZE, LNG, 0, 512 )
OPT_ENTRY( ftpport, FTPPORT, STR, LCURL_STORE_STRING )
OPT_ENTRY( quote, QUOTE, LST, 0 )
OPT_ENTRY( postquote, POSTQUOTE, LST, 0 )
OPT_ENTRY( prequote, PREQUOTE, STR, LCURL_STORE_STRING )
OPT_ENTRY( dirlistonly, DIRLISTONLY, LNG, 0 )
OPT_ENTRY( append, APPEND, LNG, 0 )
OPT_ENTRY( ftp_use_eprt, FTP_USE_EPRT, LNG, 0 )
OPT_ENTRY( ftp_use_epsv, FTP_USE_EPSV, LNG, 0 )
OPT_ENTRY( ftpport, FTPPORT, STR, LCURL_STORE_STRING, LCURL_DEFAULT_VALUE )
OPT_ENTRY( quote, QUOTE, LST, 0, LCURL_DEFAULT_VALUE )
OPT_ENTRY( postquote, POSTQUOTE, LST, 0, LCURL_DEFAULT_VALUE )
OPT_ENTRY( prequote, PREQUOTE, STR, LCURL_STORE_STRING, LCURL_DEFAULT_VALUE )
OPT_ENTRY( dirlistonly, DIRLISTONLY, LNG, 0, LCURL_DEFAULT_VALUE )
OPT_ENTRY( append, APPEND, LNG, 0, LCURL_DEFAULT_VALUE )
OPT_ENTRY( ftp_use_eprt, FTP_USE_EPRT, LNG, 0, LCURL_DEFAULT_VALUE )/*! @check doc says nothing */
OPT_ENTRY( ftp_use_epsv, FTP_USE_EPSV, LNG, 0, 1 )
#if LCURL_CURL_VER_GE(7,20,0)
OPT_ENTRY( ftp_use_pret, FTP_USE_PRET, LNG, 0 )
OPT_ENTRY( ftp_use_pret, FTP_USE_PRET, LNG, 0, LCURL_DEFAULT_VALUE )
#endif
OPT_ENTRY( ftp_create_missing_dirs, FTP_CREATE_MISSING_DIRS, LNG, 0 )
OPT_ENTRY( ftp_response_timeout, FTP_RESPONSE_TIMEOUT, LNG, 0 )
OPT_ENTRY( ftp_alternative_to_user, FTP_ALTERNATIVE_TO_USER, STR, LCURL_STORE_STRING )
OPT_ENTRY( ftp_skip_pasv_ip, FTP_SKIP_PASV_IP, LNG, 0 )
OPT_ENTRY( ftpsslauth, FTPSSLAUTH, LNG, 0 )
OPT_ENTRY( ftp_ssl_ccc, FTP_SSL_CCC, LNG, 0 )
OPT_ENTRY( ftp_account, FTP_ACCOUNT, STR, LCURL_STORE_STRING )
OPT_ENTRY( ftp_filemethod, FTP_FILEMETHOD, LNG, 0 )
OPT_ENTRY( ftp_create_missing_dirs, FTP_CREATE_MISSING_DIRS, LNG, 0, CURLFTP_CREATE_DIR_NONE )
OPT_ENTRY( ftp_response_timeout, FTP_RESPONSE_TIMEOUT, LNG, 0, LCURL_DEFAULT_VALUE ) /*! @fixme doc says `None` */
OPT_ENTRY( ftp_alternative_to_user, FTP_ALTERNATIVE_TO_USER, STR, LCURL_STORE_STRING, LCURL_DEFAULT_VALUE )
OPT_ENTRY( ftp_skip_pasv_ip, FTP_SKIP_PASV_IP, LNG, 0, LCURL_DEFAULT_VALUE )
OPT_ENTRY( ftpsslauth, FTPSSLAUTH, LNG, 0, CURLFTPAUTH_DEFAULT )
OPT_ENTRY( ftp_ssl_ccc, FTP_SSL_CCC, LNG, 0, CURLFTPSSL_CCC_NONE )
OPT_ENTRY( ftp_account, FTP_ACCOUNT, STR, LCURL_STORE_STRING, LCURL_DEFAULT_VALUE )
OPT_ENTRY( ftp_filemethod, FTP_FILEMETHOD, LNG, 0, CURLFTPMETHOD_MULTICWD )
OPT_ENTRY( transfertext, TRANSFERTEXT, LNG, 0 )
OPT_ENTRY( proxy_transfer_mode, PROXY_TRANSFER_MODE, LNG, 0 )
OPT_ENTRY( crlf, CRLF, LNG, 0 )
OPT_ENTRY( range, RANGE, STR, LCURL_STORE_STRING )
OPT_ENTRY( resume_from, RESUME_FROM, LNG, 0 )
OPT_ENTRY( resume_from_large, RESUME_FROM_LARGE, LNG, 0 )
OPT_ENTRY( customrequest, CUSTOMREQUEST, STR, LCURL_STORE_STRING )
OPT_ENTRY( filetime, FILETIME, LNG, 0 )
OPT_ENTRY( nobody, NOBODY, LNG, 0 )
OPT_ENTRY( infilesize, INFILESIZE, LNG, 0 )
OPT_ENTRY( infilesize_large, INFILESIZE_LARGE, LNG, 0 )
OPT_ENTRY( upload, UPLOAD, LNG, 0 )
OPT_ENTRY( maxfilesize, MAXFILESIZE, LNG, 0 )
OPT_ENTRY( maxfilesize_large, MAXFILESIZE_LARGE, LNG, 0 )
OPT_ENTRY( timecondition, TIMECONDITION, LNG, 0 )
OPT_ENTRY( timevalue, TIMEVALUE, LNG, 0 )
OPT_ENTRY( transfertext, TRANSFERTEXT, LNG, 0, LCURL_DEFAULT_VALUE )
OPT_ENTRY( proxy_transfer_mode, PROXY_TRANSFER_MODE, LNG, 0, LCURL_DEFAULT_VALUE )
OPT_ENTRY( crlf, CRLF, LNG, 0, LCURL_DEFAULT_VALUE )
OPT_ENTRY( range, RANGE, STR, LCURL_STORE_STRING, LCURL_DEFAULT_VALUE )
OPT_ENTRY( resume_from, RESUME_FROM, LNG, 0, LCURL_DEFAULT_VALUE )
OPT_ENTRY( resume_from_large, RESUME_FROM_LARGE, LNG, 0, LCURL_DEFAULT_VALUE )
OPT_ENTRY( customrequest, CUSTOMREQUEST, STR, LCURL_STORE_STRING, LCURL_DEFAULT_VALUE )
OPT_ENTRY( filetime, FILETIME, LNG, 0, LCURL_DEFAULT_VALUE )
OPT_ENTRY( nobody, NOBODY, LNG, 0, LCURL_DEFAULT_VALUE )
OPT_ENTRY( infilesize, INFILESIZE, LNG, 0, LCURL_DEFAULT_VALUE )/*! @fixme doc says `Unset` */
OPT_ENTRY( infilesize_large, INFILESIZE_LARGE, LNG, 0, LCURL_DEFAULT_VALUE )/*! @fixme doc says `Unset` */
OPT_ENTRY( upload, UPLOAD, LNG, 0, LCURL_DEFAULT_VALUE )
OPT_ENTRY( maxfilesize, MAXFILESIZE, LNG, 0, LCURL_DEFAULT_VALUE ) /*! @fixme doc says `None` */
OPT_ENTRY( maxfilesize_large, MAXFILESIZE_LARGE, LNG, 0, LCURL_DEFAULT_VALUE ) /*! @fixme doc says `None` */
OPT_ENTRY( timecondition, TIMECONDITION, LNG, 0, CURL_TIMECOND_NONE )
OPT_ENTRY( timevalue, TIMEVALUE, LNG, 0, LCURL_DEFAULT_VALUE )
OPT_ENTRY( timeout, TIMEOUT, LNG, 0 )
OPT_ENTRY( timeout_ms, TIMEOUT_MS, LNG, 0 )
OPT_ENTRY( low_speed_limit, LOW_SPEED_LIMIT, LNG, 0 )
OPT_ENTRY( low_speed_time, LOW_SPEED_TIME, LNG, 0 )
OPT_ENTRY( max_send_speed_large, MAX_SEND_SPEED_LARGE, LNG, 0 )
OPT_ENTRY( max_recv_speed_large, MAX_RECV_SPEED_LARGE, LNG, 0 )
OPT_ENTRY( maxconnects, MAXCONNECTS, LNG, 0 )
OPT_ENTRY( fresh_connect, FRESH_CONNECT, LNG, 0 )
OPT_ENTRY( forbid_reuse, FORBID_REUSE, LNG, 0 )
OPT_ENTRY( connecttimeout, CONNECTTIMEOUT, LNG, 0 )
OPT_ENTRY( connecttimeout_ms, CONNECTTIMEOUT_MS, LNG, 0 )
OPT_ENTRY( ipresolve, IPRESOLVE, LNG, 0 )
OPT_ENTRY( connect_only, CONNECT_ONLY, LNG, 0 )
OPT_ENTRY( use_ssl, USE_SSL, LNG, 0 )
OPT_ENTRY( timeout, TIMEOUT, LNG, 0, LCURL_DEFAULT_VALUE )
OPT_ENTRY( timeout_ms, TIMEOUT_MS, LNG, 0, LCURL_DEFAULT_VALUE )
OPT_ENTRY( low_speed_limit, LOW_SPEED_LIMIT, LNG, 0, LCURL_DEFAULT_VALUE )
OPT_ENTRY( low_speed_time, LOW_SPEED_TIME, LNG, 0, LCURL_DEFAULT_VALUE )
OPT_ENTRY( max_send_speed_large, MAX_SEND_SPEED_LARGE, LNG, 0, LCURL_DEFAULT_VALUE )
OPT_ENTRY( max_recv_speed_large, MAX_RECV_SPEED_LARGE, LNG, 0, LCURL_DEFAULT_VALUE )
OPT_ENTRY( maxconnects, MAXCONNECTS, LNG, 0, 5 )
OPT_ENTRY( fresh_connect, FRESH_CONNECT, LNG, 0, LCURL_DEFAULT_VALUE )
OPT_ENTRY( forbid_reuse, FORBID_REUSE, LNG, 0, LCURL_DEFAULT_VALUE )
OPT_ENTRY( connecttimeout, CONNECTTIMEOUT, LNG, 0, 300 )
OPT_ENTRY( connecttimeout_ms, CONNECTTIMEOUT_MS, LNG, 0, 300000 )
OPT_ENTRY( ipresolve, IPRESOLVE, LNG, 0, CURL_IPRESOLVE_WHATEVER )
OPT_ENTRY( connect_only, CONNECT_ONLY, LNG, 0, LCURL_DEFAULT_VALUE )
OPT_ENTRY( use_ssl, USE_SSL, LNG, 0, CURLUSESSL_NONE )
#if LCURL_CURL_VER_GE(7,21,3)
OPT_ENTRY( resolve, RESOLVE, LST, 0 )
OPT_ENTRY( resolve, RESOLVE, LST, 0, LCURL_DEFAULT_VALUE )
#endif
#if LCURL_CURL_VER_GE(7,33,0)
OPT_ENTRY( dns_interface, DNS_INTERFACE, STR, LCURL_STORE_STRING )
OPT_ENTRY( dns_local_ip4, DNS_LOCAL_IP4, STR, LCURL_STORE_STRING )
OPT_ENTRY( dns_local_ip6, DNS_LOCAL_IP6, STR, LCURL_STORE_STRING )
OPT_ENTRY( accepttimeout_ms, ACCEPTTIMEOUT_MS, LNG, 0 )
OPT_ENTRY( dns_interface, DNS_INTERFACE, STR, LCURL_STORE_STRING, LCURL_DEFAULT_VALUE )
OPT_ENTRY( dns_local_ip4, DNS_LOCAL_IP4, STR, LCURL_STORE_STRING, LCURL_DEFAULT_VALUE )
OPT_ENTRY( dns_local_ip6, DNS_LOCAL_IP6, STR, LCURL_STORE_STRING, LCURL_DEFAULT_VALUE )
OPT_ENTRY( accepttimeout_ms, ACCEPTTIMEOUT_MS, LNG, 0, 60000 )
#endif
OPT_ENTRY( ssh_auth_types, SSH_AUTH_TYPES, LNG, 0)
OPT_ENTRY( ssh_host_public_key_md5, SSH_HOST_PUBLIC_KEY_MD5, STR, 0)
OPT_ENTRY( ssh_public_keyfile, SSH_PUBLIC_KEYFILE, STR, 0)
OPT_ENTRY( ssh_private_keyfile, SSH_PRIVATE_KEYFILE, STR, 0)
OPT_ENTRY( ssh_knownhosts, SSH_KNOWNHOSTS, STR, 0)
OPT_ENTRY( ssh_auth_types, SSH_AUTH_TYPES, LNG, 0, LCURL_DEFAULT_VALUE) /*! @fixme doc says `None` */
OPT_ENTRY( ssh_host_public_key_md5, SSH_HOST_PUBLIC_KEY_MD5, STR, 0, LCURL_DEFAULT_VALUE)
OPT_ENTRY( ssh_public_keyfile, SSH_PUBLIC_KEYFILE, STR, 0, LCURL_DEFAULT_VALUE)
OPT_ENTRY( ssh_private_keyfile, SSH_PRIVATE_KEYFILE, STR, 0, LCURL_DEFAULT_VALUE)
OPT_ENTRY( ssh_knownhosts, SSH_KNOWNHOSTS, STR, 0, LCURL_DEFAULT_VALUE)
OPT_ENTRY( new_file_perms, NEW_FILE_PERMS, LNG, 0)
OPT_ENTRY( new_directory_perms, NEW_DIRECTORY_PERMS, LNG, 0)
OPT_ENTRY( new_file_perms, NEW_FILE_PERMS, LNG, 0, 0644)
OPT_ENTRY( new_directory_perms, NEW_DIRECTORY_PERMS, LNG, 0, 0755)
OPT_ENTRY( telnetoptions, TELNETOPTIONS, LST, 0)
OPT_ENTRY( telnetoptions, TELNETOPTIONS, LST, 0, LCURL_DEFAULT_VALUE)
OPT_ENTRY( random_file, RANDOM_FILE, STR, LCURL_STORE_STRING )
OPT_ENTRY( egdsocket, EGDSOCKET, STR, LCURL_STORE_STRING )
OPT_ENTRY( issuercert, ISSUERCERT, STR, LCURL_STORE_STRING )
OPT_ENTRY( krblevel, KRBLEVEL, STR, LCURL_STORE_STRING )
OPT_ENTRY( random_file, RANDOM_FILE, STR, LCURL_STORE_STRING, LCURL_DEFAULT_VALUE )
OPT_ENTRY( egdsocket, EGDSOCKET, STR, LCURL_STORE_STRING, LCURL_DEFAULT_VALUE )
OPT_ENTRY( issuercert, ISSUERCERT, STR, LCURL_STORE_STRING, LCURL_DEFAULT_VALUE )
OPT_ENTRY( krblevel, KRBLEVEL, STR, LCURL_STORE_STRING, LCURL_DEFAULT_VALUE )
OPT_ENTRY( cainfo, CAINFO, STR, LCURL_STORE_STRING )
OPT_ENTRY( capath, CAPATH, STR, LCURL_STORE_STRING )
OPT_ENTRY( certinfo, CERTINFO, LNG, 0 )
OPT_ENTRY( crlfile, CRLFILE, STR, LCURL_STORE_STRING )
OPT_ENTRY( cainfo, CAINFO, STR, LCURL_STORE_STRING, LCURL_DEFAULT_VALUE ) /*! @fixme doc says `Built-in system specific` */
OPT_ENTRY( capath, CAPATH, STR, LCURL_STORE_STRING, LCURL_DEFAULT_VALUE )
OPT_ENTRY( certinfo, CERTINFO, LNG, 0, LCURL_DEFAULT_VALUE )
OPT_ENTRY( crlfile, CRLFILE, STR, LCURL_STORE_STRING, LCURL_DEFAULT_VALUE )
OPT_ENTRY( sslcert, SSLCERT, STR, LCURL_STORE_STRING )
OPT_ENTRY( sslcerttype, SSLCERTTYPE, STR, LCURL_STORE_STRING )
OPT_ENTRY( sslengine, SSLENGINE, STR, LCURL_STORE_STRING )
OPT_ENTRY( sslengine_default, SSLENGINE_DEFAULT, LNG, 0 )
OPT_ENTRY( sslkey, SSLKEY, STR, LCURL_STORE_STRING )
OPT_ENTRY( sslkeytype, SSLKEYTYPE, STR, LCURL_STORE_STRING )
OPT_ENTRY( sslversion, SSLVERSION, LNG, 0 )
OPT_ENTRY( ssl_cipher_list, SSL_CIPHER_LIST, STR, LCURL_STORE_STRING )
OPT_ENTRY( sslcert, SSLCERT, STR, LCURL_STORE_STRING, LCURL_DEFAULT_VALUE )
OPT_ENTRY( sslcerttype, SSLCERTTYPE, STR, LCURL_STORE_STRING, "PEM" )
OPT_ENTRY( sslengine, SSLENGINE, STR, LCURL_STORE_STRING, LCURL_DEFAULT_VALUE )
OPT_ENTRY( sslengine_default, SSLENGINE_DEFAULT, LNG, 0, LCURL_DEFAULT_VALUE ) /*! @fixme doc says `None` */
OPT_ENTRY( sslkey, SSLKEY, STR, LCURL_STORE_STRING, LCURL_DEFAULT_VALUE )
OPT_ENTRY( sslkeytype, SSLKEYTYPE, STR, LCURL_STORE_STRING, "PEM" )
OPT_ENTRY( sslversion, SSLVERSION, LNG, 0, CURL_SSLVERSION_DEFAULT )
OPT_ENTRY( ssl_cipher_list, SSL_CIPHER_LIST, STR, LCURL_STORE_STRING, LCURL_DEFAULT_VALUE )
#if LCURL_CURL_VER_GE(7,33,0)
OPT_ENTRY( ssl_enable_alpn, SSL_ENABLE_ALPN, LNG, 0 )
OPT_ENTRY( ssl_enable_npn, SSL_ENABLE_NPN, LNG, 0 )
OPT_ENTRY( ssl_enable_alpn, SSL_ENABLE_ALPN, LNG, 0, 1 )
OPT_ENTRY( ssl_enable_npn, SSL_ENABLE_NPN, LNG, 0, 1 )
#endif
#if LCURL_CURL_VER_GE(7,25,0)
OPT_ENTRY( ssl_options, SSL_OPTIONS, LNG, 0 )
OPT_ENTRY( ssl_options, SSL_OPTIONS, LNG, 0, LCURL_DEFAULT_VALUE )
#endif
OPT_ENTRY( ssl_sessionid_cache, SSL_SESSIONID_CACHE, LNG, 0 )
OPT_ENTRY( ssl_verifyhost, SSL_VERIFYHOST, LNG, 0 )
OPT_ENTRY( ssl_verifypeer, SSL_VERIFYPEER, LNG, 0 )
OPT_ENTRY( ssl_sessionid_cache, SSL_SESSIONID_CACHE, LNG, 0, 1 )
OPT_ENTRY( ssl_verifyhost, SSL_VERIFYHOST, LNG, 0, 2 )
OPT_ENTRY( ssl_verifypeer, SSL_VERIFYPEER, LNG, 0, 1 )
FLG_ENTRY( SSLVERSION_DEFAULT )

View File

@ -136,6 +136,60 @@ void lcurl_util_set_const(lua_State *L, const lcurl_const_t *reg){
}
}
int lcurl_set_callback(lua_State *L, lcurl_callback_t *c, int i, const char *method){
int top = lua_gettop(L);
i = lua_absindex(L, i);
luaL_argcheck(L, !lua_isnoneornil(L, i), i, "no function present");
luaL_argcheck(L, (top < (i + 1)), i + 2, "no arguments expected");
// if(top > (i + 1)) lua_settop(L, i + 1); // this for force ignore other arguments
assert((top == i)||(top == (i + 1)));
if(c->ud_ref != LUA_NOREF){
luaL_unref(L, LCURL_LUA_REGISTRY, c->ud_ref);
c->ud_ref = LUA_NOREF;
}
if(c->cb_ref != LUA_NOREF){
luaL_unref(L, LCURL_LUA_REGISTRY, c->cb_ref);
c->cb_ref = LUA_NOREF;
}
if(lua_gettop(L) == (i + 1)){// function + context
c->ud_ref = luaL_ref(L, LCURL_LUA_REGISTRY);
c->cb_ref = luaL_ref(L, LCURL_LUA_REGISTRY);
assert(top == (2 + lua_gettop(L)));
return 1;
}
assert(top == i);
if(lua_isfunction(L, i)){ // function
c->cb_ref = luaL_ref(L, LCURL_LUA_REGISTRY);
assert(top == (1 + lua_gettop(L)));
return 1;
}
if(lua_isuserdata(L, i) || lua_istable(L, i)){ // object
lua_getfield(L, i, method);
luaL_argcheck(L, lua_isfunction(L, -1), 2, "method not found in object");
c->cb_ref = luaL_ref(L, LCURL_LUA_REGISTRY);
c->ud_ref = luaL_ref(L, LCURL_LUA_REGISTRY);
assert(top == (1 + lua_gettop(L)));
return 1;
}
lua_pushliteral(L, "invalid object type");
return lua_error(L);
}
int lcurl_util_push_cb(lua_State *L, lcurl_callback_t *c){
assert(c->cb_ref != LUA_NOREF);
lua_rawgeti(L, LCURL_LUA_REGISTRY, c->cb_ref);

View File

@ -16,6 +16,11 @@ typedef struct lcurl_callback_tag{
int ud_ref;
}lcurl_callback_t;
typedef struct lcurl_read_buffer_tag{
int ref;
int off;
}lcurl_read_buffer_t;
int lcurl_storage_init(lua_State *L);
void lcurl_storage_preserve_value(lua_State *L, int storage, int i);
@ -40,6 +45,8 @@ void lcurl_util_slist_to_table(lua_State *L, struct curl_slist* list);
void lcurl_util_set_const(lua_State *L, const lcurl_const_t *reg);
int lcurl_set_callback(lua_State *L, lcurl_callback_t *c, int i, const char *method);
int lcurl_util_push_cb(lua_State *L, lcurl_callback_t *c);
int lcurl_util_new_weak_table(lua_State*L, const char *mode);

View File

@ -1,3 +1,5 @@
lunit = require "lunit"
local ok, curl = pcall(require, "lcurl")
local version if ok then
version = curl.version()