1
0
mirror of https://github.com/moparisthebest/curl synced 2024-12-21 07:38:49 -05:00

moved here from the newlib branch

This commit is contained in:
Daniel Stenberg 2000-05-22 14:12:12 +00:00
parent fb9d1ff00f
commit 96dde76b99
54 changed files with 2824 additions and 2580 deletions

33
CHANGES
View File

@ -8,6 +8,39 @@
Version XX Version XX
Daniel (21 May 2000)
- Updated lots of #defines, enums and variable type names in the library. No
more weird URG or URLTAG prefixes. All types and names should be curl-
prefixed to avoid name space clashes. The FLAGS-parameter to the former
curl_urlget() has been converted into a bunch of flags to use in separate
setopt calls. I'm still focusing on the easy-interface, as the curl tool is
now using that.
- Bjorn Reese has provided me with an asynchronous name resolver that I plan
to use in upcoming versions of curl to be able to gracefully timeout name
lookups.
Version 7.0beta released
Daniel (18 May 2000)
- Introduced LIBCURL_VERSION_NUM to the curl.h include file to better allow
source codes to be dependent on the lib version. This define is now set to
a dexadecimal number, with 8 bits each for major number, minor number and
patch number. In other words, version 1.2.3 would make it 0x010203. It also
makes a larger number a newer version.
Daniel (17 May 2000)
- Martin Kammerhofer correctly pointed out several flaws in the FTP range
option. I corrected them.
- Removed the win32 winsock init crap from the lib to the src/main.c file
in the application instead. They can't be in the lib, especially not for
multithreaded purposes.
Daniel (16 May 2000)
- Rewrote the src/main.c source to use the new easy-interface to libcurl 7.
There is still more work to do, but the first step is now taken.
<curl/easy.h> is the include file to use.
Daniel (14 May 2000) Daniel (14 May 2000)
- FTP URLs are now treated slightly different, more according to RFC 1738. - FTP URLs are now treated slightly different, more according to RFC 1738.
- FTP sessions are now performed differently, with CWD commands to change - FTP sessions are now performed differently, with CWD commands to change

11
FAQ
View File

@ -83,14 +83,3 @@ configre doesn't find OpenSSL even when it is installed
things work things work
Submitted by: Bob Allison <allisonb@users.sourceforge.net> Submitted by: Bob Allison <allisonb@users.sourceforge.net>
Will you write a script for me getting ZZZ from YYY?
====================================================
No.
I try to help out to solve issues with curl and related stuff, but I really
do have a lot of stuff on my daily schedule and I'd prefer if you did not
ask me to do your jobs. Writing scripts is very easy. Using curl might be
tricky, but once you're past the initial mistakes the road to success is
very short and straight-forward.

View File

@ -71,6 +71,9 @@
/* Define if you have the strcasecmp function. */ /* Define if you have the strcasecmp function. */
/*#define HAVE_STRCASECMP 1*/ /*#define HAVE_STRCASECMP 1*/
/* Define if you have the stricmp function. */
#define HAVE_STRICMP 1
/* Define if you have the strdup function. */ /* Define if you have the strdup function. */
#define HAVE_STRDUP 1 #define HAVE_STRDUP 1

View File

@ -82,12 +82,18 @@
/* Define if you have the strcasecmp function. */ /* Define if you have the strcasecmp function. */
#undef HAVE_STRCASECMP #undef HAVE_STRCASECMP
/* Define if you have the strcmpi function. */
#undef HAVE_STRCMPI
/* Define if you have the strdup function. */ /* Define if you have the strdup function. */
#undef HAVE_STRDUP #undef HAVE_STRDUP
/* Define if you have the strftime function. */ /* Define if you have the strftime function. */
#undef HAVE_STRFTIME #undef HAVE_STRFTIME
/* Define if you have the stricmp function. */
#undef HAVE_STRICMP
/* Define if you have the strstr function. */ /* Define if you have the strstr function. */
#undef HAVE_STRSTR #undef HAVE_STRSTR

View File

@ -2,13 +2,7 @@ dnl $Id$
dnl Process this file with autoconf to produce a configure script. dnl Process this file with autoconf to produce a configure script.
AC_INIT(lib/urldata.h) AC_INIT(lib/urldata.h)
AM_CONFIG_HEADER(config.h src/config.h) AM_CONFIG_HEADER(config.h src/config.h)
AM_INIT_AUTOMAKE(curl,"3-test") AM_INIT_AUTOMAKE(curl,"7.0beta")
dnl
dnl Detect the canonical host and target build environment
dnl
AC_CANONICAL_HOST
AC_CANONICAL_TARGET
dnl Checks for programs. dnl Checks for programs.
AC_PROG_CC AC_PROG_CC
@ -26,27 +20,6 @@ dnl **********************************************************************
dnl nsl lib? dnl nsl lib?
AC_CHECK_FUNC(gethostbyname, , AC_CHECK_LIB(nsl, gethostbyname)) AC_CHECK_FUNC(gethostbyname, , AC_CHECK_LIB(nsl, gethostbyname))
dnl At least one system has been identified to require BOTH nsl and
dnl socket libs to link properly.
if test "$ac_cv_lib_nsl_gethostbyname" = "$ac_cv_func_gethostbyname"; then
AC_MSG_CHECKING([trying both nsl and socket libs])
my_ac_save_LIBS=$LIBS
LIBS="-lnsl -lsocket $LIBS"
AC_TRY_LINK( ,
[gethostbyname();],
my_ac_link_result=success,
my_ac_link_result=failure )
if test "$my_ac_link_result" = "failure"; then
AC_MSG_RESULT([no])
AC_MSG_ERROR([couldn't find libraries for gethostbyname()])
dnl restore LIBS
LIBS=$my_ac_save_LIBS
else
AC_MSG_RESULT([yes])
fi
fi
dnl resolve lib? dnl resolve lib?
AC_CHECK_FUNC(strcasecmp, , AC_CHECK_LIB(resolve, strcasecmp)) AC_CHECK_FUNC(strcasecmp, , AC_CHECK_LIB(resolve, strcasecmp))
@ -219,14 +192,13 @@ AC_CHECK_FUNCS( socket \
RAND_screen RAND_screen
) )
AC_PATH_PROG( PERL, perl, , AC_PATH_PROG( PERL, perl, ,
$PATH:/usr/local/bin/perl:/usr/bin/:/usr/local/bin ) $PATH:/usr/local/bin/perl:/usr/bin/:/usr/local/bin )
AC_SUBST(PERL) AC_SUBST(PERL)
AC_PATH_PROGS( NROFF, gnroff nroff, , AC_PATH_PROGS( NROFF, gnroff nroff, ,
$PATH:/usr/bin/:/usr/local/bin ) $PATH:/usr/bin/:/usr/local/bin )
AC_SUBST(NROFF)
AC_PROG_RANLIB AC_PROG_RANLIB
AC_PROG_YACC AC_PROG_YACC
@ -236,8 +208,6 @@ dnl $PATH:/usr/bin/:/usr/local/bin )
dnl AC_SUBST(RANLIB) dnl AC_SUBST(RANLIB)
AC_OUTPUT( Makefile \ AC_OUTPUT( Makefile \
curl.spec \
curl-ssl.spec \
src/Makefile \ src/Makefile \
lib/Makefile ) lib/Makefile )
dnl perl/checklinks.pl \ dnl perl/checklinks.pl \

2
curl.1
View File

@ -204,7 +204,7 @@ A quick and very simple example of how to setup a
to allow curl to ftp to the machine host.domain.com with user name to allow curl to ftp to the machine host.domain.com with user name
'myself' and password 'secret' should look similar to: 'myself' and password 'secret' should look similar to:
.B "machine host.domain.com user myself password secret" .B "machine host.domain.com login myself password secret"
.IP "-N/--no-buffer" .IP "-N/--no-buffer"
Disables the buffering of the output stream. In normal work situations, curl Disables the buffering of the output stream. In normal work situations, curl
will use a standard buffered output stream that will have the effect that it will use a standard buffered output stream that will have the effect that it

View File

