1/***************************************************************************
2 * _ _ ____ _
3 * Project ___| | | | _ \| |
4 * / __| | | | |_) | |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
7 *
8 * Copyright (C) 1998 - 2019, 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
38void 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
56bool 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
66bool 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 */
76char *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 || !strlen(++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 Curl_safefree(url);
119
120 if(!urlbuffer)
121 return NULL;
122
123 url = urlbuffer; /* use our new URL instead! */
124 }
125 else
126 Curl_safefree(url);
127 }
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 */
136CURLcode 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