• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
clean_getout(struct OperationConfig * config)39 void 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 
output_expected(const char * url,const char * uploadfile)58 bool 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 
stdin_upload(const char * uploadfile)68 bool stdin_upload(const char *uploadfile)
69 {
70   return (!strcmp(uploadfile, "-") ||
71           !strcmp(uploadfile, ".")) ? TRUE : FALSE;
72 }
73 
74 /* Convert a CURLUcode into a CURLcode */
urlerr_cvt(CURLUcode ucode)75 CURLcode 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  */
add_file_name_to_url(CURL * curl,char ** inurlp,const char * filename)92 CURLcode 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   if(uh) {
99     char *ptr;
100     uerr = curl_url_set(uh, CURLUPART_URL, *inurlp,
101                     CURLU_GUESS_SCHEME|CURLU_NON_SUPPORT_SCHEME);
102     if(uerr) {
103       result = urlerr_cvt(uerr);
104       goto fail;
105     }
106     uerr = curl_url_get(uh, CURLUPART_PATH, &path, 0);
107     if(uerr) {
108       result = urlerr_cvt(uerr);
109       goto fail;
110     }
111 
112     ptr = strrchr(path, '/');
113     if(!ptr || !*++ptr) {
114       /* The URL path has no file name part, add the local file name. 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 file name */
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  */
get_url_file_name(char ** filename,const char * url)176 CURLcode get_url_file_name(char **filename, const char *url)
177 {
178   const char *pc, *pc2;
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     if(!uerr) {
192       curl_url_cleanup(uh);
193 
194       pc = strrchr(path, '/');
195       pc2 = strrchr(pc ? pc + 1 : path, '\\');
196       if(pc2)
197         pc = pc2;
198 
199       if(pc)
200         /* duplicate the string beyond the slash */
201         pc++;
202       else
203         /* no slash => empty string */
204         pc = "";
205 
206       *filename = strdup(pc);
207       curl_free(path);
208       if(!*filename)
209         return CURLE_OUT_OF_MEMORY;
210 
211 #if defined(MSDOS) || defined(WIN32)
212       {
213         char *sanitized;
214         SANITIZEcode sc = sanitize_file_name(&sanitized, *filename, 0);
215         Curl_safefree(*filename);
216         if(sc) {
217           if(sc == SANITIZE_ERR_OUT_OF_MEMORY)
218             return CURLE_OUT_OF_MEMORY;
219           return CURLE_URL_MALFORMAT;
220         }
221         *filename = sanitized;
222       }
223 #endif /* MSDOS || WIN32 */
224 
225       /* in case we built debug enabled, we allow an environment variable
226        * named CURL_TESTDIR to prefix the given file name to put it into a
227        * specific directory
228        */
229 #ifdef DEBUGBUILD
230       {
231         char *tdir = curlx_getenv("CURL_TESTDIR");
232         if(tdir) {
233           char *alt = aprintf("%s/%s", tdir, *filename);
234           Curl_safefree(*filename);
235           *filename = alt;
236           curl_free(tdir);
237           if(!*filename)
238             return CURLE_OUT_OF_MEMORY;
239         }
240       }
241 #endif
242       return CURLE_OK;
243     }
244   }
245   curl_url_cleanup(uh);
246   return urlerr_cvt(uerr);
247 }
248