diff --git a/.travis.yml b/.travis.yml index aa7c96b..08bd5a6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -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 .. diff --git a/doc/lcurl.ldoc b/doc/lcurl.ldoc index ffac7e5..86d6841 100644 --- a/doc/lcurl.ldoc +++ b/doc/lcurl.ldoc @@ -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 diff --git a/examples/post_stream.lua b/examples/post_stream.lua new file mode 100644 index 0000000..b0f50c8 --- /dev/null +++ b/examples/post_stream.lua @@ -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() + diff --git a/lakefile b/lakefile index a351450..3d63db1 100644 --- a/lakefile +++ b/lakefile @@ -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") diff --git a/src/lceasy.c b/src/lceasy.c index 3c3d9e1..aaf5640 100644 --- a/src/lceasy.c +++ b/src/lceasy.c @@ -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; - } + 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); - 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); - - 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); + return 1; } 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 diff --git a/src/lceasy.h b/src/lceasy.h index 5d64928..e41c5eb 100644 --- a/src/lceasy.h +++ b/src/lceasy.h @@ -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; diff --git a/src/lchttppost.c b/src/lchttppost.c index 376cf33..2525027 100644 --- a/src/lchttppost.c +++ b/src/lchttppost.c @@ -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 }, diff --git a/src/lchttppost.h b/src/lchttppost.h index 311ad35..6052ad1 100644 --- a/src/lchttppost.h +++ b/src/lchttppost.h @@ -2,13 +2,22 @@ #define _LCHTTPPOST_H_ #include "lcurl.h" +#include "lcutils.h" #include +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); diff --git a/src/lcmulti.c b/src/lcmulti.c index 6171bc2..8b8a653 100644 --- a/src/lcmulti.c +++ b/src/lcmulti.c @@ -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; - } + 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); - 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); - - 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); + return 1; } //{Timer diff --git a/src/lcopteasy.h b/src/lcopteasy.h index 0de6760..5c19b86 100644 --- a/src/lcopteasy.h +++ b/src/lcopteasy.h @@ -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 ) diff --git a/src/lcutils.c b/src/lcutils.c index cfeac76..0a758a8 100644 --- a/src/lcutils.c +++ b/src/lcutils.c @@ -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); diff --git a/src/lcutils.h b/src/lcutils.h index 67c1c2e..727b94d 100644 --- a/src/lcutils.h +++ b/src/lcutils.h @@ -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); diff --git a/test/run.lua b/test/run.lua index 25a1eec..41a72ce 100644 --- a/test/run.lua +++ b/test/run.lua @@ -1,3 +1,5 @@ +lunit = require "lunit" + local ok, curl = pcall(require, "lcurl") local version if ok then version = curl.version()