summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Monnerat <patrick@monnerat.net>2022-11-16 17:40:11 +0100
committerDaniel Stenberg <daniel@haxx.se>2022-11-28 09:09:54 +0100
commiteb559c8056916f1e71570ac058d599347bebc2b4 (patch)
treef0f897f8b605a39222afd8724f33bf299d400e19
parent383fb29da17df6fed2612cb95454103dadfe948f (diff)
downloadcurl-eb559c8056916f1e71570ac058d599347bebc2b4.tar.gz
mime: relax easy/mime structures binding
Deprecation and removal of codeset conversion support from the library have released the strict need for an early binding of mime structures to an easy handle (https://github.com/curl/curl/commit/2610142). This constraint currently forces to create the handle before the mime structure and the latter cannot be attached to another handle once created (see https://curl.se/mail/lib-2022-08/0027.html). This commit removes the handle pointers from the mime structures allowing more flexibility on their use. When an easy handle is duplicated, bound mime structures must however still be duplicated too as their components hold send-time dynamic information. Closes #9927
-rw-r--r--docs/libcurl/curl_mime_init.314
-rw-r--r--lib/easy.c4
-rw-r--r--lib/formdata.c4
-rw-r--r--lib/http.c4
-rw-r--r--lib/imap.c2
-rw-r--r--lib/mime.c32
-rw-r--r--lib/mime.h16
-rw-r--r--lib/smtp.c2
-rw-r--r--lib/url.c2
9 files changed, 40 insertions, 40 deletions
diff --git a/docs/libcurl/curl_mime_init.3 b/docs/libcurl/curl_mime_init.3
index 9ee466f12..09c3ee166 100644
--- a/docs/libcurl/curl_mime_init.3
+++ b/docs/libcurl/curl_mime_init.3
@@ -31,11 +31,14 @@ curl_mime_init - create a mime handle
curl_mime *curl_mime_init(CURL *easy_handle);
.fi
.SH DESCRIPTION
-\fIcurl_mime_init(3)\fP creates a handle to a new empty mime structure
-intended to be used with \fIeasy_handle\fP. This mime structure can be
-subsequently filled using the mime API, then attached to \fIeasy_handle\fP
-using option \fICURLOPT_MIMEPOST(3)\fP within a \fIcurl_easy_setopt(3)\fP
-call.
+\fIcurl_mime_init(3)\fP creates a handle to a new empty mime structure,
+This mime structure can be subsequently filled using the mime API, then
+attached to some easy handle using option \fICURLOPT_MIMEPOST(3)\fP within
+a \fIcurl_easy_setopt(3)\fP call or added as a multipart in another mime
+handle's part using \fIcurl_mime_subparts(3)\fP.
+
+\fIeasy_handle\fP is used for part separator randomization and error
+reporting. It does not need to be the final target handle.
Using a mime handle is the recommended way to post an HTTP form, format and
send a multi-part email with SMTP or upload such an email to an IMAP server.
@@ -65,5 +68,6 @@ As long as at least one of HTTP, SMTP or IMAP is enabled. Added in 7.56.0.
A mime struct handle, or NULL upon failure.
.SH "SEE ALSO"
.BR curl_mime_addpart "(3),"
+.BR curl_mime_subparts "(3),"
.BR curl_mime_free "(3),"
.BR CURLOPT_MIMEPOST "(3)"
diff --git a/lib/easy.c b/lib/easy.c
index b61ea7b7c..d7f93be1e 100644
--- a/lib/easy.c
+++ b/lib/easy.c
@@ -828,7 +828,7 @@ static CURLcode dupset(struct Curl_easy *dst, struct Curl_easy *src)
/* Copy src->set into dst->set first, then deal with the strings
afterwards */
dst->set = src->set;
- Curl_mime_initpart(&dst->set.mimepost, dst);
+ Curl_mime_initpart(&dst->set.mimepost);
/* clear all string pointers first */
memset(dst->set.str, 0, STRING_LAST * sizeof(char *));
@@ -862,7 +862,7 @@ static CURLcode dupset(struct Curl_easy *dst, struct Curl_easy *src)
}
/* Duplicate mime data. */
- result = Curl_mime_duppart(&dst->set.mimepost, &src->set.mimepost);
+ result = Curl_mime_duppart(dst, &dst->set.mimepost, &src->set.mimepost);
if(src->set.resolve)
dst->state.resolve = dst->set.resolve;
diff --git a/lib/formdata.c b/lib/formdata.c
index 058e06f1f..b30e8deee 100644
--- a/lib/formdata.c
+++ b/lib/formdata.c
@@ -715,10 +715,10 @@ int curl_formget(struct curl_httppost *form, void *arg,
CURLcode result;
curl_mimepart toppart;
- Curl_mime_initpart(&toppart, NULL); /* default form is empty */
+ Curl_mime_initpart(&toppart); /* default form is empty */
result = Curl_getformdata(NULL, &toppart, form, NULL);
if(!result)
- result = Curl_mime_prepare_headers(&toppart, "multipart/form-data",
+ result = Curl_mime_prepare_headers(NULL, &toppart, "multipart/form-data",
NULL, MIMESTRATEGY_FORM);
while(!result) {
diff --git a/lib/http.c b/lib/http.c
index 66d3b4dd6..85528a221 100644
--- a/lib/http.c
+++ b/lib/http.c
@@ -265,7 +265,7 @@ static CURLcode http_setup_conn(struct Curl_easy *data,
if(!http)
return CURLE_OUT_OF_MEMORY;
- Curl_mime_initpart(&http->form, data);
+ Curl_mime_initpart(&http->form);
data->req.p.http = http;
if(data->state.httpwant == CURL_HTTP_VERSION_3) {
@@ -2303,7 +2303,7 @@ CURLcode Curl_http_body(struct Curl_easy *data, struct connectdata *conn,
cthdr = "multipart/form-data";
curl_mime_headers(http->sendit, data->set.headers, 0);
- result = Curl_mime_prepare_headers(http->sendit, cthdr,
+ result = Curl_mime_prepare_headers(data, http->sendit, cthdr,
NULL, MIMESTRATEGY_FORM);
curl_mime_headers(http->sendit, NULL, 0);
if(!result)
diff --git a/lib/imap.c b/lib/imap.c
index 03dc19166..a462ff042 100644
--- a/lib/imap.c
+++ b/lib/imap.c
@@ -777,7 +777,7 @@ static CURLcode imap_perform_append(struct Curl_easy *data)
/* Add external headers and mime version. */
curl_mime_headers(&data->set.mimepost, data->set.headers, 0);
- result = Curl_mime_prepare_headers(&data->set.mimepost, NULL,
+ result = Curl_mime_prepare_headers(data, &data->set.mimepost, NULL,
NULL, MIMESTRATEGY_MAIL);
if(!result)
diff --git a/lib/mime.c b/lib/mime.c
index 117c66f4d..e3f2821db 100644
--- a/lib/mime.c
+++ b/lib/mime.c
@@ -1175,7 +1175,7 @@ void Curl_mime_cleanpart(curl_mimepart *part)
Curl_safefree(part->mimetype);
Curl_safefree(part->name);
Curl_safefree(part->filename);
- Curl_mime_initpart(part, part->easy);
+ Curl_mime_initpart(part);
}
/* Recursively delete a mime handle and its parts. */
@@ -1195,7 +1195,8 @@ void curl_mime_free(curl_mime *mime)
}
}
-CURLcode Curl_mime_duppart(curl_mimepart *dst, const curl_mimepart *src)
+CURLcode Curl_mime_duppart(struct Curl_easy *data,
+ curl_mimepart *dst, const curl_mimepart *src)
{
curl_mime *mime;
curl_mimepart *d;
@@ -1224,13 +1225,13 @@ CURLcode Curl_mime_duppart(curl_mimepart *dst, const curl_mimepart *src)
case MIMEKIND_MULTIPART:
/* No one knows about the cloned subparts, thus always attach ownership
to the part. */
- mime = curl_mime_init(dst->easy);
+ mime = curl_mime_init(data);
res = mime? curl_mime_subparts(dst, mime): CURLE_OUT_OF_MEMORY;
/* Duplicate subparts. */
for(s = ((curl_mime *) src->arg)->firstpart; !res && s; s = s->nextpart) {
d = curl_mime_addpart(mime);
- res = d? Curl_mime_duppart(d, s): CURLE_OUT_OF_MEMORY;
+ res = d? Curl_mime_duppart(data, d, s): CURLE_OUT_OF_MEMORY;
}
break;
default: /* Invalid kind: should not occur. */
@@ -1282,7 +1283,6 @@ curl_mime *curl_mime_init(struct Curl_easy *easy)
mime = (curl_mime *) malloc(sizeof(*mime));
if(mime) {
- mime->easy = easy;
mime->parent = NULL;
mime->firstpart = NULL;
mime->lastpart = NULL;
@@ -1302,10 +1302,9 @@ curl_mime *curl_mime_init(struct Curl_easy *easy)
}
/* Initialize a mime part. */
-void Curl_mime_initpart(curl_mimepart *part, struct Curl_easy *easy)
+void Curl_mime_initpart(curl_mimepart *part)
{
memset((char *) part, 0, sizeof(*part));
- part->easy = easy;
part->lastreadstatus = 1; /* Successful read status. */
mimesetstate(&part->state, MIMESTATE_BEGIN, NULL);
}
@@ -1321,7 +1320,7 @@ curl_mimepart *curl_mime_addpart(curl_mime *mime)
part = (curl_mimepart *) malloc(sizeof(*part));
if(part) {
- Curl_mime_initpart(part, mime->easy);
+ Curl_mime_initpart(part);
part->parent = mime;
if(mime->lastpart)
@@ -1551,10 +1550,6 @@ CURLcode Curl_mime_set_subparts(curl_mimepart *part,
cleanup_part_content(part);
if(subparts) {
- /* Must belong to the same data handle. */
- if(part->easy && subparts->easy && part->easy != subparts->easy)
- return CURLE_BAD_FUNCTION_ARGUMENT;
-
/* Should not have been attached already. */
if(subparts->parent)
return CURLE_BAD_FUNCTION_ARGUMENT;
@@ -1565,8 +1560,7 @@ CURLcode Curl_mime_set_subparts(curl_mimepart *part,
while(root->parent && root->parent->parent)
root = root->parent->parent;
if(subparts == root) {
- if(part->easy)
- failf(part->easy, "Can't add itself as a subpart");
+ /* Can't add as a subpart of itself. */
return CURLE_BAD_FUNCTION_ARGUMENT;
}
}
@@ -1766,7 +1760,8 @@ static bool content_type_match(const char *contenttype,
return FALSE;
}
-CURLcode Curl_mime_prepare_headers(curl_mimepart *part,
+CURLcode Curl_mime_prepare_headers(struct Curl_easy *data,
+ curl_mimepart *part,
const char *contenttype,
const char *disposition,
enum mimestrategy strategy)
@@ -1835,12 +1830,12 @@ CURLcode Curl_mime_prepare_headers(curl_mimepart *part,
char *filename = NULL;
if(part->name) {
- name = escape_string(part->easy, part->name, strategy);
+ name = escape_string(data, part->name, strategy);
if(!name)
ret = CURLE_OUT_OF_MEMORY;
}
if(!ret && part->filename) {
- filename = escape_string(part->easy, part->filename, strategy);
+ filename = escape_string(data, part->filename, strategy);
if(!filename)
ret = CURLE_OUT_OF_MEMORY;
}
@@ -1897,7 +1892,8 @@ CURLcode Curl_mime_prepare_headers(curl_mimepart *part,
if(content_type_match(contenttype, STRCONST("multipart/form-data")))
disposition = "form-data";
for(subpart = mime->firstpart; subpart; subpart = subpart->nextpart) {
- ret = Curl_mime_prepare_headers(subpart, NULL, disposition, strategy);
+ ret = Curl_mime_prepare_headers(data, subpart, NULL,
+ disposition, strategy);
if(ret)
return ret;
}
diff --git a/lib/mime.h b/lib/mime.h
index bafde29f4..b9ea0f101 100644
--- a/lib/mime.h
+++ b/lib/mime.h
@@ -99,7 +99,6 @@ struct mime_state {
/* A mime multipart. */
struct curl_mime {
- struct Curl_easy *easy; /* The associated easy handle. */
curl_mimepart *parent; /* Parent part. */
curl_mimepart *firstpart; /* First part. */
curl_mimepart *lastpart; /* Last part. */
@@ -109,7 +108,6 @@ struct curl_mime {
/* A mime part. */
struct curl_mimepart {
- struct Curl_easy *easy; /* The associated easy handle. */
curl_mime *parent; /* Parent mime structure. */
curl_mimepart *nextpart; /* Forward linked list. */
enum mimekind kind; /* The part kind. */
@@ -139,14 +137,16 @@ CURLcode Curl_mime_add_header(struct curl_slist **slp, const char *fmt, ...);
!defined(CURL_DISABLE_IMAP))
/* Prototypes. */
-void Curl_mime_initpart(struct curl_mimepart *part, struct Curl_easy *easy);
+void Curl_mime_initpart(struct curl_mimepart *part);
void Curl_mime_cleanpart(struct curl_mimepart *part);
-CURLcode Curl_mime_duppart(struct curl_mimepart *dst,
+CURLcode Curl_mime_duppart(struct Curl_easy *data,
+ struct curl_mimepart *dst,
const curl_mimepart *src);
CURLcode Curl_mime_set_subparts(struct curl_mimepart *part,
struct curl_mime *subparts,
int take_ownership);
-CURLcode Curl_mime_prepare_headers(struct curl_mimepart *part,
+CURLcode Curl_mime_prepare_headers(struct Curl_easy *data,
+ struct curl_mimepart *part,
const char *contenttype,
const char *disposition,
enum mimestrategy strategy);
@@ -159,11 +159,11 @@ void Curl_mime_unpause(struct curl_mimepart *part);
#else
/* if disabled */
-#define Curl_mime_initpart(x,y)
+#define Curl_mime_initpart(x)
#define Curl_mime_cleanpart(x)
-#define Curl_mime_duppart(x,y) CURLE_OK /* Nothing to duplicate. Succeed */
+#define Curl_mime_duppart(x,y,z) CURLE_OK /* Nothing to duplicate. Succeed */
#define Curl_mime_set_subparts(a,b,c) CURLE_NOT_BUILT_IN
-#define Curl_mime_prepare_headers(a,b,c,d) CURLE_NOT_BUILT_IN
+#define Curl_mime_prepare_headers(a,b,c,d,e) CURLE_NOT_BUILT_IN
#define Curl_mime_size(x) (curl_off_t) -1
#define Curl_mime_read NULL
#define Curl_mime_rewind(x) ((void)x, CURLE_NOT_BUILT_IN)
diff --git a/lib/smtp.c b/lib/smtp.c
index cbaf482e9..085faf9e3 100644
--- a/lib/smtp.c
+++ b/lib/smtp.c
@@ -697,7 +697,7 @@ static CURLcode smtp_perform_mail(struct Curl_easy *data)
/* Add external headers and mime version. */
curl_mime_headers(&data->set.mimepost, data->set.headers, 0);
- result = Curl_mime_prepare_headers(&data->set.mimepost, NULL,
+ result = Curl_mime_prepare_headers(data, &data->set.mimepost, NULL,
NULL, MIMESTRATEGY_MAIL);
if(!result)
diff --git a/lib/url.c b/lib/url.c
index 74201f9bb..0af812bcd 100644
--- a/lib/url.c
+++ b/lib/url.c
@@ -560,7 +560,7 @@ CURLcode Curl_init_userdefined(struct Curl_easy *data)
/* make libcurl quiet by default: */
set->hide_progress = TRUE; /* CURLOPT_NOPROGRESS changes these */
- Curl_mime_initpart(&set->mimepost, data);
+ Curl_mime_initpart(&set->mimepost);
/*
* libcurl 7.10 introduced SSL verification *by default*! This needs to be