mirror of
https://github.com/moparisthebest/curl
synced 2024-11-11 12:05:06 -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_multi_timeout.3 curl_formget.3 curl_multi_assign.3 \
|
||||||
curl_easy_pause.3 curl_easy_recv.3 curl_easy_send.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 \
|
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
|
Size of file to send. \fICURLOPT_INFILESIZE_LARGE(3)\fP
|
||||||
.IP CURLOPT_UPLOAD
|
.IP CURLOPT_UPLOAD
|
||||||
Upload data. See \fICURLOPT_UPLOAD(3)\fP
|
Upload data. See \fICURLOPT_UPLOAD(3)\fP
|
||||||
|
.IP CURLOPT_MIMEPOST
|
||||||
|
Post/send MIME data. See \fICURLOPT_MIMEPOST(3)\fP
|
||||||
.IP CURLOPT_MAXFILESIZE
|
.IP CURLOPT_MAXFILESIZE
|
||||||
Maximum file size to get. See \fICURLOPT_MAXFILESIZE(3)\fP
|
Maximum file size to get. See \fICURLOPT_MAXFILESIZE(3)\fP
|
||||||
.IP CURLOPT_MAXFILESIZE_LARGE
|
.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
|
.\" * This software is licensed as described in the file COPYING, which
|
||||||
.\" * you should have received as part of this distribution. The terms
|
.\" * 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, " ...);"
|
.BI "struct curl_httppost ** " lastitem, " ...);"
|
||||||
.ad
|
.ad
|
||||||
.SH DESCRIPTION
|
.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
|
curl_formadd() is used to append sections when building a multipart/formdata
|
||||||
HTTP POST (sometimes referred to as RFC2388-style posts). Append one section
|
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
|
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.
|
you've called \fIcurl_easy_cleanup(3)\fP for the curl handle.
|
||||||
|
|
||||||
See example below.
|
See example below.
|
||||||
|
.SH AVAILABILITY
|
||||||
|
Deprecated in 7.56.0.
|
||||||
.SH RETURN VALUE
|
.SH RETURN VALUE
|
||||||
0 means everything was ok, non-zero means an error occurred corresponding
|
0 means everything was ok, non-zero means an error occurred corresponding
|
||||||
to a CURL_FORMADD_* constant defined in
|
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);
|
curl_easy_setopt(curl, CURLOPT_HTTPPOST, post);
|
||||||
|
|
||||||
.SH "SEE ALSO"
|
.SH "SEE ALSO"
|
||||||
.BR curl_easy_setopt "(3), "
|
.BR curl_easy_setopt "(3),"
|
||||||
.BR curl_formfree "(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
|
.\" * This software is licensed as described in the file COPYING, which
|
||||||
.\" * you should have received as part of this distribution. The terms
|
.\" * 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);
|
.BI "void curl_formfree(struct curl_httppost *" form);
|
||||||
.ad
|
.ad
|
||||||
.SH DESCRIPTION
|
.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
|
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
|
\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.
|
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
|
\fBform\fP is the pointer as returned from a previous call to
|
||||||
\fIcurl_formadd(3)\fP and may be NULL.
|
\fIcurl_formadd(3)\fP and may be NULL.
|
||||||
|
.SH AVAILABILITY
|
||||||
|
Deprecated in 7.56.0.
|
||||||
.SH RETURN VALUE
|
.SH RETURN VALUE
|
||||||
None
|
None
|
||||||
.SH "SEE ALSO"
|
.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
|
.\" * This software is licensed as described in the file COPYING, which
|
||||||
.\" * you should have received as part of this distribution. The terms
|
.\" * 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;
|
return total_size;
|
||||||
}
|
}
|
||||||
.SH AVAILABILITY
|
.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"
|
.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
|
.\" * This software is licensed as described in the file COPYING, which
|
||||||
.\" * you should have received as part of this distribution. The terms
|
.\" * 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
|
When setting \fICURLOPT_HTTPPOST(3)\fP, it will automatically set
|
||||||
\fICURLOPT_NOBODY(3)\fP to 0.
|
\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
|
.SH DEFAULT
|
||||||
NULL
|
NULL
|
||||||
.SH PROTOCOLS
|
.SH PROTOCOLS
|
||||||
@ -71,9 +74,9 @@ curl_formadd(&formpost,
|
|||||||
CURLFORM_END);
|
CURLFORM_END);
|
||||||
.fi
|
.fi
|
||||||
.SH AVAILABILITY
|
.SH AVAILABILITY
|
||||||
As long as HTTP is enabled
|
As long as HTTP is enabled. Deprecated in 7.56.0.
|
||||||
.SH RETURN VALUE
|
.SH RETURN VALUE
|
||||||
Returns CURLE_OK if HTTP is enabled, and CURLE_UNKNOWN_OPTION if not.
|
Returns CURLE_OK if HTTP is enabled, and CURLE_UNKNOWN_OPTION if not.
|
||||||
.SH "SEE ALSO"
|
.SH "SEE ALSO"
|
||||||
.BR CURLOPT_POSTFIELDS "(3), " CURLOPT_POST "(3), "
|
.BR CURLOPT_POSTFIELDS "(3), " CURLOPT_POST "(3), " CURLOPT_MIMEPOST "(3),"
|
||||||
.BR curl_formadd "(3), " curl_formfree "(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_MAXREDIRS.3 \
|
||||||
CURLOPT_MAX_RECV_SPEED_LARGE.3 \
|
CURLOPT_MAX_RECV_SPEED_LARGE.3 \
|
||||||
CURLOPT_MAX_SEND_SPEED_LARGE.3 \
|
CURLOPT_MAX_SEND_SPEED_LARGE.3 \
|
||||||
|
CURLOPT_MIMEPOST.3 \
|
||||||
CURLOPT_NETRC.3 \
|
CURLOPT_NETRC.3 \
|
||||||
CURLOPT_NETRC_FILE.3 \
|
CURLOPT_NETRC_FILE.3 \
|
||||||
CURLOPT_NEW_DIRECTORY_PERMS.3 \
|
CURLOPT_NEW_DIRECTORY_PERMS.3 \
|
||||||
|
@ -441,6 +441,7 @@ CURLOPT_MAXFILESIZE_LARGE 7.11.0
|
|||||||
CURLOPT_MAXREDIRS 7.5
|
CURLOPT_MAXREDIRS 7.5
|
||||||
CURLOPT_MAX_RECV_SPEED_LARGE 7.15.5
|
CURLOPT_MAX_RECV_SPEED_LARGE 7.15.5
|
||||||
CURLOPT_MAX_SEND_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_MUTE 7.1 7.8 7.15.5
|
||||||
CURLOPT_NETRC 7.1
|
CURLOPT_NETRC 7.1
|
||||||
CURLOPT_NETRC_FILE 7.11.0
|
CURLOPT_NETRC_FILE 7.11.0
|
||||||
|
@ -1791,6 +1791,9 @@ typedef enum {
|
|||||||
/* Enable/disable SSH compression */
|
/* Enable/disable SSH compression */
|
||||||
CINIT(SSH_COMPRESSION, LONG, 268),
|
CINIT(SSH_COMPRESSION, LONG, 268),
|
||||||
|
|
||||||
|
/* Post MIME data. */
|
||||||
|
CINIT(MIMEPOST, OBJECTPOINT, 269),
|
||||||
|
|
||||||
CURLOPT_LASTENTRY /* the last unused */
|
CURLOPT_LASTENTRY /* the last unused */
|
||||||
} CURLoption;
|
} CURLoption;
|
||||||
|
|
||||||
@ -1946,6 +1949,133 @@ typedef enum {
|
|||||||
CURL_EXTERN int (curl_strequal)(const char *s1, const char *s2);
|
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);
|
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> */
|
/* name is uppercase CURLFORM_<name> */
|
||||||
#ifdef CFINIT
|
#ifdef CFINIT
|
||||||
#undef CFINIT
|
#undef CFINIT
|
||||||
|
@ -96,6 +96,9 @@ __extension__ ({ \
|
|||||||
if((_curl_opt) == CURLOPT_HTTPPOST) \
|
if((_curl_opt) == CURLOPT_HTTPPOST) \
|
||||||
if(!_curl_is_arr((value), struct curl_httppost)) \
|
if(!_curl_is_arr((value), struct curl_httppost)) \
|
||||||
_curl_easy_setopt_err_curl_httpost(); \
|
_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_slist_option(_curl_opt)) \
|
||||||
if(!_curl_is_arr((value), struct curl_slist)) \
|
if(!_curl_is_arr((value), struct curl_slist)) \
|
||||||
_curl_easy_setopt_err_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_WARNING(_curl_easy_setopt_err_curl_httpost,
|
||||||
"curl_easy_setopt expects a 'struct curl_httppost *' "
|
"curl_easy_setopt expects a 'struct curl_httppost *' "
|
||||||
"argument for this option")
|
"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_WARNING(_curl_easy_setopt_err_curl_slist,
|
||||||
"curl_easy_setopt expects a 'struct curl_slist *' argument for this option")
|
"curl_easy_setopt expects a 'struct curl_slist *' argument for this option")
|
||||||
_CURL_WARNING(_curl_easy_setopt_err_CURLSH,
|
_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_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 \
|
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 \
|
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 \
|
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 \
|
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_sasl.h curl_multibyte.h hostcheck.h conncache.h \
|
||||||
curl_setup_once.h multihandle.h setup-vms.h pipeline.h dotdot.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 \
|
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
|
LIB_RCFILES = libcurl.rc
|
||||||
|
|
||||||
|
869
lib/formdata.c
869
lib/formdata.c
@ -32,6 +32,8 @@
|
|||||||
|
|
||||||
#include "urldata.h" /* for struct Curl_easy */
|
#include "urldata.h" /* for struct Curl_easy */
|
||||||
#include "formdata.h"
|
#include "formdata.h"
|
||||||
|
#include "mime.h"
|
||||||
|
#include "non-ascii.h"
|
||||||
#include "vtls/vtls.h"
|
#include "vtls/vtls.h"
|
||||||
#include "strcase.h"
|
#include "strcase.h"
|
||||||
#include "sendf.h"
|
#include "sendf.h"
|
||||||
@ -42,13 +44,6 @@
|
|||||||
#include "curl_memory.h"
|
#include "curl_memory.h"
|
||||||
#include "memdebug.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
|
/* What kind of Content-Type to use on un-specified files with unrecognized
|
||||||
extensions. */
|
extensions. */
|
||||||
@ -746,211 +741,6 @@ CURLFORMcode curl_formadd(struct curl_httppost **httppost,
|
|||||||
return result;
|
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()
|
* curl_formget()
|
||||||
* Serialize a curl_httppost struct.
|
* Serialize a curl_httppost struct.
|
||||||
@ -962,42 +752,34 @@ int curl_formget(struct curl_httppost *form, void *arg,
|
|||||||
curl_formget_callback append)
|
curl_formget_callback append)
|
||||||
{
|
{
|
||||||
CURLcode result;
|
CURLcode result;
|
||||||
curl_off_t size;
|
struct Curl_mimepart toppart;
|
||||||
struct FormData *data, *ptr;
|
|
||||||
|
|
||||||
result = Curl_getformdata(NULL, &data, form, NULL, &size);
|
Curl_mime_initpart(&toppart, NULL); /* default form is empty */
|
||||||
if(result)
|
result = Curl_getformdata(NULL, &toppart, form, NULL);
|
||||||
return (int)result;
|
if(!result)
|
||||||
|
result = Curl_mime_prepare_headers(&toppart, "multipart/form-data",
|
||||||
|
NULL, MIMESTRATEGY_FORM);
|
||||||
|
|
||||||
for(ptr = data; ptr; ptr = ptr->next) {
|
while(!result) {
|
||||||
if((ptr->type == FORM_FILE) || (ptr->type == FORM_CALLBACK)) {
|
char buffer[8192];
|
||||||
char buffer[8192];
|
size_t nread = Curl_mime_read(buffer, 1, sizeof buffer, &toppart);
|
||||||
size_t nread;
|
|
||||||
struct Form temp;
|
|
||||||
|
|
||||||
Curl_FormInit(&temp, ptr);
|
if(!nread)
|
||||||
|
break;
|
||||||
|
|
||||||
do {
|
switch(nread) {
|
||||||
nread = readfromfile(&temp, buffer, sizeof(buffer));
|
default:
|
||||||
if((nread == (size_t) -1) ||
|
if(append(arg, buffer, nread) != nread)
|
||||||
(nread > sizeof(buffer)) ||
|
result = CURLE_READ_ERROR;
|
||||||
(nread != append(arg, buffer, nread))) {
|
break;
|
||||||
if(temp.fp)
|
case CURL_READFUNC_ABORT:
|
||||||
fclose(temp.fp);
|
case CURL_READFUNC_PAUSE:
|
||||||
Curl_formclean(&data);
|
break;
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
} while(nread);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if(ptr->length != append(arg, ptr->line, ptr->length)) {
|
|
||||||
Curl_formclean(&data);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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 */
|
} 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
|
* Curl_getformdata() converts a linked list of "meta data" into a mime
|
||||||
* (possibly huge) multipart formdata. The input list is in 'post', while the
|
* structure. The input list is in 'post', while the output is stored in
|
||||||
* output resulting linked lists gets stored in '*finalform'. *sizep will get
|
* mime part at '*finalform'.
|
||||||
* 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'.
|
|
||||||
*
|
*
|
||||||
* This function will not do a failf() for the potential memory failures but
|
* 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
|
* should for all other errors it spots. Just note that this function MAY get
|
||||||
@ -1150,422 +825,114 @@ static CURLcode formdata_add_filename(const struct curl_httppost *file,
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
CURLcode Curl_getformdata(struct Curl_easy *data,
|
CURLcode Curl_getformdata(struct Curl_easy *data,
|
||||||
struct FormData **finalform,
|
struct Curl_mimepart *finalform,
|
||||||
struct curl_httppost *post,
|
struct curl_httppost *post,
|
||||||
const char *custom_content_type,
|
curl_read_callback fread_func)
|
||||||
curl_off_t *sizep)
|
|
||||||
{
|
{
|
||||||
struct FormData *form = NULL;
|
|
||||||
struct FormData *firstform;
|
|
||||||
struct curl_httppost *file;
|
|
||||||
CURLcode result = CURLE_OK;
|
CURLcode result = CURLE_OK;
|
||||||
curl_off_t size = 0; /* support potentially ENORMOUS formposts */
|
struct Curl_mime *form = NULL;
|
||||||
char fileboundary[42];
|
struct Curl_mime *multipart;
|
||||||
struct curl_slist *curList;
|
struct Curl_mimepart *part;
|
||||||
char boundary[42];
|
struct curl_httppost *file;
|
||||||
|
|
||||||
*finalform = NULL; /* default form is empty */
|
Curl_mime_cleanpart(finalform); /* default form is empty */
|
||||||
|
|
||||||
if(!post)
|
if(!post)
|
||||||
return result; /* no input => no output! */
|
return result; /* no input => no output! */
|
||||||
|
|
||||||
result = formboundary(data, boundary, sizeof(boundary));
|
form = curl_mime_init(data);
|
||||||
if(result)
|
if(!form)
|
||||||
return result;
|
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(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;
|
|
||||||
}
|
|
||||||
|
|
||||||
result = AddFormDataf(&form, &size,
|
|
||||||
"\r\nContent-Type: multipart/mixed;"
|
|
||||||
" boundary=%s\r\n",
|
|
||||||
fileboundary);
|
|
||||||
if(result)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
file = post;
|
|
||||||
|
|
||||||
do {
|
|
||||||
|
|
||||||
/* 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. */
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(result)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(post->flags & HTTPPOST_BUFFER)
|
|
||||||
/* include contents of buffer */
|
|
||||||
result = AddFormData(&form, FORM_CONTENT, post->buffer,
|
|
||||||
post->bufferlength, &size);
|
|
||||||
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)
|
if(!result)
|
||||||
result = AddFormDataf(&form, &size, "\r\n--%s--\r\n", boundary);
|
result = curl_mime_subparts(finalform, form);
|
||||||
|
|
||||||
if(result) {
|
/* Process each top part. */
|
||||||
Curl_formclean(&firstform);
|
for(; !result && post; post = post->next) {
|
||||||
return result;
|
/* If we have more than a file here, create a mime subpart and fill it. */
|
||||||
|
multipart = form;
|
||||||
|
if(post->more) {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
|
||||||
|
/* Set the headers. */
|
||||||
|
if(!result)
|
||||||
|
result = curl_mime_headers(part, file->contentheader, 0);
|
||||||
|
|
||||||
|
/* Set the content type. */
|
||||||
|
if(!result &&file->contenttype)
|
||||||
|
result = curl_mime_type(part, file->contenttype);
|
||||||
|
|
||||||
|
/* Set field name. */
|
||||||
|
if(!result && !post->more)
|
||||||
|
result = curl_mime_name(part, post->name,
|
||||||
|
post->namelength? post->namelength: -1);
|
||||||
|
|
||||||
|
/* Process contents. */
|
||||||
|
if(!result) {
|
||||||
|
curl_off_t clen = post->contentslength;
|
||||||
|
|
||||||
|
if(post->flags & CURL_HTTPPOST_LARGE)
|
||||||
|
clen = post->contentlen;
|
||||||
|
if(!clen)
|
||||||
|
clen = -1;
|
||||||
|
|
||||||
|
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)
|
||||||
|
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 = curl_mime_data_cb(part, clen,
|
||||||
|
fread_func, NULL, NULL, post->userp);
|
||||||
|
else {
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
*sizep = size;
|
if(result)
|
||||||
*finalform = firstform;
|
Curl_mime_cleanpart(finalform);
|
||||||
|
|
||||||
return result;
|
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);
|
|
||||||
}
|
|
||||||
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 */
|
|
||||||
}
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
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;
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
#else /* CURL_DISABLE_HTTP */
|
#else /* CURL_DISABLE_HTTP */
|
||||||
CURLFORMcode curl_formadd(struct curl_httppost **httppost,
|
CURLFORMcode curl_formadd(struct curl_httppost **httppost,
|
||||||
struct curl_httppost **last_post,
|
struct curl_httppost **last_post,
|
||||||
|
@ -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
|
* This software is licensed as described in the file COPYING, which
|
||||||
* you should have received as part of this distribution. The terms
|
* 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 */
|
/* used by FormAdd for temporary storage */
|
||||||
typedef struct FormInfo {
|
typedef struct FormInfo {
|
||||||
char *name;
|
char *name;
|
||||||
@ -69,31 +43,9 @@ typedef struct FormInfo {
|
|||||||
struct FormInfo *more;
|
struct FormInfo *more;
|
||||||
} FormInfo;
|
} FormInfo;
|
||||||
|
|
||||||
int Curl_FormInit(struct Form *form, struct FormData *formdata);
|
|
||||||
|
|
||||||
CURLcode Curl_getformdata(struct Curl_easy *data,
|
CURLcode Curl_getformdata(struct Curl_easy *data,
|
||||||
struct FormData **,
|
struct Curl_mimepart *,
|
||||||
struct curl_httppost *post,
|
struct curl_httppost *post,
|
||||||
const char *custom_contenttype,
|
curl_read_callback fread_func);
|
||||||
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 *);
|
|
||||||
|
|
||||||
#endif /* HEADER_CURL_FORMDATA_H */
|
#endif /* HEADER_CURL_FORMDATA_H */
|
||||||
|
289
lib/http.c
289
lib/http.c
@ -50,6 +50,7 @@
|
|||||||
#include "transfer.h"
|
#include "transfer.h"
|
||||||
#include "sendf.h"
|
#include "sendf.h"
|
||||||
#include "formdata.h"
|
#include "formdata.h"
|
||||||
|
#include "mime.h"
|
||||||
#include "progress.h"
|
#include "progress.h"
|
||||||
#include "curl_base64.h"
|
#include "curl_base64.h"
|
||||||
#include "cookie.h"
|
#include "cookie.h"
|
||||||
@ -162,6 +163,7 @@ CURLcode Curl_http_setup_conn(struct connectdata *conn)
|
|||||||
if(!http)
|
if(!http)
|
||||||
return CURLE_OUT_OF_MEMORY;
|
return CURLE_OUT_OF_MEMORY;
|
||||||
|
|
||||||
|
Curl_mime_initpart(&http->form, conn->data);
|
||||||
conn->data->req.protop = http;
|
conn->data->req.protop = http;
|
||||||
|
|
||||||
Curl_http2_setup_conn(conn);
|
Curl_http2_setup_conn(conn);
|
||||||
@ -427,6 +429,7 @@ static CURLcode http_perhapsrewind(struct connectdata *conn)
|
|||||||
expectsend = data->state.infilesize;
|
expectsend = data->state.infilesize;
|
||||||
break;
|
break;
|
||||||
case HTTPREQ_POST_FORM:
|
case HTTPREQ_POST_FORM:
|
||||||
|
case HTTPREQ_POST_MIME:
|
||||||
expectsend = http->postsize;
|
expectsend = http->postsize;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -1470,18 +1473,17 @@ CURLcode Curl_http_done(struct connectdata *conn,
|
|||||||
|
|
||||||
Curl_http2_done(conn, premature);
|
Curl_http2_done(conn, premature);
|
||||||
|
|
||||||
if(HTTPREQ_POST_FORM == data->set.httpreq) {
|
Curl_mime_cleanpart(&http->form);
|
||||||
data->req.bytecount = http->readbytecount + http->writebytecount;
|
|
||||||
|
|
||||||
Curl_formclean(&http->sendit); /* Now free that whole lot */
|
switch(data->set.httpreq) {
|
||||||
if(http->form.fp) {
|
case HTTPREQ_PUT:
|
||||||
/* a file being uploaded was left opened, close it! */
|
case HTTPREQ_POST_FORM:
|
||||||
fclose(http->form.fp);
|
case HTTPREQ_POST_MIME:
|
||||||
http->form.fp = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(HTTPREQ_PUT == data->set.httpreq)
|
|
||||||
data->req.bytecount = http->readbytecount + http->writebytecount;
|
data->req.bytecount = http->readbytecount + http->writebytecount;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if(status)
|
if(status)
|
||||||
return status;
|
return status;
|
||||||
@ -1637,6 +1639,10 @@ CURLcode Curl_add_custom_headers(struct connectdata *conn,
|
|||||||
/* this header (extended by formdata.c) is sent later */
|
/* this header (extended by formdata.c) is sent later */
|
||||||
checkprefix("Content-Type:", headers->data))
|
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 &&
|
else if(conn->bits.authneg &&
|
||||||
/* while doing auth neg, don't allow the custom length since
|
/* while doing auth neg, don't allow the custom length since
|
||||||
we will force length zero then */
|
we will force length zero then */
|
||||||
@ -1775,7 +1781,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
|
|||||||
const char *httpstring;
|
const char *httpstring;
|
||||||
Curl_send_buffer *req_buffer;
|
Curl_send_buffer *req_buffer;
|
||||||
curl_off_t postsize = 0; /* curl_off_t to handle large file sizes */
|
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
|
/* 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
|
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) {
|
switch(httpreq) {
|
||||||
case HTTPREQ_POST:
|
case HTTPREQ_POST:
|
||||||
case HTTPREQ_POST_FORM:
|
case HTTPREQ_POST_FORM:
|
||||||
|
case HTTPREQ_POST_MIME:
|
||||||
request = "POST";
|
request = "POST";
|
||||||
break;
|
break;
|
||||||
case HTTPREQ_PUT:
|
case HTTPREQ_PUT:
|
||||||
@ -1942,6 +1949,48 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
|
|||||||
}
|
}
|
||||||
#endif
|
#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:");
|
ptr = Curl_checkheaders(conn, "Transfer-Encoding:");
|
||||||
if(ptr) {
|
if(ptr) {
|
||||||
/* Some kind of TE is requested, check if 'chunked' is chosen */
|
/* 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");
|
Curl_compareheader(ptr, "Transfer-Encoding:", "chunked");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if((conn->handler->protocol&PROTO_FAMILY_HTTP) &&
|
if((conn->handler->protocol & PROTO_FAMILY_HTTP) &&
|
||||||
data->set.upload &&
|
(((httpreq == HTTPREQ_POST_MIME || httpreq == HTTPREQ_POST_FORM) &&
|
||||||
(data->state.infilesize == -1)) {
|
http->postsize < 0) ||
|
||||||
|
(data->set.upload && data->state.infilesize == -1))) {
|
||||||
if(conn->bits.authneg)
|
if(conn->bits.authneg)
|
||||||
/* don't enable chunked during auth neg */
|
/* don't enable chunked during auth neg */
|
||||||
;
|
;
|
||||||
@ -2123,21 +2173,9 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
|
|||||||
}
|
}
|
||||||
#endif /* CURL_DISABLE_PROXY */
|
#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";
|
http->p_accept = Curl_checkheaders(conn, "Accept:")?NULL:"Accept: */*\r\n";
|
||||||
|
|
||||||
if(( (HTTPREQ_POST == httpreq) ||
|
if((HTTPREQ_POST == httpreq || HTTPREQ_PUT == httpreq) &&
|
||||||
(HTTPREQ_POST_FORM == httpreq) ||
|
|
||||||
(HTTPREQ_PUT == httpreq) ) &&
|
|
||||||
data->state.resume_from) {
|
data->state.resume_from) {
|
||||||
/**********************************************************************
|
/**********************************************************************
|
||||||
* Resuming upload in HTTP means that we PUT or POST and that we have
|
* 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"
|
* 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
|
* 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.
|
* 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) {
|
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",
|
conn->allocptr.rangeline = aprintf("Range: bytes=%s\r\n",
|
||||||
data->state.range);
|
data->state.range);
|
||||||
}
|
}
|
||||||
else if((httpreq != HTTPREQ_GET) &&
|
else if((httpreq == HTTPREQ_POST || httpreq == HTTPREQ_PUT) &&
|
||||||
!Curl_checkheaders(conn, "Content-Range:")) {
|
!Curl_checkheaders(conn, "Content-Range:")) {
|
||||||
|
|
||||||
/* if a line like this was already allocated, free the previous one */
|
/* 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) {
|
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! */
|
case HTTPREQ_PUT: /* Let's PUT the data to the server! */
|
||||||
|
|
||||||
if(conn->bits.authneg)
|
if(conn->bits.authneg)
|
||||||
@ -2560,6 +2498,98 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
|
|||||||
return result;
|
return result;
|
||||||
break;
|
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:
|
case HTTPREQ_POST:
|
||||||
/* this is the simple POST, using x-www-form-urlencoded style */
|
/* 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_PUT:
|
||||||
case HTTPREQ_POST:
|
case HTTPREQ_POST:
|
||||||
case HTTPREQ_POST_FORM:
|
case HTTPREQ_POST_FORM:
|
||||||
|
case HTTPREQ_POST_MIME:
|
||||||
/* We got an error response. If this happened before the whole
|
/* We got an error response. If this happened before the whole
|
||||||
* request body has been sent we stop sending and mark the
|
* request body has been sent we stop sending and mark the
|
||||||
* connection for closure after we've read the entire response.
|
* connection for closure after we've read the entire response.
|
||||||
|
@ -130,7 +130,7 @@ CURLcode Curl_http_perhapsrewind(struct connectdata *conn);
|
|||||||
* HTTP unique setup
|
* HTTP unique setup
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
struct HTTP {
|
struct HTTP {
|
||||||
struct FormData *sendit;
|
struct Curl_mimepart *sendit;
|
||||||
curl_off_t postsize; /* off_t to handle large file sizes */
|
curl_off_t postsize; /* off_t to handle large file sizes */
|
||||||
const char *postdata;
|
const char *postdata;
|
||||||
|
|
||||||
@ -140,7 +140,7 @@ struct HTTP {
|
|||||||
curl_off_t writebytecount;
|
curl_off_t writebytecount;
|
||||||
|
|
||||||
/* For FORM posting */
|
/* For FORM posting */
|
||||||
struct Form form;
|
struct Curl_mimepart form;
|
||||||
|
|
||||||
struct back {
|
struct back {
|
||||||
curl_read_callback fread_func; /* backup storage for fread pointer */
|
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) {
|
switch(conn->data->set.httpreq) {
|
||||||
case HTTPREQ_POST:
|
case HTTPREQ_POST:
|
||||||
case HTTPREQ_POST_FORM:
|
case HTTPREQ_POST_FORM:
|
||||||
|
case HTTPREQ_POST_MIME:
|
||||||
case HTTPREQ_PUT:
|
case HTTPREQ_PUT:
|
||||||
if(conn->data->state.infilesize != -1)
|
if(conn->data->state.infilesize != -1)
|
||||||
stream->upload_left = conn->data->state.infilesize;
|
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 "http.h" /* for HTTP proxy tunnel stuff */
|
||||||
#include "socks.h"
|
#include "socks.h"
|
||||||
#include "imap.h"
|
#include "imap.h"
|
||||||
|
#include "mime.h"
|
||||||
#include "strtoofft.h"
|
#include "strtoofft.h"
|
||||||
#include "strcase.h"
|
#include "strcase.h"
|
||||||
#include "vtls/vtls.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)
|
static CURLcode imap_perform_append(struct connectdata *conn)
|
||||||
{
|
{
|
||||||
CURLcode result = CURLE_OK;
|
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;
|
char *mailbox;
|
||||||
|
|
||||||
/* Check we have a mailbox */
|
/* Check we have a mailbox */
|
||||||
if(!imap->mailbox) {
|
if(!imap->mailbox) {
|
||||||
failf(conn->data, "Cannot APPEND without a mailbox.");
|
failf(data, "Cannot APPEND without a mailbox.");
|
||||||
return CURLE_URL_MALFORMAT;
|
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 */
|
/* Check we know the size of the upload */
|
||||||
if(conn->data->state.infilesize < 0) {
|
if(data->state.infilesize < 0) {
|
||||||
failf(conn->data, "Cannot APPEND with unknown input file size\n");
|
failf(data, "Cannot APPEND with unknown input file size\n");
|
||||||
return CURLE_UPLOAD_FAILED;
|
return CURLE_UPLOAD_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -730,7 +761,7 @@ static CURLcode imap_perform_append(struct connectdata *conn)
|
|||||||
|
|
||||||
/* Send the APPEND command */
|
/* Send the APPEND command */
|
||||||
result = imap_sendf(conn, "APPEND %s (\\Seen) {%" CURL_FORMAT_CURL_OFF_T "}",
|
result = imap_sendf(conn, "APPEND %s (\\Seen) {%" CURL_FORMAT_CURL_OFF_T "}",
|
||||||
mailbox, conn->data->state.infilesize);
|
mailbox, data->state.infilesize);
|
||||||
|
|
||||||
free(mailbox);
|
free(mailbox);
|
||||||
|
|
||||||
@ -1423,9 +1454,10 @@ static CURLcode imap_done(struct connectdata *conn, CURLcode status,
|
|||||||
result = status; /* use the already set error code */
|
result = status; /* use the already set error code */
|
||||||
}
|
}
|
||||||
else if(!data->set.connect_only && !imap->custom &&
|
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 */
|
/* 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);
|
state(conn, IMAP_FETCH_FINAL);
|
||||||
else {
|
else {
|
||||||
/* End the APPEND command first by sending an empty line */
|
/* 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;
|
selected = TRUE;
|
||||||
|
|
||||||
/* Start the first command in the DO phase */
|
/* 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 */
|
/* APPEND can be executed directly */
|
||||||
result = imap_perform_append(conn);
|
result = imap_perform_append(conn);
|
||||||
else if(imap->custom && (selected || !imap->mailbox))
|
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 */
|
#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 */
|
#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
|
* This software is licensed as described in the file COPYING, which
|
||||||
* you should have received as part of this distribution. The terms
|
* 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);
|
char *buffer, size_t length);
|
||||||
CURLcode Curl_convert_from_utf8(struct Curl_easy *data,
|
CURLcode Curl_convert_from_utf8(struct Curl_easy *data,
|
||||||
char *buffer, size_t length);
|
char *buffer, size_t length);
|
||||||
CURLcode Curl_convert_form(struct Curl_easy *data, struct FormData *form);
|
|
||||||
#else
|
#else
|
||||||
#define Curl_convert_clone(a,b,c,d) ((void)a, CURLE_OK)
|
#define Curl_convert_clone(a,b,c,d) ((void)a, CURLE_OK)
|
||||||
#define Curl_convert_init(x) Curl_nop_stmt
|
#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_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_network(a,b,c) ((void)a, CURLE_OK)
|
||||||
#define Curl_convert_from_utf8(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
|
||||||
|
|
||||||
#endif /* HEADER_CURL_NON_ASCII_H */
|
#endif /* HEADER_CURL_NON_ASCII_H */
|
||||||
|
37
lib/smtp.c
37
lib/smtp.c
@ -67,6 +67,7 @@
|
|||||||
#include "transfer.h"
|
#include "transfer.h"
|
||||||
#include "escape.h"
|
#include "escape.h"
|
||||||
#include "http.h" /* for HTTP proxy tunnel stuff */
|
#include "http.h" /* for HTTP proxy tunnel stuff */
|
||||||
|
#include "mime.h"
|
||||||
#include "socks.h"
|
#include "socks.h"
|
||||||
#include "smtp.h"
|
#include "smtp.h"
|
||||||
#include "strtoofft.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 */
|
/* 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);
|
size = aprintf("%" CURL_FORMAT_CURL_OFF_T, data->state.infilesize);
|
||||||
|
|
||||||
if(!size) {
|
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 */
|
connclose(conn, "SMTP done with bad status"); /* marked for closure */
|
||||||
result = status; /* use the already set error code */
|
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
|
/* 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
|
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.
|
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;
|
smtp->rcpt = data->set.mail_rcpt;
|
||||||
|
|
||||||
/* Start the first command in the DO phase */
|
/* 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 */
|
/* MAIL transfer */
|
||||||
result = smtp_perform_mail(conn);
|
result = smtp_perform_mail(conn);
|
||||||
else
|
else
|
||||||
|
@ -73,6 +73,7 @@
|
|||||||
#include "connect.h"
|
#include "connect.h"
|
||||||
#include "non-ascii.h"
|
#include "non-ascii.h"
|
||||||
#include "http2.h"
|
#include "http2.h"
|
||||||
|
#include "mime.h"
|
||||||
|
|
||||||
/* The last 3 #include files should be in this order */
|
/* The last 3 #include files should be in this order */
|
||||||
#include "curl_printf.h"
|
#include "curl_printf.h"
|
||||||
@ -241,6 +242,7 @@ CURLcode Curl_fillreadbuffer(struct connectdata *conn, int bytes, int *nreadp)
|
|||||||
CURLcode Curl_readrewind(struct connectdata *conn)
|
CURLcode Curl_readrewind(struct connectdata *conn)
|
||||||
{
|
{
|
||||||
struct Curl_easy *data = conn->data;
|
struct Curl_easy *data = conn->data;
|
||||||
|
struct Curl_mimepart *mimepart = &data->set.mimepost;
|
||||||
|
|
||||||
conn->bits.rewindaftersend = FALSE; /* we rewind now */
|
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
|
/* We have sent away data. If not using CURLOPT_POSTFIELDS or
|
||||||
CURLOPT_HTTPPOST, call app to rewind
|
CURLOPT_HTTPPOST, call app to rewind
|
||||||
*/
|
*/
|
||||||
if(data->set.postfields ||
|
if(conn->handler->protocol & PROTO_FAMILY_HTTP) {
|
||||||
(data->set.httpreq == HTTPREQ_POST_FORM))
|
struct HTTP *http = data->req.protop;
|
||||||
|
|
||||||
|
if(http->sendit)
|
||||||
|
mimepart = http->sendit;
|
||||||
|
}
|
||||||
|
if(data->set.postfields)
|
||||||
; /* do nothing */
|
; /* 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 {
|
else {
|
||||||
if(data->set.seek_func) {
|
if(data->set.seek_func) {
|
||||||
int err;
|
int err;
|
||||||
@ -1826,7 +1840,8 @@ CURLcode Curl_follow(struct Curl_easy *data,
|
|||||||
* can be overridden with CURLOPT_POSTREDIR.
|
* can be overridden with CURLOPT_POSTREDIR.
|
||||||
*/
|
*/
|
||||||
if((data->set.httpreq == HTTPREQ_POST
|
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)) {
|
&& !(data->set.keep_post & CURL_REDIR_POST_301)) {
|
||||||
infof(data, "Switch from POST to GET\n");
|
infof(data, "Switch from POST to GET\n");
|
||||||
data->set.httpreq = HTTPREQ_GET;
|
data->set.httpreq = HTTPREQ_GET;
|
||||||
@ -1850,7 +1865,8 @@ CURLcode Curl_follow(struct Curl_easy *data,
|
|||||||
* can be overridden with CURLOPT_POSTREDIR.
|
* can be overridden with CURLOPT_POSTREDIR.
|
||||||
*/
|
*/
|
||||||
if((data->set.httpreq == HTTPREQ_POST
|
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)) {
|
&& !(data->set.keep_post & CURL_REDIR_POST_302)) {
|
||||||
infof(data, "Switch from POST to GET\n");
|
infof(data, "Switch from POST to GET\n");
|
||||||
data->set.httpreq = HTTPREQ_GET;
|
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 "netrc.h"
|
||||||
|
|
||||||
#include "formdata.h"
|
#include "formdata.h"
|
||||||
|
#include "mime.h"
|
||||||
#include "vtls/vtls.h"
|
#include "vtls/vtls.h"
|
||||||
#include "hostip.h"
|
#include "hostip.h"
|
||||||
#include "transfer.h"
|
#include "transfer.h"
|
||||||
@ -479,6 +480,8 @@ CURLcode Curl_close(struct Curl_easy *data)
|
|||||||
Curl_http2_cleanup_dependencies(data);
|
Curl_http2_cleanup_dependencies(data);
|
||||||
Curl_convert_close(data);
|
Curl_convert_close(data);
|
||||||
|
|
||||||
|
Curl_mime_cleanpart(&data->set.mimepost);
|
||||||
|
|
||||||
/* No longer a dirty share, if it exists */
|
/* No longer a dirty share, if it exists */
|
||||||
if(data->share) {
|
if(data->share) {
|
||||||
Curl_share_lock(data, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE);
|
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;
|
result = CURLE_OUT_OF_MEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Curl_mime_initpart(&data->set.mimepost, data);
|
||||||
|
|
||||||
data->state.headerbuff = malloc(HEADERSIZE);
|
data->state.headerbuff = malloc(HEADERSIZE);
|
||||||
if(!data->state.headerbuff) {
|
if(!data->state.headerbuff) {
|
||||||
DEBUGF(fprintf(stderr, "Error: malloc of headerbuff failed\n"));
|
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 */
|
data->set.opt_no_body = FALSE; /* this is implied */
|
||||||
break;
|
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:
|
case CURLOPT_REFERER:
|
||||||
/*
|
/*
|
||||||
* String to set in the HTTP Referer: field.
|
* String to set in the HTTP Referer: field.
|
||||||
@ -1875,13 +1893,13 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
|
|||||||
break;
|
break;
|
||||||
case CURLOPT_RESUME_FROM:
|
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);
|
data->set.set_resume_from = va_arg(param, long);
|
||||||
break;
|
break;
|
||||||
case CURLOPT_RESUME_FROM_LARGE:
|
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);
|
data->set.set_resume_from = va_arg(param, curl_off_t);
|
||||||
break;
|
break;
|
||||||
|
@ -103,6 +103,7 @@
|
|||||||
#include "hash.h"
|
#include "hash.h"
|
||||||
#include "splay.h"
|
#include "splay.h"
|
||||||
|
|
||||||
|
#include "mime.h"
|
||||||
#include "imap.h"
|
#include "imap.h"
|
||||||
#include "pop3.h"
|
#include "pop3.h"
|
||||||
#include "smtp.h"
|
#include "smtp.h"
|
||||||
@ -1140,6 +1141,7 @@ typedef enum {
|
|||||||
HTTPREQ_GET,
|
HTTPREQ_GET,
|
||||||
HTTPREQ_POST,
|
HTTPREQ_POST,
|
||||||
HTTPREQ_POST_FORM, /* we make a difference internally */
|
HTTPREQ_POST_FORM, /* we make a difference internally */
|
||||||
|
HTTPREQ_POST_MIME, /* we make a difference internally */
|
||||||
HTTPREQ_PUT,
|
HTTPREQ_PUT,
|
||||||
HTTPREQ_HEAD,
|
HTTPREQ_HEAD,
|
||||||
HTTPREQ_OPTIONS,
|
HTTPREQ_OPTIONS,
|
||||||
@ -1557,7 +1559,8 @@ struct UserDefined {
|
|||||||
curl_off_t set_resume_from; /* continue [ftp] transfer from here */
|
curl_off_t set_resume_from; /* continue [ftp] transfer from here */
|
||||||
struct curl_slist *headers; /* linked list of extra headers */
|
struct curl_slist *headers; /* linked list of extra headers */
|
||||||
struct curl_slist *proxyheaders; /* linked list of extra CONNECT 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 sep_headers; /* handle host and proxy headers separately */
|
||||||
bool cookiesession; /* new cookie session? */
|
bool cookiesession; /* new cookie session? */
|
||||||
bool crlf; /* convert crlf on ftp upload(?) */
|
bool crlf; /* convert crlf on ftp upload(?) */
|
||||||
|
@ -146,6 +146,7 @@ int test(char *URL)
|
|||||||
char *stringpointerextra=(char *)"moooo";
|
char *stringpointerextra=(char *)"moooo";
|
||||||
struct curl_slist *slist=NULL;
|
struct curl_slist *slist=NULL;
|
||||||
struct curl_httppost *httppost=NULL;
|
struct curl_httppost *httppost=NULL;
|
||||||
|
curl_mime *mimepost = NULL;
|
||||||
FILE *stream = stderr;
|
FILE *stream = stderr;
|
||||||
struct data object;
|
struct data object;
|
||||||
char *charp;
|
char *charp;
|
||||||
@ -216,6 +217,9 @@ while(<STDIN>) {
|
|||||||
elsif($name eq "HTTPPOST") {
|
elsif($name eq "HTTPPOST") {
|
||||||
print "${pref} httppost);\n$check";
|
print "${pref} httppost);\n$check";
|
||||||
}
|
}
|
||||||
|
elsif($name eq "MIMEPOST") {
|
||||||
|
print "${pref} mimepost);\n$check";
|
||||||
|
}
|
||||||
elsif($name eq "STDERR") {
|
elsif($name eq "STDERR") {
|
||||||
print "${pref} stream);\n$check";
|
print "${pref} stream);\n$check";
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user