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"
2339static const char * LCURL_MIME_PART = LCURL_MIME_PART_NAME ;
2440
41+ //{ Free mime and subparts
42+
2543static void lcurl_mime_part_remove_subparts (lua_State * L , lcurl_mime_part_t * p , int free_it );
2644
2745static 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+
72126int 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
87141static 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
109164static 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
113168static 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-
326357static 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){
589620static 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
0 commit comments