From f028667131025100a0caeb59a8ae8a2bb8722239 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 30 Jul 2025 14:32:36 +0200 Subject: [PATCH] test757: MIME parts reused as a child part, using data_cb An attempt to reproduce #18070. That turned out to not be a bug, but the test is still a good one. Based on test695 Closes #18101 --- tests/data/Makefile.am | 2 +- tests/data/test757 | 78 +++++++++++++++++++++ tests/libtest/Makefile.inc | 1 + tests/libtest/lib757.c | 135 +++++++++++++++++++++++++++++++++++++ 4 files changed, 215 insertions(+), 1 deletion(-) create mode 100644 tests/data/test757 create mode 100644 tests/libtest/lib757.c diff --git a/tests/data/Makefile.am b/tests/data/Makefile.am index a0a7879660..4fda5f8178 100644 --- a/tests/data/Makefile.am +++ b/tests/data/Makefile.am @@ -108,7 +108,7 @@ test718 test719 test720 test721 test722 test723 test724 test725 test726 \ test727 test728 test729 test730 test731 test732 test733 test734 test735 \ test736 test737 test738 test739 test740 test741 test742 test743 test744 \ test745 test746 test747 test748 test749 test750 test751 test752 test753 \ -test754 test755 test756 \ +test754 test755 test756 test757 \ test780 test781 test782 test783 test784 test785 test786 test787 test788 \ test789 test790 test791 test792 test793 \ \ diff --git a/tests/data/test757 b/tests/data/test757 new file mode 100644 index 0000000000..9cf9b2c3b1 --- /dev/null +++ b/tests/data/test757 @@ -0,0 +1,78 @@ + + + +MIME + + +# Server-side + + +HTTP/1.0 200 OK swsclose +Date: Tue, 09 Nov 2010 14:49:00 GMT +Server: test-server/fake + +blablabla + + + + +# Client-side + + +Mime + + +http + + +lib%TESTNUMBER + + + +MIME parts reused as a child part, using data_cb + + +http://%HOSTIP:%HTTPPORT/we/want/%TESTNUMBER + + + +# Verify data after the test has been "shot" + + +s/^--------------------------[A-Za-z0-9]*/------------------------------/ +s/boundary=------------------------[A-Za-z0-9]*/boundary=----------------------------/ + + +POST /we/want/%TESTNUMBER HTTP/1.1 +Host: %HOSTIP:%HTTPPORT +Accept: */* +Content-Length: 200 +Content-Type: multipart/form-data; boundary=---------------------------- + +------------------------------ +Content-Disposition: form-data; name="data" +Content-Type: text/html + +fun-times +-------------------------------- +POST /we/want/%TESTNUMBER HTTP/1.1 +Host: %HOSTIP:%HTTPPORT +Accept: */* +Content-Length: 427 +Content-Type: multipart/form-data; boundary=---------------------------- + +------------------------------ +Content-Disposition: form-data +Content-Type: multipart/mixed; boundary=---------------------------- + +------------------------------ +Content-Disposition: attachment; name="data" +Content-Type: text/html + +fun-times +-------------------------------- + +-------------------------------- + + + diff --git a/tests/libtest/Makefile.inc b/tests/libtest/Makefile.inc index f30010bd86..770184f713 100644 --- a/tests/libtest/Makefile.inc +++ b/tests/libtest/Makefile.inc @@ -72,6 +72,7 @@ TESTS_C = \ lib670.c lib674.c lib676.c lib677.c lib678.c \ lib694.c lib695.c \ lib751.c lib753.c \ + lib757.c \ lib1156.c \ lib1301.c lib1308.c \ lib1485.c \ diff --git a/tests/libtest/lib757.c b/tests/libtest/lib757.c new file mode 100644 index 0000000000..632818f946 --- /dev/null +++ b/tests/libtest/lib757.c @@ -0,0 +1,135 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + * SPDX-License-Identifier: curl + * + ***************************************************************************/ +#include "first.h" + +#include "memdebug.h" + +/* write callback that does nothing */ +static size_t write_757(char *ptr, size_t size, size_t nmemb, void *userdata) +{ + (void)ptr; + (void)userdata; + return size * nmemb; +} + +#define DATA757 "fun-times" +#define DATALEN (sizeof(DATA757) - 1) + +static size_t read_757(char *buffer, size_t size, size_t nitems, void *arg) +{ + (void)arg; + if((size * nitems) >= DATALEN) { + memcpy(buffer, DATA757, DATALEN); + return DATALEN; + } + return 0; +} + +static int seek_757(void *arg, curl_off_t offset, int origin) +{ + (void)arg; + (void)offset; + (void)origin; + return CURL_SEEKFUNC_OK; +} + +static CURLcode test_lib757(const char *URL) +{ + CURL *curl = NULL; + curl_mime *mime1 = NULL; + curl_mime *mime2 = NULL; + curl_mimepart *part; + CURLcode res = TEST_ERR_FAILURE; + + /* + * Check proper rewind when reusing a mime structure. + */ + + if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) { + curl_mfprintf(stderr, "curl_global_init() failed\n"); + return TEST_ERR_MAJOR_BAD; + } + + curl = curl_easy_init(); + + /* First set the URL that is about to receive our POST. */ + test_setopt(curl, CURLOPT_URL, URL); + + /* get verbose debug output please */ + test_setopt(curl, CURLOPT_VERBOSE, 1L); + + /* Do not write anything. */ + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_757); + + /* Build the first mime structure. */ + mime1 = curl_mime_init(curl); + part = curl_mime_addpart(mime1); + curl_mime_data_cb(part, DATALEN, read_757, seek_757, NULL, NULL); + curl_mime_type(part, "text/html"); + curl_mime_name(part, "data"); + + /* Use first mime structure as top level MIME POST. */ + curl_easy_setopt(curl, CURLOPT_MIMEPOST, mime1); + + /* Perform the request, res gets the return code */ + res = curl_easy_perform(curl); + + /* Check for errors */ + if(res != CURLE_OK) + curl_mfprintf(stderr, "curl_easy_perform() 1 failed: %s\n", + curl_easy_strerror(res)); + else { + /* phase two, create a mime struct using the mime1 handle */ + mime2 = curl_mime_init(curl); + part = curl_mime_addpart(mime2); + + /* use the new mime setup */ + curl_easy_setopt(curl, CURLOPT_MIMEPOST, mime2); + + /* Reuse previous mime structure as a child. */ + res = curl_mime_subparts(part, mime1); + + if(res != CURLE_OK) + curl_mfprintf(stderr, "curl_mime_subparts() failed: %sn", + curl_easy_strerror(res)); + else { + mime1 = NULL; + + /* Perform the request, res gets the return code */ + res = curl_easy_perform(curl); + + /* Check for errors */ + if(res != CURLE_OK) + curl_mfprintf(stderr, "curl_easy_perform() 2 failed: %s\n", + curl_easy_strerror(res)); + } + } + +test_cleanup: + curl_easy_cleanup(curl); + curl_mime_free(mime1); + curl_mime_free(mime2); + curl_global_cleanup(); + return res; +} -- 2.47.2