1 /***************************************************************************
2  *                                  _   _ ____  _
3  *  Project                     ___| | | |  _ \| |
4  *                             / __| | | | |_) | |
5  *                            | (__| |_| |  _ <| |___
6  *                             \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 1998 - 2020, 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.haxx.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  ***************************************************************************/
22 #include "tool_setup.h"
23 
24 #include "strcase.h"
25 
26 #define ENABLE_CURLX_PRINTF
27 /* use our own printf() functions */
28 #include "curlx.h"
29 
30 #include "tool_cfgable.h"
31 #include "tool_convert.h"
32 #include "tool_doswin.h"
33 #include "tool_operhlp.h"
34 #include "tool_metalink.h"
35 
36 #include "memdebug.h" /* keep this as LAST include */
37 
clean_getout(struct OperationConfig * config)38 void clean_getout(struct OperationConfig *config)
39 {
40   if(config) {
41     struct getout *next;
42     struct getout *node = config->url_list;
43 
44     while(node) {
45       next = node->next;
46       Curl_safefree(node->url);
47       Curl_safefree(node->outfile);
48       Curl_safefree(node->infile);
49       Curl_safefree(node);
50       node = next;
51     }
52     config->url_list = NULL;
53   }
54 }
55 
output_expected(const char * url,const char * uploadfile)56 bool output_expected(const char *url, const char *uploadfile)
57 {
58   if(!uploadfile)
59     return TRUE;  /* download */
60   if(checkprefix("http://", url) || checkprefix("https://", url))
61     return TRUE;   /* HTTP(S) upload */
62 
63   return FALSE; /* non-HTTP upload, probably no output should be expected */
64 }
65 
stdin_upload(const char * uploadfile)66 bool stdin_upload(const char *uploadfile)
67 {
68   return (!strcmp(uploadfile, "-") ||
69           !strcmp(uploadfile, ".")) ? TRUE : FALSE;
70 }
71 
72 /*
73  * Adds the file name to the URL if it doesn't already have one.
74  * url will be freed before return if the returned pointer is different
75  */
add_file_name_to_url(char * url,const char * filename)76 char *add_file_name_to_url(char *url, const char *filename)
77 {
78   /* If no file name part is given in the URL, we add this file name */
79   char *ptr = strstr(url, "://");
80   CURL *curl = curl_easy_init(); /* for url escaping */
81   if(!curl)
82     return NULL; /* error! */
83   if(ptr)
84     ptr += 3;
85   else
86     ptr = url;
87   ptr = strrchr(ptr, '/');
88   if(!ptr || !*++ptr) {
89     /* The URL has no file name part, add the local file name. In order
90        to be able to do so, we have to create a new URL in another
91        buffer.*/
92 
93     /* We only want the part of the local path that is on the right
94        side of the rightmost slash and backslash. */
95     const char *filep = strrchr(filename, '/');
96     char *file2 = strrchr(filep?filep:filename, '\\');
97     char *encfile;
98 
99     if(file2)
100       filep = file2 + 1;
101     else if(filep)
102       filep++;
103     else
104       filep = filename;
105 
106     /* URL encode the file name */
107     encfile = curl_easy_escape(curl, filep, 0 /* use strlen */);
108     if(encfile) {
109       char *urlbuffer;
110       if(ptr)
111         /* there is a trailing slash on the URL */
112         urlbuffer = aprintf("%s%s", url, encfile);
113       else
114         /* there is no trailing slash on the URL */
115         urlbuffer = aprintf("%s/%s", url, encfile);
116 
117       curl_free(encfile);
118 
119       if(!urlbuffer) {
120         url = NULL;
121         goto end;
122       }
123 
124       Curl_safefree(url);
125       url = urlbuffer; /* use our new URL instead! */
126     }
127   }
128   end:
129   curl_easy_cleanup(curl);
130   return url;
131 }
132 
133 /* Extracts the name portion of the URL.
134  * Returns a pointer to a heap-allocated string or NULL if
135  * no name part, at location indicated by first argument.
136  */
get_url_file_name(char ** filename,const char * url)137 CURLcode get_url_file_name(char **filename, const char *url)
138 {
139   const char *pc, *pc2;
140 
141   *filename = NULL;
142 
143   /* Find and get the remote file name */
144   pc = strstr(url, "://");
145   if(pc)
146     pc += 3;
147   else
148     pc = url;
149 
150   pc2 = strrchr(pc, '\\');
151   pc = strrchr(pc, '/');
152   if(pc2 && (!pc || pc < pc2))
153     pc = pc2;
154 
155   if(pc)
156     /* duplicate the string beyond the slash */
157     pc++;
158   else
159     /* no slash => empty string */
160     pc = "";
161 
162   *filename = strdup(pc);
163   if(!*filename)
164     return CURLE_OUT_OF_MEMORY;
165 
166 #if defined(MSDOS) || defined(WIN32)
167   {
168     char *sanitized;
169     SANITIZEcode sc = sanitize_file_name(&sanitized, *filename, 0);
170     Curl_safefree(*filename);
171     if(sc)
172       return CURLE_URL_MALFORMAT;
173     *filename = sanitized;
174   }
175 #endif /* MSDOS || WIN32 */
176 
177   /* in case we built debug enabled, we allow an environment variable
178    * named CURL_TESTDIR to prefix the given file name to put it into a
179    * specific directory
180    */
181 #ifdef DEBUGBUILD
182   {
183     char *tdir = curlx_getenv("CURL_TESTDIR");
184     if(tdir) {
185       char buffer[512]; /* suitably large */
186       msnprintf(buffer, sizeof(buffer), "%s/%s", tdir, *filename);
187       Curl_safefree(*filename);
188       *filename = strdup(buffer); /* clone the buffer */
189       curl_free(tdir);
190       if(!*filename)
191         return CURLE_OUT_OF_MEMORY;
192     }
193   }
194 #endif
195 
196   return CURLE_OK;
197 }
198