1 /*************************************************************************** 2 * _ _ ____ _ 3 * Project ___| | | | _ \| | 4 * / __| | | | |_) | | 5 * | (__| |_| | _ <| |___ 6 * \___|\___/|_| \_\_____| 7 * 8 * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel (at) haxx.se>, et al. 9 * 10 * This software is licensed as described in the file COPYING, which 11 * you should have received as part of this distribution. The terms 12 * are also available at https://curl.haxx.se/docs/copyright.html. 13 * 14 * You may opt to use, copy, modify, merge, publish, distribute and/or sell 15 * copies of the Software, and permit persons to whom the Software is 16 * furnished to do so, under the terms of the COPYING file. 17 * 18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 19 * KIND, either express or implied. 20 * 21 ***************************************************************************/ 22 #include "test.h" 23 24 #include "memdebug.h" 25 26 static char data[]= 27 #ifdef CURL_DOES_CONVERSIONS 28 /* ASCII representation with escape sequences for non-ASCII platforms */ 29 "\x74\x68\x69\x73\x20\x69\x73\x20\x77\x68\x61\x74\x20\x77\x65\x20\x70" 30 "\x6f\x73\x74\x20\x74\x6f\x20\x74\x68\x65\x20\x73\x69\x6c\x6c\x79\x20" 31 "\x77\x65\x62\x20\x73\x65\x72\x76\x65\x72\x0a"; 32 #else 33 "this is what we post to the silly web server\n"; 34 #endif 35 36 struct WriteThis { 37 char *readptr; 38 curl_off_t sizeleft; 39 int freecount; 40 }; 41 42 static void free_callback(void *userp) 43 { 44 struct WriteThis *pooh = (struct WriteThis *) userp; 45 46 pooh->freecount++; 47 } 48 49 static size_t read_callback(char *ptr, size_t size, size_t nmemb, void *userp) 50 { 51 struct WriteThis *pooh = (struct WriteThis *)userp; 52 int eof = !*pooh->readptr; 53 54 if(size*nmemb < 1) 55 return 0; 56 57 eof = pooh->sizeleft <= 0; 58 if(!eof) 59 pooh->sizeleft--; 60 61 if(!eof) { 62 *ptr = *pooh->readptr; /* copy one single byte */ 63 pooh->readptr++; /* advance pointer */ 64 return 1; /* we return 1 byte at a time! */ 65 } 66 67 return 0; /* no more data left to deliver */ 68 } 69 70 int test(char *URL) 71 { 72 CURL *easy = NULL; 73 CURL *easy2 = NULL; 74 curl_mime *mime = NULL; 75 curl_mimepart *part; 76 struct curl_slist *hdrs = NULL; 77 CURLcode result; 78 int res = TEST_ERR_FAILURE; 79 struct WriteThis pooh; 80 81 /* 82 * Check proper copy/release of mime post data bound to a duplicated 83 * easy handle. 84 */ 85 86 if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) { 87 fprintf(stderr, "curl_global_init() failed\n"); 88 return TEST_ERR_MAJOR_BAD; 89 } 90 91 easy = curl_easy_init(); 92 93 /* First set the URL that is about to receive our POST. */ 94 test_setopt(easy, CURLOPT_URL, URL); 95 96 /* get verbose debug output please */ 97 test_setopt(easy, CURLOPT_VERBOSE, 1L); 98 99 /* include headers in the output */ 100 test_setopt(easy, CURLOPT_HEADER, 1L); 101 102 /* Prepare the callback structure. */ 103 pooh.readptr = data; 104 pooh.sizeleft = (curl_off_t) strlen(data); 105 pooh.freecount = 0; 106 107 /* Build the mime tree. */ 108 mime = curl_mime_init(easy); 109 part = curl_mime_addpart(mime); 110 curl_mime_data(part, "hello", CURL_ZERO_TERMINATED); 111 curl_mime_name(part, "greeting"); 112 curl_mime_type(part, "application/X-Greeting"); 113 curl_mime_encoder(part, "base64"); 114 hdrs = curl_slist_append(hdrs, "X-Test-Number: 654"); 115 curl_mime_headers(part, hdrs, TRUE); 116 part = curl_mime_addpart(mime); 117 curl_mime_filedata(part, "log/file654.txt"); 118 part = curl_mime_addpart(mime); 119 curl_mime_data_cb(part, (curl_off_t) -1, read_callback, NULL, free_callback, 120 &pooh); 121 122 /* Bind mime data to its easy handle. */ 123 test_setopt(easy, CURLOPT_MIMEPOST, mime); 124 125 /* Duplicate the handle. */ 126 easy2 = curl_easy_duphandle(easy); 127 if(!easy2) { 128 fprintf(stderr, "curl_easy_duphandle() failed\n"); 129 res = TEST_ERR_FAILURE; 130 goto test_cleanup; 131 } 132 133 /* Now free the mime structure: it should unbind it from the first 134 easy handle. */ 135 curl_mime_free(mime); 136 mime = NULL; /* Already cleaned up. */ 137 138 /* Perform on the first handle: should not send any data. */ 139 result = curl_easy_perform(easy); 140 if(result) { 141 fprintf(stderr, "curl_easy_perform(original) failed\n"); 142 res = (int) result; 143 goto test_cleanup; 144 } 145 146 /* Perform on the second handle: if the bound mime structure has not been 147 duplicated properly, it should cause a valgrind error. */ 148 result = curl_easy_perform(easy2); 149 if(result) { 150 fprintf(stderr, "curl_easy_perform(duplicated) failed\n"); 151 res = (int) result; 152 goto test_cleanup; 153 } 154 155 /* Free the duplicated handle: it should call free_callback again. 156 If the mime copy was bad or not automatically released, valgrind 157 will signal it. */ 158 curl_easy_cleanup(easy2); 159 easy2 = NULL; /* Already cleaned up. */ 160 161 if(pooh.freecount != 2) { 162 fprintf(stderr, "free_callback() called %d times instead of 2\n", 163 pooh.freecount); 164 res = TEST_ERR_FAILURE; 165 goto test_cleanup; 166 } 167 168 test_cleanup: 169 curl_easy_cleanup(easy); 170 curl_easy_cleanup(easy2); 171 curl_mime_free(mime); 172 curl_global_cleanup(); 173 return res; 174 } 175