Skip to content

Commit 58847b1

Browse files
committed
Add. mime:easy() method.
1 parent d86d77b commit 58847b1

File tree

5 files changed

+143
-80
lines changed

5 files changed

+143
-80
lines changed

appveyor.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ shallow_clone: true
77

88
environment:
99
LR_EXTERNAL: c:\external
10-
CURL_VER: 7.56.1
10+
CURL_VER: 7.59.0
1111

1212
matrix:
1313
- LUA: "lua 5.1"

src/lcmime.c

+73-40
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,22 @@
1414
#include "lcerror.h"
1515
#include "lcutils.h"
1616

17+
/* API Notes.
18+
* 1. Each mime can be root or child. If mime is a child (subpart) then curl free it
19+
* when parent mime is freed or when remove this part from parent. There no way reuse same mime.
20+
* Its not clear is it possible use mime created by one easy handle when do preform in another.
21+
* `m=e1:mime() e2:setopt_httpmime(m) e1:close() e2:perform()`
22+
*
23+
* // Attach child to root (root also can have parent)
24+
* curl_mime_subparts(root, child);
25+
*
26+
* // curl free `child` and all its childs
27+
* curl_mime_subparts(root, other_child_or_null);
28+
*
29+
* // forbidden
30+
* curl_mime_free(child);
31+
*/
32+
1733
#if LCURL_CURL_VER_GE(7,56,0)
1834

1935
#define LCURL_MIME_NAME LCURL_PREFIX" MIME"
@@ -22,6 +38,8 @@ static const char *LCURL_MIME = LCURL_MIME_NAME;
2238
#define LCURL_MIME_PART_NAME LCURL_PREFIX" MIME Part"
2339
static const char *LCURL_MIME_PART = LCURL_MIME_PART_NAME;
2440

41+
//{ Free mime and subparts
42+
2543
static void lcurl_mime_part_remove_subparts(lua_State *L, lcurl_mime_part_t *p, int free_it);
2644

