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