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 */ 41char *my_useragent(void) 42{ 43 return strdup( CURL_NAME "/" CURL_VERSION ); 44} 45 46/* 47 * Print list of OpenSSL supported engines 48 */ 49void 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 60void 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 76bool 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 86bool 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 */ 96char *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 } 143 return url; 144} 145 146/* Extracts the name portion of the URL. 147 * Returns a pointer to a heap-allocated string or NULL if 148 * no name part, at location indicated by first argument. 149 */ 150CURLcode get_url_file_name(char **filename, const char *url) 151{ 152 const char *pc; 153 154 *filename = NULL; 155 156 /* Find and get the remote file name */ 157 pc = strstr(url, "://"); 158 if(pc) 159 pc += 3; 160 else 161 pc = url; 162 pc = strrchr(pc, '/'); 163 164 if(pc) { 165 /* duplicate the string beyond the slash */ 166 pc++; 167 if(*pc) { 168 *filename = strdup(pc); 169 if(!*filename) 170 return CURLE_OUT_OF_MEMORY; 171 } 172 } 173 174 /* in case we built debug enabled, we allow an environment variable 175 * named CURL_TESTDIR to prefix the given file name to put it into a 176 * specific directory 177 */ 178#ifdef DEBUGBUILD 179 { 180 char *tdir = curlx_getenv("CURL_TESTDIR"); 181 if(tdir) { 182 char buffer[512]; /* suitably large */ 183 snprintf(buffer, sizeof(buffer), "%s/%s", tdir, *filename); 184 Curl_safefree(*filename); 185 *filename = strdup(buffer); /* clone the buffer */ 186 curl_free(tdir); 187 } 188 } 189#endif 190 191 return CURLE_OK; 192} 193 194/* 195 * This is the main global constructor for the app. Call this before 196 * _any_ libcurl usage. If this fails, *NO* libcurl functions may be 197 * used, or havoc may be the result. 198 */ 199CURLcode main_init(void) 200{ 201#if defined(__DJGPP__) || defined(__GO32__) 202 /* stop stat() wasting time */ 203 _djstat_flags |= _STAT_INODE | _STAT_EXEC_MAGIC | _STAT_DIRSIZE; 204#endif 205 206 return curl_global_init(CURL_GLOBAL_DEFAULT); 207} 208 209/* 210 * This is the main global destructor for the app. Call this after 211 * _all_ libcurl usage is done. 212 */ 213void main_free(void) 214{ 215 curl_global_cleanup(); 216 convert_cleanup(); 217 metalink_cleanup(); 218} 219 220#ifdef CURLDEBUG 221void memory_tracking_init(void) 222{ 223 char *env; 224 /* if CURL_MEMDEBUG is set, this starts memory tracking message logging */ 225 env = curlx_getenv("CURL_MEMDEBUG"); 226 if(env) { 227 /* use the value as file name */ 228 char fname[CURL_MT_LOGFNAME_BUFSIZE]; 229 if(strlen(env) >= CURL_MT_LOGFNAME_BUFSIZE) 230 env[CURL_MT_LOGFNAME_BUFSIZE-1] = '\0'; 231 strcpy(fname, env); 232 curl_free(env); 233 curl_memdebug(fname); 234 /* this weird stuff here is to make curl_free() get called 235 before curl_memdebug() as otherwise memory tracking will 236 log a free() without an alloc! */ 237 } 238 /* if CURL_MEMLIMIT is set, this enables fail-on-alloc-number-N feature */ 239 env = curlx_getenv("CURL_MEMLIMIT"); 240 if(env) { 241 char *endptr; 242 long num = strtol(env, &endptr, 10); 243 if((endptr != env) && (endptr == env + strlen(env)) && (num > 0)) 244 curl_memlimit(num); 245 curl_free(env); 246 } 247} 248#endif 249 250