1*6236dae4SAndroid Build Coastguard Worker /***************************************************************************
2*6236dae4SAndroid Build Coastguard Worker * _ _ ____ _
3*6236dae4SAndroid Build Coastguard Worker * Project ___| | | | _ \| |
4*6236dae4SAndroid Build Coastguard Worker * / __| | | | |_) | |
5*6236dae4SAndroid Build Coastguard Worker * | (__| |_| | _ <| |___
6*6236dae4SAndroid Build Coastguard Worker * \___|\___/|_| \_\_____|
7*6236dae4SAndroid Build Coastguard Worker *
8*6236dae4SAndroid Build Coastguard Worker * Copyright (C) Daniel Stenberg, <[email protected]>, et al.
9*6236dae4SAndroid Build Coastguard Worker *
10*6236dae4SAndroid Build Coastguard Worker * This software is licensed as described in the file COPYING, which
11*6236dae4SAndroid Build Coastguard Worker * you should have received as part of this distribution. The terms
12*6236dae4SAndroid Build Coastguard Worker * are also available at https://curl.se/docs/copyright.html.
13*6236dae4SAndroid Build Coastguard Worker *
14*6236dae4SAndroid Build Coastguard Worker * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15*6236dae4SAndroid Build Coastguard Worker * copies of the Software, and permit persons to whom the Software is
16*6236dae4SAndroid Build Coastguard Worker * furnished to do so, under the terms of the COPYING file.
17*6236dae4SAndroid Build Coastguard Worker *
18*6236dae4SAndroid Build Coastguard Worker * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19*6236dae4SAndroid Build Coastguard Worker * KIND, either express or implied.
20*6236dae4SAndroid Build Coastguard Worker *
21*6236dae4SAndroid Build Coastguard Worker * SPDX-License-Identifier: curl
22*6236dae4SAndroid Build Coastguard Worker *
23*6236dae4SAndroid Build Coastguard Worker ***************************************************************************/
24*6236dae4SAndroid Build Coastguard Worker
25*6236dae4SAndroid Build Coastguard Worker #include "curl_setup.h"
26*6236dae4SAndroid Build Coastguard Worker
27*6236dae4SAndroid Build Coastguard Worker #include <curl/curl.h>
28*6236dae4SAndroid Build Coastguard Worker
29*6236dae4SAndroid Build Coastguard Worker struct Curl_easy;
30*6236dae4SAndroid Build Coastguard Worker
31*6236dae4SAndroid Build Coastguard Worker #include "mime.h"
32*6236dae4SAndroid Build Coastguard Worker #include "warnless.h"
33*6236dae4SAndroid Build Coastguard Worker #include "urldata.h"
34*6236dae4SAndroid Build Coastguard Worker #include "sendf.h"
35*6236dae4SAndroid Build Coastguard Worker #include "strdup.h"
36*6236dae4SAndroid Build Coastguard Worker
37*6236dae4SAndroid Build Coastguard Worker #if !defined(CURL_DISABLE_MIME) && (!defined(CURL_DISABLE_HTTP) || \
38*6236dae4SAndroid Build Coastguard Worker !defined(CURL_DISABLE_SMTP) || \
39*6236dae4SAndroid Build Coastguard Worker !defined(CURL_DISABLE_IMAP))
40*6236dae4SAndroid Build Coastguard Worker
41*6236dae4SAndroid Build Coastguard Worker #if defined(HAVE_LIBGEN_H) && defined(HAVE_BASENAME)
42*6236dae4SAndroid Build Coastguard Worker #include <libgen.h>
43*6236dae4SAndroid Build Coastguard Worker #endif
44*6236dae4SAndroid Build Coastguard Worker
45*6236dae4SAndroid Build Coastguard Worker #include "rand.h"
46*6236dae4SAndroid Build Coastguard Worker #include "slist.h"
47*6236dae4SAndroid Build Coastguard Worker #include "strcase.h"
48*6236dae4SAndroid Build Coastguard Worker #include "dynbuf.h"
49*6236dae4SAndroid Build Coastguard Worker /* The last 3 #include files should be in this order */
50*6236dae4SAndroid Build Coastguard Worker #include "curl_printf.h"
51*6236dae4SAndroid Build Coastguard Worker #include "curl_memory.h"
52*6236dae4SAndroid Build Coastguard Worker #include "memdebug.h"
53*6236dae4SAndroid Build Coastguard Worker
54*6236dae4SAndroid Build Coastguard Worker #ifdef _WIN32
55*6236dae4SAndroid Build Coastguard Worker # ifndef R_OK
56*6236dae4SAndroid Build Coastguard Worker # define R_OK 4
57*6236dae4SAndroid Build Coastguard Worker # endif
58*6236dae4SAndroid Build Coastguard Worker #endif
59*6236dae4SAndroid Build Coastguard Worker
60*6236dae4SAndroid Build Coastguard Worker
61*6236dae4SAndroid Build Coastguard Worker #define READ_ERROR ((size_t) -1)
62*6236dae4SAndroid Build Coastguard Worker #define STOP_FILLING ((size_t) -2)
63*6236dae4SAndroid Build Coastguard Worker
64*6236dae4SAndroid Build Coastguard Worker static size_t mime_subparts_read(char *buffer, size_t size, size_t nitems,
65*6236dae4SAndroid Build Coastguard Worker void *instream, bool *hasread);
66*6236dae4SAndroid Build Coastguard Worker
67*6236dae4SAndroid Build Coastguard Worker /* Encoders. */
68*6236dae4SAndroid Build Coastguard Worker static size_t encoder_nop_read(char *buffer, size_t size, bool ateof,
69*6236dae4SAndroid Build Coastguard Worker curl_mimepart *part);
70*6236dae4SAndroid Build Coastguard Worker static curl_off_t encoder_nop_size(curl_mimepart *part);
71*6236dae4SAndroid Build Coastguard Worker static size_t encoder_7bit_read(char *buffer, size_t size, bool ateof,
72*6236dae4SAndroid Build Coastguard Worker curl_mimepart *part);
73*6236dae4SAndroid Build Coastguard Worker static size_t encoder_base64_read(char *buffer, size_t size, bool ateof,
74*6236dae4SAndroid Build Coastguard Worker curl_mimepart *part);
75*6236dae4SAndroid Build Coastguard Worker static curl_off_t encoder_base64_size(curl_mimepart *part);
76*6236dae4SAndroid Build Coastguard Worker static size_t encoder_qp_read(char *buffer, size_t size, bool ateof,
77*6236dae4SAndroid Build Coastguard Worker curl_mimepart *part);
78*6236dae4SAndroid Build Coastguard Worker static curl_off_t encoder_qp_size(curl_mimepart *part);
79*6236dae4SAndroid Build Coastguard Worker static curl_off_t mime_size(curl_mimepart *part);
80*6236dae4SAndroid Build Coastguard Worker
81*6236dae4SAndroid Build Coastguard Worker static const struct mime_encoder encoders[] = {
82*6236dae4SAndroid Build Coastguard Worker {"binary", encoder_nop_read, encoder_nop_size},
83*6236dae4SAndroid Build Coastguard Worker {"8bit", encoder_nop_read, encoder_nop_size},
84*6236dae4SAndroid Build Coastguard Worker {"7bit", encoder_7bit_read, encoder_nop_size},
85*6236dae4SAndroid Build Coastguard Worker {"base64", encoder_base64_read, encoder_base64_size},
86*6236dae4SAndroid Build Coastguard Worker {"quoted-printable", encoder_qp_read, encoder_qp_size},
87*6236dae4SAndroid Build Coastguard Worker {ZERO_NULL, ZERO_NULL, ZERO_NULL}
88*6236dae4SAndroid Build Coastguard Worker };
89*6236dae4SAndroid Build Coastguard Worker
90*6236dae4SAndroid Build Coastguard Worker /* Base64 encoding table */
91*6236dae4SAndroid Build Coastguard Worker static const char base64enc[] =
92*6236dae4SAndroid Build Coastguard Worker "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
93*6236dae4SAndroid Build Coastguard Worker
94*6236dae4SAndroid Build Coastguard Worker /* Quoted-printable character class table.
95*6236dae4SAndroid Build Coastguard Worker *
96*6236dae4SAndroid Build Coastguard Worker * We cannot rely on ctype functions since quoted-printable input data
97*6236dae4SAndroid Build Coastguard Worker * is assumed to be ASCII-compatible, even on non-ASCII platforms. */
98*6236dae4SAndroid Build Coastguard Worker #define QP_OK 1 /* Can be represented by itself. */
99*6236dae4SAndroid Build Coastguard Worker #define QP_SP 2 /* Space or tab. */
100*6236dae4SAndroid Build Coastguard Worker #define QP_CR 3 /* Carriage return. */
101*6236dae4SAndroid Build Coastguard Worker #define QP_LF 4 /* Line-feed. */
102*6236dae4SAndroid Build Coastguard Worker static const unsigned char qp_class[] = {
103*6236dae4SAndroid Build Coastguard Worker 0, 0, 0, 0, 0, 0, 0, 0, /* 00 - 07 */
104*6236dae4SAndroid Build Coastguard Worker 0, QP_SP, QP_LF, 0, 0, QP_CR, 0, 0, /* 08 - 0F */
105*6236dae4SAndroid Build Coastguard Worker 0, 0, 0, 0, 0, 0, 0, 0, /* 10 - 17 */
106*6236dae4SAndroid Build Coastguard Worker 0, 0, 0, 0, 0, 0, 0, 0, /* 18 - 1F */
107*6236dae4SAndroid Build Coastguard Worker QP_SP, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, /* 20 - 27 */
108*6236dae4SAndroid Build Coastguard Worker QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, /* 28 - 2F */
109*6236dae4SAndroid Build Coastguard Worker QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, /* 30 - 37 */
110*6236dae4SAndroid Build Coastguard Worker QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, 0 , QP_OK, QP_OK, /* 38 - 3F */
111*6236dae4SAndroid Build Coastguard Worker QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, /* 40 - 47 */
112*6236dae4SAndroid Build Coastguard Worker QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, /* 48 - 4F */
113*6236dae4SAndroid Build Coastguard Worker QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, /* 50 - 57 */
114*6236dae4SAndroid Build Coastguard Worker QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, /* 58 - 5F */
115*6236dae4SAndroid Build Coastguard Worker QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, /* 60 - 67 */
116*6236dae4SAndroid Build Coastguard Worker QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, /* 68 - 6F */
117*6236dae4SAndroid Build Coastguard Worker QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, /* 70 - 77 */
118*6236dae4SAndroid Build Coastguard Worker QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, 0, /* 78 - 7F */
119*6236dae4SAndroid Build Coastguard Worker 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 80 - 8F */
120*6236dae4SAndroid Build Coastguard Worker 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 90 - 9F */
121*6236dae4SAndroid Build Coastguard Worker 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* A0 - AF */
122*6236dae4SAndroid Build Coastguard Worker 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* B0 - BF */
123*6236dae4SAndroid Build Coastguard Worker 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* C0 - CF */
124*6236dae4SAndroid Build Coastguard Worker 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* D0 - DF */
125*6236dae4SAndroid Build Coastguard Worker 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* E0 - EF */
126*6236dae4SAndroid Build Coastguard Worker 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* F0 - FF */
127*6236dae4SAndroid Build Coastguard Worker };
128*6236dae4SAndroid Build Coastguard Worker
129*6236dae4SAndroid Build Coastguard Worker
130*6236dae4SAndroid Build Coastguard Worker /* Binary --> hexadecimal ASCII table. */
131*6236dae4SAndroid Build Coastguard Worker static const char aschex[] =
132*6236dae4SAndroid Build Coastguard Worker "\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x41\x42\x43\x44\x45\x46";
133*6236dae4SAndroid Build Coastguard Worker
134*6236dae4SAndroid Build Coastguard Worker
135*6236dae4SAndroid Build Coastguard Worker
136*6236dae4SAndroid Build Coastguard Worker #ifndef __VMS
137*6236dae4SAndroid Build Coastguard Worker #define filesize(name, stat_data) (stat_data.st_size)
138*6236dae4SAndroid Build Coastguard Worker #define fopen_read fopen
139*6236dae4SAndroid Build Coastguard Worker
140*6236dae4SAndroid Build Coastguard Worker #else
141*6236dae4SAndroid Build Coastguard Worker
142*6236dae4SAndroid Build Coastguard Worker #include <fabdef.h>
143*6236dae4SAndroid Build Coastguard Worker /*
144*6236dae4SAndroid Build Coastguard Worker * get_vms_file_size does what it takes to get the real size of the file
145*6236dae4SAndroid Build Coastguard Worker *
146*6236dae4SAndroid Build Coastguard Worker * For fixed files, find out the size of the EOF block and adjust.
147*6236dae4SAndroid Build Coastguard Worker *
148*6236dae4SAndroid Build Coastguard Worker * For all others, have to read the entire file in, discarding the contents.
149*6236dae4SAndroid Build Coastguard Worker * Most posted text files will be small, and binary files like zlib archives
150*6236dae4SAndroid Build Coastguard Worker * and CD/DVD images should be either a STREAM_LF format or a fixed format.
151*6236dae4SAndroid Build Coastguard Worker *
152*6236dae4SAndroid Build Coastguard Worker */
VmsRealFileSize(const char * name,const struct_stat * stat_buf)153*6236dae4SAndroid Build Coastguard Worker curl_off_t VmsRealFileSize(const char *name,
154*6236dae4SAndroid Build Coastguard Worker const struct_stat *stat_buf)
155*6236dae4SAndroid Build Coastguard Worker {
156*6236dae4SAndroid Build Coastguard Worker char buffer[8192];
157*6236dae4SAndroid Build Coastguard Worker curl_off_t count;
158*6236dae4SAndroid Build Coastguard Worker int ret_stat;
159*6236dae4SAndroid Build Coastguard Worker FILE * file;
160*6236dae4SAndroid Build Coastguard Worker
161*6236dae4SAndroid Build Coastguard Worker file = fopen(name, FOPEN_READTEXT); /* VMS */
162*6236dae4SAndroid Build Coastguard Worker if(!file)
163*6236dae4SAndroid Build Coastguard Worker return 0;
164*6236dae4SAndroid Build Coastguard Worker
165*6236dae4SAndroid Build Coastguard Worker count = 0;
166*6236dae4SAndroid Build Coastguard Worker ret_stat = 1;
167*6236dae4SAndroid Build Coastguard Worker while(ret_stat > 0) {
168*6236dae4SAndroid Build Coastguard Worker ret_stat = fread(buffer, 1, sizeof(buffer), file);
169*6236dae4SAndroid Build Coastguard Worker if(ret_stat)
170*6236dae4SAndroid Build Coastguard Worker count += ret_stat;
171*6236dae4SAndroid Build Coastguard Worker }
172*6236dae4SAndroid Build Coastguard Worker fclose(file);
173*6236dae4SAndroid Build Coastguard Worker
174*6236dae4SAndroid Build Coastguard Worker return count;
175*6236dae4SAndroid Build Coastguard Worker }
176*6236dae4SAndroid Build Coastguard Worker
177*6236dae4SAndroid Build Coastguard Worker /*
178*6236dae4SAndroid Build Coastguard Worker *
179*6236dae4SAndroid Build Coastguard Worker * VmsSpecialSize checks to see if the stat st_size can be trusted and
180*6236dae4SAndroid Build Coastguard Worker * if not to call a routine to get the correct size.
181*6236dae4SAndroid Build Coastguard Worker *
182*6236dae4SAndroid Build Coastguard Worker */
VmsSpecialSize(const char * name,const struct_stat * stat_buf)183*6236dae4SAndroid Build Coastguard Worker static curl_off_t VmsSpecialSize(const char *name,
184*6236dae4SAndroid Build Coastguard Worker const struct_stat *stat_buf)
185*6236dae4SAndroid Build Coastguard Worker {
186*6236dae4SAndroid Build Coastguard Worker switch(stat_buf->st_fab_rfm) {
187*6236dae4SAndroid Build Coastguard Worker case FAB$C_VAR:
188*6236dae4SAndroid Build Coastguard Worker case FAB$C_VFC:
189*6236dae4SAndroid Build Coastguard Worker return VmsRealFileSize(name, stat_buf);
190*6236dae4SAndroid Build Coastguard Worker break;
191*6236dae4SAndroid Build Coastguard Worker default:
192*6236dae4SAndroid Build Coastguard Worker return stat_buf->st_size;
193*6236dae4SAndroid Build Coastguard Worker }
194*6236dae4SAndroid Build Coastguard Worker }
195*6236dae4SAndroid Build Coastguard Worker
196*6236dae4SAndroid Build Coastguard Worker #define filesize(name, stat_data) VmsSpecialSize(name, &stat_data)
197*6236dae4SAndroid Build Coastguard Worker
198*6236dae4SAndroid Build Coastguard Worker /*
199*6236dae4SAndroid Build Coastguard Worker * vmsfopenread
200*6236dae4SAndroid Build Coastguard Worker *
201*6236dae4SAndroid Build Coastguard Worker * For upload to work as expected on VMS, different optional
202*6236dae4SAndroid Build Coastguard Worker * parameters must be added to the fopen command based on
203*6236dae4SAndroid Build Coastguard Worker * record format of the file.
204*6236dae4SAndroid Build Coastguard Worker *
205*6236dae4SAndroid Build Coastguard Worker */
vmsfopenread(const char * file,const char * mode)206*6236dae4SAndroid Build Coastguard Worker static FILE * vmsfopenread(const char *file, const char *mode)
207*6236dae4SAndroid Build Coastguard Worker {
208*6236dae4SAndroid Build Coastguard Worker struct_stat statbuf;
209*6236dae4SAndroid Build Coastguard Worker int result;
210*6236dae4SAndroid Build Coastguard Worker
211*6236dae4SAndroid Build Coastguard Worker result = stat(file, &statbuf);
212*6236dae4SAndroid Build Coastguard Worker
213*6236dae4SAndroid Build Coastguard Worker switch(statbuf.st_fab_rfm) {
214*6236dae4SAndroid Build Coastguard Worker case FAB$C_VAR:
215*6236dae4SAndroid Build Coastguard Worker case FAB$C_VFC:
216*6236dae4SAndroid Build Coastguard Worker case FAB$C_STMCR:
217*6236dae4SAndroid Build Coastguard Worker return fopen(file, FOPEN_READTEXT); /* VMS */
218*6236dae4SAndroid Build Coastguard Worker break;
219*6236dae4SAndroid Build Coastguard Worker default:
220*6236dae4SAndroid Build Coastguard Worker return fopen(file, FOPEN_READTEXT, "rfm=stmlf", "ctx=stm");
221*6236dae4SAndroid Build Coastguard Worker }
222*6236dae4SAndroid Build Coastguard Worker }
223*6236dae4SAndroid Build Coastguard Worker
224*6236dae4SAndroid Build Coastguard Worker #define fopen_read vmsfopenread
225*6236dae4SAndroid Build Coastguard Worker #endif
226*6236dae4SAndroid Build Coastguard Worker
227*6236dae4SAndroid Build Coastguard Worker
228*6236dae4SAndroid Build Coastguard Worker #ifndef HAVE_BASENAME
229*6236dae4SAndroid Build Coastguard Worker /*
230*6236dae4SAndroid Build Coastguard Worker (Quote from The Open Group Base Specifications Issue 6 IEEE Std 1003.1, 2004
231*6236dae4SAndroid Build Coastguard Worker Edition)
232*6236dae4SAndroid Build Coastguard Worker
233*6236dae4SAndroid Build Coastguard Worker The basename() function shall take the pathname pointed to by path and
234*6236dae4SAndroid Build Coastguard Worker return a pointer to the final component of the pathname, deleting any
235*6236dae4SAndroid Build Coastguard Worker trailing '/' characters.
236*6236dae4SAndroid Build Coastguard Worker
237*6236dae4SAndroid Build Coastguard Worker If the string pointed to by path consists entirely of the '/' character,
238*6236dae4SAndroid Build Coastguard Worker basename() shall return a pointer to the string "/". If the string pointed
239*6236dae4SAndroid Build Coastguard Worker to by path is exactly "//", it is implementation-defined whether '/' or "//"
240*6236dae4SAndroid Build Coastguard Worker is returned.
241*6236dae4SAndroid Build Coastguard Worker
242*6236dae4SAndroid Build Coastguard Worker If path is a null pointer or points to an empty string, basename() shall
243*6236dae4SAndroid Build Coastguard Worker return a pointer to the string ".".
244*6236dae4SAndroid Build Coastguard Worker
245*6236dae4SAndroid Build Coastguard Worker The basename() function may modify the string pointed to by path, and may
246*6236dae4SAndroid Build Coastguard Worker return a pointer to static storage that may then be overwritten by a
247*6236dae4SAndroid Build Coastguard Worker subsequent call to basename().
248*6236dae4SAndroid Build Coastguard Worker
249*6236dae4SAndroid Build Coastguard Worker The basename() function need not be reentrant. A function that is not
250*6236dae4SAndroid Build Coastguard Worker required to be reentrant is not required to be thread-safe.
251*6236dae4SAndroid Build Coastguard Worker
252*6236dae4SAndroid Build Coastguard Worker */
Curl_basename(char * path)253*6236dae4SAndroid Build Coastguard Worker static char *Curl_basename(char *path)
254*6236dae4SAndroid Build Coastguard Worker {
255*6236dae4SAndroid Build Coastguard Worker /* Ignore all the details above for now and make a quick and simple
256*6236dae4SAndroid Build Coastguard Worker implementation here */
257*6236dae4SAndroid Build Coastguard Worker char *s1;
258*6236dae4SAndroid Build Coastguard Worker char *s2;
259*6236dae4SAndroid Build Coastguard Worker
260*6236dae4SAndroid Build Coastguard Worker s1 = strrchr(path, '/');
261*6236dae4SAndroid Build Coastguard Worker s2 = strrchr(path, '\\');
262*6236dae4SAndroid Build Coastguard Worker
263*6236dae4SAndroid Build Coastguard Worker if(s1 && s2) {
264*6236dae4SAndroid Build Coastguard Worker path = (s1 > s2 ? s1 : s2) + 1;
265*6236dae4SAndroid Build Coastguard Worker }
266*6236dae4SAndroid Build Coastguard Worker else if(s1)
267*6236dae4SAndroid Build Coastguard Worker path = s1 + 1;
268*6236dae4SAndroid Build Coastguard Worker else if(s2)
269*6236dae4SAndroid Build Coastguard Worker path = s2 + 1;
270*6236dae4SAndroid Build Coastguard Worker
271*6236dae4SAndroid Build Coastguard Worker return path;
272*6236dae4SAndroid Build Coastguard Worker }
273*6236dae4SAndroid Build Coastguard Worker
274*6236dae4SAndroid Build Coastguard Worker #define basename(x) Curl_basename((x))
275*6236dae4SAndroid Build Coastguard Worker #endif
276*6236dae4SAndroid Build Coastguard Worker
277*6236dae4SAndroid Build Coastguard Worker
278*6236dae4SAndroid Build Coastguard Worker /* Set readback state. */
mimesetstate(struct mime_state * state,enum mimestate tok,void * ptr)279*6236dae4SAndroid Build Coastguard Worker static void mimesetstate(struct mime_state *state,
280*6236dae4SAndroid Build Coastguard Worker enum mimestate tok, void *ptr)
281*6236dae4SAndroid Build Coastguard Worker {
282*6236dae4SAndroid Build Coastguard Worker state->state = tok;
283*6236dae4SAndroid Build Coastguard Worker state->ptr = ptr;
284*6236dae4SAndroid Build Coastguard Worker state->offset = 0;
285*6236dae4SAndroid Build Coastguard Worker }
286*6236dae4SAndroid Build Coastguard Worker
287*6236dae4SAndroid Build Coastguard Worker
288*6236dae4SAndroid Build Coastguard Worker /* Escape header string into allocated memory. */
escape_string(struct Curl_easy * data,const char * src,enum mimestrategy strategy)289*6236dae4SAndroid Build Coastguard Worker static char *escape_string(struct Curl_easy *data,
290*6236dae4SAndroid Build Coastguard Worker const char *src, enum mimestrategy strategy)
291*6236dae4SAndroid Build Coastguard Worker {
292*6236dae4SAndroid Build Coastguard Worker CURLcode result;
293*6236dae4SAndroid Build Coastguard Worker struct dynbuf db;
294*6236dae4SAndroid Build Coastguard Worker const char * const *table;
295*6236dae4SAndroid Build Coastguard Worker const char * const *p;
296*6236dae4SAndroid Build Coastguard Worker /* replace first character by rest of string. */
297*6236dae4SAndroid Build Coastguard Worker static const char * const mimetable[] = {
298*6236dae4SAndroid Build Coastguard Worker "\\\\\\",
299*6236dae4SAndroid Build Coastguard Worker "\"\\\"",
300*6236dae4SAndroid Build Coastguard Worker NULL
301*6236dae4SAndroid Build Coastguard Worker };
302*6236dae4SAndroid Build Coastguard Worker /* WHATWG HTML living standard 4.10.21.8 2 specifies:
303*6236dae4SAndroid Build Coastguard Worker For field names and filenames for file fields, the result of the
304*6236dae4SAndroid Build Coastguard Worker encoding in the previous bullet point must be escaped by replacing
305*6236dae4SAndroid Build Coastguard Worker any 0x0A (LF) bytes with the byte sequence `%0A`, 0x0D (CR) with `%0D`
306*6236dae4SAndroid Build Coastguard Worker and 0x22 (") with `%22`.
307*6236dae4SAndroid Build Coastguard Worker The user agent must not perform any other escapes. */
308*6236dae4SAndroid Build Coastguard Worker static const char * const formtable[] = {
309*6236dae4SAndroid Build Coastguard Worker "\"%22",
310*6236dae4SAndroid Build Coastguard Worker "\r%0D",
311*6236dae4SAndroid Build Coastguard Worker "\n%0A",
312*6236dae4SAndroid Build Coastguard Worker NULL
313*6236dae4SAndroid Build Coastguard Worker };
314*6236dae4SAndroid Build Coastguard Worker
315*6236dae4SAndroid Build Coastguard Worker table = formtable;
316*6236dae4SAndroid Build Coastguard Worker /* data can be NULL when this function is called indirectly from
317*6236dae4SAndroid Build Coastguard Worker curl_formget(). */
318*6236dae4SAndroid Build Coastguard Worker if(strategy == MIMESTRATEGY_MAIL || (data && (data->set.mime_formescape)))
319*6236dae4SAndroid Build Coastguard Worker table = mimetable;
320*6236dae4SAndroid Build Coastguard Worker
321*6236dae4SAndroid Build Coastguard Worker Curl_dyn_init(&db, CURL_MAX_INPUT_LENGTH);
322*6236dae4SAndroid Build Coastguard Worker
323*6236dae4SAndroid Build Coastguard Worker for(result = Curl_dyn_addn(&db, STRCONST("")); !result && *src; src++) {
324*6236dae4SAndroid Build Coastguard Worker for(p = table; *p && **p != *src; p++)
325*6236dae4SAndroid Build Coastguard Worker ;
326*6236dae4SAndroid Build Coastguard Worker
327*6236dae4SAndroid Build Coastguard Worker if(*p)
328*6236dae4SAndroid Build Coastguard Worker result = Curl_dyn_add(&db, *p + 1);
329*6236dae4SAndroid Build Coastguard Worker else
330*6236dae4SAndroid Build Coastguard Worker result = Curl_dyn_addn(&db, src, 1);
331*6236dae4SAndroid Build Coastguard Worker }
332*6236dae4SAndroid Build Coastguard Worker
333*6236dae4SAndroid Build Coastguard Worker return Curl_dyn_ptr(&db);
334*6236dae4SAndroid Build Coastguard Worker }
335*6236dae4SAndroid Build Coastguard Worker
336*6236dae4SAndroid Build Coastguard Worker /* Check if header matches. */
match_header(struct curl_slist * hdr,const char * lbl,size_t len)337*6236dae4SAndroid Build Coastguard Worker static char *match_header(struct curl_slist *hdr, const char *lbl, size_t len)
338*6236dae4SAndroid Build Coastguard Worker {
339*6236dae4SAndroid Build Coastguard Worker char *value = NULL;
340*6236dae4SAndroid Build Coastguard Worker
341*6236dae4SAndroid Build Coastguard Worker if(strncasecompare(hdr->data, lbl, len) && hdr->data[len] == ':')
342*6236dae4SAndroid Build Coastguard Worker for(value = hdr->data + len + 1; *value == ' '; value++)
343*6236dae4SAndroid Build Coastguard Worker ;
344*6236dae4SAndroid Build Coastguard Worker return value;
345*6236dae4SAndroid Build Coastguard Worker }
346*6236dae4SAndroid Build Coastguard Worker
347*6236dae4SAndroid Build Coastguard Worker /* Get a header from an slist. */
search_header(struct curl_slist * hdrlist,const char * hdr,size_t len)348*6236dae4SAndroid Build Coastguard Worker static char *search_header(struct curl_slist *hdrlist,
349*6236dae4SAndroid Build Coastguard Worker const char *hdr, size_t len)
350*6236dae4SAndroid Build Coastguard Worker {
351*6236dae4SAndroid Build Coastguard Worker char *value = NULL;
352*6236dae4SAndroid Build Coastguard Worker
353*6236dae4SAndroid Build Coastguard Worker for(; !value && hdrlist; hdrlist = hdrlist->next)
354*6236dae4SAndroid Build Coastguard Worker value = match_header(hdrlist, hdr, len);
355*6236dae4SAndroid Build Coastguard Worker
356*6236dae4SAndroid Build Coastguard Worker return value;
357*6236dae4SAndroid Build Coastguard Worker }
358*6236dae4SAndroid Build Coastguard Worker
strippath(const char * fullfile)359*6236dae4SAndroid Build Coastguard Worker static char *strippath(const char *fullfile)
360*6236dae4SAndroid Build Coastguard Worker {
361*6236dae4SAndroid Build Coastguard Worker char *filename;
362*6236dae4SAndroid Build Coastguard Worker char *base;
363*6236dae4SAndroid Build Coastguard Worker filename = strdup(fullfile); /* duplicate since basename() may ruin the
364*6236dae4SAndroid Build Coastguard Worker buffer it works on */
365*6236dae4SAndroid Build Coastguard Worker if(!filename)
366*6236dae4SAndroid Build Coastguard Worker return NULL;
367*6236dae4SAndroid Build Coastguard Worker base = strdup(basename(filename));
368*6236dae4SAndroid Build Coastguard Worker
369*6236dae4SAndroid Build Coastguard Worker free(filename); /* free temporary buffer */
370*6236dae4SAndroid Build Coastguard Worker
371*6236dae4SAndroid Build Coastguard Worker return base; /* returns an allocated string or NULL ! */
372*6236dae4SAndroid Build Coastguard Worker }
373*6236dae4SAndroid Build Coastguard Worker
374*6236dae4SAndroid Build Coastguard Worker /* Initialize data encoder state. */
cleanup_encoder_state(struct mime_encoder_state * p)375*6236dae4SAndroid Build Coastguard Worker static void cleanup_encoder_state(struct mime_encoder_state *p)
376*6236dae4SAndroid Build Coastguard Worker {
377*6236dae4SAndroid Build Coastguard Worker p->pos = 0;
378*6236dae4SAndroid Build Coastguard Worker p->bufbeg = 0;
379*6236dae4SAndroid Build Coastguard Worker p->bufend = 0;
380*6236dae4SAndroid Build Coastguard Worker }
381*6236dae4SAndroid Build Coastguard Worker
382*6236dae4SAndroid Build Coastguard Worker
383*6236dae4SAndroid Build Coastguard Worker /* Dummy encoder. This is used for 8bit and binary content encodings. */
encoder_nop_read(char * buffer,size_t size,bool ateof,struct curl_mimepart * part)384*6236dae4SAndroid Build Coastguard Worker static size_t encoder_nop_read(char *buffer, size_t size, bool ateof,
385*6236dae4SAndroid Build Coastguard Worker struct curl_mimepart *part)
386*6236dae4SAndroid Build Coastguard Worker {
387*6236dae4SAndroid Build Coastguard Worker struct mime_encoder_state *st = &part->encstate;
388*6236dae4SAndroid Build Coastguard Worker size_t insize = st->bufend - st->bufbeg;
389*6236dae4SAndroid Build Coastguard Worker
390*6236dae4SAndroid Build Coastguard Worker (void) ateof;
391*6236dae4SAndroid Build Coastguard Worker
392*6236dae4SAndroid Build Coastguard Worker if(!size)
393*6236dae4SAndroid Build Coastguard Worker return STOP_FILLING;
394*6236dae4SAndroid Build Coastguard Worker
395*6236dae4SAndroid Build Coastguard Worker if(size > insize)
396*6236dae4SAndroid Build Coastguard Worker size = insize;
397*6236dae4SAndroid Build Coastguard Worker
398*6236dae4SAndroid Build Coastguard Worker if(size)
399*6236dae4SAndroid Build Coastguard Worker memcpy(buffer, st->buf + st->bufbeg, size);
400*6236dae4SAndroid Build Coastguard Worker
401*6236dae4SAndroid Build Coastguard Worker st->bufbeg += size;
402*6236dae4SAndroid Build Coastguard Worker return size;
403*6236dae4SAndroid Build Coastguard Worker }
404*6236dae4SAndroid Build Coastguard Worker
encoder_nop_size(curl_mimepart * part)405*6236dae4SAndroid Build Coastguard Worker static curl_off_t encoder_nop_size(curl_mimepart *part)
406*6236dae4SAndroid Build Coastguard Worker {
407*6236dae4SAndroid Build Coastguard Worker return part->datasize;
408*6236dae4SAndroid Build Coastguard Worker }
409*6236dae4SAndroid Build Coastguard Worker
410*6236dae4SAndroid Build Coastguard Worker
411*6236dae4SAndroid Build Coastguard Worker /* 7bit encoder: the encoder is just a data validity check. */
encoder_7bit_read(char * buffer,size_t size,bool ateof,curl_mimepart * part)412*6236dae4SAndroid Build Coastguard Worker static size_t encoder_7bit_read(char *buffer, size_t size, bool ateof,
413*6236dae4SAndroid Build Coastguard Worker curl_mimepart *part)
414*6236dae4SAndroid Build Coastguard Worker {
415*6236dae4SAndroid Build Coastguard Worker struct mime_encoder_state *st = &part->encstate;
416*6236dae4SAndroid Build Coastguard Worker size_t cursize = st->bufend - st->bufbeg;
417*6236dae4SAndroid Build Coastguard Worker
418*6236dae4SAndroid Build Coastguard Worker (void) ateof;
419*6236dae4SAndroid Build Coastguard Worker
420*6236dae4SAndroid Build Coastguard Worker if(!size)
421*6236dae4SAndroid Build Coastguard Worker return STOP_FILLING;
422*6236dae4SAndroid Build Coastguard Worker
423*6236dae4SAndroid Build Coastguard Worker if(size > cursize)
424*6236dae4SAndroid Build Coastguard Worker size = cursize;
425*6236dae4SAndroid Build Coastguard Worker
426*6236dae4SAndroid Build Coastguard Worker for(cursize = 0; cursize < size; cursize++) {
427*6236dae4SAndroid Build Coastguard Worker *buffer = st->buf[st->bufbeg];
428*6236dae4SAndroid Build Coastguard Worker if(*buffer++ & 0x80)
429*6236dae4SAndroid Build Coastguard Worker return cursize ? cursize : READ_ERROR;
430*6236dae4SAndroid Build Coastguard Worker st->bufbeg++;
431*6236dae4SAndroid Build Coastguard Worker }
432*6236dae4SAndroid Build Coastguard Worker
433*6236dae4SAndroid Build Coastguard Worker return cursize;
434*6236dae4SAndroid Build Coastguard Worker }
435*6236dae4SAndroid Build Coastguard Worker
436*6236dae4SAndroid Build Coastguard Worker
437*6236dae4SAndroid Build Coastguard Worker /* Base64 content encoder. */
encoder_base64_read(char * buffer,size_t size,bool ateof,curl_mimepart * part)438*6236dae4SAndroid Build Coastguard Worker static size_t encoder_base64_read(char *buffer, size_t size, bool ateof,
439*6236dae4SAndroid Build Coastguard Worker curl_mimepart *part)
440*6236dae4SAndroid Build Coastguard Worker {
441*6236dae4SAndroid Build Coastguard Worker struct mime_encoder_state *st = &part->encstate;
442*6236dae4SAndroid Build Coastguard Worker size_t cursize = 0;
443*6236dae4SAndroid Build Coastguard Worker int i;
444*6236dae4SAndroid Build Coastguard Worker char *ptr = buffer;
445*6236dae4SAndroid Build Coastguard Worker
446*6236dae4SAndroid Build Coastguard Worker while(st->bufbeg < st->bufend) {
447*6236dae4SAndroid Build Coastguard Worker /* Line full ? */
448*6236dae4SAndroid Build Coastguard Worker if(st->pos > MAX_ENCODED_LINE_LENGTH - 4) {
449*6236dae4SAndroid Build Coastguard Worker /* Yes, we need 2 characters for CRLF. */
450*6236dae4SAndroid Build Coastguard Worker if(size < 2) {
451*6236dae4SAndroid Build Coastguard Worker if(!cursize)
452*6236dae4SAndroid Build Coastguard Worker return STOP_FILLING;
453*6236dae4SAndroid Build Coastguard Worker break;
454*6236dae4SAndroid Build Coastguard Worker }
455*6236dae4SAndroid Build Coastguard Worker *ptr++ = '\r';
456*6236dae4SAndroid Build Coastguard Worker *ptr++ = '\n';
457*6236dae4SAndroid Build Coastguard Worker st->pos = 0;
458*6236dae4SAndroid Build Coastguard Worker cursize += 2;
459*6236dae4SAndroid Build Coastguard Worker size -= 2;
460*6236dae4SAndroid Build Coastguard Worker }
461*6236dae4SAndroid Build Coastguard Worker
462*6236dae4SAndroid Build Coastguard Worker /* Be sure there is enough space and input data for a base64 group. */
463*6236dae4SAndroid Build Coastguard Worker if(size < 4) {
464*6236dae4SAndroid Build Coastguard Worker if(!cursize)
465*6236dae4SAndroid Build Coastguard Worker return STOP_FILLING;
466*6236dae4SAndroid Build Coastguard Worker break;
467*6236dae4SAndroid Build Coastguard Worker }
468*6236dae4SAndroid Build Coastguard Worker if(st->bufend - st->bufbeg < 3)
469*6236dae4SAndroid Build Coastguard Worker break;
470*6236dae4SAndroid Build Coastguard Worker
471*6236dae4SAndroid Build Coastguard Worker /* Encode three bytes as four characters. */
472*6236dae4SAndroid Build Coastguard Worker i = st->buf[st->bufbeg++] & 0xFF;
473*6236dae4SAndroid Build Coastguard Worker i = (i << 8) | (st->buf[st->bufbeg++] & 0xFF);
474*6236dae4SAndroid Build Coastguard Worker i = (i << 8) | (st->buf[st->bufbeg++] & 0xFF);
475*6236dae4SAndroid Build Coastguard Worker *ptr++ = base64enc[(i >> 18) & 0x3F];
476*6236dae4SAndroid Build Coastguard Worker *ptr++ = base64enc[(i >> 12) & 0x3F];
477*6236dae4SAndroid Build Coastguard Worker *ptr++ = base64enc[(i >> 6) & 0x3F];
478*6236dae4SAndroid Build Coastguard Worker *ptr++ = base64enc[i & 0x3F];
479*6236dae4SAndroid Build Coastguard Worker cursize += 4;
480*6236dae4SAndroid Build Coastguard Worker st->pos += 4;
481*6236dae4SAndroid Build Coastguard Worker size -= 4;
482*6236dae4SAndroid Build Coastguard Worker }
483*6236dae4SAndroid Build Coastguard Worker
484*6236dae4SAndroid Build Coastguard Worker /* If at eof, we have to flush the buffered data. */
485*6236dae4SAndroid Build Coastguard Worker if(ateof) {
486*6236dae4SAndroid Build Coastguard Worker if(size < 4) {
487*6236dae4SAndroid Build Coastguard Worker if(!cursize)
488*6236dae4SAndroid Build Coastguard Worker return STOP_FILLING;
489*6236dae4SAndroid Build Coastguard Worker }
490*6236dae4SAndroid Build Coastguard Worker else {
491*6236dae4SAndroid Build Coastguard Worker /* Buffered data size can only be 0, 1 or 2. */
492*6236dae4SAndroid Build Coastguard Worker ptr[2] = ptr[3] = '=';
493*6236dae4SAndroid Build Coastguard Worker i = 0;
494*6236dae4SAndroid Build Coastguard Worker
495*6236dae4SAndroid Build Coastguard Worker /* If there is buffered data */
496*6236dae4SAndroid Build Coastguard Worker if(st->bufend != st->bufbeg) {
497*6236dae4SAndroid Build Coastguard Worker
498*6236dae4SAndroid Build Coastguard Worker if(st->bufend - st->bufbeg == 2)
499*6236dae4SAndroid Build Coastguard Worker i = (st->buf[st->bufbeg + 1] & 0xFF) << 8;
500*6236dae4SAndroid Build Coastguard Worker
501*6236dae4SAndroid Build Coastguard Worker i |= (st->buf[st->bufbeg] & 0xFF) << 16;
502*6236dae4SAndroid Build Coastguard Worker ptr[0] = base64enc[(i >> 18) & 0x3F];
503*6236dae4SAndroid Build Coastguard Worker ptr[1] = base64enc[(i >> 12) & 0x3F];
504*6236dae4SAndroid Build Coastguard Worker if(++st->bufbeg != st->bufend) {
505*6236dae4SAndroid Build Coastguard Worker ptr[2] = base64enc[(i >> 6) & 0x3F];
506*6236dae4SAndroid Build Coastguard Worker st->bufbeg++;
507*6236dae4SAndroid Build Coastguard Worker }
508*6236dae4SAndroid Build Coastguard Worker cursize += 4;
509*6236dae4SAndroid Build Coastguard Worker st->pos += 4;
510*6236dae4SAndroid Build Coastguard Worker }
511*6236dae4SAndroid Build Coastguard Worker }
512*6236dae4SAndroid Build Coastguard Worker }
513*6236dae4SAndroid Build Coastguard Worker
514*6236dae4SAndroid Build Coastguard Worker return cursize;
515*6236dae4SAndroid Build Coastguard Worker }
516*6236dae4SAndroid Build Coastguard Worker
encoder_base64_size(curl_mimepart * part)517*6236dae4SAndroid Build Coastguard Worker static curl_off_t encoder_base64_size(curl_mimepart *part)
518*6236dae4SAndroid Build Coastguard Worker {
519*6236dae4SAndroid Build Coastguard Worker curl_off_t size = part->datasize;
520*6236dae4SAndroid Build Coastguard Worker
521*6236dae4SAndroid Build Coastguard Worker if(size <= 0)
522*6236dae4SAndroid Build Coastguard Worker return size; /* Unknown size or no data. */
523*6236dae4SAndroid Build Coastguard Worker
524*6236dae4SAndroid Build Coastguard Worker /* Compute base64 character count. */
525*6236dae4SAndroid Build Coastguard Worker size = 4 * (1 + (size - 1) / 3);
526*6236dae4SAndroid Build Coastguard Worker
527*6236dae4SAndroid Build Coastguard Worker /* Effective character count must include CRLFs. */
528*6236dae4SAndroid Build Coastguard Worker return size + 2 * ((size - 1) / MAX_ENCODED_LINE_LENGTH);
529*6236dae4SAndroid Build Coastguard Worker }
530*6236dae4SAndroid Build Coastguard Worker
531*6236dae4SAndroid Build Coastguard Worker
532*6236dae4SAndroid Build Coastguard Worker /* Quoted-printable lookahead.
533*6236dae4SAndroid Build Coastguard Worker *
534*6236dae4SAndroid Build Coastguard Worker * Check if a CRLF or end of data is in input buffer at current position + n.
535*6236dae4SAndroid Build Coastguard Worker * Return -1 if more data needed, 1 if CRLF or end of data, else 0.
536*6236dae4SAndroid Build Coastguard Worker */
qp_lookahead_eol(struct mime_encoder_state * st,int ateof,size_t n)537*6236dae4SAndroid Build Coastguard Worker static int qp_lookahead_eol(struct mime_encoder_state *st, int ateof, size_t n)
538*6236dae4SAndroid Build Coastguard Worker {
539*6236dae4SAndroid Build Coastguard Worker n += st->bufbeg;
540*6236dae4SAndroid Build Coastguard Worker if(n >= st->bufend && ateof)
541*6236dae4SAndroid Build Coastguard Worker return 1;
542*6236dae4SAndroid Build Coastguard Worker if(n + 2 > st->bufend)
543*6236dae4SAndroid Build Coastguard Worker return ateof ? 0 : -1;
544*6236dae4SAndroid Build Coastguard Worker if(qp_class[st->buf[n] & 0xFF] == QP_CR &&
545*6236dae4SAndroid Build Coastguard Worker qp_class[st->buf[n + 1] & 0xFF] == QP_LF)
546*6236dae4SAndroid Build Coastguard Worker return 1;
547*6236dae4SAndroid Build Coastguard Worker return 0;
548*6236dae4SAndroid Build Coastguard Worker }
549*6236dae4SAndroid Build Coastguard Worker
550*6236dae4SAndroid Build Coastguard Worker /* Quoted-printable encoder. */
encoder_qp_read(char * buffer,size_t size,bool ateof,curl_mimepart * part)551*6236dae4SAndroid Build Coastguard Worker static size_t encoder_qp_read(char *buffer, size_t size, bool ateof,
552*6236dae4SAndroid Build Coastguard Worker curl_mimepart *part)
553*6236dae4SAndroid Build Coastguard Worker {
554*6236dae4SAndroid Build Coastguard Worker struct mime_encoder_state *st = &part->encstate;
555*6236dae4SAndroid Build Coastguard Worker char *ptr = buffer;
556*6236dae4SAndroid Build Coastguard Worker size_t cursize = 0;
557*6236dae4SAndroid Build Coastguard Worker int softlinebreak;
558*6236dae4SAndroid Build Coastguard Worker char buf[4];
559*6236dae4SAndroid Build Coastguard Worker
560*6236dae4SAndroid Build Coastguard Worker /* On all platforms, input is supposed to be ASCII compatible: for this
561*6236dae4SAndroid Build Coastguard Worker reason, we use hexadecimal ASCII codes in this function rather than
562*6236dae4SAndroid Build Coastguard Worker character constants that can be interpreted as non-ASCII on some
563*6236dae4SAndroid Build Coastguard Worker platforms. Preserve ASCII encoding on output too. */
564*6236dae4SAndroid Build Coastguard Worker while(st->bufbeg < st->bufend) {
565*6236dae4SAndroid Build Coastguard Worker size_t len = 1;
566*6236dae4SAndroid Build Coastguard Worker size_t consumed = 1;
567*6236dae4SAndroid Build Coastguard Worker int i = st->buf[st->bufbeg];
568*6236dae4SAndroid Build Coastguard Worker buf[0] = (char) i;
569*6236dae4SAndroid Build Coastguard Worker buf[1] = aschex[(i >> 4) & 0xF];
570*6236dae4SAndroid Build Coastguard Worker buf[2] = aschex[i & 0xF];
571*6236dae4SAndroid Build Coastguard Worker
572*6236dae4SAndroid Build Coastguard Worker switch(qp_class[st->buf[st->bufbeg] & 0xFF]) {
573*6236dae4SAndroid Build Coastguard Worker case QP_OK: /* Not a special character. */
574*6236dae4SAndroid Build Coastguard Worker break;
575*6236dae4SAndroid Build Coastguard Worker case QP_SP: /* Space or tab. */
576*6236dae4SAndroid Build Coastguard Worker /* Spacing must be escaped if followed by CRLF. */
577*6236dae4SAndroid Build Coastguard Worker switch(qp_lookahead_eol(st, ateof, 1)) {
578*6236dae4SAndroid Build Coastguard Worker case -1: /* More input data needed. */
579*6236dae4SAndroid Build Coastguard Worker return cursize;
580*6236dae4SAndroid Build Coastguard Worker case 0: /* No encoding needed. */
581*6236dae4SAndroid Build Coastguard Worker break;
582*6236dae4SAndroid Build Coastguard Worker default: /* CRLF after space or tab. */
583*6236dae4SAndroid Build Coastguard Worker buf[0] = '\x3D'; /* '=' */
584*6236dae4SAndroid Build Coastguard Worker len = 3;
585*6236dae4SAndroid Build Coastguard Worker break;
586*6236dae4SAndroid Build Coastguard Worker }
587*6236dae4SAndroid Build Coastguard Worker break;
588*6236dae4SAndroid Build Coastguard Worker case QP_CR: /* Carriage return. */
589*6236dae4SAndroid Build Coastguard Worker /* If followed by a line-feed, output the CRLF pair.
590*6236dae4SAndroid Build Coastguard Worker Else escape it. */
591*6236dae4SAndroid Build Coastguard Worker switch(qp_lookahead_eol(st, ateof, 0)) {
592*6236dae4SAndroid Build Coastguard Worker case -1: /* Need more data. */
593*6236dae4SAndroid Build Coastguard Worker return cursize;
594*6236dae4SAndroid Build Coastguard Worker case 1: /* CRLF found. */
595*6236dae4SAndroid Build Coastguard Worker buf[len++] = '\x0A'; /* Append '\n'. */
596*6236dae4SAndroid Build Coastguard Worker consumed = 2;
597*6236dae4SAndroid Build Coastguard Worker break;
598*6236dae4SAndroid Build Coastguard Worker default: /* Not followed by LF: escape. */
599*6236dae4SAndroid Build Coastguard Worker buf[0] = '\x3D'; /* '=' */
600*6236dae4SAndroid Build Coastguard Worker len = 3;
601*6236dae4SAndroid Build Coastguard Worker break;
602*6236dae4SAndroid Build Coastguard Worker }
603*6236dae4SAndroid Build Coastguard Worker break;
604*6236dae4SAndroid Build Coastguard Worker default: /* Character must be escaped. */
605*6236dae4SAndroid Build Coastguard Worker buf[0] = '\x3D'; /* '=' */
606*6236dae4SAndroid Build Coastguard Worker len = 3;
607*6236dae4SAndroid Build Coastguard Worker break;
608*6236dae4SAndroid Build Coastguard Worker }
609*6236dae4SAndroid Build Coastguard Worker
610*6236dae4SAndroid Build Coastguard Worker /* Be sure the encoded character fits within maximum line length. */
611*6236dae4SAndroid Build Coastguard Worker if(buf[len - 1] != '\x0A') { /* '\n' */
612*6236dae4SAndroid Build Coastguard Worker softlinebreak = st->pos + len > MAX_ENCODED_LINE_LENGTH;
613*6236dae4SAndroid Build Coastguard Worker if(!softlinebreak && st->pos + len == MAX_ENCODED_LINE_LENGTH) {
614*6236dae4SAndroid Build Coastguard Worker /* We may use the current line only if end of data or followed by
615*6236dae4SAndroid Build Coastguard Worker a CRLF. */
616*6236dae4SAndroid Build Coastguard Worker switch(qp_lookahead_eol(st, ateof, consumed)) {
617*6236dae4SAndroid Build Coastguard Worker case -1: /* Need more data. */
618*6236dae4SAndroid Build Coastguard Worker return cursize;
619*6236dae4SAndroid Build Coastguard Worker case 0: /* Not followed by a CRLF. */
620*6236dae4SAndroid Build Coastguard Worker softlinebreak = 1;
621*6236dae4SAndroid Build Coastguard Worker break;
622*6236dae4SAndroid Build Coastguard Worker }
623*6236dae4SAndroid Build Coastguard Worker }
624*6236dae4SAndroid Build Coastguard Worker if(softlinebreak) {
625*6236dae4SAndroid Build Coastguard Worker strcpy(buf, "\x3D\x0D\x0A"); /* "=\r\n" */
626*6236dae4SAndroid Build Coastguard Worker len = 3;
627*6236dae4SAndroid Build Coastguard Worker consumed = 0;
628*6236dae4SAndroid Build Coastguard Worker }
629*6236dae4SAndroid Build Coastguard Worker }
630*6236dae4SAndroid Build Coastguard Worker
631*6236dae4SAndroid Build Coastguard Worker /* If the output buffer would overflow, do not store. */
632*6236dae4SAndroid Build Coastguard Worker if(len > size) {
633*6236dae4SAndroid Build Coastguard Worker if(!cursize)
634*6236dae4SAndroid Build Coastguard Worker return STOP_FILLING;
635*6236dae4SAndroid Build Coastguard Worker break;
636*6236dae4SAndroid Build Coastguard Worker }
637*6236dae4SAndroid Build Coastguard Worker
638*6236dae4SAndroid Build Coastguard Worker /* Append to output buffer. */
639*6236dae4SAndroid Build Coastguard Worker memcpy(ptr, buf, len);
640*6236dae4SAndroid Build Coastguard Worker cursize += len;
641*6236dae4SAndroid Build Coastguard Worker ptr += len;
642*6236dae4SAndroid Build Coastguard Worker size -= len;
643*6236dae4SAndroid Build Coastguard Worker st->pos += len;
644*6236dae4SAndroid Build Coastguard Worker if(buf[len - 1] == '\x0A') /* '\n' */
645*6236dae4SAndroid Build Coastguard Worker st->pos = 0;
646*6236dae4SAndroid Build Coastguard Worker st->bufbeg += consumed;
647*6236dae4SAndroid Build Coastguard Worker }
648*6236dae4SAndroid Build Coastguard Worker
649*6236dae4SAndroid Build Coastguard Worker return cursize;
650*6236dae4SAndroid Build Coastguard Worker }
651*6236dae4SAndroid Build Coastguard Worker
encoder_qp_size(curl_mimepart * part)652*6236dae4SAndroid Build Coastguard Worker static curl_off_t encoder_qp_size(curl_mimepart *part)
653*6236dae4SAndroid Build Coastguard Worker {
654*6236dae4SAndroid Build Coastguard Worker /* Determining the size can only be done by reading the data: unless the
655*6236dae4SAndroid Build Coastguard Worker data size is 0, we return it as unknown (-1). */
656*6236dae4SAndroid Build Coastguard Worker return part->datasize ? -1 : 0;
657*6236dae4SAndroid Build Coastguard Worker }
658*6236dae4SAndroid Build Coastguard Worker
659*6236dae4SAndroid Build Coastguard Worker
660*6236dae4SAndroid Build Coastguard Worker /* In-memory data callbacks. */
661*6236dae4SAndroid Build Coastguard Worker /* Argument is a pointer to the mime part. */
mime_mem_read(char * buffer,size_t size,size_t nitems,void * instream)662*6236dae4SAndroid Build Coastguard Worker static size_t mime_mem_read(char *buffer, size_t size, size_t nitems,
663*6236dae4SAndroid Build Coastguard Worker void *instream)
664*6236dae4SAndroid Build Coastguard Worker {
665*6236dae4SAndroid Build Coastguard Worker curl_mimepart *part = (curl_mimepart *) instream;
666*6236dae4SAndroid Build Coastguard Worker size_t sz = curlx_sotouz(part->datasize - part->state.offset);
667*6236dae4SAndroid Build Coastguard Worker (void) size; /* Always 1.*/
668*6236dae4SAndroid Build Coastguard Worker
669*6236dae4SAndroid Build Coastguard Worker if(!nitems)
670*6236dae4SAndroid Build Coastguard Worker return STOP_FILLING;
671*6236dae4SAndroid Build Coastguard Worker
672*6236dae4SAndroid Build Coastguard Worker if(sz > nitems)
673*6236dae4SAndroid Build Coastguard Worker sz = nitems;
674*6236dae4SAndroid Build Coastguard Worker
675*6236dae4SAndroid Build Coastguard Worker if(sz)
676*6236dae4SAndroid Build Coastguard Worker memcpy(buffer, part->data + curlx_sotouz(part->state.offset), sz);
677*6236dae4SAndroid Build Coastguard Worker
678*6236dae4SAndroid Build Coastguard Worker return sz;
679*6236dae4SAndroid Build Coastguard Worker }
680*6236dae4SAndroid Build Coastguard Worker
mime_mem_seek(void * instream,curl_off_t offset,int whence)681*6236dae4SAndroid Build Coastguard Worker static int mime_mem_seek(void *instream, curl_off_t offset, int whence)
682*6236dae4SAndroid Build Coastguard Worker {
683*6236dae4SAndroid Build Coastguard Worker curl_mimepart *part = (curl_mimepart *) instream;
684*6236dae4SAndroid Build Coastguard Worker
685*6236dae4SAndroid Build Coastguard Worker switch(whence) {
686*6236dae4SAndroid Build Coastguard Worker case SEEK_CUR:
687*6236dae4SAndroid Build Coastguard Worker offset += part->state.offset;
688*6236dae4SAndroid Build Coastguard Worker break;
689*6236dae4SAndroid Build Coastguard Worker case SEEK_END:
690*6236dae4SAndroid Build Coastguard Worker offset += part->datasize;
691*6236dae4SAndroid Build Coastguard Worker break;
692*6236dae4SAndroid Build Coastguard Worker }
693*6236dae4SAndroid Build Coastguard Worker
694*6236dae4SAndroid Build Coastguard Worker if(offset < 0 || offset > part->datasize)
695*6236dae4SAndroid Build Coastguard Worker return CURL_SEEKFUNC_FAIL;
696*6236dae4SAndroid Build Coastguard Worker
697*6236dae4SAndroid Build Coastguard Worker part->state.offset = offset;
698*6236dae4SAndroid Build Coastguard Worker return CURL_SEEKFUNC_OK;
699*6236dae4SAndroid Build Coastguard Worker }
700*6236dae4SAndroid Build Coastguard Worker
mime_mem_free(void * ptr)701*6236dae4SAndroid Build Coastguard Worker static void mime_mem_free(void *ptr)
702*6236dae4SAndroid Build Coastguard Worker {
703*6236dae4SAndroid Build Coastguard Worker Curl_safefree(((curl_mimepart *) ptr)->data);
704*6236dae4SAndroid Build Coastguard Worker }
705*6236dae4SAndroid Build Coastguard Worker
706*6236dae4SAndroid Build Coastguard Worker
707*6236dae4SAndroid Build Coastguard Worker /* Named file callbacks. */
708*6236dae4SAndroid Build Coastguard Worker /* Argument is a pointer to the mime part. */
mime_open_file(curl_mimepart * part)709*6236dae4SAndroid Build Coastguard Worker static int mime_open_file(curl_mimepart *part)
710*6236dae4SAndroid Build Coastguard Worker {
711*6236dae4SAndroid Build Coastguard Worker /* Open a MIMEKIND_FILE part. */
712*6236dae4SAndroid Build Coastguard Worker
713*6236dae4SAndroid Build Coastguard Worker if(part->fp)
714*6236dae4SAndroid Build Coastguard Worker return 0;
715*6236dae4SAndroid Build Coastguard Worker part->fp = fopen_read(part->data, "rb");
716*6236dae4SAndroid Build Coastguard Worker return part->fp ? 0 : -1;
717*6236dae4SAndroid Build Coastguard Worker }
718*6236dae4SAndroid Build Coastguard Worker
mime_file_read(char * buffer,size_t size,size_t nitems,void * instream)719*6236dae4SAndroid Build Coastguard Worker static size_t mime_file_read(char *buffer, size_t size, size_t nitems,
720*6236dae4SAndroid Build Coastguard Worker void *instream)
721*6236dae4SAndroid Build Coastguard Worker {
722*6236dae4SAndroid Build Coastguard Worker curl_mimepart *part = (curl_mimepart *) instream;
723*6236dae4SAndroid Build Coastguard Worker
724*6236dae4SAndroid Build Coastguard Worker if(!nitems)
725*6236dae4SAndroid Build Coastguard Worker return STOP_FILLING;
726*6236dae4SAndroid Build Coastguard Worker
727*6236dae4SAndroid Build Coastguard Worker if(mime_open_file(part))
728*6236dae4SAndroid Build Coastguard Worker return READ_ERROR;
729*6236dae4SAndroid Build Coastguard Worker
730*6236dae4SAndroid Build Coastguard Worker return fread(buffer, size, nitems, part->fp);
731*6236dae4SAndroid Build Coastguard Worker }
732*6236dae4SAndroid Build Coastguard Worker
mime_file_seek(void * instream,curl_off_t offset,int whence)733*6236dae4SAndroid Build Coastguard Worker static int mime_file_seek(void *instream, curl_off_t offset, int whence)
734*6236dae4SAndroid Build Coastguard Worker {
735*6236dae4SAndroid Build Coastguard Worker curl_mimepart *part = (curl_mimepart *) instream;
736*6236dae4SAndroid Build Coastguard Worker
737*6236dae4SAndroid Build Coastguard Worker if(whence == SEEK_SET && !offset && !part->fp)
738*6236dae4SAndroid Build Coastguard Worker return CURL_SEEKFUNC_OK; /* Not open: implicitly already at BOF. */
739*6236dae4SAndroid Build Coastguard Worker
740*6236dae4SAndroid Build Coastguard Worker if(mime_open_file(part))
741*6236dae4SAndroid Build Coastguard Worker return CURL_SEEKFUNC_FAIL;
742*6236dae4SAndroid Build Coastguard Worker
743*6236dae4SAndroid Build Coastguard Worker return fseek(part->fp, (long) offset, whence) ?
744*6236dae4SAndroid Build Coastguard Worker CURL_SEEKFUNC_CANTSEEK : CURL_SEEKFUNC_OK;
745*6236dae4SAndroid Build Coastguard Worker }
746*6236dae4SAndroid Build Coastguard Worker
mime_file_free(void * ptr)747*6236dae4SAndroid Build Coastguard Worker static void mime_file_free(void *ptr)
748*6236dae4SAndroid Build Coastguard Worker {
749*6236dae4SAndroid Build Coastguard Worker curl_mimepart *part = (curl_mimepart *) ptr;
750*6236dae4SAndroid Build Coastguard Worker
751*6236dae4SAndroid Build Coastguard Worker if(part->fp) {
752*6236dae4SAndroid Build Coastguard Worker fclose(part->fp);
753*6236dae4SAndroid Build Coastguard Worker part->fp = NULL;
754*6236dae4SAndroid Build Coastguard Worker }
755*6236dae4SAndroid Build Coastguard Worker Curl_safefree(part->data);
756*6236dae4SAndroid Build Coastguard Worker }
757*6236dae4SAndroid Build Coastguard Worker
758*6236dae4SAndroid Build Coastguard Worker
759*6236dae4SAndroid Build Coastguard Worker /* Subparts callbacks. */
760*6236dae4SAndroid Build Coastguard Worker /* Argument is a pointer to the mime structure. */
761*6236dae4SAndroid Build Coastguard Worker
762*6236dae4SAndroid Build Coastguard Worker /* Readback a byte string segment. */
readback_bytes(struct mime_state * state,char * buffer,size_t bufsize,const char * bytes,size_t numbytes,const char * trail,size_t traillen)763*6236dae4SAndroid Build Coastguard Worker static size_t readback_bytes(struct mime_state *state,
764*6236dae4SAndroid Build Coastguard Worker char *buffer, size_t bufsize,
765*6236dae4SAndroid Build Coastguard Worker const char *bytes, size_t numbytes,
766*6236dae4SAndroid Build Coastguard Worker const char *trail, size_t traillen)
767*6236dae4SAndroid Build Coastguard Worker {
768*6236dae4SAndroid Build Coastguard Worker size_t sz;
769*6236dae4SAndroid Build Coastguard Worker size_t offset = curlx_sotouz(state->offset);
770*6236dae4SAndroid Build Coastguard Worker
771*6236dae4SAndroid Build Coastguard Worker if(numbytes > offset) {
772*6236dae4SAndroid Build Coastguard Worker sz = numbytes - offset;
773*6236dae4SAndroid Build Coastguard Worker bytes += offset;
774*6236dae4SAndroid Build Coastguard Worker }
775*6236dae4SAndroid Build Coastguard Worker else {
776*6236dae4SAndroid Build Coastguard Worker sz = offset - numbytes;
777*6236dae4SAndroid Build Coastguard Worker if(sz >= traillen)
778*6236dae4SAndroid Build Coastguard Worker return 0;
779*6236dae4SAndroid Build Coastguard Worker bytes = trail + sz;
780*6236dae4SAndroid Build Coastguard Worker sz = traillen - sz;
781*6236dae4SAndroid Build Coastguard Worker }
782*6236dae4SAndroid Build Coastguard Worker
783*6236dae4SAndroid Build Coastguard Worker if(sz > bufsize)
784*6236dae4SAndroid Build Coastguard Worker sz = bufsize;
785*6236dae4SAndroid Build Coastguard Worker
786*6236dae4SAndroid Build Coastguard Worker memcpy(buffer, bytes, sz);
787*6236dae4SAndroid Build Coastguard Worker state->offset += sz;
788*6236dae4SAndroid Build Coastguard Worker return sz;
789*6236dae4SAndroid Build Coastguard Worker }
790*6236dae4SAndroid Build Coastguard Worker
791*6236dae4SAndroid Build Coastguard Worker /* Read a non-encoded part content. */
read_part_content(curl_mimepart * part,char * buffer,size_t bufsize,bool * hasread)792*6236dae4SAndroid Build Coastguard Worker static size_t read_part_content(curl_mimepart *part,
793*6236dae4SAndroid Build Coastguard Worker char *buffer, size_t bufsize, bool *hasread)
794*6236dae4SAndroid Build Coastguard Worker {
795*6236dae4SAndroid Build Coastguard Worker size_t sz = 0;
796*6236dae4SAndroid Build Coastguard Worker
797*6236dae4SAndroid Build Coastguard Worker switch(part->lastreadstatus) {
798*6236dae4SAndroid Build Coastguard Worker case 0:
799*6236dae4SAndroid Build Coastguard Worker case CURL_READFUNC_ABORT:
800*6236dae4SAndroid Build Coastguard Worker case CURL_READFUNC_PAUSE:
801*6236dae4SAndroid Build Coastguard Worker case READ_ERROR:
802*6236dae4SAndroid Build Coastguard Worker return part->lastreadstatus;
803*6236dae4SAndroid Build Coastguard Worker default:
804*6236dae4SAndroid Build Coastguard Worker break;
805*6236dae4SAndroid Build Coastguard Worker }
806*6236dae4SAndroid Build Coastguard Worker
807*6236dae4SAndroid Build Coastguard Worker /* If we can determine we are at end of part data, spare a read. */
808*6236dae4SAndroid Build Coastguard Worker if(part->datasize != (curl_off_t) -1 &&
809*6236dae4SAndroid Build Coastguard Worker part->state.offset >= part->datasize) {
810*6236dae4SAndroid Build Coastguard Worker /* sz is already zero. */
811*6236dae4SAndroid Build Coastguard Worker }
812*6236dae4SAndroid Build Coastguard Worker else {
813*6236dae4SAndroid Build Coastguard Worker switch(part->kind) {
814*6236dae4SAndroid Build Coastguard Worker case MIMEKIND_MULTIPART:
815*6236dae4SAndroid Build Coastguard Worker /*
816*6236dae4SAndroid Build Coastguard Worker * Cannot be processed as other kinds since read function requires
817*6236dae4SAndroid Build Coastguard Worker * an additional parameter and is highly recursive.
818*6236dae4SAndroid Build Coastguard Worker */
819*6236dae4SAndroid Build Coastguard Worker sz = mime_subparts_read(buffer, 1, bufsize, part->arg, hasread);
820*6236dae4SAndroid Build Coastguard Worker break;
821*6236dae4SAndroid Build Coastguard Worker case MIMEKIND_FILE:
822*6236dae4SAndroid Build Coastguard Worker if(part->fp && feof(part->fp))
823*6236dae4SAndroid Build Coastguard Worker break; /* At EOF. */
824*6236dae4SAndroid Build Coastguard Worker FALLTHROUGH();
825*6236dae4SAndroid Build Coastguard Worker default:
826*6236dae4SAndroid Build Coastguard Worker if(part->readfunc) {
827*6236dae4SAndroid Build Coastguard Worker if(!(part->flags & MIME_FAST_READ)) {
828*6236dae4SAndroid Build Coastguard Worker if(*hasread)
829*6236dae4SAndroid Build Coastguard Worker return STOP_FILLING;
830*6236dae4SAndroid Build Coastguard Worker *hasread = TRUE;
831*6236dae4SAndroid Build Coastguard Worker }
832*6236dae4SAndroid Build Coastguard Worker sz = part->readfunc(buffer, 1, bufsize, part->arg);
833*6236dae4SAndroid Build Coastguard Worker }
834*6236dae4SAndroid Build Coastguard Worker break;
835*6236dae4SAndroid Build Coastguard Worker }
836*6236dae4SAndroid Build Coastguard Worker }
837*6236dae4SAndroid Build Coastguard Worker
838*6236dae4SAndroid Build Coastguard Worker switch(sz) {
839*6236dae4SAndroid Build Coastguard Worker case STOP_FILLING:
840*6236dae4SAndroid Build Coastguard Worker break;
841*6236dae4SAndroid Build Coastguard Worker case 0:
842*6236dae4SAndroid Build Coastguard Worker case CURL_READFUNC_ABORT:
843*6236dae4SAndroid Build Coastguard Worker case CURL_READFUNC_PAUSE:
844*6236dae4SAndroid Build Coastguard Worker case READ_ERROR:
845*6236dae4SAndroid Build Coastguard Worker part->lastreadstatus = sz;
846*6236dae4SAndroid Build Coastguard Worker break;
847*6236dae4SAndroid Build Coastguard Worker default:
848*6236dae4SAndroid Build Coastguard Worker part->state.offset += sz;
849*6236dae4SAndroid Build Coastguard Worker part->lastreadstatus = sz;
850*6236dae4SAndroid Build Coastguard Worker break;
851*6236dae4SAndroid Build Coastguard Worker }
852*6236dae4SAndroid Build Coastguard Worker
853*6236dae4SAndroid Build Coastguard Worker return sz;
854*6236dae4SAndroid Build Coastguard Worker }
855*6236dae4SAndroid Build Coastguard Worker
856*6236dae4SAndroid Build Coastguard Worker /* Read and encode part content. */
read_encoded_part_content(curl_mimepart * part,char * buffer,size_t bufsize,bool * hasread)857*6236dae4SAndroid Build Coastguard Worker static size_t read_encoded_part_content(curl_mimepart *part, char *buffer,
858*6236dae4SAndroid Build Coastguard Worker size_t bufsize, bool *hasread)
859*6236dae4SAndroid Build Coastguard Worker {
860*6236dae4SAndroid Build Coastguard Worker struct mime_encoder_state *st = &part->encstate;
861*6236dae4SAndroid Build Coastguard Worker size_t cursize = 0;
862*6236dae4SAndroid Build Coastguard Worker size_t sz;
863*6236dae4SAndroid Build Coastguard Worker bool ateof = FALSE;
864*6236dae4SAndroid Build Coastguard Worker
865*6236dae4SAndroid Build Coastguard Worker for(;;) {
866*6236dae4SAndroid Build Coastguard Worker if(st->bufbeg < st->bufend || ateof) {
867*6236dae4SAndroid Build Coastguard Worker /* Encode buffered data. */
868*6236dae4SAndroid Build Coastguard Worker sz = part->encoder->encodefunc(buffer, bufsize, ateof, part);
869*6236dae4SAndroid Build Coastguard Worker switch(sz) {
870*6236dae4SAndroid Build Coastguard Worker case 0:
871*6236dae4SAndroid Build Coastguard Worker if(ateof)
872*6236dae4SAndroid Build Coastguard Worker return cursize;
873*6236dae4SAndroid Build Coastguard Worker break;
874*6236dae4SAndroid Build Coastguard Worker case READ_ERROR:
875*6236dae4SAndroid Build Coastguard Worker case STOP_FILLING:
876*6236dae4SAndroid Build Coastguard Worker return cursize ? cursize : sz;
877*6236dae4SAndroid Build Coastguard Worker default:
878*6236dae4SAndroid Build Coastguard Worker cursize += sz;
879*6236dae4SAndroid Build Coastguard Worker buffer += sz;
880*6236dae4SAndroid Build Coastguard Worker bufsize -= sz;
881*6236dae4SAndroid Build Coastguard Worker continue;
882*6236dae4SAndroid Build Coastguard Worker }
883*6236dae4SAndroid Build Coastguard Worker }
884*6236dae4SAndroid Build Coastguard Worker
885*6236dae4SAndroid Build Coastguard Worker /* We need more data in input buffer. */
886*6236dae4SAndroid Build Coastguard Worker if(st->bufbeg) {
887*6236dae4SAndroid Build Coastguard Worker size_t len = st->bufend - st->bufbeg;
888*6236dae4SAndroid Build Coastguard Worker
889*6236dae4SAndroid Build Coastguard Worker if(len)
890*6236dae4SAndroid Build Coastguard Worker memmove(st->buf, st->buf + st->bufbeg, len);
891*6236dae4SAndroid Build Coastguard Worker st->bufbeg = 0;
892*6236dae4SAndroid Build Coastguard Worker st->bufend = len;
893*6236dae4SAndroid Build Coastguard Worker }
894*6236dae4SAndroid Build Coastguard Worker if(st->bufend >= sizeof(st->buf))
895*6236dae4SAndroid Build Coastguard Worker return cursize ? cursize : READ_ERROR; /* Buffer full. */
896*6236dae4SAndroid Build Coastguard Worker sz = read_part_content(part, st->buf + st->bufend,
897*6236dae4SAndroid Build Coastguard Worker sizeof(st->buf) - st->bufend, hasread);
898*6236dae4SAndroid Build Coastguard Worker switch(sz) {
899*6236dae4SAndroid Build Coastguard Worker case 0:
900*6236dae4SAndroid Build Coastguard Worker ateof = TRUE;
901*6236dae4SAndroid Build Coastguard Worker break;
902*6236dae4SAndroid Build Coastguard Worker case CURL_READFUNC_ABORT:
903*6236dae4SAndroid Build Coastguard Worker case CURL_READFUNC_PAUSE:
904*6236dae4SAndroid Build Coastguard Worker case READ_ERROR:
905*6236dae4SAndroid Build Coastguard Worker case STOP_FILLING:
906*6236dae4SAndroid Build Coastguard Worker return cursize ? cursize : sz;
907*6236dae4SAndroid Build Coastguard Worker default:
908*6236dae4SAndroid Build Coastguard Worker st->bufend += sz;
909*6236dae4SAndroid Build Coastguard Worker break;
910*6236dae4SAndroid Build Coastguard Worker }
911*6236dae4SAndroid Build Coastguard Worker }
912*6236dae4SAndroid Build Coastguard Worker
913*6236dae4SAndroid Build Coastguard Worker /* NOTREACHED */
914*6236dae4SAndroid Build Coastguard Worker }
915*6236dae4SAndroid Build Coastguard Worker
916*6236dae4SAndroid Build Coastguard Worker /* Readback a mime part. */
readback_part(curl_mimepart * part,char * buffer,size_t bufsize,bool * hasread)917*6236dae4SAndroid Build Coastguard Worker static size_t readback_part(curl_mimepart *part,
918*6236dae4SAndroid Build Coastguard Worker char *buffer, size_t bufsize, bool *hasread)
919*6236dae4SAndroid Build Coastguard Worker {
920*6236dae4SAndroid Build Coastguard Worker size_t cursize = 0;
921*6236dae4SAndroid Build Coastguard Worker
922*6236dae4SAndroid Build Coastguard Worker /* Readback from part. */
923*6236dae4SAndroid Build Coastguard Worker
924*6236dae4SAndroid Build Coastguard Worker while(bufsize) {
925*6236dae4SAndroid Build Coastguard Worker size_t sz = 0;
926*6236dae4SAndroid Build Coastguard Worker struct curl_slist *hdr = (struct curl_slist *) part->state.ptr;
927*6236dae4SAndroid Build Coastguard Worker switch(part->state.state) {
928*6236dae4SAndroid Build Coastguard Worker case MIMESTATE_BEGIN:
929*6236dae4SAndroid Build Coastguard Worker mimesetstate(&part->state,
930*6236dae4SAndroid Build Coastguard Worker (part->flags & MIME_BODY_ONLY) ?
931*6236dae4SAndroid Build Coastguard Worker MIMESTATE_BODY : MIMESTATE_CURLHEADERS,
932*6236dae4SAndroid Build Coastguard Worker part->curlheaders);
933*6236dae4SAndroid Build Coastguard Worker break;
934*6236dae4SAndroid Build Coastguard Worker case MIMESTATE_USERHEADERS:
935*6236dae4SAndroid Build Coastguard Worker if(!hdr) {
936*6236dae4SAndroid Build Coastguard Worker mimesetstate(&part->state, MIMESTATE_EOH, NULL);
937*6236dae4SAndroid Build Coastguard Worker break;
938*6236dae4SAndroid Build Coastguard Worker }
939*6236dae4SAndroid Build Coastguard Worker if(match_header(hdr, "Content-Type", 12)) {
940*6236dae4SAndroid Build Coastguard Worker mimesetstate(&part->state, MIMESTATE_USERHEADERS, hdr->next);
941*6236dae4SAndroid Build Coastguard Worker break;
942*6236dae4SAndroid Build Coastguard Worker }
943*6236dae4SAndroid Build Coastguard Worker FALLTHROUGH();
944*6236dae4SAndroid Build Coastguard Worker case MIMESTATE_CURLHEADERS:
945*6236dae4SAndroid Build Coastguard Worker if(!hdr)
946*6236dae4SAndroid Build Coastguard Worker mimesetstate(&part->state, MIMESTATE_USERHEADERS, part->userheaders);
947*6236dae4SAndroid Build Coastguard Worker else {
948*6236dae4SAndroid Build Coastguard Worker sz = readback_bytes(&part->state, buffer, bufsize,
949*6236dae4SAndroid Build Coastguard Worker hdr->data, strlen(hdr->data), STRCONST("\r\n"));
950*6236dae4SAndroid Build Coastguard Worker if(!sz)
951*6236dae4SAndroid Build Coastguard Worker mimesetstate(&part->state, part->state.state, hdr->next);
952*6236dae4SAndroid Build Coastguard Worker }
953*6236dae4SAndroid Build Coastguard Worker break;
954*6236dae4SAndroid Build Coastguard Worker case MIMESTATE_EOH:
955*6236dae4SAndroid Build Coastguard Worker sz = readback_bytes(&part->state, buffer, bufsize, STRCONST("\r\n"),
956*6236dae4SAndroid Build Coastguard Worker STRCONST(""));
957*6236dae4SAndroid Build Coastguard Worker if(!sz)
958*6236dae4SAndroid Build Coastguard Worker mimesetstate(&part->state, MIMESTATE_BODY, NULL);
959*6236dae4SAndroid Build Coastguard Worker break;
960*6236dae4SAndroid Build Coastguard Worker case MIMESTATE_BODY:
961*6236dae4SAndroid Build Coastguard Worker cleanup_encoder_state(&part->encstate);
962*6236dae4SAndroid Build Coastguard Worker mimesetstate(&part->state, MIMESTATE_CONTENT, NULL);
963*6236dae4SAndroid Build Coastguard Worker break;
964*6236dae4SAndroid Build Coastguard Worker case MIMESTATE_CONTENT:
965*6236dae4SAndroid Build Coastguard Worker if(part->encoder)
966*6236dae4SAndroid Build Coastguard Worker sz = read_encoded_part_content(part, buffer, bufsize, hasread);
967*6236dae4SAndroid Build Coastguard Worker else
968*6236dae4SAndroid Build Coastguard Worker sz = read_part_content(part, buffer, bufsize, hasread);
969*6236dae4SAndroid Build Coastguard Worker switch(sz) {
970*6236dae4SAndroid Build Coastguard Worker case 0:
971*6236dae4SAndroid Build Coastguard Worker mimesetstate(&part->state, MIMESTATE_END, NULL);
972*6236dae4SAndroid Build Coastguard Worker /* Try sparing open file descriptors. */
973*6236dae4SAndroid Build Coastguard Worker if(part->kind == MIMEKIND_FILE && part->fp) {
974*6236dae4SAndroid Build Coastguard Worker fclose(part->fp);
975*6236dae4SAndroid Build Coastguard Worker part->fp = NULL;
976*6236dae4SAndroid Build Coastguard Worker }
977*6236dae4SAndroid Build Coastguard Worker FALLTHROUGH();
978*6236dae4SAndroid Build Coastguard Worker case CURL_READFUNC_ABORT:
979*6236dae4SAndroid Build Coastguard Worker case CURL_READFUNC_PAUSE:
980*6236dae4SAndroid Build Coastguard Worker case READ_ERROR:
981*6236dae4SAndroid Build Coastguard Worker case STOP_FILLING:
982*6236dae4SAndroid Build Coastguard Worker return cursize ? cursize : sz;
983*6236dae4SAndroid Build Coastguard Worker }
984*6236dae4SAndroid Build Coastguard Worker break;
985*6236dae4SAndroid Build Coastguard Worker case MIMESTATE_END:
986*6236dae4SAndroid Build Coastguard Worker return cursize;
987*6236dae4SAndroid Build Coastguard Worker default:
988*6236dae4SAndroid Build Coastguard Worker break; /* Other values not in part state. */
989*6236dae4SAndroid Build Coastguard Worker }
990*6236dae4SAndroid Build Coastguard Worker
991*6236dae4SAndroid Build Coastguard Worker /* Bump buffer and counters according to read size. */
992*6236dae4SAndroid Build Coastguard Worker cursize += sz;
993*6236dae4SAndroid Build Coastguard Worker buffer += sz;
994*6236dae4SAndroid Build Coastguard Worker bufsize -= sz;
995*6236dae4SAndroid Build Coastguard Worker }
996*6236dae4SAndroid Build Coastguard Worker
997*6236dae4SAndroid Build Coastguard Worker return cursize;
998*6236dae4SAndroid Build Coastguard Worker }
999*6236dae4SAndroid Build Coastguard Worker
1000*6236dae4SAndroid Build Coastguard Worker /* Readback from mime. Warning: not a read callback function. */
mime_subparts_read(char * buffer,size_t size,size_t nitems,void * instream,bool * hasread)1001*6236dae4SAndroid Build Coastguard Worker static size_t mime_subparts_read(char *buffer, size_t size, size_t nitems,
1002*6236dae4SAndroid Build Coastguard Worker void *instream, bool *hasread)
1003*6236dae4SAndroid Build Coastguard Worker {
1004*6236dae4SAndroid Build Coastguard Worker curl_mime *mime = (curl_mime *) instream;
1005*6236dae4SAndroid Build Coastguard Worker size_t cursize = 0;
1006*6236dae4SAndroid Build Coastguard Worker (void) size; /* Always 1. */
1007*6236dae4SAndroid Build Coastguard Worker
1008*6236dae4SAndroid Build Coastguard Worker while(nitems) {
1009*6236dae4SAndroid Build Coastguard Worker size_t sz = 0;
1010*6236dae4SAndroid Build Coastguard Worker curl_mimepart *part = mime->state.ptr;
1011*6236dae4SAndroid Build Coastguard Worker switch(mime->state.state) {
1012*6236dae4SAndroid Build Coastguard Worker case MIMESTATE_BEGIN:
1013*6236dae4SAndroid Build Coastguard Worker case MIMESTATE_BODY:
1014*6236dae4SAndroid Build Coastguard Worker mimesetstate(&mime->state, MIMESTATE_BOUNDARY1, mime->firstpart);
1015*6236dae4SAndroid Build Coastguard Worker /* The first boundary always follows the header termination empty line,
1016*6236dae4SAndroid Build Coastguard Worker so is always preceded by a CRLF. We can then spare 2 characters
1017*6236dae4SAndroid Build Coastguard Worker by skipping the leading CRLF in boundary. */
1018*6236dae4SAndroid Build Coastguard Worker mime->state.offset += 2;
1019*6236dae4SAndroid Build Coastguard Worker break;
1020*6236dae4SAndroid Build Coastguard Worker case MIMESTATE_BOUNDARY1:
1021*6236dae4SAndroid Build Coastguard Worker sz = readback_bytes(&mime->state, buffer, nitems, STRCONST("\r\n--"),
1022*6236dae4SAndroid Build Coastguard Worker STRCONST(""));
1023*6236dae4SAndroid Build Coastguard Worker if(!sz)
1024*6236dae4SAndroid Build Coastguard Worker mimesetstate(&mime->state, MIMESTATE_BOUNDARY2, part);
1025*6236dae4SAndroid Build Coastguard Worker break;
1026*6236dae4SAndroid Build Coastguard Worker case MIMESTATE_BOUNDARY2:
1027*6236dae4SAndroid Build Coastguard Worker if(part)
1028*6236dae4SAndroid Build Coastguard Worker sz = readback_bytes(&mime->state, buffer, nitems, mime->boundary,
1029*6236dae4SAndroid Build Coastguard Worker MIME_BOUNDARY_LEN, STRCONST("\r\n"));
1030*6236dae4SAndroid Build Coastguard Worker else
1031*6236dae4SAndroid Build Coastguard Worker sz = readback_bytes(&mime->state, buffer, nitems, mime->boundary,
1032*6236dae4SAndroid Build Coastguard Worker MIME_BOUNDARY_LEN, STRCONST("--\r\n"));
1033*6236dae4SAndroid Build Coastguard Worker if(!sz) {
1034*6236dae4SAndroid Build Coastguard Worker mimesetstate(&mime->state, MIMESTATE_CONTENT, part);
1035*6236dae4SAndroid Build Coastguard Worker }
1036*6236dae4SAndroid Build Coastguard Worker break;
1037*6236dae4SAndroid Build Coastguard Worker case MIMESTATE_CONTENT:
1038*6236dae4SAndroid Build Coastguard Worker if(!part) {
1039*6236dae4SAndroid Build Coastguard Worker mimesetstate(&mime->state, MIMESTATE_END, NULL);
1040*6236dae4SAndroid Build Coastguard Worker break;
1041*6236dae4SAndroid Build Coastguard Worker }
1042*6236dae4SAndroid Build Coastguard Worker sz = readback_part(part, buffer, nitems, hasread);
1043*6236dae4SAndroid Build Coastguard Worker switch(sz) {
1044*6236dae4SAndroid Build Coastguard Worker case CURL_READFUNC_ABORT:
1045*6236dae4SAndroid Build Coastguard Worker case CURL_READFUNC_PAUSE:
1046*6236dae4SAndroid Build Coastguard Worker case READ_ERROR:
1047*6236dae4SAndroid Build Coastguard Worker case STOP_FILLING:
1048*6236dae4SAndroid Build Coastguard Worker return cursize ? cursize : sz;
1049*6236dae4SAndroid Build Coastguard Worker case 0:
1050*6236dae4SAndroid Build Coastguard Worker mimesetstate(&mime->state, MIMESTATE_BOUNDARY1, part->nextpart);
1051*6236dae4SAndroid Build Coastguard Worker break;
1052*6236dae4SAndroid Build Coastguard Worker }
1053*6236dae4SAndroid Build Coastguard Worker break;
1054*6236dae4SAndroid Build Coastguard Worker case MIMESTATE_END:
1055*6236dae4SAndroid Build Coastguard Worker return cursize;
1056*6236dae4SAndroid Build Coastguard Worker default:
1057*6236dae4SAndroid Build Coastguard Worker break; /* other values not used in mime state. */
1058*6236dae4SAndroid Build Coastguard Worker }
1059*6236dae4SAndroid Build Coastguard Worker
1060*6236dae4SAndroid Build Coastguard Worker /* Bump buffer and counters according to read size. */
1061*6236dae4SAndroid Build Coastguard Worker cursize += sz;
1062*6236dae4SAndroid Build Coastguard Worker buffer += sz;
1063*6236dae4SAndroid Build Coastguard Worker nitems -= sz;
1064*6236dae4SAndroid Build Coastguard Worker }
1065*6236dae4SAndroid Build Coastguard Worker
1066*6236dae4SAndroid Build Coastguard Worker return cursize;
1067*6236dae4SAndroid Build Coastguard Worker }
1068*6236dae4SAndroid Build Coastguard Worker
mime_part_rewind(curl_mimepart * part)1069*6236dae4SAndroid Build Coastguard Worker static int mime_part_rewind(curl_mimepart *part)
1070*6236dae4SAndroid Build Coastguard Worker {
1071*6236dae4SAndroid Build Coastguard Worker int res = CURL_SEEKFUNC_OK;
1072*6236dae4SAndroid Build Coastguard Worker enum mimestate targetstate = MIMESTATE_BEGIN;
1073*6236dae4SAndroid Build Coastguard Worker
1074*6236dae4SAndroid Build Coastguard Worker if(part->flags & MIME_BODY_ONLY)
1075*6236dae4SAndroid Build Coastguard Worker targetstate = MIMESTATE_BODY;
1076*6236dae4SAndroid Build Coastguard Worker cleanup_encoder_state(&part->encstate);
1077*6236dae4SAndroid Build Coastguard Worker if(part->state.state > targetstate) {
1078*6236dae4SAndroid Build Coastguard Worker res = CURL_SEEKFUNC_CANTSEEK;
1079*6236dae4SAndroid Build Coastguard Worker if(part->seekfunc) {
1080*6236dae4SAndroid Build Coastguard Worker res = part->seekfunc(part->arg, (curl_off_t) 0, SEEK_SET);
1081*6236dae4SAndroid Build Coastguard Worker switch(res) {
1082*6236dae4SAndroid Build Coastguard Worker case CURL_SEEKFUNC_OK:
1083*6236dae4SAndroid Build Coastguard Worker case CURL_SEEKFUNC_FAIL:
1084*6236dae4SAndroid Build Coastguard Worker case CURL_SEEKFUNC_CANTSEEK:
1085*6236dae4SAndroid Build Coastguard Worker break;
1086*6236dae4SAndroid Build Coastguard Worker case -1: /* For fseek() error. */
1087*6236dae4SAndroid Build Coastguard Worker res = CURL_SEEKFUNC_CANTSEEK;
1088*6236dae4SAndroid Build Coastguard Worker break;
1089*6236dae4SAndroid Build Coastguard Worker default:
1090*6236dae4SAndroid Build Coastguard Worker res = CURL_SEEKFUNC_FAIL;
1091*6236dae4SAndroid Build Coastguard Worker break;
1092*6236dae4SAndroid Build Coastguard Worker }
1093*6236dae4SAndroid Build Coastguard Worker }
1094*6236dae4SAndroid Build Coastguard Worker }
1095*6236dae4SAndroid Build Coastguard Worker
1096*6236dae4SAndroid Build Coastguard Worker if(res == CURL_SEEKFUNC_OK)
1097*6236dae4SAndroid Build Coastguard Worker mimesetstate(&part->state, targetstate, NULL);
1098*6236dae4SAndroid Build Coastguard Worker
1099*6236dae4SAndroid Build Coastguard Worker part->lastreadstatus = 1; /* Successful read status. */
1100*6236dae4SAndroid Build Coastguard Worker return res;
1101*6236dae4SAndroid Build Coastguard Worker }
1102*6236dae4SAndroid Build Coastguard Worker
mime_subparts_seek(void * instream,curl_off_t offset,int whence)1103*6236dae4SAndroid Build Coastguard Worker static int mime_subparts_seek(void *instream, curl_off_t offset, int whence)
1104*6236dae4SAndroid Build Coastguard Worker {
1105*6236dae4SAndroid Build Coastguard Worker curl_mime *mime = (curl_mime *) instream;
1106*6236dae4SAndroid Build Coastguard Worker curl_mimepart *part;
1107*6236dae4SAndroid Build Coastguard Worker int result = CURL_SEEKFUNC_OK;
1108*6236dae4SAndroid Build Coastguard Worker
1109*6236dae4SAndroid Build Coastguard Worker if(whence != SEEK_SET || offset)
1110*6236dae4SAndroid Build Coastguard Worker return CURL_SEEKFUNC_CANTSEEK; /* Only support full rewind. */
1111*6236dae4SAndroid Build Coastguard Worker
1112*6236dae4SAndroid Build Coastguard Worker if(mime->state.state == MIMESTATE_BEGIN)
1113*6236dae4SAndroid Build Coastguard Worker return CURL_SEEKFUNC_OK; /* Already rewound. */
1114*6236dae4SAndroid Build Coastguard Worker
1115*6236dae4SAndroid Build Coastguard Worker for(part = mime->firstpart; part; part = part->nextpart) {
1116*6236dae4SAndroid Build Coastguard Worker int res = mime_part_rewind(part);
1117*6236dae4SAndroid Build Coastguard Worker if(res != CURL_SEEKFUNC_OK)
1118*6236dae4SAndroid Build Coastguard Worker result = res;
1119*6236dae4SAndroid Build Coastguard Worker }
1120*6236dae4SAndroid Build Coastguard Worker
1121*6236dae4SAndroid Build Coastguard Worker if(result == CURL_SEEKFUNC_OK)
1122*6236dae4SAndroid Build Coastguard Worker mimesetstate(&mime->state, MIMESTATE_BEGIN, NULL);
1123*6236dae4SAndroid Build Coastguard Worker
1124*6236dae4SAndroid Build Coastguard Worker return result;
1125*6236dae4SAndroid Build Coastguard Worker }
1126*6236dae4SAndroid Build Coastguard Worker
1127*6236dae4SAndroid Build Coastguard Worker /* Release part content. */
cleanup_part_content(curl_mimepart * part)1128*6236dae4SAndroid Build Coastguard Worker static void cleanup_part_content(curl_mimepart *part)
1129*6236dae4SAndroid Build Coastguard Worker {
1130*6236dae4SAndroid Build Coastguard Worker if(part->freefunc)
1131*6236dae4SAndroid Build Coastguard Worker part->freefunc(part->arg);
1132*6236dae4SAndroid Build Coastguard Worker
1133*6236dae4SAndroid Build Coastguard Worker part->readfunc = NULL;
1134*6236dae4SAndroid Build Coastguard Worker part->seekfunc = NULL;
1135*6236dae4SAndroid Build Coastguard Worker part->freefunc = NULL;
1136*6236dae4SAndroid Build Coastguard Worker part->arg = (void *) part; /* Defaults to part itself. */
1137*6236dae4SAndroid Build Coastguard Worker part->data = NULL;
1138*6236dae4SAndroid Build Coastguard Worker part->fp = NULL;
1139*6236dae4SAndroid Build Coastguard Worker part->datasize = (curl_off_t) 0; /* No size yet. */
1140*6236dae4SAndroid Build Coastguard Worker cleanup_encoder_state(&part->encstate);
1141*6236dae4SAndroid Build Coastguard Worker part->kind = MIMEKIND_NONE;
1142*6236dae4SAndroid Build Coastguard Worker part->flags &= ~(unsigned int)MIME_FAST_READ;
1143*6236dae4SAndroid Build Coastguard Worker part->lastreadstatus = 1; /* Successful read status. */
1144*6236dae4SAndroid Build Coastguard Worker part->state.state = MIMESTATE_BEGIN;
1145*6236dae4SAndroid Build Coastguard Worker }
1146*6236dae4SAndroid Build Coastguard Worker
mime_subparts_free(void * ptr)1147*6236dae4SAndroid Build Coastguard Worker static void mime_subparts_free(void *ptr)
1148*6236dae4SAndroid Build Coastguard Worker {
1149*6236dae4SAndroid Build Coastguard Worker curl_mime *mime = (curl_mime *) ptr;
1150*6236dae4SAndroid Build Coastguard Worker
1151*6236dae4SAndroid Build Coastguard Worker if(mime && mime->parent) {
1152*6236dae4SAndroid Build Coastguard Worker mime->parent->freefunc = NULL; /* Be sure we will not be called again. */
1153*6236dae4SAndroid Build Coastguard Worker cleanup_part_content(mime->parent); /* Avoid dangling pointer in part. */
1154*6236dae4SAndroid Build Coastguard Worker }
1155*6236dae4SAndroid Build Coastguard Worker curl_mime_free(mime);
1156*6236dae4SAndroid Build Coastguard Worker }
1157*6236dae4SAndroid Build Coastguard Worker
1158*6236dae4SAndroid Build Coastguard Worker /* Do not free subparts: unbind them. This is used for the top level only. */
mime_subparts_unbind(void * ptr)1159*6236dae4SAndroid Build Coastguard Worker static void mime_subparts_unbind(void *ptr)
1160*6236dae4SAndroid Build Coastguard Worker {
1161*6236dae4SAndroid Build Coastguard Worker curl_mime *mime = (curl_mime *) ptr;
1162*6236dae4SAndroid Build Coastguard Worker
1163*6236dae4SAndroid Build Coastguard Worker if(mime && mime->parent) {
1164*6236dae4SAndroid Build Coastguard Worker mime->parent->freefunc = NULL; /* Be sure we will not be called again. */
1165*6236dae4SAndroid Build Coastguard Worker cleanup_part_content(mime->parent); /* Avoid dangling pointer in part. */
1166*6236dae4SAndroid Build Coastguard Worker mime->parent = NULL;
1167*6236dae4SAndroid Build Coastguard Worker }
1168*6236dae4SAndroid Build Coastguard Worker }
1169*6236dae4SAndroid Build Coastguard Worker
1170*6236dae4SAndroid Build Coastguard Worker
Curl_mime_cleanpart(curl_mimepart * part)1171*6236dae4SAndroid Build Coastguard Worker void Curl_mime_cleanpart(curl_mimepart *part)
1172*6236dae4SAndroid Build Coastguard Worker {
1173*6236dae4SAndroid Build Coastguard Worker if(part) {
1174*6236dae4SAndroid Build Coastguard Worker cleanup_part_content(part);
1175*6236dae4SAndroid Build Coastguard Worker curl_slist_free_all(part->curlheaders);
1176*6236dae4SAndroid Build Coastguard Worker if(part->flags & MIME_USERHEADERS_OWNER)
1177*6236dae4SAndroid Build Coastguard Worker curl_slist_free_all(part->userheaders);
1178*6236dae4SAndroid Build Coastguard Worker Curl_safefree(part->mimetype);
1179*6236dae4SAndroid Build Coastguard Worker Curl_safefree(part->name);
1180*6236dae4SAndroid Build Coastguard Worker Curl_safefree(part->filename);
1181*6236dae4SAndroid Build Coastguard Worker Curl_mime_initpart(part);
1182*6236dae4SAndroid Build Coastguard Worker }
1183*6236dae4SAndroid Build Coastguard Worker }
1184*6236dae4SAndroid Build Coastguard Worker
1185*6236dae4SAndroid Build Coastguard Worker /* Recursively delete a mime handle and its parts. */
curl_mime_free(curl_mime * mime)1186*6236dae4SAndroid Build Coastguard Worker void curl_mime_free(curl_mime *mime)
1187*6236dae4SAndroid Build Coastguard Worker {
1188*6236dae4SAndroid Build Coastguard Worker curl_mimepart *part;
1189*6236dae4SAndroid Build Coastguard Worker
1190*6236dae4SAndroid Build Coastguard Worker if(mime) {
1191*6236dae4SAndroid Build Coastguard Worker mime_subparts_unbind(mime); /* Be sure it is not referenced anymore. */
1192*6236dae4SAndroid Build Coastguard Worker while(mime->firstpart) {
1193*6236dae4SAndroid Build Coastguard Worker part = mime->firstpart;
1194*6236dae4SAndroid Build Coastguard Worker mime->firstpart = part->nextpart;
1195*6236dae4SAndroid Build Coastguard Worker Curl_mime_cleanpart(part);
1196*6236dae4SAndroid Build Coastguard Worker free(part);
1197*6236dae4SAndroid Build Coastguard Worker }
1198*6236dae4SAndroid Build Coastguard Worker free(mime);
1199*6236dae4SAndroid Build Coastguard Worker }
1200*6236dae4SAndroid Build Coastguard Worker }
1201*6236dae4SAndroid Build Coastguard Worker
Curl_mime_duppart(struct Curl_easy * data,curl_mimepart * dst,const curl_mimepart * src)1202*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_mime_duppart(struct Curl_easy *data,
1203*6236dae4SAndroid Build Coastguard Worker curl_mimepart *dst, const curl_mimepart *src)
1204*6236dae4SAndroid Build Coastguard Worker {
1205*6236dae4SAndroid Build Coastguard Worker curl_mime *mime;
1206*6236dae4SAndroid Build Coastguard Worker curl_mimepart *d;
1207*6236dae4SAndroid Build Coastguard Worker const curl_mimepart *s;
1208*6236dae4SAndroid Build Coastguard Worker CURLcode res = CURLE_OK;
1209*6236dae4SAndroid Build Coastguard Worker
1210*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(dst);
1211*6236dae4SAndroid Build Coastguard Worker
1212*6236dae4SAndroid Build Coastguard Worker /* Duplicate content. */
1213*6236dae4SAndroid Build Coastguard Worker switch(src->kind) {
1214*6236dae4SAndroid Build Coastguard Worker case MIMEKIND_NONE:
1215*6236dae4SAndroid Build Coastguard Worker break;
1216*6236dae4SAndroid Build Coastguard Worker case MIMEKIND_DATA:
1217*6236dae4SAndroid Build Coastguard Worker res = curl_mime_data(dst, src->data, (size_t) src->datasize);
1218*6236dae4SAndroid Build Coastguard Worker break;
1219*6236dae4SAndroid Build Coastguard Worker case MIMEKIND_FILE:
1220*6236dae4SAndroid Build Coastguard Worker res = curl_mime_filedata(dst, src->data);
1221*6236dae4SAndroid Build Coastguard Worker /* Do not abort duplication if file is not readable. */
1222*6236dae4SAndroid Build Coastguard Worker if(res == CURLE_READ_ERROR)
1223*6236dae4SAndroid Build Coastguard Worker res = CURLE_OK;
1224*6236dae4SAndroid Build Coastguard Worker break;
1225*6236dae4SAndroid Build Coastguard Worker case MIMEKIND_CALLBACK:
1226*6236dae4SAndroid Build Coastguard Worker res = curl_mime_data_cb(dst, src->datasize, src->readfunc,
1227*6236dae4SAndroid Build Coastguard Worker src->seekfunc, src->freefunc, src->arg);
1228*6236dae4SAndroid Build Coastguard Worker break;
1229*6236dae4SAndroid Build Coastguard Worker case MIMEKIND_MULTIPART:
1230*6236dae4SAndroid Build Coastguard Worker /* No one knows about the cloned subparts, thus always attach ownership
1231*6236dae4SAndroid Build Coastguard Worker to the part. */
1232*6236dae4SAndroid Build Coastguard Worker mime = curl_mime_init(data);
1233*6236dae4SAndroid Build Coastguard Worker res = mime ? curl_mime_subparts(dst, mime) : CURLE_OUT_OF_MEMORY;
1234*6236dae4SAndroid Build Coastguard Worker
1235*6236dae4SAndroid Build Coastguard Worker /* Duplicate subparts. */
1236*6236dae4SAndroid Build Coastguard Worker for(s = ((curl_mime *) src->arg)->firstpart; !res && s; s = s->nextpart) {
1237*6236dae4SAndroid Build Coastguard Worker d = curl_mime_addpart(mime);
1238*6236dae4SAndroid Build Coastguard Worker res = d ? Curl_mime_duppart(data, d, s) : CURLE_OUT_OF_MEMORY;
1239*6236dae4SAndroid Build Coastguard Worker }
1240*6236dae4SAndroid Build Coastguard Worker break;
1241*6236dae4SAndroid Build Coastguard Worker default: /* Invalid kind: should not occur. */
1242*6236dae4SAndroid Build Coastguard Worker DEBUGF(infof(data, "invalid MIMEKIND* attempt"));
1243*6236dae4SAndroid Build Coastguard Worker res = CURLE_BAD_FUNCTION_ARGUMENT; /* Internal error? */
1244*6236dae4SAndroid Build Coastguard Worker break;
1245*6236dae4SAndroid Build Coastguard Worker }
1246*6236dae4SAndroid Build Coastguard Worker
1247*6236dae4SAndroid Build Coastguard Worker /* Duplicate headers. */
1248*6236dae4SAndroid Build Coastguard Worker if(!res && src->userheaders) {
1249*6236dae4SAndroid Build Coastguard Worker struct curl_slist *hdrs = Curl_slist_duplicate(src->userheaders);
1250*6236dae4SAndroid Build Coastguard Worker
1251*6236dae4SAndroid Build Coastguard Worker if(!hdrs)
1252*6236dae4SAndroid Build Coastguard Worker res = CURLE_OUT_OF_MEMORY;
1253*6236dae4SAndroid Build Coastguard Worker else {
1254*6236dae4SAndroid Build Coastguard Worker /* No one but this procedure knows about the new header list,
1255*6236dae4SAndroid Build Coastguard Worker so always take ownership. */
1256*6236dae4SAndroid Build Coastguard Worker res = curl_mime_headers(dst, hdrs, TRUE);
1257*6236dae4SAndroid Build Coastguard Worker if(res)
1258*6236dae4SAndroid Build Coastguard Worker curl_slist_free_all(hdrs);
1259*6236dae4SAndroid Build Coastguard Worker }
1260*6236dae4SAndroid Build Coastguard Worker }
1261*6236dae4SAndroid Build Coastguard Worker
1262*6236dae4SAndroid Build Coastguard Worker if(!res) {
1263*6236dae4SAndroid Build Coastguard Worker /* Duplicate other fields. */
1264*6236dae4SAndroid Build Coastguard Worker dst->encoder = src->encoder;
1265*6236dae4SAndroid Build Coastguard Worker res = curl_mime_type(dst, src->mimetype);
1266*6236dae4SAndroid Build Coastguard Worker }
1267*6236dae4SAndroid Build Coastguard Worker if(!res)
1268*6236dae4SAndroid Build Coastguard Worker res = curl_mime_name(dst, src->name);
1269*6236dae4SAndroid Build Coastguard Worker if(!res)
1270*6236dae4SAndroid Build Coastguard Worker res = curl_mime_filename(dst, src->filename);
1271*6236dae4SAndroid Build Coastguard Worker
1272*6236dae4SAndroid Build Coastguard Worker /* If an error occurred, rollback. */
1273*6236dae4SAndroid Build Coastguard Worker if(res)
1274*6236dae4SAndroid Build Coastguard Worker Curl_mime_cleanpart(dst);
1275*6236dae4SAndroid Build Coastguard Worker
1276*6236dae4SAndroid Build Coastguard Worker return res;
1277*6236dae4SAndroid Build Coastguard Worker }
1278*6236dae4SAndroid Build Coastguard Worker
1279*6236dae4SAndroid Build Coastguard Worker /*
1280*6236dae4SAndroid Build Coastguard Worker * Mime build functions.
1281*6236dae4SAndroid Build Coastguard Worker */
1282*6236dae4SAndroid Build Coastguard Worker
1283*6236dae4SAndroid Build Coastguard Worker /* Create a mime handle. */
curl_mime_init(void * easy)1284*6236dae4SAndroid Build Coastguard Worker curl_mime *curl_mime_init(void *easy)
1285*6236dae4SAndroid Build Coastguard Worker {
1286*6236dae4SAndroid Build Coastguard Worker curl_mime *mime;
1287*6236dae4SAndroid Build Coastguard Worker
1288*6236dae4SAndroid Build Coastguard Worker mime = (curl_mime *) malloc(sizeof(*mime));
1289*6236dae4SAndroid Build Coastguard Worker
1290*6236dae4SAndroid Build Coastguard Worker if(mime) {
1291*6236dae4SAndroid Build Coastguard Worker mime->parent = NULL;
1292*6236dae4SAndroid Build Coastguard Worker mime->firstpart = NULL;
1293*6236dae4SAndroid Build Coastguard Worker mime->lastpart = NULL;
1294*6236dae4SAndroid Build Coastguard Worker
1295*6236dae4SAndroid Build Coastguard Worker memset(mime->boundary, '-', MIME_BOUNDARY_DASHES);
1296*6236dae4SAndroid Build Coastguard Worker if(Curl_rand_alnum(easy,
1297*6236dae4SAndroid Build Coastguard Worker (unsigned char *) &mime->boundary[MIME_BOUNDARY_DASHES],
1298*6236dae4SAndroid Build Coastguard Worker MIME_RAND_BOUNDARY_CHARS + 1)) {
1299*6236dae4SAndroid Build Coastguard Worker /* failed to get random separator, bail out */
1300*6236dae4SAndroid Build Coastguard Worker free(mime);
1301*6236dae4SAndroid Build Coastguard Worker return NULL;
1302*6236dae4SAndroid Build Coastguard Worker }
1303*6236dae4SAndroid Build Coastguard Worker mimesetstate(&mime->state, MIMESTATE_BEGIN, NULL);
1304*6236dae4SAndroid Build Coastguard Worker }
1305*6236dae4SAndroid Build Coastguard Worker
1306*6236dae4SAndroid Build Coastguard Worker return mime;
1307*6236dae4SAndroid Build Coastguard Worker }
1308*6236dae4SAndroid Build Coastguard Worker
1309*6236dae4SAndroid Build Coastguard Worker /* Initialize a mime part. */
Curl_mime_initpart(curl_mimepart * part)1310*6236dae4SAndroid Build Coastguard Worker void Curl_mime_initpart(curl_mimepart *part)
1311*6236dae4SAndroid Build Coastguard Worker {
1312*6236dae4SAndroid Build Coastguard Worker memset((char *) part, 0, sizeof(*part));
1313*6236dae4SAndroid Build Coastguard Worker part->lastreadstatus = 1; /* Successful read status. */
1314*6236dae4SAndroid Build Coastguard Worker mimesetstate(&part->state, MIMESTATE_BEGIN, NULL);
1315*6236dae4SAndroid Build Coastguard Worker }
1316*6236dae4SAndroid Build Coastguard Worker
1317*6236dae4SAndroid Build Coastguard Worker /* Create a mime part and append it to a mime handle's part list. */
curl_mime_addpart(curl_mime * mime)1318*6236dae4SAndroid Build Coastguard Worker curl_mimepart *curl_mime_addpart(curl_mime *mime)
1319*6236dae4SAndroid Build Coastguard Worker {
1320*6236dae4SAndroid Build Coastguard Worker curl_mimepart *part;
1321*6236dae4SAndroid Build Coastguard Worker
1322*6236dae4SAndroid Build Coastguard Worker if(!mime)
1323*6236dae4SAndroid Build Coastguard Worker return NULL;
1324*6236dae4SAndroid Build Coastguard Worker
1325*6236dae4SAndroid Build Coastguard Worker part = (curl_mimepart *) malloc(sizeof(*part));
1326*6236dae4SAndroid Build Coastguard Worker
1327*6236dae4SAndroid Build Coastguard Worker if(part) {
1328*6236dae4SAndroid Build Coastguard Worker Curl_mime_initpart(part);
1329*6236dae4SAndroid Build Coastguard Worker part->parent = mime;
1330*6236dae4SAndroid Build Coastguard Worker
1331*6236dae4SAndroid Build Coastguard Worker if(mime->lastpart)
1332*6236dae4SAndroid Build Coastguard Worker mime->lastpart->nextpart = part;
1333*6236dae4SAndroid Build Coastguard Worker else
1334*6236dae4SAndroid Build Coastguard Worker mime->firstpart = part;
1335*6236dae4SAndroid Build Coastguard Worker
1336*6236dae4SAndroid Build Coastguard Worker mime->lastpart = part;
1337*6236dae4SAndroid Build Coastguard Worker }
1338*6236dae4SAndroid Build Coastguard Worker
1339*6236dae4SAndroid Build Coastguard Worker return part;
1340*6236dae4SAndroid Build Coastguard Worker }
1341*6236dae4SAndroid Build Coastguard Worker
1342*6236dae4SAndroid Build Coastguard Worker /* Set mime part name. */
curl_mime_name(curl_mimepart * part,const char * name)1343*6236dae4SAndroid Build Coastguard Worker CURLcode curl_mime_name(curl_mimepart *part, const char *name)
1344*6236dae4SAndroid Build Coastguard Worker {
1345*6236dae4SAndroid Build Coastguard Worker if(!part)
1346*6236dae4SAndroid Build Coastguard Worker return CURLE_BAD_FUNCTION_ARGUMENT;
1347*6236dae4SAndroid Build Coastguard Worker
1348*6236dae4SAndroid Build Coastguard Worker Curl_safefree(part->name);
1349*6236dae4SAndroid Build Coastguard Worker
1350*6236dae4SAndroid Build Coastguard Worker if(name) {
1351*6236dae4SAndroid Build Coastguard Worker part->name = strdup(name);
1352*6236dae4SAndroid Build Coastguard Worker if(!part->name)
1353*6236dae4SAndroid Build Coastguard Worker return CURLE_OUT_OF_MEMORY;
1354*6236dae4SAndroid Build Coastguard Worker }
1355*6236dae4SAndroid Build Coastguard Worker
1356*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
1357*6236dae4SAndroid Build Coastguard Worker }
1358*6236dae4SAndroid Build Coastguard Worker
1359*6236dae4SAndroid Build Coastguard Worker /* Set mime part remote filename. */
curl_mime_filename(curl_mimepart * part,const char * filename)1360*6236dae4SAndroid Build Coastguard Worker CURLcode curl_mime_filename(curl_mimepart *part, const char *filename)
1361*6236dae4SAndroid Build Coastguard Worker {
1362*6236dae4SAndroid Build Coastguard Worker if(!part)
1363*6236dae4SAndroid Build Coastguard Worker return CURLE_BAD_FUNCTION_ARGUMENT;
1364*6236dae4SAndroid Build Coastguard Worker
1365*6236dae4SAndroid Build Coastguard Worker Curl_safefree(part->filename);
1366*6236dae4SAndroid Build Coastguard Worker
1367*6236dae4SAndroid Build Coastguard Worker if(filename) {
1368*6236dae4SAndroid Build Coastguard Worker part->filename = strdup(filename);
1369*6236dae4SAndroid Build Coastguard Worker if(!part->filename)
1370*6236dae4SAndroid Build Coastguard Worker return CURLE_OUT_OF_MEMORY;
1371*6236dae4SAndroid Build Coastguard Worker }
1372*6236dae4SAndroid Build Coastguard Worker
1373*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
1374*6236dae4SAndroid Build Coastguard Worker }
1375*6236dae4SAndroid Build Coastguard Worker
1376*6236dae4SAndroid Build Coastguard Worker /* Set mime part content from memory data. */
curl_mime_data(curl_mimepart * part,const char * ptr,size_t datasize)1377*6236dae4SAndroid Build Coastguard Worker CURLcode curl_mime_data(curl_mimepart *part,
1378*6236dae4SAndroid Build Coastguard Worker const char *ptr, size_t datasize)
1379*6236dae4SAndroid Build Coastguard Worker {
1380*6236dae4SAndroid Build Coastguard Worker if(!part)
1381*6236dae4SAndroid Build Coastguard Worker return CURLE_BAD_FUNCTION_ARGUMENT;
1382*6236dae4SAndroid Build Coastguard Worker
1383*6236dae4SAndroid Build Coastguard Worker cleanup_part_content(part);
1384*6236dae4SAndroid Build Coastguard Worker
1385*6236dae4SAndroid Build Coastguard Worker if(ptr) {
1386*6236dae4SAndroid Build Coastguard Worker if(datasize == CURL_ZERO_TERMINATED)
1387*6236dae4SAndroid Build Coastguard Worker datasize = strlen(ptr);
1388*6236dae4SAndroid Build Coastguard Worker
1389*6236dae4SAndroid Build Coastguard Worker part->data = Curl_memdup0(ptr, datasize);
1390*6236dae4SAndroid Build Coastguard Worker if(!part->data)
1391*6236dae4SAndroid Build Coastguard Worker return CURLE_OUT_OF_MEMORY;
1392*6236dae4SAndroid Build Coastguard Worker
1393*6236dae4SAndroid Build Coastguard Worker part->datasize = datasize;
1394*6236dae4SAndroid Build Coastguard Worker part->readfunc = mime_mem_read;
1395*6236dae4SAndroid Build Coastguard Worker part->seekfunc = mime_mem_seek;
1396*6236dae4SAndroid Build Coastguard Worker part->freefunc = mime_mem_free;
1397*6236dae4SAndroid Build Coastguard Worker part->flags |= MIME_FAST_READ;
1398*6236dae4SAndroid Build Coastguard Worker part->kind = MIMEKIND_DATA;
1399*6236dae4SAndroid Build Coastguard Worker }
1400*6236dae4SAndroid Build Coastguard Worker
1401*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
1402*6236dae4SAndroid Build Coastguard Worker }
1403*6236dae4SAndroid Build Coastguard Worker
1404*6236dae4SAndroid Build Coastguard Worker /* Set mime part content from named local file. */
curl_mime_filedata(curl_mimepart * part,const char * filename)1405*6236dae4SAndroid Build Coastguard Worker CURLcode curl_mime_filedata(curl_mimepart *part, const char *filename)
1406*6236dae4SAndroid Build Coastguard Worker {
1407*6236dae4SAndroid Build Coastguard Worker CURLcode result = CURLE_OK;
1408*6236dae4SAndroid Build Coastguard Worker
1409*6236dae4SAndroid Build Coastguard Worker if(!part)
1410*6236dae4SAndroid Build Coastguard Worker return CURLE_BAD_FUNCTION_ARGUMENT;
1411*6236dae4SAndroid Build Coastguard Worker
1412*6236dae4SAndroid Build Coastguard Worker cleanup_part_content(part);
1413*6236dae4SAndroid Build Coastguard Worker
1414*6236dae4SAndroid Build Coastguard Worker if(filename) {
1415*6236dae4SAndroid Build Coastguard Worker char *base;
1416*6236dae4SAndroid Build Coastguard Worker struct_stat sbuf;
1417*6236dae4SAndroid Build Coastguard Worker
1418*6236dae4SAndroid Build Coastguard Worker if(stat(filename, &sbuf))
1419*6236dae4SAndroid Build Coastguard Worker result = CURLE_READ_ERROR;
1420*6236dae4SAndroid Build Coastguard Worker else {
1421*6236dae4SAndroid Build Coastguard Worker part->data = strdup(filename);
1422*6236dae4SAndroid Build Coastguard Worker if(!part->data)
1423*6236dae4SAndroid Build Coastguard Worker result = CURLE_OUT_OF_MEMORY;
1424*6236dae4SAndroid Build Coastguard Worker else {
1425*6236dae4SAndroid Build Coastguard Worker part->datasize = -1;
1426*6236dae4SAndroid Build Coastguard Worker if(S_ISREG(sbuf.st_mode)) {
1427*6236dae4SAndroid Build Coastguard Worker part->datasize = filesize(filename, sbuf);
1428*6236dae4SAndroid Build Coastguard Worker part->seekfunc = mime_file_seek;
1429*6236dae4SAndroid Build Coastguard Worker }
1430*6236dae4SAndroid Build Coastguard Worker
1431*6236dae4SAndroid Build Coastguard Worker part->readfunc = mime_file_read;
1432*6236dae4SAndroid Build Coastguard Worker part->freefunc = mime_file_free;
1433*6236dae4SAndroid Build Coastguard Worker part->kind = MIMEKIND_FILE;
1434*6236dae4SAndroid Build Coastguard Worker
1435*6236dae4SAndroid Build Coastguard Worker /* As a side effect, set the filename to the current file's base name.
1436*6236dae4SAndroid Build Coastguard Worker It is possible to withdraw this by explicitly calling
1437*6236dae4SAndroid Build Coastguard Worker curl_mime_filename() with a NULL filename argument after the current
1438*6236dae4SAndroid Build Coastguard Worker call. */
1439*6236dae4SAndroid Build Coastguard Worker base = strippath(filename);
1440*6236dae4SAndroid Build Coastguard Worker if(!base)
1441*6236dae4SAndroid Build Coastguard Worker result = CURLE_OUT_OF_MEMORY;
1442*6236dae4SAndroid Build Coastguard Worker else {
1443*6236dae4SAndroid Build Coastguard Worker result = curl_mime_filename(part, base);
1444*6236dae4SAndroid Build Coastguard Worker free(base);
1445*6236dae4SAndroid Build Coastguard Worker }
1446*6236dae4SAndroid Build Coastguard Worker }
1447*6236dae4SAndroid Build Coastguard Worker }
1448*6236dae4SAndroid Build Coastguard Worker }
1449*6236dae4SAndroid Build Coastguard Worker return result;
1450*6236dae4SAndroid Build Coastguard Worker }
1451*6236dae4SAndroid Build Coastguard Worker
1452*6236dae4SAndroid Build Coastguard Worker /* Set mime part type. */
curl_mime_type(curl_mimepart * part,const char * mimetype)1453*6236dae4SAndroid Build Coastguard Worker CURLcode curl_mime_type(curl_mimepart *part, const char *mimetype)
1454*6236dae4SAndroid Build Coastguard Worker {
1455*6236dae4SAndroid Build Coastguard Worker if(!part)
1456*6236dae4SAndroid Build Coastguard Worker return CURLE_BAD_FUNCTION_ARGUMENT;
1457*6236dae4SAndroid Build Coastguard Worker
1458*6236dae4SAndroid Build Coastguard Worker Curl_safefree(part->mimetype);
1459*6236dae4SAndroid Build Coastguard Worker
1460*6236dae4SAndroid Build Coastguard Worker if(mimetype) {
1461*6236dae4SAndroid Build Coastguard Worker part->mimetype = strdup(mimetype);
1462*6236dae4SAndroid Build Coastguard Worker if(!part->mimetype)
1463*6236dae4SAndroid Build Coastguard Worker return CURLE_OUT_OF_MEMORY;
1464*6236dae4SAndroid Build Coastguard Worker }
1465*6236dae4SAndroid Build Coastguard Worker
1466*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
1467*6236dae4SAndroid Build Coastguard Worker }
1468*6236dae4SAndroid Build Coastguard Worker
1469*6236dae4SAndroid Build Coastguard Worker /* Set mime data transfer encoder. */
curl_mime_encoder(curl_mimepart * part,const char * encoding)1470*6236dae4SAndroid Build Coastguard Worker CURLcode curl_mime_encoder(curl_mimepart *part, const char *encoding)
1471*6236dae4SAndroid Build Coastguard Worker {
1472*6236dae4SAndroid Build Coastguard Worker CURLcode result = CURLE_BAD_FUNCTION_ARGUMENT;
1473*6236dae4SAndroid Build Coastguard Worker const struct mime_encoder *mep;
1474*6236dae4SAndroid Build Coastguard Worker
1475*6236dae4SAndroid Build Coastguard Worker if(!part)
1476*6236dae4SAndroid Build Coastguard Worker return result;
1477*6236dae4SAndroid Build Coastguard Worker
1478*6236dae4SAndroid Build Coastguard Worker part->encoder = NULL;
1479*6236dae4SAndroid Build Coastguard Worker
1480*6236dae4SAndroid Build Coastguard Worker if(!encoding)
1481*6236dae4SAndroid Build Coastguard Worker return CURLE_OK; /* Removing current encoder. */
1482*6236dae4SAndroid Build Coastguard Worker
1483*6236dae4SAndroid Build Coastguard Worker for(mep = encoders; mep->name; mep++)
1484*6236dae4SAndroid Build Coastguard Worker if(strcasecompare(encoding, mep->name)) {
1485*6236dae4SAndroid Build Coastguard Worker part->encoder = mep;
1486*6236dae4SAndroid Build Coastguard Worker result = CURLE_OK;
1487*6236dae4SAndroid Build Coastguard Worker }
1488*6236dae4SAndroid Build Coastguard Worker
1489*6236dae4SAndroid Build Coastguard Worker return result;
1490*6236dae4SAndroid Build Coastguard Worker }
1491*6236dae4SAndroid Build Coastguard Worker
1492*6236dae4SAndroid Build Coastguard Worker /* Set mime part headers. */
curl_mime_headers(curl_mimepart * part,struct curl_slist * headers,int take_ownership)1493*6236dae4SAndroid Build Coastguard Worker CURLcode curl_mime_headers(curl_mimepart *part,
1494*6236dae4SAndroid Build Coastguard Worker struct curl_slist *headers, int take_ownership)
1495*6236dae4SAndroid Build Coastguard Worker {
1496*6236dae4SAndroid Build Coastguard Worker if(!part)
1497*6236dae4SAndroid Build Coastguard Worker return CURLE_BAD_FUNCTION_ARGUMENT;
1498*6236dae4SAndroid Build Coastguard Worker
1499*6236dae4SAndroid Build Coastguard Worker if(part->flags & MIME_USERHEADERS_OWNER) {
1500*6236dae4SAndroid Build Coastguard Worker if(part->userheaders != headers) /* Allow setting twice the same list. */
1501*6236dae4SAndroid Build Coastguard Worker curl_slist_free_all(part->userheaders);
1502*6236dae4SAndroid Build Coastguard Worker part->flags &= ~(unsigned int)MIME_USERHEADERS_OWNER;
1503*6236dae4SAndroid Build Coastguard Worker }
1504*6236dae4SAndroid Build Coastguard Worker part->userheaders = headers;
1505*6236dae4SAndroid Build Coastguard Worker if(headers && take_ownership)
1506*6236dae4SAndroid Build Coastguard Worker part->flags |= MIME_USERHEADERS_OWNER;
1507*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
1508*6236dae4SAndroid Build Coastguard Worker }
1509*6236dae4SAndroid Build Coastguard Worker
1510*6236dae4SAndroid Build Coastguard Worker /* Set mime part content from callback. */
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)1511*6236dae4SAndroid Build Coastguard Worker CURLcode curl_mime_data_cb(curl_mimepart *part, curl_off_t datasize,
1512*6236dae4SAndroid Build Coastguard Worker curl_read_callback readfunc,
1513*6236dae4SAndroid Build Coastguard Worker curl_seek_callback seekfunc,
1514*6236dae4SAndroid Build Coastguard Worker curl_free_callback freefunc, void *arg)
1515*6236dae4SAndroid Build Coastguard Worker {
1516*6236dae4SAndroid Build Coastguard Worker if(!part)
1517*6236dae4SAndroid Build Coastguard Worker return CURLE_BAD_FUNCTION_ARGUMENT;
1518*6236dae4SAndroid Build Coastguard Worker
1519*6236dae4SAndroid Build Coastguard Worker cleanup_part_content(part);
1520*6236dae4SAndroid Build Coastguard Worker
1521*6236dae4SAndroid Build Coastguard Worker if(readfunc) {
1522*6236dae4SAndroid Build Coastguard Worker part->readfunc = readfunc;
1523*6236dae4SAndroid Build Coastguard Worker part->seekfunc = seekfunc;
1524*6236dae4SAndroid Build Coastguard Worker part->freefunc = freefunc;
1525*6236dae4SAndroid Build Coastguard Worker part->arg = arg;
1526*6236dae4SAndroid Build Coastguard Worker part->datasize = datasize;
1527*6236dae4SAndroid Build Coastguard Worker part->kind = MIMEKIND_CALLBACK;
1528*6236dae4SAndroid Build Coastguard Worker }
1529*6236dae4SAndroid Build Coastguard Worker
1530*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
1531*6236dae4SAndroid Build Coastguard Worker }
1532*6236dae4SAndroid Build Coastguard Worker
1533*6236dae4SAndroid Build Coastguard Worker /* Set mime part content from subparts. */
Curl_mime_set_subparts(curl_mimepart * part,curl_mime * subparts,int take_ownership)1534*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_mime_set_subparts(curl_mimepart *part,
1535*6236dae4SAndroid Build Coastguard Worker curl_mime *subparts, int take_ownership)
1536*6236dae4SAndroid Build Coastguard Worker {
1537*6236dae4SAndroid Build Coastguard Worker curl_mime *root;
1538*6236dae4SAndroid Build Coastguard Worker
1539*6236dae4SAndroid Build Coastguard Worker if(!part)
1540*6236dae4SAndroid Build Coastguard Worker return CURLE_BAD_FUNCTION_ARGUMENT;
1541*6236dae4SAndroid Build Coastguard Worker
1542*6236dae4SAndroid Build Coastguard Worker /* Accept setting twice the same subparts. */
1543*6236dae4SAndroid Build Coastguard Worker if(part->kind == MIMEKIND_MULTIPART && part->arg == subparts)
1544*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
1545*6236dae4SAndroid Build Coastguard Worker
1546*6236dae4SAndroid Build Coastguard Worker cleanup_part_content(part);
1547*6236dae4SAndroid Build Coastguard Worker
1548*6236dae4SAndroid Build Coastguard Worker if(subparts) {
1549*6236dae4SAndroid Build Coastguard Worker /* Should not have been attached already. */
1550*6236dae4SAndroid Build Coastguard Worker if(subparts->parent)
1551*6236dae4SAndroid Build Coastguard Worker return CURLE_BAD_FUNCTION_ARGUMENT;
1552*6236dae4SAndroid Build Coastguard Worker
1553*6236dae4SAndroid Build Coastguard Worker /* Should not be the part's root. */
1554*6236dae4SAndroid Build Coastguard Worker root = part->parent;
1555*6236dae4SAndroid Build Coastguard Worker if(root) {
1556*6236dae4SAndroid Build Coastguard Worker while(root->parent && root->parent->parent)
1557*6236dae4SAndroid Build Coastguard Worker root = root->parent->parent;
1558*6236dae4SAndroid Build Coastguard Worker if(subparts == root) {
1559*6236dae4SAndroid Build Coastguard Worker /* cannot add as a subpart of itself. */
1560*6236dae4SAndroid Build Coastguard Worker return CURLE_BAD_FUNCTION_ARGUMENT;
1561*6236dae4SAndroid Build Coastguard Worker }
1562*6236dae4SAndroid Build Coastguard Worker }
1563*6236dae4SAndroid Build Coastguard Worker
1564*6236dae4SAndroid Build Coastguard Worker subparts->parent = part;
1565*6236dae4SAndroid Build Coastguard Worker /* Subparts are processed internally: no read callback. */
1566*6236dae4SAndroid Build Coastguard Worker part->seekfunc = mime_subparts_seek;
1567*6236dae4SAndroid Build Coastguard Worker part->freefunc = take_ownership ? mime_subparts_free :
1568*6236dae4SAndroid Build Coastguard Worker mime_subparts_unbind;
1569*6236dae4SAndroid Build Coastguard Worker part->arg = subparts;
1570*6236dae4SAndroid Build Coastguard Worker part->datasize = -1;
1571*6236dae4SAndroid Build Coastguard Worker part->kind = MIMEKIND_MULTIPART;
1572*6236dae4SAndroid Build Coastguard Worker }
1573*6236dae4SAndroid Build Coastguard Worker
1574*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
1575*6236dae4SAndroid Build Coastguard Worker }
1576*6236dae4SAndroid Build Coastguard Worker
curl_mime_subparts(curl_mimepart * part,curl_mime * subparts)1577*6236dae4SAndroid Build Coastguard Worker CURLcode curl_mime_subparts(curl_mimepart *part, curl_mime *subparts)
1578*6236dae4SAndroid Build Coastguard Worker {
1579*6236dae4SAndroid Build Coastguard Worker return Curl_mime_set_subparts(part, subparts, TRUE);
1580*6236dae4SAndroid Build Coastguard Worker }
1581*6236dae4SAndroid Build Coastguard Worker
1582*6236dae4SAndroid Build Coastguard Worker
1583*6236dae4SAndroid Build Coastguard Worker /* Readback from top mime. */
1584*6236dae4SAndroid Build Coastguard Worker /* Argument is the dummy top part. */
Curl_mime_read(char * buffer,size_t size,size_t nitems,void * instream)1585*6236dae4SAndroid Build Coastguard Worker size_t Curl_mime_read(char *buffer, size_t size, size_t nitems, void *instream)
1586*6236dae4SAndroid Build Coastguard Worker {
1587*6236dae4SAndroid Build Coastguard Worker curl_mimepart *part = (curl_mimepart *) instream;
1588*6236dae4SAndroid Build Coastguard Worker size_t ret;
1589*6236dae4SAndroid Build Coastguard Worker bool hasread;
1590*6236dae4SAndroid Build Coastguard Worker
1591*6236dae4SAndroid Build Coastguard Worker (void) size; /* Always 1. */
1592*6236dae4SAndroid Build Coastguard Worker
1593*6236dae4SAndroid Build Coastguard Worker /* TODO: this loop is broken. If `nitems` is <= 4, some encoders will
1594*6236dae4SAndroid Build Coastguard Worker * return STOP_FILLING without adding any data and this loops infinitely. */
1595*6236dae4SAndroid Build Coastguard Worker do {
1596*6236dae4SAndroid Build Coastguard Worker hasread = FALSE;
1597*6236dae4SAndroid Build Coastguard Worker ret = readback_part(part, buffer, nitems, &hasread);
1598*6236dae4SAndroid Build Coastguard Worker /*
1599*6236dae4SAndroid Build Coastguard Worker * If this is not possible to get some data without calling more than
1600*6236dae4SAndroid Build Coastguard Worker * one read callback (probably because a content encoder is not able to
1601*6236dae4SAndroid Build Coastguard Worker * deliver a new bunch for the few data accumulated so far), force another
1602*6236dae4SAndroid Build Coastguard Worker * read until we get enough data or a special exit code.
1603*6236dae4SAndroid Build Coastguard Worker */
1604*6236dae4SAndroid Build Coastguard Worker } while(ret == STOP_FILLING);
1605*6236dae4SAndroid Build Coastguard Worker
1606*6236dae4SAndroid Build Coastguard Worker return ret;
1607*6236dae4SAndroid Build Coastguard Worker }
1608*6236dae4SAndroid Build Coastguard Worker
1609*6236dae4SAndroid Build Coastguard Worker /* Rewind mime stream. */
mime_rewind(curl_mimepart * part)1610*6236dae4SAndroid Build Coastguard Worker static CURLcode mime_rewind(curl_mimepart *part)
1611*6236dae4SAndroid Build Coastguard Worker {
1612*6236dae4SAndroid Build Coastguard Worker return mime_part_rewind(part) == CURL_SEEKFUNC_OK ?
1613*6236dae4SAndroid Build Coastguard Worker CURLE_OK : CURLE_SEND_FAIL_REWIND;
1614*6236dae4SAndroid Build Coastguard Worker }
1615*6236dae4SAndroid Build Coastguard Worker
1616*6236dae4SAndroid Build Coastguard Worker /* Compute header list size. */
slist_size(struct curl_slist * s,size_t overhead,const char * skip,size_t skiplen)1617*6236dae4SAndroid Build Coastguard Worker static size_t slist_size(struct curl_slist *s,
1618*6236dae4SAndroid Build Coastguard Worker size_t overhead, const char *skip, size_t skiplen)
1619*6236dae4SAndroid Build Coastguard Worker {
1620*6236dae4SAndroid Build Coastguard Worker size_t size = 0;
1621*6236dae4SAndroid Build Coastguard Worker
1622*6236dae4SAndroid Build Coastguard Worker for(; s; s = s->next)
1623*6236dae4SAndroid Build Coastguard Worker if(!skip || !match_header(s, skip, skiplen))
1624*6236dae4SAndroid Build Coastguard Worker size += strlen(s->data) + overhead;
1625*6236dae4SAndroid Build Coastguard Worker return size;
1626*6236dae4SAndroid Build Coastguard Worker }
1627*6236dae4SAndroid Build Coastguard Worker
1628*6236dae4SAndroid Build Coastguard Worker /* Get/compute multipart size. */
multipart_size(curl_mime * mime)1629*6236dae4SAndroid Build Coastguard Worker static curl_off_t multipart_size(curl_mime *mime)
1630*6236dae4SAndroid Build Coastguard Worker {
1631*6236dae4SAndroid Build Coastguard Worker curl_off_t size;
1632*6236dae4SAndroid Build Coastguard Worker curl_off_t boundarysize;
1633*6236dae4SAndroid Build Coastguard Worker curl_mimepart *part;
1634*6236dae4SAndroid Build Coastguard Worker
1635*6236dae4SAndroid Build Coastguard Worker if(!mime)
1636*6236dae4SAndroid Build Coastguard Worker return 0; /* Not present -> empty. */
1637*6236dae4SAndroid Build Coastguard Worker
1638*6236dae4SAndroid Build Coastguard Worker boundarysize = 4 + MIME_BOUNDARY_LEN + 2;
1639*6236dae4SAndroid Build Coastguard Worker size = boundarysize; /* Final boundary - CRLF after headers. */
1640*6236dae4SAndroid Build Coastguard Worker
1641*6236dae4SAndroid Build Coastguard Worker for(part = mime->firstpart; part; part = part->nextpart) {
1642*6236dae4SAndroid Build Coastguard Worker curl_off_t sz = mime_size(part);
1643*6236dae4SAndroid Build Coastguard Worker
1644*6236dae4SAndroid Build Coastguard Worker if(sz < 0)
1645*6236dae4SAndroid Build Coastguard Worker size = sz;
1646*6236dae4SAndroid Build Coastguard Worker
1647*6236dae4SAndroid Build Coastguard Worker if(size >= 0)
1648*6236dae4SAndroid Build Coastguard Worker size += boundarysize + sz;
1649*6236dae4SAndroid Build Coastguard Worker }
1650*6236dae4SAndroid Build Coastguard Worker
1651*6236dae4SAndroid Build Coastguard Worker return size;
1652*6236dae4SAndroid Build Coastguard Worker }
1653*6236dae4SAndroid Build Coastguard Worker
1654*6236dae4SAndroid Build Coastguard Worker /* Get/compute mime size. */
mime_size(curl_mimepart * part)1655*6236dae4SAndroid Build Coastguard Worker static curl_off_t mime_size(curl_mimepart *part)
1656*6236dae4SAndroid Build Coastguard Worker {
1657*6236dae4SAndroid Build Coastguard Worker curl_off_t size;
1658*6236dae4SAndroid Build Coastguard Worker
1659*6236dae4SAndroid Build Coastguard Worker if(part->kind == MIMEKIND_MULTIPART)
1660*6236dae4SAndroid Build Coastguard Worker part->datasize = multipart_size(part->arg);
1661*6236dae4SAndroid Build Coastguard Worker
1662*6236dae4SAndroid Build Coastguard Worker size = part->datasize;
1663*6236dae4SAndroid Build Coastguard Worker
1664*6236dae4SAndroid Build Coastguard Worker if(part->encoder)
1665*6236dae4SAndroid Build Coastguard Worker size = part->encoder->sizefunc(part);
1666*6236dae4SAndroid Build Coastguard Worker
1667*6236dae4SAndroid Build Coastguard Worker if(size >= 0 && !(part->flags & MIME_BODY_ONLY)) {
1668*6236dae4SAndroid Build Coastguard Worker /* Compute total part size. */
1669*6236dae4SAndroid Build Coastguard Worker size += slist_size(part->curlheaders, 2, NULL, 0);
1670*6236dae4SAndroid Build Coastguard Worker size += slist_size(part->userheaders, 2,
1671*6236dae4SAndroid Build Coastguard Worker STRCONST("Content-Type"));
1672*6236dae4SAndroid Build Coastguard Worker size += 2; /* CRLF after headers. */
1673*6236dae4SAndroid Build Coastguard Worker }
1674*6236dae4SAndroid Build Coastguard Worker return size;
1675*6236dae4SAndroid Build Coastguard Worker }
1676*6236dae4SAndroid Build Coastguard Worker
1677*6236dae4SAndroid Build Coastguard Worker /* Add a header. */
1678*6236dae4SAndroid Build Coastguard Worker /* VARARGS2 */
Curl_mime_add_header(struct curl_slist ** slp,const char * fmt,...)1679*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_mime_add_header(struct curl_slist **slp, const char *fmt, ...)
1680*6236dae4SAndroid Build Coastguard Worker {
1681*6236dae4SAndroid Build Coastguard Worker struct curl_slist *hdr = NULL;
1682*6236dae4SAndroid Build Coastguard Worker char *s = NULL;
1683*6236dae4SAndroid Build Coastguard Worker va_list ap;
1684*6236dae4SAndroid Build Coastguard Worker
1685*6236dae4SAndroid Build Coastguard Worker va_start(ap, fmt);
1686*6236dae4SAndroid Build Coastguard Worker s = vaprintf(fmt, ap);
1687*6236dae4SAndroid Build Coastguard Worker va_end(ap);
1688*6236dae4SAndroid Build Coastguard Worker
1689*6236dae4SAndroid Build Coastguard Worker if(s) {
1690*6236dae4SAndroid Build Coastguard Worker hdr = Curl_slist_append_nodup(*slp, s);
1691*6236dae4SAndroid Build Coastguard Worker if(hdr)
1692*6236dae4SAndroid Build Coastguard Worker *slp = hdr;
1693*6236dae4SAndroid Build Coastguard Worker else
1694*6236dae4SAndroid Build Coastguard Worker free(s);
1695*6236dae4SAndroid Build Coastguard Worker }
1696*6236dae4SAndroid Build Coastguard Worker
1697*6236dae4SAndroid Build Coastguard Worker return hdr ? CURLE_OK : CURLE_OUT_OF_MEMORY;
1698*6236dae4SAndroid Build Coastguard Worker }
1699*6236dae4SAndroid Build Coastguard Worker
1700*6236dae4SAndroid Build Coastguard Worker /* Add a content type header. */
add_content_type(struct curl_slist ** slp,const char * type,const char * boundary)1701*6236dae4SAndroid Build Coastguard Worker static CURLcode add_content_type(struct curl_slist **slp,
1702*6236dae4SAndroid Build Coastguard Worker const char *type, const char *boundary)
1703*6236dae4SAndroid Build Coastguard Worker {
1704*6236dae4SAndroid Build Coastguard Worker return Curl_mime_add_header(slp, "Content-Type: %s%s%s", type,
1705*6236dae4SAndroid Build Coastguard Worker boundary ? "; boundary=" : "",
1706*6236dae4SAndroid Build Coastguard Worker boundary ? boundary : "");
1707*6236dae4SAndroid Build Coastguard Worker }
1708*6236dae4SAndroid Build Coastguard Worker
Curl_mime_contenttype(const char * filename)1709*6236dae4SAndroid Build Coastguard Worker const char *Curl_mime_contenttype(const char *filename)
1710*6236dae4SAndroid Build Coastguard Worker {
1711*6236dae4SAndroid Build Coastguard Worker /*
1712*6236dae4SAndroid Build Coastguard Worker * If no content type was specified, we scan through a few well-known
1713*6236dae4SAndroid Build Coastguard Worker * extensions and pick the first we match!
1714*6236dae4SAndroid Build Coastguard Worker */
1715*6236dae4SAndroid Build Coastguard Worker struct ContentType {
1716*6236dae4SAndroid Build Coastguard Worker const char *extension;
1717*6236dae4SAndroid Build Coastguard Worker const char *type;
1718*6236dae4SAndroid Build Coastguard Worker };
1719*6236dae4SAndroid Build Coastguard Worker static const struct ContentType ctts[] = {
1720*6236dae4SAndroid Build Coastguard Worker {".gif", "image/gif"},
1721*6236dae4SAndroid Build Coastguard Worker {".jpg", "image/jpeg"},
1722*6236dae4SAndroid Build Coastguard Worker {".jpeg", "image/jpeg"},
1723*6236dae4SAndroid Build Coastguard Worker {".png", "image/png"},
1724*6236dae4SAndroid Build Coastguard Worker {".svg", "image/svg+xml"},
1725*6236dae4SAndroid Build Coastguard Worker {".txt", "text/plain"},
1726*6236dae4SAndroid Build Coastguard Worker {".htm", "text/html"},
1727*6236dae4SAndroid Build Coastguard Worker {".html", "text/html"},
1728*6236dae4SAndroid Build Coastguard Worker {".pdf", "application/pdf"},
1729*6236dae4SAndroid Build Coastguard Worker {".xml", "application/xml"}
1730*6236dae4SAndroid Build Coastguard Worker };
1731*6236dae4SAndroid Build Coastguard Worker
1732*6236dae4SAndroid Build Coastguard Worker if(filename) {
1733*6236dae4SAndroid Build Coastguard Worker size_t len1 = strlen(filename);
1734*6236dae4SAndroid Build Coastguard Worker const char *nameend = filename + len1;
1735*6236dae4SAndroid Build Coastguard Worker unsigned int i;
1736*6236dae4SAndroid Build Coastguard Worker
1737*6236dae4SAndroid Build Coastguard Worker for(i = 0; i < sizeof(ctts) / sizeof(ctts[0]); i++) {
1738*6236dae4SAndroid Build Coastguard Worker size_t len2 = strlen(ctts[i].extension);
1739*6236dae4SAndroid Build Coastguard Worker
1740*6236dae4SAndroid Build Coastguard Worker if(len1 >= len2 && strcasecompare(nameend - len2, ctts[i].extension))
1741*6236dae4SAndroid Build Coastguard Worker return ctts[i].type;
1742*6236dae4SAndroid Build Coastguard Worker }
1743*6236dae4SAndroid Build Coastguard Worker }
1744*6236dae4SAndroid Build Coastguard Worker return NULL;
1745*6236dae4SAndroid Build Coastguard Worker }
1746*6236dae4SAndroid Build Coastguard Worker
content_type_match(const char * contenttype,const char * target,size_t len)1747*6236dae4SAndroid Build Coastguard Worker static bool content_type_match(const char *contenttype,
1748*6236dae4SAndroid Build Coastguard Worker const char *target, size_t len)
1749*6236dae4SAndroid Build Coastguard Worker {
1750*6236dae4SAndroid Build Coastguard Worker if(contenttype && strncasecompare(contenttype, target, len))
1751*6236dae4SAndroid Build Coastguard Worker switch(contenttype[len]) {
1752*6236dae4SAndroid Build Coastguard Worker case '\0':
1753*6236dae4SAndroid Build Coastguard Worker case '\t':
1754*6236dae4SAndroid Build Coastguard Worker case '\r':
1755*6236dae4SAndroid Build Coastguard Worker case '\n':
1756*6236dae4SAndroid Build Coastguard Worker case ' ':
1757*6236dae4SAndroid Build Coastguard Worker case ';':
1758*6236dae4SAndroid Build Coastguard Worker return TRUE;
1759*6236dae4SAndroid Build Coastguard Worker }
1760*6236dae4SAndroid Build Coastguard Worker return FALSE;
1761*6236dae4SAndroid Build Coastguard Worker }
1762*6236dae4SAndroid Build Coastguard Worker
Curl_mime_prepare_headers(struct Curl_easy * data,curl_mimepart * part,const char * contenttype,const char * disposition,enum mimestrategy strategy)1763*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_mime_prepare_headers(struct Curl_easy *data,
1764*6236dae4SAndroid Build Coastguard Worker curl_mimepart *part,
1765*6236dae4SAndroid Build Coastguard Worker const char *contenttype,
1766*6236dae4SAndroid Build Coastguard Worker const char *disposition,
1767*6236dae4SAndroid Build Coastguard Worker enum mimestrategy strategy)
1768*6236dae4SAndroid Build Coastguard Worker {
1769*6236dae4SAndroid Build Coastguard Worker curl_mime *mime = NULL;
1770*6236dae4SAndroid Build Coastguard Worker const char *boundary = NULL;
1771*6236dae4SAndroid Build Coastguard Worker char *customct;
1772*6236dae4SAndroid Build Coastguard Worker const char *cte = NULL;
1773*6236dae4SAndroid Build Coastguard Worker CURLcode ret = CURLE_OK;
1774*6236dae4SAndroid Build Coastguard Worker
1775*6236dae4SAndroid Build Coastguard Worker /* Get rid of previously prepared headers. */
1776*6236dae4SAndroid Build Coastguard Worker curl_slist_free_all(part->curlheaders);
1777*6236dae4SAndroid Build Coastguard Worker part->curlheaders = NULL;
1778*6236dae4SAndroid Build Coastguard Worker
1779*6236dae4SAndroid Build Coastguard Worker /* Be sure we will not access old headers later. */
1780*6236dae4SAndroid Build Coastguard Worker if(part->state.state == MIMESTATE_CURLHEADERS)
1781*6236dae4SAndroid Build Coastguard Worker mimesetstate(&part->state, MIMESTATE_CURLHEADERS, NULL);
1782*6236dae4SAndroid Build Coastguard Worker
1783*6236dae4SAndroid Build Coastguard Worker /* Check if content type is specified. */
1784*6236dae4SAndroid Build Coastguard Worker customct = part->mimetype;
1785*6236dae4SAndroid Build Coastguard Worker if(!customct)
1786*6236dae4SAndroid Build Coastguard Worker customct = search_header(part->userheaders, STRCONST("Content-Type"));
1787*6236dae4SAndroid Build Coastguard Worker if(customct)
1788*6236dae4SAndroid Build Coastguard Worker contenttype = customct;
1789*6236dae4SAndroid Build Coastguard Worker
1790*6236dae4SAndroid Build Coastguard Worker /* If content type is not specified, try to determine it. */
1791*6236dae4SAndroid Build Coastguard Worker if(!contenttype) {
1792*6236dae4SAndroid Build Coastguard Worker switch(part->kind) {
1793*6236dae4SAndroid Build Coastguard Worker case MIMEKIND_MULTIPART:
1794*6236dae4SAndroid Build Coastguard Worker contenttype = MULTIPART_CONTENTTYPE_DEFAULT;
1795*6236dae4SAndroid Build Coastguard Worker break;
1796*6236dae4SAndroid Build Coastguard Worker case MIMEKIND_FILE:
1797*6236dae4SAndroid Build Coastguard Worker contenttype = Curl_mime_contenttype(part->filename);
1798*6236dae4SAndroid Build Coastguard Worker if(!contenttype)
1799*6236dae4SAndroid Build Coastguard Worker contenttype = Curl_mime_contenttype(part->data);
1800*6236dae4SAndroid Build Coastguard Worker if(!contenttype && part->filename)
1801*6236dae4SAndroid Build Coastguard Worker contenttype = FILE_CONTENTTYPE_DEFAULT;
1802*6236dae4SAndroid Build Coastguard Worker break;
1803*6236dae4SAndroid Build Coastguard Worker default:
1804*6236dae4SAndroid Build Coastguard Worker contenttype = Curl_mime_contenttype(part->filename);
1805*6236dae4SAndroid Build Coastguard Worker break;
1806*6236dae4SAndroid Build Coastguard Worker }
1807*6236dae4SAndroid Build Coastguard Worker }
1808*6236dae4SAndroid Build Coastguard Worker
1809*6236dae4SAndroid Build Coastguard Worker if(part->kind == MIMEKIND_MULTIPART) {
1810*6236dae4SAndroid Build Coastguard Worker mime = (curl_mime *) part->arg;
1811*6236dae4SAndroid Build Coastguard Worker if(mime)
1812*6236dae4SAndroid Build Coastguard Worker boundary = mime->boundary;
1813*6236dae4SAndroid Build Coastguard Worker }
1814*6236dae4SAndroid Build Coastguard Worker else if(contenttype && !customct &&
1815*6236dae4SAndroid Build Coastguard Worker content_type_match(contenttype, STRCONST("text/plain")))
1816*6236dae4SAndroid Build Coastguard Worker if(strategy == MIMESTRATEGY_MAIL || !part->filename)
1817*6236dae4SAndroid Build Coastguard Worker contenttype = NULL;
1818*6236dae4SAndroid Build Coastguard Worker
1819*6236dae4SAndroid Build Coastguard Worker /* Issue content-disposition header only if not already set by caller. */
1820*6236dae4SAndroid Build Coastguard Worker if(!search_header(part->userheaders, STRCONST("Content-Disposition"))) {
1821*6236dae4SAndroid Build Coastguard Worker if(!disposition)
1822*6236dae4SAndroid Build Coastguard Worker if(part->filename || part->name ||
1823*6236dae4SAndroid Build Coastguard Worker (contenttype && !strncasecompare(contenttype, "multipart/", 10)))
1824*6236dae4SAndroid Build Coastguard Worker disposition = DISPOSITION_DEFAULT;
1825*6236dae4SAndroid Build Coastguard Worker if(disposition && curl_strequal(disposition, "attachment") &&
1826*6236dae4SAndroid Build Coastguard Worker !part->name && !part->filename)
1827*6236dae4SAndroid Build Coastguard Worker disposition = NULL;
1828*6236dae4SAndroid Build Coastguard Worker if(disposition) {
1829*6236dae4SAndroid Build Coastguard Worker char *name = NULL;
1830*6236dae4SAndroid Build Coastguard Worker char *filename = NULL;
1831*6236dae4SAndroid Build Coastguard Worker
1832*6236dae4SAndroid Build Coastguard Worker if(part->name) {
1833*6236dae4SAndroid Build Coastguard Worker name = escape_string(data, part->name, strategy);
1834*6236dae4SAndroid Build Coastguard Worker if(!name)
1835*6236dae4SAndroid Build Coastguard Worker ret = CURLE_OUT_OF_MEMORY;
1836*6236dae4SAndroid Build Coastguard Worker }
1837*6236dae4SAndroid Build Coastguard Worker if(!ret && part->filename) {
1838*6236dae4SAndroid Build Coastguard Worker filename = escape_string(data, part->filename, strategy);
1839*6236dae4SAndroid Build Coastguard Worker if(!filename)
1840*6236dae4SAndroid Build Coastguard Worker ret = CURLE_OUT_OF_MEMORY;
1841*6236dae4SAndroid Build Coastguard Worker }
1842*6236dae4SAndroid Build Coastguard Worker if(!ret)
1843*6236dae4SAndroid Build Coastguard Worker ret = Curl_mime_add_header(&part->curlheaders,
1844*6236dae4SAndroid Build Coastguard Worker "Content-Disposition: %s%s%s%s%s%s%s",
1845*6236dae4SAndroid Build Coastguard Worker disposition,
1846*6236dae4SAndroid Build Coastguard Worker name ? "; name=\"" : "",
1847*6236dae4SAndroid Build Coastguard Worker name ? name : "",
1848*6236dae4SAndroid Build Coastguard Worker name ? "\"" : "",
1849*6236dae4SAndroid Build Coastguard Worker filename ? "; filename=\"" : "",
1850*6236dae4SAndroid Build Coastguard Worker filename ? filename : "",
1851*6236dae4SAndroid Build Coastguard Worker filename ? "\"" : "");
1852*6236dae4SAndroid Build Coastguard Worker Curl_safefree(name);
1853*6236dae4SAndroid Build Coastguard Worker Curl_safefree(filename);
1854*6236dae4SAndroid Build Coastguard Worker if(ret)
1855*6236dae4SAndroid Build Coastguard Worker return ret;
1856*6236dae4SAndroid Build Coastguard Worker }
1857*6236dae4SAndroid Build Coastguard Worker }
1858*6236dae4SAndroid Build Coastguard Worker
1859*6236dae4SAndroid Build Coastguard Worker /* Issue Content-Type header. */
1860*6236dae4SAndroid Build Coastguard Worker if(contenttype) {
1861*6236dae4SAndroid Build Coastguard Worker ret = add_content_type(&part->curlheaders, contenttype, boundary);
1862*6236dae4SAndroid Build Coastguard Worker if(ret)
1863*6236dae4SAndroid Build Coastguard Worker return ret;
1864*6236dae4SAndroid Build Coastguard Worker }
1865*6236dae4SAndroid Build Coastguard Worker
1866*6236dae4SAndroid Build Coastguard Worker /* Content-Transfer-Encoding header. */
1867*6236dae4SAndroid Build Coastguard Worker if(!search_header(part->userheaders,
1868*6236dae4SAndroid Build Coastguard Worker STRCONST("Content-Transfer-Encoding"))) {
1869*6236dae4SAndroid Build Coastguard Worker if(part->encoder)
1870*6236dae4SAndroid Build Coastguard Worker cte = part->encoder->name;
1871*6236dae4SAndroid Build Coastguard Worker else if(contenttype && strategy == MIMESTRATEGY_MAIL &&
1872*6236dae4SAndroid Build Coastguard Worker part->kind != MIMEKIND_MULTIPART)
1873*6236dae4SAndroid Build Coastguard Worker cte = "8bit";
1874*6236dae4SAndroid Build Coastguard Worker if(cte) {
1875*6236dae4SAndroid Build Coastguard Worker ret = Curl_mime_add_header(&part->curlheaders,
1876*6236dae4SAndroid Build Coastguard Worker "Content-Transfer-Encoding: %s", cte);
1877*6236dae4SAndroid Build Coastguard Worker if(ret)
1878*6236dae4SAndroid Build Coastguard Worker return ret;
1879*6236dae4SAndroid Build Coastguard Worker }
1880*6236dae4SAndroid Build Coastguard Worker }
1881*6236dae4SAndroid Build Coastguard Worker
1882*6236dae4SAndroid Build Coastguard Worker /* If we were reading curl-generated headers, restart with new ones (this
1883*6236dae4SAndroid Build Coastguard Worker should not occur). */
1884*6236dae4SAndroid Build Coastguard Worker if(part->state.state == MIMESTATE_CURLHEADERS)
1885*6236dae4SAndroid Build Coastguard Worker mimesetstate(&part->state, MIMESTATE_CURLHEADERS, part->curlheaders);
1886*6236dae4SAndroid Build Coastguard Worker
1887*6236dae4SAndroid Build Coastguard Worker /* Process subparts. */
1888*6236dae4SAndroid Build Coastguard Worker if(part->kind == MIMEKIND_MULTIPART && mime) {
1889*6236dae4SAndroid Build Coastguard Worker curl_mimepart *subpart;
1890*6236dae4SAndroid Build Coastguard Worker
1891*6236dae4SAndroid Build Coastguard Worker disposition = NULL;
1892*6236dae4SAndroid Build Coastguard Worker if(content_type_match(contenttype, STRCONST("multipart/form-data")))
1893*6236dae4SAndroid Build Coastguard Worker disposition = "form-data";
1894*6236dae4SAndroid Build Coastguard Worker for(subpart = mime->firstpart; subpart; subpart = subpart->nextpart) {
1895*6236dae4SAndroid Build Coastguard Worker ret = Curl_mime_prepare_headers(data, subpart, NULL,
1896*6236dae4SAndroid Build Coastguard Worker disposition, strategy);
1897*6236dae4SAndroid Build Coastguard Worker if(ret)
1898*6236dae4SAndroid Build Coastguard Worker return ret;
1899*6236dae4SAndroid Build Coastguard Worker }
1900*6236dae4SAndroid Build Coastguard Worker }
1901*6236dae4SAndroid Build Coastguard Worker return ret;
1902*6236dae4SAndroid Build Coastguard Worker }
1903*6236dae4SAndroid Build Coastguard Worker
1904*6236dae4SAndroid Build Coastguard Worker /* Recursively reset paused status in the given part. */
mime_unpause(curl_mimepart * part)1905*6236dae4SAndroid Build Coastguard Worker static void mime_unpause(curl_mimepart *part)
1906*6236dae4SAndroid Build Coastguard Worker {
1907*6236dae4SAndroid Build Coastguard Worker if(part) {
1908*6236dae4SAndroid Build Coastguard Worker if(part->lastreadstatus == CURL_READFUNC_PAUSE)
1909*6236dae4SAndroid Build Coastguard Worker part->lastreadstatus = 1; /* Successful read status. */
1910*6236dae4SAndroid Build Coastguard Worker if(part->kind == MIMEKIND_MULTIPART) {
1911*6236dae4SAndroid Build Coastguard Worker curl_mime *mime = (curl_mime *) part->arg;
1912*6236dae4SAndroid Build Coastguard Worker
1913*6236dae4SAndroid Build Coastguard Worker if(mime) {
1914*6236dae4SAndroid Build Coastguard Worker curl_mimepart *subpart;
1915*6236dae4SAndroid Build Coastguard Worker
1916*6236dae4SAndroid Build Coastguard Worker for(subpart = mime->firstpart; subpart; subpart = subpart->nextpart)
1917*6236dae4SAndroid Build Coastguard Worker mime_unpause(subpart);
1918*6236dae4SAndroid Build Coastguard Worker }
1919*6236dae4SAndroid Build Coastguard Worker }
1920*6236dae4SAndroid Build Coastguard Worker }
1921*6236dae4SAndroid Build Coastguard Worker }
1922*6236dae4SAndroid Build Coastguard Worker
1923*6236dae4SAndroid Build Coastguard Worker struct cr_mime_ctx {
1924*6236dae4SAndroid Build Coastguard Worker struct Curl_creader super;
1925*6236dae4SAndroid Build Coastguard Worker curl_mimepart *part;
1926*6236dae4SAndroid Build Coastguard Worker curl_off_t total_len;
1927*6236dae4SAndroid Build Coastguard Worker curl_off_t read_len;
1928*6236dae4SAndroid Build Coastguard Worker CURLcode error_result;
1929*6236dae4SAndroid Build Coastguard Worker BIT(seen_eos);
1930*6236dae4SAndroid Build Coastguard Worker BIT(errored);
1931*6236dae4SAndroid Build Coastguard Worker };
1932*6236dae4SAndroid Build Coastguard Worker
cr_mime_init(struct Curl_easy * data,struct Curl_creader * reader)1933*6236dae4SAndroid Build Coastguard Worker static CURLcode cr_mime_init(struct Curl_easy *data,
1934*6236dae4SAndroid Build Coastguard Worker struct Curl_creader *reader)
1935*6236dae4SAndroid Build Coastguard Worker {
1936*6236dae4SAndroid Build Coastguard Worker struct cr_mime_ctx *ctx = reader->ctx;
1937*6236dae4SAndroid Build Coastguard Worker (void)data;
1938*6236dae4SAndroid Build Coastguard Worker ctx->total_len = -1;
1939*6236dae4SAndroid Build Coastguard Worker ctx->read_len = 0;
1940*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
1941*6236dae4SAndroid Build Coastguard Worker }
1942*6236dae4SAndroid Build Coastguard Worker
1943*6236dae4SAndroid Build Coastguard Worker /* Real client reader to installed client callbacks. */
cr_mime_read(struct Curl_easy * data,struct Curl_creader * reader,char * buf,size_t blen,size_t * pnread,bool * peos)1944*6236dae4SAndroid Build Coastguard Worker static CURLcode cr_mime_read(struct Curl_easy *data,
1945*6236dae4SAndroid Build Coastguard Worker struct Curl_creader *reader,
1946*6236dae4SAndroid Build Coastguard Worker char *buf, size_t blen,
1947*6236dae4SAndroid Build Coastguard Worker size_t *pnread, bool *peos)
1948*6236dae4SAndroid Build Coastguard Worker {
1949*6236dae4SAndroid Build Coastguard Worker struct cr_mime_ctx *ctx = reader->ctx;
1950*6236dae4SAndroid Build Coastguard Worker size_t nread;
1951*6236dae4SAndroid Build Coastguard Worker
1952*6236dae4SAndroid Build Coastguard Worker
1953*6236dae4SAndroid Build Coastguard Worker /* Once we have errored, we will return the same error forever */
1954*6236dae4SAndroid Build Coastguard Worker if(ctx->errored) {
1955*6236dae4SAndroid Build Coastguard Worker CURL_TRC_READ(data, "cr_mime_read(len=%zu) is errored -> %d, eos=0",
1956*6236dae4SAndroid Build Coastguard Worker blen, ctx->error_result);
1957*6236dae4SAndroid Build Coastguard Worker *pnread = 0;
1958*6236dae4SAndroid Build Coastguard Worker *peos = FALSE;
1959*6236dae4SAndroid Build Coastguard Worker return ctx->error_result;
1960*6236dae4SAndroid Build Coastguard Worker }
1961*6236dae4SAndroid Build Coastguard Worker if(ctx->seen_eos) {
1962*6236dae4SAndroid Build Coastguard Worker CURL_TRC_READ(data, "cr_mime_read(len=%zu) seen eos -> 0, eos=1", blen);
1963*6236dae4SAndroid Build Coastguard Worker *pnread = 0;
1964*6236dae4SAndroid Build Coastguard Worker *peos = TRUE;
1965*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
1966*6236dae4SAndroid Build Coastguard Worker }
1967*6236dae4SAndroid Build Coastguard Worker /* respect length limitations */
1968*6236dae4SAndroid Build Coastguard Worker if(ctx->total_len >= 0) {
1969*6236dae4SAndroid Build Coastguard Worker curl_off_t remain = ctx->total_len - ctx->read_len;
1970*6236dae4SAndroid Build Coastguard Worker if(remain <= 0)
1971*6236dae4SAndroid Build Coastguard Worker blen = 0;
1972*6236dae4SAndroid Build Coastguard Worker else if(remain < (curl_off_t)blen)
1973*6236dae4SAndroid Build Coastguard Worker blen = (size_t)remain;
1974*6236dae4SAndroid Build Coastguard Worker }
1975*6236dae4SAndroid Build Coastguard Worker
1976*6236dae4SAndroid Build Coastguard Worker if(blen <= 4) {
1977*6236dae4SAndroid Build Coastguard Worker /* TODO: Curl_mime_read() may go into an infinite loop when reading
1978*6236dae4SAndroid Build Coastguard Worker * such small lengths. Returning 0 bytes read is a fix that only works
1979*6236dae4SAndroid Build Coastguard Worker * as request upload buffers will get flushed eventually and larger
1980*6236dae4SAndroid Build Coastguard Worker * reads will happen again. */
1981*6236dae4SAndroid Build Coastguard Worker CURL_TRC_READ(data, "cr_mime_read(len=%zu), too small, return", blen);
1982*6236dae4SAndroid Build Coastguard Worker *pnread = 0;
1983*6236dae4SAndroid Build Coastguard Worker *peos = FALSE;
1984*6236dae4SAndroid Build Coastguard Worker goto out;
1985*6236dae4SAndroid Build Coastguard Worker }
1986*6236dae4SAndroid Build Coastguard Worker
1987*6236dae4SAndroid Build Coastguard Worker nread = Curl_mime_read(buf, 1, blen, ctx->part);
1988*6236dae4SAndroid Build Coastguard Worker CURL_TRC_READ(data, "cr_mime_read(len=%zu), mime_read() -> %zd",
1989*6236dae4SAndroid Build Coastguard Worker blen, nread);
1990*6236dae4SAndroid Build Coastguard Worker
1991*6236dae4SAndroid Build Coastguard Worker switch(nread) {
1992*6236dae4SAndroid Build Coastguard Worker case 0:
1993*6236dae4SAndroid Build Coastguard Worker if((ctx->total_len >= 0) && (ctx->read_len < ctx->total_len)) {
1994*6236dae4SAndroid Build Coastguard Worker failf(data, "client mime read EOF fail, "
1995*6236dae4SAndroid Build Coastguard Worker "only %"FMT_OFF_T"/%"FMT_OFF_T
1996*6236dae4SAndroid Build Coastguard Worker " of needed bytes read", ctx->read_len, ctx->total_len);
1997*6236dae4SAndroid Build Coastguard Worker return CURLE_READ_ERROR;
1998*6236dae4SAndroid Build Coastguard Worker }
1999*6236dae4SAndroid Build Coastguard Worker *pnread = 0;
2000*6236dae4SAndroid Build Coastguard Worker *peos = TRUE;
2001*6236dae4SAndroid Build Coastguard Worker ctx->seen_eos = TRUE;
2002*6236dae4SAndroid Build Coastguard Worker break;
2003*6236dae4SAndroid Build Coastguard Worker
2004*6236dae4SAndroid Build Coastguard Worker case CURL_READFUNC_ABORT:
2005*6236dae4SAndroid Build Coastguard Worker failf(data, "operation aborted by callback");
2006*6236dae4SAndroid Build Coastguard Worker *pnread = 0;
2007*6236dae4SAndroid Build Coastguard Worker *peos = FALSE;
2008*6236dae4SAndroid Build Coastguard Worker ctx->errored = TRUE;
2009*6236dae4SAndroid Build Coastguard Worker ctx->error_result = CURLE_ABORTED_BY_CALLBACK;
2010*6236dae4SAndroid Build Coastguard Worker return CURLE_ABORTED_BY_CALLBACK;
2011*6236dae4SAndroid Build Coastguard Worker
2012*6236dae4SAndroid Build Coastguard Worker case CURL_READFUNC_PAUSE:
2013*6236dae4SAndroid Build Coastguard Worker /* CURL_READFUNC_PAUSE pauses read callbacks that feed socket writes */
2014*6236dae4SAndroid Build Coastguard Worker CURL_TRC_READ(data, "cr_mime_read(len=%zu), paused by callback", blen);
2015*6236dae4SAndroid Build Coastguard Worker data->req.keepon |= KEEP_SEND_PAUSE; /* mark socket send as paused */
2016*6236dae4SAndroid Build Coastguard Worker *pnread = 0;
2017*6236dae4SAndroid Build Coastguard Worker *peos = FALSE;
2018*6236dae4SAndroid Build Coastguard Worker break; /* nothing was read */
2019*6236dae4SAndroid Build Coastguard Worker
2020*6236dae4SAndroid Build Coastguard Worker case STOP_FILLING:
2021*6236dae4SAndroid Build Coastguard Worker case READ_ERROR:
2022*6236dae4SAndroid Build Coastguard Worker failf(data, "read error getting mime data");
2023*6236dae4SAndroid Build Coastguard Worker *pnread = 0;
2024*6236dae4SAndroid Build Coastguard Worker *peos = FALSE;
2025*6236dae4SAndroid Build Coastguard Worker ctx->errored = TRUE;
2026*6236dae4SAndroid Build Coastguard Worker ctx->error_result = CURLE_READ_ERROR;
2027*6236dae4SAndroid Build Coastguard Worker return CURLE_READ_ERROR;
2028*6236dae4SAndroid Build Coastguard Worker
2029*6236dae4SAndroid Build Coastguard Worker default:
2030*6236dae4SAndroid Build Coastguard Worker if(nread > blen) {
2031*6236dae4SAndroid Build Coastguard Worker /* the read function returned a too large value */
2032*6236dae4SAndroid Build Coastguard Worker failf(data, "read function returned funny value");
2033*6236dae4SAndroid Build Coastguard Worker *pnread = 0;
2034*6236dae4SAndroid Build Coastguard Worker *peos = FALSE;
2035*6236dae4SAndroid Build Coastguard Worker ctx->errored = TRUE;
2036*6236dae4SAndroid Build Coastguard Worker ctx->error_result = CURLE_READ_ERROR;
2037*6236dae4SAndroid Build Coastguard Worker return CURLE_READ_ERROR;
2038*6236dae4SAndroid Build Coastguard Worker }
2039*6236dae4SAndroid Build Coastguard Worker ctx->read_len += nread;
2040*6236dae4SAndroid Build Coastguard Worker if(ctx->total_len >= 0)
2041*6236dae4SAndroid Build Coastguard Worker ctx->seen_eos = (ctx->read_len >= ctx->total_len);
2042*6236dae4SAndroid Build Coastguard Worker *pnread = nread;
2043*6236dae4SAndroid Build Coastguard Worker *peos = ctx->seen_eos;
2044*6236dae4SAndroid Build Coastguard Worker break;
2045*6236dae4SAndroid Build Coastguard Worker }
2046*6236dae4SAndroid Build Coastguard Worker
2047*6236dae4SAndroid Build Coastguard Worker out:
2048*6236dae4SAndroid Build Coastguard Worker CURL_TRC_READ(data, "cr_mime_read(len=%zu, total=%" FMT_OFF_T
2049*6236dae4SAndroid Build Coastguard Worker ", read=%"FMT_OFF_T") -> %d, %zu, %d",
2050*6236dae4SAndroid Build Coastguard Worker blen, ctx->total_len, ctx->read_len, CURLE_OK, *pnread, *peos);
2051*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
2052*6236dae4SAndroid Build Coastguard Worker }
2053*6236dae4SAndroid Build Coastguard Worker
cr_mime_needs_rewind(struct Curl_easy * data,struct Curl_creader * reader)2054*6236dae4SAndroid Build Coastguard Worker static bool cr_mime_needs_rewind(struct Curl_easy *data,
2055*6236dae4SAndroid Build Coastguard Worker struct Curl_creader *reader)
2056*6236dae4SAndroid Build Coastguard Worker {
2057*6236dae4SAndroid Build Coastguard Worker struct cr_mime_ctx *ctx = reader->ctx;
2058*6236dae4SAndroid Build Coastguard Worker (void)data;
2059*6236dae4SAndroid Build Coastguard Worker return ctx->read_len > 0;
2060*6236dae4SAndroid Build Coastguard Worker }
2061*6236dae4SAndroid Build Coastguard Worker
cr_mime_total_length(struct Curl_easy * data,struct Curl_creader * reader)2062*6236dae4SAndroid Build Coastguard Worker static curl_off_t cr_mime_total_length(struct Curl_easy *data,
2063*6236dae4SAndroid Build Coastguard Worker struct Curl_creader *reader)
2064*6236dae4SAndroid Build Coastguard Worker {
2065*6236dae4SAndroid Build Coastguard Worker struct cr_mime_ctx *ctx = reader->ctx;
2066*6236dae4SAndroid Build Coastguard Worker (void)data;
2067*6236dae4SAndroid Build Coastguard Worker return ctx->total_len;
2068*6236dae4SAndroid Build Coastguard Worker }
2069*6236dae4SAndroid Build Coastguard Worker
cr_mime_resume_from(struct Curl_easy * data,struct Curl_creader * reader,curl_off_t offset)2070*6236dae4SAndroid Build Coastguard Worker static CURLcode cr_mime_resume_from(struct Curl_easy *data,
2071*6236dae4SAndroid Build Coastguard Worker struct Curl_creader *reader,
2072*6236dae4SAndroid Build Coastguard Worker curl_off_t offset)
2073*6236dae4SAndroid Build Coastguard Worker {
2074*6236dae4SAndroid Build Coastguard Worker struct cr_mime_ctx *ctx = reader->ctx;
2075*6236dae4SAndroid Build Coastguard Worker
2076*6236dae4SAndroid Build Coastguard Worker if(offset > 0) {
2077*6236dae4SAndroid Build Coastguard Worker curl_off_t passed = 0;
2078*6236dae4SAndroid Build Coastguard Worker
2079*6236dae4SAndroid Build Coastguard Worker do {
2080*6236dae4SAndroid Build Coastguard Worker char scratch[4*1024];
2081*6236dae4SAndroid Build Coastguard Worker size_t readthisamountnow =
2082*6236dae4SAndroid Build Coastguard Worker (offset - passed > (curl_off_t)sizeof(scratch)) ?
2083*6236dae4SAndroid Build Coastguard Worker sizeof(scratch) :
2084*6236dae4SAndroid Build Coastguard Worker curlx_sotouz(offset - passed);
2085*6236dae4SAndroid Build Coastguard Worker size_t nread;
2086*6236dae4SAndroid Build Coastguard Worker
2087*6236dae4SAndroid Build Coastguard Worker nread = Curl_mime_read(scratch, 1, readthisamountnow, ctx->part);
2088*6236dae4SAndroid Build Coastguard Worker passed += (curl_off_t)nread;
2089*6236dae4SAndroid Build Coastguard Worker if((nread == 0) || (nread > readthisamountnow)) {
2090*6236dae4SAndroid Build Coastguard Worker /* this checks for greater-than only to make sure that the
2091*6236dae4SAndroid Build Coastguard Worker CURL_READFUNC_ABORT return code still aborts */
2092*6236dae4SAndroid Build Coastguard Worker failf(data, "Could only read %" FMT_OFF_T
2093*6236dae4SAndroid Build Coastguard Worker " bytes from the mime post", passed);
2094*6236dae4SAndroid Build Coastguard Worker return CURLE_READ_ERROR;
2095*6236dae4SAndroid Build Coastguard Worker }
2096*6236dae4SAndroid Build Coastguard Worker } while(passed < offset);
2097*6236dae4SAndroid Build Coastguard Worker
2098*6236dae4SAndroid Build Coastguard Worker /* now, decrease the size of the read */
2099*6236dae4SAndroid Build Coastguard Worker if(ctx->total_len > 0) {
2100*6236dae4SAndroid Build Coastguard Worker ctx->total_len -= offset;
2101*6236dae4SAndroid Build Coastguard Worker
2102*6236dae4SAndroid Build Coastguard Worker if(ctx->total_len <= 0) {
2103*6236dae4SAndroid Build Coastguard Worker failf(data, "Mime post already completely uploaded");
2104*6236dae4SAndroid Build Coastguard Worker return CURLE_PARTIAL_FILE;
2105*6236dae4SAndroid Build Coastguard Worker }
2106*6236dae4SAndroid Build Coastguard Worker }
2107*6236dae4SAndroid Build Coastguard Worker /* we have passed, proceed as normal */
2108*6236dae4SAndroid Build Coastguard Worker }
2109*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
2110*6236dae4SAndroid Build Coastguard Worker }
2111*6236dae4SAndroid Build Coastguard Worker
cr_mime_rewind(struct Curl_easy * data,struct Curl_creader * reader)2112*6236dae4SAndroid Build Coastguard Worker static CURLcode cr_mime_rewind(struct Curl_easy *data,
2113*6236dae4SAndroid Build Coastguard Worker struct Curl_creader *reader)
2114*6236dae4SAndroid Build Coastguard Worker {
2115*6236dae4SAndroid Build Coastguard Worker struct cr_mime_ctx *ctx = reader->ctx;
2116*6236dae4SAndroid Build Coastguard Worker CURLcode result = mime_rewind(ctx->part);
2117*6236dae4SAndroid Build Coastguard Worker if(result)
2118*6236dae4SAndroid Build Coastguard Worker failf(data, "Cannot rewind mime/post data");
2119*6236dae4SAndroid Build Coastguard Worker return result;
2120*6236dae4SAndroid Build Coastguard Worker }
2121*6236dae4SAndroid Build Coastguard Worker
cr_mime_unpause(struct Curl_easy * data,struct Curl_creader * reader)2122*6236dae4SAndroid Build Coastguard Worker static CURLcode cr_mime_unpause(struct Curl_easy *data,
2123*6236dae4SAndroid Build Coastguard Worker struct Curl_creader *reader)
2124*6236dae4SAndroid Build Coastguard Worker {
2125*6236dae4SAndroid Build Coastguard Worker struct cr_mime_ctx *ctx = reader->ctx;
2126*6236dae4SAndroid Build Coastguard Worker (void)data;
2127*6236dae4SAndroid Build Coastguard Worker mime_unpause(ctx->part);
2128*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
2129*6236dae4SAndroid Build Coastguard Worker }
2130*6236dae4SAndroid Build Coastguard Worker
cr_mime_is_paused(struct Curl_easy * data,struct Curl_creader * reader)2131*6236dae4SAndroid Build Coastguard Worker static bool cr_mime_is_paused(struct Curl_easy *data,
2132*6236dae4SAndroid Build Coastguard Worker struct Curl_creader *reader)
2133*6236dae4SAndroid Build Coastguard Worker {
2134*6236dae4SAndroid Build Coastguard Worker struct cr_mime_ctx *ctx = reader->ctx;
2135*6236dae4SAndroid Build Coastguard Worker (void)data;
2136*6236dae4SAndroid Build Coastguard Worker return (ctx->part && ctx->part->lastreadstatus == CURL_READFUNC_PAUSE);
2137*6236dae4SAndroid Build Coastguard Worker }
2138*6236dae4SAndroid Build Coastguard Worker
2139*6236dae4SAndroid Build Coastguard Worker static const struct Curl_crtype cr_mime = {
2140*6236dae4SAndroid Build Coastguard Worker "cr-mime",
2141*6236dae4SAndroid Build Coastguard Worker cr_mime_init,
2142*6236dae4SAndroid Build Coastguard Worker cr_mime_read,
2143*6236dae4SAndroid Build Coastguard Worker Curl_creader_def_close,
2144*6236dae4SAndroid Build Coastguard Worker cr_mime_needs_rewind,
2145*6236dae4SAndroid Build Coastguard Worker cr_mime_total_length,
2146*6236dae4SAndroid Build Coastguard Worker cr_mime_resume_from,
2147*6236dae4SAndroid Build Coastguard Worker cr_mime_rewind,
2148*6236dae4SAndroid Build Coastguard Worker cr_mime_unpause,
2149*6236dae4SAndroid Build Coastguard Worker cr_mime_is_paused,
2150*6236dae4SAndroid Build Coastguard Worker Curl_creader_def_done,
2151*6236dae4SAndroid Build Coastguard Worker sizeof(struct cr_mime_ctx)
2152*6236dae4SAndroid Build Coastguard Worker };
2153*6236dae4SAndroid Build Coastguard Worker
Curl_creader_set_mime(struct Curl_easy * data,curl_mimepart * part)2154*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_creader_set_mime(struct Curl_easy *data, curl_mimepart *part)
2155*6236dae4SAndroid Build Coastguard Worker {
2156*6236dae4SAndroid Build Coastguard Worker struct Curl_creader *r;
2157*6236dae4SAndroid Build Coastguard Worker struct cr_mime_ctx *ctx;
2158*6236dae4SAndroid Build Coastguard Worker CURLcode result;
2159*6236dae4SAndroid Build Coastguard Worker
2160*6236dae4SAndroid Build Coastguard Worker result = Curl_creader_create(&r, data, &cr_mime, CURL_CR_CLIENT);
2161*6236dae4SAndroid Build Coastguard Worker if(result)
2162*6236dae4SAndroid Build Coastguard Worker return result;
2163*6236dae4SAndroid Build Coastguard Worker ctx = r->ctx;
2164*6236dae4SAndroid Build Coastguard Worker ctx->part = part;
2165*6236dae4SAndroid Build Coastguard Worker /* Make sure we will read the entire mime structure. */
2166*6236dae4SAndroid Build Coastguard Worker result = mime_rewind(ctx->part);
2167*6236dae4SAndroid Build Coastguard Worker if(result) {
2168*6236dae4SAndroid Build Coastguard Worker Curl_creader_free(data, r);
2169*6236dae4SAndroid Build Coastguard Worker return result;
2170*6236dae4SAndroid Build Coastguard Worker }
2171*6236dae4SAndroid Build Coastguard Worker ctx->total_len = mime_size(ctx->part);
2172*6236dae4SAndroid Build Coastguard Worker
2173*6236dae4SAndroid Build Coastguard Worker return Curl_creader_set(data, r);
2174*6236dae4SAndroid Build Coastguard Worker }
2175*6236dae4SAndroid Build Coastguard Worker
2176*6236dae4SAndroid Build Coastguard Worker #else /* !CURL_DISABLE_MIME && (!CURL_DISABLE_HTTP ||
2177*6236dae4SAndroid Build Coastguard Worker !CURL_DISABLE_SMTP || !CURL_DISABLE_IMAP) */
2178*6236dae4SAndroid Build Coastguard Worker
2179*6236dae4SAndroid Build Coastguard Worker /* Mime not compiled in: define stubs for externally-referenced functions. */
curl_mime_init(CURL * easy)2180*6236dae4SAndroid Build Coastguard Worker curl_mime *curl_mime_init(CURL *easy)
2181*6236dae4SAndroid Build Coastguard Worker {
2182*6236dae4SAndroid Build Coastguard Worker (void) easy;
2183*6236dae4SAndroid Build Coastguard Worker return NULL;
2184*6236dae4SAndroid Build Coastguard Worker }
2185*6236dae4SAndroid Build Coastguard Worker
curl_mime_free(curl_mime * mime)2186*6236dae4SAndroid Build Coastguard Worker void curl_mime_free(curl_mime *mime)
2187*6236dae4SAndroid Build Coastguard Worker {
2188*6236dae4SAndroid Build Coastguard Worker (void) mime;
2189*6236dae4SAndroid Build Coastguard Worker }
2190*6236dae4SAndroid Build Coastguard Worker
curl_mime_addpart(curl_mime * mime)2191*6236dae4SAndroid Build Coastguard Worker curl_mimepart *curl_mime_addpart(curl_mime *mime)
2192*6236dae4SAndroid Build Coastguard Worker {
2193*6236dae4SAndroid Build Coastguard Worker (void) mime;
2194*6236dae4SAndroid Build Coastguard Worker return NULL;
2195*6236dae4SAndroid Build Coastguard Worker }
2196*6236dae4SAndroid Build Coastguard Worker
curl_mime_name(curl_mimepart * part,const char * name)2197*6236dae4SAndroid Build Coastguard Worker CURLcode curl_mime_name(curl_mimepart *part, const char *name)
2198*6236dae4SAndroid Build Coastguard Worker {
2199*6236dae4SAndroid Build Coastguard Worker (void) part;
2200*6236dae4SAndroid Build Coastguard Worker (void) name;
2201*6236dae4SAndroid Build Coastguard Worker return CURLE_NOT_BUILT_IN;
2202*6236dae4SAndroid Build Coastguard Worker }
2203*6236dae4SAndroid Build Coastguard Worker
curl_mime_filename(curl_mimepart * part,const char * filename)2204*6236dae4SAndroid Build Coastguard Worker CURLcode curl_mime_filename(curl_mimepart *part, const char *filename)
2205*6236dae4SAndroid Build Coastguard Worker {
2206*6236dae4SAndroid Build Coastguard Worker (void) part;
2207*6236dae4SAndroid Build Coastguard Worker (void) filename;
2208*6236dae4SAndroid Build Coastguard Worker return CURLE_NOT_BUILT_IN;
2209*6236dae4SAndroid Build Coastguard Worker }
2210*6236dae4SAndroid Build Coastguard Worker
curl_mime_type(curl_mimepart * part,const char * mimetype)2211*6236dae4SAndroid Build Coastguard Worker CURLcode curl_mime_type(curl_mimepart *part, const char *mimetype)
2212*6236dae4SAndroid Build Coastguard Worker {
2213*6236dae4SAndroid Build Coastguard Worker (void) part;
2214*6236dae4SAndroid Build Coastguard Worker (void) mimetype;
2215*6236dae4SAndroid Build Coastguard Worker return CURLE_NOT_BUILT_IN;
2216*6236dae4SAndroid Build Coastguard Worker }
2217*6236dae4SAndroid Build Coastguard Worker
curl_mime_encoder(curl_mimepart * part,const char * encoding)2218*6236dae4SAndroid Build Coastguard Worker CURLcode curl_mime_encoder(curl_mimepart *part, const char *encoding)
2219*6236dae4SAndroid Build Coastguard Worker {
2220*6236dae4SAndroid Build Coastguard Worker (void) part;
2221*6236dae4SAndroid Build Coastguard Worker (void) encoding;
2222*6236dae4SAndroid Build Coastguard Worker return CURLE_NOT_BUILT_IN;
2223*6236dae4SAndroid Build Coastguard Worker }
2224*6236dae4SAndroid Build Coastguard Worker
curl_mime_data(curl_mimepart * part,const char * data,size_t datasize)2225*6236dae4SAndroid Build Coastguard Worker CURLcode curl_mime_data(curl_mimepart *part,
2226*6236dae4SAndroid Build Coastguard Worker const char *data, size_t datasize)
2227*6236dae4SAndroid Build Coastguard Worker {
2228*6236dae4SAndroid Build Coastguard Worker (void) part;
2229*6236dae4SAndroid Build Coastguard Worker (void) data;
2230*6236dae4SAndroid Build Coastguard Worker (void) datasize;
2231*6236dae4SAndroid Build Coastguard Worker return CURLE_NOT_BUILT_IN;
2232*6236dae4SAndroid Build Coastguard Worker }
2233*6236dae4SAndroid Build Coastguard Worker
curl_mime_filedata(curl_mimepart * part,const char * filename)2234*6236dae4SAndroid Build Coastguard Worker CURLcode curl_mime_filedata(curl_mimepart *part, const char *filename)
2235*6236dae4SAndroid Build Coastguard Worker {
2236*6236dae4SAndroid Build Coastguard Worker (void) part;
2237*6236dae4SAndroid Build Coastguard Worker (void) filename;
2238*6236dae4SAndroid Build Coastguard Worker return CURLE_NOT_BUILT_IN;
2239*6236dae4SAndroid Build Coastguard Worker }
2240*6236dae4SAndroid Build Coastguard Worker
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)2241*6236dae4SAndroid Build Coastguard Worker CURLcode curl_mime_data_cb(curl_mimepart *part,
2242*6236dae4SAndroid Build Coastguard Worker curl_off_t datasize,
2243*6236dae4SAndroid Build Coastguard Worker curl_read_callback readfunc,
2244*6236dae4SAndroid Build Coastguard Worker curl_seek_callback seekfunc,
2245*6236dae4SAndroid Build Coastguard Worker curl_free_callback freefunc,
2246*6236dae4SAndroid Build Coastguard Worker void *arg)
2247*6236dae4SAndroid Build Coastguard Worker {
2248*6236dae4SAndroid Build Coastguard Worker (void) part;
2249*6236dae4SAndroid Build Coastguard Worker (void) datasize;
2250*6236dae4SAndroid Build Coastguard Worker (void) readfunc;
2251*6236dae4SAndroid Build Coastguard Worker (void) seekfunc;
2252*6236dae4SAndroid Build Coastguard Worker (void) freefunc;
2253*6236dae4SAndroid Build Coastguard Worker (void) arg;
2254*6236dae4SAndroid Build Coastguard Worker return CURLE_NOT_BUILT_IN;
2255*6236dae4SAndroid Build Coastguard Worker }
2256*6236dae4SAndroid Build Coastguard Worker
curl_mime_subparts(curl_mimepart * part,curl_mime * subparts)2257*6236dae4SAndroid Build Coastguard Worker CURLcode curl_mime_subparts(curl_mimepart *part, curl_mime *subparts)
2258*6236dae4SAndroid Build Coastguard Worker {
2259*6236dae4SAndroid Build Coastguard Worker (void) part;
2260*6236dae4SAndroid Build Coastguard Worker (void) subparts;
2261*6236dae4SAndroid Build Coastguard Worker return CURLE_NOT_BUILT_IN;
2262*6236dae4SAndroid Build Coastguard Worker }
2263*6236dae4SAndroid Build Coastguard Worker
curl_mime_headers(curl_mimepart * part,struct curl_slist * headers,int take_ownership)2264*6236dae4SAndroid Build Coastguard Worker CURLcode curl_mime_headers(curl_mimepart *part,
2265*6236dae4SAndroid Build Coastguard Worker struct curl_slist *headers, int take_ownership)
2266*6236dae4SAndroid Build Coastguard Worker {
2267*6236dae4SAndroid Build Coastguard Worker (void) part;
2268*6236dae4SAndroid Build Coastguard Worker (void) headers;
2269*6236dae4SAndroid Build Coastguard Worker (void) take_ownership;
2270*6236dae4SAndroid Build Coastguard Worker return CURLE_NOT_BUILT_IN;
2271*6236dae4SAndroid Build Coastguard Worker }
2272*6236dae4SAndroid Build Coastguard Worker
Curl_mime_add_header(struct curl_slist ** slp,const char * fmt,...)2273*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_mime_add_header(struct curl_slist **slp, const char *fmt, ...)
2274*6236dae4SAndroid Build Coastguard Worker {
2275*6236dae4SAndroid Build Coastguard Worker (void)slp;
2276*6236dae4SAndroid Build Coastguard Worker (void)fmt;
2277*6236dae4SAndroid Build Coastguard Worker return CURLE_NOT_BUILT_IN;
2278*6236dae4SAndroid Build Coastguard Worker }
2279*6236dae4SAndroid Build Coastguard Worker
2280*6236dae4SAndroid Build Coastguard Worker #endif /* if disabled */
2281