2745
static lcurl_mime_t* lcurl_mime_part_get_subparts(lua_State *L, lcurl_mime_part_t *part){
@@ -66,9 +84,45 @@ static int lcurl_mime_reset(lua_State *L, lcurl_mime_t *p){
6684
p->parts = p->parent = NULL;
6785
p->mime = NULL;
6886

87+
/* remove weak reference to easy */
88+
lua_pushnil(L);
89+
lua_rawsetp(L, LCURL_MIME_EASY, p);
90+
6991
return 0;
7092
}
7193

94+
static void lcurl_mime_part_remove_subparts(lua_State *L, lcurl_mime_part_t *p, int free_it){
95+
lcurl_mime_t *sub = lcurl_mime_part_get_subparts(L, p);
96+
if(sub){
97+
assert(LUA_NOREF != p->subpart_ref);
98+
/* detach `subpart` mime from current mime part */
99+
/* if set `sub->parent = NULL` then gc for mime will try free curl_mime_free. */
100+
101+
luaL_unref(L, LCURL_LUA_REGISTRY, p->subpart_ref);
102+
p->subpart_ref = LUA_NOREF;
103+
104+
if(p->part && free_it){
105+
curl_mime_subparts(p->part, NULL);
106+
}
107+
108+
/* seems curl_mime_subparts(h, NULL) free asubparts.
109+
so we have to invalidate all reference to all nested objects (part/mime).
110+
NOTE. All resources already feed. So just need set all pointers to NULL
111+
and free all Lua resources (like references and storages)
112+
*/
113+
{
114+
lcurl_mime_part_t *ptr;
115+
/* reset all parts*/
116+
for(ptr = sub->parts; ptr; ptr=ptr->next){
117+
lcurl_mime_part_remove_subparts(L, p, 0);
118+
}
119+
lcurl_mime_reset(L, sub);
120+
}
121+
}
122+
}
123+
124+
//}
125+
72126
int lcurl_mime_set_lua(lua_State *L, lcurl_mime_t *p, lua_State *v){
73127
lcurl_mime_part_t *part;
74128
for(part = p->parts; part; part=part->next){
@@ -86,6 +140,7 @@ int lcurl_mime_set_lua(lua_State *L, lcurl_mime_t *p, lua_State *v){
86140

87141
static int lutil_isarray(lua_State *L, int i){
88142
int ret = 0;
143+
i = lua_absindex(L, i);
89144
lua_pushnil(L);
90145
if(lua_next(L, i)){
91146
ret = lua_isnumber(L, -2);
@@ -94,7 +149,7 @@ static int lutil_isarray(lua_State *L, int i){
94149
return ret;
95150
}
96151

97-
static int lcurl_mime_part_assig(lua_State *L, int part, const char *method){
152+
static int lcurl_mime_part_assign(lua_State *L, int part, const char *method){
98153
int top = lua_gettop(L);
99154

100155
lua_pushvalue(L, part);
@@ -107,7 +162,7 @@ static int lcurl_mime_part_assig(lua_State *L, int part, const char *method){
107162
}
108163

109164
static const char *lcurl_mime_part_fields[] = {
110-
"data", "filedata", "name", "filename", "headers", "encoder", NULL
165+
"data", "filedata", "name", "filename", "headers", "encoder", "type", NULL
111166
};
112167

113168
static int lcurl_mime_part_assing_table(lua_State *L, int part, int t){
@@ -120,7 +175,7 @@ static int lcurl_mime_part_assing_table(lua_State *L, int part, int t){
120175
if(lutil_isarray(L, t)){
121176
int ret;
122177
lua_pushvalue(L, t);
123-
ret = lcurl_mime_part_assig(L, part, "headers");
178+
ret = lcurl_mime_part_assign(L, part, "headers");
124179
if(ret != 1) return ret;
125180

126181
lua_pop(L, 1);
@@ -131,7 +186,7 @@ static int lcurl_mime_part_assing_table(lua_State *L, int part, int t){
131186
for(i=0;method = lcurl_mime_part_fields[i]; ++i){
132187
lua_getfield(L, t, method);
133188
if(!lua_isnil(L, -1)){
134-
int ret = lcurl_mime_part_assig(L, part, method);
189+
int ret = lcurl_mime_part_assign(L, part, method);
135190
if(ret != 1) return ret;
136191
}
137192
lua_pop(L, 1);
@@ -141,8 +196,8 @@ static int lcurl_mime_part_assing_table(lua_State *L, int part, int t){
141196

142197
lua_getfield(L, t, "subparts");
143198
if(!lua_isnil(L, -1)){
144-
if(IS_FALSE(L, -1) || lcurl_getmimepart_at(L, -1)){
145-
int ret = lcurl_mime_part_assig(L, part, "subparts");
199+
if(IS_FALSE(L, -1) || lcurl_getmime_at(L, -1)){
200+
int ret = lcurl_mime_part_assign(L, part, "subparts");
146201
if(ret != 1) return ret;
147202
}
148203
}
@@ -190,6 +245,10 @@ int lcurl_mime_create(lua_State *L, int error_mode){
190245
p->err_mode = error_mode;
191246
p->parts = p->parent = NULL;
192247

248+
/* weak reference from mime to easy handle */
249+
lua_pushvalue(L, 1);
250+
lua_rawsetp(L, LCURL_MIME_EASY, (void*)p);
251+
193252
return 1;
194253
}
195254

@@ -242,6 +301,12 @@ static int lcurl_mime_addpart(lua_State *L){
242301
return 1;
243302
}
244303

304+
static int lcurl_mime_easy(lua_State *L){
305+
lcurl_mime_t *p = lcurl_getmime(L);
306+
lua_rawgetp(L, LCURL_MIME_EASY, p);
307+
return 1;
308+
}
309+
245310
//}
246311

247312
//{ MIME Part
@@ -289,40 +354,6 @@ static int lcurl_mime_part_free(lua_State *L){
289354
return 0;
290355
}
291356

292-
static void lcurl_mime_part_remove_subparts(lua_State *L, lcurl_mime_part_t *p, int free_it){
293-
lcurl_mime_t *sub = lcurl_mime_part_get_subparts(L, p);
294-
if(sub){
295-
assert(LUA_NOREF != p->subpart_ref);
296-
/* detach `subpart` mime from current mime part */
297-
298-
/* if set `sub->parent = NULL` then gc for mime will try free curl_mime_free. */
299-
/* So do not set it unless `curl_mime_subparts(p->part, NULL)` does not free mime */
300-
301-
luaL_unref(L, LCURL_LUA_REGISTRY, p->subpart_ref);
302-
p->subpart_ref = LUA_NOREF;
303-
304-
if(p->part && free_it){
305-
curl_mime_subparts(p->part, NULL);
306-
}
307-
308-
/* issues #1961 */
309-
310-
/* seems curl_mime_subparts(h, NULL) free asubparts.
311-
so we have to invalidate all reference to all nested objects (part/mime).
312-
NOTE. All resources already feed. So just need set all pointers to NULL
313-
and free all Lua resources (like references and storages)
314-
*/
315-
{
316-
lcurl_mime_part_t *ptr;
317-
/* reset all parts*/
318-
for(ptr = sub->parts; ptr; ptr=ptr->next){
319-
lcurl_mime_part_remove_subparts(L, p, 0);
320-
}
321-
lcurl_mime_reset(L, sub);
322-
}
323-
}
324-
}
325-
326357
static int lcurl_mime_part_assing_ext(lua_State *L, int part, int i){
327358
#define UNSET_VALUE (const char*)-1
328359

@@ -589,6 +620,7 @@ static int lcurl_mime_part_encoder(lua_State *L){
589620
static const struct luaL_Reg lcurl_mime_methods[] = {
590621

591622
{"addpart", lcurl_mime_addpart },
623+
{"easy", lcurl_mime_easy },
592624

593625
{"free", lcurl_mime_free },
594626
{"__gc", lcurl_mime_free },
@@ -646,6 +678,7 @@ void lcurl_mime_initlib(lua_State *L, int nup){
646678
if(!lutil_createmetap(L, LCURL_MIME_PART, lcurl_mime_part_methods, nup))
647679
lua_pop(L, nup);
648680
lua_pop(L, 1);
681+
649682
#else
650683
lua_pop(L, nup);
651684
#endif

src/lcurl.c

+37-10
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,21 @@ static volatile int LCURL_INIT = 0;
189189

190190
static const char* LCURL_REGISTRY = "LCURL Registry";
191191
static const char* LCURL_USERVAL = "LCURL Uservalues";
192+
#if LCURL_CURL_VER_GE(7,56,0)
193+
static const char* LCURL_MIME_EASY_MAP = "LCURL Mime easy";
194+
#endif
195+
196+
#if LCURL_CURL_VER_GE(7,56,0)
197+
#define NUP 3
198+
#else
199+
#define NUP 2
200+
#endif
201+
202+
#if LCURL_CURL_VER_GE(7,56,0)
203+
#define LCURL_PUSH_NUP(L) lua_pushvalue(L, -NUP-1);lua_pushvalue(L, -NUP-1);lua_pushvalue(L, -NUP-1);
204+
#else
205+
#define LCURL_PUSH_NUP(L) lua_pushvalue(L, -NUP-1);lua_pushvalue(L, -NUP-1);
206+
#endif
192207

193208
static int luaopen_lcurl_(lua_State *L, const struct luaL_Reg *func){
194209
if(!LCURL_INIT){
@@ -214,20 +229,32 @@ static int luaopen_lcurl_(lua_State *L, const struct luaL_Reg *func){
214229
lcurl_util_new_weak_table(L, "k");
215230
}
216231

232+
#if LCURL_CURL_VER_GE(7,56,0)
233+
lua_rawgetp(L, LUA_REGISTRYINDEX, LCURL_MIME_EASY_MAP);
234+
if(!lua_istable(L, -1)){ /* Mime->Easy */
235+
lua_pop(L, 1);
236+
lcurl_util_new_weak_table(L, "v");
237+
}
238+
#endif
239+
217240
lua_newtable(L); /* library */
218241

219-
lua_pushvalue(L, -3); lua_pushvalue(L, -3); luaL_setfuncs(L, func, 2);
220-
lua_pushvalue(L, -3); lua_pushvalue(L, -3); lcurl_error_initlib(L, 2);
221-
lua_pushvalue(L, -3); lua_pushvalue(L, -3); lcurl_hpost_initlib(L, 2);
222-
lua_pushvalue(L, -3); lua_pushvalue(L, -3); lcurl_easy_initlib (L, 2);
223-
lua_pushvalue(L, -3); lua_pushvalue(L, -3); lcurl_mime_initlib (L, 2);
224-
lua_pushvalue(L, -3); lua_pushvalue(L, -3); lcurl_multi_initlib(L, 2);
225-
lua_pushvalue(L, -3); lua_pushvalue(L, -3); lcurl_share_initlib(L, 2);
242+
LCURL_PUSH_NUP(L); luaL_setfuncs(L, func, NUP);
243+
LCURL_PUSH_NUP(L); lcurl_error_initlib(L, NUP);
244+
LCURL_PUSH_NUP(L); lcurl_hpost_initlib(L, NUP);
245+
LCURL_PUSH_NUP(L); lcurl_easy_initlib (L, NUP);
246+
LCURL_PUSH_NUP(L); lcurl_mime_initlib (L, NUP);
247+
LCURL_PUSH_NUP(L); lcurl_multi_initlib(L, NUP);
248+
LCURL_PUSH_NUP(L); lcurl_share_initlib(L, NUP);
249+
250+
LCURL_PUSH_NUP(L);
226251

227-
lua_pushvalue(L, -3); lua_rawsetp(L, LUA_REGISTRYINDEX, LCURL_REGISTRY);
228-
lua_pushvalue(L, -2); lua_rawsetp(L, LUA_REGISTRYINDEX, LCURL_USERVAL);
252+
#if LCURL_CURL_VER_GE(7,56,0)
253+
lua_rawsetp(L, LUA_REGISTRYINDEX, LCURL_MIME_EASY_MAP);
254+
#endif
229255

230-
lua_remove(L, -2); /* registry */
256+
lua_rawsetp(L, LUA_REGISTRYINDEX, LCURL_USERVAL);
257+
lua_rawsetp(L, LUA_REGISTRYINDEX, LCURL_REGISTRY);
231258

232259
lcurl_util_set_const(L, lcurl_flags);
233260

src/lcurl.h

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/******************************************************************************
22
* Author: Alexey Melnichuk <[email protected]>
33
*
4-
* Copyright (C) 2014 Alexey Melnichuk <[email protected]>
4+
* Copyright (C) 2014-2017 Alexey Melnichuk <[email protected]>
55
*
66
* Licensed according to the included 'LICENSE' document
77
*
@@ -25,4 +25,7 @@
2525

2626
#define LCURL_USERVALUES lua_upvalueindex(2)
2727

28+
/* only for `mime` API */
29+
#define LCURL_MIME_EASY lua_upvalueindex(3)
30+
2831
#endif

0 commit comments

Comments
 (0)