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 | |
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 | |
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 | |
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 | */ |
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 || !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 | */ |
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 | |