mirror of
https://github.com/moparisthebest/curl
synced 2024-12-21 07:38:49 -05:00
mime: new MIME API.
Available in HTTP, SMTP and IMAP. Deprecates the FORM API. See CURLOPT_MIMEPOST. Lib code and associated documentation.
This commit is contained in:
parent
5bae72734b
commit
ce0881edee
@ -17,4 +17,8 @@ man_MANS = curl_easy_cleanup.3 curl_easy_getinfo.3 curl_easy_init.3 \
|
||||
curl_multi_timeout.3 curl_formget.3 curl_multi_assign.3 \
|
||||
curl_easy_pause.3 curl_easy_recv.3 curl_easy_send.3 \
|
||||
curl_multi_socket_action.3 curl_multi_wait.3 libcurl-symbols.3 \
|
||||
libcurl-thread.3 curl_multi_socket_all.3 curl_global_sslset.3
|
||||
libcurl-thread.3 curl_multi_socket_all.3 curl_global_sslset.3 \
|
||||
curl_mime_init.3 curl_mime_free.3 curl_mime_addpart.3 curl_mime_name.3 \
|
||||
curl_mime_data.3 curl_mime_data_cb.3 curl_mime_filedata.3 \
|
||||
curl_mime_filename.3 curl_mime_subparts.3 \
|
||||
curl_mime_type.3 curl_mime_headers.3
|
||||
|
@ -411,6 +411,8 @@ Size of file to send. \fICURLOPT_INFILESIZE(3)\fP
|
||||
Size of file to send. \fICURLOPT_INFILESIZE_LARGE(3)\fP
|
||||
.IP CURLOPT_UPLOAD
|
||||
Upload data. See \fICURLOPT_UPLOAD(3)\fP
|
||||
.IP CURLOPT_MIMEPOST
|
||||
Post/send MIME data. See \fICURLOPT_MIMEPOST(3)\fP
|
||||
.IP CURLOPT_MAXFILESIZE
|
||||
Maximum file size to get. See \fICURLOPT_MAXFILESIZE(3)\fP
|
||||
.IP CURLOPT_MAXFILESIZE_LARGE
|
||||
|
@ -5,7 +5,7 @@
|
||||
.\" * | (__| |_| | _ <| |___
|
||||
.\" * \___|\___/|_| \_\_____|
|
||||
.\" *
|
||||
.\" * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
.\" * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
.\" *
|
||||
.\" * This software is licensed as described in the file COPYING, which
|
||||
.\" * you should have received as part of this distribution. The terms
|
||||
@ -29,6 +29,8 @@ curl_formadd - add a section to a multipart/formdata HTTP POST
|
||||
.BI "struct curl_httppost ** " lastitem, " ...);"
|
||||
.ad
|
||||
.SH DESCRIPTION
|
||||
This function is deprecated. Do not use! See \fIcurl_mime_init(3)\fP instead!
|
||||
|
||||
curl_formadd() is used to append sections when building a multipart/formdata
|
||||
HTTP POST (sometimes referred to as RFC2388-style posts). Append one section
|
||||
at a time until you've added all the sections you want included and then you
|
||||
@ -169,6 +171,8 @@ the \fICURLOPT_HTTPPOST(3)\fP option), you must not free the list until after
|
||||
you've called \fIcurl_easy_cleanup(3)\fP for the curl handle.
|
||||
|
||||
See example below.
|
||||
.SH AVAILABILITY
|
||||
Deprecated in 7.56.0.
|
||||
.SH RETURN VALUE
|
||||
0 means everything was ok, non-zero means an error occurred corresponding
|
||||
to a CURL_FORMADD_* constant defined in
|
||||
@ -254,5 +258,6 @@ to a CURL_FORMADD_* constant defined in
|
||||
curl_easy_setopt(curl, CURLOPT_HTTPPOST, post);
|
||||
|
||||
.SH "SEE ALSO"
|
||||
.BR curl_easy_setopt "(3), "
|
||||
.BR curl_formfree "(3)"
|
||||
.BR curl_easy_setopt "(3),"
|
||||
.BR curl_formfree "(3),"
|
||||
.BR curl_mime_init "(3)"
|
||||
|
@ -5,7 +5,7 @@
|
||||
.\" * | (__| |_| | _ <| |___
|
||||
.\" * \___|\___/|_| \_\_____|
|
||||
.\" *
|
||||
.\" * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
.\" * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
.\" *
|
||||
.\" * This software is licensed as described in the file COPYING, which
|
||||
.\" * you should have received as part of this distribution. The terms
|
||||
@ -28,6 +28,8 @@ curl_formfree - free a previously build multipart/formdata HTTP POST chain
|
||||
.BI "void curl_formfree(struct curl_httppost *" form);
|
||||
.ad
|
||||
.SH DESCRIPTION
|
||||
This function is deprecated. Do not use! See \fIcurl_mime_init(3)\fP instead!
|
||||
|
||||
curl_formfree() is used to clean up data previously built/appended with
|
||||
\fIcurl_formadd(3)\fP. This must be called when the data has been used, which
|
||||
typically means after \fIcurl_easy_perform(3)\fP has been called.
|
||||
@ -38,7 +40,9 @@ the \fIcurl_formadd(3)\fP invoke(s).
|
||||
|
||||
\fBform\fP is the pointer as returned from a previous call to
|
||||
\fIcurl_formadd(3)\fP and may be NULL.
|
||||
.SH AVAILABILITY
|
||||
Deprecated in 7.56.0.
|
||||
.SH RETURN VALUE
|
||||
None
|
||||
.SH "SEE ALSO"
|
||||
.BR curl_formadd "(3) "
|
||||
.BR curl_formadd "(3), " curl_mime_init "(3), " curl_mime_free "(3)"
|
||||
|
@ -5,7 +5,7 @@
|
||||
.\" * | (__| |_| | _ <| |___
|
||||
.\" * \___|\___/|_| \_\_____|
|
||||
.\" *
|
||||
.\" * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
.\" * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
.\" *
|
||||
.\" * This software is licensed as described in the file COPYING, which
|
||||
.\" * you should have received as part of this distribution. The terms
|
||||
@ -65,6 +65,7 @@ request as only then will libcurl get the actual read callback to use!
|
||||
return total_size;
|
||||
}
|
||||
.SH AVAILABILITY
|
||||
This function was added in libcurl 7.15.5
|
||||
This function was added in libcurl 7.15.5. The form API is deprecated in
|
||||
libcurl 7.56.0.
|
||||
.SH "SEE ALSO"
|
||||
.BR curl_formadd "(3) "
|
||||
.BR curl_formadd "(3), " curl_mime_init "(3)"
|
||||
|
52
docs/libcurl/curl_mime_addpart.3
Normal file
52
docs/libcurl/curl_mime_addpart.3
Normal file
@ -0,0 +1,52 @@
|
||||
.\" **************************************************************************
|
||||
.\" * _ _ ____ _
|
||||
.\" * Project ___| | | | _ \| |
|
||||
.\" * / __| | | | |_) | |
|
||||
.\" * | (__| |_| | _ <| |___
|
||||
.\" * \___|\___/|_| \_\_____|
|
||||
.\" *
|
||||
.\" * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
.\" *
|
||||
.\" * This software is licensed as described in the file COPYING, which
|
||||
.\" * you should have received as part of this distribution. The terms
|
||||
.\" * are also available at https://curl.haxx.se/docs/copyright.html.
|
||||
.\" *
|
||||
.\" * You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
.\" * copies of the Software, and permit persons to whom the Software is
|
||||
.\" * furnished to do so, under the terms of the COPYING file.
|
||||
.\" *
|
||||
.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
.\" * KIND, either express or implied.
|
||||
.\" *
|
||||
.\" **************************************************************************
|
||||
.TH curl_mime_addpart 3 "22 August 2017" "libcurl 7.56.0" "libcurl Manual"
|
||||
.SH NAME
|
||||
curl_mime_addpart - append a new empty part to a mime structure
|
||||
.SH SYNOPSIS
|
||||
.B #include <curl/curl.h>
|
||||
.sp
|
||||
.BI "curl_mimepart * curl_mime_addpart(curl_mime * " mime ");"
|
||||
.ad
|
||||
.SH DESCRIPTION
|
||||
curl_mime_addpart() appends a new empty part to the given mime structure and
|
||||
returns a handle to it.
|
||||
The returned part can be subsequently filled using functions from the mime API.
|
||||
|
||||
\fImime\fP is the handle of the mime structure in which the new part must be
|
||||
appended.
|
||||
|
||||
.SH AVAILABILITY
|
||||
As long as at least one of HTTP, SMTP or IMAP is enabled. Added in 7.56.0.
|
||||
.SH RETURN VALUE
|
||||
A mime part structure handle, or NULL upon failure.
|
||||
|
||||
.SH "SEE ALSO"
|
||||
.BR curl_mime_init "(3),"
|
||||
.BR curl_mime_name "(3),"
|
||||
.BR curl_mime_data "(3),"
|
||||
.BR curl_mime_data_cb "(3),"
|
||||
.BR curl_mime_filedata "(3),"
|
||||
.BR curl_mime_filename "(3),"
|
||||
.BR curl_mime_subparts "(3),"
|
||||
.BR curl_mime_type "(3),"
|
||||
.BR curl_mime_headers "(3)"
|
54
docs/libcurl/curl_mime_data.3
Normal file
54
docs/libcurl/curl_mime_data.3
Normal file
@ -0,0 +1,54 @@
|
||||
.\" **************************************************************************
|
||||
.\" * _ _ ____ _
|
||||
.\" * Project ___| | | | _ \| |
|
||||
.\" * / __| | | | |_) | |
|
||||
.\" * | (__| |_| | _ <| |___
|
||||
.\" * \___|\___/|_| \_\_____|
|
||||
.\" *
|
||||
.\" * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
.\" *
|
||||
.\" * This software is licensed as described in the file COPYING, which
|
||||
.\" * you should have received as part of this distribution. The terms
|
||||
.\" * are also available at https://curl.haxx.se/docs/copyright.html.
|
||||
.\" *
|
||||
.\" * You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
.\" * copies of the Software, and permit persons to whom the Software is
|
||||
.\" * furnished to do so, under the terms of the COPYING file.
|
||||
.\" *
|
||||
.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
.\" * KIND, either express or implied.
|
||||
.\" *
|
||||
.\" **************************************************************************
|
||||
.TH curl_mime_data 3 "22 August 2017" "libcurl 7.56.0" "libcurl Manual"
|
||||
.SH NAME
|
||||
curl_mime_data - set a mime part's body data from memory
|
||||
.SH SYNOPSIS
|
||||
.B #include <curl/curl.h>
|
||||
.sp
|
||||
.BI "CURLcode curl_mime_data(curl_mimepart * " part ", const char * " data
|
||||
.BI ", ssize_t " datasize ");"
|
||||
.ad
|
||||
.SH DESCRIPTION
|
||||
curl_mime_data() sets a mime part's body content from memory data.
|
||||
|
||||
\fIdata\fP points to the data bytes: those are copied to the part and their
|
||||
storage may safely be reused after call.
|
||||
\fIdatasize\fP is the number of data bytes: it can be set to -1 to indicate
|
||||
\fIdata\fP is a nul-terminated character string.
|
||||
\fIpart\fP is the part's to assign contents to.
|
||||
|
||||
Setting a part's contents twice is valid: only the value set by the last call
|
||||
is retained. It is possible to unassign part's contents by setting
|
||||
\fIdata\fP to NULL.
|
||||
|
||||
Setting very large data is memory consuming: one might consider using
|
||||
\fIcurl_mime_data_cb\fP() in such a case.
|
||||
|
||||
.SH AVAILABILITY
|
||||
As long as at least one of HTTP, SMTP or IMAP is enabled. Added in 7.56.0.
|
||||
.SH RETURN VALUE
|
||||
CURLE_OK or a CURL error code upon failure.
|
||||
|
||||
.SH "SEE ALSO"
|
||||
.BR curl_mime_addpart "(3),"
|
||||
.BR curl_mime_data_cb "(3)"
|
154
docs/libcurl/curl_mime_data_cb.3
Normal file
154
docs/libcurl/curl_mime_data_cb.3
Normal file
@ -0,0 +1,154 @@
|
||||
.\" **************************************************************************
|
||||
.\" * _ _ ____ _
|
||||
.\" * Project ___| | | | _ \| |
|
||||
.\" * / __| | | | |_) | |
|
||||
.\" * | (__| |_| | _ <| |___
|
||||
.\" * \___|\___/|_| \_\_____|
|
||||
.\" *
|
||||
.\" * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
.\" *
|
||||
.\" * This software is licensed as described in the file COPYING, which
|
||||
.\" * you should have received as part of this distribution. The terms
|
||||
.\" * are also available at https://curl.haxx.se/docs/copyright.html.
|
||||
.\" *
|
||||
.\" * You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
.\" * copies of the Software, and permit persons to whom the Software is
|
||||
.\" * furnished to do so, under the terms of the COPYING file.
|
||||
.\" *
|
||||
.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
.\" * KIND, either express or implied.
|
||||
.\" *
|
||||
.\" **************************************************************************
|
||||
.TH curl_mime_data_cb 3 "22 August 2017" "libcurl 7.56.0" "libcurl Manual"
|
||||
.SH NAME
|
||||
curl_mime_data_cb - set a callback-based data source for a mime part's body
|
||||
.SH SYNOPSIS
|
||||
.B #include <curl/curl.h>
|
||||
.sp
|
||||
size_t readfunc(char *buffer, size_t size, size_t nitems, void *arg);
|
||||
.br
|
||||
int seekfunc(void *arg, curl_off_t offset, int origin);
|
||||
.br
|
||||
void freefunc(void *arg);
|
||||
.sp
|
||||
.BI "CURLcode curl_mime_data(curl_mimepart * " part ", curl_off_t " datasize ,
|
||||
.br
|
||||
.BI " curl_read_callback " readfunc ", curl_seek_callback " seekfunc ,
|
||||
.br
|
||||
.BI " curl_free_callback " freefunc ", void * " arg ");"
|
||||
.ad
|
||||
.SH DESCRIPTION
|
||||
curl_mime_data_cb() sets the data source of a mime part's body content from
|
||||
a data read callback function.
|
||||
|
||||
\fIpart\fP is the part's to assign contents to.
|
||||
\fIreadfunc\fP is a pointer to a data read callback function, with a
|
||||
signature as shown by the above prototype. It may not be set to NULL.
|
||||
\fIseekfunc\fP is a pointer to a seek callback function, with a
|
||||
signature as shown by the above prototype. This function will be used upon
|
||||
resending data (i.e.: after a redirect); this pointer may be set to NULL,
|
||||
in which case a resend is not possible.
|
||||
\fIfreefunc\fP is a pointer to a user resource freeing callback function, with
|
||||
a signature as shown by the above prototype. If no resource is to be freed,
|
||||
it may safely be set to NULL. This function will be called upon mime
|
||||
structure freeing.
|
||||
\fIarg\fP is a user defined argument to callback functions.
|
||||
|
||||
The read callback function gets called by libcurl as soon as it needs to
|
||||
read data in order to send it to the peer - like if you ask it to upload or
|
||||
post data to the server. The data area pointed at by the pointer \fIbuffer\fP
|
||||
should be filled up with at most \fIsize\fP multiplied with \fInmemb\fP number
|
||||
of bytes by your function.
|
||||
|
||||
Your read function must then return the actual number of bytes that it stored
|
||||
in that memory area. Returning 0 will signal end-of-file to the library and
|
||||
cause it to stop the current transfer.
|
||||
|
||||
If you stop the current transfer by returning 0 "pre-maturely" (i.e before the
|
||||
server expected it, like when you've said you will upload N bytes and you
|
||||
upload less than N bytes), you may experience that the server "hangs" waiting
|
||||
for the rest of the data that won't come.
|
||||
|
||||
The read callback may return \fICURL_READFUNC_ABORT\fP to stop the current
|
||||
operation immediately, resulting in a \fICURLE_ABORTED_BY_CALLBACK\fP error
|
||||
code from the transfer.
|
||||
|
||||
The callback can return \fICURL_READFUNC_PAUSE\fP to cause reading from this
|
||||
connection to pause. See \fIcurl_easy_pause(3)\fP for further details.
|
||||
|
||||
The seek function gets called by libcurl to rewind input stream data or to
|
||||
seek to a certain position. The function shall work like fseek(3) or lseek(3)
|
||||
and it gets SEEK_SET, SEEK_CUR or SEEK_END as argument for \fIorigin\fP,
|
||||
although libcurl currently only passes SEEK_SET.
|
||||
|
||||
The callback function must return \fICURL_SEEKFUNC_OK\fP on success,
|
||||
\fICURL_SEEKFUNC_FAIL\fP to cause the upload operation to fail or
|
||||
\fICURL_SEEKFUNC_CANTSEEK\fP to indicate that while the seek failed, libcurl
|
||||
is free to work around the problem if possible. The latter can sometimes be
|
||||
done by instead reading from the input or similar.
|
||||
|
||||
.SH AVAILABILITY
|
||||
As long as at least one of HTTP, SMTP or IMAP is enabled. Added in 7.56.0.
|
||||
.SH RETURN VALUE
|
||||
CURLE_OK or a CURL error code upon failure.
|
||||
.SH EXAMPLE
|
||||
Sending a huge data string will cause the same amount of memory to be
|
||||
allocated: to avoid overhead resources consumption, one might want to use a
|
||||
callback source to avoid data duplication. In this case, original data
|
||||
must be retained until after the transfer terminates.
|
||||
.nf
|
||||
|
||||
char hugedata[512000];
|
||||
|
||||
struct ctl {
|
||||
char *buffer;
|
||||
curl_off_t size;
|
||||
curl_off_t position;
|
||||
};
|
||||
|
||||
size_t read_callback(char *buffer, size_t size, size_t nitems, void *arg)
|
||||
{
|
||||
struct ctl *p = (struct ctl *) arg;
|
||||
curl_off_t sz = p->size - p->position;
|
||||
|
||||
nitems *= size;
|
||||
if(sz > nitems)
|
||||
sz = nitems;
|
||||
if(sz)
|
||||
memcpy(buffer, p->buffer + p->position, sz);
|
||||
p->position += sz;
|
||||
return sz;
|
||||
}
|
||||
|
||||
int seek_callback(void *arg, curl_off_t offset, int origin)
|
||||
{
|
||||
struct ctl *p = (struct ctl *) arg;
|
||||
|
||||
switch(origin) {
|
||||
case SEEK_END:
|
||||
offset += p->size;
|
||||
break;
|
||||
case SEEK_CUR:
|
||||
offset += p->position;
|
||||
break;
|
||||
}
|
||||
|
||||
if(offset < 0)
|
||||
return CURL_SEEKFUNC_FAIL;
|
||||
p->position = offset;
|
||||
return CURL_SEEKFUNC_OK;
|
||||
}
|
||||
|
||||
CURL *easy = curl_easy_init();
|
||||
curl_mime *mime = curl_mime_init(easy);
|
||||
curl_mimepart *part = curl_mime_addpart(mime);
|
||||
struct ctl hugectl;
|
||||
|
||||
hugectl.buffer = hugedata;
|
||||
hugectl.size = sizeof hugedata;
|
||||
hugectl.position = 0;
|
||||
curl_mime_data_cb(part, hugectl.size, read_callback, seek_callback, NULL,
|
||||
&hugectl);
|
||||
|
||||
.SH "SEE ALSO"
|
||||
.BR curl_mime_addpart "(3)"
|
55
docs/libcurl/curl_mime_filedata.3
Normal file
55
docs/libcurl/curl_mime_filedata.3
Normal file
@ -0,0 +1,55 @@
|
||||
.\" **************************************************************************
|
||||
.\" * _ _ ____ _
|
||||
.\" * Project ___| | | | _ \| |
|
||||
.\" * / __| | | | |_) | |
|
||||
.\" * | (__| |_| | _ <| |___
|
||||
.\" * \___|\___/|_| \_\_____|
|
||||
.\" *
|
||||
.\" * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
.\" *
|
||||
.\" * This software is licensed as described in the file COPYING, which
|
||||
.\" * you should have received as part of this distribution. The terms
|
||||
.\" * are also available at https://curl.haxx.se/docs/copyright.html.
|
||||
.\" *
|
||||
.\" * You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
.\" * copies of the Software, and permit persons to whom the Software is
|
||||
.\" * furnished to do so, under the terms of the COPYING file.
|
||||
.\" *
|
||||
.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
.\" * KIND, either express or implied.
|
||||
.\" *
|
||||
.\" **************************************************************************
|
||||
.TH curl_mime_filedata 3 "22 August 2017" "libcurl 7.56.0" "libcurl Manual"
|
||||
.SH NAME
|
||||
curl_mime_filedata - set a mime part's body data from a file contents
|
||||
.SH SYNOPSIS
|
||||
.B #include <curl/curl.h>
|
||||
.sp
|
||||
.BI "CURLcode curl_mime_filedata(curl_mimepart * " part ,
|
||||
.BI " const char * " filename ");"
|
||||
.ad
|
||||
.SH DESCRIPTION
|
||||
curl_mime_filedata() sets a mime part's body content from the named file's
|
||||
contents.
|
||||
|
||||
\fIpart\fP is the part's to assign contents to.
|
||||
\fIfilename\fP points to the nul-terminated file's path name. The pointer can
|
||||
be NULL to detach previous part contents settings.
|
||||
If \fIfilename\fP is "-", part contents data will be read from stdin.
|
||||
Filename storage can be safely be reused after this call.
|
||||
|
||||
As a side effect, the part's remote file name is set to the base name of the
|
||||
given \fIfilename\fP if it is a valid named file. This can be undone or
|
||||
overriden by a subsequent call to \fIcurl_mime_filename\fP().
|
||||
|
||||
Setting a part's contents twice is valid: only the value set by the last call
|
||||
is retained.
|
||||
|
||||
.SH AVAILABILITY
|
||||
As long as at least one of HTTP, SMTP or IMAP is enabled. Added in 7.56.0.
|
||||
.SH RETURN VALUE
|
||||
CURLE_OK or a CURL error code upon failure.
|
||||
|
||||
.SH "SEE ALSO"
|
||||
.BR curl_mime_addpart "(3),"
|
||||
.BR curl_mime_filename "(3)"
|
51
docs/libcurl/curl_mime_filename.3
Normal file
51
docs/libcurl/curl_mime_filename.3
Normal file
@ -0,0 +1,51 @@
|
||||
.\" **************************************************************************
|
||||
.\" * _ _ ____ _
|
||||
.\" * Project ___| | | | _ \| |
|
||||
.\" * / __| | | | |_) | |
|
||||
.\" * | (__| |_| | _ <| |___
|
||||
.\" * \___|\___/|_| \_\_____|
|
||||
.\" *
|
||||
.\" * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
.\" *
|
||||
.\" * This software is licensed as described in the file COPYING, which
|
||||
.\" * you should have received as part of this distribution. The terms
|
||||
.\" * are also available at https://curl.haxx.se/docs/copyright.html.
|
||||
.\" *
|
||||
.\" * You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
.\" * copies of the Software, and permit persons to whom the Software is
|
||||
.\" * furnished to do so, under the terms of the COPYING file.
|
||||
.\" *
|
||||
.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
.\" * KIND, either express or implied.
|
||||
.\" *
|
||||
.\" **************************************************************************
|
||||
.TH curl_mime_filename 3 "22 August 2017" "libcurl 7.56.0" "libcurl Manual"
|
||||
.SH NAME
|
||||
curl_mime_filename - set a mime part's remote file name
|
||||
.SH SYNOPSIS
|
||||
.B #include <curl/curl.h>
|
||||
.sp
|
||||
.BI "CURLcode curl_mime_filename(curl_mimepart * " part ,
|
||||
.BI "const char * " filename ");"
|
||||
.ad
|
||||
.SH DESCRIPTION
|
||||
curl_mime_filename() sets a mime part's remote file name. When remote file
|
||||
name is set, content data is processed as a file, whatever is the part's
|
||||
content source. A part's remote file name is transmitted to the server in
|
||||
the associated Content-Disposition generated header.
|
||||
|
||||
\fIpart\fP is the part's handle to assign the remote file name to.
|
||||
\fIfilename\fP points to the nul-terminated file name string; it may be set to
|
||||
NULL to remove a previously attached remote file name.
|
||||
|
||||
The remote file name string is copied into the part, thus the associated
|
||||
storage may safely be released or reused after call. Setting a part's file
|
||||
name twice is valid: only the value set by the last call is retained.
|
||||
|
||||
.SH AVAILABILITY
|
||||
As long as at least one of HTTP, SMTP or IMAP is enabled. Added in 7.56.0.
|
||||
.SH RETURN VALUE
|
||||
CURLE_OK or a CURL error code upon failure.
|
||||
|
||||
.SH "SEE ALSO"
|
||||
.BR curl_mime_addpart "(3)"
|
48
docs/libcurl/curl_mime_free.3
Normal file
48
docs/libcurl/curl_mime_free.3
Normal file
@ -0,0 +1,48 @@
|
||||
.\" **************************************************************************
|
||||
.\" * _ _ ____ _
|
||||
.\" * Project ___| | | | _ \| |
|
||||
.\" * / __| | | | |_) | |
|
||||
.\" * | (__| |_| | _ <| |___
|
||||
.\" * \___|\___/|_| \_\_____|
|
||||
.\" *
|
||||
.\" * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
.\" *
|
||||
.\" * This software is licensed as described in the file COPYING, which
|
||||
.\" * you should have received as part of this distribution. The terms
|
||||
.\" * are also available at https://curl.haxx.se/docs/copyright.html.
|
||||
.\" *
|
||||
.\" * You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
.\" * copies of the Software, and permit persons to whom the Software is
|
||||
.\" * furnished to do so, under the terms of the COPYING file.
|
||||
.\" *
|
||||
.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
.\" * KIND, either express or implied.
|
||||
.\" *
|
||||
.\" **************************************************************************
|
||||
.TH curl_mime_free 3 "22 August 2017" "libcurl 7.56.0" "libcurl Manual"
|
||||
.SH NAME
|
||||
curl_mime_free - free a previously built mime structure
|
||||
.SH SYNOPSIS
|
||||
.B #include <curl/curl.h>
|
||||
.sp
|
||||
.BI "void curl_mime_free(curl_mime *" mime);
|
||||
.ad
|
||||
.SH DESCRIPTION
|
||||
curl_mime_free() is used to clean up data previously built/appended with
|
||||
\fIcurl_mime_addpart(3)\fP and other mime-handling functions.
|
||||
This must be called when the data has been used, which
|
||||
typically means after \fIcurl_easy_perform(3)\fP has been called.
|
||||
|
||||
The handle to free is the one you passed to
|
||||
the \fICURLOPT_MIMEPOST(3)\fP option: attached subparts mime structures must
|
||||
not be explicitly freed as they are by the top structure freeing.
|
||||
|
||||
\fBmime\fP is the handle as returned from a previous call to
|
||||
\fIcurl_mime_init(3)\fP and may be NULL.
|
||||
|
||||
.SH AVAILABILITY
|
||||
As long as at least one of HTTP, SMTP or IMAP is enabled. Added in 7.56.0.
|
||||
.SH RETURN VALUE
|
||||
None
|
||||
.SH "SEE ALSO"
|
||||
.BR curl_mime_init "(3)"
|
50
docs/libcurl/curl_mime_headers.3
Normal file
50
docs/libcurl/curl_mime_headers.3
Normal file
@ -0,0 +1,50 @@
|
||||
.\" **************************************************************************
|
||||
.\" * _ _ ____ _
|
||||
.\" * Project ___| | | | _ \| |
|
||||
.\" * / __| | | | |_) | |
|
||||
.\" * | (__| |_| | _ <| |___
|
||||
.\" * \___|\___/|_| \_\_____|
|
||||
.\" *
|
||||
.\" * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
.\" *
|
||||
.\" * This software is licensed as described in the file COPYING, which
|
||||
.\" * you should have received as part of this distribution. The terms
|
||||
.\" * are also available at https://curl.haxx.se/docs/copyright.html.
|
||||
.\" *
|
||||
.\" * You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
.\" * copies of the Software, and permit persons to whom the Software is
|
||||
.\" * furnished to do so, under the terms of the COPYING file.
|
||||
.\" *
|
||||
.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
.\" * KIND, either express or implied.
|
||||
.\" *
|
||||
.\" **************************************************************************
|
||||
.TH curl_mime_headers 3 "22 August 2017" "libcurl 7.56.0" "libcurl Manual"
|
||||
.SH NAME
|
||||
curl_mime_headers - set a mime part's custom headers
|
||||
.SH SYNOPSIS
|
||||
.B #include <curl/curl.h>
|
||||
.sp
|
||||
.BI "CURLcode curl_mime_headers(curl_mimepart * " part ,
|
||||
.BI "struct curl_slist * " headers ", int " take_ownership ");"
|
||||
.ad
|
||||
.SH DESCRIPTION
|
||||
curl_mime_headers() sets a mime part's custom headers.
|
||||
|
||||
\fIpart\fP is the part's handle to assign the custom headers list to.
|
||||
\fIheaders\fP is the head of a list of custom headers; it may be set to
|
||||
NULL to remove a previously attached custom header list.
|
||||
\fItake_ownership\fP: when non-zero, causes the list to be freed upon
|
||||
replacement or mime structure deletion; in this case the list must not be
|
||||
freed explicitly.
|
||||
|
||||
Setting a part's custom headers list twice is valid: only the value set by
|
||||
the last call is retained.
|
||||
|
||||
.SH AVAILABILITY
|
||||
As long as at least one of HTTP, SMTP or IMAP is enabled. Added in 7.56.0.
|
||||
.SH RETURN VALUE
|
||||
CURLE_OK or a CURL error code upon failure.
|
||||
|
||||
.SH "SEE ALSO"
|
||||
.BR curl_mime_addpart "(3)"
|
68
docs/libcurl/curl_mime_init.3
Normal file
68
docs/libcurl/curl_mime_init.3
Normal file
@ -0,0 +1,68 @@
|
||||
.\" **************************************************************************
|
||||
.\" * _ _ ____ _
|
||||
.\" * Project ___| | | | _ \| |
|
||||
.\" * / __| | | | |_) | |
|
||||
.\" * | (__| |_| | _ <| |___
|
||||
.\" * \___|\___/|_| \_\_____|
|
||||
.\" *
|
||||
.\" * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
.\" *
|
||||
.\" * This software is licensed as described in the file COPYING, which
|
||||
.\" * you should have received as part of this distribution. The terms
|
||||
.\" * are also available at https://curl.haxx.se/docs/copyright.html.
|
||||
.\" *
|
||||
.\" * You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
.\" * copies of the Software, and permit persons to whom the Software is
|
||||
.\" * furnished to do so, under the terms of the COPYING file.
|
||||
.\" *
|
||||
.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
.\" * KIND, either express or implied.
|
||||
.\" *
|
||||
.\" **************************************************************************
|
||||
.TH curl_mime_init 3 "22 August 2017" "libcurl 7.56.0" "libcurl Manual"
|
||||
.SH NAME
|
||||
curl_mime_init - create a mime handle
|
||||
.SH SYNOPSIS
|
||||
.B #include <curl/curl.h>
|
||||
.sp
|
||||
.BI "curl_mime * curl_mime_init(CURL * " easy_handle ");"
|
||||
.ad
|
||||
.SH DESCRIPTION
|
||||
curl_mime_init() 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\fP within a \fIcurl_easy_setopt\fP() call.
|
||||
|
||||
Using a mime handle is the recommended way to post an HTTP form, format and
|
||||
send a multi-part e-mail with SMTP or upload such an e-mail to an IMAP server.
|
||||
|
||||
.SH AVAILABILITY
|
||||
As long as at least one of HTTP, SMTP or IMAP is enabled. Added in 7.56.0.
|
||||
.SH RETURN VALUE
|
||||
A mime struct handle, or NULL upon failure.
|
||||
.SH EXAMPLE
|
||||
.nf
|
||||
|
||||
CURL *easy = curl_easy_init();
|
||||
struct curl_mime *mime;
|
||||
struct mimepart *part;
|
||||
|
||||
/* Build an HTTP form with a single field named "data", */
|
||||
mime = curl_mime_init(easy);
|
||||
part = curl_mime_addpart(mime);
|
||||
curl_mime_data(part, "This is the field data", -1);
|
||||
curl_mime_name(part, "data", -1);
|
||||
|
||||
/* Post and send it. */
|
||||
curl_easy_setopt(easy, CURLOPT_MIMEPOST, mime);
|
||||
curl_easy_setopt(easy, CURLOPT_URL, "http://example.com");
|
||||
curl_easy_perform(easy);
|
||||
|
||||
/* Clean-up. */
|
||||
curl_easy_cleanup(easy);
|
||||
curl_mime_free(mime);
|
||||
|
||||
.SH "SEE ALSO"
|
||||
.BR curl_mime_addpart "(3),"
|
||||
.BR curl_mime_free "(3),"
|
||||
.BR CURLOPT_MIMEPOST "(3)"
|
52
docs/libcurl/curl_mime_name.3
Normal file
52
docs/libcurl/curl_mime_name.3
Normal file
@ -0,0 +1,52 @@
|
||||
.\" **************************************************************************
|
||||
.\" * _ _ ____ _
|
||||
.\" * Project ___| | | | _ \| |
|
||||
.\" * / __| | | | |_) | |
|
||||
.\" * | (__| |_| | _ <| |___
|
||||
.\" * \___|\___/|_| \_\_____|
|
||||
.\" *
|
||||
.\" * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
.\" *
|
||||
.\" * This software is licensed as described in the file COPYING, which
|
||||
.\" * you should have received as part of this distribution. The terms
|
||||
.\" * are also available at https://curl.haxx.se/docs/copyright.html.
|
||||
.\" *
|
||||
.\" * You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
.\" * copies of the Software, and permit persons to whom the Software is
|
||||
.\" * furnished to do so, under the terms of the COPYING file.
|
||||
.\" *
|
||||
.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
.\" * KIND, either express or implied.
|
||||
.\" *
|
||||
.\" **************************************************************************
|
||||
.TH curl_mime_name 3 "22 August 2017" "libcurl 7.56.0" "libcurl Manual"
|
||||
.SH NAME
|
||||
curl_mime_name - set a mime part's name
|
||||
.SH SYNOPSIS
|
||||
.B #include <curl/curl.h>
|
||||
.sp
|
||||
.BI "CURLcode curl_mime_name(curl_mimepart * " part ", const char * " name
|
||||
.BI ", ssize_t " namesize ");"
|
||||
.ad
|
||||
.SH DESCRIPTION
|
||||
curl_mime_name() sets a mime part's name. This is the way HTTP form fields are
|
||||
named.
|
||||
|
||||
\fIname\fP points to the name byte string; the string may contain nul bytes
|
||||
unless \fInamesize\fP is -1.
|
||||
\fInamesize\fP is the name length: it can be set to -1 to indicate
|
||||
\fIname\fP is a nul-terminated string.
|
||||
\fIpart\fP is the part's handle to assign a name to.
|
||||
|
||||
The name string is copied into the part, thus the associated storage may safely
|
||||
be released or reused after call. Setting a part's name twice is valid:
|
||||
only the value set by the last call is retained. It is possible to "unname"
|
||||
a part by setting \fIname\fP to NULL.
|
||||
|
||||
.SH AVAILABILITY
|
||||
As long as at least one of HTTP, SMTP or IMAP is enabled. Added in 7.56.0.
|
||||
.SH RETURN VALUE
|
||||
CURLE_OK or a CURL error code upon failure.
|
||||
|
||||
.SH "SEE ALSO"
|
||||
.BR curl_mime_addpart "(3)"
|
52
docs/libcurl/curl_mime_subparts.3
Normal file
52
docs/libcurl/curl_mime_subparts.3
Normal file
@ -0,0 +1,52 @@
|
||||
.\" **************************************************************************
|
||||
.\" * _ _ ____ _
|
||||
.\" * Project ___| | | | _ \| |
|
||||
.\" * / __| | | | |_) | |
|
||||
.\" * | (__| |_| | _ <| |___
|
||||
.\" * \___|\___/|_| \_\_____|
|
||||
.\" *
|
||||
.\" * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
.\" *
|
||||
.\" * This software is licensed as described in the file COPYING, which
|
||||
.\" * you should have received as part of this distribution. The terms
|
||||
.\" * are also available at https://curl.haxx.se/docs/copyright.html.
|
||||
.\" *
|
||||
.\" * You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
.\" * copies of the Software, and permit persons to whom the Software is
|
||||
.\" * furnished to do so, under the terms of the COPYING file.
|
||||
.\" *
|
||||
.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
.\" * KIND, either express or implied.
|
||||
.\" *
|
||||
.\" **************************************************************************
|
||||
.TH curl_mime_subparts 3 "22 August 2017" "libcurl 7.56.0" "libcurl Manual"
|
||||
.SH NAME
|
||||
curl_mime_subparts - set subparts of a multipart mime part
|
||||
.SH SYNOPSIS
|
||||
.B #include <curl/curl.h>
|
||||
.sp
|
||||
.BI "CURLcode curl_mime_subparts(curl_mimepart * " part ,
|
||||
.BI "curl_mime * " subparts ");"
|
||||
.ad
|
||||
.SH DESCRIPTION
|
||||
curl_mime_subparts() sets a multipart mime part's content from a mime
|
||||
structure.
|
||||
|
||||
\fIpart\fP is a handle to the multipart part.
|
||||
\fIsubparts\fP is a mime structure handle holding the subparts. After
|
||||
\fIcurl_mime_subparts\fP succeeds, the mime structure handle belongs to the
|
||||
multipart part and must not be freed explicitly. It may however be updated
|
||||
by subsequent calls to mime API functions.
|
||||
|
||||
Setting a part's contents twice is valid: only the value set by the last call
|
||||
is retained. It is possible to unassign previous part's contents by setting
|
||||
\fIsubparts\fP to NULL.
|
||||
|
||||
.SH AVAILABILITY
|
||||
As long as at least one of HTTP, SMTP or IMAP is enabled. Added in 7.56.0.
|
||||
.SH RETURN VALUE
|
||||
CURLE_OK or a CURL error code upon failure.
|
||||
|
||||
.SH "SEE ALSO"
|
||||
.BR curl_mime_addpart "(3),"
|
||||
.BR curl_mime_init "(3)"
|
62
docs/libcurl/curl_mime_type.3
Normal file
62
docs/libcurl/curl_mime_type.3
Normal file
@ -0,0 +1,62 @@
|
||||
.\" **************************************************************************
|
||||
.\" * _ _ ____ _
|
||||
.\" * Project ___| | | | _ \| |
|
||||
.\" * / __| | | | |_) | |
|
||||
.\" * | (__| |_| | _ <| |___
|
||||
.\" * \___|\___/|_| \_\_____|
|
||||
.\" *
|
||||
.\" * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
.\" *
|
||||
.\" * This software is licensed as described in the file COPYING, which
|
||||
.\" * you should have received as part of this distribution. The terms
|
||||
.\" * are also available at https://curl.haxx.se/docs/copyright.html.
|
||||
.\" *
|
||||
.\" * You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
.\" * copies of the Software, and permit persons to whom the Software is
|
||||
.\" * furnished to do so, under the terms of the COPYING file.
|
||||
.\" *
|
||||
.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
.\" * KIND, either express or implied.
|
||||
.\" *
|
||||
.\" **************************************************************************
|
||||
.TH curl_mime_type 3 "22 August 2017" "libcurl 7.56.0" "libcurl Manual"
|
||||
.SH NAME
|
||||
curl_mime_type - set a mime part's content type
|
||||
.SH SYNOPSIS
|
||||
.B #include <curl/curl.h>
|
||||
.sp
|
||||
.BI "CURLcode curl_mime_type(curl_mimepart * " part ,
|
||||
.BI "const char * " mimetype ");"
|
||||
.ad
|
||||
.SH DESCRIPTION
|
||||
curl_mime_type() sets a mime part's content type.
|
||||
|
||||
\fIpart\fP is the part's handle to assign the content type to.
|
||||
\fImimetype\fP points to the nul-terminated file mime type string; it may be
|
||||
set to NULL to remove a previously attached mime type.
|
||||
|
||||
The mime type string is copied into the part, thus the associated
|
||||
storage may safely be released or reused after call. Setting a part's type
|
||||
twice is valid: only the value set by the last call is retained.
|
||||
|
||||
In the absence of a mime type and if needed by the protocol specifications,
|
||||
a default mime type is determined by the context:
|
||||
.br
|
||||
- If set as a custom header, use this value.
|
||||
.br
|
||||
- application/form-data for a HTTP form post.
|
||||
.br
|
||||
- If a remote file name is set, the mime type is taken from the file name
|
||||
extension, or application/octet-stream by default.
|
||||
.br
|
||||
- For a multipart part, multipart/mixed.
|
||||
.br
|
||||
- text/plain in other cases.
|
||||
|
||||
.SH AVAILABILITY
|
||||
As long as at least one of HTTP, SMTP or IMAP is enabled. Added in 7.56.0.
|
||||
.SH RETURN VALUE
|
||||
CURLE_OK or a CURL error code upon failure.
|
||||
|
||||
.SH "SEE ALSO"
|
||||
.BR curl_mime_addpart "(3)"
|
@ -5,7 +5,7 @@
|
||||
.\" * | (__| |_| | _ <| |___
|
||||
.\" * \___|\___/|_| \_\_____|
|
||||
.\" *
|
||||
.\" * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
.\" * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
.\" *
|
||||
.\" * This software is licensed as described in the file COPYING, which
|
||||
.\" * you should have received as part of this distribution. The terms
|
||||
@ -42,6 +42,9 @@ You can disable this header with \fICURLOPT_HTTPHEADER(3)\fP.
|
||||
|
||||
When setting \fICURLOPT_HTTPPOST(3)\fP, it will automatically set
|
||||
\fICURLOPT_NOBODY(3)\fP to 0.
|
||||
|
||||
This option is deprecated! Do not use it. Use \fICURLOPT_MIMEPOST(3)\fP
|
||||
instead after having prepared mime data.
|
||||
.SH DEFAULT
|
||||
NULL
|
||||
.SH PROTOCOLS
|
||||
@ -71,9 +74,9 @@ curl_formadd(&formpost,
|
||||
CURLFORM_END);
|
||||
.fi
|
||||
.SH AVAILABILITY
|
||||
As long as HTTP is enabled
|
||||
As long as HTTP is enabled. Deprecated in 7.56.0.
|
||||
.SH RETURN VALUE
|
||||
Returns CURLE_OK if HTTP is enabled, and CURLE_UNKNOWN_OPTION if not.
|
||||
.SH "SEE ALSO"
|
||||
.BR CURLOPT_POSTFIELDS "(3), " CURLOPT_POST "(3), "
|
||||
.BR curl_formadd "(3), " curl_formfree "(3), "
|
||||
.BR CURLOPT_POSTFIELDS "(3), " CURLOPT_POST "(3), " CURLOPT_MIMEPOST "(3),"
|
||||
.BR curl_formadd "(3), " curl_formfree "(3), " curl_mime_init "(3)"
|
||||
|
52
docs/libcurl/opts/CURLOPT_MIMEPOST.3
Normal file
52
docs/libcurl/opts/CURLOPT_MIMEPOST.3
Normal file
@ -0,0 +1,52 @@
|
||||
.\" **************************************************************************
|
||||
.\" * _ _ ____ _
|
||||
.\" * Project ___| | | | _ \| |
|
||||
.\" * / __| | | | |_) | |
|
||||
.\" * | (__| |_| | _ <| |___
|
||||
.\" * \___|\___/|_| \_\_____|
|
||||
.\" *
|
||||
.\" * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
.\" *
|
||||
.\" * This software is licensed as described in the file COPYING, which
|
||||
.\" * you should have received as part of this distribution. The terms
|
||||
.\" * are also available at https://curl.haxx.se/docs/copyright.html.
|
||||
.\" *
|
||||
.\" * You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
.\" * copies of the Software, and permit persons to whom the Software is
|
||||
.\" * furnished to do so, under the terms of the COPYING file.
|
||||
.\" *
|
||||
.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
.\" * KIND, either express or implied.
|
||||
.\" *
|
||||
.\" **************************************************************************
|
||||
.\"
|
||||
.TH CURLOPT_MIMEPOST 3 "22 Aug 2017" "libcurl 7.56.0" "curl_easy_setopt options"
|
||||
.SH NAME
|
||||
CURLOPT_MIMEPOST \- set post/send data from mime structure
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
#include <curl/curl.h>
|
||||
|
||||
curl_mime *mime;
|
||||
|
||||
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_MIMEPOST, mime);
|
||||
.SH DESCRIPTION
|
||||
Pass a mime handle previously obtained from \fIcurl_mime_init()\fP.
|
||||
|
||||
This setting is supported by the HTTP protocol to post forms and by the
|
||||
SMTP and IMAP protocols to provide the e-mail data to send/upload.
|
||||
|
||||
This option is the preferred way of posting an HTTP form, replacing
|
||||
and extending the deprecated \fICURLOPT_HTTPPOST\fP option.
|
||||
.SH PROTOCOLS
|
||||
HTTP, SMTP, IMAP.
|
||||
.SH AVAILABILITY
|
||||
Since 7.56.0.
|
||||
.SH RETURN VALUE
|
||||
This will return CURLE_OK.
|
||||
.SH EXAMPLE
|
||||
Using this option implies the use of several mime structure building
|
||||
functions: see https://curl.haxx.se/libcurl/c/smtp-mime.html for a complete
|
||||
example.
|
||||
.SH "SEE ALSO"
|
||||
.BR curl_mime_init "(3)"
|
@ -175,6 +175,7 @@ man_MANS = \
|
||||
CURLOPT_MAXREDIRS.3 \
|
||||
CURLOPT_MAX_RECV_SPEED_LARGE.3 \
|
||||
CURLOPT_MAX_SEND_SPEED_LARGE.3 \
|
||||
CURLOPT_MIMEPOST.3 \
|
||||
CURLOPT_NETRC.3 \
|
||||
CURLOPT_NETRC_FILE.3 \
|
||||
CURLOPT_NEW_DIRECTORY_PERMS.3 \
|
||||
|
@ -441,6 +441,7 @@ CURLOPT_MAXFILESIZE_LARGE 7.11.0
|
||||
CURLOPT_MAXREDIRS 7.5
|
||||
CURLOPT_MAX_RECV_SPEED_LARGE 7.15.5
|
||||
CURLOPT_MAX_SEND_SPEED_LARGE 7.15.5
|
||||
CURLOPT_MIMEPOST 7.56.0
|
||||
CURLOPT_MUTE 7.1 7.8 7.15.5
|
||||
CURLOPT_NETRC 7.1
|
||||
CURLOPT_NETRC_FILE 7.11.0
|
||||
|
@ -1791,6 +1791,9 @@ typedef enum {
|
||||
/* Enable/disable SSH compression */
|
||||
CINIT(SSH_COMPRESSION, LONG, 268),
|
||||
|
||||
/* Post MIME data. */
|
||||
CINIT(MIMEPOST, OBJECTPOINT, 269),
|
||||
|
||||
CURLOPT_LASTENTRY /* the last unused */
|
||||
} CURLoption;
|
||||
|
||||
@ -1946,6 +1949,133 @@ typedef enum {
|
||||
CURL_EXTERN int (curl_strequal)(const char *s1, const char *s2);
|
||||
CURL_EXTERN int (curl_strnequal)(const char *s1, const char *s2, size_t n);
|
||||
|
||||
/* Mime/form handling support. */
|
||||
typedef struct Curl_mime curl_mime; /* Mime context. */
|
||||
typedef struct Curl_mimepart curl_mimepart; /* Mime part context. */
|
||||
|
||||
/*
|
||||
* NAME curl_mime_init()
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* Create a mime context and return its handle. The easy parameter is the
|
||||
* target handle.
|
||||
*/
|
||||
CURL_EXTERN curl_mime *curl_mime_init(CURL *easy);
|
||||
|
||||
/*
|
||||
* NAME curl_mime_free()
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* release a mime handle and its substructures.
|
||||
*/
|
||||
CURL_EXTERN void curl_mime_free(curl_mime *mime);
|
||||
|
||||
/*
|
||||
* NAME curl_mime_addpart()
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* Append a new empty part to the given mime context and return a handle to
|
||||
* the created part.
|
||||
*/
|
||||
CURL_EXTERN curl_mimepart *curl_mime_addpart(curl_mime *mime);
|
||||
|
||||
/*
|
||||
* NAME curl_mime_name()
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* Set mime/form part name.
|
||||
*/
|
||||
CURL_EXTERN CURLcode curl_mime_name(curl_mimepart *part,
|
||||
const char *name, ssize_t namesize);
|
||||
|
||||
/*
|
||||
* NAME curl_mime_filename()
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* Set mime part remote file name.
|
||||
*/
|
||||
CURL_EXTERN CURLcode curl_mime_filename(curl_mimepart *part,
|
||||
const char *filename);
|
||||
|
||||
/*
|
||||
* NAME curl_mime_type()
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* Set mime part type.
|
||||
*/
|
||||
CURL_EXTERN CURLcode curl_mime_type(curl_mimepart *part, const char *mimetype);
|
||||
|
||||
/*
|
||||
* NAME curl_mime_encoder()
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* Set mime data transfer encoder.
|
||||
*/
|
||||
CURL_EXTERN CURLcode curl_mime_encoder(struct Curl_mimepart *part,
|
||||
const char *encoding);
|
||||
|
||||
/*
|
||||
* NAME curl_mime_data()
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* Set mime part data source from memory data,
|
||||
*/
|
||||
CURL_EXTERN CURLcode curl_mime_data(curl_mimepart *part,
|
||||
const char *data, ssize_t datasize);
|
||||
|
||||
/*
|
||||
* NAME curl_mime_filedata()
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* Set mime part data source from named file.
|
||||
*/
|
||||
CURL_EXTERN CURLcode curl_mime_filedata(curl_mimepart *part,
|
||||
const char *filename);
|
||||
|
||||
/*
|
||||
* NAME curl_mime_data_cb()
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* Set mime part data source from callback function.
|
||||
*/
|
||||
CURL_EXTERN CURLcode curl_mime_data_cb(curl_mimepart *part,
|
||||
curl_off_t datasize,
|
||||
curl_read_callback readfunc,
|
||||
curl_seek_callback seekfunc,
|
||||
curl_free_callback freefunc,
|
||||
void *arg);
|
||||
|
||||
/*
|
||||
* NAME curl_mime_subparts()
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* Set mime part data source from subparts.
|
||||
*/
|
||||
CURL_EXTERN CURLcode curl_mime_subparts(curl_mimepart *part,
|
||||
curl_mime *subparts);
|
||||
/*
|
||||
* NAME curl_mime_headers()
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* Set mime part headers.
|
||||
*/
|
||||
CURL_EXTERN CURLcode curl_mime_headers(curl_mimepart *part,
|
||||
struct curl_slist *headers,
|
||||
int take_ownership);
|
||||
|
||||
/* Old form API. */
|
||||
/* name is uppercase CURLFORM_<name> */
|
||||
#ifdef CFINIT
|
||||
#undef CFINIT
|
||||
|
@ -96,6 +96,9 @@ __extension__ ({ \
|
||||
if((_curl_opt) == CURLOPT_HTTPPOST) \
|
||||
if(!_curl_is_arr((value), struct curl_httppost)) \
|
||||
_curl_easy_setopt_err_curl_httpost(); \
|
||||
if((_curl_opt) == CURLOPT_MIMEPOST) \
|
||||
if(!_curl_is_ptr((value), curl_mime)) \
|
||||
_curl_easy_setopt_err_curl_mimepost(); \
|
||||
if(_curl_is_slist_option(_curl_opt)) \
|
||||
if(!_curl_is_arr((value), struct curl_slist)) \
|
||||
_curl_easy_setopt_err_curl_slist(); \
|
||||
@ -200,6 +203,9 @@ _CURL_WARNING(_curl_easy_setopt_err_postfields,
|
||||
_CURL_WARNING(_curl_easy_setopt_err_curl_httpost,
|
||||
"curl_easy_setopt expects a 'struct curl_httppost *' "
|
||||
"argument for this option")
|
||||
_CURL_WARNING(_curl_easy_setopt_err_curl_mimepost,
|
||||
"curl_easy_setopt expects a 'curl_mime *' "
|
||||
"argument for this option")
|
||||
_CURL_WARNING(_curl_easy_setopt_err_curl_slist,
|
||||
"curl_easy_setopt expects a 'struct curl_slist *' argument for this option")
|
||||
_CURL_WARNING(_curl_easy_setopt_err_CURLSH,
|
||||
|
@ -53,7 +53,8 @@ LIB_CFILES = file.c timeval.c base64.c hostip.c progress.c formdata.c \
|
||||
http_proxy.c non-ascii.c asyn-ares.c asyn-thread.c curl_gssapi.c \
|
||||
http_ntlm.c curl_ntlm_wb.c curl_ntlm_core.c curl_sasl.c rand.c \
|
||||
curl_multibyte.c hostcheck.c conncache.c pipeline.c dotdot.c \
|
||||
x509asn1.c http2.c smb.c curl_endian.c curl_des.c system_win32.c
|
||||
x509asn1.c http2.c smb.c curl_endian.c curl_des.c system_win32.c \
|
||||
mime.c
|
||||
|
||||
LIB_HFILES = arpa_telnet.h netrc.h file.h timeval.h hostip.h progress.h \
|
||||
formdata.h cookie.h http.h sendf.h ftp.h url.h dict.h if2ip.h \
|
||||
@ -72,7 +73,7 @@ LIB_HFILES = arpa_telnet.h netrc.h file.h timeval.h hostip.h progress.h \
|
||||
curl_sasl.h curl_multibyte.h hostcheck.h conncache.h \
|
||||
curl_setup_once.h multihandle.h setup-vms.h pipeline.h dotdot.h \
|
||||
x509asn1.h http2.h sigpipe.h smb.h curl_endian.h curl_des.h \
|
||||
curl_printf.h system_win32.h rand.h
|
||||
curl_printf.h system_win32.h rand.h mime.h
|
||||
|
||||
LIB_RCFILES = libcurl.rc
|
||||
|
||||
|
833
lib/formdata.c
833
lib/formdata.c
@ -32,6 +32,8 @@
|
||||
|
||||
#include "urldata.h" /* for struct Curl_easy */
|
||||
#include "formdata.h"
|
||||
#include "mime.h"
|
||||
#include "non-ascii.h"
|
||||
#include "vtls/vtls.h"
|
||||
#include "strcase.h"
|
||||
#include "sendf.h"
|
||||
@ -42,13 +44,6 @@
|
||||
#include "curl_memory.h"
|
||||
#include "memdebug.h"
|
||||
|
||||
#ifndef HAVE_BASENAME
|
||||
static char *Curl_basename(char *path);
|
||||
#define basename(x) Curl_basename((x))
|
||||
#endif
|
||||
|
||||
static size_t readfromfile(struct Form *form, char *buffer, size_t size);
|
||||
static CURLcode formboundary(struct Curl_easy *data, char *buffer, size_t len);
|
||||
|
||||
/* What kind of Content-Type to use on un-specified files with unrecognized
|
||||
extensions. */
|
||||
@ -746,211 +741,6 @@ CURLFORMcode curl_formadd(struct curl_httppost **httppost,
|
||||
return result;
|
||||
}
|
||||
|
||||
#ifdef __VMS
|
||||
#include <fabdef.h>
|
||||
/*
|
||||
* get_vms_file_size does what it takes to get the real size of the file
|
||||
*
|
||||
* For fixed files, find out the size of the EOF block and adjust.
|
||||
*
|
||||
* For all others, have to read the entire file in, discarding the contents.
|
||||
* Most posted text files will be small, and binary files like zlib archives
|
||||
* and CD/DVD images should be either a STREAM_LF format or a fixed format.
|
||||
*
|
||||
*/
|
||||
curl_off_t VmsRealFileSize(const char *name,
|
||||
const struct_stat *stat_buf)
|
||||
{
|
||||
char buffer[8192];
|
||||
curl_off_t count;
|
||||
int ret_stat;
|
||||
FILE * file;
|
||||
|
||||
file = fopen(name, FOPEN_READTEXT); /* VMS */
|
||||
if(file == NULL)
|
||||
return 0;
|
||||
|
||||
count = 0;
|
||||
ret_stat = 1;
|
||||
while(ret_stat > 0) {
|
||||
ret_stat = fread(buffer, 1, sizeof(buffer), file);
|
||||
if(ret_stat != 0)
|
||||
count += ret_stat;
|
||||
}
|
||||
fclose(file);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* VmsSpecialSize checks to see if the stat st_size can be trusted and
|
||||
* if not to call a routine to get the correct size.
|
||||
*
|
||||
*/
|
||||
static curl_off_t VmsSpecialSize(const char *name,
|
||||
const struct_stat *stat_buf)
|
||||
{
|
||||
switch(stat_buf->st_fab_rfm) {
|
||||
case FAB$C_VAR:
|
||||
case FAB$C_VFC:
|
||||
return VmsRealFileSize(name, stat_buf);
|
||||
break;
|
||||
default:
|
||||
return stat_buf->st_size;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef __VMS
|
||||
#define filesize(name, stat_data) (stat_data.st_size)
|
||||
#else
|
||||
/* Getting the expected file size needs help on VMS */
|
||||
#define filesize(name, stat_data) VmsSpecialSize(name, &stat_data)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* AddFormData() adds a chunk of data to the FormData linked list.
|
||||
*
|
||||
* size is incremented by the chunk length, unless it is NULL
|
||||
*/
|
||||
static CURLcode AddFormData(struct FormData **formp,
|
||||
enum formtype type,
|
||||
const void *line,
|
||||
curl_off_t length,
|
||||
curl_off_t *size)
|
||||
{
|
||||
struct FormData *newform;
|
||||
char *alloc2 = NULL;
|
||||
CURLcode result = CURLE_OK;
|
||||
if(length < 0 || (size && *size < 0))
|
||||
return CURLE_BAD_FUNCTION_ARGUMENT;
|
||||
|
||||
newform = malloc(sizeof(struct FormData));
|
||||
if(!newform)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
newform->next = NULL;
|
||||
|
||||
if(type <= FORM_CONTENT) {
|
||||
/* we make it easier for plain strings: */
|
||||
if(!length)
|
||||
length = strlen((char *)line);
|
||||
#if (SIZEOF_SIZE_T < CURL_SIZEOF_CURL_OFF_T)
|
||||
else if(length >= (curl_off_t)(size_t)-1) {
|
||||
result = CURLE_BAD_FUNCTION_ARGUMENT;
|
||||
goto error;
|
||||
}
|
||||
#endif
|
||||
if(type != FORM_DATAMEM) {
|
||||
newform->line = malloc((size_t)length+1);
|
||||
if(!newform->line) {
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
goto error;
|
||||
}
|
||||
alloc2 = newform->line;
|
||||
memcpy(newform->line, line, (size_t)length);
|
||||
|
||||
/* zero terminate for easier debugging */
|
||||
newform->line[(size_t)length]=0;
|
||||
}
|
||||
else {
|
||||
newform->line = (char *)line;
|
||||
type = FORM_DATA; /* in all other aspects this is just FORM_DATA */
|
||||
}
|
||||
newform->length = (size_t)length;
|
||||
}
|
||||
else
|
||||
/* For callbacks and files we don't have any actual data so we just keep a
|
||||
pointer to whatever this points to */
|
||||
newform->line = (char *)line;
|
||||
|
||||
newform->type = type;
|
||||
|
||||
if(size) {
|
||||
if(type != FORM_FILE)
|
||||
/* for static content as well as callback data we add the size given
|
||||
as input argument */
|
||||
*size += length;
|
||||
else {
|
||||
/* Since this is a file to be uploaded here, add the size of the actual
|
||||
file */
|
||||
if(strcmp("-", newform->line)) {
|
||||
struct_stat file;
|
||||
if(!stat(newform->line, &file) && !S_ISDIR(file.st_mode))
|
||||
*size += filesize(newform->line, file);
|
||||
else {
|
||||
result = CURLE_BAD_FUNCTION_ARGUMENT;
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(*formp) {
|
||||
(*formp)->next = newform;
|
||||
*formp = newform;
|
||||
}
|
||||
else
|
||||
*formp = newform;
|
||||
|
||||
return CURLE_OK;
|
||||
error:
|
||||
if(newform)
|
||||
free(newform);
|
||||
if(alloc2)
|
||||
free(alloc2);
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* AddFormDataf() adds printf()-style formatted data to the formdata chain.
|
||||
*/
|
||||
|
||||
static CURLcode AddFormDataf(struct FormData **formp,
|
||||
curl_off_t *size,
|
||||
const char *fmt, ...)
|
||||
{
|
||||
char *s;
|
||||
CURLcode result;
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
s = curl_mvaprintf(fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
if(!s)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
result = AddFormData(formp, FORM_DATAMEM, s, 0, size);
|
||||
if(result)
|
||||
free(s);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Curl_formclean() is used from http.c, this cleans a built FormData linked
|
||||
* list
|
||||
*/
|
||||
void Curl_formclean(struct FormData **form_ptr)
|
||||
{
|
||||
struct FormData *next, *form;
|
||||
|
||||
form = *form_ptr;
|
||||
if(!form)
|
||||
return;
|
||||
|
||||
do {
|
||||
next=form->next; /* the following form line */
|
||||
if(form->type <= FORM_CONTENT)
|
||||
free(form->line); /* free the line */
|
||||
free(form); /* free the struct */
|
||||
form = next;
|
||||
} while(form); /* continue */
|
||||
|
||||
*form_ptr = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* curl_formget()
|
||||
* Serialize a curl_httppost struct.
|
||||
@ -962,42 +752,34 @@ int curl_formget(struct curl_httppost *form, void *arg,
|
||||
curl_formget_callback append)
|
||||
{
|
||||
CURLcode result;
|
||||
curl_off_t size;
|
||||
struct FormData *data, *ptr;
|
||||
struct Curl_mimepart toppart;
|
||||
|
||||
result = Curl_getformdata(NULL, &data, form, NULL, &size);
|
||||
if(result)
|
||||
return (int)result;
|
||||
Curl_mime_initpart(&toppart, NULL); /* default form is empty */
|
||||
result = Curl_getformdata(NULL, &toppart, form, NULL);
|
||||
if(!result)
|
||||
result = Curl_mime_prepare_headers(&toppart, "multipart/form-data",
|
||||
NULL, MIMESTRATEGY_FORM);
|
||||
|
||||
for(ptr = data; ptr; ptr = ptr->next) {
|
||||
if((ptr->type == FORM_FILE) || (ptr->type == FORM_CALLBACK)) {
|
||||
while(!result) {
|
||||
char buffer[8192];
|
||||
size_t nread;
|
||||
struct Form temp;
|
||||
size_t nread = Curl_mime_read(buffer, 1, sizeof buffer, &toppart);
|
||||
|
||||
Curl_FormInit(&temp, ptr);
|
||||
if(!nread)
|
||||
break;
|
||||
|
||||
do {
|
||||
nread = readfromfile(&temp, buffer, sizeof(buffer));
|
||||
if((nread == (size_t) -1) ||
|
||||
(nread > sizeof(buffer)) ||
|
||||
(nread != append(arg, buffer, nread))) {
|
||||
if(temp.fp)
|
||||
fclose(temp.fp);
|
||||
Curl_formclean(&data);
|
||||
return -1;
|
||||
}
|
||||
} while(nread);
|
||||
}
|
||||
else {
|
||||
if(ptr->length != append(arg, ptr->line, ptr->length)) {
|
||||
Curl_formclean(&data);
|
||||
return -1;
|
||||
switch(nread) {
|
||||
default:
|
||||
if(append(arg, buffer, nread) != nread)
|
||||
result = CURLE_READ_ERROR;
|
||||
break;
|
||||
case CURL_READFUNC_ABORT:
|
||||
case CURL_READFUNC_PAUSE:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
Curl_formclean(&data);
|
||||
return 0;
|
||||
|
||||
Curl_mime_cleanpart(&toppart);
|
||||
return (int) result;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1031,118 +813,11 @@ void curl_formfree(struct curl_httppost *form)
|
||||
} while(form); /* continue */
|
||||
}
|
||||
|
||||
#ifndef HAVE_BASENAME
|
||||
/*
|
||||
(Quote from The Open Group Base Specifications Issue 6 IEEE Std 1003.1, 2004
|
||||
Edition)
|
||||
|
||||
The basename() function shall take the pathname pointed to by path and
|
||||
return a pointer to the final component of the pathname, deleting any
|
||||
trailing '/' characters.
|
||||
|
||||
If the string pointed to by path consists entirely of the '/' character,
|
||||
basename() shall return a pointer to the string "/". If the string pointed
|
||||
to by path is exactly "//", it is implementation-defined whether '/' or "//"
|
||||
is returned.
|
||||
|
||||
If path is a null pointer or points to an empty string, basename() shall
|
||||
return a pointer to the string ".".
|
||||
|
||||
The basename() function may modify the string pointed to by path, and may
|
||||
return a pointer to static storage that may then be overwritten by a
|
||||
subsequent call to basename().
|
||||
|
||||
The basename() function need not be reentrant. A function that is not
|
||||
required to be reentrant is not required to be thread-safe.
|
||||
|
||||
*/
|
||||
static char *Curl_basename(char *path)
|
||||
{
|
||||
/* Ignore all the details above for now and make a quick and simple
|
||||
implementaion here */
|
||||
char *s1;
|
||||
char *s2;
|
||||
|
||||
s1=strrchr(path, '/');
|
||||
s2=strrchr(path, '\\');
|
||||
|
||||
if(s1 && s2) {
|
||||
path = (s1 > s2? s1 : s2)+1;
|
||||
}
|
||||
else if(s1)
|
||||
path = s1 + 1;
|
||||
else if(s2)
|
||||
path = s2 + 1;
|
||||
|
||||
return path;
|
||||
}
|
||||
#endif
|
||||
|
||||
static char *strippath(const char *fullfile)
|
||||
{
|
||||
char *filename;
|
||||
char *base;
|
||||
filename = strdup(fullfile); /* duplicate since basename() may ruin the
|
||||
buffer it works on */
|
||||
if(!filename)
|
||||
return NULL;
|
||||
base = strdup(basename(filename));
|
||||
|
||||
free(filename); /* free temporary buffer */
|
||||
|
||||
return base; /* returns an allocated string or NULL ! */
|
||||
}
|
||||
|
||||
static CURLcode formdata_add_filename(const struct curl_httppost *file,
|
||||
struct FormData **form,
|
||||
curl_off_t *size)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
char *filename = file->showfilename;
|
||||
char *filebasename = NULL;
|
||||
char *filename_escaped = NULL;
|
||||
|
||||
if(!filename) {
|
||||
filebasename = strippath(file->contents);
|
||||
if(!filebasename)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
filename = filebasename;
|
||||
}
|
||||
|
||||
if(strchr(filename, '\\') || strchr(filename, '"')) {
|
||||
char *p0, *p1;
|
||||
|
||||
/* filename need be escaped */
|
||||
filename_escaped = malloc(strlen(filename)*2+1);
|
||||
if(!filename_escaped) {
|
||||
free(filebasename);
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
p0 = filename_escaped;
|
||||
p1 = filename;
|
||||
while(*p1) {
|
||||
if(*p1 == '\\' || *p1 == '"')
|
||||
*p0++ = '\\';
|
||||
*p0++ = *p1++;
|
||||
}
|
||||
*p0 = '\0';
|
||||
filename = filename_escaped;
|
||||
}
|
||||
result = AddFormDataf(form, size,
|
||||
"; filename=\"%s\"",
|
||||
filename);
|
||||
free(filename_escaped);
|
||||
free(filebasename);
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Curl_getformdata() converts a linked list of "meta data" into a complete
|
||||
* (possibly huge) multipart formdata. The input list is in 'post', while the
|
||||
* output resulting linked lists gets stored in '*finalform'. *sizep will get
|
||||
* the total size of the whole POST.
|
||||
* A multipart/form_data content-type is built, unless a custom content-type
|
||||
* is passed in 'custom_content_type'.
|
||||
* Curl_getformdata() converts a linked list of "meta data" into a mime
|
||||
* structure. The input list is in 'post', while the output is stored in
|
||||
* mime part at '*finalform'.
|
||||
*
|
||||
* This function will not do a failf() for the potential memory failures but
|
||||
* should for all other errors it spots. Just note that this function MAY get
|
||||
@ -1150,420 +825,112 @@ static CURLcode formdata_add_filename(const struct curl_httppost *file,
|
||||
*/
|
||||
|
||||
CURLcode Curl_getformdata(struct Curl_easy *data,
|
||||
struct FormData **finalform,
|
||||
struct Curl_mimepart *finalform,
|
||||
struct curl_httppost *post,
|
||||
const char *custom_content_type,
|
||||
curl_off_t *sizep)
|
||||
curl_read_callback fread_func)
|
||||
{
|
||||
struct FormData *form = NULL;
|
||||
struct FormData *firstform;
|
||||
struct curl_httppost *file;
|
||||
CURLcode result = CURLE_OK;
|
||||
curl_off_t size = 0; /* support potentially ENORMOUS formposts */
|
||||
char fileboundary[42];
|
||||
struct curl_slist *curList;
|
||||
char boundary[42];
|
||||
struct Curl_mime *form = NULL;
|
||||
struct Curl_mime *multipart;
|
||||
struct Curl_mimepart *part;
|
||||
struct curl_httppost *file;
|
||||
|
||||
*finalform = NULL; /* default form is empty */
|
||||
Curl_mime_cleanpart(finalform); /* default form is empty */
|
||||
|
||||
if(!post)
|
||||
return result; /* no input => no output! */
|
||||
|
||||
result = formboundary(data, boundary, sizeof(boundary));
|
||||
if(result)
|
||||
return result;
|
||||
form = curl_mime_init(data);
|
||||
if(!form)
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
|
||||
/* Make the first line of the output */
|
||||
result = AddFormDataf(&form, NULL,
|
||||
"%s; boundary=%s\r\n",
|
||||
custom_content_type?custom_content_type:
|
||||
"Content-Type: multipart/form-data",
|
||||
boundary);
|
||||
|
||||
if(result) {
|
||||
return result;
|
||||
}
|
||||
/* we DO NOT include that line in the total size of the POST, since it'll be
|
||||
part of the header! */
|
||||
|
||||
firstform = form;
|
||||
|
||||
do {
|
||||
|
||||
if(size) {
|
||||
result = AddFormDataf(&form, &size, "\r\n");
|
||||
if(result)
|
||||
break;
|
||||
}
|
||||
|
||||
/* boundary */
|
||||
result = AddFormDataf(&form, &size, "--%s\r\n", boundary);
|
||||
if(result)
|
||||
break;
|
||||
|
||||
/* Maybe later this should be disabled when a custom_content_type is
|
||||
passed, since Content-Disposition is not meaningful for all multipart
|
||||
types.
|
||||
*/
|
||||
result = AddFormDataf(&form, &size,
|
||||
"Content-Disposition: form-data; name=\"");
|
||||
if(result)
|
||||
break;
|
||||
|
||||
result = AddFormData(&form, FORM_DATA, post->name, post->namelength,
|
||||
&size);
|
||||
if(result)
|
||||
break;
|
||||
|
||||
result = AddFormDataf(&form, &size, "\"");
|
||||
if(result)
|
||||
break;
|
||||
if(!result)
|
||||
result = curl_mime_subparts(finalform, form);
|
||||
|
||||
/* Process each top part. */
|
||||
for(; !result && post; post = post->next) {
|
||||
/* If we have more than a file here, create a mime subpart and fill it. */
|
||||
multipart = form;
|
||||
if(post->more) {
|
||||
/* If used, this is a link to more file names, we must then do
|
||||
the magic to include several files with the same field name */
|
||||
|
||||
result = formboundary(data, fileboundary, sizeof(fileboundary));
|
||||
if(result) {
|
||||
break;
|
||||
part = curl_mime_addpart(form);
|
||||
if(!part)
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
if(!result)
|
||||
result = curl_mime_name(part, post->name,
|
||||
post->namelength? post->namelength: -1);
|
||||
if(!result) {
|
||||
multipart = curl_mime_init(data);
|
||||
if(!multipart)
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
if(!result)
|
||||
result = curl_mime_subparts(part, multipart);
|
||||
}
|
||||
|
||||
result = AddFormDataf(&form, &size,
|
||||
"\r\nContent-Type: multipart/mixed;"
|
||||
" boundary=%s\r\n",
|
||||
fileboundary);
|
||||
if(result)
|
||||
break;
|
||||
}
|
||||
/* Generate all the part contents. */
|
||||
for(file = post; !result && file; file = file->more) {
|
||||
/* Create the part. */
|
||||
part = curl_mime_addpart(multipart);
|
||||
if(!part)
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
|
||||
file = post;
|
||||
/* Set the headers. */
|
||||
if(!result)
|
||||
result = curl_mime_headers(part, file->contentheader, 0);
|
||||
|
||||
do {
|
||||
/* Set the content type. */
|
||||
if(!result &&file->contenttype)
|
||||
result = curl_mime_type(part, file->contenttype);
|
||||
|
||||
/* If 'showfilename' is set, that is a faked name passed on to us
|
||||
to use to in the formpost. If that is not set, the actually used
|
||||
local file name should be added. */
|
||||
/* Set field name. */
|
||||
if(!result && !post->more)
|
||||
result = curl_mime_name(part, post->name,
|
||||
post->namelength? post->namelength: -1);
|
||||
|
||||
if(post->more) {
|
||||
/* if multiple-file */
|
||||
result = AddFormDataf(&form, &size,
|
||||
"\r\n--%s\r\nContent-Disposition: "
|
||||
"attachment",
|
||||
fileboundary);
|
||||
if(result)
|
||||
break;
|
||||
result = formdata_add_filename(file, &form, &size);
|
||||
if(result)
|
||||
break;
|
||||
}
|
||||
else if(post->flags & (HTTPPOST_FILENAME|HTTPPOST_BUFFER|
|
||||
HTTPPOST_CALLBACK)) {
|
||||
/* it should be noted that for the HTTPPOST_FILENAME and
|
||||
HTTPPOST_CALLBACK cases the ->showfilename struct member is always
|
||||
assigned at this point */
|
||||
if(post->showfilename || (post->flags & HTTPPOST_FILENAME)) {
|
||||
result = formdata_add_filename(post, &form, &size);
|
||||
}
|
||||
/* Process contents. */
|
||||
if(!result) {
|
||||
curl_off_t clen = post->contentslength;
|
||||
|
||||
if(result)
|
||||
break;
|
||||
}
|
||||
if(post->flags & CURL_HTTPPOST_LARGE)
|
||||
clen = post->contentlen;
|
||||
if(!clen)
|
||||
clen = -1;
|
||||
|
||||
if(file->contenttype) {
|
||||
/* we have a specified type */
|
||||
result = AddFormDataf(&form, &size,
|
||||
"\r\nContent-Type: %s",
|
||||
file->contenttype);
|
||||
if(result)
|
||||
break;
|
||||
}
|
||||
|
||||
curList = file->contentheader;
|
||||
while(curList) {
|
||||
/* Process the additional headers specified for this form */
|
||||
result = AddFormDataf(&form, &size, "\r\n%s", curList->data);
|
||||
if(result)
|
||||
break;
|
||||
curList = curList->next;
|
||||
}
|
||||
if(result)
|
||||
break;
|
||||
|
||||
result = AddFormDataf(&form, &size, "\r\n\r\n");
|
||||
if(result)
|
||||
break;
|
||||
|
||||
if((post->flags & HTTPPOST_FILENAME) ||
|
||||
(post->flags & HTTPPOST_READFILE)) {
|
||||
/* we should include the contents from the specified file */
|
||||
FILE *fileread;
|
||||
|
||||
fileread = !strcmp("-", file->contents)?
|
||||
stdin:fopen(file->contents, "rb"); /* binary read for win32 */
|
||||
|
||||
/*
|
||||
* VMS: This only allows for stream files on VMS. Stream files are
|
||||
* OK, as are FIXED & VAR files WITHOUT implied CC For implied CC,
|
||||
* every record needs to have a \n appended & 1 added to SIZE
|
||||
*/
|
||||
|
||||
if(fileread) {
|
||||
if(fileread != stdin) {
|
||||
/* close the file */
|
||||
fclose(fileread);
|
||||
/* add the file name only - for later reading from this */
|
||||
result = AddFormData(&form, FORM_FILE, file->contents, 0, &size);
|
||||
}
|
||||
else {
|
||||
/* When uploading from stdin, we can't know the size of the file,
|
||||
* thus must read the full file as before. We *could* use chunked
|
||||
* transfer-encoding, but that only works for HTTP 1.1 and we
|
||||
* can't be sure we work with such a server.
|
||||
*/
|
||||
size_t nread;
|
||||
char buffer[512];
|
||||
while((nread = fread(buffer, 1, sizeof(buffer), fileread)) != 0) {
|
||||
result = AddFormData(&form, FORM_CONTENT, buffer, nread, &size);
|
||||
if(result || feof(fileread) || ferror(fileread))
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(data)
|
||||
failf(data, "couldn't open file \"%s\"", file->contents);
|
||||
*finalform = NULL;
|
||||
result = CURLE_READ_ERROR;
|
||||
}
|
||||
if(post->flags & (HTTPPOST_FILENAME | HTTPPOST_READFILE)) {
|
||||
result = curl_mime_filedata(part, file->contents);
|
||||
if(!result && (post->flags & HTTPPOST_READFILE))
|
||||
result = curl_mime_filename(part, NULL);
|
||||
}
|
||||
else if(post->flags & HTTPPOST_BUFFER)
|
||||
/* include contents of buffer */
|
||||
result = AddFormData(&form, FORM_CONTENT, post->buffer,
|
||||
post->bufferlength, &size);
|
||||
result = curl_mime_data(part, post->buffer,
|
||||
post->bufferlength? post->bufferlength: -1);
|
||||
else if(post->flags & HTTPPOST_CALLBACK)
|
||||
/* the contents should be read with the callback and the size is set
|
||||
with the contentslength */
|
||||
result = AddFormData(&form, FORM_CALLBACK, post->userp,
|
||||
post->flags&CURL_HTTPPOST_LARGE?
|
||||
post->contentlen:post->contentslength, &size);
|
||||
else
|
||||
/* include the contents we got */
|
||||
result = AddFormData(&form, FORM_CONTENT, post->contents,
|
||||
post->flags&CURL_HTTPPOST_LARGE?
|
||||
post->contentlen:post->contentslength, &size);
|
||||
file = file->more;
|
||||
} while(file && !result); /* for each specified file for this field */
|
||||
|
||||
if(result)
|
||||
break;
|
||||
|
||||
if(post->more) {
|
||||
/* this was a multiple-file inclusion, make a termination file
|
||||
boundary: */
|
||||
result = AddFormDataf(&form, &size,
|
||||
"\r\n--%s--",
|
||||
fileboundary);
|
||||
if(result)
|
||||
break;
|
||||
}
|
||||
post = post->next;
|
||||
} while(post); /* for each field */
|
||||
|
||||
/* end-boundary for everything */
|
||||
if(!result)
|
||||
result = AddFormDataf(&form, &size, "\r\n--%s--\r\n", boundary);
|
||||
|
||||
if(result) {
|
||||
Curl_formclean(&firstform);
|
||||
return result;
|
||||
}
|
||||
|
||||
*sizep = size;
|
||||
*finalform = firstform;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Curl_FormInit() inits the struct 'form' points to with the 'formdata'
|
||||
* and resets the 'sent' counter.
|
||||
*/
|
||||
int Curl_FormInit(struct Form *form, struct FormData *formdata)
|
||||
{
|
||||
if(!formdata)
|
||||
return 1; /* error */
|
||||
|
||||
form->data = formdata;
|
||||
form->sent = 0;
|
||||
form->fp = NULL;
|
||||
form->fread_func = ZERO_NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef __VMS
|
||||
# define fopen_read fopen
|
||||
#else
|
||||
/*
|
||||
* vmsfopenread
|
||||
*
|
||||
* For upload to work as expected on VMS, different optional
|
||||
* parameters must be added to the fopen command based on
|
||||
* record format of the file.
|
||||
*
|
||||
*/
|
||||
# define fopen_read vmsfopenread
|
||||
static FILE * vmsfopenread(const char *file, const char *mode)
|
||||
{
|
||||
struct_stat statbuf;
|
||||
int result;
|
||||
|
||||
result = stat(file, &statbuf);
|
||||
|
||||
switch(statbuf.st_fab_rfm) {
|
||||
case FAB$C_VAR:
|
||||
case FAB$C_VFC:
|
||||
case FAB$C_STMCR:
|
||||
return fopen(file, FOPEN_READTEXT); /* VMS */
|
||||
break;
|
||||
default:
|
||||
return fopen(file, FOPEN_READTEXT, "rfm=stmlf", "ctx=stm");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* readfromfile()
|
||||
*
|
||||
* The read callback that this function may use can return a value larger than
|
||||
* 'size' (which then this function returns) that indicates a problem and it
|
||||
* must be properly dealt with
|
||||
*/
|
||||
static size_t readfromfile(struct Form *form, char *buffer,
|
||||
size_t size)
|
||||
{
|
||||
size_t nread;
|
||||
bool callback = (form->data->type == FORM_CALLBACK)?TRUE:FALSE;
|
||||
|
||||
if(callback) {
|
||||
if(form->fread_func == ZERO_NULL)
|
||||
return 0;
|
||||
nread = form->fread_func(buffer, 1, size, form->data->line);
|
||||
}
|
||||
result = curl_mime_data_cb(part, clen,
|
||||
fread_func, NULL, NULL, post->userp);
|
||||
else {
|
||||
if(!form->fp) {
|
||||
/* this file hasn't yet been opened */
|
||||
form->fp = fopen_read(form->data->line, "rb"); /* b is for binary */
|
||||
if(!form->fp)
|
||||
return (size_t)-1; /* failure */
|
||||
result = curl_mime_data(part, post->contents, (ssize_t) clen);
|
||||
#ifdef CURL_DOES_CONVERSIONS
|
||||
/* Convert textual contents now. */
|
||||
if(!result && data && part->datasize)
|
||||
result = Curl_convert_to_network(data, part->data, part->datasize);
|
||||
#endif
|
||||
}
|
||||
nread = fread(buffer, 1, size, form->fp);
|
||||
}
|
||||
if(!nread) {
|
||||
/* this is the last chunk from the file, move on */
|
||||
if(form->fp) {
|
||||
fclose(form->fp);
|
||||
form->fp = NULL;
|
||||
}
|
||||
form->data = form->data->next;
|
||||
}
|
||||
|
||||
return nread;
|
||||
}
|
||||
|
||||
/*
|
||||
* Curl_FormReader() is the fread() emulation function that will be used to
|
||||
* deliver the formdata to the transfer loop and then sent away to the peer.
|
||||
*/
|
||||
size_t Curl_FormReader(char *buffer,
|
||||
size_t size,
|
||||
size_t nitems,
|
||||
FILE *mydata)
|
||||
{
|
||||
struct Form *form;
|
||||
size_t wantedsize;
|
||||
size_t gotsize = 0;
|
||||
|
||||
form=(struct Form *)mydata;
|
||||
|
||||
wantedsize = size * nitems;
|
||||
|
||||
if(!form->data)
|
||||
return 0; /* nothing, error, empty */
|
||||
|
||||
if((form->data->type == FORM_FILE) ||
|
||||
(form->data->type == FORM_CALLBACK)) {
|
||||
gotsize = readfromfile(form, buffer, wantedsize);
|
||||
|
||||
if(gotsize)
|
||||
/* If positive or -1, return. If zero, continue! */
|
||||
return gotsize;
|
||||
/* Set fake file name. */
|
||||
if(!result && post->showfilename)
|
||||
if(post->more || (post->flags & (HTTPPOST_FILENAME | HTTPPOST_BUFFER |
|
||||
HTTPPOST_CALLBACK)))
|
||||
result = curl_mime_filename(part, post->showfilename);
|
||||
}
|
||||
do {
|
||||
|
||||
if((form->data->length - form->sent) > wantedsize - gotsize) {
|
||||
|
||||
memcpy(buffer + gotsize, form->data->line + form->sent,
|
||||
wantedsize - gotsize);
|
||||
|
||||
form->sent += wantedsize-gotsize;
|
||||
|
||||
return wantedsize;
|
||||
}
|
||||
|
||||
memcpy(buffer+gotsize,
|
||||
form->data->line + form->sent,
|
||||
(form->data->length - form->sent) );
|
||||
gotsize += form->data->length - form->sent;
|
||||
if(result)
|
||||
Curl_mime_cleanpart(finalform);
|
||||
|
||||
form->sent = 0;
|
||||
|
||||
form->data = form->data->next; /* advance */
|
||||
|
||||
} while(form->data && (form->data->type < FORM_CALLBACK));
|
||||
/* If we got an empty line and we have more data, we proceed to the next
|
||||
line immediately to avoid returning zero before we've reached the end. */
|
||||
|
||||
return gotsize;
|
||||
}
|
||||
|
||||
/*
|
||||
* Curl_formpostheader() returns the first line of the formpost, the
|
||||
* request-header part (which is not part of the request-body like the rest of
|
||||
* the post).
|
||||
*/
|
||||
char *Curl_formpostheader(void *formp, size_t *len)
|
||||
{
|
||||
char *header;
|
||||
struct Form *form=(struct Form *)formp;
|
||||
|
||||
if(!form->data)
|
||||
return NULL; /* nothing, ERROR! */
|
||||
|
||||
header = form->data->line;
|
||||
*len = form->data->length;
|
||||
|
||||
form->data = form->data->next; /* advance */
|
||||
|
||||
return header;
|
||||
}
|
||||
|
||||
/*
|
||||
* formboundary() creates a suitable boundary string and returns an allocated
|
||||
* one.
|
||||
*/
|
||||
static CURLcode formboundary(struct Curl_easy *data,
|
||||
char *buffer, size_t buflen)
|
||||
{
|
||||
/* 24 dashes and 16 hexadecimal digits makes 64 bit (18446744073709551615)
|
||||
combinations */
|
||||
if(buflen < 41)
|
||||
return CURLE_BAD_FUNCTION_ARGUMENT;
|
||||
|
||||
memset(buffer, '-', 24);
|
||||
Curl_rand_hex(data, (unsigned char *)&buffer[24], 17);
|
||||
|
||||
return CURLE_OK;
|
||||
return result;
|
||||
}
|
||||
|
||||
#else /* CURL_DISABLE_HTTP */
|
||||
|
@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@ -22,32 +22,6 @@
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
enum formtype {
|
||||
FORM_DATAMEM, /* already allocated FORM_DATA memory */
|
||||
FORM_DATA, /* form metadata (convert to network encoding if necessary) */
|
||||
FORM_CONTENT, /* form content (never convert) */
|
||||
FORM_CALLBACK, /* 'line' points to the custom pointer we pass to the callback
|
||||
*/
|
||||
FORM_FILE /* 'line' points to a file name we should read from
|
||||
to create the form data (never convert) */
|
||||
};
|
||||
|
||||
/* plain and simple linked list with lines to send */
|
||||
struct FormData {
|
||||
struct FormData *next;
|
||||
enum formtype type;
|
||||
char *line;
|
||||
size_t length;
|
||||
};
|
||||
|
||||
struct Form {
|
||||
struct FormData *data; /* current form line to send */
|
||||
size_t sent; /* number of bytes of the current line that has
|
||||
already been sent in a previous invoke */
|
||||
FILE *fp; /* file to read from */
|
||||
curl_read_callback fread_func; /* fread callback pointer */
|
||||
};
|
||||
|
||||
/* used by FormAdd for temporary storage */
|
||||
typedef struct FormInfo {
|
||||
char *name;
|
||||
@ -69,31 +43,9 @@ typedef struct FormInfo {
|
||||
struct FormInfo *more;
|
||||
} FormInfo;
|
||||
|
||||
int Curl_FormInit(struct Form *form, struct FormData *formdata);
|
||||
|
||||
CURLcode Curl_getformdata(struct Curl_easy *data,
|
||||
struct FormData **,
|
||||
struct Curl_mimepart *,
|
||||
struct curl_httppost *post,
|
||||
const char *custom_contenttype,
|
||||
curl_off_t *size);
|
||||
|
||||
/* fread() emulation */
|
||||
size_t Curl_FormReader(char *buffer,
|
||||
size_t size,
|
||||
size_t nitems,
|
||||
FILE *mydata);
|
||||
|
||||
/*
|
||||
* Curl_formpostheader() returns the first line of the formpost, the
|
||||
* request-header part (which is not part of the request-body like the rest of
|
||||
* the post).
|
||||
*/
|
||||
char *Curl_formpostheader(void *formp, size_t *len);
|
||||
|
||||
char *Curl_FormBoundary(void);
|
||||
|
||||
void Curl_formclean(struct FormData **);
|
||||
|
||||
CURLcode Curl_formconvert(struct Curl_easy *, struct FormData *);
|
||||
curl_read_callback fread_func);
|
||||
|
||||
#endif /* HEADER_CURL_FORMDATA_H */
|
||||
|
289
lib/http.c
289
lib/http.c
@ -50,6 +50,7 @@
|
||||
#include "transfer.h"
|
||||
#include "sendf.h"
|
||||
#include "formdata.h"
|
||||
#include "mime.h"
|
||||
#include "progress.h"
|
||||
#include "curl_base64.h"
|
||||
#include "cookie.h"
|
||||
@ -162,6 +163,7 @@ CURLcode Curl_http_setup_conn(struct connectdata *conn)
|
||||
if(!http)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
Curl_mime_initpart(&http->form, conn->data);
|
||||
conn->data->req.protop = http;
|
||||
|
||||
Curl_http2_setup_conn(conn);
|
||||
@ -427,6 +429,7 @@ static CURLcode http_perhapsrewind(struct connectdata *conn)
|
||||
expectsend = data->state.infilesize;
|
||||
break;
|
||||
case HTTPREQ_POST_FORM:
|
||||
case HTTPREQ_POST_MIME:
|
||||
expectsend = http->postsize;
|
||||
break;
|
||||
default:
|
||||
@ -1470,18 +1473,17 @@ CURLcode Curl_http_done(struct connectdata *conn,
|
||||
|
||||
Curl_http2_done(conn, premature);
|
||||
|
||||
if(HTTPREQ_POST_FORM == data->set.httpreq) {
|
||||
data->req.bytecount = http->readbytecount + http->writebytecount;
|
||||
Curl_mime_cleanpart(&http->form);
|
||||
|
||||
Curl_formclean(&http->sendit); /* Now free that whole lot */
|
||||
if(http->form.fp) {
|
||||
/* a file being uploaded was left opened, close it! */
|
||||
fclose(http->form.fp);
|
||||
http->form.fp = NULL;
|
||||
}
|
||||
}
|
||||
else if(HTTPREQ_PUT == data->set.httpreq)
|
||||
switch(data->set.httpreq) {
|
||||
case HTTPREQ_PUT:
|
||||
case HTTPREQ_POST_FORM:
|
||||
case HTTPREQ_POST_MIME:
|
||||
data->req.bytecount = http->readbytecount + http->writebytecount;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if(status)
|
||||
return status;
|
||||
@ -1637,6 +1639,10 @@ CURLcode Curl_add_custom_headers(struct connectdata *conn,
|
||||
/* this header (extended by formdata.c) is sent later */
|
||||
checkprefix("Content-Type:", headers->data))
|
||||
;
|
||||
else if(data->set.httpreq == HTTPREQ_POST_MIME &&
|
||||
/* this header is sent later */
|
||||
checkprefix("Content-Type:", headers->data))
|
||||
;
|
||||
else if(conn->bits.authneg &&
|
||||
/* while doing auth neg, don't allow the custom length since
|
||||
we will force length zero then */
|
||||
@ -1775,7 +1781,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
|
||||
const char *httpstring;
|
||||
Curl_send_buffer *req_buffer;
|
||||
curl_off_t postsize = 0; /* curl_off_t to handle large file sizes */
|
||||
int seekerr = CURL_SEEKFUNC_OK;
|
||||
int seekerr = CURL_SEEKFUNC_CANTSEEK;
|
||||
|
||||
/* Always consider the DO phase done after this function call, even if there
|
||||
may be parts of the request that is not yet sent, since we can deal with
|
||||
@ -1848,6 +1854,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
|
||||
switch(httpreq) {
|
||||
case HTTPREQ_POST:
|
||||
case HTTPREQ_POST_FORM:
|
||||
case HTTPREQ_POST_MIME:
|
||||
request = "POST";
|
||||
break;
|
||||
case HTTPREQ_PUT:
|
||||
@ -1942,6 +1949,48 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
|
||||
}
|
||||
#endif
|
||||
|
||||
switch(httpreq) {
|
||||
case HTTPREQ_POST_MIME:
|
||||
http->sendit = &data->set.mimepost;
|
||||
break;
|
||||
case HTTPREQ_POST_FORM:
|
||||
/* Convert the form structure into a mime structure. */
|
||||
Curl_mime_cleanpart(&http->form);
|
||||
result = Curl_getformdata(data, &http->form, data->set.httppost,
|
||||
data->state.fread_func);
|
||||
if(result)
|
||||
return result;
|
||||
http->sendit = &http->form;
|
||||
break;
|
||||
default:
|
||||
http->sendit = NULL;
|
||||
}
|
||||
|
||||
if(http->sendit) {
|
||||
const char *cthdr = Curl_checkheaders(conn, "Content-Type:");
|
||||
|
||||
/* Read and seek body only. */
|
||||
http->sendit->flags |= MIME_BODY_ONLY;
|
||||
|
||||
/* Prepare the mime structure headers & set content type. */
|
||||
|
||||
if(cthdr)
|
||||
for(cthdr += 13; *cthdr == ' '; cthdr++)
|
||||
;
|
||||
else if(http->sendit->kind == MIMEKIND_MULTIPART)
|
||||
cthdr = "multipart/form-data";
|
||||
|
||||
curl_mime_headers(http->sendit, data->set.headers, 0);
|
||||
result = Curl_mime_prepare_headers(http->sendit, cthdr,
|
||||
NULL, MIMESTRATEGY_FORM);
|
||||
curl_mime_headers(http->sendit, NULL, 0);
|
||||
if(!result)
|
||||
result = Curl_mime_rewind(http->sendit);
|
||||
if(result)
|
||||
return result;
|
||||
http->postsize = Curl_mime_size(http->sendit);
|
||||
}
|
||||
|
||||
ptr = Curl_checkheaders(conn, "Transfer-Encoding:");
|
||||
if(ptr) {
|
||||
/* Some kind of TE is requested, check if 'chunked' is chosen */
|
||||
@ -1949,9 +1998,10 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
|
||||
Curl_compareheader(ptr, "Transfer-Encoding:", "chunked");
|
||||
}
|
||||
else {
|
||||
if((conn->handler->protocol&PROTO_FAMILY_HTTP) &&
|
||||
data->set.upload &&
|
||||
(data->state.infilesize == -1)) {
|
||||
if((conn->handler->protocol & PROTO_FAMILY_HTTP) &&
|
||||
(((httpreq == HTTPREQ_POST_MIME || httpreq == HTTPREQ_POST_FORM) &&
|
||||
http->postsize < 0) ||
|
||||
(data->set.upload && data->state.infilesize == -1))) {
|
||||
if(conn->bits.authneg)
|
||||
/* don't enable chunked during auth neg */
|
||||
;
|
||||
@ -2123,21 +2173,9 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
|
||||
}
|
||||
#endif /* CURL_DISABLE_PROXY */
|
||||
|
||||
if(HTTPREQ_POST_FORM == httpreq) {
|
||||
/* we must build the whole post sequence first, so that we have a size of
|
||||
the whole transfer before we start to send it */
|
||||
result = Curl_getformdata(data, &http->sendit, data->set.httppost,
|
||||
Curl_checkheaders(conn, "Content-Type:"),
|
||||
&http->postsize);
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
|
||||
http->p_accept = Curl_checkheaders(conn, "Accept:")?NULL:"Accept: */*\r\n";
|
||||
|
||||
if(( (HTTPREQ_POST == httpreq) ||
|
||||
(HTTPREQ_POST_FORM == httpreq) ||
|
||||
(HTTPREQ_PUT == httpreq) ) &&
|
||||
if((HTTPREQ_POST == httpreq || HTTPREQ_PUT == httpreq) &&
|
||||
data->state.resume_from) {
|
||||
/**********************************************************************
|
||||
* Resuming upload in HTTP means that we PUT or POST and that we have
|
||||
@ -2145,6 +2183,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
|
||||
* a Range: header that will be passed along. We need to "fast forward"
|
||||
* the file the given number of bytes and decrease the assume upload
|
||||
* file size before we continue this venture in the dark lands of HTTP.
|
||||
* Resuming mime/form posting at an offset > 0 has no sense and is ignored.
|
||||
*********************************************************************/
|
||||
|
||||
if(data->state.resume_from < 0) {
|
||||
@ -2219,7 +2258,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
|
||||
conn->allocptr.rangeline = aprintf("Range: bytes=%s\r\n",
|
||||
data->state.range);
|
||||
}
|
||||
else if((httpreq != HTTPREQ_GET) &&
|
||||
else if((httpreq == HTTPREQ_POST || httpreq == HTTPREQ_PUT) &&
|
||||
!Curl_checkheaders(conn, "Content-Range:")) {
|
||||
|
||||
/* if a line like this was already allocated, free the previous one */
|
||||
@ -2415,107 +2454,6 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
|
||||
|
||||
switch(httpreq) {
|
||||
|
||||
case HTTPREQ_POST_FORM:
|
||||
if(!http->sendit || conn->bits.authneg) {
|
||||
/* nothing to post! */
|
||||
result = Curl_add_bufferf(req_buffer, "Content-Length: 0\r\n\r\n");
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
result = Curl_add_buffer_send(req_buffer, conn,
|
||||
&data->info.request_size, 0, FIRSTSOCKET);
|
||||
if(result)
|
||||
failf(data, "Failed sending POST request");
|
||||
else
|
||||
/* setup variables for the upcoming transfer */
|
||||
Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, &http->readbytecount,
|
||||
-1, NULL);
|
||||
break;
|
||||
}
|
||||
|
||||
if(Curl_FormInit(&http->form, http->sendit)) {
|
||||
failf(data, "Internal HTTP POST error!");
|
||||
return CURLE_HTTP_POST_ERROR;
|
||||
}
|
||||
|
||||
/* Get the currently set callback function pointer and store that in the
|
||||
form struct since we might want the actual user-provided callback later
|
||||
on. The data->set.fread_func pointer itself will be changed for the
|
||||
multipart case to the function that returns a multipart formatted
|
||||
stream. */
|
||||
http->form.fread_func = data->state.fread_func;
|
||||
|
||||
/* Set the read function to read from the generated form data */
|
||||
data->state.fread_func = (curl_read_callback)Curl_FormReader;
|
||||
data->state.in = &http->form;
|
||||
|
||||
http->sending = HTTPSEND_BODY;
|
||||
|
||||
if(!data->req.upload_chunky &&
|
||||
!Curl_checkheaders(conn, "Content-Length:")) {
|
||||
/* only add Content-Length if not uploading chunked */
|
||||
result = Curl_add_bufferf(req_buffer,
|
||||
"Content-Length: %" CURL_FORMAT_CURL_OFF_T
|
||||
"\r\n", http->postsize);
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
|
||||
result = expect100(data, conn, req_buffer);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
{
|
||||
|
||||
/* Get Content-Type: line from Curl_formpostheader.
|
||||
*/
|
||||
char *contentType;
|
||||
size_t linelength=0;
|
||||
contentType = Curl_formpostheader((void *)&http->form,
|
||||
&linelength);
|
||||
if(!contentType) {
|
||||
failf(data, "Could not get Content-Type header line!");
|
||||
return CURLE_HTTP_POST_ERROR;
|
||||
}
|
||||
|
||||
result = Curl_add_buffer(req_buffer, contentType, linelength);
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
|
||||
/* make the request end in a true CRLF */
|
||||
result = Curl_add_buffer(req_buffer, "\r\n", 2);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
/* set upload size to the progress meter */
|
||||
Curl_pgrsSetUploadSize(data, http->postsize);
|
||||
|
||||
/* fire away the whole request to the server */
|
||||
result = Curl_add_buffer_send(req_buffer, conn,
|
||||
&data->info.request_size, 0, FIRSTSOCKET);
|
||||
if(result)
|
||||
failf(data, "Failed sending POST request");
|
||||
else
|
||||
/* setup variables for the upcoming transfer */
|
||||
Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE,
|
||||
&http->readbytecount, FIRSTSOCKET,
|
||||
&http->writebytecount);
|
||||
|
||||
if(result) {
|
||||
Curl_formclean(&http->sendit); /* free that whole lot */
|
||||
return result;
|
||||
}
|
||||
|
||||
/* convert the form data */
|
||||
result = Curl_convert_form(data, http->sendit);
|
||||
if(result) {
|
||||
Curl_formclean(&http->sendit); /* free that whole lot */
|
||||
return result;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case HTTPREQ_PUT: /* Let's PUT the data to the server! */
|
||||
|
||||
if(conn->bits.authneg)
|
||||
@ -2560,6 +2498,98 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
|
||||
return result;
|
||||
break;
|
||||
|
||||
case HTTPREQ_POST_FORM:
|
||||
case HTTPREQ_POST_MIME:
|
||||
/* This is form posting using mime data. */
|
||||
if(conn->bits.authneg) {
|
||||
/* nothing to post! */
|
||||
result = Curl_add_bufferf(req_buffer, "Content-Length: 0\r\n\r\n");
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
result = Curl_add_buffer_send(req_buffer, conn,
|
||||
&data->info.request_size, 0, FIRSTSOCKET);
|
||||
if(result)
|
||||
failf(data, "Failed sending POST request");
|
||||
else
|
||||
/* setup variables for the upcoming transfer */
|
||||
Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, &http->readbytecount,
|
||||
-1, NULL);
|
||||
break;
|
||||
}
|
||||
|
||||
postsize = http->postsize;
|
||||
|
||||
/* We only set Content-Length and allow a custom Content-Length if
|
||||
we don't upload data chunked, as RFC2616 forbids us to set both
|
||||
kinds of headers (Transfer-Encoding: chunked and Content-Length) */
|
||||
if(postsize != -1 && !data->req.upload_chunky &&
|
||||
(conn->bits.authneg || !Curl_checkheaders(conn, "Content-Length:"))) {
|
||||
/* we allow replacing this header if not during auth negotiation,
|
||||
although it isn't very wise to actually set your own */
|
||||
result = Curl_add_bufferf(req_buffer,
|
||||
"Content-Length: %" CURL_FORMAT_CURL_OFF_T
|
||||
"\r\n", postsize);
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Output mime-generated headers. */
|
||||
{
|
||||
struct curl_slist *hdr;
|
||||
|
||||
for(hdr = http->sendit->curlheaders; hdr; hdr = hdr->next) {
|
||||
result = Curl_add_bufferf(req_buffer, "%s\r\n", hdr->data);
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/* For really small posts we don't use Expect: headers at all, and for
|
||||
the somewhat bigger ones we allow the app to disable it. Just make
|
||||
sure that the expect100header is always set to the preferred value
|
||||
here. */
|
||||
ptr = Curl_checkheaders(conn, "Expect:");
|
||||
if(ptr) {
|
||||
data->state.expect100header =
|
||||
Curl_compareheader(ptr, "Expect:", "100-continue");
|
||||
}
|
||||
else if(postsize > EXPECT_100_THRESHOLD || postsize < 0) {
|
||||
result = expect100(data, conn, req_buffer);
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
else
|
||||
data->state.expect100header = FALSE;
|
||||
|
||||
/* make the request end in a true CRLF */
|
||||
result = Curl_add_buffer(req_buffer, "\r\n", 2);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
/* set the upload size to the progress meter */
|
||||
Curl_pgrsSetUploadSize(data, postsize);
|
||||
|
||||
/* Read from mime structure. */
|
||||
data->state.fread_func = (curl_read_callback) Curl_mime_read;
|
||||
data->state.in = (void *) http->sendit;
|
||||
http->sending = HTTPSEND_BODY;
|
||||
|
||||
/* this sends the buffer and frees all the buffer resources */
|
||||
result = Curl_add_buffer_send(req_buffer, conn,
|
||||
&data->info.request_size, 0, FIRSTSOCKET);
|
||||
if(result)
|
||||
failf(data, "Failed sending POST request");
|
||||
else
|
||||
/* prepare for transfer */
|
||||
Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE,
|
||||
&http->readbytecount, postsize?FIRSTSOCKET:-1,
|
||||
postsize?&http->writebytecount:NULL);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
break;
|
||||
|
||||
case HTTPREQ_POST:
|
||||
/* this is the simple POST, using x-www-form-urlencoded style */
|
||||
|
||||
@ -3171,6 +3201,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
|
||||
case HTTPREQ_PUT:
|
||||
case HTTPREQ_POST:
|
||||
case HTTPREQ_POST_FORM:
|
||||
case HTTPREQ_POST_MIME:
|
||||
/* We got an error response. If this happened before the whole
|
||||
* request body has been sent we stop sending and mark the
|
||||
* connection for closure after we've read the entire response.
|
||||
|
@ -130,7 +130,7 @@ CURLcode Curl_http_perhapsrewind(struct connectdata *conn);
|
||||
* HTTP unique setup
|
||||
***************************************************************************/
|
||||
struct HTTP {
|
||||
struct FormData *sendit;
|
||||
struct Curl_mimepart *sendit;
|
||||
curl_off_t postsize; /* off_t to handle large file sizes */
|
||||
const char *postdata;
|
||||
|
||||
@ -140,7 +140,7 @@ struct HTTP {
|
||||
curl_off_t writebytecount;
|
||||
|
||||
/* For FORM posting */
|
||||
struct Form form;
|
||||
struct Curl_mimepart form;
|
||||
|
||||
struct back {
|
||||
curl_read_callback fread_func; /* backup storage for fread pointer */
|
||||
|
@ -1955,6 +1955,7 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
|
||||
switch(conn->data->set.httpreq) {
|
||||
case HTTPREQ_POST:
|
||||
case HTTPREQ_POST_FORM:
|
||||
case HTTPREQ_POST_MIME:
|
||||
case HTTPREQ_PUT:
|
||||
if(conn->data->state.infilesize != -1)
|
||||
stream->upload_left = conn->data->state.infilesize;
|
||||
|
48
lib/imap.c
48
lib/imap.c
@ -68,6 +68,7 @@
|
||||
#include "http.h" /* for HTTP proxy tunnel stuff */
|
||||
#include "socks.h"
|
||||
#include "imap.h"
|
||||
#include "mime.h"
|
||||
#include "strtoofft.h"
|
||||
#include "strcase.h"
|
||||
#include "vtls/vtls.h"
|
||||
@ -708,18 +709,48 @@ static CURLcode imap_perform_fetch(struct connectdata *conn)
|
||||
static CURLcode imap_perform_append(struct connectdata *conn)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
struct IMAP *imap = conn->data->req.protop;
|
||||
struct Curl_easy *data = conn->data;
|
||||
struct IMAP *imap = data->req.protop;
|
||||
char *mailbox;
|
||||
|
||||
/* Check we have a mailbox */
|
||||
if(!imap->mailbox) {
|
||||
failf(conn->data, "Cannot APPEND without a mailbox.");
|
||||
failf(data, "Cannot APPEND without a mailbox.");
|
||||
return CURLE_URL_MALFORMAT;
|
||||
}
|
||||
|
||||
/* Prepare the mime data if some. */
|
||||
if(data->set.mimepost.kind != MIMEKIND_NONE) {
|
||||
/* Use the whole structure as data. */
|
||||
data->set.mimepost.flags &= ~MIME_BODY_ONLY;
|
||||
|
||||
/* 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,
|
||||
NULL, MIMESTRATEGY_MAIL);
|
||||
|
||||
if(!result)
|
||||
if(!Curl_checkheaders(conn, "Mime-Version"))
|
||||
result = Curl_mime_add_header(&data->set.mimepost.curlheaders,
|
||||
"Mime-Version: 1.0");
|
||||
|
||||
/* Make sure we will read the entire mime structure. */
|
||||
if(!result)
|
||||
result = Curl_mime_rewind(&data->set.mimepost);
|
||||
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
data->state.infilesize = Curl_mime_size(&data->set.mimepost);
|
||||
|
||||
/* Read from mime structure. */
|
||||
data->state.fread_func = (curl_read_callback) Curl_mime_read;
|
||||
data->state.in = (void *) &data->set.mimepost;
|
||||
}
|
||||
|
||||
/* Check we know the size of the upload */
|
||||
if(conn->data->state.infilesize < 0) {
|
||||
failf(conn->data, "Cannot APPEND with unknown input file size\n");
|
||||
if(data->state.infilesize < 0) {
|
||||
failf(data, "Cannot APPEND with unknown input file size\n");
|
||||
return CURLE_UPLOAD_FAILED;
|
||||
}
|
||||
|
||||
@ -730,7 +761,7 @@ static CURLcode imap_perform_append(struct connectdata *conn)
|
||||
|
||||
/* Send the APPEND command */
|
||||
result = imap_sendf(conn, "APPEND %s (\\Seen) {%" CURL_FORMAT_CURL_OFF_T "}",
|
||||
mailbox, conn->data->state.infilesize);
|
||||
mailbox, data->state.infilesize);
|
||||
|
||||
free(mailbox);
|
||||
|
||||
@ -1423,9 +1454,10 @@ static CURLcode imap_done(struct connectdata *conn, CURLcode status,
|
||||
result = status; /* use the already set error code */
|
||||
}
|
||||
else if(!data->set.connect_only && !imap->custom &&
|
||||
(imap->uid || data->set.upload)) {
|
||||
(imap->uid || data->set.upload ||
|
||||
data->set.mimepost.kind != MIMEKIND_NONE)) {
|
||||
/* Handle responses after FETCH or APPEND transfer has finished */
|
||||
if(!data->set.upload)
|
||||
if(!data->set.upload && data->set.mimepost.kind == MIMEKIND_NONE)
|
||||
state(conn, IMAP_FETCH_FINAL);
|
||||
else {
|
||||
/* End the APPEND command first by sending an empty line */
|
||||
@ -1495,7 +1527,7 @@ static CURLcode imap_perform(struct connectdata *conn, bool *connected,
|
||||
selected = TRUE;
|
||||
|
||||
/* Start the first command in the DO phase */
|
||||
if(conn->data->set.upload)
|
||||
if(conn->data->set.upload || data->set.mimepost.kind != MIMEKIND_NONE)
|
||||
/* APPEND can be executed directly */
|
||||
result = imap_perform_append(conn);
|
||||
else if(imap->custom && (selected || !imap->mailbox))
|
||||
|
1497
lib/mime.c
Normal file
1497
lib/mime.c
Normal file
File diff suppressed because it is too large
Load Diff
119
lib/mime.h
Normal file
119
lib/mime.h
Normal file
@ -0,0 +1,119 @@
|
||||
#ifndef HEADER_CURL_MIME_H
|
||||
#define HEADER_CURL_MIME_H
|
||||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
* are also available at https://curl.haxx.se/docs/copyright.html.
|
||||
*
|
||||
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
* copies of the Software, and permit persons to whom the Software is
|
||||
* furnished to do so, under the terms of the COPYING file.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#define MIME_RAND_BOUNDARY_CHARS 16 /* Nb. of random boundary chars. */
|
||||
|
||||
/* Part flags. */
|
||||
#define MIME_USERHEADERS_OWNER (1 << 0)
|
||||
#define MIME_BODY_ONLY (1 << 1)
|
||||
|
||||
/* Part source kinds. */
|
||||
enum mimekind {
|
||||
MIMEKIND_NONE = 0, /* Part not set. */
|
||||
MIMEKIND_DATA, /* Allocated mime data. */
|
||||
MIMEKIND_NAMEDFILE, /* Data from named file. */
|
||||
MIMEKIND_FILE, /* Data from file pointer. */
|
||||
MIMEKIND_CALLBACK, /* Data from `read' callback. */
|
||||
MIMEKIND_MULTIPART, /* Data is a mime subpart. */
|
||||
MIMEKIND_LAST
|
||||
};
|
||||
|
||||
/* Readback state tokens. */
|
||||
enum mimestate {
|
||||
MIMESTATE_BEGIN, /* Readback has not yet started. */
|
||||
MIMESTATE_CURLHEADERS, /* In curl-generated headers. */
|
||||
MIMESTATE_USERHEADERS, /* In caller's supplied headers. */
|
||||
MIMESTATE_EOH, /* End of headers. */
|
||||
MIMESTATE_BODY, /* Placeholder. */
|
||||
MIMESTATE_BOUNDARY1, /* In boundary prefix. */
|
||||
MIMESTATE_BOUNDARY2, /* In boundary. */
|
||||
MIMESTATE_CONTENT, /* In content. */
|
||||
MIMESTATE_END, /* End of part reached. */
|
||||
MIMESTATE_LAST
|
||||
};
|
||||
|
||||
/* Mime headers strategies. */
|
||||
enum mimestrategy {
|
||||
MIMESTRATEGY_MAIL, /* Mime mail. */
|
||||
MIMESTRATEGY_FORM, /* HTTP post form. */
|
||||
MIMESTRATEGY_LAST
|
||||
};
|
||||
|
||||
/* Mime readback state. */
|
||||
struct mime_state {
|
||||
enum mimestate state; /* Current state token. */
|
||||
void * ptr; /* State-dependent pointer. */
|
||||
size_t offset; /* State-dependent offset. */
|
||||
};
|
||||
|
||||
/* A mime context. */
|
||||
struct Curl_mime {
|
||||
struct Curl_easy * easy; /* The associated easy handle. */
|
||||
struct Curl_mimepart * parent; /* Parent part. */
|
||||
struct Curl_mimepart * firstpart; /* First part. */
|
||||
struct Curl_mimepart * lastpart; /* Last part. */
|
||||
char * boundary; /* The part boundary. */
|
||||
struct mime_state state; /* Current readback state. */
|
||||
};
|
||||
|
||||
/* A mime part. */
|
||||
struct Curl_mimepart {
|
||||
struct Curl_easy * easy; /* The associated easy handle. */
|
||||
struct Curl_mime * parent; /* Parent mime structure. */
|
||||
struct Curl_mimepart * nextpart; /* Forward linked list. */
|
||||
enum mimekind kind; /* The part kind. */
|
||||
char * data; /* Memory data or file name. */
|
||||
curl_read_callback readfunc; /* Read function. */
|
||||
curl_seek_callback seekfunc; /* Seek function. */
|
||||
curl_free_callback freefunc; /* Argument free function. */
|
||||
void * arg; /* Argument to callback functions. */
|
||||
FILE * namedfp; /* Named file pointer. */
|
||||
struct curl_slist * curlheaders; /* Part headers. */
|
||||
struct curl_slist * userheaders; /* Part headers. */
|
||||
char * mimetype; /* Part mime type. */
|
||||
char * filename; /* Remote file name. */
|
||||
char * name; /* Data name. */
|
||||
size_t namesize; /* Data name size. */
|
||||
curl_off_t origin; /* Origin file offset. */
|
||||
curl_off_t datasize; /* Expected data size. */
|
||||
unsigned int flags; /* Flags. */
|
||||
struct mime_state state; /* Current readback state. */
|
||||
};
|
||||
|
||||
|
||||
/* Prototypes. */
|
||||
void Curl_mime_initpart(struct Curl_mimepart *part, struct Curl_easy *easy);
|
||||
void Curl_mime_cleanpart(struct Curl_mimepart *part);
|
||||
CURLcode Curl_mime_prepare_headers(struct Curl_mimepart *part,
|
||||
const char *contenttype,
|
||||
const char *disposition,
|
||||
enum mimestrategy strategy);
|
||||
curl_off_t Curl_mime_size(struct Curl_mimepart *part);
|
||||
size_t Curl_mime_read(char *buffer, size_t size, size_t nitems,
|
||||
void *instream);
|
||||
CURLcode Curl_mime_rewind(struct Curl_mimepart *part);
|
||||
CURLcode Curl_mime_add_header(struct curl_slist **slp, const char *fmt, ...);
|
||||
CURLcode Curl_mime_file(curl_mimepart *part, FILE *fp, int closewhendone);
|
||||
|
||||
#endif /* HEADER_CURL_MIME_H */
|
@ -319,29 +319,4 @@ void Curl_convert_close(struct Curl_easy *data)
|
||||
#endif /* HAVE_ICONV */
|
||||
}
|
||||
|
||||
/*
|
||||
* Curl_convert_form() is used from http.c, this converts any form items that
|
||||
need to be sent in the network encoding. Returns CURLE_OK on success.
|
||||
*/
|
||||
CURLcode Curl_convert_form(struct Curl_easy *data, struct FormData *form)
|
||||
{
|
||||
CURLcode result;
|
||||
|
||||
if(!data)
|
||||
return CURLE_BAD_FUNCTION_ARGUMENT;
|
||||
|
||||
while(form) {
|
||||
if(form->type == FORM_DATA) {
|
||||
result = Curl_convert_to_network(data, form->line, form->length);
|
||||
/* Curl_convert_to_network calls failf if unsuccessful */
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
|
||||
form = form->next;
|
||||
}
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
#endif /* CURL_DOES_CONVERSIONS */
|
||||
|
@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@ -48,7 +48,6 @@ CURLcode Curl_convert_from_network(struct Curl_easy *data,
|
||||
char *buffer, size_t length);
|
||||
CURLcode Curl_convert_from_utf8(struct Curl_easy *data,
|
||||
char *buffer, size_t length);
|
||||
CURLcode Curl_convert_form(struct Curl_easy *data, struct FormData *form);
|
||||
#else
|
||||
#define Curl_convert_clone(a,b,c,d) ((void)a, CURLE_OK)
|
||||
#define Curl_convert_init(x) Curl_nop_stmt
|
||||
@ -57,7 +56,6 @@ CURLcode Curl_convert_form(struct Curl_easy *data, struct FormData *form);
|
||||
#define Curl_convert_to_network(a,b,c) ((void)a, CURLE_OK)
|
||||
#define Curl_convert_from_network(a,b,c) ((void)a, CURLE_OK)
|
||||
#define Curl_convert_from_utf8(a,b,c) ((void)a, CURLE_OK)
|
||||
#define Curl_convert_form(a,b) CURLE_OK
|
||||
#endif
|
||||
|
||||
#endif /* HEADER_CURL_NON_ASCII_H */
|
||||
|
37
lib/smtp.c
37
lib/smtp.c
@ -67,6 +67,7 @@
|
||||
#include "transfer.h"
|
||||
#include "escape.h"
|
||||
#include "http.h" /* for HTTP proxy tunnel stuff */
|
||||
#include "mime.h"
|
||||
#include "socks.h"
|
||||
#include "smtp.h"
|
||||
#include "strtoofft.h"
|
||||
@ -530,8 +531,37 @@ static CURLcode smtp_perform_mail(struct connectdata *conn)
|
||||
}
|
||||
}
|
||||
|
||||
/* Prepare the mime data if some. */
|
||||
if(data->set.mimepost.kind != MIMEKIND_NONE) {
|
||||
/* Use the whole structure as data. */
|
||||
data->set.mimepost.flags &= ~MIME_BODY_ONLY;
|
||||
|
||||
/* 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,
|
||||
NULL, MIMESTRATEGY_MAIL);
|
||||
|
||||
if(!result)
|
||||
if(!Curl_checkheaders(conn, "Mime-Version"))
|
||||
result = Curl_mime_add_header(&data->set.mimepost.curlheaders,
|
||||
"Mime-Version: 1.0");
|
||||
|
||||
/* Make sure we will read the entire mime structure. */
|
||||
if(!result)
|
||||
result = Curl_mime_rewind(&data->set.mimepost);
|
||||
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
data->state.infilesize = Curl_mime_size(&data->set.mimepost);
|
||||
|
||||
/* Read from mime structure. */
|
||||
data->state.fread_func = (curl_read_callback) Curl_mime_read;
|
||||
data->state.in = (void *) &data->set.mimepost;
|
||||
}
|
||||
|
||||
/* Calculate the optional SIZE parameter */
|
||||
if(conn->proto.smtpc.size_supported && conn->data->state.infilesize > 0) {
|
||||
if(conn->proto.smtpc.size_supported && data->state.infilesize > 0) {
|
||||
size = aprintf("%" CURL_FORMAT_CURL_OFF_T, data->state.infilesize);
|
||||
|
||||
if(!size) {
|
||||
@ -1159,7 +1189,8 @@ static CURLcode smtp_done(struct connectdata *conn, CURLcode status,
|
||||
connclose(conn, "SMTP done with bad status"); /* marked for closure */
|
||||
result = status; /* use the already set error code */
|
||||
}
|
||||
else if(!data->set.connect_only && data->set.upload && data->set.mail_rcpt) {
|
||||
else if(!data->set.connect_only && data->set.mail_rcpt &&
|
||||
(data->set.upload || data->set.mimepost.kind)) {
|
||||
/* Calculate the EOB taking into account any terminating CRLF from the
|
||||
previous line of the email or the CRLF of the DATA command when there
|
||||
is "no mail data". RFC-5321, sect. 4.1.1.4.
|
||||
@ -1249,7 +1280,7 @@ static CURLcode smtp_perform(struct connectdata *conn, bool *connected,
|
||||
smtp->rcpt = data->set.mail_rcpt;
|
||||
|
||||
/* Start the first command in the DO phase */
|
||||
if(data->set.upload && data->set.mail_rcpt)
|
||||
if((data->set.upload || data->set.mimepost.kind) && data->set.mail_rcpt)
|
||||
/* MAIL transfer */
|
||||
result = smtp_perform_mail(conn);
|
||||
else
|
||||
|
@ -73,6 +73,7 @@
|
||||
#include "connect.h"
|
||||
#include "non-ascii.h"
|
||||
#include "http2.h"
|
||||
#include "mime.h"
|
||||
|
||||
/* The last 3 #include files should be in this order */
|
||||
#include "curl_printf.h"
|
||||
@ -241,6 +242,7 @@ CURLcode Curl_fillreadbuffer(struct connectdata *conn, int bytes, int *nreadp)
|
||||
CURLcode Curl_readrewind(struct connectdata *conn)
|
||||
{
|
||||
struct Curl_easy *data = conn->data;
|
||||
struct Curl_mimepart *mimepart = &data->set.mimepost;
|
||||
|
||||
conn->bits.rewindaftersend = FALSE; /* we rewind now */
|
||||
|
||||
@ -253,9 +255,21 @@ CURLcode Curl_readrewind(struct connectdata *conn)
|
||||
/* We have sent away data. If not using CURLOPT_POSTFIELDS or
|
||||
CURLOPT_HTTPPOST, call app to rewind
|
||||
*/
|
||||
if(data->set.postfields ||
|
||||
(data->set.httpreq == HTTPREQ_POST_FORM))
|
||||
if(conn->handler->protocol & PROTO_FAMILY_HTTP) {
|
||||
struct HTTP *http = data->req.protop;
|
||||
|
||||
if(http->sendit)
|
||||
mimepart = http->sendit;
|
||||
}
|
||||
if(data->set.postfields)
|
||||
; /* do nothing */
|
||||
else if(data->set.httpreq == HTTPREQ_POST_MIME ||
|
||||
data->set.httpreq == HTTPREQ_POST_FORM) {
|
||||
if(Curl_mime_rewind(mimepart)) {
|
||||
failf(data, "Cannot rewind mime/post data");
|
||||
return CURLE_SEND_FAIL_REWIND;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(data->set.seek_func) {
|
||||
int err;
|
||||
@ -1826,7 +1840,8 @@ CURLcode Curl_follow(struct Curl_easy *data,
|
||||
* can be overridden with CURLOPT_POSTREDIR.
|
||||
*/
|
||||
if((data->set.httpreq == HTTPREQ_POST
|
||||
|| data->set.httpreq == HTTPREQ_POST_FORM)
|
||||
|| data->set.httpreq == HTTPREQ_POST_FORM
|
||||
|| data->set.httpreq == HTTPREQ_POST_MIME)
|
||||
&& !(data->set.keep_post & CURL_REDIR_POST_301)) {
|
||||
infof(data, "Switch from POST to GET\n");
|
||||
data->set.httpreq = HTTPREQ_GET;
|
||||
@ -1850,7 +1865,8 @@ CURLcode Curl_follow(struct Curl_easy *data,
|
||||
* can be overridden with CURLOPT_POSTREDIR.
|
||||
*/
|
||||
if((data->set.httpreq == HTTPREQ_POST
|
||||
|| data->set.httpreq == HTTPREQ_POST_FORM)
|
||||
|| data->set.httpreq == HTTPREQ_POST_FORM
|
||||
|| data->set.httpreq == HTTPREQ_POST_MIME)
|
||||
&& !(data->set.keep_post & CURL_REDIR_POST_302)) {
|
||||
infof(data, "Switch from POST to GET\n");
|
||||
data->set.httpreq = HTTPREQ_GET;
|
||||
|
22
lib/url.c
22
lib/url.c
@ -71,6 +71,7 @@ bool curl_win32_idn_to_ascii(const char *in, char **out);
|
||||
#include "netrc.h"
|
||||
|
||||
#include "formdata.h"
|
||||
#include "mime.h"
|
||||
#include "vtls/vtls.h"
|
||||
#include "hostip.h"
|
||||
#include "transfer.h"
|
||||
@ -479,6 +480,8 @@ CURLcode Curl_close(struct Curl_easy *data)
|
||||
Curl_http2_cleanup_dependencies(data);
|
||||
Curl_convert_close(data);
|
||||
|
||||
Curl_mime_cleanpart(&data->set.mimepost);
|
||||
|
||||
/* No longer a dirty share, if it exists */
|
||||
if(data->share) {
|
||||
Curl_share_lock(data, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE);
|
||||
@ -668,6 +671,8 @@ CURLcode Curl_open(struct Curl_easy **curl)
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
Curl_mime_initpart(&data->set.mimepost, data);
|
||||
|
||||
data->state.headerbuff = malloc(HEADERSIZE);
|
||||
if(!data->state.headerbuff) {
|
||||
DEBUGF(fprintf(stderr, "Error: malloc of headerbuff failed\n"));
|
||||
@ -1148,6 +1153,19 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
|
||||
data->set.opt_no_body = FALSE; /* this is implied */
|
||||
break;
|
||||
|
||||
case CURLOPT_MIMEPOST:
|
||||
/*
|
||||
* Set to make us do MIME/form POST
|
||||
*/
|
||||
result = curl_mime_subparts(&data->set.mimepost,
|
||||
va_arg(param, curl_mime *));
|
||||
if(!result) {
|
||||
data->set.mimepost.freefunc = NULL; /* Avoid free upon easy cleanup. */
|
||||
data->set.httpreq = HTTPREQ_POST_MIME;
|
||||
data->set.opt_no_body = FALSE; /* this is implied */
|
||||
}
|
||||
break;
|
||||
|
||||
case CURLOPT_REFERER:
|
||||
/*
|
||||
* String to set in the HTTP Referer: field.
|
||||
@ -1875,13 +1893,13 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
|
||||
break;
|
||||
case CURLOPT_RESUME_FROM:
|
||||
/*
|
||||
* Resume transfer at the give file position
|
||||
* Resume transfer at the given file position
|
||||
*/
|
||||
data->set.set_resume_from = va_arg(param, long);
|
||||
break;
|
||||
case CURLOPT_RESUME_FROM_LARGE:
|
||||
/*
|
||||
* Resume transfer at the give file position
|
||||
* Resume transfer at the given file position
|
||||
*/
|
||||
data->set.set_resume_from = va_arg(param, curl_off_t);
|
||||
break;
|
||||
|
@ -103,6 +103,7 @@
|
||||
#include "hash.h"
|
||||
#include "splay.h"
|
||||
|
||||
#include "mime.h"
|
||||
#include "imap.h"
|
||||
#include "pop3.h"
|
||||
#include "smtp.h"
|
||||
@ -1140,6 +1141,7 @@ typedef enum {
|
||||
HTTPREQ_GET,
|
||||
HTTPREQ_POST,
|
||||
HTTPREQ_POST_FORM, /* we make a difference internally */
|
||||
HTTPREQ_POST_MIME, /* we make a difference internally */
|
||||
HTTPREQ_PUT,
|
||||
HTTPREQ_HEAD,
|
||||
HTTPREQ_OPTIONS,
|
||||
@ -1557,7 +1559,8 @@ struct UserDefined {
|
||||
curl_off_t set_resume_from; /* continue [ftp] transfer from here */
|
||||
struct curl_slist *headers; /* linked list of extra headers */
|
||||
struct curl_slist *proxyheaders; /* linked list of extra CONNECT headers */
|
||||
struct curl_httppost *httppost; /* linked list of POST data */
|
||||
struct curl_httppost *httppost; /* linked list of old POST data */
|
||||
struct Curl_mimepart mimepost; /* MIME/POST data. */
|
||||
bool sep_headers; /* handle host and proxy headers separately */
|
||||
bool cookiesession; /* new cookie session? */
|
||||
bool crlf; /* convert crlf on ftp upload(?) */
|
||||
|
@ -146,6 +146,7 @@ int test(char *URL)
|
||||
char *stringpointerextra=(char *)"moooo";
|
||||
struct curl_slist *slist=NULL;
|
||||
struct curl_httppost *httppost=NULL;
|
||||
curl_mime *mimepost = NULL;
|
||||
FILE *stream = stderr;
|
||||
struct data object;
|
||||
char *charp;
|
||||
@ -216,6 +217,9 @@ while(<STDIN>) {
|
||||
elsif($name eq "HTTPPOST") {
|
||||
print "${pref} httppost);\n$check";
|
||||
}
|
||||
elsif($name eq "MIMEPOST") {
|
||||
print "${pref} mimepost);\n$check";
|
||||
}
|
||||
elsif($name eq "STDERR") {
|
||||
print "${pref} stream);\n$check";
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user