@ -1,5 +1,5 @@
#ifndef __CURL_H #ifndef __CURL_CURL_H
#define __CURL_H #define __CURL_CURL_H
/***************************************************************************** /*****************************************************************************
* _ _ ____ _ * _ _ ____ _
* Project ___| | | | _ \| | * Project ___| | | | _ \| |
@ -39,6 +39,25 @@
* *
* ------------------------------------------------------------ * ------------------------------------------------------------
****************************************************************************/ ****************************************************************************/
/* The include stuff here is mainly for time_t! */
#ifdef vms
# include <types.h>
# include <time.h>
#else
# include <sys/types.h>
# if TIME_WITH_SYS_TIME
# include <sys/time.h>
# include <time.h>
# else
# if HAVE_SYS_TIME_H
# include <sys/time.h>
# else
# include <time.h>
# endif
# endif
#endif /* defined (vms) */
#ifndef TRUE #ifndef TRUE
#define TRUE 1 #define TRUE 1
#endif #endif
@ -46,71 +65,8 @@
#define FALSE 0 #define FALSE 0
#endif #endif
#include <curl/types.h>
#define CONF_DEFAULT 0
#define CONF_PROXY (1<<0) /* set if proxy is in use */
#define CONF_PORT (1<<1) /* set if different port than protcol-defines is
used */
#define CONF_HTTP (1<<2) /* http get */
#define CONF_GOPHER (1<<3) /* gopher get */
#define CONF_FTP (1<<4) /* ftp get (binary mode) */
#define CONF_VERBOSE (1<<5) /* talk a lot */
#define CONF_TELNET (1<<6)
#define CONF_HEADER (1<<8) /* throw the header out too */
#define CONF_USERPWD (1<<9) /* user+passwd has been specified */
#define CONF_NOPROGRESS (1<<10) /* shut off the progress meter (auto)
see also _MUTE */
#define CONF_NOBODY (1<<11) /* use HEAD to get http document */
#define CONF_FAILONERROR (1<<12) /* Makes urlget() fail with a return code
WITHOUT writing anything to the output if
a return code >=300 is returned from the
server. */
#define CONF_RANGE (1<<13) /* Byte-range request, specified parameter is set */
#define CONF_UPLOAD (1<<14) /* this is an upload, only supported for ftp
currently */
#define CONF_POST (1<<15) /* HTTP POST method */
/* When getting an FTP directory, this switch makes the listing only show file
names and nothing else. Makes machine parsing of the output possible. This
enforces the NLST command to the ftp server, compared to the otherwise
used: LIST. */
#define CONF_FTPLISTONLY (1<<16)
/* Set the referer string */
#define CONF_REFERER (1<<17)
#define CONF_PROXYUSERPWD (1<<18) /* Proxy user+passwd has been specified */
/* For FTP, use PORT instead of PASV! */
#define CONF_FTPPORT (1<<19)
/* FTP: Append instead of overwrite on upload! */
#define CONF_FTPAPPEND (1<<20)
#define CONF_HTTPS (1<<21) /* Use SSLeay for encrypted communication */
#define CONF_NETRC (1<<22) /* read user+password from .netrc */
#define CONF_FOLLOWLOCATION (1<<23) /* get the page that the Location: tells
us to get */
#define CONF_FTPASCII (1<<24) /* use TYPE A for transfer */
#define CONF_HTTPPOST (1<<25) /* this causes a multipart/form-data
HTTP POST */
#define CONF_NOPROT (1<<26) /* host name specified without protocol */
#define CONF_PUT (1<<27) /* PUT the input file */
#define CONF_MUTE (1<<28) /* force NOPROGRESS */
#define CONF_DICT (1<<29) /* DICT:// protocol */
#define CONF_FILE (1<<30) /* FILE:// protocol */
#define CONF_LDAP (1<<31) /* LDAP:// protocol */
struct HttpHeader { struct HttpHeader {
struct HttpHeader *next; /* next entry in the list */ struct HttpHeader *next; /* next entry in the list */
@ -132,68 +88,69 @@ struct HttpPost {
may return other values, stay prepared. */ may return other values, stay prepared. */
typedef enum { typedef enum {
URG_OK = 0, CURLE_OK = 0,
URG_UNSUPPORTED_PROTOCOL, CURLE_UNSUPPORTED_PROTOCOL,
URG_FAILED_INIT, CURLE_FAILED_INIT,
URG_URL_MALFORMAT, CURLE_URL_MALFORMAT,
URG_URL_MALFORMAT_USER, CURLE_URL_MALFORMAT_USER,
URG_COULDNT_RESOLVE_PROXY, CURLE_COULDNT_RESOLVE_PROXY,
URG_COULDNT_RESOLVE_HOST, CURLE_COULDNT_RESOLVE_HOST,
URG_COULDNT_CONNECT, CURLE_COULDNT_CONNECT,
URG_FTP_WEIRD_SERVER_REPLY, CURLE_FTP_WEIRD_SERVER_REPLY,
URG_FTP_ACCESS_DENIED, CURLE_FTP_ACCESS_DENIED,
URG_FTP_USER_PASSWORD_INCORRECT, CURLE_FTP_USER_PASSWORD_INCORRECT,
URG_FTP_WEIRD_PASS_REPLY, CURLE_FTP_WEIRD_PASS_REPLY,
URG_FTP_WEIRD_USER_REPLY, CURLE_FTP_WEIRD_USER_REPLY,
URG_FTP_WEIRD_PASV_REPLY, CURLE_FTP_WEIRD_PASV_REPLY,
URG_FTP_WEIRD_227_FORMAT, CURLE_FTP_WEIRD_227_FORMAT,
URG_FTP_CANT_GET_HOST, CURLE_FTP_CANT_GET_HOST,
URG_FTP_CANT_RECONNECT, CURLE_FTP_CANT_RECONNECT,
URG_FTP_COULDNT_SET_BINARY, CURLE_FTP_COULDNT_SET_BINARY,
URG_PARTIAL_FILE, CURLE_PARTIAL_FILE,
URG_FTP_COULDNT_RETR_FILE, CURLE_FTP_COULDNT_RETR_FILE,
URG_FTP_WRITE_ERROR, CURLE_FTP_WRITE_ERROR,
URG_FTP_QUOTE_ERROR, CURLE_FTP_QUOTE_ERROR,
URG_HTTP_NOT_FOUND, CURLE_HTTP_NOT_FOUND,
URG_WRITE_ERROR, CURLE_WRITE_ERROR,
URG_MALFORMAT_USER, /* the user name is illegally specified */ CURLE_MALFORMAT_USER, /* the user name is illegally specified */
URG_FTP_COULDNT_STOR_FILE, /* failed FTP upload */ CURLE_FTP_COULDNT_STOR_FILE, /* failed FTP upload */
URG_READ_ERROR, /* could open/read from file */ CURLE_READ_ERROR, /* could open/read from file */
URG_OUT_OF_MEMORY, CURLE_OUT_OF_MEMORY,
URG_OPERATION_TIMEOUTED, /* the timeout time was reached */ CURLE_OPERATION_TIMEOUTED, /* the timeout time was reached */
URG_FTP_COULDNT_SET_ASCII, /* TYPE A failed */ CURLE_FTP_COULDNT_SET_ASCII, /* TYPE A failed */
URG_FTP_PORT_FAILED, /* FTP PORT operation failed */ CURLE_FTP_PORT_FAILED, /* FTP PORT operation failed */
URG_FTP_COULDNT_USE_REST, /* the REST command failed */ CURLE_FTP_COULDNT_USE_REST, /* the REST command failed */
URG_FTP_COULDNT_GET_SIZE, /* the SIZE command failed */ CURLE_FTP_COULDNT_GET_SIZE, /* the SIZE command failed */
URG_HTTP_RANGE_ERROR, /* The RANGE "command" didn't seem to work */ CURLE_HTTP_RANGE_ERROR, /* The RANGE "command" didn't seem to work */
URG_HTTP_POST_ERROR, CURLE_HTTP_POST_ERROR,
URG_SSL_CONNECT_ERROR, /* something was wrong when connecting with SSL */ CURLE_SSL_CONNECT_ERROR, /* something was wrong when connecting with SSL */
URG_FTP_BAD_DOWNLOAD_RESUME, /* couldn't resume download */ CURLE_FTP_BAD_DOWNLOAD_RESUME, /* couldn't resume download */
URG_FILE_COULDNT_READ_FILE, CURLE_FILE_COULDNT_READ_FILE,
URG_LDAP_CANNOT_BIND, CURLE_LDAP_CANNOT_BIND,
URG_LDAP_SEARCH_FAILED, CURLE_LDAP_SEARCH_FAILED,
URG_LIBRARY_NOT_FOUND, CURLE_LIBRARY_NOT_FOUND,
URG_FUNCTION_NOT_FOUND, CURLE_FUNCTION_NOT_FOUND,
CURLE_ABORTED_BY_CALLBACK,
URL_LAST CURLE_BAD_FUNCTION_ARGUMENT,
} UrgError; CURLE_BAD_CALLING_ORDER,
CURL_LAST
} CURLcode;
/* This is just to make older programs not break: */ /* This is just to make older programs not break: */
#define URG_FTP_PARTIAL_FILE URG_PARTIAL_FILE #define CURLE_FTP_PARTIAL_FILE CURLE_PARTIAL_FILE
#define URGTAG_DONE -1
#define URGTAG_LAST -1
#define URGTAG_END -1
#define URLGET_ERROR_SIZE 256 #define URLGET_ERROR_SIZE 256
@ -201,19 +158,19 @@ typedef enum {
#define URL_MAX_LENGTH 4096 #define URL_MAX_LENGTH 4096
#define URL_MAX_LENGTH_TXT "4095" #define URL_MAX_LENGTH_TXT "4095"
/* name is uppercase URGTAG_<name>, /* name is uppercase CURLOPT_<name>,
type is one of the defined URGTYPE_<type> type is one of the defined CURLOPTTYPE_<type>
number is unique identifier */ number is unique identifier */
#define T(name,type,number) URGTAG_ ## name = URGTYPE_ ## type + number #define T(name,type,number) CURLOPT_ ## name = CURLOPTTYPE_ ## type + number
/* long may be 32 or 64 bits, but we should never depend on anything else /* long may be 32 or 64 bits, but we should never depend on anything else
but 32 */ but 32 */
#define URGTYPE_LONG 0 #define CURLOPTTYPE_LONG 0
#define URGTYPE_OBJECTPOINT 10000 #define CURLOPTTYPE_OBJECTPOINT 10000
#define URGTYPE_FUNCTIONPOINT 20000 #define CURLOPTTYPE_FUNCTIONPOINT 20000
typedef enum { typedef enum {
URGTAG_NOTHING, /* the first unused */ T(NOTHING, LONG, 0), /********* the first one is unused ************/
/* This is the FILE * the regular output should be written to. */ /* This is the FILE * the regular output should be written to. */
T(FILE, OBJECTPOINT, 1), T(FILE, OBJECTPOINT, 1),
@ -222,28 +179,29 @@ typedef enum {
T(URL, OBJECTPOINT, 2), T(URL, OBJECTPOINT, 2),
/* Port number to connect to, if other than default. Specify the CONF_PORT /* Port number to connect to, if other than default. Specify the CONF_PORT
flag in the URGTAG_FLAGS to activate this */ flag in the CURLOPT_FLAGS to activate this */
T(PORT, LONG, 3), T(PORT, LONG, 3),
/* Name of proxy to use. Specify the CONF_PROXY flag in the URGTAG_FLAGS to /* Name of proxy to use. Specify the CONF_PROXY flag in the CURLOPT_FLAGS to
activate this */ activate this */
T(PROXY, OBJECTPOINT, 4), T(PROXY, OBJECTPOINT, 4),
/* Name and password to use when fetching. Specify the CONF_USERPWD flag in /* Name and password to use when fetching. Specify the CONF_USERPWD flag in
the URGTAG_FLAGS to activate this */ the CURLOPT_FLAGS to activate this */
T(USERPWD, OBJECTPOINT, 5), T(USERPWD, OBJECTPOINT, 5),
/* Name and password to use with Proxy. Specify the CONF_PROXYUSERPWD /* Name and password to use with Proxy. Specify the CONF_PROXYUSERPWD
flag in the URGTAG_FLAGS to activate this */ flag in the CURLOPT_FLAGS to activate this */
T(PROXYUSERPWD, OBJECTPOINT, 6), T(PROXYUSERPWD, OBJECTPOINT, 6),
/* Range to get, specified as an ASCII string. Specify the CONF_RANGE flag /* Range to get, specified as an ASCII string. Specify the CONF_RANGE flag
in the URGTAG_FLAGS to activate this */ in the CURLOPT_FLAGS to activate this */
T(RANGE, OBJECTPOINT, 7), T(RANGE, OBJECTPOINT, 7),
#if 0
/* Configuration flags */ /* Configuration flags */
T(FLAGS, LONG, 8), T(FLAGS, LONG, 8),
#endif
/* Specified file stream to upload from (use as input): */ /* Specified file stream to upload from (use as input): */
T(INFILE, OBJECTPOINT, 9), T(INFILE, OBJECTPOINT, 9),
@ -262,7 +220,7 @@ typedef enum {
/* Time-out the read operation after this amount of seconds */ /* Time-out the read operation after this amount of seconds */
T(TIMEOUT, LONG, 13), T(TIMEOUT, LONG, 13),
/* If the URGTAG_INFILE is used, this can be used to inform urlget about how /* If the CURLOPT_INFILE is used, this can be used to inform urlget about how
large the file being sent really is. That allows better error checking large the file being sent really is. That allows better error checking
and better verifies that the upload was succcessful. -1 means unknown and better verifies that the upload was succcessful. -1 means unknown
size. */ size. */
@ -364,8 +322,25 @@ typedef enum {
as described elsewhere. */ as described elsewhere. */
T(WRITEINFO, OBJECTPOINT, 40), T(WRITEINFO, OBJECTPOINT, 40),
URGTAG_LASTENTRY /* the last unusued */ /* Previous FLAG bits */
} UrgTag; T(VERBOSE, LONG, 41), /* talk a lot */
T(HEADER, LONG, 42), /* throw the header out too */
T(NOPROGRESS, LONG, 43), /* shut off the progress meter */
T(NOBODY, LONG, 44), /* use HEAD to get http document */
T(FAILONERROR, LONG, 45), /* no output on http error codes >= 300 */
T(UPLOAD, LONG, 46), /* this is an upload */
T(POST, LONG, 47), /* HTTP POST method */
T(FTPLISTONLY, LONG, 48), /* Use NLST when listing ftp dir */
T(FTPAPPEND, LONG, 50), /* Append instead of overwrite on upload! */
T(NETRC, LONG, 51), /* read user+password from .netrc */
T(FOLLOWLOCATION, LONG, 52), /* use Location: Luke! */
T(FTPASCII, LONG, 53), /* use TYPE A for transfer */
T(PUT, LONG, 54), /* PUT the input file */
T(MUTE, LONG, 55), /* force NOPROGRESS */
CURLOPT_LASTENTRY /* the last unusued */
} CURLoption;
#define CURL_PROGRESS_STATS 0 /* default progress display */ #define CURL_PROGRESS_STATS 0 /* default progress display */
#define CURL_PROGRESS_BAR 1 #define CURL_PROGRESS_BAR 1
@ -388,23 +363,11 @@ typedef char bool;
#endif /* (rabe) */ #endif /* (rabe) */
#endif #endif
/********************************************************************** #if 0
* /* At last, I stand here in front of you today and can officially proclaim
* >>> urlget() interface #defines changed in v5! <<< this function prototype as history... 17th of May, 2000 */
*
* You enter parameters as tags. Tags are specified as a pair of parameters.
* The first parameter in a pair is the tag identifier, telling urlget what
* kind of tag it is, and the second is the data. The tags may come in any
* order but MUST ALWAYS BE TERMINATED with an ending URGTAG_DONE (which
* needs no data).
*
* _Very_ simple example:
*
* curl_urlget(URGTAG_URL, "http://www.fts.frontec.se/~dast/", URGTAG_DONE);
*
***********************************************************************/
UrgError curl_urlget(UrgTag, ...); UrgError curl_urlget(UrgTag, ...);
#endif
/* external form function */ /* external form function */
int curl_FormParse(char *string, int curl_FormParse(char *string,
@ -418,9 +381,10 @@ char *curl_GetEnv(char *variable);
char *curl_version(void); char *curl_version(void);
/* This is the version number */ /* This is the version number */
#define LIBCURL_VERSION "6.5.2" #define LIBCURL_VERSION "7.0beta"
#define LIBCURL_VERSION_NUM 0x070000
/* linked-list structure for QUOTE */ /* linked-list structure for the CURLOPT_QUOTE option */
struct curl_slist { struct curl_slist {
char *data; char *data;
struct curl_slist *next; struct curl_slist *next;
@ -429,4 +393,192 @@ struct curl_slist {
struct curl_slist *curl_slist_append(struct curl_slist *list, char *data); struct curl_slist *curl_slist_append(struct curl_slist *list, char *data);
void curl_slist_free_all(struct curl_slist *list); void curl_slist_free_all(struct curl_slist *list);
#endif /* __URLGET_H */ /*
* NAME curl_init()
*
* DESCRIPTION
*
* Inits libcurl globally. This must be used before any libcurl calls can
* be used. This may install global plug-ins or whatever. (This does not
* do winsock inits in Windows.)
*
* EXAMPLE
*
* curl_init();
*
*/
CURLcode curl_init(void);
/*
* NAME curl_init()
*
* DESCRIPTION
*
* Frees libcurl globally. This must be used after all libcurl calls have
* been used. This may remove global plug-ins or whatever. (This does not
* do winsock cleanups in Windows.)
*
* EXAMPLE
*
* curl_free(curl);
*
*/
void curl_free(void);
/*
* NAME curl_open()
*
* DESCRIPTION
*
* Opens a general curl session. It does not try to connect or do anything
* on the network because of this call. The specified URL is only required
* to enable curl to figure out what protocol to "activate".
*
* A session should be looked upon as a series of requests to a single host. A
* session interacts with one host only, using one single protocol.
*
* The URL is not required. If set to "" or NULL, it can still be set later
* using the curl_setopt() function. If the curl_connect() function is called
* without the URL being known, it will return error.
*
* EXAMPLE
*
* CURLcode result;
* CURL *curl;
* result = curl_open(&curl, "http://curl.haxx.nu/libcurl/");
* if(result != CURL_OK) {
* return result;
* }
* */
CURLcode curl_open(CURL **curl, char *url);
/*
* NAME curl_setopt()
*
* DESCRIPTION
*
* Sets a particular option to the specified value.
*
* EXAMPLE
*
* CURL curl;
* curl_setopt(curl, CURL_HTTP_FOLLOW_LOCATION, TRUE);
*/
CURLcode curl_setopt(CURL *handle, CURLoption option, ...);
/*
* NAME curl_close()
*
* DESCRIPTION
*
* Closes a session previously opened with curl_open()
*
* EXAMPLE
*
* CURL *curl;
* CURLcode result;
*
* result = curl_close(curl);
*/
CURLcode curl_close(CURL *curl); /* the opposite of curl_open() */
CURLcode curl_read(CURLconnect *c_conn, char *buf, size_t buffersize,
size_t *n);
CURLcode curl_write(CURLconnect *c_conn, char *buf, size_t amount,
size_t *n);
/*
* NAME curl_connect()
*
* DESCRIPTION
*
* Connects to the peer server and performs the initial setup. This function
* writes a connect handle to its second argument that is a unique handle for
* this connect. This allows multiple connects from the same handle returned
* by curl_open().
*
* EXAMPLE
*
* CURLCode result;
* CURL curl;
* CURLconnect connect;
* result = curl_connect(curl, &connect);
*/
CURLcode curl_connect(CURL *curl, CURLconnect **in_connect);
/*
* NAME curl_do()
*
* DESCRIPTION
*
* (Note: May 3rd 2000: this function does not currently allow you to
* specify a document, it will use the one set previously)
*
* This function asks for the particular document, file or resource that
* resides on the server we have connected to. You may specify a full URL,
* just an absolute path or even a relative path. That means, if you're just
* getting one file from the remote site, you can use the same URL as input
* for both curl_open() as well as for this function.
*
* In the even there is a host name, port number, user name or password parts
* in the URL, you can use the 'flags' argument to ignore them completely, or
* at your choice, make the function fail if you're trying to get a URL from
* different host than you connected to with curl_connect().
*
* You can only get one document at a time using the same connection. When one
* document has been received you can although request again.
*
* When the transfer is done, curl_done() MUST be called.
*
* EXAMPLE
*
* CURLCode result;
* char *url;
* CURLconnect *connect;
* result = curl_do(connect, url, CURL_DO_NONE); */
CURLcode curl_do(CURLconnect *in_conn);
/*
* NAME curl_done()
*
* DESCRIPTION
*
* When the transfer following a curl_do() call is done, this function should
* get called.
*
* EXAMPLE
*
* CURLCode result;
* char *url;
* CURLconnect *connect;
* result = curl_done(connect); */
CURLcode curl_done(CURLconnect *connect);
/*
* NAME curl_disconnect()
*
* DESCRIPTION
*
* Disconnects from the peer server and performs connection cleanup.
*
* EXAMPLE
*
* CURLcode result;
* CURLconnect *connect;
* result = curl_disconnect(connect); */
CURLcode curl_disconnect(CURLconnect *connect);
/*
* NAME curl_getdate()
*
* DESCRIPTION
*
* Returns the time, in seconds since 1 Jan 1970 of the time string given in
* the first argument. The time argument in the second parameter is for cases
* where the specified time is relative now, like 'two weeks' or 'tomorrow'
* etc.
*/
time_t curl_getdate(const char *p, const time_t *now);
#endif /* __CURL_CURL_H */

46
include/curl/easy.h Normal file
View File

@ -0,0 +1,46 @@
#ifndef __CURL_EASY_H
#define __CURL_EASY_H
/*****************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
* License for the specific language governing rights and limitations
* under the License.
*
* The Original Code is Curl.
*
* The Initial Developer of the Original Code is Daniel Stenberg.
*
* Portions created by the Initial Developer are Copyright (C) 1998.
* All Rights Reserved.
*
* ------------------------------------------------------------
* Main author:
* - Daniel Stenberg <Daniel.Stenberg@haxx.nu>
*
* http://curl.haxx.nu
*
* $Source$
* $Revision$
* $Date$
* $Author$
* $State$
* $Locker$
*
* ------------------------------------------------------------
****************************************************************************/
CURL *curl_easy_init(void);
CURLcode curl_easy_setopt(CURL *curl, CURLoption option, ...);
CURLcode curl_easy_perform(CURL *curl);
void curl_easy_cleanup(CURL *curl);
#endif

45
include/curl/types.h Normal file
View File

@ -0,0 +1,45 @@
#ifndef __CURL_TYPES_H
#define __CURL_TYPES_H
/*****************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
* License for the specific language governing rights and limitations
* under the License.
*
* The Original Code is Curl.
*
* The Initial Developer of the Original Code is Daniel Stenberg.
*
* Portions created by the Initial Developer are Copyright (C) 1998.
* All Rights Reserved.
*
* ------------------------------------------------------------
* Main author:
* - Daniel Stenberg <Daniel.Stenberg@haxx.nu>
*
* http://curl.haxx.nu
*
* $Source$
* $Revision$
* $Date$
* $Author$
* $State$
* $Locker$
*
* ------------------------------------------------------------
****************************************************************************/
typedef void CURL;
typedef void CURLconnect;
#endif /* __CURL_TYPES_H */

View File

@ -7,7 +7,7 @@ AUTOMAKE_OPTIONS = foreign no-dependencies
noinst_LIBRARIES = libcurl.a noinst_LIBRARIES = libcurl.a
# Some flags needed when trying to cause warnings ;-) # Some flags needed when trying to cause warnings ;-)
#CFLAGS = -g -Wall -pedantic CFLAGS = -g -Wall #-pedantic
INCLUDES = -I$(top_srcdir)/include INCLUDES = -I$(top_srcdir)/include
@ -23,7 +23,7 @@ download.c getdate.h ldap.c ssluse.c version.c \
download.h getenv.c ldap.h ssluse.h \ download.h getenv.c ldap.h ssluse.h \
escape.c getenv.h mprintf.c telnet.c \ escape.c getenv.h mprintf.c telnet.c \
escape.h getpass.c netrc.c telnet.h \ escape.h getpass.c netrc.c telnet.h \
writeout.c writeout.h writeout.c writeout.h highlevel.c strequal.c strequal.h easy.c
# Say $(srcdir), so GNU make does not report an ambiguity with the .y.c rule. # Say $(srcdir), so GNU make does not report an ambiguity with the .y.c rule.
$(srcdir)/getdate.c: getdate.y $(srcdir)/getdate.c: getdate.y

View File

@ -77,11 +77,11 @@ AUTOMAKE_OPTIONS = foreign no-dependencies
noinst_LIBRARIES = libcurl.a noinst_LIBRARIES = libcurl.a
# Some flags needed when trying to cause warnings ;-) # Some flags needed when trying to cause warnings ;-)
#CFLAGS = -g -Wall -pedantic CFLAGS = -g -Wall #-pedantic
INCLUDES = -I$(top_srcdir)/include INCLUDES = -I$(top_srcdir)/include
libcurl_a_SOURCES = arpa_telnet.h file.c getpass.h netrc.h timeval.c base64.c file.h hostip.c progress.c timeval.h base64.h formdata.c hostip.h progress.h cookie.c formdata.h http.c sendf.c cookie.h ftp.c http.h sendf.h url.c dict.c ftp.h if2ip.c speedcheck.c url.h dict.h getdate.c if2ip.h speedcheck.h urldata.h download.c getdate.h ldap.c ssluse.c version.c download.h getenv.c ldap.h ssluse.h escape.c getenv.h mprintf.c telnet.c escape.h getpass.c netrc.c telnet.h writeout.c writeout.h libcurl_a_SOURCES = arpa_telnet.h file.c getpass.h netrc.h timeval.c base64.c file.h hostip.c progress.c timeval.h base64.h formdata.c hostip.h progress.h cookie.c formdata.h http.c sendf.c cookie.h ftp.c http.h sendf.h url.c dict.c ftp.h if2ip.c speedcheck.c url.h dict.h getdate.c if2ip.h speedcheck.h urldata.h download.c getdate.h ldap.c ssluse.c version.c download.h getenv.c ldap.h ssluse.h escape.c getenv.h mprintf.c telnet.c escape.h getpass.c netrc.c telnet.h writeout.c writeout.h highlevel.c strequal.c strequal.h easy.c
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
CONFIG_HEADER = ../config.h ../src/config.h CONFIG_HEADER = ../config.h ../src/config.h
@ -97,9 +97,9 @@ libcurl_a_LIBADD =
libcurl_a_OBJECTS = file.o timeval.o base64.o hostip.o progress.o \ libcurl_a_OBJECTS = file.o timeval.o base64.o hostip.o progress.o \
formdata.o cookie.o http.o sendf.o ftp.o url.o dict.o if2ip.o \ formdata.o cookie.o http.o sendf.o ftp.o url.o dict.o if2ip.o \
speedcheck.o getdate.o download.o ldap.o ssluse.o version.o getenv.o \ speedcheck.o getdate.o download.o ldap.o ssluse.o version.o getenv.o \
escape.o mprintf.o telnet.o getpass.o netrc.o writeout.o escape.o mprintf.o telnet.o getpass.o netrc.o writeout.o highlevel.o \
strequal.o easy.o
AR = ar AR = ar
CFLAGS = @CFLAGS@
COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
CCLD = $(CC) CCLD = $(CC)
LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@

View File

@ -62,6 +62,7 @@ Example set of cookies:
#include "cookie.h" #include "cookie.h"
#include "setup.h" #include "setup.h"
#include "getdate.h" #include "getdate.h"
#include "strequal.h"
/**************************************************************************** /****************************************************************************
* *
@ -131,7 +132,7 @@ struct Cookie *cookie_add(struct CookieInfo *c,
} }
else if(strequal("expires", name)) { else if(strequal("expires", name)) {
co->expirestr=strdup(what); co->expirestr=strdup(what);
co->expires = get_date(what, &now); co->expires = curl_getdate(what, &now);
} }
else if(!co->name) { else if(!co->name) {
co->name = strdup(name); co->name = strdup(name);
@ -173,9 +174,11 @@ struct Cookie *cookie_add(struct CookieInfo *c,
return NULL; return NULL;
} }
/* strip off the possible end-of-line characters */ /* strip off the possible end-of-line characters */
if(ptr=strchr(lineptr, '\r')) ptr=strchr(lineptr, '\r');
if(ptr)
*ptr=0; /* clear it */ *ptr=0; /* clear it */
if(ptr=strchr(lineptr, '\n')) ptr=strchr(lineptr, '\n');
if(ptr)
*ptr=0; /* clear it */ *ptr=0; /* clear it */
firstptr=strtok(lineptr, "\t"); /* first tokenize it on the TAB */ firstptr=strtok(lineptr, "\t"); /* first tokenize it on the TAB */

View File

@ -92,12 +92,17 @@
#include "sendf.h" #include "sendf.h"
#include "progress.h" #include "progress.h"
#include "strequal.h"
#define _MPRINTF_REPLACE /* use our functions only */ #define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h> #include <curl/mprintf.h>
CURLcode dict_done(struct connectdata *conn)
{
return CURLE_OK;
}
UrgError dict(struct UrlData *data, char *path, long *bytecount) CURLcode dict(struct connectdata *conn)
{ {
int nth; int nth;
char *word; char *word;
@ -106,9 +111,13 @@ UrgError dict(struct UrlData *data, char *path, long *bytecount)
char *strategy = NULL; char *strategy = NULL;
char *nthdef = NULL; /* This is not part of the protocol, but required char *nthdef = NULL; /* This is not part of the protocol, but required
by RFC 2229 */ by RFC 2229 */
UrgError result=URG_OK; CURLcode result=CURLE_OK;
struct UrlData *data=conn->data;
if(data->conf & CONF_USERPWD) {
char *path = conn->path;
long *bytecount = &conn->bytecount;
if(data->bits.user_passwd) {
/* AUTH is missing */ /* AUTH is missing */
} }
@ -162,7 +171,7 @@ UrgError dict(struct UrlData *data, char *path, long *bytecount)
word word
); );
result = Transfer(data, data->firstsocket, -1, FALSE, bytecount, result = Transfer(conn, data->firstsocket, -1, FALSE, bytecount,
-1, NULL); /* no upload */ -1, NULL); /* no upload */
if(result) if(result)
@ -210,7 +219,7 @@ UrgError dict(struct UrlData *data, char *path, long *bytecount)
word word
); );
result = Transfer(data, data->firstsocket, -1, FALSE, bytecount, result = Transfer(conn, data->firstsocket, -1, FALSE, bytecount,
-1, NULL); /* no upload */ -1, NULL); /* no upload */
if(result) if(result)
@ -234,7 +243,7 @@ UrgError dict(struct UrlData *data, char *path, long *bytecount)
"QUIT\n", "QUIT\n",
ppath); ppath);
result = Transfer(data, data->firstsocket, -1, FALSE, bytecount, result = Transfer(conn, data->firstsocket, -1, FALSE, bytecount,
-1, NULL); -1, NULL);
if(result) if(result)
@ -243,10 +252,5 @@ UrgError dict(struct UrlData *data, char *path, long *bytecount)
} }
} }
#if 0 return CURLE_OK;
ProgressEnd(data);
#endif
pgrsDone(data);
return URG_OK;
} }

View File

@ -40,6 +40,7 @@
* *
* ------------------------------------------------------------ * ------------------------------------------------------------
****************************************************************************/ ****************************************************************************/
UrgError dict(struct UrlData *data, char *path, long *bytecountp); CURLcode dict(struct connectdata *conn);
CURLcode dict_done(struct connectdata *conn);
#endif #endif

View File

@ -78,20 +78,16 @@
#include "speedcheck.h" #include "speedcheck.h"
#include "sendf.h" #include "sendf.h"
#ifdef USE_ZLIB #include <curl/types.h>
#include <zlib.h>
#endif
#define MAX(x,y) ((x)>(y)?(x):(y))
/* --- download and upload a stream from/to a socket --- */ /* --- download and upload a stream from/to a socket --- */
/* Parts of this function was brought to us by the friendly Mark Butler /* Parts of this function was brought to us by the friendly Mark Butler
<butlerm@xmission.com>. */ <butlerm@xmission.com>. */
UrgError CURLcode
Transfer (struct UrlData *data, Transfer(CURLconnect *c_conn,
/* READ stuff */ /* READ stuff */
int sockfd, /* socket to read from or -1 */ int sockfd, /* socket to read from or -1 */
int size, /* -1 if unknown at this point */ int size, /* -1 if unknown at this point */
bool getheader, /* TRUE if header parsing is wanted */ bool getheader, /* TRUE if header parsing is wanted */
@ -101,492 +97,21 @@ Transfer (struct UrlData *data,
int writesockfd, /* socket to write to, it may very well be int writesockfd, /* socket to write to, it may very well be
the same we read from. -1 disables */ the same we read from. -1 disables */
long *writebytecountp /* return number of bytes written or NULL */ long *writebytecountp /* return number of bytes written or NULL */
)
)
{ {
char *buf = data->buffer; struct connectdata *conn = (struct connectdata *)c_conn;
size_t nread; if(!conn)
int bytecount = 0; /* number of bytes read */ return CURLE_BAD_FUNCTION_ARGUMENT;
int writebytecount = 0; /* number of bytes written */
long contentlength=0; /* size of incoming data */
struct timeval start = tvnow();
struct timeval now = start;
bool header = TRUE; /* incoming data has HTTP header */
int headerline = 0; /* counts header lines to better track the
first one */
char *hbufp; /* points at *end* of header line */ /* now copy all input parameters */
int hbuflen = 0; conn->sockfd = sockfd;
char *str; /* within buf */ conn->size = size;
char *str_start; /* within buf */ conn->getheader = getheader;
char *end_ptr; /* within buf */ conn->bytecountp = bytecountp;
char *p; /* within headerbuff */ conn->writesockfd = writesockfd;
bool content_range = FALSE; /* set TRUE if Content-Range: was found */ conn->writebytecountp = writebytecountp;
int offset = 0; /* possible resume offset read from the
Content-Range: header */
int code = 0; /* error code from the 'HTTP/1.? XXX' line */
/* for the low speed checks: */ return CURLE_OK;
UrgError urg;
time_t timeofdoc=0;
long bodywrites=0;
char newurl[URL_MAX_LENGTH]; /* buffer for Location: URL */
/* the highest fd we use + 1 */
int maxfd = (sockfd>writesockfd?sockfd:writesockfd)+1;
hbufp = data->headerbuff;
myalarm (0); /* switch off the alarm-style timeout */
now = tvnow();
start = now;
#define KEEP_READ 1
#define KEEP_WRITE 2
pgrsTime(data, TIMER_PRETRANSFER);
if (!getheader) {
header = FALSE;
if(size > 0)
pgrsSetDownloadSize(data, size);
}
{
fd_set readfd;
fd_set writefd;
fd_set rkeepfd;
fd_set wkeepfd;
struct timeval interval;
int keepon=0;
/* timeout every X second
- makes a better progressmeter (i.e even when no data is read, the
meter can be updated and reflect reality)
- allows removal of the alarm() crap
- variable timeout is easier
*/
FD_ZERO (&readfd); /* clear it */
if(sockfd != -1) {
FD_SET (sockfd, &readfd); /* read socket */
keepon |= KEEP_READ;
}
FD_ZERO (&writefd); /* clear it */
if(writesockfd != -1) {
FD_SET (writesockfd, &writefd); /* write socket */
keepon |= KEEP_WRITE;
}
/* get these in backup variables to be able to restore them on each lap in
the select() loop */
rkeepfd = readfd;
wkeepfd = writefd;
while (keepon) {
readfd = rkeepfd; /* set those every lap in the loop */
writefd = wkeepfd;
interval.tv_sec = 1;
interval.tv_usec = 0;
switch (select (maxfd, &readfd, &writefd, NULL, &interval)) {
case -1: /* select() error, stop reading */
#ifdef EINTR
/* The EINTR is not serious, and it seems you might get this more
ofen when using the lib in a multi-threaded environment! */
if(errno == EINTR)
;
else
#endif
keepon = 0; /* no more read or write */
continue;
case 0: /* timeout */
break;
default:
if((keepon & KEEP_READ) && FD_ISSET(sockfd, &readfd)) {
/* read! */
#ifdef USE_SSLEAY
if (data->use_ssl) {
nread = SSL_read (data->ssl, buf, BUFSIZE - 1);
}
else {
#endif
nread = sread (sockfd, buf, BUFSIZE - 1);
#ifdef USE_SSLEAY
}
#endif /* USE_SSLEAY */
/* NULL terminate, allowing string ops to be used */
if (0 < (signed int) nread)
buf[nread] = 0;
/* if we receive 0 or less here, the server closed the connection and
we bail out from this! */
else if (0 >= (signed int) nread) {
keepon &= ~KEEP_READ;
break;
}
str = buf; /* Default buffer to use when we write the
buffer, it may be changed in the flow below
before the actual storing is done. */
/* Since this is a two-state thing, we check if we are parsing
headers at the moment or not. */
if (header) {
/* we are in parse-the-header-mode */
/* header line within buffer loop */
do {
int hbufp_index;
str_start = str; /* str_start is start of line within buf */
end_ptr = strchr (str_start, '\n');
if (!end_ptr) {
/* no more complete header lines within buffer */
/* copy what is remaining into headerbuff */
int str_length = (int)strlen(str);
if (hbuflen + (int)str_length >= data->headersize) {
char *newbuff;
long newsize=MAX((hbuflen+str_length)*3/2,
data->headersize*2);
hbufp_index = hbufp - data->headerbuff;
newbuff = (char *)realloc(data->headerbuff, newsize);
if(!newbuff) {
failf (data, "Failed to alloc memory for big header!");
return URG_READ_ERROR;
}
data->headersize=newsize;
data->headerbuff = newbuff;
hbufp = data->headerbuff + hbufp_index;
}
strcpy (hbufp, str);
hbufp += strlen (str);
hbuflen += strlen (str);
break; /* read more and try again */
}
str = end_ptr + 1; /* move just past new line */
if (hbuflen + (str - str_start) >= data->headersize) {
char *newbuff;
long newsize=MAX((hbuflen+(str-str_start))*3/2,
data->headersize*2);
hbufp_index = hbufp - data->headerbuff;
newbuff = (char *)realloc(data->headerbuff, newsize);
if(!newbuff) {
failf (data, "Failed to alloc memory for big header!");
return URG_READ_ERROR;
}
data->headersize= newsize;
data->headerbuff = newbuff;
hbufp = data->headerbuff + hbufp_index;
}
/* copy to end of line */
strncpy (hbufp, str_start, str - str_start);
hbufp += str - str_start;
hbuflen += str - str_start;
*hbufp = 0;
p = data->headerbuff;
/* we now have a full line that p points to */
if (('\n' == *p) || ('\r' == *p)) {
/* Zero-length line means end of header! */
if (-1 != size) /* if known */
size += bytecount; /* we append the already read size */
if ('\r' == *p)
p++; /* pass the \r byte */
if ('\n' == *p)
p++; /* pass the \n byte */
pgrsSetDownloadSize(data, size);
header = FALSE; /* no more header to parse! */
/* now, only output this if the header AND body are requested:
*/
if ((data->conf & (CONF_HEADER | CONF_NOBODY)) ==
CONF_HEADER) {
if((p - data->headerbuff) !=
data->fwrite (data->headerbuff, 1,
p - data->headerbuff, data->out)) {
failf (data, "Failed writing output");
return URG_WRITE_ERROR;
}
}
if(data->writeheader) {
/* obviously, the header is requested to be written to
this file: */
if((p - data->headerbuff) !=
data->fwrite (data->headerbuff, 1, p - data->headerbuff,
data->writeheader)) {
failf (data, "Failed writing output");
return URG_WRITE_ERROR;
}
}
break; /* exit header line loop */
}
if (!headerline++) {
/* This is the first header, it MUST be the error code line
or else we consiser this to be the body right away! */
if (sscanf (p, " HTTP/1.%*c %3d", &code)) {
/* 404 -> URL not found! */
if (
( ((data->conf & CONF_FOLLOWLOCATION) && (code >= 400))
||
!(data->conf & CONF_FOLLOWLOCATION) && (code >= 300))
&& (data->conf & CONF_FAILONERROR)) {
/* If we have been told to fail hard on HTTP-errors,
here is the check for that: */
/* serious error, go home! */
failf (data, "The requested file was not found");
return URG_HTTP_NOT_FOUND;
}
data->progress.httpcode = code;
}
else {
header = FALSE; /* this is not a header line */
break;
}
}
/* check for Content-Length: header lines to get size */
if (strnequal("Content-Length", p, 14) &&
sscanf (p+14, ": %ld", &contentlength))
size = contentlength;
else if (strnequal("Content-Range", p, 13) &&
sscanf (p+13, ": bytes %d-", &offset)) {
if (data->resume_from == offset) {
/* we asked for a resume and we got it */
content_range = TRUE;
}
}
else if(data->cookies &&
strnequal("Set-Cookie: ", p, 11)) {
cookie_add(data->cookies, TRUE, &p[12]);
}
else if(strnequal("Last-Modified:", p,
strlen("Last-Modified:")) &&
data->timecondition) {
time_t secs=time(NULL);
timeofdoc = get_date(p+strlen("Last-Modified:"), &secs);
}
else if ((code >= 300 && code < 400) &&
(data->conf & CONF_FOLLOWLOCATION) &&
strnequal("Location", p, 8) &&
sscanf (p+8, ": %" URL_MAX_LENGTH_TXT "s", newurl)) {
/* this is the URL that the server advices us to get
instead */
data->newurl = strdup (newurl);
}
if (data->conf & CONF_HEADER) {
if(hbuflen != data->fwrite (p, 1, hbuflen, data->out)) {
failf (data, "Failed writing output");
return URG_WRITE_ERROR;
}
}
if(data->writeheader) {
/* the header is requested to be written to this file */
if(hbuflen != data->fwrite (p, 1, hbuflen,
data->writeheader)) {
failf (data, "Failed writing output");
return URG_WRITE_ERROR;
}
}
/* reset hbufp pointer && hbuflen */
hbufp = data->headerbuff;
hbuflen = 0;
}
while (*str); /* header line within buffer */
/* We might have reached the end of the header part here, but
there might be a non-header part left in the end of the read
buffer. */
if (!header) {
/* the next token and forward is not part of
the header! */
/* we subtract the remaining header size from the buffer */
nread -= (str - buf);
}
} /* end if header mode */
/* This is not an 'else if' since it may be a rest from the header
parsing, where the beginning of the buffer is headers and the end
is non-headers. */
if (str && !header && (nread > 0)) {
if(0 == bodywrites) {
/* These checks are only made the first time we are about to
write a chunk of the body */
if(data->conf&CONF_HTTP) {
/* HTTP-only checks */
if (data->resume_from && !content_range ) {
/* we wanted to resume a download, although the server
doesn't seem to support this */
failf (data, "HTTP server doesn't seem to support byte ranges. Cannot resume.");
return URG_HTTP_RANGE_ERROR;
}
else if (data->newurl) {
/* abort after the headers if "follow Location" is set */
infof (data, "Follow to new URL: %s\n", data->newurl);
return URG_OK;
}
else if(data->timecondition && !data->range) {
/* A time condition has been set AND no ranges have been
requested. This seems to be what chapter 13.3.4 of
RFC 2616 defines to be the correct action for a
HTTP/1.1 client */
if((timeofdoc > 0) && (data->timevalue > 0)) {
switch(data->timecondition) {
case TIMECOND_IFMODSINCE:
default:
if(timeofdoc < data->timevalue) {
infof(data,
"The requested document is not new enough");
return URG_OK;
}
break;
case TIMECOND_IFUNMODSINCE:
if(timeofdoc > data->timevalue) {
infof(data,
"The requested document is not old enough");
return URG_OK;
}
break;
} /* switch */
} /* two valid time strings */
} /* we have a time condition */
} /* this is HTTP */
} /* this is the first time we write a body part */
bodywrites++;
if(data->maxdownload &&
(bytecount + nread > data->maxdownload)) {
nread = data->maxdownload - bytecount;
if(nread < 0 ) /* this should be unusual */
nread = 0;
keepon &= ~KEEP_READ; /* we're done reading */
}
bytecount += nread;
pgrsSetDownloadCounter(data, (double)bytecount);
if (nread != data->fwrite (str, 1, nread, data->out)) {
failf (data, "Failed writing output");
return URG_WRITE_ERROR;
}
} /* if (! header and data to read ) */
} /* if( read from socket ) */
if((keepon & KEEP_WRITE) && FD_ISSET(writesockfd, &writefd)) {
/* write */
char scratch[BUFSIZE * 2];
int i, si;
int bytes_written;
if(data->crlf)
buf = data->buffer; /* put it back on the buffer */
nread = data->fread(buf, 1, BUFSIZE, data->in);
writebytecount += nread;
pgrsSetUploadCounter(data, (double)writebytecount);
if (nread<=0) {
/* done */
keepon &= ~KEEP_WRITE; /* we're done writing */
break;
}
/* convert LF to CRLF if so asked */
if (data->crlf) {
for(i = 0, si = 0; i < (int)nread; i++, si++) {
if (buf[i] == 0x0a) {
scratch[si++] = 0x0d;
scratch[si] = 0x0a;
}
else {
scratch[si] = buf[i];
}
}
nread = si;
buf = scratch; /* point to the new buffer */
}
/* write to socket */
#ifdef USE_SSLEAY
if (data->use_ssl) {
bytes_written = SSL_write(data->ssl, buf, nread);
}
else {
#endif
bytes_written = swrite(writesockfd, buf, nread);
#ifdef USE_SSLEAY
}
#endif /* USE_SSLEAY */
if(nread != bytes_written) {
failf(data, "Failed uploading data");
return URG_WRITE_ERROR;
}
}
break;
}
now = tvnow();
pgrsUpdate(data);
urg = speedcheck (data, now);
if (urg)
return urg;
if (data->timeout && (tvdiff (now, start) > data->timeout)) {
failf (data, "Operation timed out with %d out of %d bytes received",
bytecount, size);
return URG_OPERATION_TIMEOUTED;
}
#ifdef MULTIDOC
if(contentlength && bytecount >= contentlength) {
/* we're done with this download, now stop it */
break;
}
#endif
}
}
if(!(data->conf&CONF_NOBODY) && contentlength &&
(bytecount != contentlength)) {
failf(data, "transfer closed with %d bytes remaining to read",
contentlength-bytecount);
return URG_PARTIAL_FILE;
}
pgrsUpdate(data);
if(bytecountp)
*bytecountp = bytecount; /* read count */
if(writebytecountp)
*writebytecountp = writebytecount; /* write count */
return URG_OK;
} }

View File

@ -39,8 +39,8 @@
* *
* ------------------------------------------------------------ * ------------------------------------------------------------
****************************************************************************/ ****************************************************************************/
UrgError CURLcode
Transfer (struct UrlData *data, Transfer (struct connectdata *data,
int sockfd, /* socket to read from or -1 */ int sockfd, /* socket to read from or -1 */
int size, /* -1 if unknown at this point */ int size, /* -1 if unknown at this point */
bool getheader, /* TRUE if header parsing is wanted */ bool getheader, /* TRUE if header parsing is wanted */

View File

@ -81,16 +81,15 @@ char *curl_escape(char *string)
return ns; return ns;
} }
char *curl_unescape(char *string) char *curl_unescape(char *string, int length)
{ {
int alloc = strlen(string)+1; int alloc = (length?length:strlen(string))+1;
char *ns = malloc(alloc); char *ns = malloc(alloc);
unsigned char in; unsigned char in;
int index=0; int index=0;
int hex; int hex;
while(--alloc) {
while(*string) {
in = *string; in = *string;
if('+' == in) if('+' == in)
in = ' '; in = ' ';

View File

@ -44,6 +44,6 @@
* allocated string or NULL if an error occurred. */ * allocated string or NULL if an error occurred. */
char *curl_escape(char *string); char *curl_escape(char *string);
char *curl_unescape(char *string); char *curl_unescape(char *string, int length);
#endif #endif

View File

@ -100,23 +100,25 @@
#include <curl/mprintf.h> #include <curl/mprintf.h>
UrgError file(struct UrlData *data, char *path, long *bytecountp) CURLcode file(struct connectdata *conn)
{ {
/* This implementation ignores the host name in conformance with /* This implementation ignores the host name in conformance with
RFC 1738. Only local files (reachable via the standard file system) RFC 1738. Only local files (reachable via the standard file system)
are supported. This means that files on remotely mounted directories are supported. This means that files on remotely mounted directories
(via NFS, Samba, NT sharing) can be accessed through a file:// URL (via NFS, Samba, NT sharing) can be accessed through a file:// URL
*/ */
CURLcode res = CURLE_OK;
char *path = conn->path;
struct stat statbuf; struct stat statbuf;
size_t expected_size=-1; size_t expected_size=-1;
size_t nread; size_t nread;
struct UrlData *data = conn->data;
char *buf = data->buffer; char *buf = data->buffer;
int bytecount = 0; int bytecount = 0;
struct timeval start = tvnow(); struct timeval start = tvnow();
struct timeval now = start; struct timeval now = start;
int fd; int fd;
char *actual_path = curl_unescape(path); char *actual_path = curl_unescape(path, 0);
#if defined(WIN32) || defined(__EMX__) #if defined(WIN32) || defined(__EMX__)
int i; int i;
@ -134,7 +136,7 @@ UrgError file(struct UrlData *data, char *path, long *bytecountp)
if(fd == -1) { if(fd == -1) {
failf(data, "Couldn't open file %s", path); failf(data, "Couldn't open file %s", path);
return URG_FILE_COULDNT_READ_FILE; return CURLE_FILE_COULDNT_READ_FILE;
} }
if( -1 != fstat(fd, &statbuf)) { if( -1 != fstat(fd, &statbuf)) {
/* we could stat it, then read out the size */ /* we could stat it, then read out the size */
@ -151,7 +153,7 @@ UrgError file(struct UrlData *data, char *path, long *bytecountp)
if(expected_size != -1) if(expected_size != -1)
pgrsSetDownloadSize(data, expected_size); pgrsSetDownloadSize(data, expected_size);
while (1) { while (res == CURLE_OK) {
nread = read(fd, buf, BUFSIZE-1); nread = read(fd, buf, BUFSIZE-1);
if (0 <= nread) if (0 <= nread)
@ -166,21 +168,19 @@ UrgError file(struct UrlData *data, char *path, long *bytecountp)
file descriptor). */ file descriptor). */
if(nread != data->fwrite (buf, 1, nread, data->out)) { if(nread != data->fwrite (buf, 1, nread, data->out)) {
failf (data, "Failed writing output"); failf (data, "Failed writing output");
return URG_WRITE_ERROR; return CURLE_WRITE_ERROR;
} }
now = tvnow(); now = tvnow();
pgrsUpdate(data); if(pgrsUpdate(data))
#if 0 res = CURLE_ABORTED_BY_CALLBACK;
ProgressShow (data, bytecount, start, now, FALSE);
#endif
} }
now = tvnow(); now = tvnow();
#if 0 if(pgrsUpdate(data))
ProgressShow (data, bytecount, start, now, TRUE); res = CURLE_ABORTED_BY_CALLBACK;
#endif
pgrsUpdate(data);
close(fd); close(fd);
return URG_OK; free(actual_path);
return res;
} }

View File

@ -40,6 +40,6 @@
* *
* ------------------------------------------------------------ * ------------------------------------------------------------
****************************************************************************/ ****************************************************************************/
UrgError file(struct UrlData *data, char *path, long *bytecountp); CURLcode file(struct connectdata *conn);
#endif #endif

View File

@ -60,6 +60,8 @@
#include <curl/curl.h> #include <curl/curl.h>
#include "formdata.h" #include "formdata.h"
#include "strequal.h"
/* Length of the random boundary string. The risk of this being used /* Length of the random boundary string. The risk of this being used
in binary data is very close to zero, 64^32 makes in binary data is very close to zero, 64^32 makes
6277101735386680763835789423207666416102355444464034512896 6277101735386680763835789423207666416102355444464034512896
@ -377,7 +379,7 @@ void FormFree(struct FormData *form)
free(form->line); /* free the line */ free(form->line); /* free the line */
free(form); /* free the struct */ free(form); /* free the struct */
} while(form=next); /* continue */ } while((form=next)); /* continue */
} }
struct FormData *getFormData(struct HttpPost *post, struct FormData *getFormData(struct HttpPost *post,
@ -513,11 +515,16 @@ struct FormData *getFormData(struct HttpPost *post,
int FormInit(struct Form *form, struct FormData *formdata ) int FormInit(struct Form *form, struct FormData *formdata )
{ {
form->data = formdata;
form->sent = 0;
if(!formdata) if(!formdata)
return 1; /* error */ return 1; /* error */
/* First, make sure that we'll send a nice terminating sequence at the end
* of the post. We *DONT* add this string to the size of the data since this
* is actually AFTER the data. */
AddFormDataf(&formdata, "\r\n\r\n");
form->data = formdata;
form->sent = 0;
return 0; return 0;
} }

436
lib/ftp.c
View File

@ -149,7 +149,7 @@ void curl_slist_free_all(struct curl_slist *list)
} }
static UrgError AllowServerConnect(struct UrlData *data, static CURLcode AllowServerConnect(struct UrlData *data,
int sock) int sock)
{ {
fd_set rdset; fd_set rdset;
@ -167,11 +167,11 @@ static UrgError AllowServerConnect(struct UrlData *data,
case -1: /* error */ case -1: /* error */
/* let's die here */ /* let's die here */
failf(data, "Error while waiting for server connect"); failf(data, "Error while waiting for server connect");
return URG_FTP_PORT_FAILED; return CURLE_FTP_PORT_FAILED;
case 0: /* timeout */ case 0: /* timeout */
/* let's die here */ /* let's die here */
failf(data, "Timeout while waiting for server connect"); failf(data, "Timeout while waiting for server connect");
return URG_FTP_PORT_FAILED; return CURLE_FTP_PORT_FAILED;
default: default:
/* we have received data here */ /* we have received data here */
{ {
@ -185,7 +185,7 @@ static UrgError AllowServerConnect(struct UrlData *data,
if( -1 == s) { if( -1 == s) {
/* DIE! */ /* DIE! */
failf(data, "Error accept()ing server connect"); failf(data, "Error accept()ing server connect");
return URG_FTP_PORT_FAILED; return CURLE_FTP_PORT_FAILED;
} }
infof(data, "Connection accepted from server\n"); infof(data, "Connection accepted from server\n");
@ -193,7 +193,7 @@ static UrgError AllowServerConnect(struct UrlData *data,
} }
break; break;
} }
return URG_OK; return CURLE_OK;
} }
@ -202,7 +202,7 @@ static UrgError AllowServerConnect(struct UrlData *data,
#define lastline(line) (isdigit((int)line[0]) && isdigit((int)line[1]) && \ #define lastline(line) (isdigit((int)line[0]) && isdigit((int)line[1]) && \
isdigit((int)line[2]) && (' ' == line[3])) isdigit((int)line[2]) && (' ' == line[3]))
static int GetLastResponse(int sockfd, char *buf, int GetLastResponse(int sockfd, char *buf,
struct UrlData *data) struct UrlData *data)
{ {
int nread; int nread;
@ -230,7 +230,7 @@ static int GetLastResponse(int sockfd, char *buf,
} }
*ptr=0; /* zero terminate */ *ptr=0; /* zero terminate */
if(data->conf & CONF_VERBOSE) { if(data->bits.verbose) {
fputs("< ", data->err); fputs("< ", data->err);
fwrite(buf, 1, nread, data->err); fwrite(buf, 1, nread, data->err);
fputs("\n", data->err); fputs("\n", data->err);
@ -310,32 +310,37 @@ static char *URLfix(char *string)
} }
#endif #endif
static /* ftp_connect() should do everything that is to be considered a part
UrgError _ftp(struct UrlData *data, of the connection phase. */
long *bytecountp, CURLcode ftp_connect(struct connectdata *conn)
char *ftpuser,
char *ftppasswd,
char *ppath)
{ {
/* this is FTP and no proxy */ /* this is FTP and no proxy */
size_t nread; size_t nread;
UrgError result; struct UrlData *data=conn->data;
char *buf = data->buffer; /* this is our buffer */ char *buf = data->buffer; /* this is our buffer */
/* for the ftp PORT mode */ struct FTP *ftp;
int portsock=-1;
struct sockaddr_in serv_addr;
struct curl_slist *qitem; /* QUOTE item */ ftp = (struct FTP *)malloc(sizeof(struct FTP));
if(!ftp)
return CURLE_OUT_OF_MEMORY;
memset(ftp, 0, sizeof(struct FTP));
data->proto.ftp = ftp;
/* get some initial data into the ftp struct */
ftp->bytecountp = &conn->bytecount;
ftp->user = data->user;
ftp->passwd = data->passwd;
/* The first thing we do is wait for the "220*" line: */ /* The first thing we do is wait for the "220*" line: */
nread = GetLastResponse(data->firstsocket, buf, data); nread = GetLastResponse(data->firstsocket, buf, data);
if(strncmp(buf, "220", 3)) { if(strncmp(buf, "220", 3)) {
failf(data, "This doesn't seem like a nice ftp-server response"); failf(data, "This doesn't seem like a nice ftp-server response");
return URG_FTP_WEIRD_SERVER_REPLY; return CURLE_FTP_WEIRD_SERVER_REPLY;
} }
/* send USER */ /* send USER */
sendf(data->firstsocket, data, "USER %s\r\n", ftpuser); sendf(data->firstsocket, data, "USER %s\r\n", ftp->user);
/* wait for feedback */ /* wait for feedback */
nread = GetLastResponse(data->firstsocket, buf, data); nread = GetLastResponse(data->firstsocket, buf, data);
@ -344,19 +349,19 @@ UrgError _ftp(struct UrlData *data,
/* 530 User ... access denied /* 530 User ... access denied
(the server denies to log the specified user) */ (the server denies to log the specified user) */
failf(data, "Access denied: %s", &buf[4]); failf(data, "Access denied: %s", &buf[4]);
return URG_FTP_ACCESS_DENIED; return CURLE_FTP_ACCESS_DENIED;
} }
else if(!strncmp(buf, "331", 3)) { else if(!strncmp(buf, "331", 3)) {
/* 331 Password required for ... /* 331 Password required for ...
(the server requires to send the user's password too) */ (the server requires to send the user's password too) */
sendf(data->firstsocket, data, "PASS %s\r\n", ftppasswd); sendf(data->firstsocket, data, "PASS %s\r\n", ftp->passwd);
nread = GetLastResponse(data->firstsocket, buf, data); nread = GetLastResponse(data->firstsocket, buf, data);
if(!strncmp(buf, "530", 3)) { if(!strncmp(buf, "530", 3)) {
/* 530 Login incorrect. /* 530 Login incorrect.
(the username and/or the password are incorrect) */ (the username and/or the password are incorrect) */
failf(data, "the username and/or the password are incorrect"); failf(data, "the username and/or the password are incorrect");
return URG_FTP_USER_PASSWORD_INCORRECT; return CURLE_FTP_USER_PASSWORD_INCORRECT;
} }
else if(!strncmp(buf, "230", 3)) { else if(!strncmp(buf, "230", 3)) {
/* 230 User ... logged in. /* 230 User ... logged in.
@ -366,7 +371,7 @@ UrgError _ftp(struct UrlData *data,
} }
else { else {
failf(data, "Odd return code after PASS"); failf(data, "Odd return code after PASS");
return URG_FTP_WEIRD_PASS_REPLY; return CURLE_FTP_WEIRD_PASS_REPLY;
} }
} }
else if(! strncmp(buf, "230", 3)) { else if(! strncmp(buf, "230", 3)) {
@ -376,9 +381,105 @@ UrgError _ftp(struct UrlData *data,
} }
else { else {
failf(data, "Odd return code after USER"); failf(data, "Odd return code after USER");
return URG_FTP_WEIRD_USER_REPLY; return CURLE_FTP_WEIRD_USER_REPLY;
} }
return CURLE_OK;
}
/* argument is already checked for validity */
CURLcode ftp_done(struct connectdata *conn)
{
struct UrlData *data = conn->data;
struct FTP *ftp = data->proto.ftp;
size_t nread;
char *buf = data->buffer; /* this is our buffer */
struct curl_slist *qitem; /* QUOTE item */
if(data->bits.upload) {
if((-1 != data->infilesize) && (data->infilesize != *ftp->bytecountp)) {
failf(data, "Wrote only partial file (%d out of %d bytes)",
*ftp->bytecountp, data->infilesize);
return CURLE_PARTIAL_FILE;
}
}
else {
if((-1 != conn->size) && (conn->size != *ftp->bytecountp) &&
(data->maxdownload != *ftp->bytecountp)) {
failf(data, "Received only partial file");
return CURLE_PARTIAL_FILE;
}
else if(0 == *ftp->bytecountp) {
failf(data, "No data was received!");
return CURLE_FTP_COULDNT_RETR_FILE;
}
}
/* shut down the socket to inform the server we're done */
sclose(data->secondarysocket);
data->secondarysocket = -1;
/* now let's see what the server says about the transfer we
just performed: */
nread = GetLastResponse(data->firstsocket, buf, data);
/* 226 Transfer complete */
if(strncmp(buf, "226", 3)) {
failf(data, "%s", buf+4);
return CURLE_FTP_WRITE_ERROR;
}
/* Send any post-transfer QUOTE strings? */
if(data->postquote) {
qitem = data->postquote;
/* Send all QUOTE strings in same order as on command-line */
while (qitem) {
/* Send string */
if (qitem->data) {
sendf(data->firstsocket, data, "%s\r\n", qitem->data);
nread = GetLastResponse(data->firstsocket, buf, data);
if (buf[0] != '2') {
failf(data, "QUOT string not accepted: %s",
qitem->data);
return CURLE_FTP_QUOTE_ERROR;
}
}
qitem = qitem->next;
}
}
if(ftp->file)
free(ftp->file);
if(ftp->dir)
free(ftp->dir);
/* TBD: the ftp struct is still allocated here */
return CURLE_OK;
}
static
CURLcode _ftp(struct connectdata *conn)
{
/* this is FTP and no proxy */
size_t nread;
CURLcode result;
struct UrlData *data=conn->data;
char *buf = data->buffer; /* this is our buffer */
/* for the ftp PORT mode */
int portsock=-1;
struct sockaddr_in serv_addr;
struct curl_slist *qitem; /* QUOTE item */
/* the ftp struct is already inited in ftp_connect() */
struct FTP *ftp = data->proto.ftp;
long *bytecountp = ftp->bytecountp;
/* Send any QUOTE strings? */ /* Send any QUOTE strings? */
if(data->quote) { if(data->quote) {
qitem = data->quote; qitem = data->quote;
@ -393,7 +494,7 @@ UrgError _ftp(struct UrlData *data,
if (buf[0] != '2') { if (buf[0] != '2') {
failf(data, "QUOT string not accepted: %s", failf(data, "QUOT string not accepted: %s",
qitem->data); qitem->data);
return URG_FTP_QUOTE_ERROR; return CURLE_FTP_QUOTE_ERROR;
} }
} }
qitem = qitem->next; qitem = qitem->next;
@ -402,18 +503,18 @@ UrgError _ftp(struct UrlData *data,
/* If we have selected NOBODY, it means that we only want file information. /* If we have selected NOBODY, it means that we only want file information.
Which in FTP can't be much more than the file size! */ Which in FTP can't be much more than the file size! */
if(data->conf & CONF_NOBODY) { if(data->bits.no_body) {
/* The SIZE command is _not_ RFC 959 specified, and therefor many servers /* The SIZE command is _not_ RFC 959 specified, and therefor many servers
may not support it! It is however the only way we have to get a file's may not support it! It is however the only way we have to get a file's
size! */ size! */
int filesize; int filesize;
sendf(data->firstsocket, data, "SIZE %s\r\n", ppath); sendf(data->firstsocket, data, "SIZE %s\r\n", ftp->file);
nread = GetLastResponse(data->firstsocket, buf, data); nread = GetLastResponse(data->firstsocket, buf, data);
if(strncmp(buf, "213", 3)) { if(strncmp(buf, "213", 3)) {
failf(data, "Couldn't get file size: %s", buf+4); failf(data, "Couldn't get file size: %s", buf+4);
return URG_FTP_COULDNT_GET_SIZE; return CURLE_FTP_COULDNT_GET_SIZE;
} }
/* get the size from the ascii string: */ /* get the size from the ascii string: */
filesize = atoi(buf+4); filesize = atoi(buf+4);
@ -422,21 +523,21 @@ UrgError _ftp(struct UrlData *data,
if(strlen(buf) != data->fwrite(buf, 1, strlen(buf), data->out)) { if(strlen(buf) != data->fwrite(buf, 1, strlen(buf), data->out)) {
failf (data, "Failed writing output"); failf (data, "Failed writing output");
return URG_WRITE_ERROR; return CURLE_WRITE_ERROR;
} }
if(data->writeheader) { if(data->writeheader) {
/* the header is requested to be written to this file */ /* the header is requested to be written to this file */
if(strlen(buf) != data->fwrite (buf, 1, strlen(buf), if(strlen(buf) != data->fwrite (buf, 1, strlen(buf),
data->writeheader)) { data->writeheader)) {
failf (data, "Failed writing output"); failf (data, "Failed writing output");
return URG_WRITE_ERROR; return CURLE_WRITE_ERROR;
} }
} }
return URG_OK; return CURLE_OK;
} }
/* We have chosen to use the PORT command */ /* We have chosen to use the PORT command */
if(data->conf & CONF_FTPPORT) { if(data->bits.ftp_use_port) {
struct sockaddr_in sa; struct sockaddr_in sa;
struct hostent *h=NULL; struct hostent *h=NULL;
size_t size; size_t size;
@ -481,28 +582,28 @@ UrgError _ftp(struct UrlData *data,
if(getsockname(portsock, (struct sockaddr *) &add, if(getsockname(portsock, (struct sockaddr *) &add,
(int *)&size)<0) { (int *)&size)<0) {
failf(data, "getsockname() failed"); failf(data, "getsockname() failed");
return URG_FTP_PORT_FAILED; return CURLE_FTP_PORT_FAILED;
} }
porttouse = ntohs(add.sin_port); porttouse = ntohs(add.sin_port);
if ( listen(portsock, 1) < 0 ) { if ( listen(portsock, 1) < 0 ) {
failf(data, "listen(2) failed on socket"); failf(data, "listen(2) failed on socket");
return URG_FTP_PORT_FAILED; return CURLE_FTP_PORT_FAILED;
} }
} }
else { else {
failf(data, "bind(2) failed on socket"); failf(data, "bind(2) failed on socket");
return URG_FTP_PORT_FAILED; return CURLE_FTP_PORT_FAILED;
} }
} }
else { else {
failf(data, "socket(2) failed (%s)"); failf(data, "socket(2) failed (%s)");
return URG_FTP_PORT_FAILED; return CURLE_FTP_PORT_FAILED;
} }
} }
else { else {
failf(data, "could't find my own IP address (%s)", myhost); failf(data, "could't find my own IP address (%s)", myhost);
return URG_FTP_PORT_FAILED; return CURLE_FTP_PORT_FAILED;
} }
{ {
struct in_addr in; struct in_addr in;
@ -520,7 +621,7 @@ UrgError _ftp(struct UrlData *data,
if(strncmp(buf, "200", 3)) { if(strncmp(buf, "200", 3)) {
failf(data, "Server does not grok PORT, try without it!"); failf(data, "Server does not grok PORT, try without it!");
return URG_FTP_PORT_FAILED; return CURLE_FTP_PORT_FAILED;
} }
} }
else { /* we use the PASV command */ else { /* we use the PASV command */
@ -531,7 +632,7 @@ UrgError _ftp(struct UrlData *data,
if(strncmp(buf, "227", 3)) { if(strncmp(buf, "227", 3)) {
failf(data, "Odd return code after PASV"); failf(data, "Odd return code after PASV");
return URG_FTP_WEIRD_PASV_REPLY; return CURLE_FTP_WEIRD_PASV_REPLY;
} }
else { else {
int ip[4]; int ip[4];
@ -561,13 +662,13 @@ UrgError _ftp(struct UrlData *data,
} }
if(!*str) { if(!*str) {
failf(data, "Couldn't interpret this 227-reply: %s", buf); failf(data, "Couldn't interpret this 227-reply: %s", buf);
return URG_FTP_WEIRD_227_FORMAT; return CURLE_FTP_WEIRD_227_FORMAT;
} }
sprintf(newhost, "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]); sprintf(newhost, "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
he = GetHost(data, newhost); he = GetHost(data, newhost);
if(!he) { if(!he) {
failf(data, "Can't resolve new host %s", newhost); failf(data, "Can't resolve new host %s", newhost);
return URG_FTP_CANT_GET_HOST; return CURLE_FTP_CANT_GET_HOST;
} }
@ -579,7 +680,7 @@ UrgError _ftp(struct UrlData *data,
serv_addr.sin_family = he->h_addrtype; serv_addr.sin_family = he->h_addrtype;
serv_addr.sin_port = htons(newport); serv_addr.sin_port = htons(newport);
if(data->conf & CONF_VERBOSE) { if(data->bits.verbose) {
struct in_addr in; struct in_addr in;
#if 1 #if 1
struct hostent * answer; struct hostent * answer;
@ -620,26 +721,38 @@ UrgError _ftp(struct UrlData *data,
failf(data, "Can't connect to ftp server"); failf(data, "Can't connect to ftp server");
break; break;
} }
return URG_FTP_CANT_RECONNECT; return CURLE_FTP_CANT_RECONNECT;
} }
} }
} }
/* we have the (new) data connection ready */ /* we have the (new) data connection ready */
if(data->conf & CONF_UPLOAD) { /* change directory first */
if(ftp->dir && ftp->dir[0]) {
sendf(data->firstsocket, data, "CWD %s\r\n", ftp->dir);
nread = GetLastResponse(data->firstsocket, buf, data);
if(strncmp(buf, "250", 3)) {
failf(data, "Couldn't change to directory %s", ftp->dir);
return CURLE_FTP_ACCESS_DENIED;
}
}
if(data->bits.upload) {
/* Set type to binary (unless specified ASCII) */ /* Set type to binary (unless specified ASCII) */
sendf(data->firstsocket, data, "TYPE %s\r\n", sendf(data->firstsocket, data, "TYPE %s\r\n",
(data->conf&CONF_FTPASCII)?"A":"I"); (data->bits.ftp_ascii)?"A":"I");
nread = GetLastResponse(data->firstsocket, buf, data); nread = GetLastResponse(data->firstsocket, buf, data);
if(strncmp(buf, "200", 3)) { if(strncmp(buf, "200", 3)) {
failf(data, "Couldn't set %s mode", failf(data, "Couldn't set %s mode",
(data->conf&CONF_FTPASCII)?"ASCII":"binary"); (data->bits.ftp_ascii)?"ASCII":"binary");
return (data->conf&CONF_FTPASCII)? URG_FTP_COULDNT_SET_ASCII: return (data->bits.ftp_ascii)? CURLE_FTP_COULDNT_SET_ASCII:
URG_FTP_COULDNT_SET_BINARY; CURLE_FTP_COULDNT_SET_BINARY;
} }
if(data->resume_from) { if(data->resume_from) {
@ -660,13 +773,13 @@ UrgError _ftp(struct UrlData *data,
/* we could've got a specified offset from the command line, /* we could've got a specified offset from the command line,
but now we know we didn't */ but now we know we didn't */
sendf(data->firstsocket, data, "SIZE %s\r\n", ppath); sendf(data->firstsocket, data, "SIZE %s\r\n", ftp->file);
nread = GetLastResponse(data->firstsocket, buf, data); nread = GetLastResponse(data->firstsocket, buf, data);
if(strncmp(buf, "213", 3)) { if(strncmp(buf, "213", 3)) {
failf(data, "Couldn't get file size: %s", buf+4); failf(data, "Couldn't get file size: %s", buf+4);
return URG_FTP_COULDNT_GET_SIZE; return CURLE_FTP_COULDNT_GET_SIZE;
} }
/* get the size from the ascii string: */ /* get the size from the ascii string: */
@ -687,11 +800,11 @@ UrgError _ftp(struct UrlData *data,
if(strncmp(buf, "350", 3)) { if(strncmp(buf, "350", 3)) {
failf(data, "Couldn't use REST: %s", buf+4); failf(data, "Couldn't use REST: %s", buf+4);
return URG_FTP_COULDNT_USE_REST; return CURLE_FTP_COULDNT_USE_REST;
} }
#else #else
/* enable append instead */ /* enable append instead */
data->conf |= CONF_FTPAPPEND; data->bits.ftp_append = 1;
#endif #endif
/* Now, let's read off the proper amount of bytes from the /* Now, let's read off the proper amount of bytes from the
input. If we knew it was a proper file we could've just input. If we knew it was a proper file we could've just
@ -710,7 +823,7 @@ UrgError _ftp(struct UrlData *data,
if(actuallyread != readthisamountnow) { if(actuallyread != readthisamountnow) {
failf(data, "Could only read %d bytes from the input\n", failf(data, "Could only read %d bytes from the input\n",
passed); passed);
return URG_FTP_COULDNT_USE_REST; return CURLE_FTP_COULDNT_USE_REST;
} }
} }
while(passed != data->resume_from); while(passed != data->resume_from);
@ -721,7 +834,7 @@ UrgError _ftp(struct UrlData *data,
if(data->infilesize <= 0) { if(data->infilesize <= 0) {
infof(data, "File already completely uploaded\n"); infof(data, "File already completely uploaded\n");
return URG_OK; return CURLE_OK;
} }
} }
/* we've passed, proceed as normal */ /* we've passed, proceed as normal */
@ -729,21 +842,21 @@ UrgError _ftp(struct UrlData *data,
} }
/* Send everything on data->in to the socket */ /* Send everything on data->in to the socket */
if(data->conf & CONF_FTPAPPEND) if(data->bits.ftp_append)
/* we append onto the file instead of rewriting it */ /* we append onto the file instead of rewriting it */
sendf(data->firstsocket, data, "APPE %s\r\n", ppath); sendf(data->firstsocket, data, "APPE %s\r\n", ftp->file);
else else
sendf(data->firstsocket, data, "STOR %s\r\n", ppath); sendf(data->firstsocket, data, "STOR %s\r\n", ftp->file);
nread = GetLastResponse(data->firstsocket, buf, data); nread = GetLastResponse(data->firstsocket, buf, data);
if(atoi(buf)>=400) { if(atoi(buf)>=400) {
failf(data, "Failed FTP upload:%s", buf+3); failf(data, "Failed FTP upload:%s", buf+3);
/* oops, we never close the sockets! */ /* oops, we never close the sockets! */
return URG_FTP_COULDNT_STOR_FILE; return CURLE_FTP_COULDNT_STOR_FILE;
} }
if(data->conf & CONF_FTPPORT) { if(data->bits.ftp_use_port) {
result = AllowServerConnect(data, portsock); result = AllowServerConnect(data, portsock);
if( result ) if( result )
return result; return result;
@ -758,24 +871,19 @@ UrgError _ftp(struct UrlData *data,
#if 0 #if 0
ProgressInit(data, data->infilesize); ProgressInit(data, data->infilesize);
#endif #endif
result = Transfer(data, -1, -1, FALSE, NULL, /* no download */ result = Transfer(conn, -1, -1, FALSE, NULL, /* no download */
data->secondarysocket, bytecountp); data->secondarysocket, bytecountp);
if(result) if(result)
return result; return result;
if((-1 != data->infilesize) && (data->infilesize != *bytecountp)) {
failf(data, "Wrote only partial file (%d out of %d bytes)",
*bytecountp, data->infilesize);
return URG_PARTIAL_FILE;
}
} }
else { else {
/* Retrieve file or directory */ /* Retrieve file or directory */
bool dirlist=FALSE; bool dirlist=FALSE;
long downloadsize=-1; long downloadsize=-1;
if(data->conf&CONF_RANGE && data->range) { if(data->bits.set_range && data->range) {
int from, to; long from, to;
int totalsize=-1; int totalsize=-1;
char *ptr; char *ptr;
char *ptr2; char *ptr2;
@ -788,32 +896,34 @@ UrgError _ftp(struct UrlData *data,
/* we didn't get any digit */ /* we didn't get any digit */
to=-1; to=-1;
} }
if(-1 == to) { if((-1 == to) && (from>=0)) {
/* X - */ /* X - */
data->resume_from = from; data->resume_from = from;
infof(data, "FTP RANGE %d to end of file\n", from);
} }
else if(from < 0) { else if(from < 0) {
/* -Y */ /* -Y */
from = 0; totalsize = -from;
to = -from; data->maxdownload = -from;
totalsize = to-from; data->resume_from = from;
data->maxdownload = totalsize; infof(data, "FTP RANGE the last %d bytes\n", totalsize);
} }
else { else {
/* X- */ /* X-Y */
totalsize = to-from; totalsize = to-from;
data->maxdownload = totalsize; data->maxdownload = totalsize+1; /* include the last mentioned byte */
data->resume_from = from;
infof(data, "FTP RANGE from %d getting %d bytes\n", from, data->maxdownload);
} }
infof(data, "range-download from %d to %d, totally %d bytes\n", infof(data, "range-download from %d to %d, totally %d bytes\n",
from, to, totalsize); from, to, totalsize);
} }
#if 0
if(!ppath[0]) if(!ppath[0])
/* make sure this becomes a valid name */ /* make sure this becomes a valid name */
ppath="./"; ppath="./";
#endif
if((data->conf & CONF_FTPLISTONLY) || if((data->bits.ftp_list_only) || !ftp->file) {
('/' == ppath[strlen(ppath)-1] )) {
/* The specified path ends with a slash, and therefore we think this /* The specified path ends with a slash, and therefore we think this
is a directory that is requested, use LIST. But before that we is a directory that is requested, use LIST. But before that we
need to set ASCII transfer mode. */ need to set ASCII transfer mode. */
@ -826,30 +936,29 @@ UrgError _ftp(struct UrlData *data,
if(strncmp(buf, "200", 3)) { if(strncmp(buf, "200", 3)) {
failf(data, "Couldn't set ascii mode"); failf(data, "Couldn't set ascii mode");
return URG_FTP_COULDNT_SET_ASCII; return CURLE_FTP_COULDNT_SET_ASCII;
} }
/* if this output is to be machine-parsed, the NLST command will be /* if this output is to be machine-parsed, the NLST command will be
better used since the LIST command output is not specified or better used since the LIST command output is not specified or
standard in any way */ standard in any way */
sendf(data->firstsocket, data, "%s %s\r\n", sendf(data->firstsocket, data, "%s\r\n",
data->customrequest?data->customrequest: data->customrequest?data->customrequest:
(data->conf&CONF_FTPLISTONLY?"NLST":"LIST"), (data->bits.ftp_list_only?"NLST":"LIST"));
ppath);
} }
else { else {
/* Set type to binary (unless specified ASCII) */ /* Set type to binary (unless specified ASCII) */
sendf(data->firstsocket, data, "TYPE %s\r\n", sendf(data->firstsocket, data, "TYPE %s\r\n",
(data->conf&CONF_FTPASCII)?"A":"I"); (data->bits.ftp_list_only)?"A":"I");
nread = GetLastResponse(data->firstsocket, buf, data); nread = GetLastResponse(data->firstsocket, buf, data);
if(strncmp(buf, "200", 3)) { if(strncmp(buf, "200", 3)) {
failf(data, "Couldn't set %s mode", failf(data, "Couldn't set %s mode",
(data->conf&CONF_FTPASCII)?"ASCII":"binary"); (data->bits.ftp_ascii)?"ASCII":"binary");
return (data->conf&CONF_FTPASCII)? URG_FTP_COULDNT_SET_ASCII: return (data->bits.ftp_ascii)? CURLE_FTP_COULDNT_SET_ASCII:
URG_FTP_COULDNT_SET_BINARY; CURLE_FTP_COULDNT_SET_BINARY;
} }
if(data->resume_from) { if(data->resume_from) {
@ -860,7 +969,7 @@ UrgError _ftp(struct UrlData *data,
* of the file we're gonna get. If we can get the size, this is by far * of the file we're gonna get. If we can get the size, this is by far
* the best way to know if we're trying to resume beyond the EOF. */ * the best way to know if we're trying to resume beyond the EOF. */
sendf(data->firstsocket, data, "SIZE %s\r\n", ppath); sendf(data->firstsocket, data, "SIZE %s\r\n", ftp->file);
nread = GetLastResponse(data->firstsocket, buf, data); nread = GetLastResponse(data->firstsocket, buf, data);
@ -875,13 +984,27 @@ UrgError _ftp(struct UrlData *data,
int foundsize=atoi(buf+4); int foundsize=atoi(buf+4);
/* We got a file size report, so we check that there actually is a /* We got a file size report, so we check that there actually is a
part of the file left to get, or else we go home. */ part of the file left to get, or else we go home. */
if(foundsize <= data->resume_from) { if(data->resume_from< 0) {
failf(data, "Offset (%d) was beyond file size (%d)", /* We're supposed to download the last abs(from) bytes */
data->resume_from, foundsize); if(foundsize < -data->resume_from) {
return URG_FTP_BAD_DOWNLOAD_RESUME; failf(data, "Offset (%d) was beyond file size (%d)",
data->resume_from, foundsize);
return CURLE_FTP_BAD_DOWNLOAD_RESUME;
}
/* convert to size to download */
downloadsize = -data->resume_from;
/* download from where? */
data->resume_from = foundsize - downloadsize;
}
else {
if(foundsize <= data->resume_from) {
failf(data, "Offset (%d) was beyond file size (%d)",
data->resume_from, foundsize);
return CURLE_FTP_BAD_DOWNLOAD_RESUME;
}
/* Now store the number of bytes we are expected to download */
downloadsize = foundsize-data->resume_from;
} }
/* Now store the number of bytes we are expected to download */
downloadsize = foundsize-data->resume_from;
} }
/* Set resume file transfer offset */ /* Set resume file transfer offset */
@ -894,11 +1017,11 @@ UrgError _ftp(struct UrlData *data,
if(strncmp(buf, "350", 3)) { if(strncmp(buf, "350", 3)) {
failf(data, "Couldn't use REST: %s", buf+4); failf(data, "Couldn't use REST: %s", buf+4);
return URG_FTP_COULDNT_USE_REST; return CURLE_FTP_COULDNT_USE_REST;
} }
} }
sendf(data->firstsocket, data, "RETR %s\r\n", ppath); sendf(data->firstsocket, data, "RETR %s\r\n", ftp->file);
} }
nread = GetLastResponse(data->firstsocket, buf, data); nread = GetLastResponse(data->firstsocket, buf, data);
@ -968,12 +1091,12 @@ UrgError _ftp(struct UrlData *data,
if(size <= 0) { if(size <= 0) {
failf(data, "Offset (%d) was beyond file size (%d)", failf(data, "Offset (%d) was beyond file size (%d)",
data->resume_from, data->resume_from+size); data->resume_from, data->resume_from+size);
return URG_PARTIAL_FILE; return CURLE_PARTIAL_FILE;
} }
} }
#endif #endif
if(data->conf & CONF_FTPPORT) { if(data->bits.ftp_use_port) {
result = AllowServerConnect(data, portsock); result = AllowServerConnect(data, portsock);
if( result ) if( result )
return result; return result;
@ -982,95 +1105,74 @@ UrgError _ftp(struct UrlData *data,
infof(data, "Getting file with size: %d\n", size); infof(data, "Getting file with size: %d\n", size);
/* FTP download: */ /* FTP download: */
result=Transfer(data, data->secondarysocket, size, FALSE, result=Transfer(conn, data->secondarysocket, size, FALSE,
bytecountp, bytecountp,
-1, NULL); /* no upload here */ -1, NULL); /* no upload here */
if(result) if(result)
return result; return result;
if((-1 != size) && (size != *bytecountp)) {
failf(data, "Received only partial file");
return URG_PARTIAL_FILE;
}
else if(0 == *bytecountp) {
failf(data, "No data was received!");
return URG_FTP_COULDNT_RETR_FILE;
}
} }
else { else {
failf(data, "%s", buf+4); failf(data, "%s", buf+4);
return URG_FTP_COULDNT_RETR_FILE; return CURLE_FTP_COULDNT_RETR_FILE;
} }
} }
/* end of transfer */ /* end of transfer */
#if 0
ProgressEnd(data);
#endif
pgrsDone(data);
/* shut down the socket to inform the server we're done */ return CURLE_OK;
sclose(data->secondarysocket);
data->secondarysocket = -1;
/* now let's see what the server says about the transfer we
just performed: */
nread = GetLastResponse(data->firstsocket, buf, data);
/* 226 Transfer complete */
if(strncmp(buf, "226", 3)) {
failf(data, "%s", buf+4);
return URG_FTP_WRITE_ERROR;
}
/* Send any post-transfer QUOTE strings? */
if(data->postquote) {
qitem = data->postquote;
/* Send all QUOTE strings in same order as on command-line */
while (qitem) {
/* Send string */
if (qitem->data) {
sendf(data->firstsocket, data, "%s\r\n", qitem->data);
nread = GetLastResponse(data->firstsocket, buf, data);
if (buf[0] != '2') {
failf(data, "QUOT string not accepted: %s",
qitem->data);
return URG_FTP_QUOTE_ERROR;
}
}
qitem = qitem->next;
}
}
return URG_OK;
} }
/* -- deal with the ftp server! -- */ /* -- deal with the ftp server! -- */
UrgError ftp(struct UrlData *data, /* argument is already checked for validity */
long *bytecountp, CURLcode ftp(struct connectdata *conn)
char *ftpuser,
char *ftppasswd,
char *urlpath)
{ {
char *realpath; CURLcode retcode;
UrgError retcode;
#if 0 struct UrlData *data = conn->data;
realpath = URLfix(urlpath); struct FTP *ftp;
#else int dirlength=0; /* 0 forces strlen() */
realpath = curl_unescape(urlpath);
#endif /* the ftp struct is already inited in ftp_connect() */
if(realpath) { ftp = data->proto.ftp;
retcode = _ftp(data, bytecountp, ftpuser, ftppasswd, realpath);
free(realpath); /* We split the path into dir and file parts *before* we URLdecode
it */
ftp->file = strrchr(conn->ppath, '/');
if(ftp->file) {
ftp->file++; /* point to the first letter in the file name part or
remain NULL */
}
else {
ftp->file = conn->ppath; /* there's only a file part */
}
dirlength=ftp->file-conn->ppath;
if(*ftp->file) {
ftp->file = curl_unescape(ftp->file, 0);
if(NULL == ftp->file) {
failf(data, "no memory");
return CURLE_OUT_OF_MEMORY;
}
} }
else else
/* then we try the original path */ ftp->file=NULL; /* instead of point to a zero byte, we make it a NULL
retcode = _ftp(data, bytecountp, ftpuser, ftppasswd, urlpath); pointer */
ftp->urlpath = conn->ppath;
if(dirlength) {
ftp->dir = curl_unescape(ftp->urlpath, dirlength);
if(NULL == ftp->dir) {
if(ftp->file)
free(ftp->file);
failf(data, "no memory");
return CURLE_OUT_OF_MEMORY; /* failure */
}
}
else
ftp->dir = NULL;
retcode = _ftp(conn);
return retcode; return retcode;
} }

View File

@ -40,11 +40,9 @@
* *
* ------------------------------------------------------------ * ------------------------------------------------------------
****************************************************************************/ ****************************************************************************/
UrgError ftp(struct UrlData *data, CURLcode ftp(struct connectdata *conn);
long *bytecountp, CURLcode ftp_done(struct connectdata *conn);
char *ftpuser, CURLcode ftp_connect(struct connectdata *conn);
char *ftppasswd,
char *ppath);
struct curl_slist *curl_slist_append(struct curl_slist *list, char *data); struct curl_slist *curl_slist_append(struct curl_slist *list, char *data);
void curl_slist_free_all(struct curl_slist *list); void curl_slist_free_all(struct curl_slist *list);

View File

@ -1864,7 +1864,7 @@ difftm (struct tm *a, struct tm *b)
} }
time_t time_t
get_date (const char *p, const time_t *now) curl_getdate (const char *p, const time_t *now)
{ {
struct tm tm, tm0, *tmp; struct tm tm, tm0, *tmp;
time_t Start; time_t Start;
@ -1998,7 +1998,7 @@ main (ac, av)
buff[MAX_BUFF_LEN] = 0; buff[MAX_BUFF_LEN] = 0;
while (fgets (buff, MAX_BUFF_LEN, stdin) && buff[0]) while (fgets (buff, MAX_BUFF_LEN, stdin) && buff[0])
{ {
d = get_date (buff, (time_t *) NULL); d = curl_getdate (buff, (time_t *) NULL);
if (d == -1) if (d == -1)
(void) printf ("Bad format - couldn't convert.\n"); (void) printf ("Bad format - couldn't convert.\n");
else else

View File

@ -1,18 +1,11 @@
/* Copyright (C) 1995, 1997, 1998 Free Software Foundation, Inc. /*
** Originally written by Steven M. Bellovin <smb@research.att.com> while
This program is free software; you can redistribute it and/or modify ** at the University of North Carolina at Chapel Hill. Later tweaked by
it under the terms of the GNU General Public License as published by ** a couple of people on Usenet. Completely overhauled by Rich $alz
the Free Software Foundation; either version 2, or (at your option) ** <rsalz@bbn.com> and Jim Berets <jberets@bbn.com> in August, 1990.
any later version. **
** This code is in the public domain and has no copyright.
This program is distributed in the hope that it will be useful, */
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#if HAVE_CONFIG_H #if HAVE_CONFIG_H
# include <config.h> # include <config.h>
@ -43,4 +36,4 @@
# endif # endif
#endif /* defined (vms) */ #endif /* defined (vms) */
time_t get_date PARAMS ((const char *p, const time_t *now)); time_t curl_getdate PARAMS ((const char *p, const time_t *now));

View File

@ -914,7 +914,7 @@ difftm (struct tm *a, struct tm *b)
} }
time_t time_t
get_date (const char *p, const time_t *now) curl_getdate (const char *p, const time_t *now)
{ {
struct tm tm, tm0, *tmp; struct tm tm, tm0, *tmp;
time_t Start; time_t Start;
@ -1048,7 +1048,7 @@ main (ac, av)
buff[MAX_BUFF_LEN] = 0; buff[MAX_BUFF_LEN] = 0;
while (fgets (buff, MAX_BUFF_LEN, stdin) && buff[0]) while (fgets (buff, MAX_BUFF_LEN, stdin) && buff[0])
{ {
d = get_date (buff, (time_t *) NULL); d = curl_getdate (buff, (time_t *) NULL);
if (d == -1) if (d == -1)
(void) printf ("Bad format - couldn't convert.\n"); (void) printf ("Bad format - couldn't convert.\n");
else else

View File

@ -22,18 +22,6 @@
* Portions created by the Initial Developer are Copyright (C) 1998. * Portions created by the Initial Developer are Copyright (C) 1998.
* All Rights Reserved. * All Rights Reserved.
* *
* Contributor(s):
* Rafael Sagula <sagula@inf.ufrgs.br>
* Sampo Kellomaki <sampo@iki.fi>
* Linas Vepstas <linas@linas.org>
* Bjorn Reese <breese@imada.ou.dk>
* Johan Anderson <johan@homemail.com>
* Kjell Ericson <Kjell.Ericson@haxx.nu>
* Troy Engel <tengel@palladium.net>
* Ryan Nelson <ryan@inch.com>
* Bjorn Stenberg <Bjorn.Stenberg@haxx.nu>
* Angus Mackay <amackay@gus.ml.org>
*
* ------------------------------------------------------------ * ------------------------------------------------------------
* Main author: * Main author:
* - Daniel Stenberg <Daniel.Stenberg@haxx.nu> * - Daniel Stenberg <Daniel.Stenberg@haxx.nu>
@ -47,24 +35,6 @@
* $State$ * $State$
* $Locker$ * $Locker$
* *
* ------------------------------------------------------------
* $Log$
* Revision 1.2 2000-01-10 23:36:14 bagder
* syncing with local edit
*
* Revision 1.4 1999/09/06 06:59:40 dast
* Changed email info
*
* Revision 1.3 1999/08/13 07:34:48 dast
* Changed the URL in the header
*
* Revision 1.2 1999/03/13 00:56:09 dast
* Big changes done due to url.c being split up in X smaller files and that
* the lib is now more stand-alone.
*
* Revision 1.1.1.1 1999/03/11 22:23:34 dast
* Imported sources
*
****************************************************************************/ ****************************************************************************/
#include <stdio.h> #include <stdio.h>

View File

@ -94,6 +94,9 @@
#include "progress.h" #include "progress.h"
#include "base64.h" #include "base64.h"
#include "cookie.h" #include "cookie.h"
#include "strequal.h"
#include "url.h"
#include "ssluse.h"
#define _MPRINTF_REPLACE /* use our functions only */ #define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h> #include <curl/mprintf.h>
@ -115,33 +118,114 @@ bool static checkheaders(struct UrlData *data, char *thisheader)
return FALSE; return FALSE;
} }
UrgError http(struct UrlData *data, char *ppath, char *host, long *bytecount) CURLcode http_connect(struct connectdata *conn)
{ {
/* Send the GET line to the HTTP server */ struct UrlData *data;
struct FormData *sendit=NULL; data=conn->data;
int postsize=0;
UrgError result;
char *buf;
struct Cookie *co = NULL;
char *p_pragma = NULL;
char *p_accept = NULL;
long readbytecount;
long writebytecount;
buf = data->buffer; /* this is our buffer */ /* If we are not using a proxy and we want a secure connection,
* perform SSL initialization & connection now.
* If using a proxy with https, then we must tell the proxy to CONNECT
* us to the host we want to talk to. Only after the connect
* has occured, can we start talking SSL
*/
if (conn->protocol & PROT_HTTPS) {
if (data->bits.httpproxy) {
if ( (data->conf&(CONF_HTTP|CONF_FTP)) && /* OK, now send the connect statment */
(data->conf&CONF_UPLOAD)) { sendf(data->firstsocket, data,
data->conf |= CONF_PUT; "CONNECT %s:%d HTTP/1.0\015\012"
"%s"
"%s"
"\r\n",
data->hostname, data->remote_port,
(data->bits.proxy_user_passwd)?data->ptr_proxyuserpwd:"",
(data->useragent?data->ptr_uagent:"")
);
/* wait for the proxy to send us a HTTP/1.0 200 OK header */
/* Daniel rewrote this part Nov 5 1998 to make it more obvious */
{
int httperror=0;
int subversion=0;
while(GetLine(data->firstsocket, data->buffer, data)) {
if('\r' == data->buffer[0])
break; /* end of headers */
if(2 == sscanf(data->buffer, "HTTP/1.%d %d",
&subversion,
&httperror)) {
;
}
}
if(200 != httperror) {
if(407 == httperror)
/* Added Nov 6 1998 */
failf(data, "Proxy requires authorization!");
else
failf(data, "Received error code %d from proxy", httperror);
return CURLE_READ_ERROR;
}
}
infof (data, "Proxy has replied to CONNECT request\n");
}
/* now, perform the SSL initialization for this socket */
if(UrgSSLConnect (data)) {
return CURLE_SSL_CONNECT_ERROR;
}
} }
#if 0 /* old version */
if((data->conf&(CONF_HTTP|CONF_UPLOAD)) == return CURLE_OK;
(CONF_HTTP|CONF_UPLOAD)) { }
/* enable PUT! */ CURLcode http_done(struct connectdata *conn)
data->conf |= CONF_PUT; {
struct UrlData *data;
long *bytecount = &conn->bytecount;
struct HTTP *http;
data=conn->data;
http=data->proto.http;
if(data->bits.http_formpost) {
*bytecount = http->readbytecount + http->writebytecount;
FormFree(http->sendit); /* Now free that whole lot */
data->fread = http->storefread; /* restore */
data->in = http->in; /* restore */
}
else if(data->bits.http_put) {
*bytecount = http->readbytecount + http->writebytecount;
}
/* TBD: the HTTP struct remains allocated here */
return CURLE_OK;
}
CURLcode http(struct connectdata *conn)
{
struct UrlData *data=conn->data;
char *buf = data->buffer; /* this is a short cut to the buffer */
CURLcode result;
struct HTTP *http;
struct Cookie *co=NULL; /* no cookies from start */
char *ppath = conn->ppath; /* three previous function arguments */
char *host = conn->name;
long *bytecount = &conn->bytecount;
http = (struct HTTP *)malloc(sizeof(struct HTTP));
if(!http)
return CURLE_OUT_OF_MEMORY;
memset(http, 0, sizeof(struct HTTP));
data->proto.http = http;
if ( (conn->protocol&(PROT_HTTP|PROT_FTP)) &&
data->bits.upload) {
data->bits.http_put=1;
} }
#endif
/* The User-Agent string has been built in url.c already, because it might /* The User-Agent string has been built in url.c already, because it might
have been used in the proxy connect, but if we have got a header with have been used in the proxy connect, but if we have got a header with
@ -152,17 +236,17 @@ UrgError http(struct UrlData *data, char *ppath, char *host, long *bytecount)
data->ptr_uagent=NULL; data->ptr_uagent=NULL;
} }
if((data->conf & CONF_USERPWD) && !checkheaders(data, "Authorization:")) { if((data->bits.user_passwd) && !checkheaders(data, "Authorization:")) {
char authorization[512]; char authorization[512];
sprintf(data->buffer, "%s:%s", data->user, data->passwd); sprintf(data->buffer, "%s:%s", data->user, data->passwd);
base64Encode(data->buffer, authorization); base64Encode(data->buffer, authorization);
data->ptr_userpwd = maprintf( "Authorization: Basic %s\015\012", data->ptr_userpwd = maprintf( "Authorization: Basic %s\015\012",
authorization); authorization);
} }
if((data->conf & CONF_RANGE) && !checkheaders(data, "Range:")) { if((data->bits.set_range) && !checkheaders(data, "Range:")) {
data->ptr_rangeline = maprintf("Range: bytes=%s\015\012", data->range); data->ptr_rangeline = maprintf("Range: bytes=%s\015\012", data->range);
} }
if((data->conf & CONF_REFERER) && !checkheaders(data, "Referer:")) { if((data->bits.http_set_referer) && !checkheaders(data, "Referer:")) {
data->ptr_ref = maprintf("Referer: %s\015\012", data->referer); data->ptr_ref = maprintf("Referer: %s\015\012", data->referer);
} }
if(data->cookie && !checkheaders(data, "Cookie:")) { if(data->cookie && !checkheaders(data, "Cookie:")) {
@ -173,16 +257,16 @@ UrgError http(struct UrlData *data, char *ppath, char *host, long *bytecount)
co = cookie_getlist(data->cookies, co = cookie_getlist(data->cookies,
host, host,
ppath, ppath,
data->conf&CONF_HTTPS?TRUE:FALSE); conn->protocol&PROT_HTTPS?TRUE:FALSE);
} }
if ((data->conf & CONF_PROXY) && (!(data->conf & CONF_HTTPS))) { if ((data->bits.httpproxy) && !(conn->protocol&PROT_HTTPS)) {
/* The path sent to the proxy is in fact the entire URL */ /* The path sent to the proxy is in fact the entire URL */
strncpy(ppath, data->url, URL_MAX_LENGTH-1); strncpy(ppath, data->url, URL_MAX_LENGTH-1);
} }
if(data->conf & CONF_HTTPPOST) { if(data->bits.http_formpost) {
/* we must build the whole darned post sequence first, so that we have /* we must build the whole darned post sequence first, so that we have
a size of the whole shebang before we start to send it */ a size of the whole shebang before we start to send it */
sendit = getFormData(data->httppost, &postsize); http->sendit = getFormData(data->httppost, &http->postsize);
} }
if(!checkheaders(data, "Host:")) if(!checkheaders(data, "Host:"))
@ -190,10 +274,10 @@ UrgError http(struct UrlData *data, char *ppath, char *host, long *bytecount)
if(!checkheaders(data, "Pragma:")) if(!checkheaders(data, "Pragma:"))
p_pragma = "Pragma: no-cache\r\n"; http->p_pragma = "Pragma: no-cache\r\n";
if(!checkheaders(data, "Accept:")) if(!checkheaders(data, "Accept:"))
p_accept = "Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*\r\n"; http->p_accept = "Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*\r\n";
do { do {
sendf(data->firstsocket, data, sendf(data->firstsocket, data,
@ -210,19 +294,19 @@ UrgError http(struct UrlData *data, char *ppath, char *host, long *bytecount)
"%s", /* referer */ "%s", /* referer */
data->customrequest?data->customrequest: data->customrequest?data->customrequest:
(data->conf&CONF_NOBODY?"HEAD": (data->bits.no_body?"HEAD":
(data->conf&(CONF_POST|CONF_HTTPPOST))?"POST": (data->bits.http_post || data->bits.http_formpost)?"POST":
(data->conf&CONF_PUT)?"PUT":"GET"), (data->bits.http_put)?"PUT":"GET"),
ppath, ppath,
(data->conf&CONF_PROXYUSERPWD && data->ptr_proxyuserpwd)?data->ptr_proxyuserpwd:"", (data->bits.proxy_user_passwd && data->ptr_proxyuserpwd)?data->ptr_proxyuserpwd:"",
(data->conf&CONF_USERPWD && data->ptr_userpwd)?data->ptr_userpwd:"", (data->bits.user_passwd && data->ptr_userpwd)?data->ptr_userpwd:"",
(data->conf&CONF_RANGE && data->ptr_rangeline)?data->ptr_rangeline:"", (data->bits.set_range && data->ptr_rangeline)?data->ptr_rangeline:"",
(data->useragent && *data->useragent && data->ptr_uagent)?data->ptr_uagent:"", (data->useragent && *data->useragent && data->ptr_uagent)?data->ptr_uagent:"",
(data->ptr_cookie?data->ptr_cookie:""), /* Cookie: <data> */ (data->ptr_cookie?data->ptr_cookie:""), /* Cookie: <data> */
(data->ptr_host?data->ptr_host:""), /* Host: host */ (data->ptr_host?data->ptr_host:""), /* Host: host */
p_pragma?p_pragma:"", http->p_pragma?http->p_pragma:"",
p_accept?p_accept:"", http->p_accept?http->p_accept:"",
(data->conf&CONF_REFERER && data->ptr_ref)?data->ptr_ref:"" /* Referer: <data> <CRLF> */ (data->bits.http_set_referer && data->ptr_ref)?data->ptr_ref:"" /* Referer: <data> <CRLF> */
); );
if(co) { if(co) {
@ -234,9 +318,10 @@ UrgError http(struct UrlData *data, char *ppath, char *host, long *bytecount)
sendf(data->firstsocket, data, sendf(data->firstsocket, data,
"Cookie:"); "Cookie:");
} }
count++;
sendf(data->firstsocket, data, sendf(data->firstsocket, data,
" %s=%s;", co->name, co->value); "%s%s=%s", count?"; ":"", co->name,
co->value);
count++;
} }
co = co->next; /* next cookie please */ co = co->next; /* next cookie please */
} }
@ -284,8 +369,8 @@ UrgError http(struct UrlData *data, char *ppath, char *host, long *bytecount)
data->headers = data->headers->next; data->headers = data->headers->next;
} }
if(data->conf&(CONF_POST|CONF_HTTPPOST)) { if(data->bits.http_post || data->bits.http_formpost) {
if(data->conf & CONF_POST) { if(data->bits.http_post) {
/* this is the simple x-www-form-urlencoded style */ /* this is the simple x-www-form-urlencoded style */
sendf(data->firstsocket, data, sendf(data->firstsocket, data,
"Content-Length: %d\015\012" "Content-Length: %d\015\012"
@ -295,53 +380,39 @@ UrgError http(struct UrlData *data, char *ppath, char *host, long *bytecount)
data->postfields ); data->postfields );
} }
else { else {
struct Form form;
size_t (*storefread)(char *, size_t , size_t , FILE *);
FILE *in;
long conf;
if(FormInit(&form, sendit)) { if(FormInit(&http->form, http->sendit)) {
failf(data, "Internal HTTP POST error!\n"); failf(data, "Internal HTTP POST error!\n");
return URG_HTTP_POST_ERROR; return CURLE_HTTP_POST_ERROR;
} }
storefread = data->fread; /* backup */ http->storefread = data->fread; /* backup */
in = data->in; /* backup */ http->in = data->in; /* backup */
data->fread = data->fread =
(size_t (*)(char *, size_t, size_t, FILE *)) (size_t (*)(char *, size_t, size_t, FILE *))
FormReader; /* set the read function to read from the FormReader; /* set the read function to read from the
generated form data */ generated form data */
data->in = (FILE *)&form; data->in = (FILE *)&http->form;
sendf(data->firstsocket, data, sendf(data->firstsocket, data,
"Content-Length: %d\r\n", "Content-Length: %d\r\n",
postsize-2); http->postsize-2);
pgrsSetUploadSize(data, postsize); pgrsSetUploadSize(data, http->postsize);
#if 0
ProgressInit(data, postsize);
#endif
result = Transfer(data, data->firstsocket, -1, TRUE, &readbytecount, result = Transfer(conn, data->firstsocket, -1, TRUE,
data->firstsocket, &writebytecount); &http->readbytecount,
*bytecount = readbytecount + writebytecount; data->firstsocket,
&http->writebytecount);
FormFree(sendit); /* Now free that whole lot */ if(result) {
FormFree(http->sendit); /* free that whole lot */
if(result)
return result; return result;
}
data->fread = storefread; /* restore */
data->in = in; /* restore */
sendf(data->firstsocket, data,
"\r\n\r\n");
} }
} }
else if(data->conf&CONF_PUT) { else if(data->bits.http_put) {
/* Let's PUT the data to the server! */ /* Let's PUT the data to the server! */
long conf;
if(data->infilesize>0) { if(data->infilesize>0) {
sendf(data->firstsocket, data, sendf(data->firstsocket, data,
@ -352,39 +423,28 @@ UrgError http(struct UrlData *data, char *ppath, char *host, long *bytecount)
sendf(data->firstsocket, data, sendf(data->firstsocket, data,
"\015\012"); "\015\012");
#if 0
ProgressInit(data, data->infilesize);
#endif
pgrsSetUploadSize(data, data->infilesize); pgrsSetUploadSize(data, data->infilesize);
result = Transfer(data, data->firstsocket, -1, TRUE, &readbytecount, result = Transfer(conn, data->firstsocket, -1, TRUE,
data->firstsocket, &writebytecount); &http->readbytecount,
data->firstsocket,
*bytecount = readbytecount + writebytecount; &http->writebytecount);
if(result) if(result)
return result; return result;
} }
else { else {
sendf(data->firstsocket, data, "\r\n"); sendf(data->firstsocket, data, "\r\n");
}
if(0 == *bytecount) {
/* HTTP GET/HEAD download: */ /* HTTP GET/HEAD download: */
result = Transfer(data, data->firstsocket, -1, TRUE, bytecount, result = Transfer(conn, data->firstsocket, -1, TRUE, bytecount,
-1, NULL); /* nothing to upload */ -1, NULL); /* nothing to upload */
} }
if(result) if(result)
return result; return result;
#if 0
ProgressEnd(data);
#endif
pgrsDone(data);
} while (0); /* this is just a left-over from the multiple document download } while (0); /* this is just a left-over from the multiple document download
attempts */ attempts */
return URG_OK; return CURLE_OK;
} }

View File

@ -40,6 +40,9 @@
* *
* ------------------------------------------------------------ * ------------------------------------------------------------
****************************************************************************/ ****************************************************************************/
UrgError http(struct UrlData *data, char *path, char *host, long *bytecountp);
CURLcode http(struct connectdata *conn);
CURLcode http_done(struct connectdata *conn);
CURLcode http_connect(struct connectdata *conn);
#endif #endif

View File

@ -72,7 +72,7 @@
#define DYNA_GET_FUNCTION(type, fnc) \ #define DYNA_GET_FUNCTION(type, fnc) \
(fnc) = (type)DynaGetFunction(#fnc); \ (fnc) = (type)DynaGetFunction(#fnc); \
if ((fnc) == NULL) { \ if ((fnc) == NULL) { \
return URG_FUNCTION_NOT_FOUND; \ return CURLE_FUNCTION_NOT_FOUND; \
} \ } \
/*********************************************************************** /***********************************************************************
@ -129,16 +129,21 @@ static void * DynaGetFunction(char *name)
static int WriteProc(void *param, char *text, int len) static int WriteProc(void *param, char *text, int len)
{ {
struct UrlData *data = (struct UrlData *)param; struct UrlData *data = (struct UrlData *)param;
printf("%s\n", text); data->fwrite(text, 1, strlen(text), data->out);
return 0; return 0;
} }
CURLcode ldap_done(struct connectdata *conn)
{
return CURLE_OK;
}
/*********************************************************************** /***********************************************************************
*/ */
UrgError ldap(struct UrlData *data, char *path, long *bytecount) CURLcode ldap(struct connectdata *conn)
{ {
UrgError status = URG_OK; CURLcode status = CURLE_OK;
int rc; int rc;
void *(*ldap_open)(char *, int); void *(*ldap_open)(char *, int);
int (*ldap_simple_bind_s)(void *, char *, char *); int (*ldap_simple_bind_s)(void *, char *, char *);
@ -152,24 +157,19 @@ UrgError ldap(struct UrlData *data, char *path, long *bytecount)
void *server; void *server;
void *result; void *result;
void *entryIterator; void *entryIterator;
#if 0
char *dn;
char **attrArray;
char *attrIterator;
char *attrString;
void *dummy;
#endif
int ldaptext; int ldaptext;
struct UrlData *data=conn->data;
infof(data, "LDAP: %s %s\n", data->url); infof(data, "LDAP: %s %s\n", data->url);
DynaOpen(); DynaOpen();
if (libldap == NULL) { if (libldap == NULL) {
failf(data, "The needed LDAP library/libraries couldn't be opened"); failf(data, "The needed LDAP library/libraries couldn't be opened");
return URG_LIBRARY_NOT_FOUND; return CURLE_LIBRARY_NOT_FOUND;
} }
ldaptext = data->conf & CONF_FTPASCII; /* This is a dirty hack */ ldaptext = data->bits.ftp_ascii; /* This is a dirty hack */
/* The types are needed because ANSI C distinguishes between /* The types are needed because ANSI C distinguishes between
* pointer-to-object (data) and pointer-to-function. * pointer-to-object (data) and pointer-to-function.
@ -188,17 +188,17 @@ UrgError ldap(struct UrlData *data, char *path, long *bytecount)
if (server == NULL) { if (server == NULL) {
failf(data, "LDAP: Cannot connect to %s:%d", failf(data, "LDAP: Cannot connect to %s:%d",
data->hostname, data->port); data->hostname, data->port);
status = URG_COULDNT_CONNECT; status = CURLE_COULDNT_CONNECT;
} else { } else {
rc = ldap_simple_bind_s(server, data->user, data->passwd); rc = ldap_simple_bind_s(server, data->user, data->passwd);
if (rc != 0) { if (rc != 0) {
failf(data, "LDAP: %s", ldap_err2string(rc)); failf(data, "LDAP: %s", ldap_err2string(rc));
status = URG_LDAP_CANNOT_BIND; status = CURLE_LDAP_CANNOT_BIND;
} else { } else {
rc = ldap_url_search_s(server, data->url, 0, &result); rc = ldap_url_search_s(server, data->url, 0, &result);
if (rc != 0) { if (rc != 0) {
failf(data, "LDAP: %s", ldap_err2string(rc)); failf(data, "LDAP: %s", ldap_err2string(rc));
status = URG_LDAP_SEARCH_FAILED; status = CURLE_LDAP_SEARCH_FAILED;
} else { } else {
for (entryIterator = ldap_first_entry(server, result); for (entryIterator = ldap_first_entry(server, result);
entryIterator; entryIterator;
@ -210,7 +210,7 @@ UrgError ldap(struct UrlData *data, char *path, long *bytecount)
"", 0, 0); "", 0, 0);
if (rc != 0) { if (rc != 0) {
failf(data, "LDAP: %s", ldap_err2string(rc)); failf(data, "LDAP: %s", ldap_err2string(rc));
status = URG_LDAP_SEARCH_FAILED; status = CURLE_LDAP_SEARCH_FAILED;
} }
} else { } else {
rc = ldap_entry2html(server, NULL, entryIterator, NULL, rc = ldap_entry2html(server, NULL, entryIterator, NULL,
@ -218,7 +218,7 @@ UrgError ldap(struct UrlData *data, char *path, long *bytecount)
"", 0, 0, NULL, NULL); "", 0, 0, NULL, NULL);
if (rc != 0) { if (rc != 0) {
failf(data, "LDAP: %s", ldap_err2string(rc)); failf(data, "LDAP: %s", ldap_err2string(rc));
status = URG_LDAP_SEARCH_FAILED; status = CURLE_LDAP_SEARCH_FAILED;
} }
} }
} }

View File

@ -40,6 +40,7 @@
* *
* ------------------------------------------------------------ * ------------------------------------------------------------
****************************************************************************/ ****************************************************************************/
UrgError ldap(struct UrlData *data, char *path, long *bytecount); CURLcode ldap(struct connectdata *conn);
CURLcode ldap_done(struct connectdata *conn);
#endif /* __LDAP_H */ #endif /* __LDAP_H */

View File

@ -56,6 +56,7 @@
#include "setup.h" #include "setup.h"
#include "getenv.h" #include "getenv.h"
#include "strequal.h"
/* Debug this single source file with: /* Debug this single source file with:
'make netrc' then run './netrc'! 'make netrc' then run './netrc'!

View File

@ -118,7 +118,7 @@ void pgrsDone(struct UrlData *data)
void pgrsMode(struct UrlData *data, int mode) void pgrsMode(struct UrlData *data, int mode)
{ {
/* mode should include a hidden mode as well */ /* mode should include a hidden mode as well */
if(data->conf&(CONF_NOPROGRESS|CONF_MUTE)) if(data->bits.hide_progress || data->bits.mute)
data->progress.flags |= PGRS_HIDE; /* don't show anything */ data->progress.flags |= PGRS_HIDE; /* don't show anything */
else { else {
data->progress.mode = mode; /* store type */ data->progress.mode = mode; /* store type */
@ -187,10 +187,36 @@ void pgrsSetUploadSize(struct UrlData *data, double size)
*/ */
void pgrsUpdate(struct UrlData *data) int pgrsUpdate(struct UrlData *data)
{ {
struct timeval now; struct timeval now;
char max5[6][6];
double dlpercen=0;
double ulpercen=0;
double total_percen=0;
double total_transfer;
double total_expected_transfer;
#define CURR_TIME 5
static double speeder[ CURR_TIME ];
static int speeder_c=0;
int nowindex = speeder_c% CURR_TIME;
int checkindex;
int count;
char time_left[10];
char time_total[10];
char time_current[10];
double ulestimate=0;
double dlestimate=0;
double total_estimate;
if(data->progress.flags & PGRS_HIDE) if(data->progress.flags & PGRS_HIDE)
; /* We do enter this function even if we don't wanna see anything, since ; /* We do enter this function even if we don't wanna see anything, since
this is were lots of the calculations are being made that will be used this is were lots of the calculations are being made that will be used
@ -206,133 +232,109 @@ void pgrsUpdate(struct UrlData *data)
now = tvnow(); /* what time is it */ now = tvnow(); /* what time is it */
switch(data->progress.mode) { if(data->progress.lastshow == tvlong(now))
case CURL_PROGRESS_STATS: return 0; /* never update this more than once a second if the end isn't
default: reached */
{ data->progress.lastshow = now.tv_sec;
char max5[6][6];
double dlpercen=0;
double ulpercen=0;
double total_percen=0;
double total_transfer; /* The exact time spent so far */
double total_expected_transfer; data->progress.timespent = tvdiff (now, data->progress.start);
#define CURR_TIME 5 /* The average download speed this far */
data->progress.dlspeed = data->progress.downloaded/(data->progress.timespent!=0.0?data->progress.timespent:1.0);
static double speeder[ CURR_TIME ]; /* The average upload speed this far */
static int speeder_c=0; data->progress.ulspeed = data->progress.uploaded/(data->progress.timespent!=0.0?data->progress.timespent:1.0);
int nowindex = speeder_c% CURR_TIME; /* Let's do the "current speed" thing, which should use the fastest
int checkindex;
int count;
char time_left[10];
char time_total[10];
char time_current[10];
double ulestimate=0;
double dlestimate=0;
double total_estimate;
if(data->progress.lastshow == tvlong(now))
return; /* never update this more than once a second if the end isn't
reached */
data->progress.lastshow = now.tv_sec;
/* The exact time spent so far */
data->progress.timespent = tvdiff (now, data->progress.start);
/* The average download speed this far */
data->progress.dlspeed = data->progress.downloaded/(data->progress.timespent!=0.0?data->progress.timespent:1.0);
/* The average upload speed this far */
data->progress.ulspeed = data->progress.uploaded/(data->progress.timespent!=0.0?data->progress.timespent:1.0);
/* Let's do the "current speed" thing, which should use the fastest
of the dl/ul speeds */ of the dl/ul speeds */
speeder[ nowindex ] = data->progress.downloaded>data->progress.uploaded? speeder[ nowindex ] = data->progress.downloaded>data->progress.uploaded?
data->progress.downloaded:data->progress.uploaded; data->progress.downloaded:data->progress.uploaded;
speeder_c++; /* increase */ speeder_c++; /* increase */
count = ((speeder_c>=CURR_TIME)?CURR_TIME:speeder_c) - 1; count = ((speeder_c>=CURR_TIME)?CURR_TIME:speeder_c) - 1;
checkindex = (speeder_c>=CURR_TIME)?speeder_c%CURR_TIME:0; checkindex = (speeder_c>=CURR_TIME)?speeder_c%CURR_TIME:0;
/* find out the average speed the last CURR_TIME seconds */ /* find out the average speed the last CURR_TIME seconds */
data->progress.current_speed = data->progress.current_speed =
(speeder[nowindex]-speeder[checkindex])/(count?count:1); (speeder[nowindex]-speeder[checkindex])/(count?count:1);
if(data->progress.flags & PGRS_HIDE) if(data->progress.flags & PGRS_HIDE)
return; return 0;
else if(data->fprogress) {
return data->fprogress(data->progress_client,
data->progress.size_dl,
data->progress.downloaded,
data->progress.size_ul,
data->progress.uploaded);
}
/* Figure out the estimated time of arrival for the upload */ /* Figure out the estimated time of arrival for the upload */
if(data->progress.flags & PGRS_UL_SIZE_KNOWN) { if(data->progress.flags & PGRS_UL_SIZE_KNOWN) {
if(!data->progress.ulspeed) if(!data->progress.ulspeed)
data->progress.ulspeed=1; data->progress.ulspeed=1;
ulestimate = data->progress.size_ul / data->progress.ulspeed; ulestimate = data->progress.size_ul / data->progress.ulspeed;
ulpercen = (data->progress.uploaded / data->progress.size_ul)*100; ulpercen = (data->progress.uploaded / data->progress.size_ul)*100;
} }
/* ... and the download */ /* ... and the download */
if(data->progress.flags & PGRS_DL_SIZE_KNOWN) { if(data->progress.flags & PGRS_DL_SIZE_KNOWN) {
if(!data->progress.dlspeed) if(!data->progress.dlspeed)
data->progress.dlspeed=1; data->progress.dlspeed=1;
dlestimate = data->progress.size_dl / data->progress.dlspeed; dlestimate = data->progress.size_dl / data->progress.dlspeed;
dlpercen = (data->progress.downloaded / data->progress.size_dl)*100; dlpercen = (data->progress.downloaded / data->progress.size_dl)*100;
} }
/* Now figure out which of them that is slower and use for the for /* Now figure out which of them that is slower and use for the for
total estimate! */ total estimate! */
total_estimate = ulestimate>dlestimate?ulestimate:dlestimate; total_estimate = ulestimate>dlestimate?ulestimate:dlestimate;
/* If we have a total estimate, we can display that and the expected /* If we have a total estimate, we can display that and the expected
time left */ time left */
if(total_estimate) { if(total_estimate) {
time2str(time_left, total_estimate-(int) data->progress.timespent); time2str(time_left, total_estimate-(int) data->progress.timespent);
time2str(time_total, total_estimate); time2str(time_total, total_estimate);
} }
else { else {
/* otherwise we blank those times */ /* otherwise we blank those times */
strcpy(time_left, "--:--:--"); strcpy(time_left, "--:--:--");
strcpy(time_total, "--:--:--"); strcpy(time_total, "--:--:--");
} }
/* The time spent so far is always known */ /* The time spent so far is always known */
time2str(time_current, data->progress.timespent); time2str(time_current, data->progress.timespent);
/* Get the total amount of data expected to get transfered */ /* Get the total amount of data expected to get transfered */
total_expected_transfer = total_expected_transfer =
(data->progress.flags & PGRS_UL_SIZE_KNOWN? (data->progress.flags & PGRS_UL_SIZE_KNOWN?
data->progress.size_ul:data->progress.uploaded)+ data->progress.size_ul:data->progress.uploaded)+
(data->progress.flags & PGRS_DL_SIZE_KNOWN? (data->progress.flags & PGRS_DL_SIZE_KNOWN?
data->progress.size_dl:data->progress.downloaded); data->progress.size_dl:data->progress.downloaded);
/* We have transfered this much so far */ /* We have transfered this much so far */
total_transfer = data->progress.downloaded + data->progress.uploaded; total_transfer = data->progress.downloaded + data->progress.uploaded;
/* Get the percentage of data transfered so far */ /* Get the percentage of data transfered so far */
if(total_expected_transfer) if(total_expected_transfer)
total_percen=(double)(total_transfer/total_expected_transfer)*100; total_percen=(double)(total_transfer/total_expected_transfer)*100;
fprintf(stderr,
"\r%3d %s %3d %s %3d %s %s %s %s %s %s %s",
(int)total_percen, /* total % */
max5data(total_expected_transfer, max5[2]), /* total size */
(int)dlpercen, /* rcvd % */
max5data(data->progress.downloaded, max5[0]), /* rcvd size */
(int)ulpercen, /* xfer % */
max5data(data->progress.uploaded, max5[1]), /* xfer size */
max5data(data->progress.dlspeed, max5[3]), /* avrg dl speed */
max5data(data->progress.ulspeed, max5[4]), /* avrg ul speed */
time_total, /* total time */
time_current, /* current time */
time_left, /* time left */
max5data(data->progress.current_speed, max5[5]) /* current speed */
);
fprintf(stderr,
"\r%3d %s %3d %s %3d %s %s %s %s %s %s %s",
(int)total_percen, /* total % */
max5data(total_expected_transfer, max5[2]), /* total size */
(int)dlpercen, /* rcvd % */
max5data(data->progress.downloaded, max5[0]), /* rcvd size */
(int)ulpercen, /* xfer % */
max5data(data->progress.uploaded, max5[1]), /* xfer size */
max5data(data->progress.dlspeed, max5[3]), /* avrg dl speed */
max5data(data->progress.ulspeed, max5[4]), /* avrg ul speed */
time_total, /* total time */
time_current, /* current time */
time_left, /* time left */
max5data(data->progress.current_speed, max5[5]) /* current speed */
);
}
break;
#if 0 #if 0
case CURL_PROGRESS_BAR: case CURL_PROGRESS_BAR:
/* original progress bar code by Lars Aas */ /* original progress bar code by Lars Aas */
@ -365,7 +367,8 @@ void pgrsUpdate(struct UrlData *data)
prev = point; prev = point;
break; break;
#endif #endif
}
return 0;
} }

View File

@ -52,13 +52,14 @@ typedef enum {
TIMER_LAST /* must be last */ TIMER_LAST /* must be last */
} timerid; } timerid;
void pgrsDone(struct UrlData *data);
void pgrsMode(struct UrlData *data, int mode); void pgrsMode(struct UrlData *data, int mode);
void pgrsStartNow(struct UrlData *data); void pgrsStartNow(struct UrlData *data);
void pgrsSetDownloadSize(struct UrlData *data, double size); void pgrsSetDownloadSize(struct UrlData *data, double size);
void pgrsSetUploadSize(struct UrlData *data, double size); void pgrsSetUploadSize(struct UrlData *data, double size);
void pgrsSetDownloadCounter(struct UrlData *data, double size); void pgrsSetDownloadCounter(struct UrlData *data, double size);
void pgrsSetUploadCounter(struct UrlData *data, double size); void pgrsSetUploadCounter(struct UrlData *data, double size);
void pgrsUpdate(struct UrlData *data); int pgrsUpdate(struct UrlData *data);
void pgrsTime(struct UrlData *data, timerid timer); void pgrsTime(struct UrlData *data, timerid timer);

View File

@ -61,7 +61,7 @@
void infof(struct UrlData *data, char *fmt, ...) void infof(struct UrlData *data, char *fmt, ...)
{ {
va_list ap; va_list ap;
if(data->conf & CONF_VERBOSE) { if(data->bits.verbose) {
va_start(ap, fmt); va_start(ap, fmt);
fputs("* ", data->err); fputs("* ", data->err);
vfprintf(data->err, fmt, ap); vfprintf(data->err, fmt, ap);
@ -95,7 +95,7 @@ int sendf(int fd, struct UrlData *data, char *fmt, ...)
va_end(ap); va_end(ap);
if(!s) if(!s)
return 0; /* failure */ return 0; /* failure */
if(data->conf & CONF_VERBOSE) if(data->bits.verbose)
fprintf(data->err, "> %s", s); fprintf(data->err, "> %s", s);
#ifndef USE_SSLEAY #ifndef USE_SSLEAY
bytes_written = swrite(fd, s, strlen(s)); bytes_written = swrite(fd, s, strlen(s));

View File

@ -57,8 +57,6 @@
#endif #endif
#endif #endif
#ifndef OS #ifndef OS
#ifdef WIN32 #ifdef WIN32
#define OS "win32" #define OS "win32"
@ -99,6 +97,7 @@ defined(HAVE_LIBSSL) && defined(HAVE_LIBCRYPTO)
#endif #endif
#endif #endif
#if 0
#ifdef HAVE_STRCASECMP #ifdef HAVE_STRCASECMP
#define strnequal(x,y,z) !(strncasecmp)(x,y,z) #define strnequal(x,y,z) !(strncasecmp)(x,y,z)
#define strequal(x,y) !(strcasecmp)(x,y) #define strequal(x,y) !(strcasecmp)(x,y)
@ -107,6 +106,7 @@ defined(HAVE_LIBSSL) && defined(HAVE_LIBCRYPTO)
#define strnequal(x,y,z) !strnicmp(x,y,z) #define strnequal(x,y,z) !strnicmp(x,y,z)
#define strequal(x,y) !stricmp(x,y) #define strequal(x,y) !stricmp(x,y)
#endif #endif
#endif
/* Below we define four functions. They should /* Below we define four functions. They should
1. close a socket 1. close a socket

View File

@ -48,7 +48,7 @@
#include "sendf.h" #include "sendf.h"
#include "speedcheck.h" #include "speedcheck.h"
UrgError speedcheck(struct UrlData *data, CURLcode speedcheck(struct UrlData *data,
struct timeval now) struct timeval now)
{ {
static struct timeval keeps_speed; static struct timeval keeps_speed;
@ -69,13 +69,13 @@ UrgError speedcheck(struct UrlData *data,
"Less than %d bytes/sec transfered the last %d seconds", "Less than %d bytes/sec transfered the last %d seconds",
data->low_speed_limit, data->low_speed_limit,
data->low_speed_time); data->low_speed_time);
return URG_OPERATION_TIMEOUTED; return CURLE_OPERATION_TIMEOUTED;
} }
} }
else { else {
/* we keep up the required speed all right */ /* we keep up the required speed all right */
keeps_speed = now; keeps_speed = now;
} }
return URG_OK; return CURLE_OK;
} }

View File

@ -44,7 +44,7 @@
#include "timeval.h" #include "timeval.h"
UrgError speedcheck(struct UrlData *data, CURLcode speedcheck(struct UrlData *data,
struct timeval now); struct timeval now);
#endif #endif

View File

@ -38,6 +38,12 @@
* ------------------------------------------------------------ * ------------------------------------------------------------
****************************************************************************/ ****************************************************************************/
/*
* The original SSL code was written by
* Linas Vepstas <linas@linas.org> and Sampo Kellomaki <sampo@iki.fi>
*/
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>

View File

@ -225,7 +225,7 @@ static void printoption(struct UrlData *data,
char *fmt; char *fmt;
char *opt; char *opt;
if (data->conf & CONF_VERBOSE) if (data->bits.verbose)
{ {
if (cmd == IAC) if (cmd == IAC)
{ {
@ -628,7 +628,7 @@ static void printsub(struct UrlData *data,
{ {
int i = 0; int i = 0;
if (data->conf & CONF_VERBOSE) if (data->bits.verbose)
{ {
if (direction) if (direction)
{ {
@ -871,23 +871,29 @@ void telwrite(struct UrlData *data,
} }
} }
UrgError telnet(struct UrlData *data) CURLcode telnet_done(struct connectdata *conn)
{ {
int sockfd = data->firstsocket; return CURLE_OK;
fd_set readfd; }
fd_set keepfd;
bool keepon = TRUE; CURLcode telnet(struct connectdata *conn)
char *buf = data->buffer; {
int nread; struct UrlData *data = conn->data;
int sockfd = data->firstsocket;
fd_set readfd;
fd_set keepfd;
init_telnet(data); bool keepon = TRUE;
char *buf = data->buffer;
int nread;
init_telnet(data);
FD_ZERO (&readfd); /* clear it */ FD_ZERO (&readfd); /* clear it */
FD_SET (sockfd, &readfd); FD_SET (sockfd, &readfd);
FD_SET (1, &readfd); FD_SET (1, &readfd);
keepfd = readfd; keepfd = readfd;
while (keepon) while (keepon)
{ {
@ -931,7 +937,7 @@ UrgError telnet(struct UrlData *data)
telrcv(data, (unsigned char *)buf, nread); telrcv(data, (unsigned char *)buf, nread);
} }
} }
return URG_OK; return CURLE_OK;
} }

View File

@ -40,6 +40,7 @@
* *
* ------------------------------------------------------------ * ------------------------------------------------------------
****************************************************************************/ ****************************************************************************/
UrgError telnet(struct UrlData *data); CURLcode telnet(struct connectdata *conn);
CURLcode telnet_done(struct connectdata *conn);
#endif #endif

1177
lib/url.c

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,44 @@
#ifndef __URL_H
#define __URL_H
/*****************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
* License for the specific language governing rights and limitations
* under the License.
*
* The Original Code is Curl.
*
* The Initial Developer of the Original Code is Daniel Stenberg.
*
* Portions created by the Initial Developer are Copyright (C) 1998.
* All Rights Reserved.
*
* ------------------------------------------------------------
* Main author:
* - Daniel Stenberg <Daniel.Stenberg@haxx.nu>
*
* http://curl.haxx.nu
*
* $Source$
* $Revision$
* $Date$
* $Author$
* $State$
* $Locker$
*
* ------------------------------------------------------------
****************************************************************************/
int GetLine(int sockfd, char *buf, struct UrlData *data);
#endif

View File

@ -67,6 +67,7 @@
#define CURL_DEFAULT_PASSWORD "curl_by_Daniel.Stenberg@haxx.nu" #define CURL_DEFAULT_PASSWORD "curl_by_Daniel.Stenberg@haxx.nu"
#include "cookie.h" #include "cookie.h"
#include "formdata.h"
#ifdef USE_SSLEAY #ifdef USE_SSLEAY
/* SSLeay stuff usually in /usr/local/ssl/include */ /* SSLeay stuff usually in /usr/local/ssl/include */
@ -87,8 +88,12 @@
#endif #endif
#endif #endif
#include <netinet/in.h>
#include "timeval.h" #include "timeval.h"
/* Download buffer size, keep it fairly big for speed reasons */ /* Download buffer size, keep it fairly big for speed reasons */
#define BUFSIZE (1024*50) #define BUFSIZE (1024*50)
@ -96,6 +101,88 @@
of need. */ of need. */
#define HEADERSIZE 256 #define HEADERSIZE 256
#ifndef MAX
#define MAX(x,y) ((x)>(y)?(x):(y))
#endif
typedef enum {
STRUCT_NONE,
STRUCT_OPEN,
STRUCT_CONNECT,
STRUCT_LAST
} Handle;
typedef enum {
CONN_NONE, /* illegal state */
CONN_INIT, /* curl_connect() has been called */
CONN_DO, /* curl_do() has been called successfully */
CONN_DONE, /* curl_done() has been called successfully */
CONN_ERROR, /* and error has occurred */
CONN_LAST /* illegal state */
} ConnState;
/*
* The connectdata struct contains all fields and variables that should be
* unique for an entire connection.
*/
struct connectdata {
/**** Fields set when inited and not modified again */
/* To better see what kind of struct that is passed as input, *ALL* publicly
returned handles MUST have this initial 'Handle'. */
Handle handle; /* struct identifier */
struct UrlData *data; /* link to the root CURL struct */
/**** curl_connect() phase fields */
ConnState state; /* for state dependent actions */
long protocol; /* PROT_* flags concerning the protocol set */
#define PROT_MISSING (1<<0)
#define PROT_GOPHER (1<<1)
#define PROT_HTTP (1<<2)
#define PROT_HTTPS (1<<3)
#define PROT_FTP (1<<4)
#define PROT_TELNET (1<<5)
#define PROT_DICT (1<<6)
#define PROT_LDAP (1<<7)
#define PROT_FILE (1<<8)
struct hostent *hp;
struct sockaddr_in serv_addr;
char proto[64];
char gname[256];
char *name;
char path[URL_MAX_LENGTH];
char *ppath;
long bytecount;
struct timeval now;
/* These two functions MUST be set by the curl_connect() function to be
be protocol dependent */
CURLcode (*curl_do)(struct connectdata *connect);
CURLcode (*curl_done)(struct connectdata *connect);
/* This function *MAY* be set to a protocol-dependent function that is run
* after the connect() and everything is done, as a step in the connection.
*/
CURLcode (*curl_connect)(struct connectdata *connect);
/**** curl_get() phase fields */
/* READ stuff */
int sockfd; /* socket to read from or -1 */
int size; /* -1 if unknown at this point */
bool getheader; /* TRUE if header parsing is wanted */
long *bytecountp; /* return number of bytes read or NULL */
/* WRITE stuff */
int writesockfd; /* socket to write to, it may very well be
the same we read from. -1 disables */
long *writebytecountp; /* return number of bytes written or NULL */
};
struct Progress { struct Progress {
long lastshow; /* time() of the last displayed progress meter or NULL to long lastshow; /* time() of the last displayed progress meter or NULL to
force redraw at next call */ force redraw at next call */
@ -121,42 +208,160 @@ struct Progress {
int httpcode; int httpcode;
}; };
/****************************************************************************
* HTTP unique setup
***************************************************************************/
struct HTTP {
struct FormData *sendit;
int postsize;
char *p_pragma;
char *p_accept;
long readbytecount;
long writebytecount;
/* For FORM posting */
struct Form form;
size_t (*storefread)(char *, size_t , size_t , FILE *);
FILE *in;
};
/****************************************************************************
* FTP unique setup
***************************************************************************/
struct FTP {
long *bytecountp;
char *user;
char *passwd;
char *urlpath; /* the originally given path part of the URL */
char *dir; /* decoded directory */
char *file; /* decoded file */
};
struct Configbits {
bool ftp_append;
bool ftp_ascii;
bool http_post;
bool http_set_referer;
bool http_fail_on_error;
bool http_formpost;
bool http_include_header;
bool http_follow_location;
bool http_put;
bool no_body;
bool ftp_list_only;
bool use_netrc;
bool ftp_use_port;
bool set_port;
bool set_range;
bool mute;
bool hide_progress;
bool upload;
bool user_passwd;
bool proxy_user_passwd;
bool verbose;
bool httpproxy;
};
typedef size_t (*progress_callback)(void *clientp,
size_t dltotal,
size_t dlnow,
size_t ultotal,
size_t ulnow);
typedef size_t (*write_callback)(char *buffer,
size_t size,
size_t nitems,
FILE *outstream);
typedef size_t (*read_callback)(char *buffer,
size_t size,
size_t nitems,
FILE *instream);
/* What type of interface that intiated this struct */
typedef enum {
CURLI_NONE,
CURLI_EASY,
CURLI_NORMAL,
CURLI_LAST
} CurlInterface;
/*
* As of April 11, 2000 we're now trying to split up the urldata struct in
* three different parts:
*
* (Global)
* 1 - No matter how many hosts and requests that are being performed, this
* goes for all of them.
*
* (Session)
* 2 - Host and protocol-specific. No matter if we do several transfers to and
* from this host, these variables stay the same.
*
* (Request)
* 3 - Request-specific. Variables that are of interest for this particular
* transfer being made right now.
*
*/
struct UrlData { struct UrlData {
Handle handle; /* struct identifier */
CurlInterface interface;
/*************** Global - specific items ************/
FILE *err; /* the stderr writes goes here */
char *errorbuffer; /* store failure messages in here */
/*************** Session - specific items ************/
char *proxy; /* if proxy, set it here, set CONF_PROXY to use this */
char *proxyuserpwd; /* Proxy <user:password>, if used */
/*************** Request - specific items ************/
union {
struct HTTP *http;
struct HTTP *gopher; /* alias, just for the sake of being more readable */
struct HTTP *https; /* alias, just for the sake of being more readable */
struct FTP *ftp;
#if 0 /* no need for special ones for these: */
struct TELNET *telnet;
struct FILE *file;
struct LDAP *ldap;
struct DICT *dict;
#endif
void *generic;
} proto;
FILE *out; /* the fetched file goes here */ FILE *out; /* the fetched file goes here */
FILE *in; /* the uploaded file is read from here */ FILE *in; /* the uploaded file is read from here */
FILE *err; /* the stderr writes goes here */
FILE *writeheader; /* write the header to this is non-NULL */ FILE *writeheader; /* write the header to this is non-NULL */
char *url; /* what to get */ char *url; /* what to get */
char *freethis; /* if non-NULL, an allocated string for the URL */ char *freethis; /* if non-NULL, an allocated string for the URL */
char *hostname; /* hostname to contect, as parsed from url */ char *hostname; /* hostname to connect, as parsed from url */
unsigned short port; /* which port to use (if non-protocol bind) set unsigned short port; /* which port to use (if non-protocol bind) set
CONF_PORT to use this */ CONF_PORT to use this */
unsigned short remote_port; /* what remote port to connect to, not the proxy unsigned short remote_port; /* what remote port to connect to, not the proxy
port! */ port! */
char *proxy; /* if proxy, set it here, set CONF_PROXY to use this */ struct Configbits bits; /* new-style (v7) flag data */
long conf; /* configure flags */
char *userpwd; /* <user:password>, if used */ char *userpwd; /* <user:password>, if used */
char *proxyuserpwd; /* Proxy <user:password>, if used */
char *range; /* range, if used. See README for detailed specification on char *range; /* range, if used. See README for detailed specification on
this syntax. */ this syntax. */
char *postfields; /* if POST, set the fields' values here */ char *postfields; /* if POST, set the fields' values here */
char *referer; char *referer;
char *errorbuffer; /* store failure messages in here */
char *useragent; /* User-Agent string */ char *useragent; /* User-Agent string */
char *ftpport; /* port to send with the PORT command */ char *ftpport; /* port to send with the PORT command */
/* function that stores the output:*/ /* function that stores the output:*/
size_t (*fwrite)(char *buffer, write_callback fwrite;
size_t size,
size_t nitems,
FILE *outstream);
/* function that reads the input:*/ /* function that reads the input:*/
size_t (*fread)(char *buffer, read_callback fread;
size_t size,
size_t nitems, /* function that wants progress information */
FILE *outstream); progress_callback fprogress;
void *progress_client; /* pointer to pass to the progress callback */
long timeout; /* in seconds, 0 means no timeout */ long timeout; /* in seconds, 0 means no timeout */
long infilesize; /* size of file to upload, -1 means unknown */ long infilesize; /* size of file to upload, -1 means unknown */

View File

@ -58,7 +58,7 @@ char *curl_version(void)
#ifdef USE_SSLEAY #ifdef USE_SSLEAY
#if (SSLEAY_VERSION_NUMBER >= 0x900000) #if (SSLEAY_VERSION_NUMBER >= 0x900000)
sprintf(ptr, " (SSL %x.%x.%x)", sprintf(ptr, " (SSL %lx.%lx.%lx)",
(SSLEAY_VERSION_NUMBER>>28)&0xff, (SSLEAY_VERSION_NUMBER>>28)&0xff,
(SSLEAY_VERSION_NUMBER>>20)&0xff, (SSLEAY_VERSION_NUMBER>>20)&0xff,
(SSLEAY_VERSION_NUMBER>>12)&0xf); (SSLEAY_VERSION_NUMBER>>12)&0xf);

View File

@ -41,6 +41,7 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include "strequal.h"
#include "writeout.h" #include "writeout.h"
typedef enum { typedef enum {

View File

@ -1,3 +1,5 @@
#ifndef __WRITEOUT_H
#define __WRITEOUT_H
/***************************************************************************** /*****************************************************************************
* _ _ ____ _ * _ _ ____ _
* Project ___| | | | _ \| | * Project ___| | | | _ \| |
@ -41,3 +43,5 @@
#include "urldata.h" #include "urldata.h"
void WriteOut(struct UrlData *data); void WriteOut(struct UrlData *data);
#endif

13
maketgz
View File

@ -7,15 +7,24 @@ read version
libversion="$version" libversion="$version"
#
# Now we have a section to get the major, minor and patch number from the
# full version string. We create a single hexadecimal number from it '0xMMmmpp'
#
perl='$a=<STDIN>;@p=split("\\.",$a);for(0..2){printf STDOUT ("%02x",$p[0+$_]);}';
numeric=`echo $libversion | perl -e "$perl"`
echo "CURL version number?" echo "CURL version number?"
read curlversion read curlversion
HEADER=include/curl/curl.h HEADER=include/curl/curl.h
CHEADER=src/version.h CHEADER=src/version.h
# Replace version number in header file: # Replace version number in header file:
sed 's/#define LIBCURL_VERSION.*/#define LIBCURL_VERSION "'$libversion'"/g' $HEADER >$HEADER.new sed -e 's/^#define LIBCURL_VERSION .*/#define LIBCURL_VERSION "'$libversion'"/g' \
-e 's/^#define LIBCURL_VERSION_NUM .*/#define LIBCURL_VERSION_NUM 0x'$numeric'/g' \
$HEADER >$HEADER.new
# Save old header file # Save old header file
cp -p $HEADER $HEADER.old cp -p $HEADER $HEADER.old

View File

@ -4,7 +4,7 @@
# Some flags needed when trying to cause warnings ;-) # Some flags needed when trying to cause warnings ;-)
# CFLAGS = -Wall -pedantic # CFLAGS = -Wall -pedantic
CPPFLAGS = -DGLOBURL -DCURL_SEPARATORS #CPPFLAGS = -DGLOBURL -DCURL_SEPARATORS
INCLUDES = -I$(top_srcdir)/include INCLUDES = -I$(top_srcdir)/include

View File

@ -2,6 +2,9 @@
/* Define if you have the strcasecmp function. */ /* Define if you have the strcasecmp function. */
/*#define HAVE_STRCASECMP 1*/ /*#define HAVE_STRCASECMP 1*/
/* Define if you have the stricmp function. */
#define HAVE_STRICMP 1
/* Define cpu-machine-OS */ /* Define cpu-machine-OS */
#define OS "win32" #define OS "win32"

File diff suppressed because it is too large Load Diff

View File

@ -46,6 +46,8 @@
#include <ctype.h> #include <ctype.h>
#include <curl/curl.h> #include <curl/curl.h>
#include <curl/types.h> /* new for v7 */
#include <curl/easy.h> /* new for v7 */
#include <curl/mprintf.h> #include <curl/mprintf.h>
#include "../lib/getdate.h" #include "../lib/getdate.h"
@ -71,6 +73,25 @@
#include <unistd.h> #include <unistd.h>
#endif #endif
/* Just a set of bits */
#define CONF_DEFAULT 0
#define CONF_VERBOSE (1<<5) /* talk a lot */
#define CONF_HEADER (1<<8) /* throw the header out too */
#define CONF_NOPROGRESS (1<<10) /* shut off the progress meter */
#define CONF_NOBODY (1<<11) /* use HEAD to get http document */
#define CONF_FAILONERROR (1<<12) /* no output on http error codes >= 300 */
#define CONF_UPLOAD (1<<14) /* this is an upload */
#define CONF_POST (1<<15) /* HTTP POST method */
#define CONF_FTPLISTONLY (1<<16) /* Use NLST when listing ftp dir */
#define CONF_FTPAPPEND (1<<20) /* Append instead of overwrite on upload! */
#define CONF_NETRC (1<<22) /* read user+password from .netrc */
#define CONF_FOLLOWLOCATION (1<<23) /* use Location: Luke! */
#define CONF_FTPASCII (1<<24) /* use TYPE A for transfer */
#define CONF_HTTPPOST (1<<25) /* multipart/form-data HTTP POST */
#define CONF_PUT (1<<27) /* PUT the input file */
#define CONF_MUTE (1<<28) /* force NOPROGRESS */
#ifndef HAVE_STRDUP #ifndef HAVE_STRDUP
/* Ultrix doesn't have strdup(), so make a quick clone: */ /* Ultrix doesn't have strdup(), so make a quick clone: */
char *strdup(char *str) char *strdup(char *str)
@ -113,7 +134,7 @@ static UrgError win32_init(void)
if (err != 0) if (err != 0)
/* Tell the user that we couldn't find a useable */ /* Tell the user that we couldn't find a useable */
/* winsock.dll. */ /* winsock.dll. */
return URG_FAILED_INIT; return CURLE_FAILED_INIT;
/* Confirm that the Windows Sockets DLL supports 1.1.*/ /* Confirm that the Windows Sockets DLL supports 1.1.*/
/* Note that if the DLL supports versions greater */ /* Note that if the DLL supports versions greater */
@ -127,13 +148,13 @@ static UrgError win32_init(void)
/* winsock.dll. */ /* winsock.dll. */
WSACleanup(); WSACleanup();
return URG_FAILED_INIT; return CURLE_FAILED_INIT;
} }
return URG_OK; return CURLE_OK;
} }
/* The Windows Sockets DLL is acceptable. Proceed. */ /* The Windows Sockets DLL is acceptable. Proceed. */
#else #else
static UrgError win32_init(void) { return URG_OK; } static CURLcode win32_init(void) { return CURLE_OK; }
#define win32_cleanup() #define win32_cleanup()
#endif #endif
@ -143,7 +164,7 @@ static UrgError win32_init(void) { return URG_OK; }
* _any_ libcurl usage. If this fails, *NO* libcurl functions may be * _any_ libcurl usage. If this fails, *NO* libcurl functions may be
* used, or havoc may be the result. * used, or havoc may be the result.
*/ */
UrgError main_init(void) CURLcode main_init(void)
{ {
return win32_init(); return win32_init();
} }
@ -297,7 +318,10 @@ static void GetStr(char **string,
{ {
if(*string) if(*string)
free(*string); free(*string);
*string = strdup(value); if(value && *value)
*string = strdup(value);
else
*string = NULL;
} }
static char *file2string(FILE *file) static char *file2string(FILE *file)
@ -420,7 +444,7 @@ static int getparameter(char *flag, /* f or -long-flag */
if(parse) { if(parse) {
/* this is the second match, we can't continue! */ /* this is the second match, we can't continue! */
helpf("option --%s is ambiguous\n", &flag[1]); helpf("option --%s is ambiguous\n", &flag[1]);
return URG_FAILED_INIT; return CURLE_FAILED_INIT;
} }
parse = aliases[j].letter; parse = aliases[j].letter;
hit = j; hit = j;
@ -428,7 +452,7 @@ static int getparameter(char *flag, /* f or -long-flag */
} }
if(hit < 0) { if(hit < 0) {
helpf("unknown option -%s.\n", flag); helpf("unknown option -%s.\n", flag);
return URG_FAILED_INIT; return CURLE_FAILED_INIT;
} }
} }
else { else {
@ -454,18 +478,18 @@ static int getparameter(char *flag, /* f or -long-flag */
} }
if(hit < 0) { if(hit < 0) {
helpf("unknown option -%c.\n", letter); helpf("unknown option -%c.\n", letter);
return URG_FAILED_INIT; return CURLE_FAILED_INIT;
} }
} }
if(hit < 0) { if(hit < 0) {
helpf("unknown option -%c.\n", letter); helpf("unknown option -%c.\n", letter);
return URG_FAILED_INIT; return CURLE_FAILED_INIT;
} }
if(!nextarg && aliases[hit].extraparam) { if(!nextarg && aliases[hit].extraparam) {
helpf("option -%s/--%s requires an extra argument!\n", helpf("option -%s/--%s requires an extra argument!\n",
aliases[hit].letter, aliases[hit].letter,
aliases[hit].lname); aliases[hit].lname);
return URG_FAILED_INIT; return CURLE_FAILED_INIT;
} }
else if(nextarg && aliases[hit].extraparam) else if(nextarg && aliases[hit].extraparam)
*usedarg = TRUE; /* mark it as used */ *usedarg = TRUE; /* mark it as used */
@ -491,7 +515,7 @@ static int getparameter(char *flag, /* f or -long-flag */
break; break;
} }
now=time(NULL); now=time(NULL);
config->condtime=get_date(nextarg, &now); config->condtime=curl_getdate(nextarg, &now);
if(-1 == config->condtime) { if(-1 == config->condtime) {
/* now let's see if it is a file name to get the time from instead! */ /* now let's see if it is a file name to get the time from instead! */
struct stat statbuf; struct stat statbuf;
@ -586,7 +610,6 @@ static int getparameter(char *flag, /* f or -long-flag */
break; break;
case 'e': case 'e':
GetStr(&config->referer, nextarg); GetStr(&config->referer, nextarg);
config->conf |= CONF_REFERER;
break; break;
case 'E': case 'E':
{ {
@ -610,13 +633,12 @@ static int getparameter(char *flag, /* f or -long-flag */
if(curl_FormParse(nextarg, if(curl_FormParse(nextarg,
&config->httppost, &config->httppost,
&config->last_post)) &config->last_post))
return URG_FAILED_INIT; return CURLE_FAILED_INIT;
config->conf |= CONF_HTTPPOST; /* no toggle, OR! */
break; break;
case 'h': /* h for help */ case 'h': /* h for help */
help(); help();
return URG_FAILED_INIT; return CURLE_FAILED_INIT;
case 'H': case 'H':
head = (struct HttpHeader *)malloc(sizeof(struct HttpHeader)); head = (struct HttpHeader *)malloc(sizeof(struct HttpHeader));
if(head) { if(head) {
@ -659,7 +681,7 @@ static int getparameter(char *flag, /* f or -long-flag */
break; break;
case 'M': /* M for manual, huge help */ case 'M': /* M for manual, huge help */
hugehelp(); hugehelp();
return URG_FAILED_INIT; return CURLE_FAILED_INIT;
case 'n': case 'n':
/* pick info from .netrc, if this is used for http, curl will /* pick info from .netrc, if this is used for http, curl will
automatically enfore user+password with the request */ automatically enfore user+password with the request */
@ -683,7 +705,6 @@ static int getparameter(char *flag, /* f or -long-flag */
this will make us try to get the "default" address. this will make us try to get the "default" address.
NOTE: this is a changed behaviour since the released 4.1! NOTE: this is a changed behaviour since the released 4.1!
*/ */
config->conf |= CONF_FTPPORT;
GetStr(&config->ftpport, nextarg); GetStr(&config->ftpport, nextarg);
break; break;
#if 0 #if 0
@ -712,7 +733,6 @@ static int getparameter(char *flag, /* f or -long-flag */
case 'r': case 'r':
/* byte range requested */ /* byte range requested */
GetStr(&config->range, nextarg); GetStr(&config->range, nextarg);
config->conf |= CONF_RANGE;
break; break;
case 's': case 's':
/* don't show progress meter, don't show errors : */ /* don't show progress meter, don't show errors : */
@ -735,19 +755,17 @@ static int getparameter(char *flag, /* f or -long-flag */
case 'u': case 'u':
/* user:password */ /* user:password */
GetStr(&config->userpwd, nextarg); GetStr(&config->userpwd, nextarg);
config->conf |= CONF_USERPWD;
break; break;
case 'U': case 'U':
/* Proxy user:password */ /* Proxy user:password */
GetStr(&config->proxyuserpwd, nextarg); GetStr(&config->proxyuserpwd, nextarg);
config->conf |= CONF_PROXYUSERPWD;
break; break;
case 'v': case 'v':
config->conf ^= CONF_VERBOSE; /* talk a lot */ config->conf ^= CONF_VERBOSE; /* talk a lot */
break; break;
case 'V': case 'V':
printf(CURL_ID "%s\n", curl_version()); printf(CURL_ID "%s\n", curl_version());
return URG_FAILED_INIT; return CURLE_FAILED_INIT;
case 'w': case 'w':
/* get the output string */ /* get the output string */
if('@' == *nextarg) { if('@' == *nextarg) {
@ -768,14 +786,7 @@ static int getparameter(char *flag, /* f or -long-flag */
break; break;
case 'x': case 'x':
/* proxy */ /* proxy */
if(!*nextarg) { GetStr(&config->proxy, nextarg);
/* disable proxy when no proxy is given */
config->conf &= ~CONF_PROXY;
}
else {
config->conf |= CONF_PROXY;
GetStr(&config->proxy, nextarg);
}
break; break;
case 'X': case 'X':
/* HTTP request */ /* HTTP request */
@ -799,13 +810,13 @@ static int getparameter(char *flag, /* f or -long-flag */
helpf("Unknown option '%c'\n", letter); helpf("Unknown option '%c'\n", letter);
else else
helpf("Unknown option\n"); /* short help blurb */ helpf("Unknown option\n"); /* short help blurb */
return URG_FAILED_INIT; return CURLE_FAILED_INIT;
} }
hit = -1; hit = -1;
} while(*++parse && !*usedarg); } while(*++parse && !*usedarg);
return URG_OK; return CURLE_OK;
} }
@ -826,7 +837,7 @@ static int parseconfig(char *filename,
char *home = curl_GetEnv("HOME"); /* portable environment reader */ char *home = curl_GetEnv("HOME"); /* portable environment reader */
if(!home || (strlen(home)>(sizeof(filebuffer)-strlen(CURLRC)))) if(!home || (strlen(home)>(sizeof(filebuffer)-strlen(CURLRC))))
return URG_OK; return CURLE_OK;
sprintf(filebuffer, "%s%s%s", home, DIR_CHAR, CURLRC); sprintf(filebuffer, "%s%s%s", home, DIR_CHAR, CURLRC);
@ -894,7 +905,7 @@ static int parseconfig(char *filename,
if(file != stdin) if(file != stdin)
fclose(file); fclose(file);
} }
return URG_OK; return CURLE_OK;
} }
struct OutStruct { struct OutStruct {
@ -944,7 +955,8 @@ int main(int argc, char *argv[])
int infilesize=-1; /* -1 means unknown */ int infilesize=-1; /* -1 means unknown */
bool stillflags=TRUE; bool stillflags=TRUE;
int res=URG_OK; CURL *curl;
int res=CURLE_OK;
int i; int i;
outs.stream = stdout; outs.stream = stdout;
@ -981,7 +993,7 @@ int main(int argc, char *argv[])
if ((argc < 2) && !config.url) { if ((argc < 2) && !config.url) {
helpf(NULL); helpf(NULL);
return URG_FAILED_INIT; return CURLE_FAILED_INIT;
} }
/* Parse options */ /* Parse options */
@ -1014,7 +1026,7 @@ int main(int argc, char *argv[])
else { else {
if(url) { if(url) {
helpf("only one URL is supported!\n"); helpf("only one URL is supported!\n");
return URG_FAILED_INIT; return CURLE_FAILED_INIT;
} }
url = argv[i]; url = argv[i];
} }
@ -1027,7 +1039,7 @@ int main(int argc, char *argv[])
if(!url) { if(!url) {
helpf("no URL specified!\n"); helpf("no URL specified!\n");
return URG_FAILED_INIT; return CURLE_FAILED_INIT;
} }
#if 0 #if 0
fprintf(stderr, "URL: %s PROXY: %s\n", url, config.proxy?config.proxy:"none"); fprintf(stderr, "URL: %s PROXY: %s\n", url, config.proxy?config.proxy:"none");
@ -1036,7 +1048,7 @@ int main(int argc, char *argv[])
/* expand '{...}' and '[...]' expressions and return total number of URLs /* expand '{...}' and '[...]' expressions and return total number of URLs
in pattern set */ in pattern set */
res = glob_url(&urls, url, &urlnum); res = glob_url(&urls, url, &urlnum);
if(res != URG_OK) if(res != CURLE_OK)
return res; return res;
outfiles = config.outfile; /* save outfile pattern befor expansion */ outfiles = config.outfile; /* save outfile pattern befor expansion */
@ -1058,7 +1070,7 @@ int main(int argc, char *argv[])
if(config.outfile && config.infile) { if(config.outfile && config.infile) {
helpf("you can't both upload and download!\n"); helpf("you can't both upload and download!\n");
return URG_FAILED_INIT; return CURLE_FAILED_INIT;
} }
if (config.outfile || config.remotefile) { if (config.outfile || config.remotefile) {
@ -1077,7 +1089,7 @@ int main(int argc, char *argv[])
config.outfile = strrchr(config.outfile, '/'); config.outfile = strrchr(config.outfile, '/');
if(!config.outfile || !strlen(++config.outfile)) { if(!config.outfile || !strlen(++config.outfile)) {
helpf("Remote file name has no length!\n"); helpf("Remote file name has no length!\n");
return URG_WRITE_ERROR; return CURLE_WRITE_ERROR;
} }
} }
else /* fill '#1' ... '#9' terms from URL pattern */ else /* fill '#1' ... '#9' terms from URL pattern */
@ -1100,7 +1112,7 @@ int main(int argc, char *argv[])
outs.stream=(FILE *) fopen(config.outfile, config.resume_from?"ab":"wb"); outs.stream=(FILE *) fopen(config.outfile, config.resume_from?"ab":"wb");
if (!outs.stream) { if (!outs.stream) {
helpf("Can't open '%s'!\n", config.outfile); helpf("Can't open '%s'!\n", config.outfile);
return URG_WRITE_ERROR; return CURLE_WRITE_ERROR;
} }
} }
else { else {
@ -1127,7 +1139,7 @@ int main(int argc, char *argv[])
urlbuffer=(char *)malloc(strlen(url) + strlen(config.infile) + 3); urlbuffer=(char *)malloc(strlen(url) + strlen(config.infile) + 3);
if(!urlbuffer) { if(!urlbuffer) {
helpf("out of memory\n"); helpf("out of memory\n");
return URG_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
} }
if(ptr) if(ptr)
/* there is a trailing slash on the URL */ /* there is a trailing slash on the URL */
@ -1142,7 +1154,7 @@ int main(int argc, char *argv[])
infd=(FILE *) fopen(config.infile, "rb"); infd=(FILE *) fopen(config.infile, "rb");
if (!infd || stat(config.infile, &fileinfo)) { if (!infd || stat(config.infile, &fileinfo)) {
helpf("Can't open '%s'!\n", config.infile); helpf("Can't open '%s'!\n", config.infile);
return URG_READ_ERROR; return CURLE_READ_ERROR;
} }
infilesize=fileinfo.st_size; infilesize=fileinfo.st_size;
@ -1189,49 +1201,122 @@ int main(int argc, char *argv[])
main_init(); main_init();
res = curl_urlget(URGTAG_FILE, (FILE *)&outs, /* where to store */ #if 0
URGTAG_WRITEFUNCTION, my_fwrite, /* what call to write */ /* This is code left from the pre-v7 time, left here mainly as a reminder
URGTAG_INFILE, infd, /* for uploads */ and possibly as a warning! ;-) */
URGTAG_INFILESIZE, infilesize, /* size of uploaded file */
URGTAG_URL, url, /* what to fetch */ res = curl_urlget(CURLOPT_FILE, (FILE *)&outs, /* where to store */
URGTAG_PROXY, config.proxy, /* proxy to use */ CURLOPT_WRITEFUNCTION, my_fwrite, /* what call to write */
URGTAG_FLAGS, config.conf, /* flags */ CURLOPT_INFILE, infd, /* for uploads */
URGTAG_USERPWD, config.userpwd, /* user + passwd */ CURLOPT_INFILESIZE, infilesize, /* size of uploaded file */
URGTAG_PROXYUSERPWD, config.proxyuserpwd, /* Proxy user + passwd */ CURLOPT_URL, url, /* what to fetch */
URGTAG_RANGE, config.range, /* range of document */ CURLOPT_PROXY, config.proxy, /* proxy to use */
URGTAG_ERRORBUFFER, errorbuffer, CURLOPT_FLAGS, config.conf, /* flags */
URGTAG_TIMEOUT, config.timeout, CURLOPT_USERPWD, config.userpwd, /* user + passwd */
URGTAG_POSTFIELDS, config.postfields, CURLOPT_PROXYUSERPWD, config.proxyuserpwd, /* Proxy user + passwd */
URGTAG_REFERER, config.referer, CURLOPT_RANGE, config.range, /* range of document */
URGTAG_USERAGENT, config.useragent, CURLOPT_ERRORBUFFER, errorbuffer,
URGTAG_FTPPORT, config.ftpport, CURLOPT_TIMEOUT, config.timeout,
URGTAG_LOW_SPEED_LIMIT, config.low_speed_limit, CURLOPT_POSTFIELDS, config.postfields,
URGTAG_LOW_SPEED_TIME, config.low_speed_time, CURLOPT_REFERER, config.referer,
URGTAG_RESUME_FROM, config.use_resume?config.resume_from:0, CURLOPT_USERAGENT, config.useragent,
URGTAG_COOKIE, config.cookie, CURLOPT_FTPPORT, config.ftpport,
URGTAG_HTTPHEADER, config.headers, CURLOPT_LOW_SPEED_LIMIT, config.low_speed_limit,
URGTAG_HTTPPOST, config.httppost, CURLOPT_LOW_SPEED_TIME, config.low_speed_time,
URGTAG_SSLCERT, config.cert, CURLOPT_RESUME_FROM, config.use_resume?config.resume_from:0,
URGTAG_SSLCERTPASSWD, config.cert_passwd, CURLOPT_COOKIE, config.cookie,
URGTAG_CRLF, config.crlf, CURLOPT_HTTPHEADER, config.headers,
URGTAG_QUOTE, config.quote, CURLOPT_HTTPPOST, config.httppost,
URGTAG_POSTQUOTE, config.postquote, CURLOPT_SSLCERT, config.cert,
URGTAG_WRITEHEADER, config.headerfile?&heads:NULL, CURLOPT_SSLCERTPASSWD, config.cert_passwd,
URGTAG_COOKIEFILE, config.cookiefile, CURLOPT_CRLF, config.crlf,
URGTAG_SSLVERSION, config.ssl_version, CURLOPT_QUOTE, config.quote,
URGTAG_TIMECONDITION, config.timecond, CURLOPT_POSTQUOTE, config.postquote,
URGTAG_TIMEVALUE, config.condtime, CURLOPT_WRITEHEADER, config.headerfile?&heads:NULL,
URGTAG_CUSTOMREQUEST, config.customrequest, CURLOPT_COOKIEFILE, config.cookiefile,
URGTAG_STDERR, config.errors, CURLOPT_SSLVERSION, config.ssl_version,
URGTAG_PROGRESSMODE, config.progressmode, CURLOPT_TIMECONDITION, config.timecond,
URGTAG_WRITEINFO, config.writeout, CURLOPT_TIMEVALUE, config.condtime,
URGTAG_DONE); /* always terminate the list of tags */ CURLOPT_CUSTOMREQUEST, config.customrequest,
CURLOPT_STDERR, config.errors,
CURLOPT_PROGRESSMODE, config.progressmode,
CURLOPT_WRITEINFO, config.writeout,
CURLOPT_DONE); /* always terminate the list of tags */
#endif
/* The new, v7-style easy-interface! */
curl = curl_easy_init();
if(curl) {
curl_easy_setopt(curl, CURLOPT_FILE, (FILE *)&outs); /* where to store */
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, my_fwrite); /* what call to write */
curl_easy_setopt(curl, CURLOPT_INFILE, infd); /* for uploads */
curl_easy_setopt(curl, CURLOPT_INFILESIZE, infilesize); /* size of uploaded file */
curl_easy_setopt(curl, CURLOPT_URL, url); /* what to fetch */
curl_easy_setopt(curl, CURLOPT_PROXY, config.proxy); /* proxy to use */
#if 0
curl_easy_setopt(curl, CURLOPT_FLAGS, config.conf); /* flags */
#else
curl_easy_setopt(curl, CURLOPT_VERBOSE, config.conf&CONF_VERBOSE);
curl_easy_setopt(curl, CURLOPT_HEADER, config.conf&CONF_HEADER);
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, config.conf&CONF_NOPROGRESS);
curl_easy_setopt(curl, CURLOPT_NOBODY, config.conf&CONF_NOBODY);
curl_easy_setopt(curl, CURLOPT_FAILONERROR, config.conf&CONF_FAILONERROR);
curl_easy_setopt(curl, CURLOPT_UPLOAD, config.conf&CONF_UPLOAD);
curl_easy_setopt(curl, CURLOPT_POST, config.conf&CONF_POST);
curl_easy_setopt(curl, CURLOPT_FTPLISTONLY, config.conf&CONF_FTPLISTONLY);
curl_easy_setopt(curl, CURLOPT_FTPAPPEND, config.conf&CONF_FTPAPPEND);
curl_easy_setopt(curl, CURLOPT_NETRC, config.conf&CONF_NETRC);
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, config.conf&CONF_FOLLOWLOCATION);
curl_easy_setopt(curl, CURLOPT_FTPASCII, config.conf&CONF_FTPASCII);
curl_easy_setopt(curl, CURLOPT_PUT, config.conf&CONF_PUT);
curl_easy_setopt(curl, CURLOPT_MUTE, config.conf&CONF_MUTE);
#endif
curl_easy_setopt(curl, CURLOPT_USERPWD, config.userpwd); /* user + passwd */
curl_easy_setopt(curl, CURLOPT_PROXYUSERPWD, config.proxyuserpwd); /* Proxy user + passwd */
curl_easy_setopt(curl, CURLOPT_RANGE, config.range); /* range of document */
curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errorbuffer);
curl_easy_setopt(curl, CURLOPT_TIMEOUT, config.timeout);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, config.postfields);
curl_easy_setopt(curl, CURLOPT_REFERER, config.referer);
curl_easy_setopt(curl, CURLOPT_USERAGENT, config.useragent);
curl_easy_setopt(curl, CURLOPT_FTPPORT, config.ftpport);
curl_easy_setopt(curl, CURLOPT_LOW_SPEED_LIMIT, config.low_speed_limit);
curl_easy_setopt(curl, CURLOPT_LOW_SPEED_TIME, config.low_speed_time);
curl_easy_setopt(curl, CURLOPT_RESUME_FROM, config.use_resume?config.resume_from:0);
curl_easy_setopt(curl, CURLOPT_COOKIE, config.cookie);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, config.headers);
curl_easy_setopt(curl, CURLOPT_HTTPPOST, config.httppost);
curl_easy_setopt(curl, CURLOPT_SSLCERT, config.cert);
curl_easy_setopt(curl, CURLOPT_SSLCERTPASSWD, config.cert_passwd);
curl_easy_setopt(curl, CURLOPT_CRLF, config.crlf);
curl_easy_setopt(curl, CURLOPT_QUOTE, config.quote);
curl_easy_setopt(curl, CURLOPT_POSTQUOTE, config.postquote);
curl_easy_setopt(curl, CURLOPT_WRITEHEADER, config.headerfile?&heads:NULL);
curl_easy_setopt(curl, CURLOPT_COOKIEFILE, config.cookiefile);
curl_easy_setopt(curl, CURLOPT_SSLVERSION, config.ssl_version);
curl_easy_setopt(curl, CURLOPT_TIMECONDITION, config.timecond);
curl_easy_setopt(curl, CURLOPT_TIMEVALUE, config.condtime);
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, config.customrequest);
curl_easy_setopt(curl, CURLOPT_STDERR, config.errors);
curl_easy_setopt(curl, CURLOPT_PROGRESSMODE, config.progressmode);
curl_easy_setopt(curl, CURLOPT_WRITEINFO, config.writeout);
res = curl_easy_perform(curl);
/* always cleanup */
curl_easy_cleanup(curl);
if((res!=CURLE_OK) && config.showerror)
fprintf(config.errors, "curl: (%d) %s\n", res, errorbuffer);
}
else
fprintf(config.errors, "curl: failed to init libcurl!\n");
main_free(); main_free();
if((res!=URG_OK) && config.showerror)
fprintf(config.errors, "curl: (%d) %s\n", res, errorbuffer);
if((config.errors != stderr) && if((config.errors != stderr) &&
(config.errors != stdout)) (config.errors != stdout))
/* it wasn't directed to stdout or stderr so close the file! */ /* it wasn't directed to stdout or stderr so close the file! */

View File

@ -69,18 +69,18 @@ int glob_set(char *pattern, int pos) {
switch (*pattern) { switch (*pattern) {
case '\0': /* URL ended while set was still open */ case '\0': /* URL ended while set was still open */
printf("error: unmatched brace at pos %d\n", pos); printf("error: unmatched brace at pos %d\n", pos);
exit (URG_URL_MALFORMAT); exit (CURLE_URL_MALFORMAT);
case '{': case '{':
case '[': /* no nested expressions at this time */ case '[': /* no nested expressions at this time */
printf("error: nested braces not supported %d\n", pos); printf("error: nested braces not supported %d\n", pos);
exit (URG_URL_MALFORMAT); exit (CURLE_URL_MALFORMAT);
case ',': case ',':
case '}': /* set element completed */ case '}': /* set element completed */
*buf = '\0'; *buf = '\0';
pat->content.Set.elements = realloc(pat->content.Set.elements, (pat->content.Set.size + 1) * sizeof(char*)); pat->content.Set.elements = realloc(pat->content.Set.elements, (pat->content.Set.size + 1) * sizeof(char*));
if (!pat->content.Set.elements) { if (!pat->content.Set.elements) {
printf("out of memory in set pattern\n"); printf("out of memory in set pattern\n");
exit(URG_OUT_OF_MEMORY); exit(CURLE_OUT_OF_MEMORY);
} }
pat->content.Set.elements[pat->content.Set.size] = strdup(glob_buffer); pat->content.Set.elements[pat->content.Set.size] = strdup(glob_buffer);
++pat->content.Set.size; ++pat->content.Set.size;
@ -95,11 +95,11 @@ int glob_set(char *pattern, int pos) {
break; break;
case ']': /* illegal closing bracket */ case ']': /* illegal closing bracket */
printf("error: illegal pattern at pos %d\n", pos); printf("error: illegal pattern at pos %d\n", pos);
exit (URG_URL_MALFORMAT); exit (CURLE_URL_MALFORMAT);
case '\\': /* escaped character, skip '\' */ case '\\': /* escaped character, skip '\' */
if (*(buf+1) == '\0') { /* but no escaping of '\0'! */ if (*(buf+1) == '\0') { /* but no escaping of '\0'! */
printf("error: illegal pattern at pos %d\n", pos); printf("error: illegal pattern at pos %d\n", pos);
exit (URG_URL_MALFORMAT); exit (CURLE_URL_MALFORMAT);
} }
++pattern; ++pattern;
++pos; /* intentional fallthrough */ ++pos; /* intentional fallthrough */
@ -108,7 +108,7 @@ int glob_set(char *pattern, int pos) {
++pos; ++pos;
} }
} }
exit (URG_FAILED_INIT); exit (CURLE_FAILED_INIT);
} }
int glob_range(char *pattern, int pos) { int glob_range(char *pattern, int pos) {
@ -132,7 +132,7 @@ int glob_range(char *pattern, int pos) {
pat->content.CharRange.max_c - pat->content.CharRange.min_c > 'z' - 'a') { pat->content.CharRange.max_c - pat->content.CharRange.min_c > 'z' - 'a') {
/* the pattern is not well-formed */ /* the pattern is not well-formed */
printf("error: illegal pattern or range specification after pos %d\n", pos); printf("error: illegal pattern or range specification after pos %d\n", pos);
exit (URG_URL_MALFORMAT); exit (CURLE_URL_MALFORMAT);
} }
pat->content.CharRange.ptr_c = pat->content.CharRange.min_c; pat->content.CharRange.ptr_c = pat->content.CharRange.min_c;
/* always check for a literal (may be "") between patterns */ /* always check for a literal (may be "") between patterns */
@ -146,7 +146,7 @@ int glob_range(char *pattern, int pos) {
pat->content.NumRange.min_n >= pat->content.NumRange.max_n) { pat->content.NumRange.min_n >= pat->content.NumRange.max_n) {
/* the pattern is not well-formed */ /* the pattern is not well-formed */
printf("error: illegal pattern or range specification after pos %d\n", pos); printf("error: illegal pattern or range specification after pos %d\n", pos);
exit (URG_URL_MALFORMAT); exit (CURLE_URL_MALFORMAT);
} }
if (*pattern == '0') { /* leading zero specified */ if (*pattern == '0') { /* leading zero specified */
c = pattern; c = pattern;
@ -161,7 +161,7 @@ int glob_range(char *pattern, int pos) {
glob_word(c, pos + (c - pattern)); glob_word(c, pos + (c - pattern));
} }
printf("error: illegal character in range specification at pos %d\n", pos); printf("error: illegal character in range specification at pos %d\n", pos);
exit (URG_URL_MALFORMAT); exit (CURLE_URL_MALFORMAT);
} }
int glob_word(char *pattern, int pos) { int glob_word(char *pattern, int pos) {
@ -174,14 +174,14 @@ int glob_word(char *pattern, int pos) {
while (*pattern != '\0' && *pattern != '{' && *pattern != '[') { while (*pattern != '\0' && *pattern != '{' && *pattern != '[') {
if (*pattern == '}' || *pattern == ']') { if (*pattern == '}' || *pattern == ']') {
printf("illegal character at position %d\n", pos); printf("illegal character at position %d\n", pos);
exit (URG_URL_MALFORMAT); exit (CURLE_URL_MALFORMAT);
} }
if (*pattern == '\\') { /* escape character, skip '\' */ if (*pattern == '\\') { /* escape character, skip '\' */
++pattern; ++pattern;
++pos; ++pos;
if (*pattern == '\0') { /* but no escaping of '\0'! */ if (*pattern == '\0') { /* but no escaping of '\0'! */
printf("illegal character at position %d\n", pos); printf("illegal character at position %d\n", pos);
exit (URG_URL_MALFORMAT); exit (CURLE_URL_MALFORMAT);
} }
} }
*buf++ = *pattern++; /* copy character to literal */ *buf++ = *pattern++; /* copy character to literal */
@ -201,21 +201,21 @@ int glob_word(char *pattern, int pos) {
return glob_range(++pattern, ++pos);/* process range pattern */ return glob_range(++pattern, ++pos);/* process range pattern */
} }
printf("internal error\n"); printf("internal error\n");
exit (URG_FAILED_INIT); exit (CURLE_FAILED_INIT);
} }
int glob_url(URLGlob** glob, char* url, int *urlnum) int glob_url(URLGlob** glob, char* url, int *urlnum)
{ {
if (strlen(url)>URL_MAX_LENGTH) { if (strlen(url)>URL_MAX_LENGTH) {
printf("Illegally sized URL\n"); printf("Illegally sized URL\n");
return URG_URL_MALFORMAT; return CURLE_URL_MALFORMAT;
} }
glob_expand = (URLGlob*)malloc(sizeof(URLGlob)); glob_expand = (URLGlob*)malloc(sizeof(URLGlob));
glob_expand->size = 0; glob_expand->size = 0;
*urlnum = glob_word(url, 1); *urlnum = glob_word(url, 1);
*glob = glob_expand; *glob = glob_expand;
return URG_OK; return CURLE_OK;
} }
char *next_url(URLGlob *glob) char *next_url(URLGlob *glob)
@ -258,7 +258,7 @@ char *next_url(URLGlob *glob)
break; break;
default: default:
printf("internal error: invalid pattern type (%d)\n", pat->type); printf("internal error: invalid pattern type (%d)\n", pat->type);
exit (URG_FAILED_INIT); exit (CURLE_FAILED_INIT);
} }
} }
if (carry) /* first pattern ptr has run into overflow, done! */ if (carry) /* first pattern ptr has run into overflow, done! */
@ -287,7 +287,7 @@ char *next_url(URLGlob *glob)
break; break;
default: default:
printf("internal error: invalid pattern type (%d)\n", pat->type); printf("internal error: invalid pattern type (%d)\n", pat->type);
exit (URG_FAILED_INIT); exit (CURLE_FAILED_INIT);
} }
} }
} }
@ -305,12 +305,12 @@ char *match_url(char *filename, URLGlob glob) {
if (!isdigit((int)*++filename) || if (!isdigit((int)*++filename) ||
*filename == '0') { /* only '#1' ... '#9' allowed */ *filename == '0') { /* only '#1' ... '#9' allowed */
printf("illegal matching expression\n"); printf("illegal matching expression\n");
exit(URG_URL_MALFORMAT); exit(CURLE_URL_MALFORMAT);
} }
i = *filename - '1'; i = *filename - '1';
if (i + 1 > glob.size / 2) { if (i + 1 > glob.size / 2) {
printf("match against nonexisting pattern\n"); printf("match against nonexisting pattern\n");
exit(URG_URL_MALFORMAT); exit(CURLE_URL_MALFORMAT);
} }
pat = glob.pattern[i]; pat = glob.pattern[i];
switch (pat.type) { switch (pat.type) {
@ -327,7 +327,7 @@ char *match_url(char *filename, URLGlob glob) {
break; break;
default: default:
printf("internal error: invalid pattern type (%d)\n", pat.type); printf("internal error: invalid pattern type (%d)\n", pat.type);
exit (URG_FAILED_INIT); exit (CURLE_FAILED_INIT);
} }
++filename; ++filename;
} }

View File

@ -1,3 +1,3 @@
#define CURL_NAME "curl" #define CURL_NAME "curl"
#define CURL_VERSION "6.5.2" #define CURL_VERSION "7.0beta"
#define CURL_ID CURL_NAME " " CURL_VERSION " (" OS ") " #define CURL_ID CURL_NAME " " CURL_VERSION " (" OS ") "