tool_operhlp.c (6852B)
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 "tool_cfgable.h" 28 #include "tool_doswin.h" 29 #include "tool_operhlp.h" 30 #include "tool_msgs.h" 31 #include "memdebug.h" /* keep this as LAST include */ 32 33 void clean_getout(struct OperationConfig *config) 34 { 35 if(config) { 36 struct getout *next; 37 struct getout *node = config->url_list; 38 39 while(node) { 40 next = node->next; 41 tool_safefree(node->url); 42 tool_safefree(node->outfile); 43 tool_safefree(node->infile); 44 tool_safefree(node); 45 node = next; 46 } 47 config->url_list = NULL; 48 } 49 single_transfer_cleanup(config); 50 } 51 52 bool output_expected(const char *url, const char *uploadfile) 53 { 54 if(!uploadfile) 55 return TRUE; /* download */ 56 if(checkprefix("http://", url) || checkprefix("https://", url)) 57 return TRUE; /* HTTP(S) upload */ 58 59 return FALSE; /* non-HTTP upload, probably no output should be expected */ 60 } 61 62 bool stdin_upload(const char *uploadfile) 63 { 64 return !strcmp(uploadfile, "-") || !strcmp(uploadfile, "."); 65 } 66 67 /* Convert a CURLUcode into a CURLcode */ 68 CURLcode urlerr_cvt(CURLUcode ucode) 69 { 70 if(ucode == CURLUE_OUT_OF_MEMORY) 71 return CURLE_OUT_OF_MEMORY; 72 else if(ucode == CURLUE_UNSUPPORTED_SCHEME) 73 return CURLE_UNSUPPORTED_PROTOCOL; 74 else if(ucode == CURLUE_LACKS_IDN) 75 return CURLE_NOT_BUILT_IN; 76 else if(ucode == CURLUE_BAD_HANDLE) 77 return CURLE_BAD_FUNCTION_ARGUMENT; 78 return CURLE_URL_MALFORMAT; 79 } 80 81 /* 82 * Adds the filename to the URL if it does not already have one. 83 * url will be freed before return if the returned pointer is different 84 */ 85 CURLcode add_file_name_to_url(CURL *curl, char **inurlp, const char *filename) 86 { 87 CURLcode result = CURLE_URL_MALFORMAT; 88 CURLUcode uerr; 89 CURLU *uh = curl_url(); 90 char *path = NULL; 91 char *query = NULL; 92 if(uh) { 93 char *ptr; 94 uerr = curl_url_set(uh, CURLUPART_URL, *inurlp, 95 CURLU_GUESS_SCHEME|CURLU_NON_SUPPORT_SCHEME); 96 if(uerr) { 97 result = urlerr_cvt(uerr); 98 goto fail; 99 } 100 uerr = curl_url_get(uh, CURLUPART_PATH, &path, 0); 101 if(uerr) { 102 result = urlerr_cvt(uerr); 103 goto fail; 104 } 105 uerr = curl_url_get(uh, CURLUPART_QUERY, &query, 0); 106 if(!uerr && query) { 107 curl_free(query); 108 curl_free(path); 109 curl_url_cleanup(uh); 110 return CURLE_OK; 111 } 112 ptr = strrchr(path, '/'); 113 if(!ptr || !*++ptr) { 114 /* The URL path has no filename part, add the local filename. In order 115 to be able to do so, we have to create a new URL in another buffer.*/ 116 117 /* We only want the part of the local path that is on the right 118 side of the rightmost slash and backslash. */ 119 const char *filep = strrchr(filename, '/'); 120 char *file2 = strrchr(filep ? filep : filename, '\\'); 121 char *encfile; 122 123 if(file2) 124 filep = file2 + 1; 125 else if(filep) 126 filep++; 127 else 128 filep = filename; 129 130 /* URL encode the filename */ 131 encfile = curl_easy_escape(curl, filep, 0 /* use strlen */); 132 if(encfile) { 133 char *newpath; 134 char *newurl; 135 if(ptr) 136 /* there is a trailing slash on the path */ 137 newpath = aprintf("%s%s", path, encfile); 138 else 139 /* there is no trailing slash on the path */ 140 newpath = aprintf("%s/%s", path, encfile); 141 142 curl_free(encfile); 143 144 if(!newpath) 145 goto fail; 146 uerr = curl_url_set(uh, CURLUPART_PATH, newpath, 0); 147 free(newpath); 148 if(uerr) { 149 result = urlerr_cvt(uerr); 150 goto fail; 151 } 152 uerr = curl_url_get(uh, CURLUPART_URL, &newurl, CURLU_DEFAULT_SCHEME); 153 if(uerr) { 154 result = urlerr_cvt(uerr); 155 goto fail; 156 } 157 free(*inurlp); 158 *inurlp = newurl; 159 result = CURLE_OK; 160 } 161 } 162 else 163 /* nothing to do */ 164 result = CURLE_OK; 165 } 166 fail: 167 curl_url_cleanup(uh); 168 curl_free(path); 169 return result; 170 } 171 172 /* Extracts the name portion of the URL. 173 * Returns a pointer to a heap-allocated string or NULL if 174 * no name part, at location indicated by first argument. 175 */ 176 CURLcode get_url_file_name(struct GlobalConfig *global, 177 char **filename, const char *url) 178 { 179 CURLU *uh = curl_url(); 180 char *path = NULL; 181 CURLUcode uerr; 182 183 if(!uh) 184 return CURLE_OUT_OF_MEMORY; 185 186 *filename = NULL; 187 188 uerr = curl_url_set(uh, CURLUPART_URL, url, CURLU_GUESS_SCHEME); 189 if(!uerr) { 190 uerr = curl_url_get(uh, CURLUPART_PATH, &path, 0); 191 curl_url_cleanup(uh); 192 uh = NULL; 193 if(!uerr) { 194 int i; 195 char *pc = NULL, *pc2 = NULL; 196 for(i = 0; i < 2; i++) { 197 pc = strrchr(path, '/'); 198 pc2 = strrchr(pc ? pc + 1 : path, '\\'); 199 if(pc2) 200 pc = pc2; 201 if(pc && !pc[1] && !i) { 202 /* if the path ends with slash, try removing the trailing one 203 and get the last directory part */ 204 *pc = 0; 205 } 206 } 207 208 if(pc) { 209 /* duplicate the string beyond the slash */ 210 *filename = strdup(pc + 1); 211 } 212 else { 213 /* no slash => empty string, use default */ 214 *filename = strdup("curl_response"); 215 warnf(global, "No remote file name, uses \"%s\"", *filename); 216 } 217 218 curl_free(path); 219 if(!*filename) 220 return CURLE_OUT_OF_MEMORY; 221 222 #if defined(_WIN32) || defined(MSDOS) 223 { 224 char *sanitized; 225 SANITIZEcode sc = sanitize_file_name(&sanitized, *filename, 0); 226 tool_safefree(*filename); 227 if(sc) { 228 if(sc == SANITIZE_ERR_OUT_OF_MEMORY) 229 return CURLE_OUT_OF_MEMORY; 230 return CURLE_URL_MALFORMAT; 231 } 232 *filename = sanitized; 233 } 234 #endif /* _WIN32 || MSDOS */ 235 236 return CURLE_OK; 237 } 238 } 239 curl_url_cleanup(uh); 240 return urlerr_cvt(uerr); 241 }