blob: eb58772fb9c9b98e309c8c8c381f985bf846dae9 [file] [log] [blame]
xf.li6c8fc1e2023-08-12 00:11:09 -07001/***************************************************************************
2 * _ _ ____ _
3 * Project ___| | | | _ \| |
4 * / __| | | | |_) | |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
7 *
8 * Copyright (C) 1998 - 2022, 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
39void 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
58bool 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
68bool stdin_upload(const char *uploadfile)
69{
70 return (!strcmp(uploadfile, "-") ||
71 !strcmp(uploadfile, ".")) ? TRUE : FALSE;
72}
73
74/*
75 * Adds the file name to the URL if it doesn't already have one.
76 * url will be freed before return if the returned pointer is different
77 */
78CURLcode add_file_name_to_url(CURL *curl, char **inurlp, const char *filename)
79{
80 CURLcode result = CURLE_OUT_OF_MEMORY;
81 CURLU *uh = curl_url();
82 char *path = NULL;
83 if(uh) {
84 char *ptr;
85 if(curl_url_set(uh, CURLUPART_URL, *inurlp,
86 CURLU_GUESS_SCHEME|CURLU_NON_SUPPORT_SCHEME))
87 goto fail;
88 if(curl_url_get(uh, CURLUPART_PATH, &path, 0))
89 goto fail;
90
91 ptr = strrchr(path, '/');
92 if(!ptr || !*++ptr) {
93 /* The URL path has no file name part, add the local file name. In order
94 to be able to do so, we have to create a new URL in another buffer.*/
95
96 /* We only want the part of the local path that is on the right
97 side of the rightmost slash and backslash. */
98 const char *filep = strrchr(filename, '/');
99 char *file2 = strrchr(filep?filep:filename, '\\');
100 char *encfile;
101
102 if(file2)
103 filep = file2 + 1;
104 else if(filep)
105 filep++;
106 else
107 filep = filename;
108
109 /* URL encode the file name */
110 encfile = curl_easy_escape(curl, filep, 0 /* use strlen */);
111 if(encfile) {
112 char *newpath;
113 char *newurl;
114 CURLUcode uerr;
115 if(ptr)
116 /* there is a trailing slash on the path */
117 newpath = aprintf("%s%s", path, encfile);
118 else
119 /* there is no trailing slash on the path */
120 newpath = aprintf("%s/%s", path, encfile);
121
122 curl_free(encfile);
123
124 if(!newpath)
125 goto fail;
126 uerr = curl_url_set(uh, CURLUPART_PATH, newpath, 0);
127 free(newpath);
128 if(uerr)
129 goto fail;
130 if(curl_url_get(uh, CURLUPART_URL, &newurl, CURLU_DEFAULT_SCHEME))
131 goto fail;
132 free(*inurlp);
133 *inurlp = newurl;
134 result = CURLE_OK;
135 }
136 }
137 else
138 /* nothing to do */
139 result = CURLE_OK;
140 }
141 fail:
142 curl_url_cleanup(uh);
143 curl_free(path);
144 return result;
145}
146
147/* Extracts the name portion of the URL.
148 * Returns a pointer to a heap-allocated string or NULL if
149 * no name part, at location indicated by first argument.
150 */
151CURLcode get_url_file_name(char **filename, const char *url)
152{
153 const char *pc, *pc2;
154 CURLU *uh = curl_url();
155 char *path = NULL;
156
157 if(!uh)
158 return CURLE_OUT_OF_MEMORY;
159
160 *filename = NULL;
161
162 if(!curl_url_set(uh, CURLUPART_URL, url, CURLU_GUESS_SCHEME) &&
163 !curl_url_get(uh, CURLUPART_PATH, &path, 0)) {
164 curl_url_cleanup(uh);
165
166 pc = strrchr(path, '/');
167 pc2 = strrchr(pc ? pc + 1 : path, '\\');
168 if(pc2)
169 pc = pc2;
170
171 if(pc)
172 /* duplicate the string beyond the slash */
173 pc++;
174 else
175 /* no slash => empty string */
176 pc = "";
177
178 *filename = strdup(pc);
179 curl_free(path);
180 if(!*filename)
181 return CURLE_OUT_OF_MEMORY;
182
183#if defined(MSDOS) || defined(WIN32)
184 {
185 char *sanitized;
186 SANITIZEcode sc = sanitize_file_name(&sanitized, *filename, 0);
187 Curl_safefree(*filename);
188 if(sc)
189 return CURLE_URL_MALFORMAT;
190 *filename = sanitized;
191 }
192#endif /* MSDOS || WIN32 */
193
194 /* in case we built debug enabled, we allow an environment variable
195 * named CURL_TESTDIR to prefix the given file name to put it into a
196 * specific directory
197 */
198#ifdef DEBUGBUILD
199 {
200 char *tdir = curlx_getenv("CURL_TESTDIR");
201 if(tdir) {
202 char *alt = aprintf("%s/%s", tdir, *filename);
203 Curl_safefree(*filename);
204 *filename = alt;
205 curl_free(tdir);
206 if(!*filename)
207 return CURLE_OUT_OF_MEMORY;
208 }
209 }
210#endif
211 return CURLE_OK;
212 }
213 curl_url_cleanup(uh);
214 return CURLE_URL_MALFORMAT;
215}