xref: /aosp_15_r20/external/curl/src/tool_operhlp.c (revision 6236dae45794135f37c4eb022389c904c8b0090d)
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