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