mirror of https://github.com/moparisthebest/curl
curl tool: reviewed code moved to tool_*.[ch] files
This commit is contained in:
parent
8bab6700d9
commit
c6702c7d3f
|
@ -11,6 +11,13 @@ SOURCE \
|
||||||
main.c hugehelp.c urlglob.c writeout.c writeenv.c \
|
main.c hugehelp.c urlglob.c writeout.c writeenv.c \
|
||||||
getpass.c homedir.c curlutil.c xattr.c \
|
getpass.c homedir.c curlutil.c xattr.c \
|
||||||
tool_bname.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_cfgable.c \
|
||||||
tool_convert.c \
|
tool_convert.c \
|
||||||
tool_dirhie.c \
|
tool_dirhie.c \
|
||||||
|
@ -20,7 +27,6 @@ SOURCE \
|
||||||
tool_mfiles.c \
|
tool_mfiles.c \
|
||||||
tool_msgs.c \
|
tool_msgs.c \
|
||||||
tool_myfunc.c \
|
tool_myfunc.c \
|
||||||
tool_progress.c \
|
|
||||||
tool_setopt.c \
|
tool_setopt.c \
|
||||||
tool_vms.c
|
tool_vms.c
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,13 @@ CURLX_ONES = $(top_srcdir)/lib/strtoofft.c \
|
||||||
CURL_CFILES = main.c hugehelp.c urlglob.c writeout.c writeenv.c \
|
CURL_CFILES = main.c hugehelp.c urlglob.c writeout.c writeenv.c \
|
||||||
getpass.c homedir.c curlutil.c xattr.c \
|
getpass.c homedir.c curlutil.c xattr.c \
|
||||||
tool_bname.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_cfgable.c \
|
||||||
tool_convert.c \
|
tool_convert.c \
|
||||||
tool_dirhie.c \
|
tool_dirhie.c \
|
||||||
|
@ -26,7 +33,6 @@ CURL_CFILES = main.c hugehelp.c urlglob.c writeout.c writeenv.c \
|
||||||
tool_mfiles.c \
|
tool_mfiles.c \
|
||||||
tool_msgs.c \
|
tool_msgs.c \
|
||||||
tool_myfunc.c \
|
tool_myfunc.c \
|
||||||
tool_progress.c \
|
|
||||||
tool_setopt.c \
|
tool_setopt.c \
|
||||||
tool_vms.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 \
|
config-riscos.h urlglob.h version.h xattr.h \
|
||||||
writeout.h writeenv.h getpass.h homedir.h curlutil.h \
|
writeout.h writeenv.h getpass.h homedir.h curlutil.h \
|
||||||
tool_bname.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_cfgable.h \
|
||||||
tool_convert.h \
|
tool_convert.h \
|
||||||
tool_dirhie.h \
|
tool_dirhie.h \
|
||||||
|
@ -43,7 +56,6 @@ CURL_HFILES = hugehelp.h setup.h config-win32.h config-mac.h \
|
||||||
tool_mfiles.h \
|
tool_mfiles.h \
|
||||||
tool_msgs.h \
|
tool_msgs.h \
|
||||||
tool_myfunc.h \
|
tool_myfunc.h \
|
||||||
tool_progress.h \
|
|
||||||
tool_sdecls.h \
|
tool_sdecls.h \
|
||||||
tool_setopt.h \
|
tool_setopt.h \
|
||||||
tool_vms.h
|
tool_vms.h
|
||||||
|
|
|
@ -142,6 +142,13 @@ RELEASE_OBJS= \
|
||||||
rawstrr.obj \
|
rawstrr.obj \
|
||||||
strtoofftr.obj \
|
strtoofftr.obj \
|
||||||
tool_bnamer.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_cfgabler.obj \
|
||||||
tool_convertr.obj \
|
tool_convertr.obj \
|
||||||
tool_dirhier.obj \
|
tool_dirhier.obj \
|
||||||
|
@ -151,7 +158,6 @@ RELEASE_OBJS= \
|
||||||
tool_mfilesr.obj \
|
tool_mfilesr.obj \
|
||||||
tool_msgsr.obj \
|
tool_msgsr.obj \
|
||||||
tool_myfuncr.obj \
|
tool_myfuncr.obj \
|
||||||
tool_progressr.obj \
|
|
||||||
tool_setoptr.obj \
|
tool_setoptr.obj \
|
||||||
tool_vmsr.obj \
|
tool_vmsr.obj \
|
||||||
urlglobr.obj \
|
urlglobr.obj \
|
||||||
|
@ -169,6 +175,13 @@ DEBUG_OBJS= \
|
||||||
rawstrd.obj \
|
rawstrd.obj \
|
||||||
strtoofftd.obj \
|
strtoofftd.obj \
|
||||||
tool_bnamed.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_cfgabled.obj \
|
||||||
tool_convertd.obj \
|
tool_convertd.obj \
|
||||||
tool_dirhied.obj \
|
tool_dirhied.obj \
|
||||||
|
@ -178,7 +191,6 @@ DEBUG_OBJS= \
|
||||||
tool_mfilesd.obj \
|
tool_mfilesd.obj \
|
||||||
tool_msgsd.obj \
|
tool_msgsd.obj \
|
||||||
tool_myfuncd.obj \
|
tool_myfuncd.obj \
|
||||||
tool_progressd.obj \
|
|
||||||
tool_setoptd.obj \
|
tool_setoptd.obj \
|
||||||
tool_vmsd.obj \
|
tool_vmsd.obj \
|
||||||
urlglobd.obj \
|
urlglobd.obj \
|
||||||
|
@ -326,6 +338,20 @@ strtoofftr.obj: ../lib/strtoofft.c
|
||||||
$(CCR) $(CFLAGS) /Fo"$@" ../lib/strtoofft.c
|
$(CCR) $(CFLAGS) /Fo"$@" ../lib/strtoofft.c
|
||||||
tool_bnamer.obj: tool_bname.c
|
tool_bnamer.obj: tool_bname.c
|
||||||
$(CCR) $(CFLAGS) /Fo"$@" 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
|
tool_cfgabler.obj: tool_cfgable.c
|
||||||
$(CCR) $(CFLAGS) /Fo"$@" tool_cfgable.c
|
$(CCR) $(CFLAGS) /Fo"$@" tool_cfgable.c
|
||||||
tool_convertr.obj: tool_convert.c
|
tool_convertr.obj: tool_convert.c
|
||||||
|
@ -344,8 +370,6 @@ tool_msgsr.obj: tool_msgs.c
|
||||||
$(CCR) $(CFLAGS) /Fo"$@" tool_msgs.c
|
$(CCR) $(CFLAGS) /Fo"$@" tool_msgs.c
|
||||||
tool_myfuncr.obj: tool_myfunc.c
|
tool_myfuncr.obj: tool_myfunc.c
|
||||||
$(CCR) $(CFLAGS) /Fo"$@" 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
|
tool_setoptr.obj: tool_setopt.c
|
||||||
$(CCR) $(CFLAGS) /Fo"$@" tool_setopt.c
|
$(CCR) $(CFLAGS) /Fo"$@" tool_setopt.c
|
||||||
tool_vmsr.obj: tool_vms.c
|
tool_vmsr.obj: tool_vms.c
|
||||||
|
@ -378,6 +402,20 @@ strtoofftd.obj: ../lib/strtoofft.c
|
||||||
$(CCD) $(CFLAGS) /Fo"$@" ../lib/strtoofft.c
|
$(CCD) $(CFLAGS) /Fo"$@" ../lib/strtoofft.c
|
||||||
tool_bnamed.obj: tool_bname.c
|
tool_bnamed.obj: tool_bname.c
|
||||||
$(CCD) $(CFLAGS) /Fo"$@" 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
|
tool_cfgabled.obj: tool_cfgable.c
|
||||||
$(CCD) $(CFLAGS) /Fo"$@" tool_cfgable.c
|
$(CCD) $(CFLAGS) /Fo"$@" tool_cfgable.c
|
||||||
tool_convertd.obj: tool_convert.c
|
tool_convertd.obj: tool_convert.c
|
||||||
|
@ -396,8 +434,6 @@ tool_msgsd.obj: tool_msgs.c
|
||||||
$(CCD) $(CFLAGS) /Fo"$@" tool_msgs.c
|
$(CCD) $(CFLAGS) /Fo"$@" tool_msgs.c
|
||||||
tool_myfuncd.obj: tool_myfunc.c
|
tool_myfuncd.obj: tool_myfunc.c
|
||||||
$(CCD) $(CFLAGS) /Fo"$@" 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
|
tool_setoptd.obj: tool_setopt.c
|
||||||
$(CCD) $(CFLAGS) /Fo"$@" tool_setopt.c
|
$(CCD) $(CFLAGS) /Fo"$@" tool_setopt.c
|
||||||
tool_vmsd.obj: tool_vms.c
|
tool_vmsd.obj: tool_vms.c
|
||||||
|
|
622
src/main.c
622
src/main.c
|
@ -102,9 +102,17 @@
|
||||||
#include "tool_mfiles.h"
|
#include "tool_mfiles.h"
|
||||||
#include "tool_msgs.h"
|
#include "tool_msgs.h"
|
||||||
#include "tool_myfunc.h"
|
#include "tool_myfunc.h"
|
||||||
#include "tool_progress.h"
|
#include "tool_cb_prg.h"
|
||||||
#include "tool_setopt.h"
|
#include "tool_setopt.h"
|
||||||
#include "tool_vms.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
|
#ifdef USE_MANUAL
|
||||||
# include "hugehelp.h"
|
# include "hugehelp.h"
|
||||||
#endif
|
#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" \
|
"If you'd like to turn off curl's verification of the certificate, use\n" \
|
||||||
" the -k (or --insecure) option.\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
|
* This is the main global constructor for the app. Call this before
|
||||||
* _any_ libcurl usage. If this fails, *NO* libcurl functions may be
|
* _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;
|
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,
|
static long delegation(struct Configurable *config,
|
||||||
char *str)
|
char *str)
|
||||||
{
|
{
|
||||||
|
@ -3045,369 +2961,6 @@ static void go_sleep(long ms)
|
||||||
#endif
|
#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_DEFAULT 1000L /* ms */
|
||||||
#define RETRY_SLEEP_MAX 600000L /* ms == 10 minutes */
|
#define RETRY_SLEEP_MAX 600000L /* ms == 10 minutes */
|
||||||
|
|
||||||
|
@ -3505,147 +3058,6 @@ static char *get_url_file_name(const char *url)
|
||||||
return fn;
|
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
|
#ifdef CURLDEBUG
|
||||||
static void memory_tracking_init(void)
|
static void memory_tracking_init(void)
|
||||||
{
|
{
|
||||||
|
@ -4322,7 +3734,7 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])
|
||||||
/* where to store */
|
/* where to store */
|
||||||
my_setopt(curl, CURLOPT_WRITEDATA, &outs);
|
my_setopt(curl, CURLOPT_WRITEDATA, &outs);
|
||||||
/* what call to write */
|
/* what call to write */
|
||||||
my_setopt(curl, CURLOPT_WRITEFUNCTION, my_fwrite);
|
my_setopt(curl, CURLOPT_WRITEFUNCTION, tool_write_cb);
|
||||||
|
|
||||||
/* for uploads */
|
/* for uploads */
|
||||||
input.fd = infd;
|
input.fd = infd;
|
||||||
|
@ -4331,12 +3743,12 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])
|
||||||
/* what call to read */
|
/* what call to read */
|
||||||
if((outfile && !curlx_strequal("-", outfile)) ||
|
if((outfile && !curlx_strequal("-", outfile)) ||
|
||||||
!checkprefix("telnet:", this_url))
|
!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
|
/* in 7.18.0, the CURLOPT_SEEKFUNCTION/DATA pair is taking over what
|
||||||
CURLOPT_IOCTLFUNCTION/DATA pair previously provided for seeking */
|
CURLOPT_IOCTLFUNCTION/DATA pair previously provided for seeking */
|
||||||
my_setopt(curl, CURLOPT_SEEKDATA, &input);
|
my_setopt(curl, CURLOPT_SEEKDATA, &input);
|
||||||
my_setopt(curl, CURLOPT_SEEKFUNCTION, my_seek);
|
my_setopt(curl, CURLOPT_SEEKFUNCTION, tool_seek_cb);
|
||||||
|
|
||||||
if(config->recvpersecond)
|
if(config->recvpersecond)
|
||||||
/* tell libcurl to use a smaller sized buffer as it allows us to
|
/* 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) {
|
!config->noprogress && !config->mute) {
|
||||||
/* we want the alternative style, then we have to implement it
|
/* we want the alternative style, then we have to implement it
|
||||||
ourselves! */
|
ourselves! */
|
||||||
my_setopt(curl, CURLOPT_PROGRESSFUNCTION, my_progress);
|
my_setopt(curl, CURLOPT_PROGRESSFUNCTION, tool_progress_cb);
|
||||||
my_setopt(curl, CURLOPT_PROGRESSDATA, &progressbar);
|
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);
|
my_setopt(curl, CURLOPT_FTP_USE_EPRT, FALSE);
|
||||||
|
|
||||||
if(config->tracetype != TRACE_NONE) {
|
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_DEBUGDATA, config);
|
||||||
my_setopt(curl, CURLOPT_VERBOSE, TRUE);
|
my_setopt(curl, CURLOPT_VERBOSE, TRUE);
|
||||||
}
|
}
|
||||||
|
@ -4702,7 +4114,7 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])
|
||||||
|
|
||||||
/* curl 7.17.1 */
|
/* curl 7.17.1 */
|
||||||
if(!config->nokeepalive) {
|
if(!config->nokeepalive) {
|
||||||
my_setopt(curl, CURLOPT_SOCKOPTFUNCTION, sockoptcallback);
|
my_setopt(curl, CURLOPT_SOCKOPTFUNCTION, tool_sockopt_cb);
|
||||||
my_setopt(curl, CURLOPT_SOCKOPTDATA, config);
|
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)
|
if((urlnode->flags & GETOUT_USEREMOTE)
|
||||||
&& config->content_disposition) {
|
&& config->content_disposition) {
|
||||||
my_setopt(curl, CURLOPT_HEADERFUNCTION, header_callback);
|
my_setopt(curl, CURLOPT_HEADERFUNCTION, tool_header_cb);
|
||||||
my_setopt(curl, CURLOPT_HEADERDATA, &outs);
|
my_setopt(curl, CURLOPT_HEADERDATA, &outs);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -5045,6 +4457,8 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])
|
||||||
Curl_safefree(urlnode->infile);
|
Curl_safefree(urlnode->infile);
|
||||||
urlnode->flags = 0;
|
urlnode->flags = 0;
|
||||||
|
|
||||||
|
/* TODO: Should CURLE_SSL_CACERT be included as critical error ? */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Bail out upon critical errors
|
** Bail out upon critical errors
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -0,0 +1,276 @@
|
||||||
|
/***************************************************************************
|
||||||
|
* _ _ ____ _
|
||||||
|
* Project ___| | | | _ \| |
|
||||||
|
* / __| | | | |_) | |
|
||||||
|
* | (__| |_| | _ <| |___
|
||||||
|
* \___|\___/|_| \_\_____|
|
||||||
|
*
|
||||||
|
* Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, 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 <curl/curl.h>
|
||||||
|
|
||||||
|
#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);
|
||||||
|
}
|
||||||
|
|
|
@ -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, <daniel@haxx.se>, 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 */
|
||||||
|
|
|
@ -0,0 +1,182 @@
|
||||||
|
/***************************************************************************
|
||||||
|
* _ _ ____ _
|
||||||
|
* Project ___| | | | _ \| |
|
||||||
|
* / __| | | | |_) | |
|
||||||
|
* | (__| |_| | _ <| |___
|
||||||
|
* \___|\___/|_| \_\_____|
|
||||||
|
*
|
||||||
|
* Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, 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 <curl/curl.h>
|
||||||
|
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
|
|
@ -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, <daniel@haxx.se>, 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 */
|
||||||
|
|
|
@ -28,13 +28,17 @@
|
||||||
#include "curlx.h"
|
#include "curlx.h"
|
||||||
|
|
||||||
#include "tool_cfgable.h"
|
#include "tool_cfgable.h"
|
||||||
#include "tool_progress.h"
|
#include "tool_cb_prg.h"
|
||||||
|
|
||||||
#include "memdebug.h" /* keep this as LAST include */
|
#include "memdebug.h" /* keep this as LAST include */
|
||||||
|
|
||||||
int my_progress(void *clientp,
|
/*
|
||||||
double dltotal, double dlnow,
|
** callback for CURLOPT_PROGRESSFUNCTION
|
||||||
double ultotal, double ulnow)
|
*/
|
||||||
|
|
||||||
|
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,
|
/* The original progress-bar source code was written for curl by Lars Aas,
|
||||||
and this new edition inherits some of his concepts. */
|
and this new edition inherits some of his concepts. */
|
|
@ -1,5 +1,5 @@
|
||||||
#ifndef HEADER_CURL_TOOL_PROGRESS_H
|
#ifndef HEADER_CURL_TOOL_CB_PRG_H
|
||||||
#define HEADER_CURL_TOOL_PROGRESS_H
|
#define HEADER_CURL_TOOL_CB_PRG_H
|
||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
* _ _ ____ _
|
* _ _ ____ _
|
||||||
* Project ___| | | | _ \| |
|
* Project ___| | | | _ \| |
|
||||||
|
@ -34,12 +34,16 @@ struct ProgressData {
|
||||||
curl_off_t initial_size;
|
curl_off_t initial_size;
|
||||||
};
|
};
|
||||||
|
|
||||||
int my_progress(void *clientp,
|
|
||||||
double dltotal, double dlnow,
|
|
||||||
double ultotal, double ulnow);
|
|
||||||
|
|
||||||
void progressbarinit(struct ProgressData *bar,
|
void progressbarinit(struct ProgressData *bar,
|
||||||
struct Configurable *config);
|
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 */
|
||||||
|
|
|
@ -0,0 +1,61 @@
|
||||||
|
/***************************************************************************
|
||||||
|
* _ _ ____ _
|
||||||
|
* Project ___| | | | _ \| |
|
||||||
|
* / __| | | | |_) | |
|
||||||
|
* | (__| |_| | _ <| |___
|
||||||
|
* \___|\___/|_| \_\_____|
|
||||||
|
*
|
||||||
|
* Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, 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 <curl/curl.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_UNISTD_H
|
||||||
|
# include <unistd.h>
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
|
|
@ -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, <daniel@haxx.se>, 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 */
|
||||||
|
|
|
@ -0,0 +1,129 @@
|
||||||
|
/***************************************************************************
|
||||||
|
* _ _ ____ _
|
||||||
|
* Project ___| | | | _ \| |
|
||||||
|
* / __| | | | |_) | |
|
||||||
|
* | (__| |_| | _ <| |___
|
||||||
|
* \___|\___/|_| \_\_____|
|
||||||
|
*
|
||||||
|
* Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, 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 <curl/curl.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_UNISTD_H
|
||||||
|
# include <unistd.h>
|
||||||
|
#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__ */
|
||||||
|
|
|
@ -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, <daniel@haxx.se>, 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 */
|
||||||
|
|
|
@ -0,0 +1,97 @@
|
||||||
|
/***************************************************************************
|
||||||
|
* _ _ ____ _
|
||||||
|
* Project ___| | | | _ \| |
|
||||||
|
* / __| | | | |_) | |
|
||||||
|
* | (__| |_| | _ <| |___
|
||||||
|
* \___|\___/|_| \_\_____|
|
||||||
|
*
|
||||||
|
* Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, 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 <curl/curl.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_SYS_SOCKET_H
|
||||||
|
# include <sys/socket.h>
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
|
|
@ -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, <daniel@haxx.se>, 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 */
|
||||||
|
|
|
@ -0,0 +1,103 @@
|
||||||
|
/***************************************************************************
|
||||||
|
* _ _ ____ _
|
||||||
|
* Project ___| | | | _ \| |
|
||||||
|
* / __| | | | |_) | |
|
||||||
|
* | (__| |_| | _ <| |___
|
||||||
|
* \___|\___/|_| \_\_____|
|
||||||
|
*
|
||||||
|
* Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, 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 <curl/curl.h>
|
||||||
|
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
|
|
@ -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, <daniel@haxx.se>, 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 */
|
||||||
|
|
|
@ -175,6 +175,34 @@ SOURCE=.\tool_bname.c
|
||||||
# End Source File
|
# End Source File
|
||||||
# Begin 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
|
SOURCE=.\tool_cfgable.c
|
||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
@ -211,10 +239,6 @@ SOURCE=.\tool_myfunc.c
|
||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
|
||||||
SOURCE=.\tool_progress.c
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\tool_setopt.c
|
SOURCE=.\tool_setopt.c
|
||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
@ -283,6 +307,34 @@ SOURCE=.\tool_bname.h
|
||||||
# End Source File
|
# End Source File
|
||||||
# Begin 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
|
SOURCE=.\tool_cfgable.h
|
||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
@ -319,10 +371,6 @@ SOURCE=.\tool_myfunc.h
|
||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
|
||||||
SOURCE=.\tool_progress.h
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\tool_sdecls.h
|
SOURCE=.\tool_sdecls.h
|
||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
|
Loading…
Reference in New Issue