1/*************************************************************************** 2 * _ _ ____ _ 3 * Project ___| | | | _ \| | 4 * / __| | | | |_) | | 5 * | (__| |_| | _ <| |___ 6 * \___|\___/|_| \_\_____| 7 * 8 * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al. 9 * 10 * This software is licensed as described in the file COPYING, which 11 * you should have received as part of this distribution. The terms 12 * are also available at https://curl.se/docs/copyright.html. 13 * 14 * You may opt to use, copy, modify, merge, publish, distribute and/or sell 15 * copies of the Software, and permit persons to whom the Software is 16 * furnished to do so, under the terms of the COPYING file. 17 * 18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 19 * KIND, either express or implied. 20 * 21 * SPDX-License-Identifier: curl 22 * 23 ***************************************************************************/ 24#include "tool_setup.h" 25#include "tool_operate.h" 26 27#include "strcase.h" 28 29#define ENABLE_CURLX_PRINTF 30/* use our own printf() functions */ 31#include "curlx.h" 32 33#include "tool_cfgable.h" 34#include "tool_doswin.h" 35#include "tool_operhlp.h" 36 37#include "memdebug.h" /* keep this as LAST include */ 38 39void clean_getout(struct OperationConfig *config) 40{ 41 if(config) { 42 struct getout *next; 43 struct getout *node = config->url_list; 44 45 while(node) { 46 next = node->next; 47 Curl_safefree(node->url); 48 Curl_safefree(node->outfile); 49 Curl_safefree(node->infile); 50 Curl_safefree(node); 51 node = next; 52 } 53 config->url_list = NULL; 54 } 55 single_transfer_cleanup(config); 56} 57 58bool output_expected(const char *url, const char *uploadfile) 59{ 60 if(!uploadfile) 61 return TRUE; /* download */ 62 if(checkprefix("http://", url) || checkprefix("https://", url)) 63 return TRUE; /* HTTP(S) upload */ 64 65 return FALSE; /* non-HTTP upload, probably no output should be expected */ 66} 67 68bool stdin_upload(const char *uploadfile) 69{ 70 return (!strcmp(uploadfile, "-") || 71 !strcmp(uploadfile, ".")) ? TRUE : FALSE; 72} 73 74/* Convert a CURLUcode into a CURLcode */ 75CURLcode urlerr_cvt(CURLUcode ucode) 76{ 77 if(ucode == CURLUE_OUT_OF_MEMORY) 78 return CURLE_OUT_OF_MEMORY; 79 else if(ucode == CURLUE_UNSUPPORTED_SCHEME) 80 return CURLE_UNSUPPORTED_PROTOCOL; 81 else if(ucode == CURLUE_LACKS_IDN) 82 return CURLE_NOT_BUILT_IN; 83 else if(ucode == CURLUE_BAD_HANDLE) 84 return CURLE_BAD_FUNCTION_ARGUMENT; 85 return CURLE_URL_MALFORMAT; 86} 87 88/* 89 * Adds the file name to the URL if it doesn't already have one. 90 * url will be freed before return if the returned pointer is different 91 */ 92CURLcode add_file_name_to_url(CURL *curl, char **inurlp, const char *filename) 93{ 94 CURLcode result = CURLE_URL_MALFORMAT; 95 CURLUcode uerr; 96 CURLU *uh = curl_url(); 97 char *path = NULL; 98 char *query = NULL; 99 if(uh) { 100 char *ptr; 101 uerr = curl_url_set(uh, CURLUPART_URL, *inurlp, 102 CURLU_GUESS_SCHEME|CURLU_NON_SUPPORT_SCHEME); 103 if(uerr) { 104 result = urlerr_cvt(uerr); 105 goto fail; 106 } 107 uerr = curl_url_get(uh, CURLUPART_PATH, &path, 0); 108 if(uerr) { 109 result = urlerr_cvt(uerr); 110 goto fail; 111 } 112 uerr = curl_url_get(uh, CURLUPART_QUERY, &query, 0); 113 if(!uerr && query) { 114 curl_free(query); 115 curl_free(path); 116 curl_url_cleanup(uh); 117 return CURLE_OK; 118 } 119 ptr = strrchr(path, '/'); 120 if(!ptr || !*++ptr) { 121 /* The URL path has no file name part, add the local file name. In order 122 to be able to do so, we have to create a new URL in another buffer.*/ 123 124 /* We only want the part of the local path that is on the right 125 side of the rightmost slash and backslash. */ 126 const char *filep = strrchr(filename, '/'); 127 char *file2 = strrchr(filep?filep:filename, '\\'); 128 char *encfile; 129 130 if(file2) 131 filep = file2 + 1; 132 else if(filep) 133 filep++; 134 else 135 filep = filename; 136 137 /* URL encode the file name */ 138 encfile = curl_easy_escape(curl, filep, 0 /* use strlen */); 139 if(encfile) { 140 char *newpath; 141 char *newurl; 142 if(ptr) 143 /* there is a trailing slash on the path */ 144 newpath = aprintf("%s%s", path, encfile); 145 else 146 /* there is no trailing slash on the path */ 147 newpath = aprintf("%s/%s", path, encfile); 148 149 curl_free(encfile); 150 151 if(!newpath) 152 goto fail; 153 uerr = curl_url_set(uh, CURLUPART_PATH, newpath, 0); 154 free(newpath); 155 if(uerr) { 156 result = urlerr_cvt(uerr); 157 goto fail; 158 } 159 uerr = curl_url_get(uh, CURLUPART_URL, &newurl, CURLU_DEFAULT_SCHEME); 160 if(uerr) { 161 result = urlerr_cvt(uerr); 162 goto fail; 163 } 164 free(*inurlp); 165 *inurlp = newurl; 166 result = CURLE_OK; 167 } 168 } 169 else 170 /* nothing to do */ 171 result = CURLE_OK; 172 } 173fail: 174 curl_url_cleanup(uh); 175 curl_free(path); 176 return result; 177} 178 179/* Extracts the name portion of the URL. 180 * Returns a pointer to a heap-allocated string or NULL if 181 * no name part, at location indicated by first argument. 182 */ 183CURLcode get_url_file_name(char **filename, const char *url) 184{ 185 const char *pc, *pc2; 186 CURLU *uh = curl_url(); 187 char *path = NULL; 188 CURLUcode uerr; 189 190 if(!uh) 191 return CURLE_OUT_OF_MEMORY; 192 193 *filename = NULL; 194 195 uerr = curl_url_set(uh, CURLUPART_URL, url, CURLU_GUESS_SCHEME); 196 if(!uerr) { 197 uerr = curl_url_get(uh, CURLUPART_PATH, &path, 0); 198 if(!uerr) { 199 curl_url_cleanup(uh); 200 201 pc = strrchr(path, '/'); 202 pc2 = strrchr(pc ? pc + 1 : path, '\\'); 203 if(pc2) 204 pc = pc2; 205 206 if(pc) 207 /* duplicate the string beyond the slash */ 208 pc++; 209 else 210 /* no slash => empty string */ 211 pc = ""; 212 213 *filename = strdup(pc); 214 curl_free(path); 215 if(!*filename) 216 return CURLE_OUT_OF_MEMORY; 217 218#if defined(_WIN32) || defined(MSDOS) 219 { 220 char *sanitized; 221 SANITIZEcode sc = sanitize_file_name(&sanitized, *filename, 0); 222 Curl_safefree(*filename); 223 if(sc) { 224 if(sc == SANITIZE_ERR_OUT_OF_MEMORY) 225 return CURLE_OUT_OF_MEMORY; 226 return CURLE_URL_MALFORMAT; 227 } 228 *filename = sanitized; 229 } 230#endif /* _WIN32 || MSDOS */ 231 232 /* in case we built debug enabled, we allow an environment variable 233 * named CURL_TESTDIR to prefix the given file name to put it into a 234 * specific directory 235 */ 236#ifdef DEBUGBUILD 237 { 238 char *tdir = curlx_getenv("CURL_TESTDIR"); 239 if(tdir) { 240 char *alt = aprintf("%s/%s", tdir, *filename); 241 Curl_safefree(*filename); 242 *filename = alt; 243 curl_free(tdir); 244 if(!*filename) 245 return CURLE_OUT_OF_MEMORY; 246 } 247 } 248#endif 249 return CURLE_OK; 250 } 251 } 252 curl_url_cleanup(uh); 253 return urlerr_cvt(uerr); 254} 255