c33ca507dae2134d71e4b12bc297ad7a8bb1781a
[platform/upstream/curl.git] / src / tool_operhlp.c
1 /***************************************************************************
2  *                                  _   _ ____  _
3  *  Project                     ___| | | |  _ \| |
4  *                             / __| | | | |_) | |
5  *                            | (__| |_| |  _ <| |___
6  *                             \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 1998 - 2013, 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 http://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 "rawstr.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_operhlp.h"
33 #include "tool_version.h"
34 #include "tool_metalink.h"
35
36 #include "memdebug.h" /* keep this as LAST include */
37
38 /*
39  * my_useragent: returns allocated string with default user agent
40  */
41 char *my_useragent(void)
42 {
43   return strdup( CURL_NAME "/" CURL_VERSION );
44 }
45
46 /*
47  * Print list of OpenSSL supported engines
48  */
49 void list_engines(const struct curl_slist *engines)
50 {
51   puts("Build-time engines:");
52   if(!engines) {
53     puts("  <none>");
54     return;
55   }
56   for(; engines; engines = engines->next)
57     printf("  %s\n", engines->data);
58 }
59
60 void clean_getout(struct Configurable *config)
61 {
62   struct getout *next;
63   struct getout *node = config->url_list;
64
65   while(node) {
66     next = node->next;
67     Curl_safefree(node->url);
68     Curl_safefree(node->outfile);
69     Curl_safefree(node->infile);
70     Curl_safefree(node);
71     node = next;
72   }
73   config->url_list = NULL;
74 }
75
76 bool output_expected(const char *url, const char *uploadfile)
77 {
78   if(!uploadfile)
79     return TRUE;  /* download */
80   if(checkprefix("http://", url) || checkprefix("https://", url))
81     return TRUE;   /* HTTP(S) upload */
82
83   return FALSE; /* non-HTTP upload, probably no output should be expected */
84 }
85
86 bool stdin_upload(const char *uploadfile)
87 {
88   return (curlx_strequal(uploadfile, "-") ||
89           curlx_strequal(uploadfile, ".")) ? TRUE : FALSE;
90 }
91
92 /*
93  * Adds the file name to the URL if it doesn't already have one.
94  * url will be freed before return if the returned pointer is different
95  */
96 char *add_file_name_to_url(CURL *curl, char *url, const char *filename)
97 {
98   /* If no file name part is given in the URL, we add this file name */
99   char *ptr = strstr(url, "://");
100   if(ptr)
101     ptr += 3;
102   else
103     ptr = url;
104   ptr = strrchr(ptr, '/');
105   if(!ptr || !strlen(++ptr)) {
106     /* The URL has no file name part, add the local file name. In order
107        to be able to do so, we have to create a new URL in another
108        buffer.*/
109
110     /* We only want the part of the local path that is on the right
111        side of the rightmost slash and backslash. */
112     const char *filep = strrchr(filename, '/');
113     char *file2 = strrchr(filep?filep:filename, '\\');
114     char *encfile;
115
116     if(file2)
117       filep = file2 + 1;
118     else if(filep)
119       filep++;
120     else
121       filep = filename;
122
123     /* URL encode the file name */
124     encfile = curl_easy_escape(curl, filep, 0 /* use strlen */);
125     if(encfile) {
126       char *urlbuffer;
127       if(ptr)
128         /* there is a trailing slash on the URL */
129         urlbuffer = aprintf("%s%s", url, encfile);
130       else
131         /* there is no trailing slash on the URL */
132         urlbuffer = aprintf("%s/%s", url, encfile);
133
134       curl_free(encfile);
135       Curl_safefree(url);
136
137       if(!urlbuffer)
138         return NULL;
139
140       url = urlbuffer; /* use our new URL instead! */
141     }
142     else
143       Curl_safefree(url);
144   }
145   return url;
146 }
147
148 /* Extracts the name portion of the URL.
149  * Returns a pointer to a heap-allocated string or NULL if
150  * no name part, at location indicated by first argument.
151  */
152 CURLcode get_url_file_name(char **filename, const char *url)
153 {
154   const char *pc;
155
156   *filename = NULL;
157
158   /* Find and get the remote file name */
159   pc = strstr(url, "://");
160   if(pc)
161     pc += 3;
162   else
163     pc = url;
164   pc = strrchr(pc, '/');
165
166   if(pc) {
167     /* duplicate the string beyond the slash */
168     pc++;
169     if(*pc) {
170       *filename = strdup(pc);
171       if(!*filename)
172         return CURLE_OUT_OF_MEMORY;
173     }
174   }
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       snprintf(buffer, sizeof(buffer), "%s/%s", tdir, *filename);
186       Curl_safefree(*filename);
187       *filename = strdup(buffer); /* clone the buffer */
188       curl_free(tdir);
189     }
190   }
191 #endif
192
193   return CURLE_OK;
194 }
195
196 /*
197  * This is the main global constructor for the app. Call this before
198  * _any_ libcurl usage. If this fails, *NO* libcurl functions may be
199  * used, or havoc may be the result.
200  */
201 CURLcode main_init(void)
202 {
203 #if defined(__DJGPP__) || defined(__GO32__)
204   /* stop stat() wasting time */
205   _djstat_flags |= _STAT_INODE | _STAT_EXEC_MAGIC | _STAT_DIRSIZE;
206 #endif
207
208   return curl_global_init(CURL_GLOBAL_DEFAULT);
209 }
210
211 /*
212  * This is the main global destructor for the app. Call this after
213  * _all_ libcurl usage is done.
214  */
215 void main_free(void)
216 {
217   curl_global_cleanup();
218   convert_cleanup();
219   metalink_cleanup();
220 }
221
222 #ifdef CURLDEBUG
223 void memory_tracking_init(void)
224 {
225   char *env;
226   /* if CURL_MEMDEBUG is set, this starts memory tracking message logging */
227   env = curlx_getenv("CURL_MEMDEBUG");
228   if(env) {
229     /* use the value as file name */
230     char fname[CURL_MT_LOGFNAME_BUFSIZE];
231     if(strlen(env) >= CURL_MT_LOGFNAME_BUFSIZE)
232       env[CURL_MT_LOGFNAME_BUFSIZE-1] = '\0';
233     strcpy(fname, env);
234     curl_free(env);
235     curl_memdebug(fname);
236     /* this weird stuff here is to make curl_free() get called
237        before curl_memdebug() as otherwise memory tracking will
238        log a free() without an alloc! */
239   }
240   /* if CURL_MEMLIMIT is set, this enables fail-on-alloc-number-N feature */
241   env = curlx_getenv("CURL_MEMLIMIT");
242   if(env) {
243     char *endptr;
244     long num = strtol(env, &endptr, 10);
245     if((endptr != env) && (endptr == env + strlen(env)) && (num > 0))
246       curl_memlimit(num);
247     curl_free(env);
248   }
249 }
250 #endif
251