From c6702c7d3f53b0eb07e452c732df1b8f5765b287 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Sat, 24 Sep 2011 17:38:16 +0200 Subject: [PATCH] curl tool: reviewed code moved to tool_*.[ch] files --- packages/Symbian/group/curl.mmp | 8 +- src/Makefile.inc | 16 +- src/Makefile.vc6 | 48 +- src/main.c | 622 +------------------------ src/tool_cb_dbg.c | 276 +++++++++++ src/tool_cb_dbg.h | 35 ++ src/tool_cb_hdr.c | 182 ++++++++ src/tool_cb_hdr.h | 33 ++ src/{tool_progress.c => tool_cb_prg.c} | 12 +- src/{tool_progress.h => tool_cb_prg.h} | 18 +- src/tool_cb_rea.c | 61 +++ src/tool_cb_rea.h | 33 ++ src/tool_cb_see.c | 129 +++++ src/tool_cb_see.h | 45 ++ src/tool_cb_skt.c | 97 ++++ src/tool_cb_skt.h | 35 ++ src/tool_cb_wrt.c | 103 ++++ src/tool_cb_wrt.h | 33 ++ src/vc6curlsrc.dsp | 64 ++- 19 files changed, 1218 insertions(+), 632 deletions(-) create mode 100644 src/tool_cb_dbg.c create mode 100644 src/tool_cb_dbg.h create mode 100644 src/tool_cb_hdr.c create mode 100644 src/tool_cb_hdr.h rename src/{tool_progress.c => tool_cb_prg.c} (94%) rename src/{tool_progress.h => tool_cb_prg.h} (82%) create mode 100644 src/tool_cb_rea.c create mode 100644 src/tool_cb_rea.h create mode 100644 src/tool_cb_see.c create mode 100644 src/tool_cb_see.h create mode 100644 src/tool_cb_skt.c create mode 100644 src/tool_cb_skt.h create mode 100644 src/tool_cb_wrt.c create mode 100644 src/tool_cb_wrt.h diff --git a/packages/Symbian/group/curl.mmp b/packages/Symbian/group/curl.mmp index ef40c7150..7ea755555 100644 --- a/packages/Symbian/group/curl.mmp +++ b/packages/Symbian/group/curl.mmp @@ -11,6 +11,13 @@ SOURCE \ main.c hugehelp.c urlglob.c writeout.c writeenv.c \ getpass.c homedir.c curlutil.c xattr.c \ tool_bname.c \ + tool_cb_dbg.c \ + tool_cb_hdr.c \ + tool_cb_prg.c \ + tool_cb_rea.c \ + tool_cb_see.c \ + tool_cb_skt.c \ + tool_cb_wrt.c \ tool_cfgable.c \ tool_convert.c \ tool_dirhie.c \ @@ -20,7 +27,6 @@ SOURCE \ tool_mfiles.c \ tool_msgs.c \ tool_myfunc.c \ - tool_progress.c \ tool_setopt.c \ tool_vms.c diff --git a/src/Makefile.inc b/src/Makefile.inc index 70e374bde..28d7f05d9 100644 --- a/src/Makefile.inc +++ b/src/Makefile.inc @@ -17,6 +17,13 @@ CURLX_ONES = $(top_srcdir)/lib/strtoofft.c \ CURL_CFILES = main.c hugehelp.c urlglob.c writeout.c writeenv.c \ getpass.c homedir.c curlutil.c xattr.c \ tool_bname.c \ + tool_cb_dbg.c \ + tool_cb_hdr.c \ + tool_cb_prg.c \ + tool_cb_rea.c \ + tool_cb_see.c \ + tool_cb_skt.c \ + tool_cb_wrt.c \ tool_cfgable.c \ tool_convert.c \ tool_dirhie.c \ @@ -26,7 +33,6 @@ CURL_CFILES = main.c hugehelp.c urlglob.c writeout.c writeenv.c \ tool_mfiles.c \ tool_msgs.c \ tool_myfunc.c \ - tool_progress.c \ tool_setopt.c \ tool_vms.c @@ -34,6 +40,13 @@ CURL_HFILES = hugehelp.h setup.h config-win32.h config-mac.h \ config-riscos.h urlglob.h version.h xattr.h \ writeout.h writeenv.h getpass.h homedir.h curlutil.h \ tool_bname.h \ + tool_cb_dbg.h \ + tool_cb_hdr.h \ + tool_cb_prg.h \ + tool_cb_rea.h \ + tool_cb_see.h \ + tool_cb_skt.h \ + tool_cb_wrt.h \ tool_cfgable.h \ tool_convert.h \ tool_dirhie.h \ @@ -43,7 +56,6 @@ CURL_HFILES = hugehelp.h setup.h config-win32.h config-mac.h \ tool_mfiles.h \ tool_msgs.h \ tool_myfunc.h \ - tool_progress.h \ tool_sdecls.h \ tool_setopt.h \ tool_vms.h diff --git a/src/Makefile.vc6 b/src/Makefile.vc6 index d2ce12ce8..dce14182e 100644 --- a/src/Makefile.vc6 +++ b/src/Makefile.vc6 @@ -142,6 +142,13 @@ RELEASE_OBJS= \ rawstrr.obj \ strtoofftr.obj \ tool_bnamer.obj \ + tool_cb_dbgr.obj \ + tool_cb_hdrr.obj \ + tool_cb_prgr.obj \ + tool_cb_rear.obj \ + tool_cb_seer.obj \ + tool_cb_sktr.obj \ + tool_cb_wrtr.obj \ tool_cfgabler.obj \ tool_convertr.obj \ tool_dirhier.obj \ @@ -151,7 +158,6 @@ RELEASE_OBJS= \ tool_mfilesr.obj \ tool_msgsr.obj \ tool_myfuncr.obj \ - tool_progressr.obj \ tool_setoptr.obj \ tool_vmsr.obj \ urlglobr.obj \ @@ -169,6 +175,13 @@ DEBUG_OBJS= \ rawstrd.obj \ strtoofftd.obj \ tool_bnamed.obj \ + tool_cb_dbgd.obj \ + tool_cb_hdrd.obj \ + tool_cb_prgd.obj \ + tool_cb_read.obj \ + tool_cb_seed.obj \ + tool_cb_sktd.obj \ + tool_cb_wrtd.obj \ tool_cfgabled.obj \ tool_convertd.obj \ tool_dirhied.obj \ @@ -178,7 +191,6 @@ DEBUG_OBJS= \ tool_mfilesd.obj \ tool_msgsd.obj \ tool_myfuncd.obj \ - tool_progressd.obj \ tool_setoptd.obj \ tool_vmsd.obj \ urlglobd.obj \ @@ -326,6 +338,20 @@ strtoofftr.obj: ../lib/strtoofft.c $(CCR) $(CFLAGS) /Fo"$@" ../lib/strtoofft.c tool_bnamer.obj: tool_bname.c $(CCR) $(CFLAGS) /Fo"$@" tool_bname.c +tool_cb_dbgr.obj: tool_cb_dbg.c + $(CCR) $(CFLAGS) /Fo"$@" tool_cb_dbg.c +tool_cb_hdrr.obj: tool_cb_hdr.c + $(CCR) $(CFLAGS) /Fo"$@" tool_cb_hdr.c +tool_cb_prgr.obj: tool_cb_prg.c + $(CCR) $(CFLAGS) /Fo"$@" tool_cb_prg.c +tool_cb_rear.obj: tool_cb_rea.c + $(CCR) $(CFLAGS) /Fo"$@" tool_cb_rea.c +tool_cb_seer.obj: tool_cb_see.c + $(CCR) $(CFLAGS) /Fo"$@" tool_cb_see.c +tool_cb_sktr.obj: tool_cb_skt.c + $(CCR) $(CFLAGS) /Fo"$@" tool_cb_skt.c +tool_cb_wrtr.obj: tool_cb_wrt.c + $(CCR) $(CFLAGS) /Fo"$@" tool_cb_wrt.c tool_cfgabler.obj: tool_cfgable.c $(CCR) $(CFLAGS) /Fo"$@" tool_cfgable.c tool_convertr.obj: tool_convert.c @@ -344,8 +370,6 @@ tool_msgsr.obj: tool_msgs.c $(CCR) $(CFLAGS) /Fo"$@" tool_msgs.c tool_myfuncr.obj: tool_myfunc.c $(CCR) $(CFLAGS) /Fo"$@" tool_myfunc.c -tool_progressr.obj: tool_progress.c - $(CCR) $(CFLAGS) /Fo"$@" tool_progress.c tool_setoptr.obj: tool_setopt.c $(CCR) $(CFLAGS) /Fo"$@" tool_setopt.c tool_vmsr.obj: tool_vms.c @@ -378,6 +402,20 @@ strtoofftd.obj: ../lib/strtoofft.c $(CCD) $(CFLAGS) /Fo"$@" ../lib/strtoofft.c tool_bnamed.obj: tool_bname.c $(CCD) $(CFLAGS) /Fo"$@" tool_bname.c +tool_cb_dbgd.obj: tool_cb_dbg.c + $(CCD) $(CFLAGS) /Fo"$@" tool_cb_dbg.c +tool_cb_hdrd.obj: tool_cb_hdr.c + $(CCD) $(CFLAGS) /Fo"$@" tool_cb_hdr.c +tool_cb_prgd.obj: tool_cb_prg.c + $(CCD) $(CFLAGS) /Fo"$@" tool_cb_prg.c +tool_cb_read.obj: tool_cb_rea.c + $(CCD) $(CFLAGS) /Fo"$@" tool_cb_rea.c +tool_cb_seed.obj: tool_cb_see.c + $(CCD) $(CFLAGS) /Fo"$@" tool_cb_see.c +tool_cb_sktd.obj: tool_cb_skt.c + $(CCD) $(CFLAGS) /Fo"$@" tool_cb_skt.c +tool_cb_wrtd.obj: tool_cb_wrt.c + $(CCD) $(CFLAGS) /Fo"$@" tool_cb_wrt.c tool_cfgabled.obj: tool_cfgable.c $(CCD) $(CFLAGS) /Fo"$@" tool_cfgable.c tool_convertd.obj: tool_convert.c @@ -396,8 +434,6 @@ tool_msgsd.obj: tool_msgs.c $(CCD) $(CFLAGS) /Fo"$@" tool_msgs.c tool_myfuncd.obj: tool_myfunc.c $(CCD) $(CFLAGS) /Fo"$@" tool_myfunc.c -tool_progressd.obj: tool_progress.c - $(CCD) $(CFLAGS) /Fo"$@" tool_progress.c tool_setoptd.obj: tool_setopt.c $(CCD) $(CFLAGS) /Fo"$@" tool_setopt.c tool_vmsd.obj: tool_vms.c diff --git a/src/main.c b/src/main.c index 1c8106626..306df623d 100644 --- a/src/main.c +++ b/src/main.c @@ -102,9 +102,17 @@ #include "tool_mfiles.h" #include "tool_msgs.h" #include "tool_myfunc.h" -#include "tool_progress.h" +#include "tool_cb_prg.h" #include "tool_setopt.h" #include "tool_vms.h" + +#include "tool_cb_rea.h" +#include "tool_cb_wrt.h" +#include "tool_cb_see.h" +#include "tool_cb_skt.h" +#include "tool_cb_hdr.h" +#include "tool_cb_dbg.h" + #ifdef USE_MANUAL # include "hugehelp.h" #endif @@ -230,44 +238,6 @@ char **__crt0_glob_function (char *arg) "If you'd like to turn off curl's verification of the certificate, use\n" \ " the -k (or --insecure) option.\n" -#if defined(WIN32) && !defined(__MINGW64__) - -#ifdef __BORLANDC__ -/* 64-bit lseek-like function unavailable */ -# define _lseeki64(hnd,ofs,whence) lseek(hnd,ofs,whence) -#endif - -#ifdef __POCC__ -# if(__POCC__ < 450) -/* 64-bit lseek-like function unavailable */ -# define _lseeki64(hnd,ofs,whence) _lseek(hnd,ofs,whence) -# else -# define _lseeki64(hnd,ofs,whence) _lseek64(hnd,ofs,whence) -# endif -#endif - -#ifndef HAVE_FTRUNCATE -#define HAVE_FTRUNCATE 1 -#endif - -/* - * Truncate a file handle at a 64-bit position 'where'. - */ - -static int ftruncate64(int fd, curl_off_t where) -{ - if(_lseeki64(fd, where, SEEK_SET) < 0) - return -1; - - if(!SetEndOfFile((HANDLE)_get_osfhandle(fd))) - return -1; - - return 0; -} -#define ftruncate(fd,where) ftruncate64(fd,where) - -#endif /* WIN32 */ - /* * This is the main global constructor for the app. Call this before * _any_ libcurl usage. If this fails, *NO* libcurl functions may be @@ -1210,60 +1180,6 @@ static int ftpcccmethod(struct Configurable *config, const char *str) return CURLFTPSSL_CCC_PASSIVE; } - -static int sockoptcallback(void *clientp, curl_socket_t curlfd, - curlsocktype purpose) -{ - struct Configurable *config = (struct Configurable *)clientp; - int onoff = 1; /* this callback is only used if we ask for keepalives on the - connection */ -#if defined(TCP_KEEPIDLE) || defined(TCP_KEEPINTVL) - int keepidle = (int)config->alivetime; -#endif - - switch(purpose) { - case CURLSOCKTYPE_IPCXN: - if(setsockopt(curlfd, SOL_SOCKET, SO_KEEPALIVE, (void *)&onoff, - sizeof(onoff)) < 0) { - /* don't abort operation, just issue a warning */ - SET_SOCKERRNO(0); - warnf(clientp, "Could not set SO_KEEPALIVE!\n"); - return 0; - } - else { - if(config->alivetime) { -#ifdef TCP_KEEPIDLE - if(setsockopt(curlfd, IPPROTO_TCP, TCP_KEEPIDLE, (void *)&keepidle, - sizeof(keepidle)) < 0) { - /* don't abort operation, just issue a warning */ - SET_SOCKERRNO(0); - warnf(clientp, "Could not set TCP_KEEPIDLE!\n"); - return 0; - } -#endif -#ifdef TCP_KEEPINTVL - if(setsockopt(curlfd, IPPROTO_TCP, TCP_KEEPINTVL, (void *)&keepidle, - sizeof(keepidle)) < 0) { - /* don't abort operation, just issue a warning */ - SET_SOCKERRNO(0); - warnf(clientp, "Could not set TCP_KEEPINTVL!\n"); - return 0; - } -#endif -#if !defined(TCP_KEEPIDLE) || !defined(TCP_KEEPINTVL) - warnf(clientp, "Keep-alive functionality somewhat crippled due to " - "missing support in your operating system!\n"); -#endif - } - } - break; - default: - break; - } - - return 0; -} - static long delegation(struct Configurable *config, char *str) { @@ -3045,369 +2961,6 @@ static void go_sleep(long ms) #endif } -static size_t my_fwrite(void *buffer, size_t sz, size_t nmemb, void *stream) -{ - size_t rc; - struct OutStruct *out=(struct OutStruct *)stream; - struct Configurable *config = out->config; - - /* - * Once that libcurl has called back my_fwrite() the returned value - * is checked against the amount that was intended to be written, if - * it does not match then it fails with CURLE_WRITE_ERROR. So at this - * point returning a value different from sz*nmemb indicates failure. - */ - const size_t err_rc = (sz * nmemb) ? 0 : 1; - - if(!out->stream) { - out->bytes = 0; /* nothing written yet */ - if(!out->filename) { - warnf(config, "Remote filename has no length!\n"); - return err_rc; /* Failure */ - } - - if(config->content_disposition) { - /* don't overwrite existing files */ - FILE* f = fopen(out->filename, "r"); - if(f) { - fclose(f); - warnf(config, "Refusing to overwrite %s: %s\n", out->filename, - strerror(EEXIST)); - return err_rc; /* Failure */ - } - } - - /* open file for writing */ - out->stream=fopen(out->filename, "wb"); - if(!out->stream) { - warnf(config, "Failed to create the file %s: %s\n", out->filename, - strerror(errno)); - return err_rc; /* failure */ - } - } - - rc = fwrite(buffer, sz, nmemb, out->stream); - - if((sz * nmemb) == rc) - /* we added this amount of data to the output */ - out->bytes += (sz * nmemb); - - if(config->readbusy) { - config->readbusy = FALSE; - curl_easy_pause(config->easy, CURLPAUSE_CONT); - } - - if(config->nobuffer) { - /* disable output buffering */ - int res = fflush(out->stream); - if(res) { - /* return a value that isn't the same as sz * nmemb */ - return err_rc; /* failure */ - } - } - - return rc; -} - -#define MAX_SEEK 2147483647 - -/* - * my_seek() is the CURLOPT_SEEKFUNCTION we use - */ -static int my_seek(void *stream, curl_off_t offset, int whence) -{ - struct InStruct *in=(struct InStruct *)stream; - -#if(CURL_SIZEOF_CURL_OFF_T > SIZEOF_OFF_T) && !defined(USE_WIN32_LARGE_FILES) - /* The offset check following here is only interesting if curl_off_t is - larger than off_t and we are not using the WIN32 large file support - macros that provide the support to do 64bit seeks correctly */ - - if(offset > MAX_SEEK) { - /* Some precaution code to work around problems with different data sizes - to allow seeking >32bit even if off_t is 32bit. Should be very rare and - is really valid on weirdo-systems. */ - curl_off_t left = offset; - - if(whence != SEEK_SET) - /* this code path doesn't support other types */ - return 1; - - if(LSEEK_ERROR == lseek(in->fd, 0, SEEK_SET)) - /* couldn't rewind to beginning */ - return 1; - - while(left) { - long step = (left>MAX_SEEK ? MAX_SEEK : (long)left); - if(LSEEK_ERROR == lseek(in->fd, step, SEEK_CUR)) - /* couldn't seek forwards the desired amount */ - return 1; - left -= step; - } - return 0; - } -#endif - if(LSEEK_ERROR == lseek(in->fd, offset, whence)) - /* couldn't rewind, the reason is in errno but errno is just not portable - enough and we don't actually care that much why we failed. We'll let - libcurl know that it may try other means if it wants to. */ - return CURL_SEEKFUNC_CANTSEEK; - - return 0; -} - -static size_t my_fread(void *buffer, size_t sz, size_t nmemb, void *userp) -{ - ssize_t rc; - struct InStruct *in=(struct InStruct *)userp; - - rc = read(in->fd, buffer, sz*nmemb); - if(rc < 0) { - if(errno == EAGAIN) { - errno = 0; - in->config->readbusy = TRUE; - return CURL_READFUNC_PAUSE; - } - /* since size_t is unsigned we can't return negative values fine */ - rc = 0; - } - in->config->readbusy = FALSE; - return (size_t)rc; -} - -static -void dump(const char *timebuf, const char *text, - FILE *stream, const unsigned char *ptr, size_t size, - trace tracetype, curl_infotype infotype) -{ - size_t i; - size_t c; - - unsigned int width=0x10; - - if(tracetype == TRACE_ASCII) - /* without the hex output, we can fit more on screen */ - width = 0x40; - - fprintf(stream, "%s%s, %zd bytes (0x%zx)\n", timebuf, text, size, size); - - for(i=0; i=0x20) && (ptr[i+c]<0x80)?ptr[i+c]:UNPRINTABLE_CHAR); -#endif /* CURL_DOES_CONVERSIONS */ - /* check again for 0D0A, to avoid an extra \n if it's at width */ - if((tracetype == TRACE_ASCII) && - (i+c+2 < size) && ptr[i+c+1]==0x0D && ptr[i+c+2]==0x0A) { - i+=(c+3-width); - break; - } - } - fputc('\n', stream); /* newline */ - } - fflush(stream); -} - -static -int my_trace(CURL *handle, curl_infotype type, - unsigned char *data, size_t size, - void *userp) -{ - struct Configurable *config = (struct Configurable *)userp; - FILE *output=config->errors; - const char *text; - struct timeval tv; - struct tm *now; - char timebuf[20]; - time_t secs; - static time_t epoch_offset; - static int known_offset; - - (void)handle; /* prevent compiler warning */ - - if(config->tracetime) { - tv = cutil_tvnow(); - if(!known_offset) { - epoch_offset = time(NULL) - tv.tv_sec; - known_offset = 1; - } - secs = epoch_offset + tv.tv_sec; - now = localtime(&secs); /* not thread safe but we don't care */ - snprintf(timebuf, sizeof(timebuf), "%02d:%02d:%02d.%06ld ", - now->tm_hour, now->tm_min, now->tm_sec, (long)tv.tv_usec); - } - else - timebuf[0]=0; - - if(!config->trace_stream) { - /* open for append */ - if(curlx_strequal("-", config->trace_dump)) - config->trace_stream = stdout; - else if(curlx_strequal("%", config->trace_dump)) - /* Ok, this is somewhat hackish but we do it undocumented for now */ - config->trace_stream = config->errors; /* aka stderr */ - else { - config->trace_stream = fopen(config->trace_dump, "w"); - config->trace_fopened = TRUE; - } - } - - if(config->trace_stream) - output = config->trace_stream; - - if(!output) { - warnf(config, "Failed to create/open output"); - return 0; - } - - if(config->tracetype == TRACE_PLAIN) { - /* - * This is the trace look that is similar to what libcurl makes on its - * own. - */ - static const char * const s_infotype[] = { - "*", "<", ">", "{", "}", "{", "}" - }; - size_t i; - size_t st=0; - static bool newl = FALSE; - static bool traced_data = FALSE; - - switch(type) { - case CURLINFO_HEADER_OUT: - for(i=0; iisatty || - ((output != stderr) && (output != stdout))) { - if(!newl) - fprintf(output, "%s%s ", timebuf, s_infotype[type]); - fprintf(output, "[data not shown]\n"); - newl = FALSE; - traced_data = TRUE; - } - } - break; - default: /* nada */ - newl = FALSE; - traced_data = FALSE; - break; - } - - return 0; - } - -#ifdef CURL_DOES_CONVERSIONS - /* Special processing is needed for CURLINFO_HEADER_OUT blocks - * if they contain both headers and data (separated by CRLFCRLF). - * We dump the header text and then switch type to CURLINFO_DATA_OUT. - */ - if((type == CURLINFO_HEADER_OUT) && (size > 4)) { - size_t i; - for(i = 0; i < size - 4; i++) { - if(memcmp(&data[i], "\r\n\r\n", 4) == 0) { - /* dump everything through the CRLFCRLF as a sent header */ - text = "=> Send header"; - dump(timebuf, text, output, data, i+4, config->tracetype, type); - data += i + 3; - size -= i + 4; - type = CURLINFO_DATA_OUT; - data += 1; - break; - } - } - } -#endif /* CURL_DOES_CONVERSIONS */ - - switch (type) { - case CURLINFO_TEXT: - fprintf(output, "%s== Info: %s", timebuf, data); - default: /* in case a new one is introduced to shock us */ - return 0; - - case CURLINFO_HEADER_OUT: - text = "=> Send header"; - break; - case CURLINFO_DATA_OUT: - text = "=> Send data"; - break; - case CURLINFO_HEADER_IN: - text = "<= Recv header"; - break; - case CURLINFO_DATA_IN: - text = "<= Recv data"; - break; - case CURLINFO_SSL_DATA_IN: - text = "<= Recv SSL data"; - break; - case CURLINFO_SSL_DATA_OUT: - text = "=> Send SSL data"; - break; - } - - dump(timebuf, text, output, data, size, config->tracetype, type); - return 0; -} - #define RETRY_SLEEP_DEFAULT 1000L /* ms */ #define RETRY_SLEEP_MAX 600000L /* ms == 10 minutes */ @@ -3505,147 +3058,6 @@ static char *get_url_file_name(const char *url) return fn; } -/* - * Copies a file name part and returns an ALLOCATED data buffer. - */ -static char* -parse_filename(char *ptr, size_t len) -{ - char* copy; - char* p; - char* q; - char stop = 0; - - /* simple implementation of strndup() */ - copy = malloc(len+1); - if(!copy) - return NULL; - memcpy(copy, ptr, len); - copy[len] = 0; - - p = copy; - if(*p == '\'' || *p == '"') { - /* store the starting quote */ - stop = *p; - p++; - } - else - stop = ';'; - - /* if the filename contains a path, only use filename portion */ - q = strrchr(copy, '/'); - if(q) { - p=q+1; - if(!*p) { - Curl_safefree(copy); - return NULL; - } - } - - /* If the filename contains a backslash, only use filename portion. The idea - is that even systems that don't handle backslashes as path separators - probably want the path removed for convenience. */ - q = strrchr(p, '\\'); - if(q) { - p = q+1; - if(!*p) { - Curl_safefree(copy); - return NULL; - } - } - - /* scan for the end letter and stop there */ - q = p; - while(*q) { - if(q[1] && q[0]=='\\') - q++; - else if(q[0] == stop) - break; - q++; - } - *q = 0; - - /* make sure the file name doesn't end in \r or \n */ - q = strchr(p, '\r'); - if(q) - *q = 0; - - q = strchr(p, '\n'); - if(q) - *q = 0; - - if(copy!=p) - memmove(copy, p, strlen(p)+1); - - /* in case we built curl debug enabled, we allow an evironment variable - * named CURL_TESTDIR to prefix the given file name to put it into a - * specific directory - */ -#ifdef CURLDEBUG - { - char *tdir = curlx_getenv("CURL_TESTDIR"); - if(tdir) { - char buffer[512]; /* suitably large */ - snprintf(buffer, sizeof(buffer), "%s/%s", tdir, copy); - Curl_safefree(copy); - copy = strdup(buffer); /* clone the buffer, we don't use the libcurl - aprintf() or similar since we want to use the - same memory code as the "real" parse_filename - function */ - curl_free(tdir); - } - } -#endif - - return copy; -} - -static size_t -header_callback(void *ptr, size_t size, size_t nmemb, void *stream) -{ - struct OutStruct* outs = (struct OutStruct*)stream; - const char* str = (char*)ptr; - const size_t cb = size*nmemb; - const char* end = (char*)ptr + cb; - - if(cb > 20 && checkprefix("Content-disposition:", str)) { - char *p = (char*)str + 20; - - /* look for the 'filename=' parameter - (encoded filenames (*=) are not supported) */ - for(;;) { - char *filename; - size_t len; - - while(*p && (p < end) && !ISALPHA(*p)) - p++; - if(p > end-9) - break; - - if(memcmp(p, "filename=", 9)) { - /* no match, find next parameter */ - while((p < end) && (*p != ';')) - p++; - continue; - } - p+=9; - - /* this expression below typecasts 'cb' only to avoid - warning: signed and unsigned type in conditional expression - */ - len = (ssize_t)cb - (p - str); - filename = parse_filename(p, len); - if(filename) { - outs->filename = filename; - outs->alloc_filename = TRUE; - break; - } - } - } - - return cb; -} - #ifdef CURLDEBUG static void memory_tracking_init(void) { @@ -4322,7 +3734,7 @@ operate(struct Configurable *config, int argc, argv_item_t argv[]) /* where to store */ my_setopt(curl, CURLOPT_WRITEDATA, &outs); /* what call to write */ - my_setopt(curl, CURLOPT_WRITEFUNCTION, my_fwrite); + my_setopt(curl, CURLOPT_WRITEFUNCTION, tool_write_cb); /* for uploads */ input.fd = infd; @@ -4331,12 +3743,12 @@ operate(struct Configurable *config, int argc, argv_item_t argv[]) /* what call to read */ if((outfile && !curlx_strequal("-", outfile)) || !checkprefix("telnet:", this_url)) - my_setopt(curl, CURLOPT_READFUNCTION, my_fread); + my_setopt(curl, CURLOPT_READFUNCTION, tool_read_cb); /* in 7.18.0, the CURLOPT_SEEKFUNCTION/DATA pair is taking over what CURLOPT_IOCTLFUNCTION/DATA pair previously provided for seeking */ my_setopt(curl, CURLOPT_SEEKDATA, &input); - my_setopt(curl, CURLOPT_SEEKFUNCTION, my_seek); + my_setopt(curl, CURLOPT_SEEKFUNCTION, tool_seek_cb); if(config->recvpersecond) /* tell libcurl to use a smaller sized buffer as it allows us to @@ -4581,7 +3993,7 @@ operate(struct Configurable *config, int argc, argv_item_t argv[]) !config->noprogress && !config->mute) { /* we want the alternative style, then we have to implement it ourselves! */ - my_setopt(curl, CURLOPT_PROGRESSFUNCTION, my_progress); + my_setopt(curl, CURLOPT_PROGRESSFUNCTION, tool_progress_cb); my_setopt(curl, CURLOPT_PROGRESSDATA, &progressbar); } @@ -4607,7 +4019,7 @@ operate(struct Configurable *config, int argc, argv_item_t argv[]) my_setopt(curl, CURLOPT_FTP_USE_EPRT, FALSE); if(config->tracetype != TRACE_NONE) { - my_setopt(curl, CURLOPT_DEBUGFUNCTION, my_trace); + my_setopt(curl, CURLOPT_DEBUGFUNCTION, tool_debug_cb); my_setopt(curl, CURLOPT_DEBUGDATA, config); my_setopt(curl, CURLOPT_VERBOSE, TRUE); } @@ -4702,7 +4114,7 @@ operate(struct Configurable *config, int argc, argv_item_t argv[]) /* curl 7.17.1 */ if(!config->nokeepalive) { - my_setopt(curl, CURLOPT_SOCKOPTFUNCTION, sockoptcallback); + my_setopt(curl, CURLOPT_SOCKOPTFUNCTION, tool_sockopt_cb); my_setopt(curl, CURLOPT_SOCKOPTDATA, config); } @@ -4727,7 +4139,7 @@ operate(struct Configurable *config, int argc, argv_item_t argv[]) if((urlnode->flags & GETOUT_USEREMOTE) && config->content_disposition) { - my_setopt(curl, CURLOPT_HEADERFUNCTION, header_callback); + my_setopt(curl, CURLOPT_HEADERFUNCTION, tool_header_cb); my_setopt(curl, CURLOPT_HEADERDATA, &outs); } else { @@ -5045,6 +4457,8 @@ operate(struct Configurable *config, int argc, argv_item_t argv[]) Curl_safefree(urlnode->infile); urlnode->flags = 0; + /* TODO: Should CURLE_SSL_CACERT be included as critical error ? */ + /* ** Bail out upon critical errors */ diff --git a/src/tool_cb_dbg.c b/src/tool_cb_dbg.c new file mode 100644 index 000000000..7b20a0c01 --- /dev/null +++ b/src/tool_cb_dbg.c @@ -0,0 +1,276 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "setup.h" + +#include + +#define ENABLE_CURLX_PRINTF +/* use our own printf() functions */ +#include "curlx.h" + +#include "curlutil.h" + +#include "tool_cfgable.h" +#include "tool_msgs.h" +#include "tool_cb_dbg.h" + +#include "memdebug.h" /* keep this as LAST include */ + +static void dump(const char *timebuf, const char *text, + FILE *stream, const unsigned char *ptr, size_t size, + trace tracetype, curl_infotype infotype); + +/* +** callback for CURLOPT_DEBUGFUNCTION +*/ + +int tool_debug_cb(CURL *handle, curl_infotype type, + unsigned char *data, size_t size, + void *userdata) +{ + struct Configurable *config = userdata; + FILE *output = config->errors; + const char *text; + struct timeval tv; + struct tm *now; + char timebuf[20]; + time_t secs; + static time_t epoch_offset; + static int known_offset; + + (void)handle; /* not used */ + + if(config->tracetime) { + tv = cutil_tvnow(); + if(!known_offset) { + epoch_offset = time(NULL) - tv.tv_sec; + known_offset = 1; + } + secs = epoch_offset + tv.tv_sec; + now = localtime(&secs); /* not thread safe but we don't care */ + snprintf(timebuf, sizeof(timebuf), "%02d:%02d:%02d.%06ld ", + now->tm_hour, now->tm_min, now->tm_sec, (long)tv.tv_usec); + } + else + timebuf[0] = 0; + + if(!config->trace_stream) { + /* open for append */ + if(curlx_strequal("-", config->trace_dump)) + config->trace_stream = stdout; + else if(curlx_strequal("%", config->trace_dump)) + /* Ok, this is somewhat hackish but we do it undocumented for now */ + config->trace_stream = config->errors; /* aka stderr */ + else { + config->trace_stream = fopen(config->trace_dump, "w"); + config->trace_fopened = TRUE; + } + } + + if(config->trace_stream) + output = config->trace_stream; + + if(!output) { + warnf(config, "Failed to create/open output"); + return 0; + } + + if(config->tracetype == TRACE_PLAIN) { + /* + * This is the trace look that is similar to what libcurl makes on its + * own. + */ + static const char * const s_infotype[] = { + "*", "<", ">", "{", "}", "{", "}" + }; + size_t i; + size_t st = 0; + static bool newl = FALSE; + static bool traced_data = FALSE; + + switch(type) { + case CURLINFO_HEADER_OUT: + for(i = 0; i < size - 1; i++) { + if(data[i] == '\n') { /* LF */ + if(!newl) { + fprintf(output, "%s%s ", timebuf, s_infotype[type]); + } + (void)fwrite(data + st, i - st + 1, 1, output); + st = i + 1; + newl = FALSE; + } + } + if(!newl) + fprintf(output, "%s%s ", timebuf, s_infotype[type]); + (void)fwrite(data + st, i - st + 1, 1, output); + newl = (size && (data[size - 1] != '\n')) ? TRUE : FALSE; + traced_data = FALSE; + break; + case CURLINFO_TEXT: + case CURLINFO_HEADER_IN: + if(!newl) + fprintf(output, "%s%s ", timebuf, s_infotype[type]); + (void)fwrite(data, size, 1, output); + newl = (size && (data[size - 1] != '\n')) ? TRUE : FALSE; + traced_data = FALSE; + break; + case CURLINFO_DATA_OUT: + case CURLINFO_DATA_IN: + case CURLINFO_SSL_DATA_IN: + case CURLINFO_SSL_DATA_OUT: + if(!traced_data) { + /* if the data is output to a tty and we're sending this debug trace + to stderr or stdout, we don't display the alert about the data not + being shown as the data _is_ shown then just not via this + function */ + if(!config->isatty || + ((output != stderr) && (output != stdout))) { + if(!newl) + fprintf(output, "%s%s ", timebuf, s_infotype[type]); + fprintf(output, "[data not shown]\n"); + newl = FALSE; + traced_data = TRUE; + } + } + break; + default: /* nada */ + newl = FALSE; + traced_data = FALSE; + break; + } + + return 0; + } + +#ifdef CURL_DOES_CONVERSIONS + /* Special processing is needed for CURLINFO_HEADER_OUT blocks + * if they contain both headers and data (separated by CRLFCRLF). + * We dump the header text and then switch type to CURLINFO_DATA_OUT. + */ + if((type == CURLINFO_HEADER_OUT) && (size > 4)) { + size_t i; + for(i = 0; i < size - 4; i++) { + if(memcmp(&data[i], "\r\n\r\n", 4) == 0) { + /* dump everything through the CRLFCRLF as a sent header */ + text = "=> Send header"; + dump(timebuf, text, output, data, i + 4, config->tracetype, type); + data += i + 3; + size -= i + 4; + type = CURLINFO_DATA_OUT; + data += 1; + break; + } + } + } +#endif /* CURL_DOES_CONVERSIONS */ + + switch (type) { + case CURLINFO_TEXT: + fprintf(output, "%s== Info: %s", timebuf, data); + default: /* in case a new one is introduced to shock us */ + return 0; + + case CURLINFO_HEADER_OUT: + text = "=> Send header"; + break; + case CURLINFO_DATA_OUT: + text = "=> Send data"; + break; + case CURLINFO_HEADER_IN: + text = "<= Recv header"; + break; + case CURLINFO_DATA_IN: + text = "<= Recv data"; + break; + case CURLINFO_SSL_DATA_IN: + text = "<= Recv SSL data"; + break; + case CURLINFO_SSL_DATA_OUT: + text = "=> Send SSL data"; + break; + } + + dump(timebuf, text, output, data, size, config->tracetype, type); + return 0; +} + +static void dump(const char *timebuf, const char *text, + FILE *stream, const unsigned char *ptr, size_t size, + trace tracetype, curl_infotype infotype) +{ + size_t i; + size_t c; + + unsigned int width = 0x10; + + if(tracetype == TRACE_ASCII) + /* without the hex output, we can fit more on screen */ + width = 0x40; + + fprintf(stream, "%s%s, %zd bytes (0x%zx)\n", timebuf, text, size, size); + + for(i = 0; i < size; i += width) { + + fprintf(stream, "%04zx: ", i); + + if(tracetype == TRACE_BIN) { + /* hex not disabled, show it */ + for(c = 0; c < width; c++) + if(i+c < size) + fprintf(stream, "%02x ", ptr[i+c]); + else + fputs(" ", stream); + } + + for(c = 0; (c < width) && (i+c < size); c++) { + /* check for 0D0A; if found, skip past and start a new line of output */ + if((tracetype == TRACE_ASCII) && + (i+c+1 < size) && (ptr[i+c] == 0x0D) && (ptr[i+c+1] == 0x0A)) { + i += (c+2-width); + break; + } +#ifdef CURL_DOES_CONVERSIONS + /* repeat the 0D0A check above but use the host encoding for CRLF */ + if((tracetype == TRACE_ASCII) && + (i+c+1 < size) && (ptr[i+c] == '\r') && (ptr[i+c+1] == '\n')) { + i += (c+2-width); + break; + } + /* convert to host encoding and print this character */ + fprintf(stream, "%c", convert_char(infotype, ptr[i+c])); +#else + (void)infotype; + fprintf(stream, "%c", ((ptr[i+c] >= 0x20) && (ptr[i+c] < 0x80)) ? + ptr[i+c] : UNPRINTABLE_CHAR); +#endif /* CURL_DOES_CONVERSIONS */ + /* check again for 0D0A, to avoid an extra \n if it's at width */ + if((tracetype == TRACE_ASCII) && + (i+c+2 < size) && (ptr[i+c+1] == 0x0D) && (ptr[i+c+2] == 0x0A)) { + i += (c+3-width); + break; + } + } + fputc('\n', stream); /* newline */ + } + fflush(stream); +} + diff --git a/src/tool_cb_dbg.h b/src/tool_cb_dbg.h new file mode 100644 index 000000000..6d4446da1 --- /dev/null +++ b/src/tool_cb_dbg.h @@ -0,0 +1,35 @@ +#ifndef HEADER_CURL_TOOL_CB_DBG_H +#define HEADER_CURL_TOOL_CB_DBG_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "setup.h" + +/* +** callback for CURLOPT_DEBUGFUNCTION +*/ + +int tool_debug_cb(CURL *handle, curl_infotype type, + unsigned char *data, size_t size, + void *userdata); + +#endif /* HEADER_CURL_TOOL_CB_DBG_H */ + diff --git a/src/tool_cb_hdr.c b/src/tool_cb_hdr.c new file mode 100644 index 000000000..2643ad2cf --- /dev/null +++ b/src/tool_cb_hdr.c @@ -0,0 +1,182 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "setup.h" + +#include + +#include "rawstr.h" + +#define ENABLE_CURLX_PRINTF +/* use our own printf() functions */ +#include "curlx.h" + +#include "tool_cfgable.h" +#include "tool_cb_hdr.h" + +#include "memdebug.h" /* keep this as LAST include */ + +static char *parse_filename(const char *ptr, size_t len); + +/* +** callback for CURLOPT_HEADERFUNCTION +*/ + +size_t tool_header_cb(void *ptr, size_t size, size_t nmemb, void *userdata) +{ + struct OutStruct *outs = userdata; + const char *str = ptr; + const size_t cb = size * nmemb; + const char *end = (char*)ptr + cb; + + if(cb > 20 && checkprefix("Content-disposition:", str)) { + const char *p = str + 20; + + /* look for the 'filename=' parameter + (encoded filenames (*=) are not supported) */ + for(;;) { + char *filename; + size_t len; + + while(*p && (p < end) && !ISALPHA(*p)) + p++; + if(p > end - 9) + break; + + if(memcmp(p, "filename=", 9)) { + /* no match, find next parameter */ + while((p < end) && (*p != ';')) + p++; + continue; + } + p += 9; + + /* this expression below typecasts 'cb' only to avoid + warning: signed and unsigned type in conditional expression + */ + len = (ssize_t)cb - (p - str); + filename = parse_filename(p, len); + /* TODO: OOM handling - return (size_t)-1 ? */ + if(filename) { + outs->filename = filename; + outs->alloc_filename = TRUE; + break; + } + } + } + + return cb; +} + +/* + * Copies a file name part and returns an ALLOCATED data buffer. + */ +static char *parse_filename(const char *ptr, size_t len) +{ + char *copy; + char *p; + char *q; + char stop = '\0'; + + /* simple implementation of strndup() */ + copy = malloc(len+1); + if(!copy) + return NULL; + memcpy(copy, ptr, len); + copy[len] = '\0'; + + p = copy; + if(*p == '\'' || *p == '"') { + /* store the starting quote */ + stop = *p; + p++; + } + else + stop = ';'; + + /* if the filename contains a path, only use filename portion */ + q = strrchr(copy, '/'); + if(q) { + p = q + 1; + if(!*p) { + Curl_safefree(copy); + return NULL; + } + } + + /* If the filename contains a backslash, only use filename portion. The idea + is that even systems that don't handle backslashes as path separators + probably want the path removed for convenience. */ + q = strrchr(p, '\\'); + if(q) { + p = q + 1; + if(!*p) { + Curl_safefree(copy); + return NULL; + } + } + + /* scan for the end letter and stop there */ + q = p; + while(*q) { + if(q[1] && (q[0] == '\\')) + q++; + else if(q[0] == stop) + break; + q++; + } + *q = '\0'; + + /* make sure the file name doesn't end in \r or \n */ + q = strchr(p, '\r'); + if(q) + *q = '\0'; + + q = strchr(p, '\n'); + if(q) + *q = '\0'; + + if(copy != p) + memmove(copy, p, strlen(p) + 1); + + /* in case we built curl debug enabled, we allow an evironment variable + * named CURL_TESTDIR to prefix the given file name to put it into a + * specific directory + */ +#ifdef CURLDEBUG + { + char *tdir = curlx_getenv("CURL_TESTDIR"); + if(tdir) { + char buffer[512]; /* suitably large */ + snprintf(buffer, sizeof(buffer), "%s/%s", tdir, copy); + Curl_safefree(copy); + copy = strdup(buffer); /* clone the buffer, we don't use the libcurl + aprintf() or similar since we want to use the + same memory code as the "real" parse_filename + function */ + curl_free(tdir); + } + } +#endif + + return copy; +} + diff --git a/src/tool_cb_hdr.h b/src/tool_cb_hdr.h new file mode 100644 index 000000000..8808a4ae1 --- /dev/null +++ b/src/tool_cb_hdr.h @@ -0,0 +1,33 @@ +#ifndef HEADER_CURL_TOOL_CB_HDR_H +#define HEADER_CURL_TOOL_CB_HDR_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "setup.h" + +/* +** callback for CURLOPT_HEADERFUNCTION +*/ + +size_t tool_header_cb(void *ptr, size_t size, size_t nmemb, void *userdata); + +#endif /* HEADER_CURL_TOOL_CB_HDR_H */ + diff --git a/src/tool_progress.c b/src/tool_cb_prg.c similarity index 94% rename from src/tool_progress.c rename to src/tool_cb_prg.c index e892ff3d2..e141f1e65 100644 --- a/src/tool_progress.c +++ b/src/tool_cb_prg.c @@ -28,13 +28,17 @@ #include "curlx.h" #include "tool_cfgable.h" -#include "tool_progress.h" +#include "tool_cb_prg.h" #include "memdebug.h" /* keep this as LAST include */ -int my_progress(void *clientp, - double dltotal, double dlnow, - double ultotal, double ulnow) +/* +** callback for CURLOPT_PROGRESSFUNCTION +*/ + +int tool_progress_cb(void *clientp, + double dltotal, double dlnow, + double ultotal, double ulnow) { /* The original progress-bar source code was written for curl by Lars Aas, and this new edition inherits some of his concepts. */ diff --git a/src/tool_progress.h b/src/tool_cb_prg.h similarity index 82% rename from src/tool_progress.h rename to src/tool_cb_prg.h index 7be2744b8..f64335a3b 100644 --- a/src/tool_progress.h +++ b/src/tool_cb_prg.h @@ -1,5 +1,5 @@ -#ifndef HEADER_CURL_TOOL_PROGRESS_H -#define HEADER_CURL_TOOL_PROGRESS_H +#ifndef HEADER_CURL_TOOL_CB_PRG_H +#define HEADER_CURL_TOOL_CB_PRG_H /*************************************************************************** * _ _ ____ _ * Project ___| | | | _ \| | @@ -34,12 +34,16 @@ struct ProgressData { curl_off_t initial_size; }; -int my_progress(void *clientp, - double dltotal, double dlnow, - double ultotal, double ulnow); - void progressbarinit(struct ProgressData *bar, struct Configurable *config); -#endif /* HEADER_CURL_TOOL_PROGRESS_H */ +/* +** callback for CURLOPT_PROGRESSFUNCTION +*/ + +int tool_progress_cb(void *clientp, + double dltotal, double dlnow, + double ultotal, double ulnow); + +#endif /* HEADER_CURL_TOOL_CB_PRG_H */ diff --git a/src/tool_cb_rea.c b/src/tool_cb_rea.c new file mode 100644 index 000000000..34edb063b --- /dev/null +++ b/src/tool_cb_rea.c @@ -0,0 +1,61 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "setup.h" + +#include + +#ifdef HAVE_UNISTD_H +# include +#endif + +#define ENABLE_CURLX_PRINTF +/* use our own printf() functions */ +#include "curlx.h" + +#include "tool_cfgable.h" +#include "tool_cb_rea.h" + +#include "memdebug.h" /* keep this as LAST include */ + +/* +** callback for CURLOPT_READFUNCTION +*/ + +size_t tool_read_cb(void *buffer, size_t sz, size_t nmemb, void *userdata) +{ + ssize_t rc; + struct InStruct *in = userdata; + + rc = read(in->fd, buffer, sz*nmemb); + if(rc < 0) { + if(errno == EAGAIN) { + errno = 0; + in->config->readbusy = TRUE; + return CURL_READFUNC_PAUSE; + } + /* since size_t is unsigned we can't return negative values fine */ + rc = 0; + } + in->config->readbusy = FALSE; + return (size_t)rc; +} + diff --git a/src/tool_cb_rea.h b/src/tool_cb_rea.h new file mode 100644 index 000000000..40c61f6f1 --- /dev/null +++ b/src/tool_cb_rea.h @@ -0,0 +1,33 @@ +#ifndef HEADER_CURL_TOOL_CB_REA_H +#define HEADER_CURL_TOOL_CB_REA_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "setup.h" + +/* +** callback for CURLOPT_READFUNCTION +*/ + +size_t tool_read_cb(void *buffer, size_t sz, size_t nmemb, void *userdata); + +#endif /* HEADER_CURL_TOOL_CB_REA_H */ + diff --git a/src/tool_cb_see.c b/src/tool_cb_see.c new file mode 100644 index 000000000..5bac4947b --- /dev/null +++ b/src/tool_cb_see.c @@ -0,0 +1,129 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "setup.h" + +#include + +#ifdef HAVE_UNISTD_H +# include +#endif + +#define ENABLE_CURLX_PRINTF +/* use our own printf() functions */ +#include "curlx.h" + +#include "tool_cfgable.h" +#include "tool_cb_see.h" + +#include "memdebug.h" /* keep this as LAST include */ + +/* OUR_MAX_SEEK_L has 'long' data type, OUR_MAX_SEEK_O has 'curl_off_t, + both represent the same value. Maximum offset used here when we lseek + using a 'long' data type offset */ + +#define OUR_MAX_SEEK_L 2147483647L - 1L +#define OUR_MAX_SEEK_O CURL_OFF_T_C(0x7FFFFFFF) - CURL_OFF_T_C(0x1) + +/* +** callback for CURLOPT_SEEKFUNCTION +** +** Notice that this is not supposed to return the resulting offset. This +** shall only return CURL_SEEKFUNC_* return codes. +*/ + +int tool_seek_cb(void *userdata, curl_off_t offset, int whence) +{ + struct InStruct *in = userdata; + +#if(CURL_SIZEOF_CURL_OFF_T > SIZEOF_OFF_T) && !defined(USE_WIN32_LARGE_FILES) + + /* The offset check following here is only interesting if curl_off_t is + larger than off_t and we are not using the WIN32 large file support + macros that provide the support to do 64bit seeks correctly */ + + if(offset > OUR_MAX_SEEK_O) { + /* Some precaution code to work around problems with different data sizes + to allow seeking >32bit even if off_t is 32bit. Should be very rare and + is really valid on weirdo-systems. */ + curl_off_t left = offset; + + if(whence != SEEK_SET) + /* this code path doesn't support other types */ + return CURL_SEEKFUNC_FAIL; + + if(LSEEK_ERROR == lseek(in->fd, 0, SEEK_SET)) + /* couldn't rewind to beginning */ + return CURL_SEEKFUNC_FAIL; + + while(left) { + long step = (left > OUR_MAX_SEEK_O) ? OUR_MAX_SEEK_L : (long)left; + if(LSEEK_ERROR == lseek(in->fd, step, SEEK_CUR)) + /* couldn't seek forwards the desired amount */ + return CURL_SEEKFUNC_FAIL; + left -= step; + } + return CURL_SEEKFUNC_OK; + } +#endif + + if(LSEEK_ERROR == lseek(in->fd, offset, whence)) + /* couldn't rewind, the reason is in errno but errno is just not portable + enough and we don't actually care that much why we failed. We'll let + libcurl know that it may try other means if it wants to. */ + return CURL_SEEKFUNC_CANTSEEK; + + return CURL_SEEKFUNC_OK; +} + +#if defined(WIN32) && !defined(__MINGW64__) + +#ifdef __BORLANDC__ +/* 64-bit lseek-like function unavailable */ +# define _lseeki64(hnd,ofs,whence) lseek(hnd,ofs,whence) +#endif + +#ifdef __POCC__ +# if(__POCC__ < 450) +/* 64-bit lseek-like function unavailable */ +# define _lseeki64(hnd,ofs,whence) _lseek(hnd,ofs,whence) +# else +# define _lseeki64(hnd,ofs,whence) _lseek64(hnd,ofs,whence) +# endif +#endif + +/* + * Truncate a file handle at a 64-bit position 'where'. + */ + +int tool_ftruncate64(int fd, curl_off_t where) +{ + if(_lseeki64(fd, where, SEEK_SET) < 0) + return -1; + + if(!SetEndOfFile((HANDLE)_get_osfhandle(fd))) + return -1; + + return 0; +} + +#endif /* WIN32 && ! __MINGW64__ */ + diff --git a/src/tool_cb_see.h b/src/tool_cb_see.h new file mode 100644 index 000000000..530bfacba --- /dev/null +++ b/src/tool_cb_see.h @@ -0,0 +1,45 @@ +#ifndef HEADER_CURL_TOOL_CB_SEE_H +#define HEADER_CURL_TOOL_CB_SEE_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "setup.h" + +#if defined(WIN32) && !defined(__MINGW64__) + +int tool_ftruncate64(int fd, curl_off_t where); + +#define ftruncate(fd,where) tool_ftruncate64(fd,where) + +#ifndef HAVE_FTRUNCATE +# define HAVE_FTRUNCATE 1 +#endif + +#endif /* WIN32 && ! __MINGW64__ */ + +/* +** callback for CURLOPT_SEEKFUNCTION +*/ + +int tool_seek_cb(void *userdata, curl_off_t offset, int whence); + +#endif /* HEADER_CURL_TOOL_CB_SEE_H */ + diff --git a/src/tool_cb_skt.c b/src/tool_cb_skt.c new file mode 100644 index 000000000..156c1108e --- /dev/null +++ b/src/tool_cb_skt.c @@ -0,0 +1,97 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "setup.h" + +#include + +#ifdef HAVE_SYS_SOCKET_H +# include +#endif + +#define ENABLE_CURLX_PRINTF +/* use our own printf() functions */ +#include "curlx.h" + +#include "tool_cfgable.h" +#include "tool_msgs.h" +#include "tool_cb_skt.h" + +#include "memdebug.h" /* keep this as LAST include */ + +/* +** callback for CURLOPT_SOCKOPTFUNCTION +*/ + +int tool_sockopt_cb(void *userdata, curl_socket_t curlfd, curlsocktype purpose) +{ + struct Configurable *config = userdata; + + int onoff = 1; /* this callback is only used if we ask for keepalives on the + connection */ + +#if defined(TCP_KEEPIDLE) || defined(TCP_KEEPINTVL) + int keepidle = (int)config->alivetime; +#endif + + switch(purpose) { + case CURLSOCKTYPE_IPCXN: + if(setsockopt(curlfd, SOL_SOCKET, SO_KEEPALIVE, (void *)&onoff, + sizeof(onoff)) < 0) { + /* don't abort operation, just issue a warning */ + SET_SOCKERRNO(0); + warnf(config, "Could not set SO_KEEPALIVE!\n"); + return 0; + } + else { + if(config->alivetime) { +#ifdef TCP_KEEPIDLE + if(setsockopt(curlfd, IPPROTO_TCP, TCP_KEEPIDLE, (void *)&keepidle, + sizeof(keepidle)) < 0) { + /* don't abort operation, just issue a warning */ + SET_SOCKERRNO(0); + warnf(config, "Could not set TCP_KEEPIDLE!\n"); + return 0; + } +#endif +#ifdef TCP_KEEPINTVL + if(setsockopt(curlfd, IPPROTO_TCP, TCP_KEEPINTVL, (void *)&keepidle, + sizeof(keepidle)) < 0) { + /* don't abort operation, just issue a warning */ + SET_SOCKERRNO(0); + warnf(config, "Could not set TCP_KEEPINTVL!\n"); + return 0; + } +#endif +#if !defined(TCP_KEEPIDLE) || !defined(TCP_KEEPINTVL) + warnf(config, "Keep-alive functionality somewhat crippled due to " + "missing support in your operating system!\n"); +#endif + } + } + break; + default: + break; + } + + return 0; +} + diff --git a/src/tool_cb_skt.h b/src/tool_cb_skt.h new file mode 100644 index 000000000..11bd0c422 --- /dev/null +++ b/src/tool_cb_skt.h @@ -0,0 +1,35 @@ +#ifndef HEADER_CURL_TOOL_CB_SKT_H +#define HEADER_CURL_TOOL_CB_SKT_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "setup.h" + +/* +** callback for CURLOPT_SOCKOPTFUNCTION +*/ + +int tool_sockopt_cb(void *userdata, + curl_socket_t curlfd, + curlsocktype purpose); + +#endif /* HEADER_CURL_TOOL_CB_SKT_H */ + diff --git a/src/tool_cb_wrt.c b/src/tool_cb_wrt.c new file mode 100644 index 000000000..3a2cd791a --- /dev/null +++ b/src/tool_cb_wrt.c @@ -0,0 +1,103 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "setup.h" + +#include + +#define ENABLE_CURLX_PRINTF +/* use our own printf() functions */ +#include "curlx.h" + +#include "tool_cfgable.h" +#include "tool_msgs.h" +#include "tool_cb_wrt.h" + +#include "memdebug.h" /* keep this as LAST include */ + +/* +** callback for CURLOPT_WRITEFUNCTION +*/ + +size_t tool_write_cb(void *buffer, size_t sz, size_t nmemb, void *userdata) +{ + size_t rc; + struct OutStruct *out = userdata; + struct Configurable *config = out->config; + + /* + * Once that libcurl has called back tool_write_cb() the returned value + * is checked against the amount that was intended to be written, if + * it does not match then it fails with CURLE_WRITE_ERROR. So at this + * point returning a value different from sz*nmemb indicates failure. + */ + const size_t err_rc = (sz * nmemb) ? 0 : 1; + + if(!out->stream) { + out->bytes = 0; /* nothing written yet */ + if(!out->filename) { + warnf(config, "Remote filename has no length!\n"); + return err_rc; /* Failure */ + } + + if(config->content_disposition) { + /* don't overwrite existing files */ + FILE* f = fopen(out->filename, "r"); + if(f) { + fclose(f); + warnf(config, "Refusing to overwrite %s: %s\n", out->filename, + strerror(EEXIST)); + return err_rc; /* Failure */ + } + } + + /* open file for writing */ + out->stream = fopen(out->filename, "wb"); + if(!out->stream) { + warnf(config, "Failed to create the file %s: %s\n", out->filename, + strerror(errno)); + return err_rc; /* failure */ + } + } + + rc = fwrite(buffer, sz, nmemb, out->stream); + + if((sz * nmemb) == rc) + /* we added this amount of data to the output */ + out->bytes += (sz * nmemb); + + if(config->readbusy) { + config->readbusy = FALSE; + curl_easy_pause(config->easy, CURLPAUSE_CONT); + } + + if(config->nobuffer) { + /* disable output buffering */ + int res = fflush(out->stream); + if(res) { + /* return a value that isn't the same as sz * nmemb */ + return err_rc; /* failure */ + } + } + + return rc; +} + diff --git a/src/tool_cb_wrt.h b/src/tool_cb_wrt.h new file mode 100644 index 000000000..a17c14607 --- /dev/null +++ b/src/tool_cb_wrt.h @@ -0,0 +1,33 @@ +#ifndef HEADER_CURL_TOOL_CB_WRT_H +#define HEADER_CURL_TOOL_CB_WRT_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "setup.h" + +/* +** callback for CURLOPT_WRITEFUNCTION +*/ + +size_t tool_write_cb(void *buffer, size_t sz, size_t nmemb, void *userdata); + +#endif /* HEADER_CURL_TOOL_CB_WRT_H */ + diff --git a/src/vc6curlsrc.dsp b/src/vc6curlsrc.dsp index 9b2011724..f8dadbd67 100644 --- a/src/vc6curlsrc.dsp +++ b/src/vc6curlsrc.dsp @@ -175,6 +175,34 @@ SOURCE=.\tool_bname.c # End Source File # Begin Source File +SOURCE=.\tool_cb_dbg.c +# End Source File +# Begin Source File + +SOURCE=.\tool_cb_hdr.c +# End Source File +# Begin Source File + +SOURCE=.\tool_cb_prg.c +# End Source File +# Begin Source File + +SOURCE=.\tool_cb_rea.c +# End Source File +# Begin Source File + +SOURCE=.\tool_cb_see.c +# End Source File +# Begin Source File + +SOURCE=.\tool_cb_skt.c +# End Source File +# Begin Source File + +SOURCE=.\tool_cb_wrt.c +# End Source File +# Begin Source File + SOURCE=.\tool_cfgable.c # End Source File # Begin Source File @@ -211,10 +239,6 @@ SOURCE=.\tool_myfunc.c # End Source File # Begin Source File -SOURCE=.\tool_progress.c -# End Source File -# Begin Source File - SOURCE=.\tool_setopt.c # End Source File # Begin Source File @@ -283,6 +307,34 @@ SOURCE=.\tool_bname.h # End Source File # Begin Source File +SOURCE=.\tool_cb_dbg.h +# End Source File +# Begin Source File + +SOURCE=.\tool_cb_hdr.h +# End Source File +# Begin Source File + +SOURCE=.\tool_cb_prg.h +# End Source File +# Begin Source File + +SOURCE=.\tool_cb_rea.h +# End Source File +# Begin Source File + +SOURCE=.\tool_cb_see.h +# End Source File +# Begin Source File + +SOURCE=.\tool_cb_skt.h +# End Source File +# Begin Source File + +SOURCE=.\tool_cb_wrt.h +# End Source File +# Begin Source File + SOURCE=.\tool_cfgable.h # End Source File # Begin Source File @@ -319,10 +371,6 @@ SOURCE=.\tool_myfunc.h # End Source File # Begin Source File -SOURCE=.\tool_progress.h -# End Source File -# Begin Source File - SOURCE=.\tool_sdecls.h # End Source File # Begin Source File