Commit c6702c7d authored by Yang Tse's avatar Yang Tse
Browse files

curl tool: reviewed code moved to tool_*.[ch] files

parent 8bab6700
Loading
Loading
Loading
Loading
+7 −1
Original line number Diff line number Diff line
@@ -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

+14 −2
Original line number Diff line number Diff line
@@ -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
+42 −6
Original line number Diff line number Diff line
@@ -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
+18 −604
Original line number Diff line number Diff line
@@ -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<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);
}

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; 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;
}

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

src/tool_cb_dbg.c

0 → 100644
+276 −0

File added.

Preview size limit exceeded, changes collapsed.

Loading