113498266Sopenharmony_ci/*************************************************************************** 213498266Sopenharmony_ci * _ _ ____ _ 313498266Sopenharmony_ci * Project ___| | | | _ \| | 413498266Sopenharmony_ci * / __| | | | |_) | | 513498266Sopenharmony_ci * | (__| |_| | _ <| |___ 613498266Sopenharmony_ci * \___|\___/|_| \_\_____| 713498266Sopenharmony_ci * 813498266Sopenharmony_ci * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al. 913498266Sopenharmony_ci * 1013498266Sopenharmony_ci * This software is licensed as described in the file COPYING, which 1113498266Sopenharmony_ci * you should have received as part of this distribution. The terms 1213498266Sopenharmony_ci * are also available at https://curl.se/docs/copyright.html. 1313498266Sopenharmony_ci * 1413498266Sopenharmony_ci * You may opt to use, copy, modify, merge, publish, distribute and/or sell 1513498266Sopenharmony_ci * copies of the Software, and permit persons to whom the Software is 1613498266Sopenharmony_ci * furnished to do so, under the terms of the COPYING file. 1713498266Sopenharmony_ci * 1813498266Sopenharmony_ci * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 1913498266Sopenharmony_ci * KIND, either express or implied. 2013498266Sopenharmony_ci * 2113498266Sopenharmony_ci * SPDX-License-Identifier: curl 2213498266Sopenharmony_ci * 2313498266Sopenharmony_ci ***************************************************************************/ 2413498266Sopenharmony_ci#include "tool_setup.h" 2513498266Sopenharmony_ci 2613498266Sopenharmony_ci#ifdef HAVE_FCNTL_H 2713498266Sopenharmony_ci# include <fcntl.h> 2813498266Sopenharmony_ci#endif 2913498266Sopenharmony_ci 3013498266Sopenharmony_ci#ifdef HAVE_LOCALE_H 3113498266Sopenharmony_ci# include <locale.h> 3213498266Sopenharmony_ci#endif 3313498266Sopenharmony_ci 3413498266Sopenharmony_ci#ifdef HAVE_SYS_SELECT_H 3513498266Sopenharmony_ci# include <sys/select.h> 3613498266Sopenharmony_ci#elif defined(HAVE_UNISTD_H) 3713498266Sopenharmony_ci# include <unistd.h> 3813498266Sopenharmony_ci#endif 3913498266Sopenharmony_ci 4013498266Sopenharmony_ci#ifdef __VMS 4113498266Sopenharmony_ci# include <fabdef.h> 4213498266Sopenharmony_ci#endif 4313498266Sopenharmony_ci 4413498266Sopenharmony_ci#ifdef __AMIGA__ 4513498266Sopenharmony_ci# include <proto/dos.h> 4613498266Sopenharmony_ci#endif 4713498266Sopenharmony_ci 4813498266Sopenharmony_ci#define ENABLE_CURLX_PRINTF 4913498266Sopenharmony_ci/* use our own printf() functions */ 5013498266Sopenharmony_ci#include "curlx.h" 5113498266Sopenharmony_ci 5213498266Sopenharmony_ci#include "tool_binmode.h" 5313498266Sopenharmony_ci#include "tool_cfgable.h" 5413498266Sopenharmony_ci#include "tool_cb_dbg.h" 5513498266Sopenharmony_ci#include "tool_cb_hdr.h" 5613498266Sopenharmony_ci#include "tool_cb_prg.h" 5713498266Sopenharmony_ci#include "tool_cb_rea.h" 5813498266Sopenharmony_ci#include "tool_cb_see.h" 5913498266Sopenharmony_ci#include "tool_cb_wrt.h" 6013498266Sopenharmony_ci#include "tool_dirhie.h" 6113498266Sopenharmony_ci#include "tool_doswin.h" 6213498266Sopenharmony_ci#include "tool_easysrc.h" 6313498266Sopenharmony_ci#include "tool_filetime.h" 6413498266Sopenharmony_ci#include "tool_getparam.h" 6513498266Sopenharmony_ci#include "tool_helpers.h" 6613498266Sopenharmony_ci#include "tool_findfile.h" 6713498266Sopenharmony_ci#include "tool_libinfo.h" 6813498266Sopenharmony_ci#include "tool_main.h" 6913498266Sopenharmony_ci#include "tool_msgs.h" 7013498266Sopenharmony_ci#include "tool_operate.h" 7113498266Sopenharmony_ci#include "tool_operhlp.h" 7213498266Sopenharmony_ci#include "tool_paramhlp.h" 7313498266Sopenharmony_ci#include "tool_parsecfg.h" 7413498266Sopenharmony_ci#include "tool_setopt.h" 7513498266Sopenharmony_ci#include "tool_sleep.h" 7613498266Sopenharmony_ci#include "tool_urlglob.h" 7713498266Sopenharmony_ci#include "tool_util.h" 7813498266Sopenharmony_ci#include "tool_writeout.h" 7913498266Sopenharmony_ci#include "tool_xattr.h" 8013498266Sopenharmony_ci#include "tool_vms.h" 8113498266Sopenharmony_ci#include "tool_help.h" 8213498266Sopenharmony_ci#include "tool_hugehelp.h" 8313498266Sopenharmony_ci#include "tool_progress.h" 8413498266Sopenharmony_ci#include "tool_ipfs.h" 8513498266Sopenharmony_ci#include "dynbuf.h" 8613498266Sopenharmony_ci 8713498266Sopenharmony_ci#include "memdebug.h" /* keep this as LAST include */ 8813498266Sopenharmony_ci 8913498266Sopenharmony_ci#ifdef CURLDEBUG 9013498266Sopenharmony_ci/* libcurl's debug builds provide an extra function */ 9113498266Sopenharmony_ciCURLcode curl_easy_perform_ev(CURL *easy); 9213498266Sopenharmony_ci#endif 9313498266Sopenharmony_ci 9413498266Sopenharmony_ci#ifndef O_BINARY 9513498266Sopenharmony_ci/* since O_BINARY as used in bitmasks, setting it to zero makes it usable in 9613498266Sopenharmony_ci source code but yet it doesn't ruin anything */ 9713498266Sopenharmony_ci# define O_BINARY 0 9813498266Sopenharmony_ci#endif 9913498266Sopenharmony_ci 10013498266Sopenharmony_ci#define CURL_CA_CERT_ERRORMSG \ 10113498266Sopenharmony_ci "More details here: https://curl.se/docs/sslcerts.html\n\n" \ 10213498266Sopenharmony_ci "curl failed to verify the legitimacy of the server and therefore " \ 10313498266Sopenharmony_ci "could not\nestablish a secure connection to it. To learn more about " \ 10413498266Sopenharmony_ci "this situation and\nhow to fix it, please visit the web page mentioned " \ 10513498266Sopenharmony_ci "above.\n" 10613498266Sopenharmony_ci 10713498266Sopenharmony_cistatic CURLcode single_transfer(struct GlobalConfig *global, 10813498266Sopenharmony_ci struct OperationConfig *config, 10913498266Sopenharmony_ci CURLSH *share, 11013498266Sopenharmony_ci bool capath_from_env, 11113498266Sopenharmony_ci bool *added); 11213498266Sopenharmony_cistatic CURLcode create_transfer(struct GlobalConfig *global, 11313498266Sopenharmony_ci CURLSH *share, 11413498266Sopenharmony_ci bool *added); 11513498266Sopenharmony_ci 11613498266Sopenharmony_cistatic bool is_fatal_error(CURLcode code) 11713498266Sopenharmony_ci{ 11813498266Sopenharmony_ci switch(code) { 11913498266Sopenharmony_ci case CURLE_FAILED_INIT: 12013498266Sopenharmony_ci case CURLE_OUT_OF_MEMORY: 12113498266Sopenharmony_ci case CURLE_UNKNOWN_OPTION: 12213498266Sopenharmony_ci case CURLE_FUNCTION_NOT_FOUND: 12313498266Sopenharmony_ci case CURLE_BAD_FUNCTION_ARGUMENT: 12413498266Sopenharmony_ci /* critical error */ 12513498266Sopenharmony_ci return TRUE; 12613498266Sopenharmony_ci default: 12713498266Sopenharmony_ci break; 12813498266Sopenharmony_ci } 12913498266Sopenharmony_ci 13013498266Sopenharmony_ci /* no error or not critical */ 13113498266Sopenharmony_ci return FALSE; 13213498266Sopenharmony_ci} 13313498266Sopenharmony_ci 13413498266Sopenharmony_ci/* 13513498266Sopenharmony_ci * Check if a given string is a PKCS#11 URI 13613498266Sopenharmony_ci */ 13713498266Sopenharmony_cistatic bool is_pkcs11_uri(const char *string) 13813498266Sopenharmony_ci{ 13913498266Sopenharmony_ci if(curl_strnequal(string, "pkcs11:", 7)) { 14013498266Sopenharmony_ci return TRUE; 14113498266Sopenharmony_ci } 14213498266Sopenharmony_ci else { 14313498266Sopenharmony_ci return FALSE; 14413498266Sopenharmony_ci } 14513498266Sopenharmony_ci} 14613498266Sopenharmony_ci 14713498266Sopenharmony_ci#ifdef __VMS 14813498266Sopenharmony_ci/* 14913498266Sopenharmony_ci * get_vms_file_size does what it takes to get the real size of the file 15013498266Sopenharmony_ci * 15113498266Sopenharmony_ci * For fixed files, find out the size of the EOF block and adjust. 15213498266Sopenharmony_ci * 15313498266Sopenharmony_ci * For all others, have to read the entire file in, discarding the contents. 15413498266Sopenharmony_ci * Most posted text files will be small, and binary files like zlib archives 15513498266Sopenharmony_ci * and CD/DVD images should be either a STREAM_LF format or a fixed format. 15613498266Sopenharmony_ci * 15713498266Sopenharmony_ci */ 15813498266Sopenharmony_cistatic curl_off_t vms_realfilesize(const char *name, 15913498266Sopenharmony_ci const struct_stat *stat_buf) 16013498266Sopenharmony_ci{ 16113498266Sopenharmony_ci char buffer[8192]; 16213498266Sopenharmony_ci curl_off_t count; 16313498266Sopenharmony_ci int ret_stat; 16413498266Sopenharmony_ci FILE * file; 16513498266Sopenharmony_ci 16613498266Sopenharmony_ci /* !checksrc! disable FOPENMODE 1 */ 16713498266Sopenharmony_ci file = fopen(name, "r"); /* VMS */ 16813498266Sopenharmony_ci if(!file) { 16913498266Sopenharmony_ci return 0; 17013498266Sopenharmony_ci } 17113498266Sopenharmony_ci count = 0; 17213498266Sopenharmony_ci ret_stat = 1; 17313498266Sopenharmony_ci while(ret_stat > 0) { 17413498266Sopenharmony_ci ret_stat = fread(buffer, 1, sizeof(buffer), file); 17513498266Sopenharmony_ci if(ret_stat) 17613498266Sopenharmony_ci count += ret_stat; 17713498266Sopenharmony_ci } 17813498266Sopenharmony_ci fclose(file); 17913498266Sopenharmony_ci 18013498266Sopenharmony_ci return count; 18113498266Sopenharmony_ci} 18213498266Sopenharmony_ci 18313498266Sopenharmony_ci/* 18413498266Sopenharmony_ci * 18513498266Sopenharmony_ci * VmsSpecialSize checks to see if the stat st_size can be trusted and 18613498266Sopenharmony_ci * if not to call a routine to get the correct size. 18713498266Sopenharmony_ci * 18813498266Sopenharmony_ci */ 18913498266Sopenharmony_cistatic curl_off_t VmsSpecialSize(const char *name, 19013498266Sopenharmony_ci const struct_stat *stat_buf) 19113498266Sopenharmony_ci{ 19213498266Sopenharmony_ci switch(stat_buf->st_fab_rfm) { 19313498266Sopenharmony_ci case FAB$C_VAR: 19413498266Sopenharmony_ci case FAB$C_VFC: 19513498266Sopenharmony_ci return vms_realfilesize(name, stat_buf); 19613498266Sopenharmony_ci break; 19713498266Sopenharmony_ci default: 19813498266Sopenharmony_ci return stat_buf->st_size; 19913498266Sopenharmony_ci } 20013498266Sopenharmony_ci} 20113498266Sopenharmony_ci#endif /* __VMS */ 20213498266Sopenharmony_ci 20313498266Sopenharmony_ci#define BUFFER_SIZE (100*1024) 20413498266Sopenharmony_ci 20513498266Sopenharmony_cistruct per_transfer *transfers; /* first node */ 20613498266Sopenharmony_cistatic struct per_transfer *transfersl; /* last node */ 20713498266Sopenharmony_cistatic curl_off_t all_pers; 20813498266Sopenharmony_ci 20913498266Sopenharmony_ci/* add_per_transfer creates a new 'per_transfer' node in the linked 21013498266Sopenharmony_ci list of transfers */ 21113498266Sopenharmony_cistatic CURLcode add_per_transfer(struct per_transfer **per) 21213498266Sopenharmony_ci{ 21313498266Sopenharmony_ci struct per_transfer *p; 21413498266Sopenharmony_ci p = calloc(1, sizeof(struct per_transfer)); 21513498266Sopenharmony_ci if(!p) 21613498266Sopenharmony_ci return CURLE_OUT_OF_MEMORY; 21713498266Sopenharmony_ci if(!transfers) 21813498266Sopenharmony_ci /* first entry */ 21913498266Sopenharmony_ci transfersl = transfers = p; 22013498266Sopenharmony_ci else { 22113498266Sopenharmony_ci /* make the last node point to the new node */ 22213498266Sopenharmony_ci transfersl->next = p; 22313498266Sopenharmony_ci /* make the new node point back to the formerly last node */ 22413498266Sopenharmony_ci p->prev = transfersl; 22513498266Sopenharmony_ci /* move the last node pointer to the new entry */ 22613498266Sopenharmony_ci transfersl = p; 22713498266Sopenharmony_ci } 22813498266Sopenharmony_ci *per = p; 22913498266Sopenharmony_ci all_xfers++; /* count total number of transfers added */ 23013498266Sopenharmony_ci all_pers++; 23113498266Sopenharmony_ci 23213498266Sopenharmony_ci return CURLE_OK; 23313498266Sopenharmony_ci} 23413498266Sopenharmony_ci 23513498266Sopenharmony_ci/* Remove the specified transfer from the list (and free it), return the next 23613498266Sopenharmony_ci in line */ 23713498266Sopenharmony_cistatic struct per_transfer *del_per_transfer(struct per_transfer *per) 23813498266Sopenharmony_ci{ 23913498266Sopenharmony_ci struct per_transfer *n; 24013498266Sopenharmony_ci struct per_transfer *p; 24113498266Sopenharmony_ci DEBUGASSERT(transfers); 24213498266Sopenharmony_ci DEBUGASSERT(transfersl); 24313498266Sopenharmony_ci DEBUGASSERT(per); 24413498266Sopenharmony_ci 24513498266Sopenharmony_ci n = per->next; 24613498266Sopenharmony_ci p = per->prev; 24713498266Sopenharmony_ci 24813498266Sopenharmony_ci if(p) 24913498266Sopenharmony_ci p->next = n; 25013498266Sopenharmony_ci else 25113498266Sopenharmony_ci transfers = n; 25213498266Sopenharmony_ci 25313498266Sopenharmony_ci if(n) 25413498266Sopenharmony_ci n->prev = p; 25513498266Sopenharmony_ci else 25613498266Sopenharmony_ci transfersl = p; 25713498266Sopenharmony_ci 25813498266Sopenharmony_ci free(per); 25913498266Sopenharmony_ci all_pers--; 26013498266Sopenharmony_ci 26113498266Sopenharmony_ci return n; 26213498266Sopenharmony_ci} 26313498266Sopenharmony_ci 26413498266Sopenharmony_cistatic CURLcode pre_transfer(struct GlobalConfig *global, 26513498266Sopenharmony_ci struct per_transfer *per) 26613498266Sopenharmony_ci{ 26713498266Sopenharmony_ci curl_off_t uploadfilesize = -1; 26813498266Sopenharmony_ci struct_stat fileinfo; 26913498266Sopenharmony_ci CURLcode result = CURLE_OK; 27013498266Sopenharmony_ci 27113498266Sopenharmony_ci if(per->uploadfile && !stdin_upload(per->uploadfile)) { 27213498266Sopenharmony_ci /* VMS Note: 27313498266Sopenharmony_ci * 27413498266Sopenharmony_ci * Reading binary from files can be a problem... Only FIXED, VAR 27513498266Sopenharmony_ci * etc WITHOUT implied CC will work. Others need a \n appended to 27613498266Sopenharmony_ci * a line 27713498266Sopenharmony_ci * 27813498266Sopenharmony_ci * - Stat gives a size but this is UNRELIABLE in VMS. E.g. 27913498266Sopenharmony_ci * a fixed file with implied CC needs to have a byte added for every 28013498266Sopenharmony_ci * record processed, this can be derived from Filesize & recordsize 28113498266Sopenharmony_ci * for VARiable record files the records need to be counted! for 28213498266Sopenharmony_ci * every record add 1 for linefeed and subtract 2 for the record 28313498266Sopenharmony_ci * header for VARIABLE header files only the bare record data needs 28413498266Sopenharmony_ci * to be considered with one appended if implied CC 28513498266Sopenharmony_ci */ 28613498266Sopenharmony_ci#ifdef __VMS 28713498266Sopenharmony_ci /* Calculate the real upload size for VMS */ 28813498266Sopenharmony_ci per->infd = -1; 28913498266Sopenharmony_ci if(stat(per->uploadfile, &fileinfo) == 0) { 29013498266Sopenharmony_ci fileinfo.st_size = VmsSpecialSize(uploadfile, &fileinfo); 29113498266Sopenharmony_ci switch(fileinfo.st_fab_rfm) { 29213498266Sopenharmony_ci case FAB$C_VAR: 29313498266Sopenharmony_ci case FAB$C_VFC: 29413498266Sopenharmony_ci case FAB$C_STMCR: 29513498266Sopenharmony_ci per->infd = open(per->uploadfile, O_RDONLY | O_BINARY); 29613498266Sopenharmony_ci break; 29713498266Sopenharmony_ci default: 29813498266Sopenharmony_ci per->infd = open(per->uploadfile, O_RDONLY | O_BINARY, 29913498266Sopenharmony_ci "rfm=stmlf", "ctx=stm"); 30013498266Sopenharmony_ci } 30113498266Sopenharmony_ci } 30213498266Sopenharmony_ci if(per->infd == -1) 30313498266Sopenharmony_ci#else 30413498266Sopenharmony_ci per->infd = open(per->uploadfile, O_RDONLY | O_BINARY); 30513498266Sopenharmony_ci if((per->infd == -1) || fstat(per->infd, &fileinfo)) 30613498266Sopenharmony_ci#endif 30713498266Sopenharmony_ci { 30813498266Sopenharmony_ci helpf(tool_stderr, "Can't open '%s'", per->uploadfile); 30913498266Sopenharmony_ci if(per->infd != -1) { 31013498266Sopenharmony_ci close(per->infd); 31113498266Sopenharmony_ci per->infd = STDIN_FILENO; 31213498266Sopenharmony_ci } 31313498266Sopenharmony_ci return CURLE_READ_ERROR; 31413498266Sopenharmony_ci } 31513498266Sopenharmony_ci per->infdopen = TRUE; 31613498266Sopenharmony_ci 31713498266Sopenharmony_ci /* we ignore file size for char/block devices, sockets, etc. */ 31813498266Sopenharmony_ci if(S_ISREG(fileinfo.st_mode)) 31913498266Sopenharmony_ci uploadfilesize = fileinfo.st_size; 32013498266Sopenharmony_ci 32113498266Sopenharmony_ci#ifdef DEBUGBUILD 32213498266Sopenharmony_ci /* allow dedicated test cases to override */ 32313498266Sopenharmony_ci { 32413498266Sopenharmony_ci char *ev = getenv("CURL_UPLOAD_SIZE"); 32513498266Sopenharmony_ci if(ev) { 32613498266Sopenharmony_ci int sz = atoi(ev); 32713498266Sopenharmony_ci uploadfilesize = (curl_off_t)sz; 32813498266Sopenharmony_ci } 32913498266Sopenharmony_ci } 33013498266Sopenharmony_ci#endif 33113498266Sopenharmony_ci 33213498266Sopenharmony_ci if(uploadfilesize != -1) { 33313498266Sopenharmony_ci struct OperationConfig *config = per->config; /* for the macro below */ 33413498266Sopenharmony_ci#ifdef CURL_DISABLE_LIBCURL_OPTION 33513498266Sopenharmony_ci (void)config; 33613498266Sopenharmony_ci (void)global; 33713498266Sopenharmony_ci#endif 33813498266Sopenharmony_ci my_setopt(per->curl, CURLOPT_INFILESIZE_LARGE, uploadfilesize); 33913498266Sopenharmony_ci } 34013498266Sopenharmony_ci } 34113498266Sopenharmony_ci per->uploadfilesize = uploadfilesize; 34213498266Sopenharmony_ci per->start = tvnow(); 34313498266Sopenharmony_ci return result; 34413498266Sopenharmony_ci} 34513498266Sopenharmony_ci 34613498266Sopenharmony_ci/* When doing serial transfers, we use a single fixed error area */ 34713498266Sopenharmony_cistatic char global_errorbuffer[CURL_ERROR_SIZE]; 34813498266Sopenharmony_ci 34913498266Sopenharmony_civoid single_transfer_cleanup(struct OperationConfig *config) 35013498266Sopenharmony_ci{ 35113498266Sopenharmony_ci if(config) { 35213498266Sopenharmony_ci struct State *state = &config->state; 35313498266Sopenharmony_ci if(state->urls) { 35413498266Sopenharmony_ci /* Free list of remaining URLs */ 35513498266Sopenharmony_ci glob_cleanup(state->urls); 35613498266Sopenharmony_ci state->urls = NULL; 35713498266Sopenharmony_ci } 35813498266Sopenharmony_ci Curl_safefree(state->outfiles); 35913498266Sopenharmony_ci Curl_safefree(state->uploadfile); 36013498266Sopenharmony_ci if(state->inglob) { 36113498266Sopenharmony_ci /* Free list of globbed upload files */ 36213498266Sopenharmony_ci glob_cleanup(state->inglob); 36313498266Sopenharmony_ci state->inglob = NULL; 36413498266Sopenharmony_ci } 36513498266Sopenharmony_ci } 36613498266Sopenharmony_ci} 36713498266Sopenharmony_ci 36813498266Sopenharmony_ci/* 36913498266Sopenharmony_ci * Call this after a transfer has completed. 37013498266Sopenharmony_ci */ 37113498266Sopenharmony_cistatic CURLcode post_per_transfer(struct GlobalConfig *global, 37213498266Sopenharmony_ci struct per_transfer *per, 37313498266Sopenharmony_ci CURLcode result, 37413498266Sopenharmony_ci bool *retryp, 37513498266Sopenharmony_ci long *delay) /* milliseconds! */ 37613498266Sopenharmony_ci{ 37713498266Sopenharmony_ci struct OutStruct *outs = &per->outs; 37813498266Sopenharmony_ci CURL *curl = per->curl; 37913498266Sopenharmony_ci struct OperationConfig *config = per->config; 38013498266Sopenharmony_ci int rc; 38113498266Sopenharmony_ci 38213498266Sopenharmony_ci if(!curl || !config) 38313498266Sopenharmony_ci return result; 38413498266Sopenharmony_ci 38513498266Sopenharmony_ci *retryp = FALSE; 38613498266Sopenharmony_ci *delay = 0; /* for no retry, keep it zero */ 38713498266Sopenharmony_ci 38813498266Sopenharmony_ci if(per->infdopen) 38913498266Sopenharmony_ci close(per->infd); 39013498266Sopenharmony_ci 39113498266Sopenharmony_ci#ifdef __VMS 39213498266Sopenharmony_ci if(is_vms_shell()) { 39313498266Sopenharmony_ci /* VMS DCL shell behavior */ 39413498266Sopenharmony_ci if(global->silent && !global->showerror) 39513498266Sopenharmony_ci vms_show = VMSSTS_HIDE; 39613498266Sopenharmony_ci } 39713498266Sopenharmony_ci else 39813498266Sopenharmony_ci#endif 39913498266Sopenharmony_ci if(!config->synthetic_error && result && 40013498266Sopenharmony_ci (!global->silent || global->showerror)) { 40113498266Sopenharmony_ci const char *msg = per->errorbuffer; 40213498266Sopenharmony_ci fprintf(tool_stderr, "curl: (%d) %s\n", result, 40313498266Sopenharmony_ci (msg && msg[0]) ? msg : curl_easy_strerror(result)); 40413498266Sopenharmony_ci if(result == CURLE_PEER_FAILED_VERIFICATION) 40513498266Sopenharmony_ci fputs(CURL_CA_CERT_ERRORMSG, tool_stderr); 40613498266Sopenharmony_ci } 40713498266Sopenharmony_ci else if(config->failwithbody) { 40813498266Sopenharmony_ci /* if HTTP response >= 400, return error */ 40913498266Sopenharmony_ci long code = 0; 41013498266Sopenharmony_ci curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &code); 41113498266Sopenharmony_ci if(code >= 400) { 41213498266Sopenharmony_ci if(!global->silent || global->showerror) 41313498266Sopenharmony_ci fprintf(tool_stderr, 41413498266Sopenharmony_ci "curl: (%d) The requested URL returned error: %ld\n", 41513498266Sopenharmony_ci CURLE_HTTP_RETURNED_ERROR, code); 41613498266Sopenharmony_ci result = CURLE_HTTP_RETURNED_ERROR; 41713498266Sopenharmony_ci } 41813498266Sopenharmony_ci } 41913498266Sopenharmony_ci /* Set file extended attributes */ 42013498266Sopenharmony_ci if(!result && config->xattr && outs->fopened && outs->stream) { 42113498266Sopenharmony_ci rc = fwrite_xattr(curl, per->this_url, fileno(outs->stream)); 42213498266Sopenharmony_ci if(rc) 42313498266Sopenharmony_ci warnf(config->global, "Error setting extended attributes on '%s': %s", 42413498266Sopenharmony_ci outs->filename, strerror(errno)); 42513498266Sopenharmony_ci } 42613498266Sopenharmony_ci 42713498266Sopenharmony_ci if(!result && !outs->stream && !outs->bytes) { 42813498266Sopenharmony_ci /* we have received no data despite the transfer was successful 42913498266Sopenharmony_ci ==> force creation of an empty output file (if an output file 43013498266Sopenharmony_ci was specified) */ 43113498266Sopenharmony_ci long cond_unmet = 0L; 43213498266Sopenharmony_ci /* do not create (or even overwrite) the file in case we get no 43313498266Sopenharmony_ci data because of unmet condition */ 43413498266Sopenharmony_ci curl_easy_getinfo(curl, CURLINFO_CONDITION_UNMET, &cond_unmet); 43513498266Sopenharmony_ci if(!cond_unmet && !tool_create_output_file(outs, config)) 43613498266Sopenharmony_ci result = CURLE_WRITE_ERROR; 43713498266Sopenharmony_ci } 43813498266Sopenharmony_ci 43913498266Sopenharmony_ci if(!outs->s_isreg && outs->stream) { 44013498266Sopenharmony_ci /* Dump standard stream buffered data */ 44113498266Sopenharmony_ci rc = fflush(outs->stream); 44213498266Sopenharmony_ci if(!result && rc) { 44313498266Sopenharmony_ci /* something went wrong in the writing process */ 44413498266Sopenharmony_ci result = CURLE_WRITE_ERROR; 44513498266Sopenharmony_ci errorf(global, "Failed writing body"); 44613498266Sopenharmony_ci } 44713498266Sopenharmony_ci } 44813498266Sopenharmony_ci 44913498266Sopenharmony_ci#ifdef _WIN32 45013498266Sopenharmony_ci /* Discard incomplete UTF-8 sequence buffered from body */ 45113498266Sopenharmony_ci if(outs->utf8seq[0]) 45213498266Sopenharmony_ci memset(outs->utf8seq, 0, sizeof(outs->utf8seq)); 45313498266Sopenharmony_ci#endif 45413498266Sopenharmony_ci 45513498266Sopenharmony_ci /* if retry-max-time is non-zero, make sure we haven't exceeded the 45613498266Sopenharmony_ci time */ 45713498266Sopenharmony_ci if(per->retry_numretries && 45813498266Sopenharmony_ci (!config->retry_maxtime || 45913498266Sopenharmony_ci (tvdiff(tvnow(), per->retrystart) < 46013498266Sopenharmony_ci config->retry_maxtime*1000L)) ) { 46113498266Sopenharmony_ci enum { 46213498266Sopenharmony_ci RETRY_NO, 46313498266Sopenharmony_ci RETRY_ALL_ERRORS, 46413498266Sopenharmony_ci RETRY_TIMEOUT, 46513498266Sopenharmony_ci RETRY_CONNREFUSED, 46613498266Sopenharmony_ci RETRY_HTTP, 46713498266Sopenharmony_ci RETRY_FTP, 46813498266Sopenharmony_ci RETRY_LAST /* not used */ 46913498266Sopenharmony_ci } retry = RETRY_NO; 47013498266Sopenharmony_ci long response = 0; 47113498266Sopenharmony_ci if((CURLE_OPERATION_TIMEDOUT == result) || 47213498266Sopenharmony_ci (CURLE_COULDNT_RESOLVE_HOST == result) || 47313498266Sopenharmony_ci (CURLE_COULDNT_RESOLVE_PROXY == result) || 47413498266Sopenharmony_ci (CURLE_FTP_ACCEPT_TIMEOUT == result)) 47513498266Sopenharmony_ci /* retry timeout always */ 47613498266Sopenharmony_ci retry = RETRY_TIMEOUT; 47713498266Sopenharmony_ci else if(config->retry_connrefused && 47813498266Sopenharmony_ci (CURLE_COULDNT_CONNECT == result)) { 47913498266Sopenharmony_ci long oserrno = 0; 48013498266Sopenharmony_ci curl_easy_getinfo(curl, CURLINFO_OS_ERRNO, &oserrno); 48113498266Sopenharmony_ci if(ECONNREFUSED == oserrno) 48213498266Sopenharmony_ci retry = RETRY_CONNREFUSED; 48313498266Sopenharmony_ci } 48413498266Sopenharmony_ci else if((CURLE_OK == result) || 48513498266Sopenharmony_ci ((config->failonerror || config->failwithbody) && 48613498266Sopenharmony_ci (CURLE_HTTP_RETURNED_ERROR == result))) { 48713498266Sopenharmony_ci /* If it returned OK. _or_ failonerror was enabled and it 48813498266Sopenharmony_ci returned due to such an error, check for HTTP transient 48913498266Sopenharmony_ci errors to retry on. */ 49013498266Sopenharmony_ci const char *scheme; 49113498266Sopenharmony_ci curl_easy_getinfo(curl, CURLINFO_SCHEME, &scheme); 49213498266Sopenharmony_ci scheme = proto_token(scheme); 49313498266Sopenharmony_ci if(scheme == proto_http || scheme == proto_https) { 49413498266Sopenharmony_ci /* This was HTTP(S) */ 49513498266Sopenharmony_ci curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response); 49613498266Sopenharmony_ci 49713498266Sopenharmony_ci switch(response) { 49813498266Sopenharmony_ci case 408: /* Request Timeout */ 49913498266Sopenharmony_ci case 429: /* Too Many Requests (RFC6585) */ 50013498266Sopenharmony_ci case 500: /* Internal Server Error */ 50113498266Sopenharmony_ci case 502: /* Bad Gateway */ 50213498266Sopenharmony_ci case 503: /* Service Unavailable */ 50313498266Sopenharmony_ci case 504: /* Gateway Timeout */ 50413498266Sopenharmony_ci retry = RETRY_HTTP; 50513498266Sopenharmony_ci /* 50613498266Sopenharmony_ci * At this point, we have already written data to the output 50713498266Sopenharmony_ci * file (or terminal). If we write to a file, we must rewind 50813498266Sopenharmony_ci * or close/re-open the file so that the next attempt starts 50913498266Sopenharmony_ci * over from the beginning. 51013498266Sopenharmony_ci * 51113498266Sopenharmony_ci * TODO: similar action for the upload case. We might need 51213498266Sopenharmony_ci * to start over reading from a previous point if we have 51313498266Sopenharmony_ci * uploaded something when this was returned. 51413498266Sopenharmony_ci */ 51513498266Sopenharmony_ci break; 51613498266Sopenharmony_ci } 51713498266Sopenharmony_ci } 51813498266Sopenharmony_ci } /* if CURLE_OK */ 51913498266Sopenharmony_ci else if(result) { 52013498266Sopenharmony_ci const char *scheme; 52113498266Sopenharmony_ci 52213498266Sopenharmony_ci curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response); 52313498266Sopenharmony_ci curl_easy_getinfo(curl, CURLINFO_SCHEME, &scheme); 52413498266Sopenharmony_ci scheme = proto_token(scheme); 52513498266Sopenharmony_ci 52613498266Sopenharmony_ci if((scheme == proto_ftp || scheme == proto_ftps) && response / 100 == 4) 52713498266Sopenharmony_ci /* 52813498266Sopenharmony_ci * This is typically when the FTP server only allows a certain 52913498266Sopenharmony_ci * amount of users and we are not one of them. All 4xx codes 53013498266Sopenharmony_ci * are transient. 53113498266Sopenharmony_ci */ 53213498266Sopenharmony_ci retry = RETRY_FTP; 53313498266Sopenharmony_ci } 53413498266Sopenharmony_ci 53513498266Sopenharmony_ci if(result && !retry && config->retry_all_errors) 53613498266Sopenharmony_ci retry = RETRY_ALL_ERRORS; 53713498266Sopenharmony_ci 53813498266Sopenharmony_ci if(retry) { 53913498266Sopenharmony_ci long sleeptime = 0; 54013498266Sopenharmony_ci curl_off_t retry_after = 0; 54113498266Sopenharmony_ci static const char * const m[]={ 54213498266Sopenharmony_ci NULL, 54313498266Sopenharmony_ci "(retrying all errors)", 54413498266Sopenharmony_ci ": timeout", 54513498266Sopenharmony_ci ": connection refused", 54613498266Sopenharmony_ci ": HTTP error", 54713498266Sopenharmony_ci ": FTP error" 54813498266Sopenharmony_ci }; 54913498266Sopenharmony_ci 55013498266Sopenharmony_ci sleeptime = per->retry_sleep; 55113498266Sopenharmony_ci if(RETRY_HTTP == retry) { 55213498266Sopenharmony_ci curl_easy_getinfo(curl, CURLINFO_RETRY_AFTER, &retry_after); 55313498266Sopenharmony_ci if(retry_after) { 55413498266Sopenharmony_ci /* store in a 'long', make sure it doesn't overflow */ 55513498266Sopenharmony_ci if(retry_after > LONG_MAX/1000) 55613498266Sopenharmony_ci sleeptime = LONG_MAX; 55713498266Sopenharmony_ci else 55813498266Sopenharmony_ci sleeptime = (long)retry_after * 1000; /* milliseconds */ 55913498266Sopenharmony_ci 56013498266Sopenharmony_ci /* if adding retry_after seconds to the process would exceed the 56113498266Sopenharmony_ci maximum time allowed for retrying, then exit the retries right 56213498266Sopenharmony_ci away */ 56313498266Sopenharmony_ci if(config->retry_maxtime) { 56413498266Sopenharmony_ci curl_off_t seconds = tvdiff(tvnow(), per->retrystart)/1000; 56513498266Sopenharmony_ci 56613498266Sopenharmony_ci if((CURL_OFF_T_MAX - retry_after < seconds) || 56713498266Sopenharmony_ci (seconds + retry_after > config->retry_maxtime)) { 56813498266Sopenharmony_ci warnf(config->global, "The Retry-After: time would " 56913498266Sopenharmony_ci "make this command line exceed the maximum allowed time " 57013498266Sopenharmony_ci "for retries."); 57113498266Sopenharmony_ci goto noretry; 57213498266Sopenharmony_ci } 57313498266Sopenharmony_ci } 57413498266Sopenharmony_ci } 57513498266Sopenharmony_ci } 57613498266Sopenharmony_ci warnf(config->global, "Problem %s. " 57713498266Sopenharmony_ci "Will retry in %ld seconds. " 57813498266Sopenharmony_ci "%ld retries left.", 57913498266Sopenharmony_ci m[retry], sleeptime/1000L, per->retry_numretries); 58013498266Sopenharmony_ci 58113498266Sopenharmony_ci per->retry_numretries--; 58213498266Sopenharmony_ci if(!config->retry_delay) { 58313498266Sopenharmony_ci per->retry_sleep *= 2; 58413498266Sopenharmony_ci if(per->retry_sleep > RETRY_SLEEP_MAX) 58513498266Sopenharmony_ci per->retry_sleep = RETRY_SLEEP_MAX; 58613498266Sopenharmony_ci } 58713498266Sopenharmony_ci if(outs->bytes && outs->filename && outs->stream) { 58813498266Sopenharmony_ci /* We have written data to an output file, we truncate file 58913498266Sopenharmony_ci */ 59013498266Sopenharmony_ci notef(config->global, 59113498266Sopenharmony_ci "Throwing away %" CURL_FORMAT_CURL_OFF_T " bytes", 59213498266Sopenharmony_ci outs->bytes); 59313498266Sopenharmony_ci fflush(outs->stream); 59413498266Sopenharmony_ci /* truncate file at the position where we started appending */ 59513498266Sopenharmony_ci#ifdef HAVE_FTRUNCATE 59613498266Sopenharmony_ci if(ftruncate(fileno(outs->stream), outs->init)) { 59713498266Sopenharmony_ci /* when truncate fails, we can't just append as then we'll 59813498266Sopenharmony_ci create something strange, bail out */ 59913498266Sopenharmony_ci errorf(config->global, "Failed to truncate file"); 60013498266Sopenharmony_ci return CURLE_WRITE_ERROR; 60113498266Sopenharmony_ci } 60213498266Sopenharmony_ci /* now seek to the end of the file, the position where we 60313498266Sopenharmony_ci just truncated the file in a large file-safe way */ 60413498266Sopenharmony_ci rc = fseek(outs->stream, 0, SEEK_END); 60513498266Sopenharmony_ci#else 60613498266Sopenharmony_ci /* ftruncate is not available, so just reposition the file 60713498266Sopenharmony_ci to the location we would have truncated it. This won't 60813498266Sopenharmony_ci work properly with large files on 32-bit systems, but 60913498266Sopenharmony_ci most of those will have ftruncate. */ 61013498266Sopenharmony_ci rc = fseek(outs->stream, (long)outs->init, SEEK_SET); 61113498266Sopenharmony_ci#endif 61213498266Sopenharmony_ci if(rc) { 61313498266Sopenharmony_ci errorf(config->global, "Failed seeking to end of file"); 61413498266Sopenharmony_ci return CURLE_WRITE_ERROR; 61513498266Sopenharmony_ci } 61613498266Sopenharmony_ci outs->bytes = 0; /* clear for next round */ 61713498266Sopenharmony_ci } 61813498266Sopenharmony_ci *retryp = TRUE; 61913498266Sopenharmony_ci *delay = sleeptime; 62013498266Sopenharmony_ci return CURLE_OK; 62113498266Sopenharmony_ci } 62213498266Sopenharmony_ci } /* if retry_numretries */ 62313498266Sopenharmony_cinoretry: 62413498266Sopenharmony_ci 62513498266Sopenharmony_ci if((global->progressmode == CURL_PROGRESS_BAR) && 62613498266Sopenharmony_ci per->progressbar.calls) 62713498266Sopenharmony_ci /* if the custom progress bar has been displayed, we output a 62813498266Sopenharmony_ci newline here */ 62913498266Sopenharmony_ci fputs("\n", per->progressbar.out); 63013498266Sopenharmony_ci 63113498266Sopenharmony_ci /* Close the outs file */ 63213498266Sopenharmony_ci if(outs->fopened && outs->stream) { 63313498266Sopenharmony_ci rc = fclose(outs->stream); 63413498266Sopenharmony_ci if(!result && rc) { 63513498266Sopenharmony_ci /* something went wrong in the writing process */ 63613498266Sopenharmony_ci result = CURLE_WRITE_ERROR; 63713498266Sopenharmony_ci errorf(config->global, "curl: (%d) Failed writing body", result); 63813498266Sopenharmony_ci } 63913498266Sopenharmony_ci if(result && config->rm_partial) { 64013498266Sopenharmony_ci struct_stat st; 64113498266Sopenharmony_ci if(!stat(outs->filename, &st) && 64213498266Sopenharmony_ci S_ISREG(st.st_mode)) { 64313498266Sopenharmony_ci if(!unlink(outs->filename)) 64413498266Sopenharmony_ci notef(global, "Removed output file: %s", outs->filename); 64513498266Sopenharmony_ci else 64613498266Sopenharmony_ci warnf(global, "Failed removing: %s", outs->filename); 64713498266Sopenharmony_ci } 64813498266Sopenharmony_ci else 64913498266Sopenharmony_ci warnf(global, "Skipping removal; not a regular file: %s", 65013498266Sopenharmony_ci outs->filename); 65113498266Sopenharmony_ci } 65213498266Sopenharmony_ci } 65313498266Sopenharmony_ci 65413498266Sopenharmony_ci /* File time can only be set _after_ the file has been closed */ 65513498266Sopenharmony_ci if(!result && config->remote_time && outs->s_isreg && outs->filename) { 65613498266Sopenharmony_ci /* Ask libcurl if we got a remote file time */ 65713498266Sopenharmony_ci curl_off_t filetime = -1; 65813498266Sopenharmony_ci curl_easy_getinfo(curl, CURLINFO_FILETIME_T, &filetime); 65913498266Sopenharmony_ci setfiletime(filetime, outs->filename, global); 66013498266Sopenharmony_ci } 66113498266Sopenharmony_ci 66213498266Sopenharmony_ci /* Write the --write-out data before cleanup but after result is final */ 66313498266Sopenharmony_ci if(config->writeout) 66413498266Sopenharmony_ci ourWriteOut(config, per, result); 66513498266Sopenharmony_ci 66613498266Sopenharmony_ci /* Close function-local opened file descriptors */ 66713498266Sopenharmony_ci if(per->heads.fopened && per->heads.stream) 66813498266Sopenharmony_ci fclose(per->heads.stream); 66913498266Sopenharmony_ci 67013498266Sopenharmony_ci if(per->heads.alloc_filename) 67113498266Sopenharmony_ci Curl_safefree(per->heads.filename); 67213498266Sopenharmony_ci 67313498266Sopenharmony_ci if(per->etag_save.fopened && per->etag_save.stream) 67413498266Sopenharmony_ci fclose(per->etag_save.stream); 67513498266Sopenharmony_ci 67613498266Sopenharmony_ci if(per->etag_save.alloc_filename) 67713498266Sopenharmony_ci Curl_safefree(per->etag_save.filename); 67813498266Sopenharmony_ci 67913498266Sopenharmony_ci curl_easy_cleanup(per->curl); 68013498266Sopenharmony_ci if(outs->alloc_filename) 68113498266Sopenharmony_ci free(outs->filename); 68213498266Sopenharmony_ci free(per->this_url); 68313498266Sopenharmony_ci free(per->outfile); 68413498266Sopenharmony_ci free(per->uploadfile); 68513498266Sopenharmony_ci if(global->parallel) 68613498266Sopenharmony_ci free(per->errorbuffer); 68713498266Sopenharmony_ci 68813498266Sopenharmony_ci return result; 68913498266Sopenharmony_ci} 69013498266Sopenharmony_ci 69113498266Sopenharmony_ci/* 69213498266Sopenharmony_ci * Return the protocol token for the scheme used in the given URL 69313498266Sopenharmony_ci */ 69413498266Sopenharmony_cistatic CURLcode url_proto(char **url, 69513498266Sopenharmony_ci struct OperationConfig *config, 69613498266Sopenharmony_ci char **scheme) 69713498266Sopenharmony_ci{ 69813498266Sopenharmony_ci CURLcode result = CURLE_OK; 69913498266Sopenharmony_ci CURLU *uh = curl_url(); 70013498266Sopenharmony_ci const char *proto = NULL; 70113498266Sopenharmony_ci *scheme = NULL; 70213498266Sopenharmony_ci 70313498266Sopenharmony_ci if(uh) { 70413498266Sopenharmony_ci if(*url) { 70513498266Sopenharmony_ci char *schemep = NULL; 70613498266Sopenharmony_ci 70713498266Sopenharmony_ci if(!curl_url_set(uh, CURLUPART_URL, *url, 70813498266Sopenharmony_ci CURLU_GUESS_SCHEME | CURLU_NON_SUPPORT_SCHEME) && 70913498266Sopenharmony_ci !curl_url_get(uh, CURLUPART_SCHEME, &schemep, 71013498266Sopenharmony_ci CURLU_DEFAULT_SCHEME)) { 71113498266Sopenharmony_ci if(curl_strequal(schemep, proto_ipfs) || 71213498266Sopenharmony_ci curl_strequal(schemep, proto_ipns)) { 71313498266Sopenharmony_ci result = ipfs_url_rewrite(uh, schemep, url, config); 71413498266Sopenharmony_ci /* short-circuit proto_token, we know it's ipfs or ipns */ 71513498266Sopenharmony_ci if(curl_strequal(schemep, proto_ipfs)) 71613498266Sopenharmony_ci proto = proto_ipfs; 71713498266Sopenharmony_ci else if(curl_strequal(schemep, proto_ipns)) 71813498266Sopenharmony_ci proto = proto_ipns; 71913498266Sopenharmony_ci if(result) 72013498266Sopenharmony_ci config->synthetic_error = TRUE; 72113498266Sopenharmony_ci } 72213498266Sopenharmony_ci else 72313498266Sopenharmony_ci proto = proto_token(schemep); 72413498266Sopenharmony_ci 72513498266Sopenharmony_ci curl_free(schemep); 72613498266Sopenharmony_ci } 72713498266Sopenharmony_ci } 72813498266Sopenharmony_ci curl_url_cleanup(uh); 72913498266Sopenharmony_ci } 73013498266Sopenharmony_ci 73113498266Sopenharmony_ci *scheme = (char *) (proto? proto: "???"); /* Never match if not found. */ 73213498266Sopenharmony_ci return result; 73313498266Sopenharmony_ci} 73413498266Sopenharmony_ci 73513498266Sopenharmony_ci/* create the next (singular) transfer */ 73613498266Sopenharmony_cistatic CURLcode single_transfer(struct GlobalConfig *global, 73713498266Sopenharmony_ci struct OperationConfig *config, 73813498266Sopenharmony_ci CURLSH *share, 73913498266Sopenharmony_ci bool capath_from_env, 74013498266Sopenharmony_ci bool *added) 74113498266Sopenharmony_ci{ 74213498266Sopenharmony_ci CURLcode result = CURLE_OK; 74313498266Sopenharmony_ci struct getout *urlnode; 74413498266Sopenharmony_ci bool orig_noprogress = global->noprogress; 74513498266Sopenharmony_ci bool orig_isatty = global->isatty; 74613498266Sopenharmony_ci struct State *state = &config->state; 74713498266Sopenharmony_ci char *httpgetfields = state->httpgetfields; 74813498266Sopenharmony_ci 74913498266Sopenharmony_ci *added = FALSE; /* not yet */ 75013498266Sopenharmony_ci 75113498266Sopenharmony_ci if(config->postfields) { 75213498266Sopenharmony_ci if(config->use_httpget) { 75313498266Sopenharmony_ci if(!httpgetfields) { 75413498266Sopenharmony_ci /* Use the postfields data for an HTTP get */ 75513498266Sopenharmony_ci httpgetfields = state->httpgetfields = config->postfields; 75613498266Sopenharmony_ci config->postfields = NULL; 75713498266Sopenharmony_ci if(SetHTTPrequest(config, 75813498266Sopenharmony_ci (config->no_body?HTTPREQ_HEAD:HTTPREQ_GET), 75913498266Sopenharmony_ci &config->httpreq)) { 76013498266Sopenharmony_ci result = CURLE_FAILED_INIT; 76113498266Sopenharmony_ci } 76213498266Sopenharmony_ci } 76313498266Sopenharmony_ci } 76413498266Sopenharmony_ci else { 76513498266Sopenharmony_ci if(SetHTTPrequest(config, HTTPREQ_SIMPLEPOST, &config->httpreq)) 76613498266Sopenharmony_ci result = CURLE_FAILED_INIT; 76713498266Sopenharmony_ci } 76813498266Sopenharmony_ci if(result) { 76913498266Sopenharmony_ci single_transfer_cleanup(config); 77013498266Sopenharmony_ci return result; 77113498266Sopenharmony_ci } 77213498266Sopenharmony_ci } 77313498266Sopenharmony_ci if(!state->urlnode) { 77413498266Sopenharmony_ci /* first time caller, setup things */ 77513498266Sopenharmony_ci state->urlnode = config->url_list; 77613498266Sopenharmony_ci state->infilenum = 1; 77713498266Sopenharmony_ci } 77813498266Sopenharmony_ci 77913498266Sopenharmony_ci while(config->state.urlnode) { 78013498266Sopenharmony_ci static bool warn_more_options = FALSE; 78113498266Sopenharmony_ci char *infiles; /* might be a glob pattern */ 78213498266Sopenharmony_ci struct URLGlob *inglob = state->inglob; 78313498266Sopenharmony_ci urlnode = config->state.urlnode; 78413498266Sopenharmony_ci 78513498266Sopenharmony_ci /* urlnode->url is the full URL (it might be NULL) */ 78613498266Sopenharmony_ci 78713498266Sopenharmony_ci if(!urlnode->url) { 78813498266Sopenharmony_ci /* This node has no URL. Free node data without destroying the 78913498266Sopenharmony_ci node itself nor modifying next pointer and continue to next */ 79013498266Sopenharmony_ci Curl_safefree(urlnode->outfile); 79113498266Sopenharmony_ci Curl_safefree(urlnode->infile); 79213498266Sopenharmony_ci urlnode->flags = 0; 79313498266Sopenharmony_ci config->state.urlnode = urlnode->next; 79413498266Sopenharmony_ci state->up = 0; 79513498266Sopenharmony_ci if(!warn_more_options) { 79613498266Sopenharmony_ci /* only show this once */ 79713498266Sopenharmony_ci warnf(config->global, "Got more output options than URLs"); 79813498266Sopenharmony_ci warn_more_options = TRUE; 79913498266Sopenharmony_ci } 80013498266Sopenharmony_ci continue; /* next URL please */ 80113498266Sopenharmony_ci } 80213498266Sopenharmony_ci 80313498266Sopenharmony_ci /* save outfile pattern before expansion */ 80413498266Sopenharmony_ci if(urlnode->outfile && !state->outfiles) { 80513498266Sopenharmony_ci state->outfiles = strdup(urlnode->outfile); 80613498266Sopenharmony_ci if(!state->outfiles) { 80713498266Sopenharmony_ci errorf(global, "out of memory"); 80813498266Sopenharmony_ci result = CURLE_OUT_OF_MEMORY; 80913498266Sopenharmony_ci break; 81013498266Sopenharmony_ci } 81113498266Sopenharmony_ci } 81213498266Sopenharmony_ci 81313498266Sopenharmony_ci infiles = urlnode->infile; 81413498266Sopenharmony_ci 81513498266Sopenharmony_ci if(!config->globoff && infiles && !inglob) { 81613498266Sopenharmony_ci /* Unless explicitly shut off */ 81713498266Sopenharmony_ci result = glob_url(&inglob, infiles, &state->infilenum, 81813498266Sopenharmony_ci (!global->silent || global->showerror)? 81913498266Sopenharmony_ci tool_stderr:NULL); 82013498266Sopenharmony_ci if(result) 82113498266Sopenharmony_ci break; 82213498266Sopenharmony_ci config->state.inglob = inglob; 82313498266Sopenharmony_ci } 82413498266Sopenharmony_ci 82513498266Sopenharmony_ci { 82613498266Sopenharmony_ci curl_off_t urlnum; 82713498266Sopenharmony_ci 82813498266Sopenharmony_ci if(!state->up && !infiles) 82913498266Sopenharmony_ci Curl_nop_stmt; 83013498266Sopenharmony_ci else { 83113498266Sopenharmony_ci if(!state->uploadfile) { 83213498266Sopenharmony_ci if(inglob) { 83313498266Sopenharmony_ci result = glob_next_url(&state->uploadfile, inglob); 83413498266Sopenharmony_ci if(result == CURLE_OUT_OF_MEMORY) 83513498266Sopenharmony_ci errorf(global, "out of memory"); 83613498266Sopenharmony_ci } 83713498266Sopenharmony_ci else if(!state->up) { 83813498266Sopenharmony_ci state->uploadfile = strdup(infiles); 83913498266Sopenharmony_ci if(!state->uploadfile) { 84013498266Sopenharmony_ci errorf(global, "out of memory"); 84113498266Sopenharmony_ci result = CURLE_OUT_OF_MEMORY; 84213498266Sopenharmony_ci } 84313498266Sopenharmony_ci } 84413498266Sopenharmony_ci } 84513498266Sopenharmony_ci if(result) 84613498266Sopenharmony_ci break; 84713498266Sopenharmony_ci } 84813498266Sopenharmony_ci 84913498266Sopenharmony_ci if(!state->urlnum) { 85013498266Sopenharmony_ci if(!config->globoff) { 85113498266Sopenharmony_ci /* Unless explicitly shut off, we expand '{...}' and '[...]' 85213498266Sopenharmony_ci expressions and return total number of URLs in pattern set */ 85313498266Sopenharmony_ci result = glob_url(&state->urls, urlnode->url, &state->urlnum, 85413498266Sopenharmony_ci (!global->silent || global->showerror)? 85513498266Sopenharmony_ci tool_stderr:NULL); 85613498266Sopenharmony_ci if(result) 85713498266Sopenharmony_ci break; 85813498266Sopenharmony_ci urlnum = state->urlnum; 85913498266Sopenharmony_ci } 86013498266Sopenharmony_ci else 86113498266Sopenharmony_ci urlnum = 1; /* without globbing, this is a single URL */ 86213498266Sopenharmony_ci } 86313498266Sopenharmony_ci else 86413498266Sopenharmony_ci urlnum = state->urlnum; 86513498266Sopenharmony_ci 86613498266Sopenharmony_ci if(state->up < state->infilenum) { 86713498266Sopenharmony_ci struct per_transfer *per = NULL; 86813498266Sopenharmony_ci struct OutStruct *outs; 86913498266Sopenharmony_ci struct OutStruct *heads; 87013498266Sopenharmony_ci struct OutStruct *etag_save; 87113498266Sopenharmony_ci struct HdrCbData *hdrcbdata = NULL; 87213498266Sopenharmony_ci struct OutStruct etag_first; 87313498266Sopenharmony_ci char *use_proto; 87413498266Sopenharmony_ci CURL *curl; 87513498266Sopenharmony_ci 87613498266Sopenharmony_ci /* --etag-save */ 87713498266Sopenharmony_ci memset(&etag_first, 0, sizeof(etag_first)); 87813498266Sopenharmony_ci etag_save = &etag_first; 87913498266Sopenharmony_ci etag_save->stream = stdout; 88013498266Sopenharmony_ci 88113498266Sopenharmony_ci /* --etag-compare */ 88213498266Sopenharmony_ci if(config->etag_compare_file) { 88313498266Sopenharmony_ci char *etag_from_file = NULL; 88413498266Sopenharmony_ci char *header = NULL; 88513498266Sopenharmony_ci ParameterError pe; 88613498266Sopenharmony_ci 88713498266Sopenharmony_ci /* open file for reading: */ 88813498266Sopenharmony_ci FILE *file = fopen(config->etag_compare_file, FOPEN_READTEXT); 88913498266Sopenharmony_ci if(!file && !config->etag_save_file) { 89013498266Sopenharmony_ci errorf(global, 89113498266Sopenharmony_ci "Failed to open %s", config->etag_compare_file); 89213498266Sopenharmony_ci result = CURLE_READ_ERROR; 89313498266Sopenharmony_ci break; 89413498266Sopenharmony_ci } 89513498266Sopenharmony_ci 89613498266Sopenharmony_ci if((PARAM_OK == file2string(&etag_from_file, file)) && 89713498266Sopenharmony_ci etag_from_file) { 89813498266Sopenharmony_ci header = aprintf("If-None-Match: %s", etag_from_file); 89913498266Sopenharmony_ci Curl_safefree(etag_from_file); 90013498266Sopenharmony_ci } 90113498266Sopenharmony_ci else 90213498266Sopenharmony_ci header = aprintf("If-None-Match: \"\""); 90313498266Sopenharmony_ci 90413498266Sopenharmony_ci if(!header) { 90513498266Sopenharmony_ci if(file) 90613498266Sopenharmony_ci fclose(file); 90713498266Sopenharmony_ci errorf(global, 90813498266Sopenharmony_ci "Failed to allocate memory for custom etag header"); 90913498266Sopenharmony_ci result = CURLE_OUT_OF_MEMORY; 91013498266Sopenharmony_ci break; 91113498266Sopenharmony_ci } 91213498266Sopenharmony_ci 91313498266Sopenharmony_ci /* add Etag from file to list of custom headers */ 91413498266Sopenharmony_ci pe = add2list(&config->headers, header); 91513498266Sopenharmony_ci Curl_safefree(header); 91613498266Sopenharmony_ci 91713498266Sopenharmony_ci if(file) 91813498266Sopenharmony_ci fclose(file); 91913498266Sopenharmony_ci if(pe != PARAM_OK) { 92013498266Sopenharmony_ci result = CURLE_OUT_OF_MEMORY; 92113498266Sopenharmony_ci break; 92213498266Sopenharmony_ci } 92313498266Sopenharmony_ci } 92413498266Sopenharmony_ci 92513498266Sopenharmony_ci if(config->etag_save_file) { 92613498266Sopenharmony_ci /* open file for output: */ 92713498266Sopenharmony_ci if(strcmp(config->etag_save_file, "-")) { 92813498266Sopenharmony_ci FILE *newfile = fopen(config->etag_save_file, "wb"); 92913498266Sopenharmony_ci if(!newfile) { 93013498266Sopenharmony_ci warnf(global, "Failed creating file for saving etags: \"%s\". " 93113498266Sopenharmony_ci "Skip this transfer", config->etag_save_file); 93213498266Sopenharmony_ci Curl_safefree(state->outfiles); 93313498266Sopenharmony_ci glob_cleanup(state->urls); 93413498266Sopenharmony_ci return CURLE_OK; 93513498266Sopenharmony_ci } 93613498266Sopenharmony_ci else { 93713498266Sopenharmony_ci etag_save->filename = config->etag_save_file; 93813498266Sopenharmony_ci etag_save->s_isreg = TRUE; 93913498266Sopenharmony_ci etag_save->fopened = TRUE; 94013498266Sopenharmony_ci etag_save->stream = newfile; 94113498266Sopenharmony_ci } 94213498266Sopenharmony_ci } 94313498266Sopenharmony_ci else { 94413498266Sopenharmony_ci /* always use binary mode for protocol header output */ 94513498266Sopenharmony_ci set_binmode(etag_save->stream); 94613498266Sopenharmony_ci } 94713498266Sopenharmony_ci } 94813498266Sopenharmony_ci 94913498266Sopenharmony_ci curl = curl_easy_init(); 95013498266Sopenharmony_ci if(curl) 95113498266Sopenharmony_ci result = add_per_transfer(&per); 95213498266Sopenharmony_ci else 95313498266Sopenharmony_ci result = CURLE_OUT_OF_MEMORY; 95413498266Sopenharmony_ci if(result) { 95513498266Sopenharmony_ci curl_easy_cleanup(curl); 95613498266Sopenharmony_ci if(etag_save->fopened) 95713498266Sopenharmony_ci fclose(etag_save->stream); 95813498266Sopenharmony_ci break; 95913498266Sopenharmony_ci } 96013498266Sopenharmony_ci per->etag_save = etag_first; /* copy the whole struct */ 96113498266Sopenharmony_ci if(state->uploadfile) { 96213498266Sopenharmony_ci per->uploadfile = strdup(state->uploadfile); 96313498266Sopenharmony_ci if(!per->uploadfile) { 96413498266Sopenharmony_ci curl_easy_cleanup(curl); 96513498266Sopenharmony_ci result = CURLE_OUT_OF_MEMORY; 96613498266Sopenharmony_ci break; 96713498266Sopenharmony_ci } 96813498266Sopenharmony_ci if(SetHTTPrequest(config, HTTPREQ_PUT, &config->httpreq)) { 96913498266Sopenharmony_ci Curl_safefree(per->uploadfile); 97013498266Sopenharmony_ci curl_easy_cleanup(curl); 97113498266Sopenharmony_ci result = CURLE_FAILED_INIT; 97213498266Sopenharmony_ci break; 97313498266Sopenharmony_ci } 97413498266Sopenharmony_ci } 97513498266Sopenharmony_ci *added = TRUE; 97613498266Sopenharmony_ci per->config = config; 97713498266Sopenharmony_ci per->curl = curl; 97813498266Sopenharmony_ci per->urlnum = urlnode->num; 97913498266Sopenharmony_ci 98013498266Sopenharmony_ci /* default headers output stream is stdout */ 98113498266Sopenharmony_ci heads = &per->heads; 98213498266Sopenharmony_ci heads->stream = stdout; 98313498266Sopenharmony_ci 98413498266Sopenharmony_ci /* Single header file for all URLs */ 98513498266Sopenharmony_ci if(config->headerfile) { 98613498266Sopenharmony_ci /* open file for output: */ 98713498266Sopenharmony_ci if(strcmp(config->headerfile, "-")) { 98813498266Sopenharmony_ci FILE *newfile; 98913498266Sopenharmony_ci 99013498266Sopenharmony_ci /* 99113498266Sopenharmony_ci * Since every transfer has its own file handle for dumping 99213498266Sopenharmony_ci * the headers, we need to open it in append mode, since transfers 99313498266Sopenharmony_ci * might finish in any order. 99413498266Sopenharmony_ci * The first transfer just clears the file. 99513498266Sopenharmony_ci * TODO: Consider placing the file handle inside the 99613498266Sopenharmony_ci * OperationConfig, so that it does not need to be opened/closed 99713498266Sopenharmony_ci * for every transfer. 99813498266Sopenharmony_ci */ 99913498266Sopenharmony_ci if(!per->prev || per->prev->config != config) { 100013498266Sopenharmony_ci newfile = fopen(config->headerfile, "wb"); 100113498266Sopenharmony_ci if(newfile) 100213498266Sopenharmony_ci fclose(newfile); 100313498266Sopenharmony_ci } 100413498266Sopenharmony_ci newfile = fopen(config->headerfile, "ab"); 100513498266Sopenharmony_ci 100613498266Sopenharmony_ci if(!newfile) { 100713498266Sopenharmony_ci errorf(global, "Failed to open %s", config->headerfile); 100813498266Sopenharmony_ci result = CURLE_WRITE_ERROR; 100913498266Sopenharmony_ci break; 101013498266Sopenharmony_ci } 101113498266Sopenharmony_ci else { 101213498266Sopenharmony_ci heads->filename = config->headerfile; 101313498266Sopenharmony_ci heads->s_isreg = TRUE; 101413498266Sopenharmony_ci heads->fopened = TRUE; 101513498266Sopenharmony_ci heads->stream = newfile; 101613498266Sopenharmony_ci } 101713498266Sopenharmony_ci } 101813498266Sopenharmony_ci else { 101913498266Sopenharmony_ci /* always use binary mode for protocol header output */ 102013498266Sopenharmony_ci set_binmode(heads->stream); 102113498266Sopenharmony_ci } 102213498266Sopenharmony_ci } 102313498266Sopenharmony_ci 102413498266Sopenharmony_ci hdrcbdata = &per->hdrcbdata; 102513498266Sopenharmony_ci 102613498266Sopenharmony_ci outs = &per->outs; 102713498266Sopenharmony_ci 102813498266Sopenharmony_ci per->outfile = NULL; 102913498266Sopenharmony_ci per->infdopen = FALSE; 103013498266Sopenharmony_ci per->infd = STDIN_FILENO; 103113498266Sopenharmony_ci 103213498266Sopenharmony_ci /* default output stream is stdout */ 103313498266Sopenharmony_ci outs->stream = stdout; 103413498266Sopenharmony_ci 103513498266Sopenharmony_ci if(state->urls) { 103613498266Sopenharmony_ci result = glob_next_url(&per->this_url, state->urls); 103713498266Sopenharmony_ci if(result) 103813498266Sopenharmony_ci break; 103913498266Sopenharmony_ci } 104013498266Sopenharmony_ci else if(!state->li) { 104113498266Sopenharmony_ci per->this_url = strdup(urlnode->url); 104213498266Sopenharmony_ci if(!per->this_url) { 104313498266Sopenharmony_ci result = CURLE_OUT_OF_MEMORY; 104413498266Sopenharmony_ci break; 104513498266Sopenharmony_ci } 104613498266Sopenharmony_ci } 104713498266Sopenharmony_ci else 104813498266Sopenharmony_ci per->this_url = NULL; 104913498266Sopenharmony_ci if(!per->this_url) 105013498266Sopenharmony_ci break; 105113498266Sopenharmony_ci 105213498266Sopenharmony_ci if(state->outfiles) { 105313498266Sopenharmony_ci per->outfile = strdup(state->outfiles); 105413498266Sopenharmony_ci if(!per->outfile) { 105513498266Sopenharmony_ci result = CURLE_OUT_OF_MEMORY; 105613498266Sopenharmony_ci break; 105713498266Sopenharmony_ci } 105813498266Sopenharmony_ci } 105913498266Sopenharmony_ci 106013498266Sopenharmony_ci if(((urlnode->flags&GETOUT_USEREMOTE) || 106113498266Sopenharmony_ci (per->outfile && strcmp("-", per->outfile)))) { 106213498266Sopenharmony_ci 106313498266Sopenharmony_ci /* 106413498266Sopenharmony_ci * We have specified a file name to store the result in, or we have 106513498266Sopenharmony_ci * decided we want to use the remote file name. 106613498266Sopenharmony_ci */ 106713498266Sopenharmony_ci 106813498266Sopenharmony_ci if(!per->outfile) { 106913498266Sopenharmony_ci /* extract the file name from the URL */ 107013498266Sopenharmony_ci result = get_url_file_name(&per->outfile, per->this_url); 107113498266Sopenharmony_ci if(result) { 107213498266Sopenharmony_ci errorf(global, "Failed to extract a sensible file name" 107313498266Sopenharmony_ci " from the URL to use for storage"); 107413498266Sopenharmony_ci break; 107513498266Sopenharmony_ci } 107613498266Sopenharmony_ci if(!*per->outfile && !config->content_disposition) { 107713498266Sopenharmony_ci errorf(global, "Remote file name has no length"); 107813498266Sopenharmony_ci result = CURLE_WRITE_ERROR; 107913498266Sopenharmony_ci break; 108013498266Sopenharmony_ci } 108113498266Sopenharmony_ci } 108213498266Sopenharmony_ci else if(state->urls) { 108313498266Sopenharmony_ci /* fill '#1' ... '#9' terms from URL pattern */ 108413498266Sopenharmony_ci char *storefile = per->outfile; 108513498266Sopenharmony_ci result = glob_match_url(&per->outfile, storefile, state->urls); 108613498266Sopenharmony_ci Curl_safefree(storefile); 108713498266Sopenharmony_ci if(result) { 108813498266Sopenharmony_ci /* bad globbing */ 108913498266Sopenharmony_ci warnf(global, "bad output glob"); 109013498266Sopenharmony_ci break; 109113498266Sopenharmony_ci } 109213498266Sopenharmony_ci if(!*per->outfile) { 109313498266Sopenharmony_ci warnf(global, "output glob produces empty string"); 109413498266Sopenharmony_ci result = CURLE_WRITE_ERROR; 109513498266Sopenharmony_ci break; 109613498266Sopenharmony_ci } 109713498266Sopenharmony_ci } 109813498266Sopenharmony_ci 109913498266Sopenharmony_ci if(config->output_dir && *config->output_dir) { 110013498266Sopenharmony_ci char *d = aprintf("%s/%s", config->output_dir, per->outfile); 110113498266Sopenharmony_ci if(!d) { 110213498266Sopenharmony_ci result = CURLE_WRITE_ERROR; 110313498266Sopenharmony_ci break; 110413498266Sopenharmony_ci } 110513498266Sopenharmony_ci free(per->outfile); 110613498266Sopenharmony_ci per->outfile = d; 110713498266Sopenharmony_ci } 110813498266Sopenharmony_ci /* Create the directory hierarchy, if not pre-existent to a multiple 110913498266Sopenharmony_ci file output call */ 111013498266Sopenharmony_ci 111113498266Sopenharmony_ci if(config->create_dirs) { 111213498266Sopenharmony_ci result = create_dir_hierarchy(per->outfile, global); 111313498266Sopenharmony_ci /* create_dir_hierarchy shows error upon CURLE_WRITE_ERROR */ 111413498266Sopenharmony_ci if(result) 111513498266Sopenharmony_ci break; 111613498266Sopenharmony_ci } 111713498266Sopenharmony_ci 111813498266Sopenharmony_ci if((urlnode->flags & GETOUT_USEREMOTE) 111913498266Sopenharmony_ci && config->content_disposition) { 112013498266Sopenharmony_ci /* Our header callback MIGHT set the filename */ 112113498266Sopenharmony_ci DEBUGASSERT(!outs->filename); 112213498266Sopenharmony_ci } 112313498266Sopenharmony_ci 112413498266Sopenharmony_ci if(config->resume_from_current) { 112513498266Sopenharmony_ci /* We're told to continue from where we are now. Get the size 112613498266Sopenharmony_ci of the file as it is now and open it for append instead */ 112713498266Sopenharmony_ci struct_stat fileinfo; 112813498266Sopenharmony_ci /* VMS -- Danger, the filesize is only valid for stream files */ 112913498266Sopenharmony_ci if(0 == stat(per->outfile, &fileinfo)) 113013498266Sopenharmony_ci /* set offset to current file size: */ 113113498266Sopenharmony_ci config->resume_from = fileinfo.st_size; 113213498266Sopenharmony_ci else 113313498266Sopenharmony_ci /* let offset be 0 */ 113413498266Sopenharmony_ci config->resume_from = 0; 113513498266Sopenharmony_ci } 113613498266Sopenharmony_ci 113713498266Sopenharmony_ci if(config->resume_from) { 113813498266Sopenharmony_ci#ifdef __VMS 113913498266Sopenharmony_ci /* open file for output, forcing VMS output format into stream 114013498266Sopenharmony_ci mode which is needed for stat() call above to always work. */ 114113498266Sopenharmony_ci FILE *file = fopen(outfile, "ab", 114213498266Sopenharmony_ci "ctx=stm", "rfm=stmlf", "rat=cr", "mrs=0"); 114313498266Sopenharmony_ci#else 114413498266Sopenharmony_ci /* open file for output: */ 114513498266Sopenharmony_ci FILE *file = fopen(per->outfile, "ab"); 114613498266Sopenharmony_ci#endif 114713498266Sopenharmony_ci if(!file) { 114813498266Sopenharmony_ci errorf(global, "Can't open '%s'", per->outfile); 114913498266Sopenharmony_ci result = CURLE_WRITE_ERROR; 115013498266Sopenharmony_ci break; 115113498266Sopenharmony_ci } 115213498266Sopenharmony_ci outs->fopened = TRUE; 115313498266Sopenharmony_ci outs->stream = file; 115413498266Sopenharmony_ci outs->init = config->resume_from; 115513498266Sopenharmony_ci } 115613498266Sopenharmony_ci else { 115713498266Sopenharmony_ci outs->stream = NULL; /* open when needed */ 115813498266Sopenharmony_ci } 115913498266Sopenharmony_ci outs->filename = per->outfile; 116013498266Sopenharmony_ci outs->s_isreg = TRUE; 116113498266Sopenharmony_ci } 116213498266Sopenharmony_ci 116313498266Sopenharmony_ci if(per->uploadfile && !stdin_upload(per->uploadfile)) { 116413498266Sopenharmony_ci /* 116513498266Sopenharmony_ci * We have specified a file to upload and it isn't "-". 116613498266Sopenharmony_ci */ 116713498266Sopenharmony_ci result = add_file_name_to_url(per->curl, &per->this_url, 116813498266Sopenharmony_ci per->uploadfile); 116913498266Sopenharmony_ci if(result) 117013498266Sopenharmony_ci break; 117113498266Sopenharmony_ci } 117213498266Sopenharmony_ci else if(per->uploadfile && stdin_upload(per->uploadfile)) { 117313498266Sopenharmony_ci /* count to see if there are more than one auth bit set 117413498266Sopenharmony_ci in the authtype field */ 117513498266Sopenharmony_ci int authbits = 0; 117613498266Sopenharmony_ci int bitcheck = 0; 117713498266Sopenharmony_ci while(bitcheck < 32) { 117813498266Sopenharmony_ci if(config->authtype & (1UL << bitcheck++)) { 117913498266Sopenharmony_ci authbits++; 118013498266Sopenharmony_ci if(authbits > 1) { 118113498266Sopenharmony_ci /* more than one, we're done! */ 118213498266Sopenharmony_ci break; 118313498266Sopenharmony_ci } 118413498266Sopenharmony_ci } 118513498266Sopenharmony_ci } 118613498266Sopenharmony_ci 118713498266Sopenharmony_ci /* 118813498266Sopenharmony_ci * If the user has also selected --anyauth or --proxy-anyauth 118913498266Sopenharmony_ci * we should warn them. 119013498266Sopenharmony_ci */ 119113498266Sopenharmony_ci if(config->proxyanyauth || (authbits>1)) { 119213498266Sopenharmony_ci warnf(global, 119313498266Sopenharmony_ci "Using --anyauth or --proxy-anyauth with upload from stdin" 119413498266Sopenharmony_ci " involves a big risk of it not working. Use a temporary" 119513498266Sopenharmony_ci " file or a fixed auth type instead"); 119613498266Sopenharmony_ci } 119713498266Sopenharmony_ci 119813498266Sopenharmony_ci DEBUGASSERT(per->infdopen == FALSE); 119913498266Sopenharmony_ci DEBUGASSERT(per->infd == STDIN_FILENO); 120013498266Sopenharmony_ci 120113498266Sopenharmony_ci set_binmode(stdin); 120213498266Sopenharmony_ci if(!strcmp(per->uploadfile, ".")) { 120313498266Sopenharmony_ci if(curlx_nonblock((curl_socket_t)per->infd, TRUE) < 0) 120413498266Sopenharmony_ci warnf(global, 120513498266Sopenharmony_ci "fcntl failed on fd=%d: %s", per->infd, strerror(errno)); 120613498266Sopenharmony_ci } 120713498266Sopenharmony_ci } 120813498266Sopenharmony_ci 120913498266Sopenharmony_ci if(per->uploadfile && config->resume_from_current) 121013498266Sopenharmony_ci config->resume_from = -1; /* -1 will then force get-it-yourself */ 121113498266Sopenharmony_ci 121213498266Sopenharmony_ci if(output_expected(per->this_url, per->uploadfile) && outs->stream && 121313498266Sopenharmony_ci isatty(fileno(outs->stream))) 121413498266Sopenharmony_ci /* we send the output to a tty, therefore we switch off the progress 121513498266Sopenharmony_ci meter */ 121613498266Sopenharmony_ci per->noprogress = global->noprogress = global->isatty = TRUE; 121713498266Sopenharmony_ci else { 121813498266Sopenharmony_ci /* progress meter is per download, so restore config 121913498266Sopenharmony_ci values */ 122013498266Sopenharmony_ci per->noprogress = global->noprogress = orig_noprogress; 122113498266Sopenharmony_ci global->isatty = orig_isatty; 122213498266Sopenharmony_ci } 122313498266Sopenharmony_ci 122413498266Sopenharmony_ci if(httpgetfields || config->query) { 122513498266Sopenharmony_ci char *q = httpgetfields ? httpgetfields : config->query; 122613498266Sopenharmony_ci CURLU *uh = curl_url(); 122713498266Sopenharmony_ci if(uh) { 122813498266Sopenharmony_ci CURLUcode uerr; 122913498266Sopenharmony_ci uerr = curl_url_set(uh, CURLUPART_URL, per->this_url, 123013498266Sopenharmony_ci CURLU_GUESS_SCHEME); 123113498266Sopenharmony_ci if(uerr) { 123213498266Sopenharmony_ci result = urlerr_cvt(uerr); 123313498266Sopenharmony_ci errorf(global, "(%d) Could not parse the URL, " 123413498266Sopenharmony_ci "failed to set query", result); 123513498266Sopenharmony_ci config->synthetic_error = TRUE; 123613498266Sopenharmony_ci } 123713498266Sopenharmony_ci else { 123813498266Sopenharmony_ci char *updated = NULL; 123913498266Sopenharmony_ci uerr = curl_url_set(uh, CURLUPART_QUERY, q, CURLU_APPENDQUERY); 124013498266Sopenharmony_ci if(!uerr) 124113498266Sopenharmony_ci uerr = curl_url_get(uh, CURLUPART_URL, &updated, 124213498266Sopenharmony_ci CURLU_GUESS_SCHEME); 124313498266Sopenharmony_ci if(uerr) 124413498266Sopenharmony_ci result = urlerr_cvt(uerr); 124513498266Sopenharmony_ci else { 124613498266Sopenharmony_ci Curl_safefree(per->this_url); /* free previous URL */ 124713498266Sopenharmony_ci per->this_url = updated; /* use our new URL instead! */ 124813498266Sopenharmony_ci } 124913498266Sopenharmony_ci } 125013498266Sopenharmony_ci curl_url_cleanup(uh); 125113498266Sopenharmony_ci if(result) 125213498266Sopenharmony_ci break; 125313498266Sopenharmony_ci } 125413498266Sopenharmony_ci } 125513498266Sopenharmony_ci 125613498266Sopenharmony_ci if((!per->outfile || !strcmp(per->outfile, "-")) && 125713498266Sopenharmony_ci !config->use_ascii) { 125813498266Sopenharmony_ci /* We get the output to stdout and we have not got the ASCII/text 125913498266Sopenharmony_ci flag, then set stdout to be binary */ 126013498266Sopenharmony_ci set_binmode(stdout); 126113498266Sopenharmony_ci } 126213498266Sopenharmony_ci 126313498266Sopenharmony_ci /* explicitly passed to stdout means okaying binary gunk */ 126413498266Sopenharmony_ci config->terminal_binary_ok = 126513498266Sopenharmony_ci (per->outfile && !strcmp(per->outfile, "-")); 126613498266Sopenharmony_ci 126713498266Sopenharmony_ci /* Avoid having this setopt added to the --libcurl source output. */ 126813498266Sopenharmony_ci result = curl_easy_setopt(curl, CURLOPT_SHARE, share); 126913498266Sopenharmony_ci if(result) 127013498266Sopenharmony_ci break; 127113498266Sopenharmony_ci 127213498266Sopenharmony_ci /* result is only used when for ipfs and ipns, ignored otherwise */ 127313498266Sopenharmony_ci result = url_proto(&per->this_url, config, &use_proto); 127413498266Sopenharmony_ci if(result && (use_proto == proto_ipfs || use_proto == proto_ipns)) 127513498266Sopenharmony_ci break; 127613498266Sopenharmony_ci 127713498266Sopenharmony_ci /* On most modern OSes, exiting works thoroughly, 127813498266Sopenharmony_ci we'll clean everything up via exit(), so don't bother with 127913498266Sopenharmony_ci slow cleanups. Crappy ones might need to skip this. 128013498266Sopenharmony_ci Note: avoid having this setopt added to the --libcurl source 128113498266Sopenharmony_ci output. */ 128213498266Sopenharmony_ci result = curl_easy_setopt(curl, CURLOPT_QUICK_EXIT, 1L); 128313498266Sopenharmony_ci if(result) 128413498266Sopenharmony_ci break; 128513498266Sopenharmony_ci 128613498266Sopenharmony_ci if(!config->tcp_nodelay) 128713498266Sopenharmony_ci my_setopt(curl, CURLOPT_TCP_NODELAY, 0L); 128813498266Sopenharmony_ci 128913498266Sopenharmony_ci if(config->tcp_fastopen) 129013498266Sopenharmony_ci my_setopt(curl, CURLOPT_TCP_FASTOPEN, 1L); 129113498266Sopenharmony_ci 129213498266Sopenharmony_ci /* where to store */ 129313498266Sopenharmony_ci my_setopt(curl, CURLOPT_WRITEDATA, per); 129413498266Sopenharmony_ci my_setopt(curl, CURLOPT_INTERLEAVEDATA, per); 129513498266Sopenharmony_ci 129613498266Sopenharmony_ci /* what call to write */ 129713498266Sopenharmony_ci my_setopt(curl, CURLOPT_WRITEFUNCTION, tool_write_cb); 129813498266Sopenharmony_ci 129913498266Sopenharmony_ci /* Note that if CURLOPT_READFUNCTION is fread (the default), then 130013498266Sopenharmony_ci * lib/telnet.c will Curl_poll() on the input file descriptor 130113498266Sopenharmony_ci * rather than calling the READFUNCTION at regular intervals. 130213498266Sopenharmony_ci * The circumstances in which it is preferable to enable this 130313498266Sopenharmony_ci * behavior, by omitting to set the READFUNCTION & READDATA options, 130413498266Sopenharmony_ci * have not been determined. 130513498266Sopenharmony_ci */ 130613498266Sopenharmony_ci my_setopt(curl, CURLOPT_READDATA, per); 130713498266Sopenharmony_ci /* what call to read */ 130813498266Sopenharmony_ci my_setopt(curl, CURLOPT_READFUNCTION, tool_read_cb); 130913498266Sopenharmony_ci 131013498266Sopenharmony_ci /* in 7.18.0, the CURLOPT_SEEKFUNCTION/DATA pair is taking over what 131113498266Sopenharmony_ci CURLOPT_IOCTLFUNCTION/DATA pair previously provided for seeking */ 131213498266Sopenharmony_ci my_setopt(curl, CURLOPT_SEEKDATA, per); 131313498266Sopenharmony_ci my_setopt(curl, CURLOPT_SEEKFUNCTION, tool_seek_cb); 131413498266Sopenharmony_ci 131513498266Sopenharmony_ci { 131613498266Sopenharmony_ci#ifdef CURLDEBUG 131713498266Sopenharmony_ci char *env = getenv("CURL_BUFFERSIZE"); 131813498266Sopenharmony_ci if(env) { 131913498266Sopenharmony_ci long size = strtol(env, NULL, 10); 132013498266Sopenharmony_ci if(size) 132113498266Sopenharmony_ci my_setopt(curl, CURLOPT_BUFFERSIZE, size); 132213498266Sopenharmony_ci } 132313498266Sopenharmony_ci else 132413498266Sopenharmony_ci#endif 132513498266Sopenharmony_ci if(config->recvpersecond && 132613498266Sopenharmony_ci (config->recvpersecond < BUFFER_SIZE)) 132713498266Sopenharmony_ci /* use a smaller sized buffer for better sleeps */ 132813498266Sopenharmony_ci my_setopt(curl, CURLOPT_BUFFERSIZE, (long)config->recvpersecond); 132913498266Sopenharmony_ci else 133013498266Sopenharmony_ci my_setopt(curl, CURLOPT_BUFFERSIZE, (long)BUFFER_SIZE); 133113498266Sopenharmony_ci } 133213498266Sopenharmony_ci 133313498266Sopenharmony_ci my_setopt_str(curl, CURLOPT_URL, per->this_url); 133413498266Sopenharmony_ci my_setopt(curl, CURLOPT_NOPROGRESS, 133513498266Sopenharmony_ci global->noprogress || global->silent?1L:0L); 133613498266Sopenharmony_ci if(config->no_body) 133713498266Sopenharmony_ci my_setopt(curl, CURLOPT_NOBODY, 1L); 133813498266Sopenharmony_ci 133913498266Sopenharmony_ci if(config->oauth_bearer) 134013498266Sopenharmony_ci my_setopt_str(curl, CURLOPT_XOAUTH2_BEARER, config->oauth_bearer); 134113498266Sopenharmony_ci 134213498266Sopenharmony_ci my_setopt_str(curl, CURLOPT_PROXY, config->proxy); 134313498266Sopenharmony_ci 134413498266Sopenharmony_ci if(config->proxy && result) { 134513498266Sopenharmony_ci errorf(global, "proxy support is disabled in this libcurl"); 134613498266Sopenharmony_ci config->synthetic_error = TRUE; 134713498266Sopenharmony_ci result = CURLE_NOT_BUILT_IN; 134813498266Sopenharmony_ci break; 134913498266Sopenharmony_ci } 135013498266Sopenharmony_ci 135113498266Sopenharmony_ci /* new in libcurl 7.5 */ 135213498266Sopenharmony_ci if(config->proxy) 135313498266Sopenharmony_ci my_setopt_enum(curl, CURLOPT_PROXYTYPE, config->proxyver); 135413498266Sopenharmony_ci 135513498266Sopenharmony_ci my_setopt_str(curl, CURLOPT_PROXYUSERPWD, config->proxyuserpwd); 135613498266Sopenharmony_ci 135713498266Sopenharmony_ci /* new in libcurl 7.3 */ 135813498266Sopenharmony_ci my_setopt(curl, CURLOPT_HTTPPROXYTUNNEL, config->proxytunnel?1L:0L); 135913498266Sopenharmony_ci 136013498266Sopenharmony_ci /* new in libcurl 7.52.0 */ 136113498266Sopenharmony_ci if(config->preproxy) 136213498266Sopenharmony_ci my_setopt_str(curl, CURLOPT_PRE_PROXY, config->preproxy); 136313498266Sopenharmony_ci 136413498266Sopenharmony_ci /* new in libcurl 7.10.6 */ 136513498266Sopenharmony_ci if(config->proxyanyauth) 136613498266Sopenharmony_ci my_setopt_bitmask(curl, CURLOPT_PROXYAUTH, 136713498266Sopenharmony_ci (long)CURLAUTH_ANY); 136813498266Sopenharmony_ci else if(config->proxynegotiate) 136913498266Sopenharmony_ci my_setopt_bitmask(curl, CURLOPT_PROXYAUTH, 137013498266Sopenharmony_ci (long)CURLAUTH_GSSNEGOTIATE); 137113498266Sopenharmony_ci else if(config->proxyntlm) 137213498266Sopenharmony_ci my_setopt_bitmask(curl, CURLOPT_PROXYAUTH, 137313498266Sopenharmony_ci (long)CURLAUTH_NTLM); 137413498266Sopenharmony_ci else if(config->proxydigest) 137513498266Sopenharmony_ci my_setopt_bitmask(curl, CURLOPT_PROXYAUTH, 137613498266Sopenharmony_ci (long)CURLAUTH_DIGEST); 137713498266Sopenharmony_ci else if(config->proxybasic) 137813498266Sopenharmony_ci my_setopt_bitmask(curl, CURLOPT_PROXYAUTH, 137913498266Sopenharmony_ci (long)CURLAUTH_BASIC); 138013498266Sopenharmony_ci 138113498266Sopenharmony_ci /* new in libcurl 7.19.4 */ 138213498266Sopenharmony_ci my_setopt_str(curl, CURLOPT_NOPROXY, config->noproxy); 138313498266Sopenharmony_ci 138413498266Sopenharmony_ci my_setopt(curl, CURLOPT_SUPPRESS_CONNECT_HEADERS, 138513498266Sopenharmony_ci config->suppress_connect_headers?1L:0L); 138613498266Sopenharmony_ci 138713498266Sopenharmony_ci my_setopt(curl, CURLOPT_FAILONERROR, config->failonerror?1L:0L); 138813498266Sopenharmony_ci my_setopt(curl, CURLOPT_REQUEST_TARGET, config->request_target); 138913498266Sopenharmony_ci my_setopt(curl, CURLOPT_UPLOAD, per->uploadfile?1L:0L); 139013498266Sopenharmony_ci my_setopt(curl, CURLOPT_DIRLISTONLY, config->dirlistonly?1L:0L); 139113498266Sopenharmony_ci my_setopt(curl, CURLOPT_APPEND, config->ftp_append?1L:0L); 139213498266Sopenharmony_ci 139313498266Sopenharmony_ci if(config->netrc_opt) 139413498266Sopenharmony_ci my_setopt_enum(curl, CURLOPT_NETRC, (long)CURL_NETRC_OPTIONAL); 139513498266Sopenharmony_ci else if(config->netrc || config->netrc_file) 139613498266Sopenharmony_ci my_setopt_enum(curl, CURLOPT_NETRC, (long)CURL_NETRC_REQUIRED); 139713498266Sopenharmony_ci else 139813498266Sopenharmony_ci my_setopt_enum(curl, CURLOPT_NETRC, (long)CURL_NETRC_IGNORED); 139913498266Sopenharmony_ci 140013498266Sopenharmony_ci if(config->netrc_file) 140113498266Sopenharmony_ci my_setopt_str(curl, CURLOPT_NETRC_FILE, config->netrc_file); 140213498266Sopenharmony_ci 140313498266Sopenharmony_ci my_setopt(curl, CURLOPT_TRANSFERTEXT, config->use_ascii?1L:0L); 140413498266Sopenharmony_ci if(config->login_options) 140513498266Sopenharmony_ci my_setopt_str(curl, CURLOPT_LOGIN_OPTIONS, config->login_options); 140613498266Sopenharmony_ci my_setopt_str(curl, CURLOPT_USERPWD, config->userpwd); 140713498266Sopenharmony_ci my_setopt_str(curl, CURLOPT_RANGE, config->range); 140813498266Sopenharmony_ci if(!global->parallel) { 140913498266Sopenharmony_ci per->errorbuffer = global_errorbuffer; 141013498266Sopenharmony_ci my_setopt(curl, CURLOPT_ERRORBUFFER, global_errorbuffer); 141113498266Sopenharmony_ci } 141213498266Sopenharmony_ci my_setopt(curl, CURLOPT_TIMEOUT_MS, config->timeout_ms); 141313498266Sopenharmony_ci 141413498266Sopenharmony_ci switch(config->httpreq) { 141513498266Sopenharmony_ci case HTTPREQ_SIMPLEPOST: 141613498266Sopenharmony_ci if(config->resume_from) { 141713498266Sopenharmony_ci errorf(global, "cannot mix --continue-at with --data"); 141813498266Sopenharmony_ci result = CURLE_FAILED_INIT; 141913498266Sopenharmony_ci } 142013498266Sopenharmony_ci else { 142113498266Sopenharmony_ci my_setopt_str(curl, CURLOPT_POSTFIELDS, 142213498266Sopenharmony_ci curlx_dyn_ptr(&config->postdata)); 142313498266Sopenharmony_ci my_setopt(curl, CURLOPT_POSTFIELDSIZE_LARGE, 142413498266Sopenharmony_ci (curl_off_t)curlx_dyn_len(&config->postdata)); 142513498266Sopenharmony_ci } 142613498266Sopenharmony_ci break; 142713498266Sopenharmony_ci case HTTPREQ_MIMEPOST: 142813498266Sopenharmony_ci /* free previous remainders */ 142913498266Sopenharmony_ci curl_mime_free(config->mimepost); 143013498266Sopenharmony_ci config->mimepost = NULL; 143113498266Sopenharmony_ci if(config->resume_from) { 143213498266Sopenharmony_ci errorf(global, "cannot mix --continue-at with --form"); 143313498266Sopenharmony_ci result = CURLE_FAILED_INIT; 143413498266Sopenharmony_ci } 143513498266Sopenharmony_ci else { 143613498266Sopenharmony_ci result = tool2curlmime(curl, config->mimeroot, &config->mimepost); 143713498266Sopenharmony_ci if(!result) 143813498266Sopenharmony_ci my_setopt_mimepost(curl, CURLOPT_MIMEPOST, config->mimepost); 143913498266Sopenharmony_ci } 144013498266Sopenharmony_ci break; 144113498266Sopenharmony_ci default: 144213498266Sopenharmony_ci break; 144313498266Sopenharmony_ci } 144413498266Sopenharmony_ci if(result) 144513498266Sopenharmony_ci break; 144613498266Sopenharmony_ci 144713498266Sopenharmony_ci /* new in libcurl 7.81.0 */ 144813498266Sopenharmony_ci if(config->mime_options) 144913498266Sopenharmony_ci my_setopt(curl, CURLOPT_MIME_OPTIONS, config->mime_options); 145013498266Sopenharmony_ci 145113498266Sopenharmony_ci /* new in libcurl 7.10.6 (default is Basic) */ 145213498266Sopenharmony_ci if(config->authtype) 145313498266Sopenharmony_ci my_setopt_bitmask(curl, CURLOPT_HTTPAUTH, (long)config->authtype); 145413498266Sopenharmony_ci 145513498266Sopenharmony_ci my_setopt_slist(curl, CURLOPT_HTTPHEADER, config->headers); 145613498266Sopenharmony_ci 145713498266Sopenharmony_ci if(proto_http || proto_rtsp) { 145813498266Sopenharmony_ci my_setopt_str(curl, CURLOPT_REFERER, config->referer); 145913498266Sopenharmony_ci my_setopt_str(curl, CURLOPT_USERAGENT, config->useragent); 146013498266Sopenharmony_ci } 146113498266Sopenharmony_ci 146213498266Sopenharmony_ci if(proto_http) { 146313498266Sopenharmony_ci long postRedir = 0; 146413498266Sopenharmony_ci 146513498266Sopenharmony_ci my_setopt(curl, CURLOPT_FOLLOWLOCATION, 146613498266Sopenharmony_ci config->followlocation?1L:0L); 146713498266Sopenharmony_ci my_setopt(curl, CURLOPT_UNRESTRICTED_AUTH, 146813498266Sopenharmony_ci config->unrestricted_auth?1L:0L); 146913498266Sopenharmony_ci my_setopt_str(curl, CURLOPT_AWS_SIGV4, config->aws_sigv4); 147013498266Sopenharmony_ci my_setopt(curl, CURLOPT_AUTOREFERER, config->autoreferer?1L:0L); 147113498266Sopenharmony_ci 147213498266Sopenharmony_ci /* new in libcurl 7.36.0 */ 147313498266Sopenharmony_ci if(config->proxyheaders) { 147413498266Sopenharmony_ci my_setopt_slist(curl, CURLOPT_PROXYHEADER, config->proxyheaders); 147513498266Sopenharmony_ci my_setopt(curl, CURLOPT_HEADEROPT, (long)CURLHEADER_SEPARATE); 147613498266Sopenharmony_ci } 147713498266Sopenharmony_ci 147813498266Sopenharmony_ci /* new in libcurl 7.5 */ 147913498266Sopenharmony_ci my_setopt(curl, CURLOPT_MAXREDIRS, config->maxredirs); 148013498266Sopenharmony_ci 148113498266Sopenharmony_ci if(config->httpversion) 148213498266Sopenharmony_ci my_setopt_enum(curl, CURLOPT_HTTP_VERSION, config->httpversion); 148313498266Sopenharmony_ci else if(feature_http2) 148413498266Sopenharmony_ci my_setopt_enum(curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2TLS); 148513498266Sopenharmony_ci 148613498266Sopenharmony_ci /* curl 7.19.1 (the 301 version existed in 7.18.2), 148713498266Sopenharmony_ci 303 was added in 7.26.0 */ 148813498266Sopenharmony_ci if(config->post301) 148913498266Sopenharmony_ci postRedir |= CURL_REDIR_POST_301; 149013498266Sopenharmony_ci if(config->post302) 149113498266Sopenharmony_ci postRedir |= CURL_REDIR_POST_302; 149213498266Sopenharmony_ci if(config->post303) 149313498266Sopenharmony_ci postRedir |= CURL_REDIR_POST_303; 149413498266Sopenharmony_ci my_setopt(curl, CURLOPT_POSTREDIR, postRedir); 149513498266Sopenharmony_ci 149613498266Sopenharmony_ci /* new in libcurl 7.21.6 */ 149713498266Sopenharmony_ci if(config->encoding) 149813498266Sopenharmony_ci my_setopt_str(curl, CURLOPT_ACCEPT_ENCODING, ""); 149913498266Sopenharmony_ci 150013498266Sopenharmony_ci /* new in libcurl 7.21.6 */ 150113498266Sopenharmony_ci if(config->tr_encoding) 150213498266Sopenharmony_ci my_setopt(curl, CURLOPT_TRANSFER_ENCODING, 1L); 150313498266Sopenharmony_ci /* new in libcurl 7.64.0 */ 150413498266Sopenharmony_ci my_setopt(curl, CURLOPT_HTTP09_ALLOWED, 150513498266Sopenharmony_ci config->http09_allowed ? 1L : 0L); 150613498266Sopenharmony_ci if(result) { 150713498266Sopenharmony_ci errorf(global, "HTTP/0.9 is not supported in this build"); 150813498266Sopenharmony_ci return result; 150913498266Sopenharmony_ci } 151013498266Sopenharmony_ci 151113498266Sopenharmony_ci } /* (proto_http) */ 151213498266Sopenharmony_ci 151313498266Sopenharmony_ci if(proto_ftp) 151413498266Sopenharmony_ci my_setopt_str(curl, CURLOPT_FTPPORT, config->ftpport); 151513498266Sopenharmony_ci my_setopt(curl, CURLOPT_LOW_SPEED_LIMIT, 151613498266Sopenharmony_ci config->low_speed_limit); 151713498266Sopenharmony_ci my_setopt(curl, CURLOPT_LOW_SPEED_TIME, config->low_speed_time); 151813498266Sopenharmony_ci my_setopt(curl, CURLOPT_MAX_SEND_SPEED_LARGE, 151913498266Sopenharmony_ci config->sendpersecond); 152013498266Sopenharmony_ci my_setopt(curl, CURLOPT_MAX_RECV_SPEED_LARGE, 152113498266Sopenharmony_ci config->recvpersecond); 152213498266Sopenharmony_ci 152313498266Sopenharmony_ci if(config->use_resume) 152413498266Sopenharmony_ci my_setopt(curl, CURLOPT_RESUME_FROM_LARGE, config->resume_from); 152513498266Sopenharmony_ci else 152613498266Sopenharmony_ci my_setopt(curl, CURLOPT_RESUME_FROM_LARGE, CURL_OFF_T_C(0)); 152713498266Sopenharmony_ci 152813498266Sopenharmony_ci my_setopt_str(curl, CURLOPT_KEYPASSWD, config->key_passwd); 152913498266Sopenharmony_ci my_setopt_str(curl, CURLOPT_PROXY_KEYPASSWD, config->proxy_key_passwd); 153013498266Sopenharmony_ci 153113498266Sopenharmony_ci if(use_proto == proto_scp || use_proto == proto_sftp) { 153213498266Sopenharmony_ci /* SSH and SSL private key uses same command-line option */ 153313498266Sopenharmony_ci /* new in libcurl 7.16.1 */ 153413498266Sopenharmony_ci my_setopt_str(curl, CURLOPT_SSH_PRIVATE_KEYFILE, config->key); 153513498266Sopenharmony_ci /* new in libcurl 7.16.1 */ 153613498266Sopenharmony_ci my_setopt_str(curl, CURLOPT_SSH_PUBLIC_KEYFILE, config->pubkey); 153713498266Sopenharmony_ci 153813498266Sopenharmony_ci /* new in libcurl 7.17.1: SSH host key md5 checking allows us 153913498266Sopenharmony_ci to fail if we are not talking to who we think we should */ 154013498266Sopenharmony_ci my_setopt_str(curl, CURLOPT_SSH_HOST_PUBLIC_KEY_MD5, 154113498266Sopenharmony_ci config->hostpubmd5); 154213498266Sopenharmony_ci 154313498266Sopenharmony_ci /* new in libcurl 7.80.0: SSH host key sha256 checking allows us 154413498266Sopenharmony_ci to fail if we are not talking to who we think we should */ 154513498266Sopenharmony_ci my_setopt_str(curl, CURLOPT_SSH_HOST_PUBLIC_KEY_SHA256, 154613498266Sopenharmony_ci config->hostpubsha256); 154713498266Sopenharmony_ci 154813498266Sopenharmony_ci /* new in libcurl 7.56.0 */ 154913498266Sopenharmony_ci if(config->ssh_compression) 155013498266Sopenharmony_ci my_setopt(curl, CURLOPT_SSH_COMPRESSION, 1L); 155113498266Sopenharmony_ci } 155213498266Sopenharmony_ci 155313498266Sopenharmony_ci if(config->cacert) 155413498266Sopenharmony_ci my_setopt_str(curl, CURLOPT_CAINFO, config->cacert); 155513498266Sopenharmony_ci if(config->proxy_cacert) 155613498266Sopenharmony_ci my_setopt_str(curl, CURLOPT_PROXY_CAINFO, config->proxy_cacert); 155713498266Sopenharmony_ci 155813498266Sopenharmony_ci if(config->capath) { 155913498266Sopenharmony_ci result = res_setopt_str(curl, CURLOPT_CAPATH, config->capath); 156013498266Sopenharmony_ci if(result == CURLE_NOT_BUILT_IN) { 156113498266Sopenharmony_ci warnf(global, "ignoring %s, not supported by libcurl", 156213498266Sopenharmony_ci capath_from_env? 156313498266Sopenharmony_ci "SSL_CERT_DIR environment variable":"--capath"); 156413498266Sopenharmony_ci } 156513498266Sopenharmony_ci else if(result) 156613498266Sopenharmony_ci break; 156713498266Sopenharmony_ci } 156813498266Sopenharmony_ci /* For the time being if --proxy-capath is not set then we use the 156913498266Sopenharmony_ci --capath value for it, if any. See #1257 */ 157013498266Sopenharmony_ci if(config->proxy_capath || config->capath) { 157113498266Sopenharmony_ci result = res_setopt_str(curl, CURLOPT_PROXY_CAPATH, 157213498266Sopenharmony_ci (config->proxy_capath ? 157313498266Sopenharmony_ci config->proxy_capath : 157413498266Sopenharmony_ci config->capath)); 157513498266Sopenharmony_ci if((result == CURLE_NOT_BUILT_IN) || 157613498266Sopenharmony_ci (result == CURLE_UNKNOWN_OPTION)) { 157713498266Sopenharmony_ci if(config->proxy_capath) { 157813498266Sopenharmony_ci warnf(global, 157913498266Sopenharmony_ci "ignoring --proxy-capath, not supported by libcurl"); 158013498266Sopenharmony_ci } 158113498266Sopenharmony_ci } 158213498266Sopenharmony_ci else if(result) 158313498266Sopenharmony_ci break; 158413498266Sopenharmony_ci } 158513498266Sopenharmony_ci 158613498266Sopenharmony_ci if(config->crlfile) 158713498266Sopenharmony_ci my_setopt_str(curl, CURLOPT_CRLFILE, config->crlfile); 158813498266Sopenharmony_ci if(config->proxy_crlfile) 158913498266Sopenharmony_ci my_setopt_str(curl, CURLOPT_PROXY_CRLFILE, config->proxy_crlfile); 159013498266Sopenharmony_ci else if(config->crlfile) /* CURLOPT_PROXY_CRLFILE default is crlfile */ 159113498266Sopenharmony_ci my_setopt_str(curl, CURLOPT_PROXY_CRLFILE, config->crlfile); 159213498266Sopenharmony_ci 159313498266Sopenharmony_ci if(config->pinnedpubkey) 159413498266Sopenharmony_ci my_setopt_str(curl, CURLOPT_PINNEDPUBLICKEY, config->pinnedpubkey); 159513498266Sopenharmony_ci 159613498266Sopenharmony_ci if(config->ssl_ec_curves) 159713498266Sopenharmony_ci my_setopt_str(curl, CURLOPT_SSL_EC_CURVES, config->ssl_ec_curves); 159813498266Sopenharmony_ci 159913498266Sopenharmony_ci if(config->writeout) 160013498266Sopenharmony_ci my_setopt_str(curl, CURLOPT_CERTINFO, 1L); 160113498266Sopenharmony_ci 160213498266Sopenharmony_ci if(feature_ssl) { 160313498266Sopenharmony_ci /* Check if config->cert is a PKCS#11 URI and set the 160413498266Sopenharmony_ci * config->cert_type if necessary */ 160513498266Sopenharmony_ci if(config->cert) { 160613498266Sopenharmony_ci if(!config->cert_type) { 160713498266Sopenharmony_ci if(is_pkcs11_uri(config->cert)) { 160813498266Sopenharmony_ci config->cert_type = strdup("ENG"); 160913498266Sopenharmony_ci } 161013498266Sopenharmony_ci } 161113498266Sopenharmony_ci } 161213498266Sopenharmony_ci 161313498266Sopenharmony_ci /* Check if config->key is a PKCS#11 URI and set the 161413498266Sopenharmony_ci * config->key_type if necessary */ 161513498266Sopenharmony_ci if(config->key) { 161613498266Sopenharmony_ci if(!config->key_type) { 161713498266Sopenharmony_ci if(is_pkcs11_uri(config->key)) { 161813498266Sopenharmony_ci config->key_type = strdup("ENG"); 161913498266Sopenharmony_ci } 162013498266Sopenharmony_ci } 162113498266Sopenharmony_ci } 162213498266Sopenharmony_ci 162313498266Sopenharmony_ci /* Check if config->proxy_cert is a PKCS#11 URI and set the 162413498266Sopenharmony_ci * config->proxy_type if necessary */ 162513498266Sopenharmony_ci if(config->proxy_cert) { 162613498266Sopenharmony_ci if(!config->proxy_cert_type) { 162713498266Sopenharmony_ci if(is_pkcs11_uri(config->proxy_cert)) { 162813498266Sopenharmony_ci config->proxy_cert_type = strdup("ENG"); 162913498266Sopenharmony_ci } 163013498266Sopenharmony_ci } 163113498266Sopenharmony_ci } 163213498266Sopenharmony_ci 163313498266Sopenharmony_ci /* Check if config->proxy_key is a PKCS#11 URI and set the 163413498266Sopenharmony_ci * config->proxy_key_type if necessary */ 163513498266Sopenharmony_ci if(config->proxy_key) { 163613498266Sopenharmony_ci if(!config->proxy_key_type) { 163713498266Sopenharmony_ci if(is_pkcs11_uri(config->proxy_key)) { 163813498266Sopenharmony_ci config->proxy_key_type = strdup("ENG"); 163913498266Sopenharmony_ci } 164013498266Sopenharmony_ci } 164113498266Sopenharmony_ci } 164213498266Sopenharmony_ci 164313498266Sopenharmony_ci /* In debug build of curl tool, using 164413498266Sopenharmony_ci * --cert loadmem=<filename>:<password> --cert-type p12 164513498266Sopenharmony_ci * must do the same thing as classic: 164613498266Sopenharmony_ci * --cert <filename>:<password> --cert-type p12 164713498266Sopenharmony_ci * but is designed to test blob */ 164813498266Sopenharmony_ci#if defined(CURLDEBUG) || defined(DEBUGBUILD) 164913498266Sopenharmony_ci if(config->cert && (strlen(config->cert) > 8) && 165013498266Sopenharmony_ci (memcmp(config->cert, "loadmem=",8) == 0)) { 165113498266Sopenharmony_ci FILE *fInCert = fopen(config->cert + 8, "rb"); 165213498266Sopenharmony_ci void *certdata = NULL; 165313498266Sopenharmony_ci long filesize = 0; 165413498266Sopenharmony_ci bool continue_reading = fInCert != NULL; 165513498266Sopenharmony_ci if(continue_reading) 165613498266Sopenharmony_ci continue_reading = fseek(fInCert, 0, SEEK_END) == 0; 165713498266Sopenharmony_ci if(continue_reading) 165813498266Sopenharmony_ci filesize = ftell(fInCert); 165913498266Sopenharmony_ci if(filesize < 0) 166013498266Sopenharmony_ci continue_reading = FALSE; 166113498266Sopenharmony_ci if(continue_reading) 166213498266Sopenharmony_ci continue_reading = fseek(fInCert, 0, SEEK_SET) == 0; 166313498266Sopenharmony_ci if(continue_reading) 166413498266Sopenharmony_ci certdata = malloc(((size_t)filesize) + 1); 166513498266Sopenharmony_ci if((!certdata) || 166613498266Sopenharmony_ci ((int)fread(certdata, (size_t)filesize, 1, fInCert) != 1)) 166713498266Sopenharmony_ci continue_reading = FALSE; 166813498266Sopenharmony_ci if(fInCert) 166913498266Sopenharmony_ci fclose(fInCert); 167013498266Sopenharmony_ci if((filesize > 0) && continue_reading) { 167113498266Sopenharmony_ci struct curl_blob structblob; 167213498266Sopenharmony_ci structblob.data = certdata; 167313498266Sopenharmony_ci structblob.len = (size_t)filesize; 167413498266Sopenharmony_ci structblob.flags = CURL_BLOB_COPY; 167513498266Sopenharmony_ci my_setopt_str(curl, CURLOPT_SSLCERT_BLOB, &structblob); 167613498266Sopenharmony_ci /* if test run well, we are sure we don't reuse 167713498266Sopenharmony_ci * original mem pointer */ 167813498266Sopenharmony_ci memset(certdata, 0, (size_t)filesize); 167913498266Sopenharmony_ci } 168013498266Sopenharmony_ci free(certdata); 168113498266Sopenharmony_ci } 168213498266Sopenharmony_ci else 168313498266Sopenharmony_ci#endif 168413498266Sopenharmony_ci my_setopt_str(curl, CURLOPT_SSLCERT, config->cert); 168513498266Sopenharmony_ci my_setopt_str(curl, CURLOPT_PROXY_SSLCERT, config->proxy_cert); 168613498266Sopenharmony_ci my_setopt_str(curl, CURLOPT_SSLCERTTYPE, config->cert_type); 168713498266Sopenharmony_ci my_setopt_str(curl, CURLOPT_PROXY_SSLCERTTYPE, 168813498266Sopenharmony_ci config->proxy_cert_type); 168913498266Sopenharmony_ci 169013498266Sopenharmony_ci 169113498266Sopenharmony_ci#if defined(CURLDEBUG) || defined(DEBUGBUILD) 169213498266Sopenharmony_ci if(config->key && (strlen(config->key) > 8) && 169313498266Sopenharmony_ci (memcmp(config->key, "loadmem=",8) == 0)) { 169413498266Sopenharmony_ci FILE *fInCert = fopen(config->key + 8, "rb"); 169513498266Sopenharmony_ci void *certdata = NULL; 169613498266Sopenharmony_ci long filesize = 0; 169713498266Sopenharmony_ci bool continue_reading = fInCert != NULL; 169813498266Sopenharmony_ci if(continue_reading) 169913498266Sopenharmony_ci continue_reading = fseek(fInCert, 0, SEEK_END) == 0; 170013498266Sopenharmony_ci if(continue_reading) 170113498266Sopenharmony_ci filesize = ftell(fInCert); 170213498266Sopenharmony_ci if(filesize < 0) 170313498266Sopenharmony_ci continue_reading = FALSE; 170413498266Sopenharmony_ci if(continue_reading) 170513498266Sopenharmony_ci continue_reading = fseek(fInCert, 0, SEEK_SET) == 0; 170613498266Sopenharmony_ci if(continue_reading) 170713498266Sopenharmony_ci certdata = malloc(((size_t)filesize) + 1); 170813498266Sopenharmony_ci if((!certdata) || 170913498266Sopenharmony_ci ((int)fread(certdata, (size_t)filesize, 1, fInCert) != 1)) 171013498266Sopenharmony_ci continue_reading = FALSE; 171113498266Sopenharmony_ci if(fInCert) 171213498266Sopenharmony_ci fclose(fInCert); 171313498266Sopenharmony_ci if((filesize > 0) && continue_reading) { 171413498266Sopenharmony_ci struct curl_blob structblob; 171513498266Sopenharmony_ci structblob.data = certdata; 171613498266Sopenharmony_ci structblob.len = (size_t)filesize; 171713498266Sopenharmony_ci structblob.flags = CURL_BLOB_COPY; 171813498266Sopenharmony_ci my_setopt_str(curl, CURLOPT_SSLKEY_BLOB, &structblob); 171913498266Sopenharmony_ci /* if test run well, we are sure we don't reuse 172013498266Sopenharmony_ci * original mem pointer */ 172113498266Sopenharmony_ci memset(certdata, 0, (size_t)filesize); 172213498266Sopenharmony_ci } 172313498266Sopenharmony_ci free(certdata); 172413498266Sopenharmony_ci } 172513498266Sopenharmony_ci else 172613498266Sopenharmony_ci#endif 172713498266Sopenharmony_ci my_setopt_str(curl, CURLOPT_SSLKEY, config->key); 172813498266Sopenharmony_ci my_setopt_str(curl, CURLOPT_PROXY_SSLKEY, config->proxy_key); 172913498266Sopenharmony_ci my_setopt_str(curl, CURLOPT_SSLKEYTYPE, config->key_type); 173013498266Sopenharmony_ci my_setopt_str(curl, CURLOPT_PROXY_SSLKEYTYPE, 173113498266Sopenharmony_ci config->proxy_key_type); 173213498266Sopenharmony_ci if(config->insecure_ok) { 173313498266Sopenharmony_ci my_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); 173413498266Sopenharmony_ci my_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L); 173513498266Sopenharmony_ci } 173613498266Sopenharmony_ci else { 173713498266Sopenharmony_ci my_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1L); 173813498266Sopenharmony_ci /* libcurl default is strict verifyhost -> 2L */ 173913498266Sopenharmony_ci /* my_setopt(curl, CURLOPT_SSL_VERIFYHOST, 2L); */ 174013498266Sopenharmony_ci } 174113498266Sopenharmony_ci 174213498266Sopenharmony_ci if(config->doh_insecure_ok) { 174313498266Sopenharmony_ci my_setopt(curl, CURLOPT_DOH_SSL_VERIFYPEER, 0L); 174413498266Sopenharmony_ci my_setopt(curl, CURLOPT_DOH_SSL_VERIFYHOST, 0L); 174513498266Sopenharmony_ci } 174613498266Sopenharmony_ci 174713498266Sopenharmony_ci if(config->proxy_insecure_ok) { 174813498266Sopenharmony_ci my_setopt(curl, CURLOPT_PROXY_SSL_VERIFYPEER, 0L); 174913498266Sopenharmony_ci my_setopt(curl, CURLOPT_PROXY_SSL_VERIFYHOST, 0L); 175013498266Sopenharmony_ci } 175113498266Sopenharmony_ci else { 175213498266Sopenharmony_ci my_setopt(curl, CURLOPT_PROXY_SSL_VERIFYPEER, 1L); 175313498266Sopenharmony_ci } 175413498266Sopenharmony_ci 175513498266Sopenharmony_ci if(config->verifystatus) 175613498266Sopenharmony_ci my_setopt(curl, CURLOPT_SSL_VERIFYSTATUS, 1L); 175713498266Sopenharmony_ci 175813498266Sopenharmony_ci if(config->doh_verifystatus) 175913498266Sopenharmony_ci my_setopt(curl, CURLOPT_DOH_SSL_VERIFYSTATUS, 1L); 176013498266Sopenharmony_ci 176113498266Sopenharmony_ci if(config->falsestart) 176213498266Sopenharmony_ci my_setopt(curl, CURLOPT_SSL_FALSESTART, 1L); 176313498266Sopenharmony_ci 176413498266Sopenharmony_ci my_setopt_enum(curl, CURLOPT_SSLVERSION, 176513498266Sopenharmony_ci config->ssl_version | config->ssl_version_max); 176613498266Sopenharmony_ci if(config->proxy) 176713498266Sopenharmony_ci my_setopt_enum(curl, CURLOPT_PROXY_SSLVERSION, 176813498266Sopenharmony_ci config->proxy_ssl_version); 176913498266Sopenharmony_ci 177013498266Sopenharmony_ci { 177113498266Sopenharmony_ci long mask = 177213498266Sopenharmony_ci (config->ssl_allow_beast ? 177313498266Sopenharmony_ci CURLSSLOPT_ALLOW_BEAST : 0) | 177413498266Sopenharmony_ci (config->ssl_no_revoke ? 177513498266Sopenharmony_ci CURLSSLOPT_NO_REVOKE : 0) | 177613498266Sopenharmony_ci (config->ssl_revoke_best_effort ? 177713498266Sopenharmony_ci CURLSSLOPT_REVOKE_BEST_EFFORT : 0) | 177813498266Sopenharmony_ci (config->native_ca_store ? 177913498266Sopenharmony_ci CURLSSLOPT_NATIVE_CA : 0) | 178013498266Sopenharmony_ci (config->ssl_auto_client_cert ? 178113498266Sopenharmony_ci CURLSSLOPT_AUTO_CLIENT_CERT : 0); 178213498266Sopenharmony_ci 178313498266Sopenharmony_ci if(mask) 178413498266Sopenharmony_ci my_setopt_bitmask(curl, CURLOPT_SSL_OPTIONS, mask); 178513498266Sopenharmony_ci } 178613498266Sopenharmony_ci 178713498266Sopenharmony_ci { 178813498266Sopenharmony_ci long mask = 178913498266Sopenharmony_ci (config->proxy_ssl_allow_beast ? 179013498266Sopenharmony_ci CURLSSLOPT_ALLOW_BEAST : 0) | 179113498266Sopenharmony_ci (config->proxy_ssl_auto_client_cert ? 179213498266Sopenharmony_ci CURLSSLOPT_AUTO_CLIENT_CERT : 0) | 179313498266Sopenharmony_ci (config->proxy_native_ca_store ? 179413498266Sopenharmony_ci CURLSSLOPT_NATIVE_CA : 0); 179513498266Sopenharmony_ci 179613498266Sopenharmony_ci if(mask) 179713498266Sopenharmony_ci my_setopt_bitmask(curl, CURLOPT_PROXY_SSL_OPTIONS, mask); 179813498266Sopenharmony_ci } 179913498266Sopenharmony_ci } 180013498266Sopenharmony_ci 180113498266Sopenharmony_ci if(config->path_as_is) 180213498266Sopenharmony_ci my_setopt(curl, CURLOPT_PATH_AS_IS, 1L); 180313498266Sopenharmony_ci 180413498266Sopenharmony_ci if((use_proto == proto_scp || use_proto == proto_sftp) && 180513498266Sopenharmony_ci !config->insecure_ok) { 180613498266Sopenharmony_ci char *known = findfile(".ssh/known_hosts", FALSE); 180713498266Sopenharmony_ci if(known) { 180813498266Sopenharmony_ci /* new in curl 7.19.6 */ 180913498266Sopenharmony_ci result = res_setopt_str(curl, CURLOPT_SSH_KNOWNHOSTS, known); 181013498266Sopenharmony_ci curl_free(known); 181113498266Sopenharmony_ci if(result == CURLE_UNKNOWN_OPTION) 181213498266Sopenharmony_ci /* libssh2 version older than 1.1.1 */ 181313498266Sopenharmony_ci result = CURLE_OK; 181413498266Sopenharmony_ci if(result) 181513498266Sopenharmony_ci break; 181613498266Sopenharmony_ci } 181713498266Sopenharmony_ci else 181813498266Sopenharmony_ci warnf(global, "Couldn't find a known_hosts file"); 181913498266Sopenharmony_ci } 182013498266Sopenharmony_ci 182113498266Sopenharmony_ci if(config->no_body || config->remote_time) { 182213498266Sopenharmony_ci /* no body or use remote time */ 182313498266Sopenharmony_ci my_setopt(curl, CURLOPT_FILETIME, 1L); 182413498266Sopenharmony_ci } 182513498266Sopenharmony_ci 182613498266Sopenharmony_ci my_setopt(curl, CURLOPT_CRLF, config->crlf?1L:0L); 182713498266Sopenharmony_ci my_setopt_slist(curl, CURLOPT_QUOTE, config->quote); 182813498266Sopenharmony_ci my_setopt_slist(curl, CURLOPT_POSTQUOTE, config->postquote); 182913498266Sopenharmony_ci my_setopt_slist(curl, CURLOPT_PREQUOTE, config->prequote); 183013498266Sopenharmony_ci 183113498266Sopenharmony_ci if(config->cookies) { 183213498266Sopenharmony_ci struct curlx_dynbuf cookies; 183313498266Sopenharmony_ci struct curl_slist *cl; 183413498266Sopenharmony_ci 183513498266Sopenharmony_ci /* The maximum size needs to match MAX_NAME in cookie.h */ 183613498266Sopenharmony_ci#define MAX_COOKIE_LINE 8200 183713498266Sopenharmony_ci curlx_dyn_init(&cookies, MAX_COOKIE_LINE); 183813498266Sopenharmony_ci for(cl = config->cookies; cl; cl = cl->next) { 183913498266Sopenharmony_ci if(cl == config->cookies) 184013498266Sopenharmony_ci result = curlx_dyn_addf(&cookies, "%s", cl->data); 184113498266Sopenharmony_ci else 184213498266Sopenharmony_ci result = curlx_dyn_addf(&cookies, ";%s", cl->data); 184313498266Sopenharmony_ci 184413498266Sopenharmony_ci if(result) { 184513498266Sopenharmony_ci warnf(global, 184613498266Sopenharmony_ci "skipped provided cookie, the cookie header " 184713498266Sopenharmony_ci "would go over %u bytes", MAX_COOKIE_LINE); 184813498266Sopenharmony_ci break; 184913498266Sopenharmony_ci } 185013498266Sopenharmony_ci } 185113498266Sopenharmony_ci 185213498266Sopenharmony_ci my_setopt_str(curl, CURLOPT_COOKIE, curlx_dyn_ptr(&cookies)); 185313498266Sopenharmony_ci curlx_dyn_free(&cookies); 185413498266Sopenharmony_ci } 185513498266Sopenharmony_ci 185613498266Sopenharmony_ci if(config->cookiefiles) { 185713498266Sopenharmony_ci struct curl_slist *cfl; 185813498266Sopenharmony_ci 185913498266Sopenharmony_ci for(cfl = config->cookiefiles; cfl; cfl = cfl->next) 186013498266Sopenharmony_ci my_setopt_str(curl, CURLOPT_COOKIEFILE, cfl->data); 186113498266Sopenharmony_ci } 186213498266Sopenharmony_ci 186313498266Sopenharmony_ci /* new in libcurl 7.9 */ 186413498266Sopenharmony_ci if(config->cookiejar) 186513498266Sopenharmony_ci my_setopt_str(curl, CURLOPT_COOKIEJAR, config->cookiejar); 186613498266Sopenharmony_ci 186713498266Sopenharmony_ci /* new in libcurl 7.9.7 */ 186813498266Sopenharmony_ci my_setopt(curl, CURLOPT_COOKIESESSION, config->cookiesession?1L:0L); 186913498266Sopenharmony_ci 187013498266Sopenharmony_ci my_setopt_enum(curl, CURLOPT_TIMECONDITION, (long)config->timecond); 187113498266Sopenharmony_ci my_setopt(curl, CURLOPT_TIMEVALUE_LARGE, config->condtime); 187213498266Sopenharmony_ci my_setopt_str(curl, CURLOPT_CUSTOMREQUEST, config->customrequest); 187313498266Sopenharmony_ci customrequest_helper(config, config->httpreq, config->customrequest); 187413498266Sopenharmony_ci my_setopt(curl, CURLOPT_STDERR, tool_stderr); 187513498266Sopenharmony_ci 187613498266Sopenharmony_ci /* three new ones in libcurl 7.3: */ 187713498266Sopenharmony_ci my_setopt_str(curl, CURLOPT_INTERFACE, config->iface); 187813498266Sopenharmony_ci my_setopt_str(curl, CURLOPT_KRBLEVEL, config->krblevel); 187913498266Sopenharmony_ci progressbarinit(&per->progressbar, config); 188013498266Sopenharmony_ci 188113498266Sopenharmony_ci if((global->progressmode == CURL_PROGRESS_BAR) && 188213498266Sopenharmony_ci !global->noprogress && !global->silent) { 188313498266Sopenharmony_ci /* we want the alternative style, then we have to implement it 188413498266Sopenharmony_ci ourselves! */ 188513498266Sopenharmony_ci my_setopt(curl, CURLOPT_XFERINFOFUNCTION, tool_progress_cb); 188613498266Sopenharmony_ci my_setopt(curl, CURLOPT_XFERINFODATA, per); 188713498266Sopenharmony_ci } 188813498266Sopenharmony_ci else if(per->uploadfile && !strcmp(per->uploadfile, ".")) { 188913498266Sopenharmony_ci /* when reading from stdin in non-blocking mode, we use the progress 189013498266Sopenharmony_ci function to unpause a busy read */ 189113498266Sopenharmony_ci my_setopt(curl, CURLOPT_NOPROGRESS, 0L); 189213498266Sopenharmony_ci my_setopt(curl, CURLOPT_XFERINFOFUNCTION, tool_readbusy_cb); 189313498266Sopenharmony_ci my_setopt(curl, CURLOPT_XFERINFODATA, per); 189413498266Sopenharmony_ci } 189513498266Sopenharmony_ci 189613498266Sopenharmony_ci /* new in libcurl 7.24.0: */ 189713498266Sopenharmony_ci if(config->dns_servers) 189813498266Sopenharmony_ci my_setopt_str(curl, CURLOPT_DNS_SERVERS, config->dns_servers); 189913498266Sopenharmony_ci 190013498266Sopenharmony_ci /* new in libcurl 7.33.0: */ 190113498266Sopenharmony_ci if(config->dns_interface) 190213498266Sopenharmony_ci my_setopt_str(curl, CURLOPT_DNS_INTERFACE, config->dns_interface); 190313498266Sopenharmony_ci if(config->dns_ipv4_addr) 190413498266Sopenharmony_ci my_setopt_str(curl, CURLOPT_DNS_LOCAL_IP4, config->dns_ipv4_addr); 190513498266Sopenharmony_ci if(config->dns_ipv6_addr) 190613498266Sopenharmony_ci my_setopt_str(curl, CURLOPT_DNS_LOCAL_IP6, config->dns_ipv6_addr); 190713498266Sopenharmony_ci 190813498266Sopenharmony_ci /* new in libcurl 7.6.2: */ 190913498266Sopenharmony_ci my_setopt_slist(curl, CURLOPT_TELNETOPTIONS, config->telnet_options); 191013498266Sopenharmony_ci 191113498266Sopenharmony_ci /* new in libcurl 7.7: */ 191213498266Sopenharmony_ci my_setopt(curl, CURLOPT_CONNECTTIMEOUT_MS, config->connecttimeout_ms); 191313498266Sopenharmony_ci 191413498266Sopenharmony_ci if(config->doh_url) 191513498266Sopenharmony_ci my_setopt_str(curl, CURLOPT_DOH_URL, config->doh_url); 191613498266Sopenharmony_ci 191713498266Sopenharmony_ci if(config->cipher_list) 191813498266Sopenharmony_ci my_setopt_str(curl, CURLOPT_SSL_CIPHER_LIST, config->cipher_list); 191913498266Sopenharmony_ci 192013498266Sopenharmony_ci if(config->proxy_cipher_list) 192113498266Sopenharmony_ci my_setopt_str(curl, CURLOPT_PROXY_SSL_CIPHER_LIST, 192213498266Sopenharmony_ci config->proxy_cipher_list); 192313498266Sopenharmony_ci 192413498266Sopenharmony_ci if(config->cipher13_list) 192513498266Sopenharmony_ci my_setopt_str(curl, CURLOPT_TLS13_CIPHERS, config->cipher13_list); 192613498266Sopenharmony_ci 192713498266Sopenharmony_ci if(config->proxy_cipher13_list) 192813498266Sopenharmony_ci my_setopt_str(curl, CURLOPT_PROXY_TLS13_CIPHERS, 192913498266Sopenharmony_ci config->proxy_cipher13_list); 193013498266Sopenharmony_ci 193113498266Sopenharmony_ci /* new in libcurl 7.9.2: */ 193213498266Sopenharmony_ci if(config->disable_epsv) 193313498266Sopenharmony_ci /* disable it */ 193413498266Sopenharmony_ci my_setopt(curl, CURLOPT_FTP_USE_EPSV, 0L); 193513498266Sopenharmony_ci 193613498266Sopenharmony_ci /* new in libcurl 7.10.5 */ 193713498266Sopenharmony_ci if(config->disable_eprt) 193813498266Sopenharmony_ci /* disable it */ 193913498266Sopenharmony_ci my_setopt(curl, CURLOPT_FTP_USE_EPRT, 0L); 194013498266Sopenharmony_ci 194113498266Sopenharmony_ci if(global->tracetype != TRACE_NONE) { 194213498266Sopenharmony_ci my_setopt(curl, CURLOPT_DEBUGFUNCTION, tool_debug_cb); 194313498266Sopenharmony_ci my_setopt(curl, CURLOPT_DEBUGDATA, config); 194413498266Sopenharmony_ci my_setopt(curl, CURLOPT_VERBOSE, 1L); 194513498266Sopenharmony_ci } 194613498266Sopenharmony_ci 194713498266Sopenharmony_ci /* new in curl 7.9.3 */ 194813498266Sopenharmony_ci if(config->engine) { 194913498266Sopenharmony_ci result = res_setopt_str(curl, CURLOPT_SSLENGINE, config->engine); 195013498266Sopenharmony_ci if(result) 195113498266Sopenharmony_ci break; 195213498266Sopenharmony_ci } 195313498266Sopenharmony_ci 195413498266Sopenharmony_ci /* new in curl 7.10.7, extended in 7.19.4. Modified to use 195513498266Sopenharmony_ci CREATE_DIR_RETRY in 7.49.0 */ 195613498266Sopenharmony_ci my_setopt(curl, CURLOPT_FTP_CREATE_MISSING_DIRS, 195713498266Sopenharmony_ci (long)(config->ftp_create_dirs? 195813498266Sopenharmony_ci CURLFTP_CREATE_DIR_RETRY: 195913498266Sopenharmony_ci CURLFTP_CREATE_DIR_NONE)); 196013498266Sopenharmony_ci 196113498266Sopenharmony_ci /* new in curl 7.10.8 */ 196213498266Sopenharmony_ci if(config->max_filesize) 196313498266Sopenharmony_ci my_setopt(curl, CURLOPT_MAXFILESIZE_LARGE, 196413498266Sopenharmony_ci config->max_filesize); 196513498266Sopenharmony_ci 196613498266Sopenharmony_ci my_setopt(curl, CURLOPT_IPRESOLVE, config->ip_version); 196713498266Sopenharmony_ci 196813498266Sopenharmony_ci /* new in curl 7.15.5 */ 196913498266Sopenharmony_ci if(config->ftp_ssl_reqd) 197013498266Sopenharmony_ci my_setopt_enum(curl, CURLOPT_USE_SSL, (long)CURLUSESSL_ALL); 197113498266Sopenharmony_ci 197213498266Sopenharmony_ci /* new in curl 7.11.0 */ 197313498266Sopenharmony_ci else if(config->ftp_ssl) 197413498266Sopenharmony_ci my_setopt_enum(curl, CURLOPT_USE_SSL, (long)CURLUSESSL_TRY); 197513498266Sopenharmony_ci 197613498266Sopenharmony_ci /* new in curl 7.16.0 */ 197713498266Sopenharmony_ci else if(config->ftp_ssl_control) 197813498266Sopenharmony_ci my_setopt_enum(curl, CURLOPT_USE_SSL, (long)CURLUSESSL_CONTROL); 197913498266Sopenharmony_ci 198013498266Sopenharmony_ci /* new in curl 7.16.1 */ 198113498266Sopenharmony_ci if(config->ftp_ssl_ccc) 198213498266Sopenharmony_ci my_setopt_enum(curl, CURLOPT_FTP_SSL_CCC, 198313498266Sopenharmony_ci (long)config->ftp_ssl_ccc_mode); 198413498266Sopenharmony_ci 198513498266Sopenharmony_ci /* new in curl 7.19.4 */ 198613498266Sopenharmony_ci if(config->socks5_gssapi_nec) 198713498266Sopenharmony_ci my_setopt_str(curl, CURLOPT_SOCKS5_GSSAPI_NEC, 1L); 198813498266Sopenharmony_ci 198913498266Sopenharmony_ci /* new in curl 7.55.0 */ 199013498266Sopenharmony_ci if(config->socks5_auth) 199113498266Sopenharmony_ci my_setopt_bitmask(curl, CURLOPT_SOCKS5_AUTH, 199213498266Sopenharmony_ci (long)config->socks5_auth); 199313498266Sopenharmony_ci 199413498266Sopenharmony_ci /* new in curl 7.43.0 */ 199513498266Sopenharmony_ci if(config->proxy_service_name) 199613498266Sopenharmony_ci my_setopt_str(curl, CURLOPT_PROXY_SERVICE_NAME, 199713498266Sopenharmony_ci config->proxy_service_name); 199813498266Sopenharmony_ci 199913498266Sopenharmony_ci /* new in curl 7.43.0 */ 200013498266Sopenharmony_ci if(config->service_name) 200113498266Sopenharmony_ci my_setopt_str(curl, CURLOPT_SERVICE_NAME, 200213498266Sopenharmony_ci config->service_name); 200313498266Sopenharmony_ci 200413498266Sopenharmony_ci /* curl 7.13.0 */ 200513498266Sopenharmony_ci my_setopt_str(curl, CURLOPT_FTP_ACCOUNT, config->ftp_account); 200613498266Sopenharmony_ci my_setopt(curl, CURLOPT_IGNORE_CONTENT_LENGTH, config->ignorecl?1L:0L); 200713498266Sopenharmony_ci 200813498266Sopenharmony_ci /* curl 7.14.2 */ 200913498266Sopenharmony_ci my_setopt(curl, CURLOPT_FTP_SKIP_PASV_IP, config->ftp_skip_ip?1L:0L); 201013498266Sopenharmony_ci 201113498266Sopenharmony_ci /* curl 7.15.1 */ 201213498266Sopenharmony_ci if(proto_ftp) 201313498266Sopenharmony_ci my_setopt(curl, CURLOPT_FTP_FILEMETHOD, 201413498266Sopenharmony_ci (long)config->ftp_filemethod); 201513498266Sopenharmony_ci 201613498266Sopenharmony_ci /* curl 7.15.2 */ 201713498266Sopenharmony_ci if(config->localport) { 201813498266Sopenharmony_ci my_setopt(curl, CURLOPT_LOCALPORT, config->localport); 201913498266Sopenharmony_ci my_setopt_str(curl, CURLOPT_LOCALPORTRANGE, config->localportrange); 202013498266Sopenharmony_ci } 202113498266Sopenharmony_ci 202213498266Sopenharmony_ci /* curl 7.15.5 */ 202313498266Sopenharmony_ci my_setopt_str(curl, CURLOPT_FTP_ALTERNATIVE_TO_USER, 202413498266Sopenharmony_ci config->ftp_alternative_to_user); 202513498266Sopenharmony_ci 202613498266Sopenharmony_ci /* curl 7.16.0 */ 202713498266Sopenharmony_ci if(config->disable_sessionid) 202813498266Sopenharmony_ci /* disable it */ 202913498266Sopenharmony_ci my_setopt(curl, CURLOPT_SSL_SESSIONID_CACHE, 0L); 203013498266Sopenharmony_ci 203113498266Sopenharmony_ci /* curl 7.16.2 */ 203213498266Sopenharmony_ci if(config->raw) { 203313498266Sopenharmony_ci my_setopt(curl, CURLOPT_HTTP_CONTENT_DECODING, 0L); 203413498266Sopenharmony_ci my_setopt(curl, CURLOPT_HTTP_TRANSFER_DECODING, 0L); 203513498266Sopenharmony_ci } 203613498266Sopenharmony_ci 203713498266Sopenharmony_ci /* curl 7.17.1 */ 203813498266Sopenharmony_ci if(!config->nokeepalive) { 203913498266Sopenharmony_ci my_setopt(curl, CURLOPT_TCP_KEEPALIVE, 1L); 204013498266Sopenharmony_ci if(config->alivetime) { 204113498266Sopenharmony_ci my_setopt(curl, CURLOPT_TCP_KEEPIDLE, config->alivetime); 204213498266Sopenharmony_ci my_setopt(curl, CURLOPT_TCP_KEEPINTVL, config->alivetime); 204313498266Sopenharmony_ci } 204413498266Sopenharmony_ci } 204513498266Sopenharmony_ci else 204613498266Sopenharmony_ci my_setopt(curl, CURLOPT_TCP_KEEPALIVE, 0L); 204713498266Sopenharmony_ci 204813498266Sopenharmony_ci /* curl 7.20.0 */ 204913498266Sopenharmony_ci if(config->tftp_blksize && proto_tftp) 205013498266Sopenharmony_ci my_setopt(curl, CURLOPT_TFTP_BLKSIZE, config->tftp_blksize); 205113498266Sopenharmony_ci 205213498266Sopenharmony_ci if(config->mail_from) 205313498266Sopenharmony_ci my_setopt_str(curl, CURLOPT_MAIL_FROM, config->mail_from); 205413498266Sopenharmony_ci 205513498266Sopenharmony_ci if(config->mail_rcpt) 205613498266Sopenharmony_ci my_setopt_slist(curl, CURLOPT_MAIL_RCPT, config->mail_rcpt); 205713498266Sopenharmony_ci 205813498266Sopenharmony_ci /* curl 7.69.x */ 205913498266Sopenharmony_ci my_setopt(curl, CURLOPT_MAIL_RCPT_ALLOWFAILS, 206013498266Sopenharmony_ci config->mail_rcpt_allowfails ? 1L : 0L); 206113498266Sopenharmony_ci 206213498266Sopenharmony_ci /* curl 7.20.x */ 206313498266Sopenharmony_ci if(config->ftp_pret) 206413498266Sopenharmony_ci my_setopt(curl, CURLOPT_FTP_USE_PRET, 1L); 206513498266Sopenharmony_ci 206613498266Sopenharmony_ci if(config->create_file_mode) 206713498266Sopenharmony_ci my_setopt(curl, CURLOPT_NEW_FILE_PERMS, config->create_file_mode); 206813498266Sopenharmony_ci 206913498266Sopenharmony_ci if(config->proto_present) 207013498266Sopenharmony_ci my_setopt_str(curl, CURLOPT_PROTOCOLS_STR, config->proto_str); 207113498266Sopenharmony_ci if(config->proto_redir_present) 207213498266Sopenharmony_ci my_setopt_str(curl, CURLOPT_REDIR_PROTOCOLS_STR, 207313498266Sopenharmony_ci config->proto_redir_str); 207413498266Sopenharmony_ci 207513498266Sopenharmony_ci if(config->content_disposition 207613498266Sopenharmony_ci && (urlnode->flags & GETOUT_USEREMOTE)) 207713498266Sopenharmony_ci hdrcbdata->honor_cd_filename = TRUE; 207813498266Sopenharmony_ci else 207913498266Sopenharmony_ci hdrcbdata->honor_cd_filename = FALSE; 208013498266Sopenharmony_ci 208113498266Sopenharmony_ci hdrcbdata->outs = outs; 208213498266Sopenharmony_ci hdrcbdata->heads = heads; 208313498266Sopenharmony_ci hdrcbdata->etag_save = etag_save; 208413498266Sopenharmony_ci hdrcbdata->global = global; 208513498266Sopenharmony_ci hdrcbdata->config = config; 208613498266Sopenharmony_ci 208713498266Sopenharmony_ci my_setopt(curl, CURLOPT_HEADERFUNCTION, tool_header_cb); 208813498266Sopenharmony_ci my_setopt(curl, CURLOPT_HEADERDATA, per); 208913498266Sopenharmony_ci 209013498266Sopenharmony_ci if(config->resolve) 209113498266Sopenharmony_ci /* new in 7.21.3 */ 209213498266Sopenharmony_ci my_setopt_slist(curl, CURLOPT_RESOLVE, config->resolve); 209313498266Sopenharmony_ci 209413498266Sopenharmony_ci if(config->connect_to) 209513498266Sopenharmony_ci /* new in 7.49.0 */ 209613498266Sopenharmony_ci my_setopt_slist(curl, CURLOPT_CONNECT_TO, config->connect_to); 209713498266Sopenharmony_ci 209813498266Sopenharmony_ci /* new in 7.21.4 */ 209913498266Sopenharmony_ci if(feature_tls_srp) { 210013498266Sopenharmony_ci if(config->tls_username) 210113498266Sopenharmony_ci my_setopt_str(curl, CURLOPT_TLSAUTH_USERNAME, 210213498266Sopenharmony_ci config->tls_username); 210313498266Sopenharmony_ci if(config->tls_password) 210413498266Sopenharmony_ci my_setopt_str(curl, CURLOPT_TLSAUTH_PASSWORD, 210513498266Sopenharmony_ci config->tls_password); 210613498266Sopenharmony_ci if(config->tls_authtype) 210713498266Sopenharmony_ci my_setopt_str(curl, CURLOPT_TLSAUTH_TYPE, 210813498266Sopenharmony_ci config->tls_authtype); 210913498266Sopenharmony_ci if(config->proxy_tls_username) 211013498266Sopenharmony_ci my_setopt_str(curl, CURLOPT_PROXY_TLSAUTH_USERNAME, 211113498266Sopenharmony_ci config->proxy_tls_username); 211213498266Sopenharmony_ci if(config->proxy_tls_password) 211313498266Sopenharmony_ci my_setopt_str(curl, CURLOPT_PROXY_TLSAUTH_PASSWORD, 211413498266Sopenharmony_ci config->proxy_tls_password); 211513498266Sopenharmony_ci if(config->proxy_tls_authtype) 211613498266Sopenharmony_ci my_setopt_str(curl, CURLOPT_PROXY_TLSAUTH_TYPE, 211713498266Sopenharmony_ci config->proxy_tls_authtype); 211813498266Sopenharmony_ci } 211913498266Sopenharmony_ci 212013498266Sopenharmony_ci /* new in 7.22.0 */ 212113498266Sopenharmony_ci if(config->gssapi_delegation) 212213498266Sopenharmony_ci my_setopt_str(curl, CURLOPT_GSSAPI_DELEGATION, 212313498266Sopenharmony_ci config->gssapi_delegation); 212413498266Sopenharmony_ci 212513498266Sopenharmony_ci if(config->mail_auth) 212613498266Sopenharmony_ci my_setopt_str(curl, CURLOPT_MAIL_AUTH, config->mail_auth); 212713498266Sopenharmony_ci 212813498266Sopenharmony_ci /* new in 7.66.0 */ 212913498266Sopenharmony_ci if(config->sasl_authzid) 213013498266Sopenharmony_ci my_setopt_str(curl, CURLOPT_SASL_AUTHZID, config->sasl_authzid); 213113498266Sopenharmony_ci 213213498266Sopenharmony_ci /* new in 7.31.0 */ 213313498266Sopenharmony_ci if(config->sasl_ir) 213413498266Sopenharmony_ci my_setopt(curl, CURLOPT_SASL_IR, 1L); 213513498266Sopenharmony_ci 213613498266Sopenharmony_ci if(config->noalpn) { 213713498266Sopenharmony_ci my_setopt(curl, CURLOPT_SSL_ENABLE_ALPN, 0L); 213813498266Sopenharmony_ci } 213913498266Sopenharmony_ci 214013498266Sopenharmony_ci /* new in 7.40.0, abstract support added in 7.53.0 */ 214113498266Sopenharmony_ci if(config->unix_socket_path) { 214213498266Sopenharmony_ci if(config->abstract_unix_socket) { 214313498266Sopenharmony_ci my_setopt_str(curl, CURLOPT_ABSTRACT_UNIX_SOCKET, 214413498266Sopenharmony_ci config->unix_socket_path); 214513498266Sopenharmony_ci } 214613498266Sopenharmony_ci else { 214713498266Sopenharmony_ci my_setopt_str(curl, CURLOPT_UNIX_SOCKET_PATH, 214813498266Sopenharmony_ci config->unix_socket_path); 214913498266Sopenharmony_ci } 215013498266Sopenharmony_ci } 215113498266Sopenharmony_ci 215213498266Sopenharmony_ci /* new in 7.45.0 */ 215313498266Sopenharmony_ci if(config->proto_default) 215413498266Sopenharmony_ci my_setopt_str(curl, CURLOPT_DEFAULT_PROTOCOL, config->proto_default); 215513498266Sopenharmony_ci 215613498266Sopenharmony_ci /* new in 7.47.0 */ 215713498266Sopenharmony_ci if(config->expect100timeout_ms > 0) 215813498266Sopenharmony_ci my_setopt_str(curl, CURLOPT_EXPECT_100_TIMEOUT_MS, 215913498266Sopenharmony_ci config->expect100timeout_ms); 216013498266Sopenharmony_ci 216113498266Sopenharmony_ci /* new in 7.48.0 */ 216213498266Sopenharmony_ci if(config->tftp_no_options && proto_tftp) 216313498266Sopenharmony_ci my_setopt(curl, CURLOPT_TFTP_NO_OPTIONS, 1L); 216413498266Sopenharmony_ci 216513498266Sopenharmony_ci /* new in 7.59.0 */ 216613498266Sopenharmony_ci if(config->happy_eyeballs_timeout_ms != CURL_HET_DEFAULT) 216713498266Sopenharmony_ci my_setopt(curl, CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS, 216813498266Sopenharmony_ci config->happy_eyeballs_timeout_ms); 216913498266Sopenharmony_ci 217013498266Sopenharmony_ci /* new in 7.60.0 */ 217113498266Sopenharmony_ci if(config->haproxy_protocol) 217213498266Sopenharmony_ci my_setopt(curl, CURLOPT_HAPROXYPROTOCOL, 1L); 217313498266Sopenharmony_ci 217413498266Sopenharmony_ci /* new in 8.2.0 */ 217513498266Sopenharmony_ci if(config->haproxy_clientip) 217613498266Sopenharmony_ci my_setopt_str(curl, CURLOPT_HAPROXY_CLIENT_IP, 217713498266Sopenharmony_ci config->haproxy_clientip); 217813498266Sopenharmony_ci 217913498266Sopenharmony_ci if(config->disallow_username_in_url) 218013498266Sopenharmony_ci my_setopt(curl, CURLOPT_DISALLOW_USERNAME_IN_URL, 1L); 218113498266Sopenharmony_ci 218213498266Sopenharmony_ci if(config->altsvc) 218313498266Sopenharmony_ci my_setopt_str(curl, CURLOPT_ALTSVC, config->altsvc); 218413498266Sopenharmony_ci 218513498266Sopenharmony_ci if(config->hsts) 218613498266Sopenharmony_ci my_setopt_str(curl, CURLOPT_HSTS, config->hsts); 218713498266Sopenharmony_ci 218813498266Sopenharmony_ci /* initialize retry vars for loop below */ 218913498266Sopenharmony_ci per->retry_sleep_default = (config->retry_delay) ? 219013498266Sopenharmony_ci config->retry_delay*1000L : RETRY_SLEEP_DEFAULT; /* ms */ 219113498266Sopenharmony_ci per->retry_numretries = config->req_retry; 219213498266Sopenharmony_ci per->retry_sleep = per->retry_sleep_default; /* ms */ 219313498266Sopenharmony_ci per->retrystart = tvnow(); 219413498266Sopenharmony_ci 219513498266Sopenharmony_ci state->li++; 219613498266Sopenharmony_ci /* Here's looping around each globbed URL */ 219713498266Sopenharmony_ci if(state->li >= urlnum) { 219813498266Sopenharmony_ci state->li = 0; 219913498266Sopenharmony_ci state->urlnum = 0; /* forced reglob of URLs */ 220013498266Sopenharmony_ci glob_cleanup(state->urls); 220113498266Sopenharmony_ci state->urls = NULL; 220213498266Sopenharmony_ci state->up++; 220313498266Sopenharmony_ci Curl_safefree(state->uploadfile); /* clear it to get the next */ 220413498266Sopenharmony_ci } 220513498266Sopenharmony_ci } 220613498266Sopenharmony_ci else { 220713498266Sopenharmony_ci /* Free this URL node data without destroying the 220813498266Sopenharmony_ci node itself nor modifying next pointer. */ 220913498266Sopenharmony_ci Curl_safefree(urlnode->outfile); 221013498266Sopenharmony_ci Curl_safefree(urlnode->infile); 221113498266Sopenharmony_ci urlnode->flags = 0; 221213498266Sopenharmony_ci glob_cleanup(state->urls); 221313498266Sopenharmony_ci state->urls = NULL; 221413498266Sopenharmony_ci state->urlnum = 0; 221513498266Sopenharmony_ci 221613498266Sopenharmony_ci Curl_safefree(state->outfiles); 221713498266Sopenharmony_ci Curl_safefree(state->uploadfile); 221813498266Sopenharmony_ci if(state->inglob) { 221913498266Sopenharmony_ci /* Free list of globbed upload files */ 222013498266Sopenharmony_ci glob_cleanup(state->inglob); 222113498266Sopenharmony_ci state->inglob = NULL; 222213498266Sopenharmony_ci } 222313498266Sopenharmony_ci config->state.urlnode = urlnode->next; 222413498266Sopenharmony_ci state->up = 0; 222513498266Sopenharmony_ci continue; 222613498266Sopenharmony_ci } 222713498266Sopenharmony_ci } 222813498266Sopenharmony_ci break; 222913498266Sopenharmony_ci } 223013498266Sopenharmony_ci Curl_safefree(state->outfiles); 223113498266Sopenharmony_ci 223213498266Sopenharmony_ci if(!*added || result) { 223313498266Sopenharmony_ci *added = FALSE; 223413498266Sopenharmony_ci single_transfer_cleanup(config); 223513498266Sopenharmony_ci } 223613498266Sopenharmony_ci return result; 223713498266Sopenharmony_ci} 223813498266Sopenharmony_ci 223913498266Sopenharmony_cistatic long all_added; /* number of easy handles currently added */ 224013498266Sopenharmony_ci 224113498266Sopenharmony_ci/* 224213498266Sopenharmony_ci * add_parallel_transfers() sets 'morep' to TRUE if there are more transfers 224313498266Sopenharmony_ci * to add even after this call returns. sets 'addedp' to TRUE if one or more 224413498266Sopenharmony_ci * transfers were added. 224513498266Sopenharmony_ci */ 224613498266Sopenharmony_cistatic CURLcode add_parallel_transfers(struct GlobalConfig *global, 224713498266Sopenharmony_ci CURLM *multi, 224813498266Sopenharmony_ci CURLSH *share, 224913498266Sopenharmony_ci bool *morep, 225013498266Sopenharmony_ci bool *addedp) 225113498266Sopenharmony_ci{ 225213498266Sopenharmony_ci struct per_transfer *per; 225313498266Sopenharmony_ci CURLcode result = CURLE_OK; 225413498266Sopenharmony_ci CURLMcode mcode; 225513498266Sopenharmony_ci bool sleeping = FALSE; 225613498266Sopenharmony_ci char *errorbuf; 225713498266Sopenharmony_ci *addedp = FALSE; 225813498266Sopenharmony_ci *morep = FALSE; 225913498266Sopenharmony_ci if(all_pers < (global->parallel_max*2)) { 226013498266Sopenharmony_ci result = create_transfer(global, share, addedp); 226113498266Sopenharmony_ci if(result) 226213498266Sopenharmony_ci return result; 226313498266Sopenharmony_ci } 226413498266Sopenharmony_ci for(per = transfers; per && (all_added < global->parallel_max); 226513498266Sopenharmony_ci per = per->next) { 226613498266Sopenharmony_ci bool getadded = FALSE; 226713498266Sopenharmony_ci if(per->added) 226813498266Sopenharmony_ci /* already added */ 226913498266Sopenharmony_ci continue; 227013498266Sopenharmony_ci if(per->startat && (time(NULL) < per->startat)) { 227113498266Sopenharmony_ci /* this is still delaying */ 227213498266Sopenharmony_ci sleeping = TRUE; 227313498266Sopenharmony_ci continue; 227413498266Sopenharmony_ci } 227513498266Sopenharmony_ci per->added = TRUE; 227613498266Sopenharmony_ci 227713498266Sopenharmony_ci result = pre_transfer(global, per); 227813498266Sopenharmony_ci if(result) 227913498266Sopenharmony_ci return result; 228013498266Sopenharmony_ci 228113498266Sopenharmony_ci errorbuf = malloc(CURL_ERROR_SIZE); 228213498266Sopenharmony_ci if(!errorbuf) 228313498266Sopenharmony_ci return CURLE_OUT_OF_MEMORY; 228413498266Sopenharmony_ci 228513498266Sopenharmony_ci /* parallel connect means that we don't set PIPEWAIT since pipewait 228613498266Sopenharmony_ci will make libcurl prefer multiplexing */ 228713498266Sopenharmony_ci (void)curl_easy_setopt(per->curl, CURLOPT_PIPEWAIT, 228813498266Sopenharmony_ci global->parallel_connect ? 0L : 1L); 228913498266Sopenharmony_ci (void)curl_easy_setopt(per->curl, CURLOPT_PRIVATE, per); 229013498266Sopenharmony_ci (void)curl_easy_setopt(per->curl, CURLOPT_XFERINFOFUNCTION, xferinfo_cb); 229113498266Sopenharmony_ci (void)curl_easy_setopt(per->curl, CURLOPT_XFERINFODATA, per); 229213498266Sopenharmony_ci (void)curl_easy_setopt(per->curl, CURLOPT_NOPROGRESS, 0L); 229313498266Sopenharmony_ci 229413498266Sopenharmony_ci mcode = curl_multi_add_handle(multi, per->curl); 229513498266Sopenharmony_ci if(mcode) { 229613498266Sopenharmony_ci DEBUGASSERT(mcode == CURLM_OUT_OF_MEMORY); 229713498266Sopenharmony_ci result = CURLE_OUT_OF_MEMORY; 229813498266Sopenharmony_ci } 229913498266Sopenharmony_ci 230013498266Sopenharmony_ci if(!result) 230113498266Sopenharmony_ci result = create_transfer(global, share, &getadded); 230213498266Sopenharmony_ci if(result) { 230313498266Sopenharmony_ci free(errorbuf); 230413498266Sopenharmony_ci return result; 230513498266Sopenharmony_ci } 230613498266Sopenharmony_ci errorbuf[0] = 0; 230713498266Sopenharmony_ci (void)curl_easy_setopt(per->curl, CURLOPT_ERRORBUFFER, errorbuf); 230813498266Sopenharmony_ci per->errorbuffer = errorbuf; 230913498266Sopenharmony_ci per->added = TRUE; 231013498266Sopenharmony_ci all_added++; 231113498266Sopenharmony_ci *addedp = TRUE; 231213498266Sopenharmony_ci } 231313498266Sopenharmony_ci *morep = (per || sleeping) ? TRUE : FALSE; 231413498266Sopenharmony_ci return CURLE_OK; 231513498266Sopenharmony_ci} 231613498266Sopenharmony_ci 231713498266Sopenharmony_cistatic CURLcode parallel_transfers(struct GlobalConfig *global, 231813498266Sopenharmony_ci CURLSH *share) 231913498266Sopenharmony_ci{ 232013498266Sopenharmony_ci CURLM *multi; 232113498266Sopenharmony_ci CURLMcode mcode = CURLM_OK; 232213498266Sopenharmony_ci CURLcode result = CURLE_OK; 232313498266Sopenharmony_ci int still_running = 1; 232413498266Sopenharmony_ci struct timeval start = tvnow(); 232513498266Sopenharmony_ci bool more_transfers; 232613498266Sopenharmony_ci bool added_transfers; 232713498266Sopenharmony_ci /* wrapitup is set TRUE after a critical error occurs to end all transfers */ 232813498266Sopenharmony_ci bool wrapitup = FALSE; 232913498266Sopenharmony_ci /* wrapitup_processed is set TRUE after the per transfer abort flag is set */ 233013498266Sopenharmony_ci bool wrapitup_processed = FALSE; 233113498266Sopenharmony_ci time_t tick = time(NULL); 233213498266Sopenharmony_ci 233313498266Sopenharmony_ci multi = curl_multi_init(); 233413498266Sopenharmony_ci if(!multi) 233513498266Sopenharmony_ci return CURLE_OUT_OF_MEMORY; 233613498266Sopenharmony_ci 233713498266Sopenharmony_ci result = add_parallel_transfers(global, multi, share, 233813498266Sopenharmony_ci &more_transfers, &added_transfers); 233913498266Sopenharmony_ci if(result) { 234013498266Sopenharmony_ci curl_multi_cleanup(multi); 234113498266Sopenharmony_ci return result; 234213498266Sopenharmony_ci } 234313498266Sopenharmony_ci 234413498266Sopenharmony_ci while(!mcode && (still_running || more_transfers)) { 234513498266Sopenharmony_ci /* If stopping prematurely (eg due to a --fail-early condition) then signal 234613498266Sopenharmony_ci that any transfers in the multi should abort (via progress callback). */ 234713498266Sopenharmony_ci if(wrapitup) { 234813498266Sopenharmony_ci if(!still_running) 234913498266Sopenharmony_ci break; 235013498266Sopenharmony_ci if(!wrapitup_processed) { 235113498266Sopenharmony_ci struct per_transfer *per; 235213498266Sopenharmony_ci for(per = transfers; per; per = per->next) { 235313498266Sopenharmony_ci if(per->added) 235413498266Sopenharmony_ci per->abort = TRUE; 235513498266Sopenharmony_ci } 235613498266Sopenharmony_ci wrapitup_processed = TRUE; 235713498266Sopenharmony_ci } 235813498266Sopenharmony_ci } 235913498266Sopenharmony_ci 236013498266Sopenharmony_ci mcode = curl_multi_poll(multi, NULL, 0, 1000, NULL); 236113498266Sopenharmony_ci if(!mcode) 236213498266Sopenharmony_ci mcode = curl_multi_perform(multi, &still_running); 236313498266Sopenharmony_ci 236413498266Sopenharmony_ci progress_meter(global, &start, FALSE); 236513498266Sopenharmony_ci 236613498266Sopenharmony_ci if(!mcode) { 236713498266Sopenharmony_ci int rc; 236813498266Sopenharmony_ci CURLMsg *msg; 236913498266Sopenharmony_ci bool checkmore = FALSE; 237013498266Sopenharmony_ci do { 237113498266Sopenharmony_ci msg = curl_multi_info_read(multi, &rc); 237213498266Sopenharmony_ci if(msg) { 237313498266Sopenharmony_ci bool retry; 237413498266Sopenharmony_ci long delay; 237513498266Sopenharmony_ci struct per_transfer *ended; 237613498266Sopenharmony_ci CURL *easy = msg->easy_handle; 237713498266Sopenharmony_ci CURLcode tres = msg->data.result; 237813498266Sopenharmony_ci curl_easy_getinfo(easy, CURLINFO_PRIVATE, (void *)&ended); 237913498266Sopenharmony_ci curl_multi_remove_handle(multi, easy); 238013498266Sopenharmony_ci 238113498266Sopenharmony_ci if(ended->abort && (tres == CURLE_ABORTED_BY_CALLBACK) && 238213498266Sopenharmony_ci ended->errorbuffer) { 238313498266Sopenharmony_ci msnprintf(ended->errorbuffer, CURL_ERROR_SIZE, 238413498266Sopenharmony_ci "Transfer aborted due to critical error " 238513498266Sopenharmony_ci "in another transfer"); 238613498266Sopenharmony_ci } 238713498266Sopenharmony_ci tres = post_per_transfer(global, ended, tres, &retry, &delay); 238813498266Sopenharmony_ci progress_finalize(ended); /* before it goes away */ 238913498266Sopenharmony_ci all_added--; /* one fewer added */ 239013498266Sopenharmony_ci checkmore = TRUE; 239113498266Sopenharmony_ci if(retry) { 239213498266Sopenharmony_ci ended->added = FALSE; /* add it again */ 239313498266Sopenharmony_ci /* we delay retries in full integer seconds only */ 239413498266Sopenharmony_ci ended->startat = delay ? time(NULL) + delay/1000 : 0; 239513498266Sopenharmony_ci } 239613498266Sopenharmony_ci else { 239713498266Sopenharmony_ci /* result receives this transfer's error unless the transfer was 239813498266Sopenharmony_ci marked for abort due to a critical error in another transfer */ 239913498266Sopenharmony_ci if(tres && (!ended->abort || !result)) 240013498266Sopenharmony_ci result = tres; 240113498266Sopenharmony_ci if(is_fatal_error(result) || (result && global->fail_early)) 240213498266Sopenharmony_ci wrapitup = TRUE; 240313498266Sopenharmony_ci (void)del_per_transfer(ended); 240413498266Sopenharmony_ci } 240513498266Sopenharmony_ci } 240613498266Sopenharmony_ci } while(msg); 240713498266Sopenharmony_ci if(wrapitup) { 240813498266Sopenharmony_ci if(still_running) 240913498266Sopenharmony_ci continue; 241013498266Sopenharmony_ci else 241113498266Sopenharmony_ci break; 241213498266Sopenharmony_ci } 241313498266Sopenharmony_ci if(!checkmore) { 241413498266Sopenharmony_ci time_t tock = time(NULL); 241513498266Sopenharmony_ci if(tick != tock) { 241613498266Sopenharmony_ci checkmore = TRUE; 241713498266Sopenharmony_ci tick = tock; 241813498266Sopenharmony_ci } 241913498266Sopenharmony_ci } 242013498266Sopenharmony_ci if(checkmore) { 242113498266Sopenharmony_ci /* one or more transfers completed, add more! */ 242213498266Sopenharmony_ci CURLcode tres = add_parallel_transfers(global, multi, share, 242313498266Sopenharmony_ci &more_transfers, 242413498266Sopenharmony_ci &added_transfers); 242513498266Sopenharmony_ci if(tres) 242613498266Sopenharmony_ci result = tres; 242713498266Sopenharmony_ci if(added_transfers) 242813498266Sopenharmony_ci /* we added new ones, make sure the loop doesn't exit yet */ 242913498266Sopenharmony_ci still_running = 1; 243013498266Sopenharmony_ci } 243113498266Sopenharmony_ci if(is_fatal_error(result) || (result && global->fail_early)) 243213498266Sopenharmony_ci wrapitup = TRUE; 243313498266Sopenharmony_ci } 243413498266Sopenharmony_ci } 243513498266Sopenharmony_ci 243613498266Sopenharmony_ci (void)progress_meter(global, &start, TRUE); 243713498266Sopenharmony_ci 243813498266Sopenharmony_ci /* Make sure to return some kind of error if there was a multi problem */ 243913498266Sopenharmony_ci if(mcode) { 244013498266Sopenharmony_ci result = (mcode == CURLM_OUT_OF_MEMORY) ? CURLE_OUT_OF_MEMORY : 244113498266Sopenharmony_ci /* The other multi errors should never happen, so return 244213498266Sopenharmony_ci something suitably generic */ 244313498266Sopenharmony_ci CURLE_BAD_FUNCTION_ARGUMENT; 244413498266Sopenharmony_ci } 244513498266Sopenharmony_ci 244613498266Sopenharmony_ci curl_multi_cleanup(multi); 244713498266Sopenharmony_ci 244813498266Sopenharmony_ci return result; 244913498266Sopenharmony_ci} 245013498266Sopenharmony_ci 245113498266Sopenharmony_cistatic CURLcode serial_transfers(struct GlobalConfig *global, 245213498266Sopenharmony_ci CURLSH *share) 245313498266Sopenharmony_ci{ 245413498266Sopenharmony_ci CURLcode returncode = CURLE_OK; 245513498266Sopenharmony_ci CURLcode result = CURLE_OK; 245613498266Sopenharmony_ci struct per_transfer *per; 245713498266Sopenharmony_ci bool added = FALSE; 245813498266Sopenharmony_ci 245913498266Sopenharmony_ci result = create_transfer(global, share, &added); 246013498266Sopenharmony_ci if(result) 246113498266Sopenharmony_ci return result; 246213498266Sopenharmony_ci if(!added) { 246313498266Sopenharmony_ci errorf(global, "no transfer performed"); 246413498266Sopenharmony_ci return CURLE_READ_ERROR; 246513498266Sopenharmony_ci } 246613498266Sopenharmony_ci for(per = transfers; per;) { 246713498266Sopenharmony_ci bool retry; 246813498266Sopenharmony_ci long delay_ms; 246913498266Sopenharmony_ci bool bailout = FALSE; 247013498266Sopenharmony_ci struct timeval start; 247113498266Sopenharmony_ci result = pre_transfer(global, per); 247213498266Sopenharmony_ci if(result) 247313498266Sopenharmony_ci break; 247413498266Sopenharmony_ci 247513498266Sopenharmony_ci if(global->libcurl) { 247613498266Sopenharmony_ci result = easysrc_perform(); 247713498266Sopenharmony_ci if(result) 247813498266Sopenharmony_ci break; 247913498266Sopenharmony_ci } 248013498266Sopenharmony_ci start = tvnow(); 248113498266Sopenharmony_ci#ifdef CURLDEBUG 248213498266Sopenharmony_ci if(global->test_event_based) 248313498266Sopenharmony_ci result = curl_easy_perform_ev(per->curl); 248413498266Sopenharmony_ci else 248513498266Sopenharmony_ci#endif 248613498266Sopenharmony_ci result = curl_easy_perform(per->curl); 248713498266Sopenharmony_ci 248813498266Sopenharmony_ci returncode = post_per_transfer(global, per, result, &retry, &delay_ms); 248913498266Sopenharmony_ci if(retry) { 249013498266Sopenharmony_ci tool_go_sleep(delay_ms); 249113498266Sopenharmony_ci continue; 249213498266Sopenharmony_ci } 249313498266Sopenharmony_ci 249413498266Sopenharmony_ci /* Bail out upon critical errors or --fail-early */ 249513498266Sopenharmony_ci if(is_fatal_error(returncode) || (returncode && global->fail_early)) 249613498266Sopenharmony_ci bailout = TRUE; 249713498266Sopenharmony_ci else { 249813498266Sopenharmony_ci /* setup the next one just before we delete this */ 249913498266Sopenharmony_ci result = create_transfer(global, share, &added); 250013498266Sopenharmony_ci if(result) { 250113498266Sopenharmony_ci returncode = result; 250213498266Sopenharmony_ci bailout = TRUE; 250313498266Sopenharmony_ci } 250413498266Sopenharmony_ci } 250513498266Sopenharmony_ci 250613498266Sopenharmony_ci per = del_per_transfer(per); 250713498266Sopenharmony_ci 250813498266Sopenharmony_ci if(bailout) 250913498266Sopenharmony_ci break; 251013498266Sopenharmony_ci 251113498266Sopenharmony_ci if(per && global->ms_per_transfer) { 251213498266Sopenharmony_ci /* how long time did the most recent transfer take in number of 251313498266Sopenharmony_ci milliseconds */ 251413498266Sopenharmony_ci long milli = tvdiff(tvnow(), start); 251513498266Sopenharmony_ci if(milli < global->ms_per_transfer) { 251613498266Sopenharmony_ci notef(global, "Transfer took %ld ms, waits %ldms as set by --rate", 251713498266Sopenharmony_ci milli, global->ms_per_transfer - milli); 251813498266Sopenharmony_ci /* The transfer took less time than wanted. Wait a little. */ 251913498266Sopenharmony_ci tool_go_sleep(global->ms_per_transfer - milli); 252013498266Sopenharmony_ci } 252113498266Sopenharmony_ci } 252213498266Sopenharmony_ci } 252313498266Sopenharmony_ci if(returncode) 252413498266Sopenharmony_ci /* returncode errors have priority */ 252513498266Sopenharmony_ci result = returncode; 252613498266Sopenharmony_ci 252713498266Sopenharmony_ci if(result) 252813498266Sopenharmony_ci single_transfer_cleanup(global->current); 252913498266Sopenharmony_ci 253013498266Sopenharmony_ci return result; 253113498266Sopenharmony_ci} 253213498266Sopenharmony_ci 253313498266Sopenharmony_ci/* setup a transfer for the given config */ 253413498266Sopenharmony_cistatic CURLcode transfer_per_config(struct GlobalConfig *global, 253513498266Sopenharmony_ci struct OperationConfig *config, 253613498266Sopenharmony_ci CURLSH *share, 253713498266Sopenharmony_ci bool *added) 253813498266Sopenharmony_ci{ 253913498266Sopenharmony_ci CURLcode result = CURLE_OK; 254013498266Sopenharmony_ci bool capath_from_env; 254113498266Sopenharmony_ci *added = FALSE; 254213498266Sopenharmony_ci 254313498266Sopenharmony_ci /* Check we have a url */ 254413498266Sopenharmony_ci if(!config->url_list || !config->url_list->url) { 254513498266Sopenharmony_ci helpf(tool_stderr, "(%d) no URL specified", CURLE_FAILED_INIT); 254613498266Sopenharmony_ci return CURLE_FAILED_INIT; 254713498266Sopenharmony_ci } 254813498266Sopenharmony_ci 254913498266Sopenharmony_ci /* On WIN32 we can't set the path to curl-ca-bundle.crt 255013498266Sopenharmony_ci * at compile time. So we look here for the file in two ways: 255113498266Sopenharmony_ci * 1: look at the environment variable CURL_CA_BUNDLE for a path 255213498266Sopenharmony_ci * 2: if #1 isn't found, use the windows API function SearchPath() 255313498266Sopenharmony_ci * to find it along the app's path (includes app's dir and CWD) 255413498266Sopenharmony_ci * 255513498266Sopenharmony_ci * We support the environment variable thing for non-Windows platforms 255613498266Sopenharmony_ci * too. Just for the sake of it. 255713498266Sopenharmony_ci */ 255813498266Sopenharmony_ci capath_from_env = false; 255913498266Sopenharmony_ci if(!config->cacert && 256013498266Sopenharmony_ci !config->capath && 256113498266Sopenharmony_ci (!config->insecure_ok || (config->doh_url && !config->doh_insecure_ok))) { 256213498266Sopenharmony_ci CURL *curltls = curl_easy_init(); 256313498266Sopenharmony_ci struct curl_tlssessioninfo *tls_backend_info = NULL; 256413498266Sopenharmony_ci 256513498266Sopenharmony_ci /* With the addition of CAINFO support for Schannel, this search could find 256613498266Sopenharmony_ci * a certificate bundle that was previously ignored. To maintain backward 256713498266Sopenharmony_ci * compatibility, only perform this search if not using Schannel. 256813498266Sopenharmony_ci */ 256913498266Sopenharmony_ci result = curl_easy_getinfo(curltls, CURLINFO_TLS_SSL_PTR, 257013498266Sopenharmony_ci &tls_backend_info); 257113498266Sopenharmony_ci if(result) { 257213498266Sopenharmony_ci curl_easy_cleanup(curltls); 257313498266Sopenharmony_ci return result; 257413498266Sopenharmony_ci } 257513498266Sopenharmony_ci 257613498266Sopenharmony_ci /* Set the CA cert locations specified in the environment. For Windows if 257713498266Sopenharmony_ci * no environment-specified filename is found then check for CA bundle 257813498266Sopenharmony_ci * default filename curl-ca-bundle.crt in the user's PATH. 257913498266Sopenharmony_ci * 258013498266Sopenharmony_ci * If Schannel is the selected SSL backend then these locations are 258113498266Sopenharmony_ci * ignored. We allow setting CA location for schannel only when explicitly 258213498266Sopenharmony_ci * specified by the user via CURLOPT_CAINFO / --cacert. 258313498266Sopenharmony_ci */ 258413498266Sopenharmony_ci if(tls_backend_info->backend != CURLSSLBACKEND_SCHANNEL) { 258513498266Sopenharmony_ci char *env; 258613498266Sopenharmony_ci env = curlx_getenv("CURL_CA_BUNDLE"); 258713498266Sopenharmony_ci if(env) { 258813498266Sopenharmony_ci config->cacert = strdup(env); 258913498266Sopenharmony_ci if(!config->cacert) { 259013498266Sopenharmony_ci curl_free(env); 259113498266Sopenharmony_ci curl_easy_cleanup(curltls); 259213498266Sopenharmony_ci errorf(global, "out of memory"); 259313498266Sopenharmony_ci return CURLE_OUT_OF_MEMORY; 259413498266Sopenharmony_ci } 259513498266Sopenharmony_ci } 259613498266Sopenharmony_ci else { 259713498266Sopenharmony_ci env = curlx_getenv("SSL_CERT_DIR"); 259813498266Sopenharmony_ci if(env) { 259913498266Sopenharmony_ci config->capath = strdup(env); 260013498266Sopenharmony_ci if(!config->capath) { 260113498266Sopenharmony_ci curl_free(env); 260213498266Sopenharmony_ci curl_easy_cleanup(curltls); 260313498266Sopenharmony_ci errorf(global, "out of memory"); 260413498266Sopenharmony_ci return CURLE_OUT_OF_MEMORY; 260513498266Sopenharmony_ci } 260613498266Sopenharmony_ci curl_free(env); 260713498266Sopenharmony_ci capath_from_env = true; 260813498266Sopenharmony_ci } 260913498266Sopenharmony_ci env = curlx_getenv("SSL_CERT_FILE"); 261013498266Sopenharmony_ci if(env) { 261113498266Sopenharmony_ci config->cacert = strdup(env); 261213498266Sopenharmony_ci if(!config->cacert) { 261313498266Sopenharmony_ci curl_free(env); 261413498266Sopenharmony_ci if(capath_from_env) 261513498266Sopenharmony_ci free(config->capath); 261613498266Sopenharmony_ci curl_easy_cleanup(curltls); 261713498266Sopenharmony_ci errorf(global, "out of memory"); 261813498266Sopenharmony_ci return CURLE_OUT_OF_MEMORY; 261913498266Sopenharmony_ci } 262013498266Sopenharmony_ci } 262113498266Sopenharmony_ci } 262213498266Sopenharmony_ci 262313498266Sopenharmony_ci if(env) 262413498266Sopenharmony_ci curl_free(env); 262513498266Sopenharmony_ci#ifdef _WIN32 262613498266Sopenharmony_ci else { 262713498266Sopenharmony_ci result = FindWin32CACert(config, tls_backend_info->backend, 262813498266Sopenharmony_ci TEXT("curl-ca-bundle.crt")); 262913498266Sopenharmony_ci } 263013498266Sopenharmony_ci#endif 263113498266Sopenharmony_ci } 263213498266Sopenharmony_ci curl_easy_cleanup(curltls); 263313498266Sopenharmony_ci } 263413498266Sopenharmony_ci 263513498266Sopenharmony_ci if(!result) 263613498266Sopenharmony_ci result = single_transfer(global, config, share, capath_from_env, added); 263713498266Sopenharmony_ci 263813498266Sopenharmony_ci return result; 263913498266Sopenharmony_ci} 264013498266Sopenharmony_ci 264113498266Sopenharmony_ci/* 264213498266Sopenharmony_ci * 'create_transfer' gets the details and sets up a new transfer if 'added' 264313498266Sopenharmony_ci * returns TRUE. 264413498266Sopenharmony_ci */ 264513498266Sopenharmony_cistatic CURLcode create_transfer(struct GlobalConfig *global, 264613498266Sopenharmony_ci CURLSH *share, 264713498266Sopenharmony_ci bool *added) 264813498266Sopenharmony_ci{ 264913498266Sopenharmony_ci CURLcode result = CURLE_OK; 265013498266Sopenharmony_ci *added = FALSE; 265113498266Sopenharmony_ci while(global->current) { 265213498266Sopenharmony_ci result = transfer_per_config(global, global->current, share, added); 265313498266Sopenharmony_ci if(!result && !*added) { 265413498266Sopenharmony_ci /* when one set is drained, continue to next */ 265513498266Sopenharmony_ci global->current = global->current->next; 265613498266Sopenharmony_ci continue; 265713498266Sopenharmony_ci } 265813498266Sopenharmony_ci break; 265913498266Sopenharmony_ci } 266013498266Sopenharmony_ci return result; 266113498266Sopenharmony_ci} 266213498266Sopenharmony_ci 266313498266Sopenharmony_cistatic CURLcode run_all_transfers(struct GlobalConfig *global, 266413498266Sopenharmony_ci CURLSH *share, 266513498266Sopenharmony_ci CURLcode result) 266613498266Sopenharmony_ci{ 266713498266Sopenharmony_ci /* Save the values of noprogress and isatty to restore them later on */ 266813498266Sopenharmony_ci bool orig_noprogress = global->noprogress; 266913498266Sopenharmony_ci bool orig_isatty = global->isatty; 267013498266Sopenharmony_ci struct per_transfer *per; 267113498266Sopenharmony_ci 267213498266Sopenharmony_ci /* Time to actually do the transfers */ 267313498266Sopenharmony_ci if(!result) { 267413498266Sopenharmony_ci if(global->parallel) 267513498266Sopenharmony_ci result = parallel_transfers(global, share); 267613498266Sopenharmony_ci else 267713498266Sopenharmony_ci result = serial_transfers(global, share); 267813498266Sopenharmony_ci } 267913498266Sopenharmony_ci 268013498266Sopenharmony_ci /* cleanup if there are any left */ 268113498266Sopenharmony_ci for(per = transfers; per;) { 268213498266Sopenharmony_ci bool retry; 268313498266Sopenharmony_ci long delay; 268413498266Sopenharmony_ci CURLcode result2 = post_per_transfer(global, per, result, &retry, &delay); 268513498266Sopenharmony_ci if(!result) 268613498266Sopenharmony_ci /* don't overwrite the original error */ 268713498266Sopenharmony_ci result = result2; 268813498266Sopenharmony_ci 268913498266Sopenharmony_ci /* Free list of given URLs */ 269013498266Sopenharmony_ci clean_getout(per->config); 269113498266Sopenharmony_ci 269213498266Sopenharmony_ci per = del_per_transfer(per); 269313498266Sopenharmony_ci } 269413498266Sopenharmony_ci 269513498266Sopenharmony_ci /* Reset the global config variables */ 269613498266Sopenharmony_ci global->noprogress = orig_noprogress; 269713498266Sopenharmony_ci global->isatty = orig_isatty; 269813498266Sopenharmony_ci 269913498266Sopenharmony_ci 270013498266Sopenharmony_ci return result; 270113498266Sopenharmony_ci} 270213498266Sopenharmony_ci 270313498266Sopenharmony_ciCURLcode operate(struct GlobalConfig *global, int argc, argv_item_t argv[]) 270413498266Sopenharmony_ci{ 270513498266Sopenharmony_ci CURLcode result = CURLE_OK; 270613498266Sopenharmony_ci char *first_arg = argc > 1 ? curlx_convert_tchar_to_UTF8(argv[1]) : NULL; 270713498266Sopenharmony_ci 270813498266Sopenharmony_ci#ifdef HAVE_SETLOCALE 270913498266Sopenharmony_ci /* Override locale for number parsing (only) */ 271013498266Sopenharmony_ci setlocale(LC_ALL, ""); 271113498266Sopenharmony_ci setlocale(LC_NUMERIC, "C"); 271213498266Sopenharmony_ci#endif 271313498266Sopenharmony_ci 271413498266Sopenharmony_ci /* Parse .curlrc if necessary */ 271513498266Sopenharmony_ci if((argc == 1) || 271613498266Sopenharmony_ci (first_arg && strncmp(first_arg, "-q", 2) && 271713498266Sopenharmony_ci !curl_strequal(first_arg, "--disable"))) { 271813498266Sopenharmony_ci parseconfig(NULL, global); /* ignore possible failure */ 271913498266Sopenharmony_ci 272013498266Sopenharmony_ci /* If we had no arguments then make sure a url was specified in .curlrc */ 272113498266Sopenharmony_ci if((argc < 2) && (!global->first->url_list)) { 272213498266Sopenharmony_ci helpf(tool_stderr, NULL); 272313498266Sopenharmony_ci result = CURLE_FAILED_INIT; 272413498266Sopenharmony_ci } 272513498266Sopenharmony_ci } 272613498266Sopenharmony_ci 272713498266Sopenharmony_ci curlx_unicodefree(first_arg); 272813498266Sopenharmony_ci 272913498266Sopenharmony_ci if(!result) { 273013498266Sopenharmony_ci /* Parse the command line arguments */ 273113498266Sopenharmony_ci ParameterError res = parse_args(global, argc, argv); 273213498266Sopenharmony_ci if(res) { 273313498266Sopenharmony_ci result = CURLE_OK; 273413498266Sopenharmony_ci 273513498266Sopenharmony_ci /* Check if we were asked for the help */ 273613498266Sopenharmony_ci if(res == PARAM_HELP_REQUESTED) 273713498266Sopenharmony_ci tool_help(global->help_category); 273813498266Sopenharmony_ci /* Check if we were asked for the manual */ 273913498266Sopenharmony_ci else if(res == PARAM_MANUAL_REQUESTED) 274013498266Sopenharmony_ci hugehelp(); 274113498266Sopenharmony_ci /* Check if we were asked for the version information */ 274213498266Sopenharmony_ci else if(res == PARAM_VERSION_INFO_REQUESTED) 274313498266Sopenharmony_ci tool_version_info(); 274413498266Sopenharmony_ci /* Check if we were asked to list the SSL engines */ 274513498266Sopenharmony_ci else if(res == PARAM_ENGINES_REQUESTED) 274613498266Sopenharmony_ci tool_list_engines(); 274713498266Sopenharmony_ci else if(res == PARAM_LIBCURL_UNSUPPORTED_PROTOCOL) 274813498266Sopenharmony_ci result = CURLE_UNSUPPORTED_PROTOCOL; 274913498266Sopenharmony_ci else if(res == PARAM_READ_ERROR) 275013498266Sopenharmony_ci result = CURLE_READ_ERROR; 275113498266Sopenharmony_ci else 275213498266Sopenharmony_ci result = CURLE_FAILED_INIT; 275313498266Sopenharmony_ci } 275413498266Sopenharmony_ci else { 275513498266Sopenharmony_ci if(global->libcurl) { 275613498266Sopenharmony_ci /* Initialise the libcurl source output */ 275713498266Sopenharmony_ci result = easysrc_init(); 275813498266Sopenharmony_ci } 275913498266Sopenharmony_ci 276013498266Sopenharmony_ci /* Perform the main operations */ 276113498266Sopenharmony_ci if(!result) { 276213498266Sopenharmony_ci size_t count = 0; 276313498266Sopenharmony_ci struct OperationConfig *operation = global->first; 276413498266Sopenharmony_ci CURLSH *share = curl_share_init(); 276513498266Sopenharmony_ci if(!share) { 276613498266Sopenharmony_ci if(global->libcurl) { 276713498266Sopenharmony_ci /* Cleanup the libcurl source output */ 276813498266Sopenharmony_ci easysrc_cleanup(); 276913498266Sopenharmony_ci } 277013498266Sopenharmony_ci result = CURLE_OUT_OF_MEMORY; 277113498266Sopenharmony_ci } 277213498266Sopenharmony_ci 277313498266Sopenharmony_ci if(!result) { 277413498266Sopenharmony_ci curl_share_setopt(share, CURLSHOPT_SHARE, CURL_LOCK_DATA_COOKIE); 277513498266Sopenharmony_ci curl_share_setopt(share, CURLSHOPT_SHARE, CURL_LOCK_DATA_DNS); 277613498266Sopenharmony_ci curl_share_setopt(share, CURLSHOPT_SHARE, 277713498266Sopenharmony_ci CURL_LOCK_DATA_SSL_SESSION); 277813498266Sopenharmony_ci curl_share_setopt(share, CURLSHOPT_SHARE, CURL_LOCK_DATA_CONNECT); 277913498266Sopenharmony_ci curl_share_setopt(share, CURLSHOPT_SHARE, CURL_LOCK_DATA_PSL); 278013498266Sopenharmony_ci curl_share_setopt(share, CURLSHOPT_SHARE, CURL_LOCK_DATA_HSTS); 278113498266Sopenharmony_ci 278213498266Sopenharmony_ci /* Get the required arguments for each operation */ 278313498266Sopenharmony_ci do { 278413498266Sopenharmony_ci result = get_args(operation, count++); 278513498266Sopenharmony_ci 278613498266Sopenharmony_ci operation = operation->next; 278713498266Sopenharmony_ci } while(!result && operation); 278813498266Sopenharmony_ci 278913498266Sopenharmony_ci /* Set the current operation pointer */ 279013498266Sopenharmony_ci global->current = global->first; 279113498266Sopenharmony_ci 279213498266Sopenharmony_ci /* now run! */ 279313498266Sopenharmony_ci result = run_all_transfers(global, share, result); 279413498266Sopenharmony_ci 279513498266Sopenharmony_ci curl_share_cleanup(share); 279613498266Sopenharmony_ci if(global->libcurl) { 279713498266Sopenharmony_ci /* Cleanup the libcurl source output */ 279813498266Sopenharmony_ci easysrc_cleanup(); 279913498266Sopenharmony_ci 280013498266Sopenharmony_ci /* Dump the libcurl code if previously enabled */ 280113498266Sopenharmony_ci dumpeasysrc(global); 280213498266Sopenharmony_ci } 280313498266Sopenharmony_ci } 280413498266Sopenharmony_ci } 280513498266Sopenharmony_ci else 280613498266Sopenharmony_ci errorf(global, "out of memory"); 280713498266Sopenharmony_ci } 280813498266Sopenharmony_ci } 280913498266Sopenharmony_ci 281013498266Sopenharmony_ci varcleanup(global); 281113498266Sopenharmony_ci 281213498266Sopenharmony_ci return result; 281313498266Sopenharmony_ci} 2814