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