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