141 const unsigned char *body,
143 const char *content_type,
144 const char *field_name,
147 const unsigned char **out_content_start,
148 size_t *out_content_len
150 char *boundary = NULL;
151 char *delimiter = NULL;
152 char *delimiter_crlf = NULL;
153 char *delimiter_lf = NULL;
154 const unsigned char *cursor = NULL;
155 size_t delimiter_len = 0;
158 if (out_text != NULL) *out_text = NULL;
159 if (out_filename != NULL) *out_filename = NULL;
160 if (out_content_start != NULL) *out_content_start = NULL;
161 if (out_content_len != NULL) *out_content_len = 0;
163 if (body == NULL || body_len == 0 || content_type == NULL || field_name == NULL || field_name[0] ==
'\0') {
168 if (boundary == NULL || boundary[0] ==
'\0') {
173 delimiter_len = strlen(boundary) + 2;
174 delimiter = (
char *)malloc(delimiter_len + 1);
175 delimiter_crlf = (
char *)malloc(delimiter_len + 3);
176 delimiter_lf = (
char *)malloc(delimiter_len + 2);
177 if (delimiter == NULL || delimiter_crlf == NULL || delimiter_lf == NULL) {
178 free(boundary); free(delimiter); free(delimiter_crlf); free(delimiter_lf);
181 snprintf(delimiter, delimiter_len + 1,
"--%s", boundary);
182 snprintf(delimiter_crlf, delimiter_len + 3,
"\r\n--%s", boundary);
183 snprintf(delimiter_lf, delimiter_len + 2,
"\n--%s", boundary);
185 cursor =
multipart_memmem(body, body_len, (
const unsigned char *)delimiter, delimiter_len);
186 while (cursor != NULL && (
size_t)(cursor - body) + delimiter_len <= body_len) {
187 const unsigned char *part_cursor = cursor + delimiter_len;
188 const unsigned char *header_end = NULL;
189 const unsigned char *content_start = NULL;
190 const unsigned char *next_marker = NULL;
191 size_t header_sep_len = 0;
192 size_t headers_len = 0;
193 size_t content_len = 0;
194 char *headers_text = NULL;
195 char *part_name = NULL;
196 char *filename = NULL;
199 if ((
size_t)(part_cursor - body) + 2 <= body_len && part_cursor[0] ==
'-' && part_cursor[1] ==
'-') {
204 if ((
size_t)(part_cursor - body) + 2 <= body_len && part_cursor[0] ==
'\r' && part_cursor[1] ==
'\n') {
206 }
else if ((
size_t)(part_cursor - body) + 1 <= body_len && part_cursor[0] ==
'\n') {
212 const unsigned char *next_crlf =
multipart_memmem(part_cursor, body_len - (
size_t)(part_cursor - body), (
const unsigned char *)
"\r\n\r\n", 4);
213 const unsigned char *next_lf =
multipart_memmem(part_cursor, body_len - (
size_t)(part_cursor - body), (
const unsigned char *)
"\n\n", 2);
214 if (next_crlf != NULL && (next_lf == NULL || next_crlf <= next_lf)) {
215 header_end = next_crlf;
217 }
else if (next_lf != NULL) {
218 header_end = next_lf;
225 headers_len = (size_t)(header_end - part_cursor);
229 content_start = header_end + header_sep_len;
233 const unsigned char *next_crlf =
multipart_memmem(content_start, body_len - (
size_t)(content_start - body), (
const unsigned char *)delimiter_crlf, delimiter_len + 2);
234 const unsigned char *next_lf =
multipart_memmem(content_start, body_len - (
size_t)(content_start - body), (
const unsigned char *)delimiter_lf, delimiter_len + 1);
235 if (next_crlf != NULL && (next_lf == NULL || next_crlf <= next_lf)) {
236 next_marker = next_crlf;
237 }
else if (next_lf != NULL) {
238 next_marker = next_lf;
240 next_marker = body + body_len;
244 content_len = (size_t)(next_marker - content_start);
246 if (part_name != NULL && strcmp(part_name, field_name) == 0) {
247 if (out_text != NULL) {
250 if (out_filename != NULL && filename != NULL) {
251 *out_filename = strdup(filename);
253 if (out_content_start != NULL) {
254 *out_content_start = content_start;
256 if (out_content_len != NULL) {
257 *out_content_len = content_len;
270 if (next_marker >= body + body_len) {
273 cursor = next_marker + (next_marker[0] ==
'\r' ? 2 : 1);
274 cursor =
multipart_memmem(cursor, body_len - (
size_t)(cursor - body), (
const unsigned char *)delimiter, delimiter_len);
279 free(delimiter_crlf);
307 const unsigned char *body,
309 const char *content_type,
310 const char *field_name,
311 const char *output_path
313 const unsigned char *content_start = NULL;
314 size_t content_len = 0;
318 if (output_path == NULL || output_path[0] ==
'\0') {
326 if (content_start == NULL || content_len == 0) {
330 fp = fopen(output_path,
"wb");
335 written = fwrite(content_start, 1, content_len, fp);
337 return written == content_len ? 0 : 74;
int native_dynamic_multipart_find_part(const unsigned char *body, size_t body_len, const char *content_type, const char *field_name, char **out_text, char **out_filename, const unsigned char **out_content_start, size_t *out_content_len)
Finds a named part in a multipart request body.