moved here from the newlib branch
authorDaniel Stenberg <daniel@haxx.se>
Mon, 22 May 2000 14:12:12 +0000 (14:12 +0000)
committerDaniel Stenberg <daniel@haxx.se>
Mon, 22 May 2000 14:12:12 +0000 (14:12 +0000)
54 files changed:
CHANGES
FAQ
config-win32.h
config.h.in
configure.in
curl.1
include/curl/curl.h
include/curl/easy.h [new file with mode: 0644]
include/curl/types.h [new file with mode: 0644]
lib/Makefile.am
lib/Makefile.in
lib/cookie.c
lib/dict.c
lib/dict.h
lib/download.c
lib/download.h
lib/escape.c
lib/escape.h
lib/file.c
lib/file.h
lib/formdata.c
lib/ftp.c
lib/ftp.h
lib/getdate.c
lib/getdate.h
lib/getdate.y
lib/getenv.c
lib/http.c
lib/http.h
lib/ldap.c
lib/ldap.h
lib/netrc.c
lib/progress.c
lib/progress.h
lib/sendf.c
lib/setup.h
lib/speedcheck.c
lib/speedcheck.h
lib/ssluse.c
lib/telnet.c
lib/telnet.h
lib/url.c
lib/url.h
lib/urldata.h
lib/version.c
lib/writeout.c
lib/writeout.h
maketgz
src/Makefile.am
src/config-win32.h
src/hugehelp.c
src/main.c
src/urlglob.c
src/version.h

diff --git a/CHANGES b/CHANGES
index 6863087..2180333 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -8,6 +8,39 @@
 
 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)
 - FTP URLs are now treated slightly different, more according to RFC 1738.
 - FTP sessions are now performed differently, with CWD commands to change
diff --git a/FAQ b/FAQ
index 1b120cb..1a9fec3 100644 (file)
--- a/FAQ
+++ b/FAQ
@@ -83,14 +83,3 @@ configre doesn't find OpenSSL even when it is installed
   things work
 
   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.
index 713fdd6..4f6ab62 100644 (file)
@@ -71,6 +71,9 @@
 /* Define if you have the strcasecmp function.  */
 /*#define HAVE_STRCASECMP 1*/
 
+/* Define if you have the stricmp function.  */
+#define HAVE_STRICMP 1
+
 /* Define if you have the strdup function.  */
 #define HAVE_STRDUP 1
 
index 7157972..c9f96d7 100644 (file)
 /* Define if you have the strcasecmp function.  */
 #undef HAVE_STRCASECMP
 
+/* Define if you have the strcmpi function.  */
+#undef HAVE_STRCMPI
+
 /* Define if you have the strdup function.  */
 #undef HAVE_STRDUP
 
 /* Define if you have the strftime function.  */
 #undef HAVE_STRFTIME
 
+/* Define if you have the stricmp function.  */
+#undef HAVE_STRICMP
+
 /* Define if you have the strstr function.  */
 #undef HAVE_STRSTR
 
index d5520cd..116fa72 100644 (file)
@@ -2,13 +2,7 @@ dnl $Id$
 dnl Process this file with autoconf to produce a configure script.
 AC_INIT(lib/urldata.h)
 AM_CONFIG_HEADER(config.h src/config.h)
-AM_INIT_AUTOMAKE(curl,"3-test")
-
-dnl
-dnl Detect the canonical host and target build environment
-dnl
-AC_CANONICAL_HOST
-AC_CANONICAL_TARGET
+AM_INIT_AUTOMAKE(curl,"7.0beta")
 
 dnl Checks for programs.
 AC_PROG_CC
@@ -26,27 +20,6 @@ dnl **********************************************************************
 dnl nsl lib?
 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?
 AC_CHECK_FUNC(strcasecmp, , AC_CHECK_LIB(resolve, strcasecmp))
 
@@ -219,14 +192,13 @@ AC_CHECK_FUNCS( socket \
                 RAND_screen
 )
 
-
-
 AC_PATH_PROG( PERL, perl, , 
   $PATH:/usr/local/bin/perl:/usr/bin/:/usr/local/bin )
 AC_SUBST(PERL)
 
 AC_PATH_PROGS( NROFF, gnroff nroff, , 
   $PATH:/usr/bin/:/usr/local/bin )
+AC_SUBST(NROFF)
 
 AC_PROG_RANLIB
 AC_PROG_YACC
@@ -236,8 +208,6 @@ dnl   $PATH:/usr/bin/:/usr/local/bin )
 dnl AC_SUBST(RANLIB)
 
 AC_OUTPUT( Makefile \
-          curl.spec \
-          curl-ssl.spec \
           src/Makefile \
            lib/Makefile )
 dnl       perl/checklinks.pl \
diff --git a/curl.1 b/curl.1
index aa2152d..7683a11 100644 (file)
--- a/curl.1
+++ b/curl.1
@@ -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
 '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"
 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
index 8a27c3e..4226df9 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef __CURL_H
-#define __CURL_H
+#ifndef __CURL_CURL_H
+#define __CURL_CURL_H
 /*****************************************************************************
  *                                  _   _ ____  _     
  *  Project                     ___| | | |  _ \| |    
  *
  * ------------------------------------------------------------
  ****************************************************************************/
+
+/* 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
 #define TRUE 1
 #endif
 #define FALSE 0
 #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 *next; /* next entry in the list */
@@ -132,68 +88,69 @@ struct HttpPost {
    may return other values, stay prepared. */
 
 typedef enum {
-  URG_OK = 0,
-  URG_UNSUPPORTED_PROTOCOL,
-  URG_FAILED_INIT,
-  URG_URL_MALFORMAT,
-  URG_URL_MALFORMAT_USER,
-  URG_COULDNT_RESOLVE_PROXY,
-  URG_COULDNT_RESOLVE_HOST,
-  URG_COULDNT_CONNECT,
-  URG_FTP_WEIRD_SERVER_REPLY,
-  URG_FTP_ACCESS_DENIED,
-  URG_FTP_USER_PASSWORD_INCORRECT,
-  URG_FTP_WEIRD_PASS_REPLY,
-  URG_FTP_WEIRD_USER_REPLY,
-  URG_FTP_WEIRD_PASV_REPLY,
-  URG_FTP_WEIRD_227_FORMAT,
-  URG_FTP_CANT_GET_HOST,
-  URG_FTP_CANT_RECONNECT,
-  URG_FTP_COULDNT_SET_BINARY,
-  URG_PARTIAL_FILE,
-  URG_FTP_COULDNT_RETR_FILE,
-  URG_FTP_WRITE_ERROR,
-  URG_FTP_QUOTE_ERROR,
-  URG_HTTP_NOT_FOUND,
-  URG_WRITE_ERROR,
-
-  URG_MALFORMAT_USER, /* the user name is illegally specified */
-  URG_FTP_COULDNT_STOR_FILE, /* failed FTP upload */
-  URG_READ_ERROR, /* could open/read from file */
-
-  URG_OUT_OF_MEMORY,
-  URG_OPERATION_TIMEOUTED, /* the timeout time was reached */
-  URG_FTP_COULDNT_SET_ASCII, /* TYPE A failed */
-
-  URG_FTP_PORT_FAILED, /* FTP PORT operation failed */
-
-  URG_FTP_COULDNT_USE_REST, /* the REST command failed */
-  URG_FTP_COULDNT_GET_SIZE, /* the SIZE command failed */
-
-  URG_HTTP_RANGE_ERROR, /* The RANGE "command" didn't seem to work */
-
-  URG_HTTP_POST_ERROR,
-
-  URG_SSL_CONNECT_ERROR, /* something was wrong when connecting with SSL */
-
-  URG_FTP_BAD_DOWNLOAD_RESUME, /* couldn't resume download */
-
-  URG_FILE_COULDNT_READ_FILE,
-
-  URG_LDAP_CANNOT_BIND,
-  URG_LDAP_SEARCH_FAILED,
-  URG_LIBRARY_NOT_FOUND,
-  URG_FUNCTION_NOT_FOUND,
-
-  URL_LAST
-} UrgError;
+  CURLE_OK = 0,
+  CURLE_UNSUPPORTED_PROTOCOL,
+  CURLE_FAILED_INIT,
+  CURLE_URL_MALFORMAT,
+  CURLE_URL_MALFORMAT_USER,
+  CURLE_COULDNT_RESOLVE_PROXY,
+  CURLE_COULDNT_RESOLVE_HOST,
+  CURLE_COULDNT_CONNECT,
+  CURLE_FTP_WEIRD_SERVER_REPLY,
+  CURLE_FTP_ACCESS_DENIED,
+  CURLE_FTP_USER_PASSWORD_INCORRECT,
+  CURLE_FTP_WEIRD_PASS_REPLY,
+  CURLE_FTP_WEIRD_USER_REPLY,
+  CURLE_FTP_WEIRD_PASV_REPLY,
+  CURLE_FTP_WEIRD_227_FORMAT,
+  CURLE_FTP_CANT_GET_HOST,
+  CURLE_FTP_CANT_RECONNECT,
+  CURLE_FTP_COULDNT_SET_BINARY,
+  CURLE_PARTIAL_FILE,
+  CURLE_FTP_COULDNT_RETR_FILE,
+  CURLE_FTP_WRITE_ERROR,
+  CURLE_FTP_QUOTE_ERROR,
+  CURLE_HTTP_NOT_FOUND,
+  CURLE_WRITE_ERROR,
+
+  CURLE_MALFORMAT_USER, /* the user name is illegally specified */
+  CURLE_FTP_COULDNT_STOR_FILE, /* failed FTP upload */
+  CURLE_READ_ERROR, /* could open/read from file */
+
+  CURLE_OUT_OF_MEMORY,
+  CURLE_OPERATION_TIMEOUTED, /* the timeout time was reached */
+  CURLE_FTP_COULDNT_SET_ASCII, /* TYPE A failed */
+
+  CURLE_FTP_PORT_FAILED, /* FTP PORT operation failed */
+
+  CURLE_FTP_COULDNT_USE_REST, /* the REST command failed */
+  CURLE_FTP_COULDNT_GET_SIZE, /* the SIZE command failed */
+
+  CURLE_HTTP_RANGE_ERROR, /* The RANGE "command" didn't seem to work */
+
+  CURLE_HTTP_POST_ERROR,
+
+  CURLE_SSL_CONNECT_ERROR, /* something was wrong when connecting with SSL */
+
+  CURLE_FTP_BAD_DOWNLOAD_RESUME, /* couldn't resume download */
+
+  CURLE_FILE_COULDNT_READ_FILE,
+
+  CURLE_LDAP_CANNOT_BIND,
+  CURLE_LDAP_SEARCH_FAILED,
+  CURLE_LIBRARY_NOT_FOUND,
+  CURLE_FUNCTION_NOT_FOUND,
+  
+  CURLE_ABORTED_BY_CALLBACK,
 
-/* This is just to make older programs not break: */
-#define URG_FTP_PARTIAL_FILE URG_PARTIAL_FILE
+  CURLE_BAD_FUNCTION_ARGUMENT,
+  CURLE_BAD_CALLING_ORDER,
 
-#define URGTAG_DONE -1
-#define URGTAG_LAST -1
-#define URGTAG_END -1
+  CURL_LAST
+} CURLcode;
+
+/* This is just to make older programs not break: */
+#define CURLE_FTP_PARTIAL_FILE CURLE_PARTIAL_FILE
 
 #define URLGET_ERROR_SIZE 256
 
@@ -201,19 +158,19 @@ typedef enum {
 #define URL_MAX_LENGTH 4096 
 #define URL_MAX_LENGTH_TXT "4095"
 
-/* name is uppercase URGTAG_<name>,
-   type is one of the defined URGTYPE_<type>
+/* name is uppercase CURLOPT_<name>,
+   type is one of the defined CURLOPTTYPE_<type>
    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
    but 32 */
-#define URGTYPE_LONG          0
-#define URGTYPE_OBJECTPOINT   10000
-#define URGTYPE_FUNCTIONPOINT 20000
+#define CURLOPTTYPE_LONG          0
+#define CURLOPTTYPE_OBJECTPOINT   10000
+#define CURLOPTTYPE_FUNCTIONPOINT 20000
 
 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. */
   T(FILE, OBJECTPOINT, 1),
@@ -222,28 +179,29 @@ typedef enum {
   T(URL,  OBJECTPOINT, 2),
 
   /* 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),
 
-  /* 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 */
   T(PROXY, OBJECTPOINT, 4),
   
   /* 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),
 
   /* 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),
 
   /* 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),
 
+#if 0
   /* Configuration flags */
   T(FLAGS, LONG, 8),
-
+#endif
   /* Specified file stream to upload from (use as input): */
   T(INFILE, OBJECTPOINT, 9),
 
@@ -262,7 +220,7 @@ typedef enum {
   /* Time-out the read operation after this amount of seconds */
   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
      and better verifies that the upload was succcessful. -1 means unknown
      size. */
@@ -364,8 +322,25 @@ typedef enum {
      as described elsewhere. */
   T(WRITEINFO, OBJECTPOINT, 40),
 
-  URGTAG_LASTENTRY /* the last unusued */
-} UrgTag;
+  /* Previous FLAG bits */
+  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_BAR   1
@@ -388,23 +363,11 @@ typedef char bool;
 #endif                     /* (rabe) */
 #endif
 
-/**********************************************************************
- *
- * >>> urlget() interface #defines changed in v5! <<<
- *
- * 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);
- *
- ***********************************************************************/
-
+#if 0
+/* At last, I stand here in front of you today and can officially proclaim
+   this function prototype as history... 17th of May, 2000 */
 UrgError curl_urlget(UrgTag, ...);
+#endif
 
 /* external form function */
 int curl_FormParse(char *string,
@@ -418,9 +381,10 @@ char *curl_GetEnv(char *variable);
 char *curl_version(void);
 
 /* 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 {
        char                    *data;
        struct curl_slist       *next;
@@ -429,4 +393,192 @@ struct curl_slist {
 struct curl_slist *curl_slist_append(struct curl_slist *list, char *data);
 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 */
diff --git a/include/curl/easy.h b/include/curl/easy.h
new file mode 100644 (file)
index 0000000..687696c
--- /dev/null
@@ -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
diff --git a/include/curl/types.h b/include/curl/types.h
new file mode 100644 (file)
index 0000000..15f7067
--- /dev/null
@@ -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 */
index 3951d88..02f2515 100644 (file)
@@ -7,7 +7,7 @@ AUTOMAKE_OPTIONS = foreign no-dependencies
 noinst_LIBRARIES = libcurl.a
 
 # Some flags needed when trying to cause warnings ;-)
-#CFLAGS = -g -Wall -pedantic
+CFLAGS = -g -Wall #-pedantic
 
 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       \
 escape.c       getenv.h       mprintf.c      telnet.c       \
 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.
 $(srcdir)/getdate.c: getdate.y
index 84be952..aece159 100644 (file)
@@ -77,11 +77,11 @@ AUTOMAKE_OPTIONS = foreign no-dependencies
 noinst_LIBRARIES = libcurl.a
 
 # Some flags needed when trying to cause warnings ;-)
-#CFLAGS = -g -Wall -pedantic
+CFLAGS = -g -Wall #-pedantic
 
 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
 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 \
 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 \
-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
-CFLAGS = @CFLAGS@
 COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
 CCLD = $(CC)
 LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@
index 00497bc..8038daf 100644 (file)
@@ -62,6 +62,7 @@ Example set of cookies:
 #include "cookie.h"
 #include "setup.h"
 #include "getdate.h"
+#include "strequal.h"
 
 /****************************************************************************
  *
@@ -131,7 +132,7 @@ struct Cookie *cookie_add(struct CookieInfo *c,
           }
           else if(strequal("expires", name)) {
             co->expirestr=strdup(what);
-            co->expires = get_date(what, &now);
+            co->expires = curl_getdate(what, &now);
           }
           else if(!co->name) {
             co->name = strdup(name);
@@ -173,9 +174,11 @@ struct Cookie *cookie_add(struct CookieInfo *c,
       return NULL;
     }
     /* strip off the possible end-of-line characters */
-    if(ptr=strchr(lineptr, '\r'))
+    ptr=strchr(lineptr, '\r');
+    if(ptr)
       *ptr=0; /* clear it */
-    if(ptr=strchr(lineptr, '\n'))
+    ptr=strchr(lineptr, '\n');
+    if(ptr)
       *ptr=0; /* clear it */
 
     firstptr=strtok(lineptr, "\t"); /* first tokenize it on the TAB */
index cf604ec..c9721bd 100644 (file)
 #include "sendf.h"
 
 #include "progress.h"
+#include "strequal.h"
 
 #define _MPRINTF_REPLACE /* use our functions only */
 #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;
   char *word;
@@ -106,9 +111,13 @@ UrgError dict(struct UrlData *data, char *path, long *bytecount)
   char *strategy = NULL;
   char *nthdef = NULL; /* This is not part of the protocol, but required
                           by RFC 2229 */
-  UrgError result=URG_OK;
-    
-  if(data->conf & CONF_USERPWD) {
+  CURLcode result=CURLE_OK;
+  struct UrlData *data=conn->data;
+
+  char *path = conn->path;
+  long *bytecount = &conn->bytecount;
+
+  if(data->bits.user_passwd) {
     /* AUTH is missing */
   }
 
@@ -162,7 +171,7 @@ UrgError dict(struct UrlData *data, char *path, long *bytecount)
           word
           );
     
-    result = Transfer(data, data->firstsocket, -1, FALSE, bytecount,
+    result = Transfer(conn, data->firstsocket, -1, FALSE, bytecount,
                       -1, NULL); /* no upload */
       
     if(result)
@@ -210,7 +219,7 @@ UrgError dict(struct UrlData *data, char *path, long *bytecount)
           word
           );
     
-    result = Transfer(data, data->firstsocket, -1, FALSE, bytecount,
+    result = Transfer(conn, data->firstsocket, -1, FALSE, bytecount,
                       -1, NULL); /* no upload */
       
     if(result)
@@ -234,7 +243,7 @@ UrgError dict(struct UrlData *data, char *path, long *bytecount)
             "QUIT\n",
             ppath);
       
-      result = Transfer(data, data->firstsocket, -1, FALSE, bytecount,
+      result = Transfer(conn, data->firstsocket, -1, FALSE, bytecount,
                         -1, NULL);
       
       if(result)
@@ -243,10 +252,5 @@ UrgError dict(struct UrlData *data, char *path, long *bytecount)
     }
   }
 
-#if 0
-  ProgressEnd(data);
-#endif
-  pgrsDone(data);
-
-  return URG_OK;
+  return CURLE_OK;
 }
index edff0c4..85e6e3b 100644 (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
index 380330b..d7ba12b 100644 (file)
 #include "speedcheck.h"
 #include "sendf.h"
 
-#ifdef USE_ZLIB
-#include <zlib.h>
-#endif
-
-#define MAX(x,y) ((x)>(y)?(x):(y))
+#include <curl/types.h>
 
 /* --- download and upload a stream from/to a socket --- */
 
 /* Parts of this function was brought to us by the friendly Mark Butler
    <butlerm@xmission.com>. */
 
-UrgError 
-Transfer (struct UrlData *data,
-          /* READ stuff */
+CURLcode 
+Transfer(CURLconnect *c_conn,
+         /* 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 */
@@ -101,492 +97,21 @@ Transfer (struct UrlData *data,
           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 */
-          
-
-)
+          )
 {
-  char *buf = data->buffer;
-  size_t nread;
-  int bytecount = 0; /* number of bytes read */
-  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 */
-  int hbuflen = 0;
-  char *str;                   /* within buf */
-  char *str_start;             /* within buf */
-  char *end_ptr;               /* within buf */
-  char *p;                     /* within headerbuff */
-  bool content_range = FALSE;  /* set TRUE if Content-Range: was found */
-  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: */
-  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 */
+  struct connectdata *conn = (struct connectdata *)c_conn;
+  if(!conn)
+    return CURLE_BAD_FUNCTION_ARGUMENT;
 
+  /* now copy all input parameters */
+  conn->sockfd = sockfd;
+  conn->size = size;
+  conn->getheader = getheader;
+  conn->bytecountp = bytecountp;
+  conn->writesockfd = writesockfd;
+  conn->writebytecountp = writebytecountp;
 
-                if ('\r' == *p)
-                  p++;         /* pass the \r byte */
-                if ('\n' == *p)
-                  p++;         /* pass the \n byte */
+  return CURLE_OK;
 
-                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;
 }
-
-
+          
index 414085d..86ba034 100644 (file)
@@ -39,8 +39,8 @@
  *
  * ------------------------------------------------------------
  ****************************************************************************/
-UrgError 
-Transfer (struct UrlData *data,
+CURLcode 
+Transfer (struct connectdata *data,
          int sockfd,           /* socket to read from or -1 */
          int size,             /* -1 if unknown at this point */
          bool getheader,       /* TRUE if header parsing is wanted */
index 274cd2d..6ac8847 100644 (file)
@@ -81,16 +81,15 @@ char *curl_escape(char *string)
    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);
    unsigned char in;
    int index=0;
    int hex;
-   
-
-   while(*string) {
+  
+   while(--alloc) {
       in = *string;
       if('+' == in)
         in = ' ';
index bca4d8b..5c080c2 100644 (file)
@@ -44,6 +44,6 @@
  * allocated string or NULL if an error occurred.  */
 
 char *curl_escape(char *string);
-char *curl_unescape(char *string);
+char *curl_unescape(char *string, int length);
 
 #endif
index af96601..532a65f 100644 (file)
 #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 
      RFC 1738. Only local files (reachable via the standard file system)
      are supported. This means that files on remotely mounted directories
      (via NFS, Samba, NT sharing) can be accessed through a file:// URL
   */
-
+  CURLcode res = CURLE_OK;
+  char *path = conn->path;
   struct stat statbuf;
   size_t expected_size=-1;
   size_t nread;
+  struct UrlData *data = conn->data;
   char *buf = data->buffer;
   int bytecount = 0;
   struct timeval start = tvnow();
   struct timeval now = start;
   int fd;
-  char *actual_path = curl_unescape(path);
+  char *actual_path = curl_unescape(path, 0);
 
 #if defined(WIN32) || defined(__EMX__)
   int i;
@@ -134,7 +136,7 @@ UrgError file(struct UrlData *data, char *path, long *bytecountp)
 
   if(fd == -1) {
     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)) {
     /* 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)
     pgrsSetDownloadSize(data, expected_size);
 
-  while (1) {
+  while (res == CURLE_OK) {
     nread = read(fd, buf, BUFSIZE-1);
 
     if (0 <= nread)
@@ -166,21 +168,19 @@ UrgError file(struct UrlData *data, char *path, long *bytecountp)
        file descriptor). */
     if(nread != data->fwrite (buf, 1, nread, data->out)) {
       failf (data, "Failed writing output");
-      return URG_WRITE_ERROR;
+      return CURLE_WRITE_ERROR;
     }
     now = tvnow();
-    pgrsUpdate(data);
-#if 0
-    ProgressShow (data, bytecount, start, now, FALSE);
-#endif
+    if(pgrsUpdate(data))
+      res = CURLE_ABORTED_BY_CALLBACK;
   }
   now = tvnow();
-#if 0
-  ProgressShow (data, bytecount, start, now, TRUE);
-#endif
-  pgrsUpdate(data);
+  if(pgrsUpdate(data))
+    res = CURLE_ABORTED_BY_CALLBACK;
 
   close(fd);
 
-  return URG_OK;
+  free(actual_path);
+
+  return res;
 }
index eeaeef4..e6ad0e6 100644 (file)
@@ -40,6 +40,6 @@
  *
  * ------------------------------------------------------------
  ****************************************************************************/
-UrgError file(struct UrlData *data, char *path, long *bytecountp);
+CURLcode file(struct connectdata *conn);
 
 #endif
index eff0212..fb6ad0f 100644 (file)
@@ -60,6 +60,8 @@
 #include <curl/curl.h>
 #include "formdata.h"
 
+#include "strequal.h"
+
 /* Length of the random boundary string. The risk of this being used
    in binary data is very close to zero, 64^32 makes
    6277101735386680763835789423207666416102355444464034512896
@@ -377,7 +379,7 @@ void FormFree(struct FormData *form)
     free(form->line); /* free the line */
     free(form);       /* free the struct */
 
-  } while(form=next); /* continue */
+  } while((form=next)); /* continue */
 }
 
 struct FormData *getFormData(struct HttpPost *post,
@@ -513,11 +515,16 @@ struct FormData *getFormData(struct HttpPost *post,
 
 int FormInit(struct Form *form, struct FormData *formdata )
 {
-  form->data = formdata;
-  form->sent = 0;
-
   if(!formdata)
     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;
 }
index 4af86fb..0844cc7 100644 (file)
--- a/lib/ftp.c
+++ b/lib/ftp.c
@@ -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)
 {
   fd_set rdset;
@@ -167,11 +167,11 @@ static UrgError AllowServerConnect(struct UrlData *data,
   case -1: /* error */
     /* let's die here */
     failf(data, "Error while waiting for server connect");
-    return URG_FTP_PORT_FAILED;
+    return CURLE_FTP_PORT_FAILED;
   case 0:  /* timeout */
     /* let's die here */
     failf(data, "Timeout while waiting for server connect");
-    return URG_FTP_PORT_FAILED;
+    return CURLE_FTP_PORT_FAILED;
   default:
     /* we have received data here */
     {
@@ -185,7 +185,7 @@ static UrgError AllowServerConnect(struct UrlData *data,
       if( -1 == s) {
        /* DIE! */
        failf(data, "Error accept()ing server connect");
-       return URG_FTP_PORT_FAILED;
+       return CURLE_FTP_PORT_FAILED;
       }
       infof(data, "Connection accepted from server\n");
 
@@ -193,7 +193,7 @@ static UrgError AllowServerConnect(struct UrlData *data,
     }
     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]) && \
                        isdigit((int)line[2]) && (' ' == line[3]))
 
-static int GetLastResponse(int sockfd, char *buf,
+int GetLastResponse(int sockfd, char *buf,
                           struct UrlData *data)
 {
   int nread;
@@ -230,7 +230,7 @@ static int GetLastResponse(int sockfd, char *buf,
     }
     *ptr=0; /* zero terminate */
 
-    if(data->conf & CONF_VERBOSE) {
+    if(data->bits.verbose) {
       fputs("< ", data->err);
       fwrite(buf, 1, nread, data->err);
       fputs("\n", data->err);
@@ -310,32 +310,37 @@ static char *URLfix(char *string)
 }
 #endif
 
-static
-UrgError _ftp(struct UrlData *data,
-              long *bytecountp,
-              char *ftpuser,
-              char *ftppasswd,
-              char *ppath)
+/* ftp_connect() should do everything that is to be considered a part
+   of the connection phase. */
+CURLcode ftp_connect(struct connectdata *conn)
 {
   /* this is FTP and no proxy */
   size_t nread;
-  UrgError 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 FTP *ftp;
 
-  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: */
   nread = GetLastResponse(data->firstsocket, buf, data);
   if(strncmp(buf, "220", 3)) {
     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 */
-  sendf(data->firstsocket, data, "USER %s\r\n", ftpuser);
+  sendf(data->firstsocket, data, "USER %s\r\n", ftp->user);
 
   /* wait for feedback */
   nread = GetLastResponse(data->firstsocket, buf, data);
@@ -344,19 +349,19 @@ UrgError _ftp(struct UrlData *data,
     /* 530 User ... access denied
        (the server denies to log the specified user) */
     failf(data, "Access denied: %s", &buf[4]);
-    return URG_FTP_ACCESS_DENIED;
+    return CURLE_FTP_ACCESS_DENIED;
   }
   else if(!strncmp(buf, "331", 3)) {
     /* 331 Password required for ...
        (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);
 
     if(!strncmp(buf, "530", 3)) {
       /* 530 Login incorrect.
          (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)) {
       /* 230 User ... logged in.
@@ -366,7 +371,7 @@ UrgError _ftp(struct UrlData *data,
     }
     else {
       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)) {
@@ -376,9 +381,105 @@ UrgError _ftp(struct UrlData *data,
   }
   else {
     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? */
   if(data->quote) {
     qitem = data->quote;
@@ -393,7 +494,7 @@ UrgError _ftp(struct UrlData *data,
         if (buf[0] != '2') {
           failf(data, "QUOT string not accepted: %s",
                 qitem->data);
-          return URG_FTP_QUOTE_ERROR;
+          return CURLE_FTP_QUOTE_ERROR;
         }
       }
       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.
      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
        may not support it! It is however the only way we have to get a file's
        size! */
     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);
 
     if(strncmp(buf, "213", 3)) {
       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: */
     filesize = atoi(buf+4);
@@ -422,21 +523,21 @@ UrgError _ftp(struct UrlData *data,
 
     if(strlen(buf) != data->fwrite(buf, 1, strlen(buf), data->out)) {
       failf (data, "Failed writing output");
-      return URG_WRITE_ERROR;
+      return CURLE_WRITE_ERROR;
     }
     if(data->writeheader) {
       /* the header is requested to be written to this file */
       if(strlen(buf) != data->fwrite (buf, 1, strlen(buf),
                                       data->writeheader)) {
         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 */
-  if(data->conf & CONF_FTPPORT) {
+  if(data->bits.ftp_use_port) {
     struct sockaddr_in sa;
     struct hostent *h=NULL;
     size_t size;
@@ -481,28 +582,28 @@ UrgError _ftp(struct UrlData *data,
           if(getsockname(portsock, (struct sockaddr *) &add,
                          (int *)&size)<0) {
             failf(data, "getsockname() failed");
-            return URG_FTP_PORT_FAILED;
+            return CURLE_FTP_PORT_FAILED;
           }
           porttouse = ntohs(add.sin_port);
 
           if ( listen(portsock, 1) < 0 ) {
             failf(data, "listen(2) failed on socket");
-            return URG_FTP_PORT_FAILED;
+            return CURLE_FTP_PORT_FAILED;
           }
         }
         else {
           failf(data, "bind(2) failed on socket");
-          return URG_FTP_PORT_FAILED;
+          return CURLE_FTP_PORT_FAILED;
         }
       }
       else {
         failf(data, "socket(2) failed (%s)");
-        return URG_FTP_PORT_FAILED;
+        return CURLE_FTP_PORT_FAILED;
       }
     }
     else {
       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;
@@ -520,7 +621,7 @@ UrgError _ftp(struct UrlData *data,
 
     if(strncmp(buf, "200", 3)) {
       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 */
@@ -531,7 +632,7 @@ UrgError _ftp(struct UrlData *data,
 
     if(strncmp(buf, "227", 3)) {
       failf(data, "Odd return code after PASV");
-      return URG_FTP_WEIRD_PASV_REPLY;
+      return CURLE_FTP_WEIRD_PASV_REPLY;
     }
     else {
       int ip[4];
@@ -561,13 +662,13 @@ UrgError _ftp(struct UrlData *data,
       }
       if(!*str) {
         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]);
       he = GetHost(data, newhost);
       if(!he) {
         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_port = htons(newport);
 
-      if(data->conf & CONF_VERBOSE) {
+      if(data->bits.verbose) {
         struct in_addr in;
 #if 1
         struct hostent * answer;
@@ -620,26 +721,38 @@ UrgError _ftp(struct UrlData *data,
           failf(data, "Can't connect to ftp server");
           break;
         }
-        return URG_FTP_CANT_RECONNECT;
+        return CURLE_FTP_CANT_RECONNECT;
       }
     }
 
   }
   /* 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) */
     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);
 
     if(strncmp(buf, "200", 3)) {
       failf(data, "Couldn't set %s mode",
-            (data->conf&CONF_FTPASCII)?"ASCII":"binary");
-      return (data->conf&CONF_FTPASCII)? URG_FTP_COULDNT_SET_ASCII:
-        URG_FTP_COULDNT_SET_BINARY;
+            (data->bits.ftp_ascii)?"ASCII":"binary");
+      return (data->bits.ftp_ascii)? CURLE_FTP_COULDNT_SET_ASCII:
+        CURLE_FTP_COULDNT_SET_BINARY;
     }
 
     if(data->resume_from) {
@@ -660,13 +773,13 @@ UrgError _ftp(struct UrlData *data,
         /* we could've got a specified offset from the command line,
            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);
 
         if(strncmp(buf, "213", 3)) {
           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: */
@@ -687,11 +800,11 @@ UrgError _ftp(struct UrlData *data,
 
         if(strncmp(buf, "350", 3)) {
           failf(data, "Couldn't use REST: %s", buf+4);
-          return URG_FTP_COULDNT_USE_REST;
+          return CURLE_FTP_COULDNT_USE_REST;
         }
 #else
         /* enable append instead */
-        data->conf |= CONF_FTPAPPEND;
+        data->bits.ftp_append = 1;
 #endif
         /* 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
@@ -710,7 +823,7 @@ UrgError _ftp(struct UrlData *data,
           if(actuallyread != readthisamountnow) {
             failf(data, "Could only read %d bytes from the input\n",
                   passed);
-            return URG_FTP_COULDNT_USE_REST;
+            return CURLE_FTP_COULDNT_USE_REST;
           }
         }
         while(passed != data->resume_from);
@@ -721,7 +834,7 @@ UrgError _ftp(struct UrlData *data,
 
           if(data->infilesize <= 0) {
             infof(data, "File already completely uploaded\n");
-            return URG_OK;
+            return CURLE_OK;
           }
         }
         /* we've passed, proceed as normal */
@@ -729,21 +842,21 @@ UrgError _ftp(struct UrlData *data,
     }
 
     /* 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 */
-      sendf(data->firstsocket, data, "APPE %s\r\n", ppath);
+      sendf(data->firstsocket, data, "APPE %s\r\n", ftp->file);
     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);
 
     if(atoi(buf)>=400) {
       failf(data, "Failed FTP upload:%s", buf+3);
       /* 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);
       if( result )
         return result;
@@ -758,24 +871,19 @@ UrgError _ftp(struct UrlData *data,
 #if 0
     ProgressInit(data, data->infilesize);
 #endif
-    result = Transfer(data, -1, -1, FALSE, NULL, /* no download */
+    result = Transfer(conn, -1, -1, FALSE, NULL, /* no download */
                       data->secondarysocket, bytecountp);
     if(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 {
     /* Retrieve file or directory */
     bool dirlist=FALSE;
     long downloadsize=-1;
 
-    if(data->conf&CONF_RANGE && data->range) {
-      int from, to;
+    if(data->bits.set_range && data->range) {
+      long from, to;
       int totalsize=-1;
       char *ptr;
       char *ptr2;
@@ -788,32 +896,34 @@ UrgError _ftp(struct UrlData *data,
         /* we didn't get any digit */
         to=-1;
       }
-      if(-1 == to) {
+      if((-1 == to) && (from>=0)) {
         /* X - */
         data->resume_from = from;
+        infof(data, "FTP RANGE %d to end of file\n", from);
       }
       else if(from < 0) {
         /* -Y */
-        from = 0;
-        to = -from;
-        totalsize = to-from;
-        data->maxdownload = totalsize;
+        totalsize = -from;
+        data->maxdownload = -from;
+        data->resume_from = from;
+        infof(data, "FTP RANGE the last %d bytes\n", totalsize);
       }
       else {
-        /* X- */
+        /* X-Y */
         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",
             from, to, totalsize);
     }
-
+#if 0
     if(!ppath[0])
       /* make sure this becomes a valid name */
       ppath="./";
-
-    if((data->conf & CONF_FTPLISTONLY) ||
-       ('/' == ppath[strlen(ppath)-1] )) {
+#endif
+    if((data->bits.ftp_list_only) || !ftp->file) {
       /* The specified path ends with a slash, and therefore we think this
          is a directory that is requested, use LIST. But before that we
          need to set ASCII transfer mode. */
@@ -826,30 +936,29 @@ UrgError _ftp(struct UrlData *data,
        
       if(strncmp(buf, "200", 3)) {
         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
          better used since the LIST command output is not specified or
          standard in any way */
 
-      sendf(data->firstsocket, data, "%s %s\r\n",
+      sendf(data->firstsocket, data, "%s\r\n",
             data->customrequest?data->customrequest:
-            (data->conf&CONF_FTPLISTONLY?"NLST":"LIST"),
-            ppath);
+            (data->bits.ftp_list_only?"NLST":"LIST"));
     }
     else {
       /* Set type to binary (unless specified ASCII) */
       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);
 
       if(strncmp(buf, "200", 3)) {
         failf(data, "Couldn't set %s mode",
-              (data->conf&CONF_FTPASCII)?"ASCII":"binary");
-        return (data->conf&CONF_FTPASCII)? URG_FTP_COULDNT_SET_ASCII:
-          URG_FTP_COULDNT_SET_BINARY;
+              (data->bits.ftp_ascii)?"ASCII":"binary");
+        return (data->bits.ftp_ascii)? CURLE_FTP_COULDNT_SET_ASCII:
+          CURLE_FTP_COULDNT_SET_BINARY;
       }
 
       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
          * 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);
 
@@ -875,13 +984,27 @@ UrgError _ftp(struct UrlData *data,
           int foundsize=atoi(buf+4);
           /* 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.  */
-          if(foundsize <= data->resume_from) {
-            failf(data, "Offset (%d) was beyond file size (%d)",
-                  data->resume_from, foundsize);
-            return URG_FTP_BAD_DOWNLOAD_RESUME;
+          if(data->resume_from< 0) {
+            /* We're supposed to download the last abs(from) bytes */
+            if(foundsize < -data->resume_from) {
+              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 */
@@ -894,11 +1017,11 @@ UrgError _ftp(struct UrlData *data,
 
         if(strncmp(buf, "350", 3)) {
           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);
@@ -968,12 +1091,12 @@ UrgError _ftp(struct UrlData *data,
         if(size <= 0) {
           failf(data, "Offset (%d) was beyond file size (%d)",
                 data->resume_from, data->resume_from+size);
-          return URG_PARTIAL_FILE;
+          return CURLE_PARTIAL_FILE;
         }
       }
 #endif
 
-      if(data->conf & CONF_FTPPORT) {
+      if(data->bits.ftp_use_port) {
         result = AllowServerConnect(data, portsock);
         if( result )
           return result;
@@ -982,95 +1105,74 @@ UrgError _ftp(struct UrlData *data,
       infof(data, "Getting file with size: %d\n", size);
 
       /* FTP download: */
-      result=Transfer(data, data->secondarysocket, size, FALSE,
+      result=Transfer(conn, data->secondarysocket, size, FALSE,
                       bytecountp,
                       -1, NULL); /* no upload here */
       if(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 {
       failf(data, "%s", buf+4);
-      return URG_FTP_COULDNT_RETR_FILE;
+      return CURLE_FTP_COULDNT_RETR_FILE;
     }
        
   }
   /* end of transfer */
-#if 0
-  ProgressEnd(data);
-#endif
-  pgrsDone(data);
-
-  /* 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 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;
+  return CURLE_OK;
 }
 
 /* -- deal with the ftp server!  -- */
 
-UrgError ftp(struct UrlData *data,
-             long *bytecountp,
-             char *ftpuser,
-             char *ftppasswd,
-             char *urlpath)
+/* argument is already checked for validity */
+CURLcode ftp(struct connectdata *conn)
 {
-  char *realpath;
-  UrgError retcode;
+  CURLcode retcode;
 
-#if 0
-  realpath = URLfix(urlpath);
-#else
-  realpath = curl_unescape(urlpath);
-#endif
-  if(realpath) {
-    retcode = _ftp(data, bytecountp, ftpuser, ftppasswd, realpath);
-    free(realpath);
+  struct UrlData *data = conn->data;
+  struct FTP *ftp;
+  int dirlength=0; /* 0 forces strlen() */
+
+  /* the ftp struct is already inited in ftp_connect() */
+  ftp = data->proto.ftp;
+
+  /* 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
-    /* then we try the original path */
-    retcode = _ftp(data, bytecountp, ftpuser, ftppasswd, urlpath);
+    ftp->file=NULL; /* instead of point to a zero byte, we make it a NULL
+                       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;
 }
index b7d2659..3eb73e1 100644 (file)
--- a/lib/ftp.h
+++ b/lib/ftp.h
  *
  * ------------------------------------------------------------
  ****************************************************************************/
-UrgError ftp(struct UrlData *data,
-             long *bytecountp,
-             char *ftpuser,
-             char *ftppasswd,
-             char *ppath);
+CURLcode ftp(struct connectdata *conn);
+CURLcode ftp_done(struct connectdata *conn);
+CURLcode ftp_connect(struct connectdata *conn);
 
 struct curl_slist *curl_slist_append(struct curl_slist *list, char *data);
 void curl_slist_free_all(struct curl_slist *list);
index 021ed85..75efdcf 100644 (file)
@@ -1864,7 +1864,7 @@ difftm (struct tm *a, struct tm *b)
 }
 
 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;
   time_t Start;
@@ -1998,7 +1998,7 @@ main (ac, av)
   buff[MAX_BUFF_LEN] = 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)
        (void) printf ("Bad format - couldn't convert.\n");
       else
index 674c474..ebb6d2c 100644 (file)
@@ -1,18 +1,11 @@
-/*  Copyright (C) 1995, 1997, 1998 Free Software Foundation, Inc.
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2, or (at your option)
-   any later version.
-
-   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.  */
+/*
+**  Originally written by Steven M. Bellovin <smb@research.att.com> while
+**  at the University of North Carolina at Chapel Hill.  Later tweaked by
+**  a couple of people on Usenet.  Completely overhauled by Rich $alz
+**  <rsalz@bbn.com> and Jim Berets <jberets@bbn.com> in August, 1990.
+**
+**  This code is in the public domain and has no copyright.
+*/
 
 #if HAVE_CONFIG_H
 # include <config.h>
@@ -43,4 +36,4 @@
 # endif
 #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));
index efcf042..80f1012 100644 (file)
@@ -914,7 +914,7 @@ difftm (struct tm *a, struct tm *b)
 }
 
 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;
   time_t Start;
@@ -1048,7 +1048,7 @@ main (ac, av)
   buff[MAX_BUFF_LEN] = 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)
        (void) printf ("Bad format - couldn't convert.\n");
       else
index e39d3c1..54b0118 100644 (file)
  *  Portions created by the Initial Developer are Copyright (C) 1998.
  *  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:
  * - Daniel Stenberg <Daniel.Stenberg@haxx.nu>
  * $State$
  * $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>
index 3f030b4..0f41e7c 100644 (file)
@@ -94,6 +94,9 @@
 #include "progress.h"
 #include "base64.h"
 #include "cookie.h"
+#include "strequal.h"
+#include "url.h"
+#include "ssluse.h"
 
 #define _MPRINTF_REPLACE /* use our functions only */
 #include <curl/mprintf.h>
@@ -115,33 +118,114 @@ bool static checkheaders(struct UrlData *data, char *thisheader)
   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 FormData *sendit=NULL;
-  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 ( (data->conf&(CONF_HTTP|CONF_FTP)) &&
-       (data->conf&CONF_UPLOAD)) {
-    data->conf |= CONF_PUT;
+  struct UrlData *data;
+
+  data=conn->data;
+
+  /* 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) {
+
+        /* OK, now send the connect statment */
+        sendf(data->firstsocket, data,
+              "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;
+     }
+  }
+
+   return CURLE_OK;
+}
+CURLcode http_done(struct connectdata *conn)
+{
+  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 */
   }
-#if 0 /* old version */
-  if((data->conf&(CONF_HTTP|CONF_UPLOAD)) ==
-     (CONF_HTTP|CONF_UPLOAD)) {
-    /* enable PUT! */
-    data->conf |= CONF_PUT;
+  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
      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;
   }
 
-  if((data->conf & CONF_USERPWD) && !checkheaders(data, "Authorization:")) {
+  if((data->bits.user_passwd) && !checkheaders(data, "Authorization:")) {
     char authorization[512];
     sprintf(data->buffer, "%s:%s", data->user, data->passwd);
     base64Encode(data->buffer, authorization);
     data->ptr_userpwd = maprintf( "Authorization: Basic %s\015\012",
                                   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);
   }
-  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);
   }
   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,
                         host,
                         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 */
     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
        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:"))
@@ -190,10 +274,10 @@ UrgError http(struct UrlData *data, char *ppath, char *host, long *bytecount)
 
 
   if(!checkheaders(data, "Pragma:"))
-    p_pragma = "Pragma: no-cache\r\n";
+    http->p_pragma = "Pragma: no-cache\r\n";
 
   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 {
     sendf(data->firstsocket, data,
@@ -210,19 +294,19 @@ UrgError http(struct UrlData *data, char *ppath, char *host, long *bytecount)
           "%s", /* referer */
 
           data->customrequest?data->customrequest:
-          (data->conf&CONF_NOBODY?"HEAD":
-           (data->conf&(CONF_POST|CONF_HTTPPOST))?"POST":
-           (data->conf&CONF_PUT)?"PUT":"GET"),
+          (data->bits.no_body?"HEAD":
+           (data->bits.http_post || data->bits.http_formpost)?"POST":
+           (data->bits.http_put)?"PUT":"GET"),
           ppath,
-          (data->conf&CONF_PROXYUSERPWD && data->ptr_proxyuserpwd)?data->ptr_proxyuserpwd:"",
-          (data->conf&CONF_USERPWD && data->ptr_userpwd)?data->ptr_userpwd:"",
-          (data->conf&CONF_RANGE && data->ptr_rangeline)?data->ptr_rangeline:"",
+          (data->bits.proxy_user_passwd && data->ptr_proxyuserpwd)?data->ptr_proxyuserpwd:"",
+          (data->bits.user_passwd && data->ptr_userpwd)?data->ptr_userpwd:"",
+          (data->bits.set_range && data->ptr_rangeline)?data->ptr_rangeline:"",
           (data->useragent && *data->useragent && data->ptr_uagent)?data->ptr_uagent:"",
           (data->ptr_cookie?data->ptr_cookie:""), /* Cookie: <data> */
           (data->ptr_host?data->ptr_host:""), /* Host: host */
-          p_pragma?p_pragma:"",
-          p_accept?p_accept:"",
-          (data->conf&CONF_REFERER && data->ptr_ref)?data->ptr_ref:"" /* Referer: <data> <CRLF> */
+          http->p_pragma?http->p_pragma:"",
+          http->p_accept?http->p_accept:"",
+          (data->bits.http_set_referer && data->ptr_ref)?data->ptr_ref:"" /* Referer: <data> <CRLF> */
           );
 
     if(co) {
@@ -234,9 +318,10 @@ UrgError http(struct UrlData *data, char *ppath, char *host, long *bytecount)
             sendf(data->firstsocket, data,
                   "Cookie:");
           }
-          count++;
           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 */
       }
@@ -284,8 +369,8 @@ UrgError http(struct UrlData *data, char *ppath, char *host, long *bytecount)
       data->headers = data->headers->next;
     }
 
-    if(data->conf&(CONF_POST|CONF_HTTPPOST)) {
-      if(data->conf & CONF_POST) {
+    if(data->bits.http_post || data->bits.http_formpost) {
+      if(data->bits.http_post) {
         /* this is the simple x-www-form-urlencoded style */
         sendf(data->firstsocket, data,
               "Content-Length: %d\015\012"
@@ -295,53 +380,39 @@ UrgError http(struct UrlData *data, char *ppath, char *host, long *bytecount)
               data->postfields );
       }
       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");
-          return URG_HTTP_POST_ERROR;
+          return CURLE_HTTP_POST_ERROR;
         }
 
-        storefread = data->fread; /* backup */
-        in = data->in; /* backup */
+        http->storefread = data->fread; /* backup */
+        http->in = data->in; /* backup */
           
         data->fread =
           (size_t (*)(char *, size_t, size_t, FILE *))
           FormReader; /* set the read function to read from the
                          generated form data */
-        data->in = (FILE *)&form;
+        data->in = (FILE *)&http->form;
 
         sendf(data->firstsocket, data,
               "Content-Length: %d\r\n",
-              postsize-2);
+              http->postsize-2);
 
-       pgrsSetUploadSize(data, postsize);
-#if 0
-        ProgressInit(data, postsize);
-#endif
+       pgrsSetUploadSize(data, http->postsize);
 
-        result = Transfer(data, data->firstsocket, -1, TRUE, &readbytecount,
-                          data->firstsocket, &writebytecount);
-        *bytecount = readbytecount + writebytecount;
-
-        FormFree(sendit); /* Now free that whole lot */
-
-        if(result)
+        result = Transfer(conn, data->firstsocket, -1, TRUE,
+                          &http->readbytecount,
+                          data->firstsocket,
+                          &http->writebytecount);
+        if(result) {
+          FormFree(http->sendit); /* free that whole lot */
           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! */
-      long conf;
 
       if(data->infilesize>0) {
         sendf(data->firstsocket, data,
@@ -352,39 +423,28 @@ UrgError http(struct UrlData *data, char *ppath, char *host, long *bytecount)
         sendf(data->firstsocket, data,
               "\015\012");
 
-#if 0        
-      ProgressInit(data, data->infilesize);
-#endif
       pgrsSetUploadSize(data, data->infilesize);
 
-      result = Transfer(data, data->firstsocket, -1, TRUE, &readbytecount,
-                        data->firstsocket, &writebytecount);
-      
-      *bytecount = readbytecount + writebytecount;
-
+      result = Transfer(conn, data->firstsocket, -1, TRUE,
+                        &http->readbytecount,
+                        data->firstsocket,
+                        &http->writebytecount);
       if(result)
         return result;
 
     }
     else {
       sendf(data->firstsocket, data, "\r\n");
-    }
-    if(0 == *bytecount) {
+
       /* 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 */
     }
     if(result)
       return result;
-
-#if 0      
-    ProgressEnd(data);
-#endif
-    pgrsDone(data);
-
   } while (0); /* this is just a left-over from the multiple document download
                   attempts */
 
-  return URG_OK;
+  return CURLE_OK;
 }
 
index be35842..6a4d8c8 100644 (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
index dde1587..e38135c 100644 (file)
@@ -72,7 +72,7 @@
 #define DYNA_GET_FUNCTION(type, fnc) \
   (fnc) = (type)DynaGetFunction(#fnc); \
   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)
 {
   struct UrlData *data = (struct UrlData *)param;
-  
-  printf("%s\n", text);
+
+  data->fwrite(text, 1, strlen(text), data->out);
   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;
   void *(*ldap_open)(char *, int);
   int (*ldap_simple_bind_s)(void *, char *, char *);
@@ -152,24 +157,19 @@ UrgError ldap(struct UrlData *data, char *path, long *bytecount)
   void *server;
   void *result;
   void *entryIterator;
-#if 0
-  char *dn;
-  char **attrArray;
-  char *attrIterator;
-  char *attrString;
-  void *dummy;
-#endif
+
   int ldaptext;
+  struct UrlData *data=conn->data;
   
   infof(data, "LDAP: %s %s\n", data->url);
 
   DynaOpen();
   if (libldap == NULL) {
     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
    * pointer-to-object (data) and pointer-to-function.
@@ -188,17 +188,17 @@ UrgError ldap(struct UrlData *data, char *path, long *bytecount)
   if (server == NULL) {
     failf(data, "LDAP: Cannot connect to %s:%d",
          data->hostname, data->port);
-    status = URG_COULDNT_CONNECT;
+    status = CURLE_COULDNT_CONNECT;
   } else {
     rc = ldap_simple_bind_s(server, data->user, data->passwd);
     if (rc != 0) {
       failf(data, "LDAP: %s", ldap_err2string(rc));
-      status = URG_LDAP_CANNOT_BIND;
+      status = CURLE_LDAP_CANNOT_BIND;
     } else {
       rc = ldap_url_search_s(server, data->url, 0, &result);
       if (rc != 0) {
        failf(data, "LDAP: %s", ldap_err2string(rc));
-       status = URG_LDAP_SEARCH_FAILED;
+       status = CURLE_LDAP_SEARCH_FAILED;
       } else {
        for (entryIterator = ldap_first_entry(server, result);
             entryIterator;
@@ -210,7 +210,7 @@ UrgError ldap(struct UrlData *data, char *path, long *bytecount)
                                   "", 0, 0);
              if (rc != 0) {
                failf(data, "LDAP: %s", ldap_err2string(rc));
-               status = URG_LDAP_SEARCH_FAILED;
+               status = CURLE_LDAP_SEARCH_FAILED;
              }
            } else {
              rc = ldap_entry2html(server, NULL, entryIterator, NULL,
@@ -218,7 +218,7 @@ UrgError ldap(struct UrlData *data, char *path, long *bytecount)
                                   "", 0, 0, NULL, NULL);
              if (rc != 0) {
                failf(data, "LDAP: %s", ldap_err2string(rc));
-               status = URG_LDAP_SEARCH_FAILED;
+               status = CURLE_LDAP_SEARCH_FAILED;
              }
            }
          }
index d88880e..0fcacc0 100644 (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 */
index f0e1382..73d94ab 100644 (file)
@@ -56,6 +56,7 @@
 
 #include "setup.h"
 #include "getenv.h"
+#include "strequal.h"
 
 /* Debug this single source file with:
    'make netrc' then run './netrc'!
index 1bb5aec..35847fa 100644 (file)
@@ -118,7 +118,7 @@ void pgrsDone(struct UrlData *data)
 void pgrsMode(struct UrlData *data, int mode)
 {
   /* 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 */
   else {
     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;
 
+  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)
     ; /* 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
@@ -206,133 +232,109 @@ void pgrsUpdate(struct UrlData *data)
 
   now = tvnow(); /* what time is it */
 
-  switch(data->progress.mode) {
-  case CURL_PROGRESS_STATS:
-  default:
-    {
-      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.lastshow == tvlong(now))
-        return; /* never update this more than once a second if the end isn't 
-                   reached */
-      data->progress.lastshow = now.tv_sec;
+  if(data->progress.lastshow == tvlong(now))
+    return 0; /* 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 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 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);
+  /* 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
+  /* Let's do the "current speed" thing, which should use the fastest
          of the dl/ul speeds */
 
-      speeder[ nowindex ] = data->progress.downloaded>data->progress.uploaded?
-        data->progress.downloaded:data->progress.uploaded;
-      speeder_c++; /* increase */
-      count = ((speeder_c>=CURR_TIME)?CURR_TIME:speeder_c) - 1;
-      checkindex = (speeder_c>=CURR_TIME)?speeder_c%CURR_TIME:0;
+  speeder[ nowindex ] = data->progress.downloaded>data->progress.uploaded?
+    data->progress.downloaded:data->progress.uploaded;
+  speeder_c++; /* increase */
+  count = ((speeder_c>=CURR_TIME)?CURR_TIME:speeder_c) - 1;
+  checkindex = (speeder_c>=CURR_TIME)?speeder_c%CURR_TIME:0;
 
-      /* find out the average speed the last CURR_TIME seconds */
-      data->progress.current_speed =
-        (speeder[nowindex]-speeder[checkindex])/(count?count:1);
+  /* find out the average speed the last CURR_TIME seconds */
+  data->progress.current_speed =
+    (speeder[nowindex]-speeder[checkindex])/(count?count:1);
 
-      if(data->progress.flags & PGRS_HIDE)
-        return;
+  if(data->progress.flags & PGRS_HIDE)
+    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 */
-      if(data->progress.flags & PGRS_UL_SIZE_KNOWN) {
-        if(!data->progress.ulspeed)
-          data->progress.ulspeed=1;
-        ulestimate = data->progress.size_ul / data->progress.ulspeed;
-        ulpercen = (data->progress.uploaded / data->progress.size_ul)*100;
-      }
+  if(data->progress.flags & PGRS_UL_SIZE_KNOWN) {
+    if(!data->progress.ulspeed)
+      data->progress.ulspeed=1;
+    ulestimate = data->progress.size_ul / data->progress.ulspeed;
+    ulpercen = (data->progress.uploaded / data->progress.size_ul)*100;
+  }
 
-      /* ... and the download */
-      if(data->progress.flags & PGRS_DL_SIZE_KNOWN) {
-        if(!data->progress.dlspeed)
-          data->progress.dlspeed=1;
-        dlestimate = data->progress.size_dl / data->progress.dlspeed;
-        dlpercen = (data->progress.downloaded / data->progress.size_dl)*100;
-      }
+  /* ... and the download */
+  if(data->progress.flags & PGRS_DL_SIZE_KNOWN) {
+    if(!data->progress.dlspeed)
+      data->progress.dlspeed=1;
+    dlestimate = data->progress.size_dl / data->progress.dlspeed;
+    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 = 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 */
-      if(total_estimate) {
-        time2str(time_left, total_estimate-(int) data->progress.timespent); 
-        time2str(time_total, total_estimate);
-      }
-      else {
-        /* otherwise we blank those times */
-        strcpy(time_left,  "--:--:--");
-        strcpy(time_total, "--:--:--");
-      }
-      /* The time spent so far is always known */
-      time2str(time_current, data->progress.timespent);
-
-      /* Get the total amount of data expected to get transfered */
-      total_expected_transfer = 
-        (data->progress.flags & PGRS_UL_SIZE_KNOWN?
-         data->progress.size_ul:data->progress.uploaded)+
-        (data->progress.flags & PGRS_DL_SIZE_KNOWN?
-         data->progress.size_dl:data->progress.downloaded);
+  if(total_estimate) {
+    time2str(time_left, total_estimate-(int) data->progress.timespent); 
+    time2str(time_total, total_estimate);
+  }
+  else {
+    /* otherwise we blank those times */
+    strcpy(time_left,  "--:--:--");
+    strcpy(time_total, "--:--:--");
+  }
+  /* The time spent so far is always known */
+  time2str(time_current, data->progress.timespent);
+
+  /* Get the total amount of data expected to get transfered */
+  total_expected_transfer = 
+    (data->progress.flags & PGRS_UL_SIZE_KNOWN?
+     data->progress.size_ul:data->progress.uploaded)+
+    (data->progress.flags & PGRS_DL_SIZE_KNOWN?
+     data->progress.size_dl:data->progress.downloaded);
       
-      /* We have transfered this much so far */
-      total_transfer = data->progress.downloaded + data->progress.uploaded;
-
-      /* Get the percentage of data transfered so far */
-      if(total_expected_transfer)
-        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 */
-              );
-    }
-    break;
+  /* We have transfered this much so far */
+  total_transfer = data->progress.downloaded + data->progress.uploaded;
+
+  /* Get the percentage of data transfered so far */
+  if(total_expected_transfer)
+    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 */
+          );
+
+
 #if 0
   case CURL_PROGRESS_BAR:
     /* original progress bar code by Lars Aas */
@@ -365,7 +367,8 @@ void pgrsUpdate(struct UrlData *data)
     prev = point;
     break;
 #endif
-  }
+
+    return 0;
 }
 
 
index 8c407f7..f4e0dcf 100644 (file)
@@ -52,13 +52,14 @@ typedef enum {
   TIMER_LAST /* must be last */
 } timerid;
   
+void pgrsDone(struct UrlData *data);
 void pgrsMode(struct UrlData *data, int mode);
 void pgrsStartNow(struct UrlData *data);
 void pgrsSetDownloadSize(struct UrlData *data, double size);
 void pgrsSetUploadSize(struct UrlData *data, double size);
 void pgrsSetDownloadCounter(struct UrlData *data, double size);
-     void pgrsSetUploadCounter(struct UrlData *data, double size);
-void pgrsUpdate(struct UrlData *data);
+void pgrsSetUploadCounter(struct UrlData *data, double size);
+int pgrsUpdate(struct UrlData *data);
 void pgrsTime(struct UrlData *data, timerid timer);
 
 
index 387984d..42c344d 100644 (file)
@@ -61,7 +61,7 @@
 void infof(struct UrlData *data, char *fmt, ...)
 {
   va_list ap;
-  if(data->conf & CONF_VERBOSE) {
+  if(data->bits.verbose) {
     va_start(ap, fmt);
     fputs("* ", data->err);
     vfprintf(data->err, fmt, ap);
@@ -95,7 +95,7 @@ int sendf(int fd, struct UrlData *data, char *fmt, ...)
   va_end(ap);
   if(!s)
     return 0; /* failure */
-  if(data->conf & CONF_VERBOSE)
+  if(data->bits.verbose)
     fprintf(data->err, "> %s", s);
 #ifndef USE_SSLEAY
    bytes_written = swrite(fd, s, strlen(s));
index 083e890..c800fa8 100644 (file)
@@ -57,8 +57,6 @@
 #endif
 #endif
 
-
-
 #ifndef OS
 #ifdef WIN32
 #define OS "win32"
@@ -99,6 +97,7 @@ defined(HAVE_LIBSSL) && defined(HAVE_LIBCRYPTO)
 #endif
 #endif
 
+#if 0
 #ifdef HAVE_STRCASECMP
 #define strnequal(x,y,z) !(strncasecmp)(x,y,z)
 #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 strequal(x,y) !stricmp(x,y)
 #endif
+#endif
 
 /* Below we define four functions. They should
    1. close a socket
index 5647b50..48772b3 100644 (file)
@@ -48,7 +48,7 @@
 #include "sendf.h"
 #include "speedcheck.h"
 
-UrgError speedcheck(struct UrlData *data,
+CURLcode speedcheck(struct UrlData *data,
                     struct timeval now)
 {
   static struct timeval keeps_speed;
@@ -69,13 +69,13 @@ UrgError speedcheck(struct UrlData *data,
            "Less than %d bytes/sec transfered the last %d seconds",
            data->low_speed_limit,
            data->low_speed_time);
-      return URG_OPERATION_TIMEOUTED;
+      return CURLE_OPERATION_TIMEOUTED;
     }
   }
   else {
     /* we keep up the required speed all right */
     keeps_speed = now;
   }
-  return URG_OK;
+  return CURLE_OK;
 }
 
index 27e7ba2..e07bdbc 100644 (file)
@@ -44,7 +44,7 @@
 
 #include "timeval.h"
 
-UrgError speedcheck(struct UrlData *data,
+CURLcode speedcheck(struct UrlData *data,
                     struct timeval now);
 
 #endif
index 0eae0a9..6eb9b77 100644 (file)
  * ------------------------------------------------------------
  ****************************************************************************/
 
+/*
+ * The original SSL code was written by
+ * Linas Vepstas <linas@linas.org> and Sampo Kellomaki <sampo@iki.fi>
+ */
+
+
 #include <string.h>
 #include <stdlib.h>
 
index 8ca1245..6857182 100644 (file)
@@ -225,7 +225,7 @@ static void printoption(struct UrlData *data,
    char *fmt;
    char *opt;
    
-   if (data->conf & CONF_VERBOSE)
+   if (data->bits.verbose)
    {
       if (cmd == IAC)
       {
@@ -628,7 +628,7 @@ static void printsub(struct UrlData *data,
 {
    int i = 0;
 
-   if (data->conf & CONF_VERBOSE)
+   if (data->bits.verbose)
    {
       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;
-   fd_set readfd;
-   fd_set keepfd;
+  return CURLE_OK;
+}
+
+CURLcode telnet(struct connectdata *conn)
+{
+  struct UrlData *data = conn->data;
+  int sockfd = data->firstsocket;
+  fd_set readfd;
+  fd_set keepfd;
 
-   bool keepon = TRUE;
-   char *buf = data->buffer;
-   int nread;
+  bool keepon = TRUE;
+  char *buf = data->buffer;
+  int nread;
 
-   init_telnet(data);
+  init_telnet(data);
    
-   FD_ZERO (&readfd);          /* clear it */
-   FD_SET (sockfd, &readfd);
-   FD_SET (1, &readfd);
+  FD_ZERO (&readfd);           /* clear it */
+  FD_SET (sockfd, &readfd);
+  FD_SET (1, &readfd);
 
-   keepfd = readfd;
+  keepfd = readfd;
 
    while (keepon)
    {
@@ -931,7 +937,7 @@ UrgError telnet(struct UrlData *data)
         telrcv(data, (unsigned char *)buf, nread);
       }
    }
-   return URG_OK;
+   return CURLE_OK;
 }
 
 
index 25b7f2d..f9d55b7 100644 (file)
@@ -40,6 +40,7 @@
  *
  * ------------------------------------------------------------
  ****************************************************************************/
-UrgError telnet(struct UrlData *data);
+CURLcode telnet(struct connectdata *conn);
+CURLcode telnet_done(struct connectdata *conn);
 
 #endif
index 75dd895..5938c57 100644 (file)
--- a/lib/url.c
+++ b/lib/url.c
  * ------------------------------------------------------------
  ****************************************************************************/
 
-/*
- * SSL code intially written by
- * Linas Vepstas <linas@linas.org> and Sampo Kellomaki <sampo@iki.fi>
- */
-
 /* -- WIN32 approved -- */
 #include <stdio.h>
 #include <string.h>
 #include "getpass.h"
 #include "progress.h"
 #include "cookie.h"
+#include "strequal.h"
+#include "writeout.h"
 
 /* And now for the protocols */
 #include "ftp.h"
 #include "http.h"
 #include "file.h"
 #include "ldap.h"
-#include "writeout.h"
+
+#include <curl/types.h>
 
 #define _MPRINTF_REPLACE /* use our functions only */
 #include <curl/mprintf.h>
 
 /* -- -- */
 
-/***********************************************************************
- * Start with some silly functions to make win32-systems survive
- ***********************************************************************/
-#if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__)
-static void win32_cleanup(void)
-{
-  WSACleanup();
-}
-
-static UrgError win32_init(void)
-{
-  WORD wVersionRequested;  
-  WSADATA wsaData; 
-  int err; 
-  wVersionRequested = MAKEWORD(1, 1); 
-    
-  err = WSAStartup(wVersionRequested, &wsaData); 
-    
-  if (err != 0) 
-    /* Tell the user that we couldn't find a useable */ 
-    /* winsock.dll.     */ 
-    return URG_FAILED_INIT; 
-    
-  /* Confirm that the Windows Sockets DLL supports 1.1.*/ 
-  /* Note that if the DLL supports versions greater */ 
-  /* than 1.1 in addition to 1.1, it will still return */ 
-  /* 1.1 in wVersion since that is the version we */ 
-  /* requested. */ 
-    
-  if ( LOBYTE( wsaData.wVersion ) != 1 || 
-       HIBYTE( wsaData.wVersion ) != 1 ) { 
-    /* Tell the user that we couldn't find a useable */ 
-
-    /* winsock.dll. */ 
-    WSACleanup(); 
-    return URG_FAILED_INIT; 
-  }
-  return URG_OK;
-}
-/* The Windows Sockets DLL is acceptable. Proceed. */ 
-#else
-static UrgError win32_init(void) { return URG_OK; }
-#define win32_cleanup()
-#endif
 
+CURLcode _urlget(struct UrlData *data);
 
-/*
- * This is the main global constructor for the lib. Call this before
- * _any_ libcurl usage. If this fails, *NO* libcurl functions may be
- * used, or havoc may be the result.
- */
-UrgError curl_init(void)
+/* does nothing, returns OK */
+CURLcode curl_init(void)
 {
-  return win32_init();
+  return CURLE_OK;
 }
 
-/*
- * This is the main global destructor for the lib. Call this after
- * _all_ libcurl usage is done.
- */
+/* does nothing */
 void curl_free(void)
 {
-  win32_cleanup();
 }
 
-static UrgError _urlget(struct UrlData *data);
-
-
 void urlfree(struct UrlData *data, bool totally)
 {
 #ifdef USE_SSLEAY
@@ -278,27 +222,78 @@ void urlfree(struct UrlData *data, bool totally)
   }
 }
 
-typedef struct UrlData CURL;
+CURLcode curl_close(CURL *curl)
+{
+  struct UrlData *data=(struct UrlData *)curl;
+  
+  void *protocol = data->proto.generic;
+
+  /* total session cleanup */
+  urlfree(data, TRUE);
+
+  if(protocol)
+    free(protocol);
+
+  free(data);
+
+  return CURLE_OK;
+}
 
-UrgError curl_open(CURL **curl, char *url)
+CURLcode curl_open(CURL **curl, char *url)
 {
   /* We don't yet support specifying the URL at this point */
+  struct UrlData *data;
 
   /* Very simple start-up: alloc the struct, init it with zeroes and return */
-  CURL *data = (CURL *)malloc(sizeof(CURL));
+  data = (struct UrlData *)malloc(sizeof(struct UrlData));
   if(data) {
-    memset(data, 0, sizeof(CURL));
+    memset(data, 0, sizeof(struct UrlData));
+    data->handle = STRUCT_OPEN;
+    data->interface = CURLI_NORMAL; /* normal interface by default */
+
+    /* We do some initial setup here, all those fields that can't be just 0 */
+
+    data-> headerbuff=(char*)malloc(HEADERSIZE);
+    if(!data->headerbuff) {
+      free(data); /* free the memory again */
+      return CURLE_OUT_OF_MEMORY;
+    }
+
+    data-> headersize=HEADERSIZE;
+
+#if 0
+    /* Let's set some default values: */
+    curl_setopt(data, CURLOPT_FILE, stdout); /* default output to stdout */
+    curl_setopt(data, CURLOPT_INFILE, stdin);  /* default input from stdin */
+    curl_setopt(data, CURLOPT_STDERR, stderr);  /* default stderr to stderr! */
+#endif
+
+    data->out = stdout; /* default output to stdout */
+    data->in  = stdin;  /* default input from stdin */
+    data->err  = stderr;  /* default stderr to stderr */
+
+    data->firstsocket = -1; /* no file descriptor */
+    data->secondarysocket = -1; /* no file descriptor */
+
+    /* use fwrite as default function to store output */
+    data->fwrite = (size_t (*)(char *, size_t, size_t, FILE *))fwrite;
+
+    /* use fread as default function to read input */
+    data->fread = (size_t (*)(char *, size_t, size_t, FILE *))fread;
+
+    data->infilesize = -1; /* we don't know any size */
+
+    data->current_speed = -1; /* init to negative == impossible */
+
     *curl = data;
-    return URG_OK;
+    return CURLE_OK;
   }
 
   /* this is a very serious error */
-  return URG_OUT_OF_MEMORY;
+  return CURLE_OUT_OF_MEMORY;
 }
 
-typedef unsigned int CURLoption;
-
-UrgError curl_setopt(CURL *curl, CURLoption option, ...)
+CURLcode curl_setopt(CURL *curl, CURLoption option, ...)
 {
   struct UrlData *data = curl;
   va_list param;
@@ -307,310 +302,187 @@ UrgError curl_setopt(CURL *curl, CURLoption option, ...)
   va_start(param, option);
 
   switch(option) {
-  case URGTAG_TIMECONDITION:
+  case CURLOPT_VERBOSE:
+    data->bits.verbose = va_arg(param, long);
+    break;
+  case CURLOPT_HEADER:
+    data->bits.http_include_header = va_arg(param, long);
+    break;
+  case CURLOPT_NOPROGRESS:
+    data->bits.hide_progress = va_arg(param, long);
+    if(data->bits.hide_progress)
+      data->progress.flags |= PGRS_HIDE;
+    break;
+  case CURLOPT_NOBODY:
+    data->bits.no_body = va_arg(param, long);
+    break;
+  case CURLOPT_FAILONERROR:
+    data->bits.http_fail_on_error = va_arg(param, long);
+    break;
+  case CURLOPT_UPLOAD:
+    data->bits.upload = va_arg(param, long);
+    break;
+  case CURLOPT_POST:
+    data->bits.http_post = va_arg(param, long);
+    break;
+  case CURLOPT_FTPLISTONLY:
+    data->bits.ftp_list_only = va_arg(param, long);
+    break;
+  case CURLOPT_FTPAPPEND:
+    data->bits.ftp_append = va_arg(param, long);
+    break;
+  case CURLOPT_NETRC:
+    data->bits.use_netrc = va_arg(param, long);
+    break;
+  case CURLOPT_FOLLOWLOCATION:
+    data->bits.http_follow_location = va_arg(param, long);
+    break;
+  case CURLOPT_FTPASCII:
+    data->bits.ftp_ascii = va_arg(param, long);
+    break;
+  case CURLOPT_PUT:
+    data->bits.http_put = va_arg(param, long);
+    break;
+  case CURLOPT_MUTE:
+    data->bits.mute = va_arg(param, long);
+    break;
+
+  case CURLOPT_TIMECONDITION:
     data->timecondition = va_arg(param, long);
     break;
 
-  case URGTAG_TIMEVALUE:
+  case CURLOPT_TIMEVALUE:
     data->timevalue = va_arg(param, long);
     break;
 
-  case URGTAG_SSLVERSION:
+  case CURLOPT_SSLVERSION:
     data->ssl_version = va_arg(param, long);
     break;
 
-  case URGTAG_COOKIEFILE:
+  case CURLOPT_COOKIEFILE:
     cookiefile = (char *)va_arg(param, void *);
     if(cookiefile) {
       data->cookies = cookie_init(cookiefile);
     }
     break;
-  case URGTAG_WRITEHEADER:
+  case CURLOPT_WRITEHEADER:
     data->writeheader = (FILE *)va_arg(param, FILE *);
     break;
-  case URGTAG_COOKIE:
+  case CURLOPT_COOKIE:
     data->cookie = va_arg(param, char *);
     break;
-  case URGTAG_ERRORBUFFER:
+  case CURLOPT_ERRORBUFFER:
     data->errorbuffer = va_arg(param, char *);
     break;
-  case URGTAG_FILE:
+  case CURLOPT_FILE:
     data->out = va_arg(param, FILE *);
     break;
-  case URGTAG_FTPPORT:
+  case CURLOPT_FTPPORT:
     data->ftpport = va_arg(param, char *);
+    data->bits.ftp_use_port = data->ftpport?1:0;
     break;
-  case URGTAG_HTTPHEADER:
+  case CURLOPT_HTTPHEADER:
     data->headers = va_arg(param, struct HttpHeader *);
     break;
-  case URGTAG_CUSTOMREQUEST:
+  case CURLOPT_CUSTOMREQUEST:
     data->customrequest = va_arg(param, char *);
     break;
-  case URGTAG_HTTPPOST:
+  case CURLOPT_HTTPPOST:
     data->httppost = va_arg(param, struct HttpPost *);
+    data->bits.http_formpost = data->httppost?1:0;
     break;
-  case URGTAG_INFILE:
+  case CURLOPT_INFILE:
     data->in = va_arg(param, FILE *);
     break;
-  case URGTAG_INFILESIZE:
+  case CURLOPT_INFILESIZE:
     data->infilesize = va_arg(param, long);
     break;
-  case URGTAG_LOW_SPEED_LIMIT:
+  case CURLOPT_LOW_SPEED_LIMIT:
     data->low_speed_limit=va_arg(param, long);
     break;
-  case URGTAG_LOW_SPEED_TIME:
+  case CURLOPT_LOW_SPEED_TIME:
     data->low_speed_time=va_arg(param, long);
     break;
-  case URGTAG_URL:
+  case CURLOPT_URL:
     data->url = va_arg(param, char *);
     break;
-  case URGTAG_PORT:
+  case CURLOPT_PORT:
     /* this typecast is used to fool the compiler to NOT warn for a
        "cast from pointer to integer of different size" */
     data->port = (unsigned short)(va_arg(param, long));
     break;
-  case URGTAG_POSTFIELDS:
+  case CURLOPT_POSTFIELDS:
     data->postfields = va_arg(param, char *);
     break;
-  case URGTAG_PROGRESSMODE:
+  case CURLOPT_PROGRESSMODE:
     data->progress.mode = va_arg(param, long);
     break;
-  case URGTAG_REFERER:
+  case CURLOPT_REFERER:
     data->referer = va_arg(param, char *);
+    data->bits.http_set_referer = (data->referer && *data->referer)?1:0;
     break;
-  case URGTAG_PROXY:
+  case CURLOPT_PROXY:
     data->proxy = va_arg(param, char *);
+    data->bits.httpproxy = data->proxy?1:0;
     break;
-  case URGTAG_FLAGS:
-    data->conf = va_arg(param, long);
+#if 0
+  case CURLOPT_FLAGS:
+    conf_to_internal(data, va_arg(param, long));
     break;
-  case URGTAG_TIMEOUT:
+#endif
+  case CURLOPT_TIMEOUT:
     data->timeout = va_arg(param, long);
     break;
-  case URGTAG_USERAGENT:
+  case CURLOPT_USERAGENT:
     data->useragent = va_arg(param, char *);
     break;
-  case URGTAG_USERPWD:
+  case CURLOPT_USERPWD:
     data->userpwd = va_arg(param, char *);
+    data->bits.user_passwd = data->userpwd?1:0;
     break;
-  case URGTAG_POSTQUOTE:
+  case CURLOPT_POSTQUOTE:
     data->postquote = va_arg(param, struct curl_slist *);
     break;
-  case URGTAG_PROXYUSERPWD:
+  case CURLOPT_PROXYUSERPWD:
     data->proxyuserpwd = va_arg(param, char *);
+    data->bits.proxy_user_passwd = data->proxyuserpwd?1:0;
     break;
-  case URGTAG_RANGE:
+  case CURLOPT_RANGE:
     data->range = va_arg(param, char *);
+    data->bits.set_range = data->range?1:0;
     break;
-  case URGTAG_RESUME_FROM:
+  case CURLOPT_RESUME_FROM:
     data->resume_from = va_arg(param, long);
     break;
-  case URGTAG_STDERR:
+  case CURLOPT_STDERR:
     data->err = va_arg(param, FILE *);
     break;
-  case URGTAG_WRITEFUNCTION:
-    data->fwrite = va_arg(param, void *);
+  case CURLOPT_WRITEFUNCTION:
+    data->fwrite = va_arg(param, write_callback);
     break;
-  case URGTAG_WRITEINFO:
+  case CURLOPT_WRITEINFO:
     data->writeinfo = va_arg(param, char *);
     break;
-  case URGTAG_READFUNCTION:
-    data->fread = va_arg(param, void *);
+  case CURLOPT_READFUNCTION:
+    data->fread = va_arg(param, read_callback);
     break;
-  case URGTAG_SSLCERT:
+  case CURLOPT_SSLCERT:
     data->cert = va_arg(param, char *);
     break;
-  case URGTAG_SSLCERTPASSWD:
+  case CURLOPT_SSLCERTPASSWD:
     data->cert_passwd = va_arg(param, char *);
     break;
-  case URGTAG_CRLF:
+  case CURLOPT_CRLF:
     data->crlf = va_arg(param, long);
     break;
-  case URGTAG_QUOTE:
+  case CURLOPT_QUOTE:
     data->quote = va_arg(param, struct curl_slist *);
     break;
   default:
     /* unknown tag and its companion, just ignore: */
-    return URG_READ_ERROR; /* correct this */
-  }
-  return URG_OK;
-}
-
-
-typedef int (*func_T)(void);
-
-UrgError curl_urlget(UrgTag tag, ...)
-{
-  va_list arg;
-  func_T param_func = (func_T)0;
-  long param_long = 0;
-  void *param_obj = NULL;
-  UrgError res;
-
-  struct UrlData *data;
-
-  /* this is for the lame win32 socket crap */
-  if(curl_init())
-    return URG_FAILED_INIT;
-
-  /* We use curl_open() with undefined URL so far */
-  res = curl_open(&data, NULL);
-  if(res == URG_OK) {
-    /* data is now filled with good-looking zeroes */
-
-    /* Let's set some default values: */
-    curl_setopt(data, URGTAG_FILE, stdout); /* default output to stdout */
-    curl_setopt(data, URGTAG_INFILE, stdin);  /* default input from stdin */
-    curl_setopt(data, URGTAG_STDERR, stderr);  /* default stderr to stderr! */
-
-    data->firstsocket = -1; /* no file descriptor */
-    data->secondarysocket = -1; /* no file descriptor */
-
-    /* use fwrite as default function to store output */
-    data->fwrite = (size_t (*)(char *, size_t, size_t, FILE *))fwrite;
-
-    /* use fread as default function to read input */
-    data->fread = (size_t (*)(char *, size_t, size_t, FILE *))fread;
-
-    data->infilesize = -1; /* we don't know any size */
-
-    data->current_speed = -1; /* init to negative == impossible */
-
-    va_start(arg, tag);
-
-    while(tag != URGTAG_DONE) {
-      /* PORTING NOTE:
-        Ojbect pointers can't necessarily be casted to function pointers and
-        therefore we need to know what type it is and read the correct type
-        at once. This should also correct problems with different sizes of
-        the types.
-         */
-
-      if(tag < URGTYPE_OBJECTPOINT) {
-       /* This is a LONG type */
-       param_long = va_arg(arg, long);
-        curl_setopt(data, tag, param_long);
-      }
-      else if(tag < URGTYPE_FUNCTIONPOINT) {
-       /* This is a object pointer type */
-       param_obj = va_arg(arg, void *);
-        curl_setopt(data, tag, param_obj);
-      }
-      else {
-       param_func = va_arg(arg, func_T );
-        curl_setopt(data, tag, param_func);
-      }
-
-      /* printf("tag: %d\n", tag); */
-      tag = va_arg(arg, UrgTag);
-    }
-
-    va_end(arg);
-
-    pgrsMode(data, data->progress.mode);
-    pgrsStartNow(data);
-
-    data-> headerbuff=(char*)malloc(HEADERSIZE);
-    if(!data->headerbuff)
-      return URG_FAILED_INIT;
-
-    data-> headersize=HEADERSIZE;
-
-    res = _urlget(data); /* fetch the URL please */
-
-    while((res == URG_OK) && data->newurl) {
-      /* Location: redirect */
-      char prot[16];
-      char path[URL_MAX_LENGTH];
-
-      if(2 != sscanf(data->newurl, "%15[^:]://%" URL_MAX_LENGTH_TXT
-                     "s", prot, path)) {
-       /***
-        *DANG* this is an RFC 2068 violation. The URL is supposed
-        to be absolute and this doesn't seem to be that!
-        ***
-        Instead, we have to TRY to append this new path to the old URL
-        to the right of the host part. Oh crap, this is doomed to cause
-        problems in the future...
-        */
-       char *protsep;
-       char *pathsep;
-       char *newest;
-
-       /* protsep points to the start of the host name */
-       protsep=strstr(data->url, "//");
-       if(!protsep)
-         protsep=data->url;
-       else {
-          data->port=0; /* we got a full URL and then we should reset the
-                           port number here to re-initiate it later */
-         protsep+=2; /* pass the // */
-        }
-
-        if('/' != data->newurl[0]) {
-          /* First we need to find out if there's a ?-letter in the URL, and
-             cut it and the right-side of that off */
-          pathsep = strrchr(protsep, '?');
-          if(pathsep)
-            *pathsep=0;
-
-          /* we have a relative path to append to the last slash if
-             there's one available */
-          pathsep = strrchr(protsep, '/');
-          if(pathsep)
-            *pathsep=0;
-        }
-        else {
-          /* We got a new absolute path for this server, cut off from the
-             first slash */
-          pathsep = strchr(protsep, '/');
-          if(pathsep)
-            *pathsep=0;
-        }
-
-        newest=(char *)malloc( strlen(data->url) +
-                               1 + /* possible slash */
-                               strlen(data->newurl) + 1/* zero byte */);
-
-       if(!newest)
-         return URG_OUT_OF_MEMORY;
-        sprintf(newest, "%s%s%s", data->url, ('/' == data->newurl[0])?"":"/",
-                data->newurl);
-       free(data->newurl);
-       data->newurl = newest;
-      }
-      else {
-        /* This was an absolute URL, clear the port number! */
-        data->port = 0;
-      }
-      
-      data->url = data->newurl;
-      data->newurl = NULL; /* don't show! */
-
-      infof(data, "Follows Location: to new URL: '%s'\n", data->url);
-
-      /* clean up the sockets and SSL stuff from the previous "round" */
-      urlfree(data, FALSE);
-
-      res = _urlget(data);
-    }
-    if(data->newurl)
-      free(data->newurl);
-
+    return CURLE_READ_ERROR; /* correct this */
   }
-  else
-    res = URG_FAILED_INIT; /* failed */
-
-  if((URG_OK == res) && data->writeinfo) {
-    /* Time to output some info to stdout */
-    WriteOut(data);
-  }
-
-
-  /* total cleanup */
-  urlfree(data, TRUE);
-
-  return res;
+  return CURLE_OK;
 }
 
 
@@ -618,8 +490,7 @@ UrgError curl_urlget(UrgTag tag, ...)
  * Read everything until a newline.
  */
 
-static int GetLine(int sockfd, char *buf,
-                  struct UrlData *data)
+int GetLine(int sockfd, char *buf, struct UrlData *data)
 {
   int nread;
   int read_rc=1;
@@ -645,7 +516,7 @@ static int GetLine(int sockfd, char *buf,
   }
   *ptr=0; /* zero terminate */
 
-  if(data->conf & CONF_VERBOSE) {
+  if(data->bits.verbose) {
     fputs("< ", data->err);
     fwrite(buf, 1, nread, data->err);
     fputs("\n", data->err);
@@ -654,7 +525,6 @@ static int GetLine(int sockfd, char *buf,
 }
 
 
-
 #ifndef WIN32
 #ifndef RETSIGTYPE
 #define RETSIGTYPE void
@@ -667,35 +537,114 @@ RETSIGTYPE alarmfunc(int signal)
 }
 #endif
 
-/* ====================================================== */
+CURLcode curl_write(CURLconnect *c_conn, char *buf, size_t amount,
+                   size_t *n)
+{
+  struct connectdata *conn = (struct connectdata *)c_conn;
+  struct UrlData *data;
+  size_t bytes_written;
+
+  if(!n || !conn || (conn->handle != STRUCT_CONNECT))
+    return CURLE_FAILED_INIT;
+  data = conn->data;
+
+#ifdef USE_SSLEAY
+  if (data->use_ssl) {
+    bytes_written = SSL_write(data->ssl, buf, amount);
+  }
+  else {
+#endif
+    bytes_written = swrite(conn->writesockfd, buf, amount);
+#ifdef USE_SSLEAY
+  }
+#endif /* USE_SSLEAY */
+
+  *n = bytes_written;
+  return CURLE_OK;
+}
+
+CURLcode curl_read(CURLconnect *c_conn, char *buf, size_t buffersize,
+                   size_t *n)
+{
+  struct connectdata *conn = (struct connectdata *)c_conn;
+  struct UrlData *data;
+  size_t nread;
+
+  if(!n || !conn || (conn->handle != STRUCT_CONNECT))
+    return CURLE_FAILED_INIT;
+  data = conn->data;
+
+#ifdef USE_SSLEAY
+  if (data->use_ssl) {
+    nread = SSL_read (data->ssl, buf, buffersize);
+  }
+  else {
+#endif
+    nread = sread (conn->sockfd, buf, buffersize);
+#ifdef USE_SSLEAY
+  }
+#endif /* USE_SSLEAY */
+  *n = nread;
+  return CURLE_OK;
+}
+
+CURLcode curl_disconnect(CURLconnect *c_connect)
+{
+  struct connectdata *conn = c_connect;
+
+  struct UrlData *data = conn->data;
+
+  /* clean up the sockets and SSL stuff from the previous "round" */
+  urlfree(data, FALSE);
+
+  return CURLE_OK;
+}
+
 /*
- * urlget <url>
- * (result put on stdout)
+ * NAME curl_connect()
  *
- * <url> ::= <proto> "://" <host> [ ":" <port> ] "/" <path>
+ * DESCRIPTION
  *
- * <proto> = "HTTP" | "HTTPS" | "GOPHER" | "FTP"
+ * 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().
  *
- * When FTP:
+ * EXAMPLE
  *
- * <host> ::= [ <user> ":" <password> "@" ] <host>
+ * CURLCode result;
+ * CURL curl;
+ * CURLconnect connect;
+ * result = curl_connect(curl, &connect);
  */
 
-static UrgError _urlget(struct UrlData *data)
+CURLcode curl_connect(CURL *curl, CURLconnect **in_connect)
 {
-  struct hostent *hp=NULL;
-  struct sockaddr_in serv_addr;
+  char *tmp;
   char *buf;
-  char proto[64];
-  char gname[256]="default.com";
-  char *name;
-  char path[URL_MAX_LENGTH]="/";
-  char *ppath, *tmp;
-  long bytecount;
-  struct timeval now;
-
-  UrgError result;
+  CURLcode result;
   char resumerange[12]="";
+  struct UrlData *data = curl;
+  struct connectdata *conn;
+
+  if(!data || (data->handle != STRUCT_OPEN))
+    return CURLE_BAD_FUNCTION_ARGUMENT; /* TBD: make error codes */
+
+  if(!data->url)
+    return CURLE_URL_MALFORMAT;
+
+  conn = (struct connectdata *)malloc(sizeof(struct connectdata));
+  if(!conn) {
+    *in_connect = NULL; /* clear the pointer */
+    return CURLE_OUT_OF_MEMORY;
+  }
+  *in_connect = conn;
+
+  memset(conn, 0, sizeof(struct connectdata));
+  conn->handle = STRUCT_CONNECT;
+
+  conn->data = data; /* remember our daddy */
+  conn->state = CONN_INIT;
 
   buf = data->buffer; /* this is our buffer */
 
@@ -709,59 +658,60 @@ static UrgError _urlget(struct UrlData *data)
    * to SSL connect through the proxy -- and we don't know if we
    * will need to use SSL until we parse the url ...
    */
-  if((1 == sscanf(data->url, "file://%" URL_MAX_LENGTH_TXT "[^\n]",
-                  path))) {
+  if((2 == sscanf(data->url, "%64[^:]://%" URL_MAX_LENGTH_TXT "[^\n]",
+                  conn->proto,
+                  conn->path)) && strequal(conn->proto, "file")) {
     /* we deal with file://<host>/<path> differently since it
        supports no hostname other than "localhost" and "127.0.0.1",
-       which ist unique among the protocols specified in RFC 1738 */
-    if (strstr(path, "localhost/") || strstr(path, "127.0.0.1/"))
-      strcpy(path, &path[10]);         /* ... since coincidentally
-                                          both host strings are of
-                                          equal length */
-    /* otherwise, <host>/ is quietly ommitted */
-
-
-    /* that's it, no more fiddling with proxies, redirections,
-       or SSL for files, go directly to the file reading function */
-    result = file(data, path, &bytecount);
-    if(result)
-      return result;
-  
-    return URG_OK;
+       which is unique among the protocols specified in RFC 1738 */
+    if (strnequal(conn->path, "localhost/", 10) ||
+        strnequal(conn->path, "127.0.0.1/", 10))
+      /* ... since coincidentally both host strings are of equal length
+         otherwise, <host>/ is quietly ommitted */
+      strcpy(conn->path, &conn->path[10]);
+
+    strcpy(conn->proto, "file");
   }
-  else if (2 > sscanf(data->url, "%64[^\n:]://%256[^\n/]%" URL_MAX_LENGTH_TXT "[^\n]",
-                 proto, gname, path)) {
-    
+  else {
+    /* Set default host and default path */
+    strcpy(conn->gname, "curl.haxx.nu");
+    strcpy(conn->path, "/");
+
+    if (2 > sscanf(data->url,
+                   "%64[^\n:]://%256[^\n/]%" URL_MAX_LENGTH_TXT "[^\n]",
+                   conn->proto, conn->gname, conn->path)) {
       
-    /* badly formatted, let's try the browser-style _without_ 'http://' */
-    if((1 > sscanf(data->url, "%256[^\n/]%" URL_MAX_LENGTH_TXT "[^\n]", gname,
-                   path)) ) {
-      failf(data, "<url> malformed");
-      return URG_URL_MALFORMAT;
-    }
-    if(strnequal(gname, "FTP", 3)) {
-      strcpy(proto, "ftp");
-    }
-    else if(strnequal(gname, "GOPHER", 6))
-      strcpy(proto, "gopher");
+      /* badly formatted, let's try the browser-style _without_ 'http://' */
+      if((1 > sscanf(data->url, "%256[^\n/]%" URL_MAX_LENGTH_TXT "[^\n]",
+                     conn->gname, conn->path)) ) {
+        failf(data, "<url> malformed");
+        return CURLE_URL_MALFORMAT;
+      }
+      if(strnequal(conn->gname, "FTP", 3)) {
+        strcpy(conn->proto, "ftp");
+      }
+      else if(strnequal(conn->gname, "GOPHER", 6))
+        strcpy(conn->proto, "gopher");
 #ifdef USE_SSLEAY
-    else if(strnequal(gname, "HTTPS", 5))
-      strcpy(proto, "https");
+      else if(strnequal(conn->gname, "HTTPS", 5))
+        strcpy(conn->proto, "https");
 #endif /* USE_SSLEAY */
-    else if(strnequal(gname, "TELNET", 6))
-      strcpy(proto, "telnet");
-    else if (strnequal(gname, "DICT", sizeof("DICT")-1))
-      strcpy(proto, "DICT");
-    else if (strnequal(gname, "LDAP", sizeof("LDAP")-1))
-      strcpy(proto, "LDAP");
-    else
-      strcpy(proto, "http");
-
-    data->conf |= CONF_NOPROT;
+      else if(strnequal(conn->gname, "TELNET", 6))
+        strcpy(conn->proto, "telnet");
+      else if (strnequal(conn->gname, "DICT", sizeof("DICT")-1))
+        strcpy(conn->proto, "DICT");
+      else if (strnequal(conn->gname, "LDAP", sizeof("LDAP")-1))
+        strcpy(conn->proto, "LDAP");
+      else {
+        strcpy(conn->proto, "http");
+      }
+
+      conn->protocol |= PROT_MISSING; /* not given in URL */
+    }
   }
 
 
-  if((data->conf & CONF_USERPWD) && ! (data->conf & CONF_NETRC)) {
+  if(data->bits.user_passwd && !data->bits.use_netrc) {
     if(':' != *data->userpwd) {
       if((1 <= sscanf(data->userpwd, "%127[^:]:%127s",
                       data->user, data->passwd))) {
@@ -774,11 +724,11 @@ static UrgError _urlget(struct UrlData *data)
     }
     if(!data->user[0]) {
       failf(data, "USER malformat: user name can't be zero length");
-      return URG_MALFORMAT_USER;
+      return CURLE_MALFORMAT_USER;
     }
   }
 
-  if(data->conf & CONF_PROXYUSERPWD) {
+  if(data->bits.proxy_user_passwd) {
     if(':' != *data->proxyuserpwd) {
       if((1 <= sscanf(data->proxyuserpwd, "%127[^:]:%127s",
                       data->proxyuser, data->proxypasswd))) {
@@ -791,16 +741,16 @@ static UrgError _urlget(struct UrlData *data)
     }
     if(!data->proxyuser[0]) {
       failf(data, " Proxy USER malformat: user name can't be zero length");
-      return URG_MALFORMAT_USER;
+      return CURLE_MALFORMAT_USER;
     }
   }
 
-  name = gname;
-  ppath = path;
-  data->hostname = name;
+  conn->name = conn->gname;
+  conn->ppath = conn->path;
+  data->hostname = conn->name;
 
 
-  if(!(data->conf & CONF_PROXY)) {
+  if(!data->bits.httpproxy) {
     /* If proxy was not specified, we check for default proxy environment
        variables, to enable i.e Lynx compliance:
 
@@ -824,9 +774,9 @@ static UrgError _urlget(struct UrlData *data)
 
       nope=no_proxy?strtok(no_proxy, ", "):NULL;
       while(nope) {
-        if(strlen(nope) <= strlen(name)) {
+        if(strlen(nope) <= strlen(conn->name)) {
           char *checkn=
-            name + strlen(name) - strlen(nope);
+            conn->name + strlen(conn->name) - strlen(nope);
           if(strnequal(nope, checkn, strlen(nope))) {
             /* no proxy for this host! */
             break;
@@ -836,7 +786,7 @@ static UrgError _urlget(struct UrlData *data)
       }
       if(!nope) {
        /* It was not listed as without proxy */
-       char *protop = proto;
+       char *protop = conn->proto;
        char *envp = proxy_env;
        char *prox;
 
@@ -861,29 +811,29 @@ static UrgError _urlget(struct UrlData *data)
         if(proxy && *proxy) {
           /* we have a proxy here to set */
           data->proxy = proxy;
-          data->conf |= CONF_PROXY;
+          data->bits.httpproxy=1;
         }
       } /* if (!nope) - it wasn't specfied non-proxy */
     } /* NO_PROXY wasn't specified or '*' */
   } /* if not using proxy */
 
-  if((data->conf & (CONF_PROXY|CONF_NOPROT)) == (CONF_PROXY|CONF_NOPROT) ) {
+  if((conn->protocol&PROT_MISSING) && data->bits.httpproxy ) {
     /* We're guessing prefixes here and since we're told to use a proxy, we
        need to add the protocol prefix to the URL string before we continue!
        */
     char *reurl;
 
-    reurl = maprintf("%s://%s", proto, data->url);
+    reurl = maprintf("%s://%s", conn->proto, data->url);
 
     if(!reurl)
-      return URG_OUT_OF_MEMORY;
+      return CURLE_OUT_OF_MEMORY;
 
     data->url = reurl;
     if(data->freethis)
       free(data->freethis);
     data->freethis = reurl;
 
-    data->conf &= ~CONF_NOPROT; /* switch that one off again */
+    conn->protocol &= ~PROT_MISSING; /* switch that one off again */
   }
 
   /* RESUME on a HTTP page is a tricky business. First, let's just check that
@@ -894,11 +844,11 @@ static UrgError _urlget(struct UrlData *data)
      server, we just fail since we can't rewind the file writing from within
      this function. */
   if(data->resume_from) {
-    if(!(data->conf & CONF_RANGE)) {
+    if(!data->bits.set_range) {
       /* if it already was in use, we just skip this */
       sprintf(resumerange, "%d-", data->resume_from);
       data->range=resumerange; /* tell ourselves to fetch this range */
-      data->conf |= CONF_RANGE; /* switch on range usage */
+      data->bits.set_range = 1; /* switch on range usage */
     }
   }
 
@@ -916,50 +866,69 @@ static UrgError _urlget(struct UrlData *data)
    * works differently, depending on whether its SSL or not).
    */
 
-  if (strequal(proto, "HTTP")) {
+  if (strequal(conn->proto, "HTTP")) {
     if(!data->port)
       data->port = PORT_HTTP;
     data->remote_port = PORT_HTTP;
-    data->conf |= CONF_HTTP;
+    conn->protocol |= PROT_HTTP;
+    conn->curl_do = http;
+    conn->curl_done = http_done;
   }
-  else if (strequal(proto, "HTTPS")) {
+  else if (strequal(conn->proto, "HTTPS")) {
 #ifdef USE_SSLEAY
     if(!data->port)
       data->port = PORT_HTTPS;
     data->remote_port = PORT_HTTPS;
-    data->conf |= CONF_HTTP;
-    data->conf |= CONF_HTTPS;
+    conn->protocol |= PROT_HTTP;
+    conn->protocol |= PROT_HTTPS;
+
+    conn->curl_do = http;
+    conn->curl_done = http_done;
+    conn->curl_connect = http_connect;
+
 #else /* USE_SSLEAY */
     failf(data, "SSL is disabled, https: not supported!");
-    return URG_UNSUPPORTED_PROTOCOL;
+    return CURLE_UNSUPPORTED_PROTOCOL;
 #endif /* !USE_SSLEAY */
   }
-  else if (strequal(proto, "GOPHER")) {
+  else if (strequal(conn->proto, "GOPHER")) {
     if(!data->port)
       data->port = PORT_GOPHER;
     data->remote_port = PORT_GOPHER;
     /* Skip /<item-type>/ in path if present */
-    if (isdigit((int)path[1])) {
-      ppath = strchr(&path[1], '/');
-      if (ppath == NULL)
-       ppath = path;
+    if (isdigit((int)conn->path[1])) {
+      conn->ppath = strchr(&conn->path[1], '/');
+      if (conn->ppath == NULL)
+       conn->ppath = conn->path;
       }
-    data->conf |= CONF_GOPHER;
+    conn->protocol |= PROT_GOPHER;
+    conn->curl_do = http;
+    conn->curl_done = http_done;
   }
-  else if(strequal(proto, "FTP")) {
+  else if(strequal(conn->proto, "FTP")) {
     char *type;
     if(!data->port)
       data->port = PORT_FTP;
     data->remote_port = PORT_FTP;
-    data->conf |= CONF_FTP;
+    conn->protocol |= PROT_FTP;
 
-    ppath++; /* don't include the initial slash */
+    if(data->bits.httpproxy) {
+      conn->curl_do = http;
+      conn->curl_done = http_done;
+    }
+    else {
+      conn->curl_do = ftp;
+      conn->curl_done = ftp_done;
+      conn->curl_connect = ftp_connect;
+    }
+
+    conn->ppath++; /* don't include the initial slash */
 
     /* FTP URLs support an extension like ";type=<typecode>" that
        we'll try to get now! */
-    type=strstr(ppath, ";type=");
+    type=strstr(conn->ppath, ";type=");
     if(!type) {
-      type=strstr(gname, ";type=");
+      type=strstr(conn->gname, ";type=");
     }
     if(type) {
       char command;
@@ -967,54 +936,59 @@ static UrgError _urlget(struct UrlData *data)
       command = toupper(type[6]);
       switch(command) {
       case 'A': /* ASCII mode */
-       data->conf |= CONF_FTPASCII;
+       data->bits.ftp_ascii = 1;
        break;
       case 'D': /* directory mode */
-       data->conf |= CONF_FTPLISTONLY;
+       data->bits.ftp_list_only = 1;
        break;
       case 'I': /* binary mode */
       default:
        /* switch off ASCII */
-       data->conf &= ~CONF_FTPASCII; 
+       data->bits.ftp_ascii = 0;
        break;
       }
     }
   }
-  else if(strequal(proto, "TELNET")) {
+  else if(strequal(conn->proto, "TELNET")) {
     /* telnet testing factory */
-    data->conf |= CONF_TELNET;
+    conn->protocol |= PROT_TELNET;
     if(!data->port)
       data->port = PORT_TELNET;
     data->remote_port = PORT_TELNET;
+
+    conn->curl_do = telnet;
+    conn->curl_done = telnet_done;
+
   }
-  else if (strequal(proto, "DICT")) {
-    data->conf |= CONF_DICT;
+  else if (strequal(conn->proto, "DICT")) {
+    conn->protocol |= PROT_DICT;
     if(!data->port)
       data->port = PORT_DICT;
     data->remote_port = PORT_DICT;
+    conn->curl_do = dict;
+    conn->curl_done = dict_done;
   }
-  else if (strequal(proto, "LDAP")) {
-    data->conf |= CONF_LDAP;
+  else if (strequal(conn->proto, "LDAP")) {
+    conn->protocol |= PROT_LDAP;
     if(!data->port)
       data->port = PORT_LDAP;
     data->remote_port = PORT_LDAP;
+    conn->curl_do = ldap;
+    conn->curl_done = ldap_done;
   }
-  /* file:// is handled above */
-  /*  else if (strequal(proto, "FILE")) {
-    data->conf |= CONF_FILE;
+  else if (strequal(conn->proto, "FILE")) {
+    conn->protocol |= PROT_FILE;
 
-    result = file(data, path, &bytecount);
-    if(result)
-      return result;
+    conn->curl_do = file;
+    /* no done() function */
+  }
 
-    return URG_OK;
-    }*/
   else {
-    failf(data, "Unsupported protocol: %s", proto);
-    return URG_UNSUPPORTED_PROTOCOL;
+    failf(data, "Unsupported protocol: %s", conn->proto);
+    return CURLE_UNSUPPORTED_PROTOCOL;
   }
 
-  if(data->conf & CONF_NETRC) {
+  if(data->bits.use_netrc) {
     if(ParseNetrc(data->hostname, data->user, data->passwd)) {
       infof(data, "Couldn't find host %s in the .netrc file, using defaults",
             data->hostname);
@@ -1025,25 +999,26 @@ static UrgError _urlget(struct UrlData *data)
       strcpy(data->user, CURL_DEFAULT_USER);
     if(!data->passwd[0])
       strcpy(data->passwd, CURL_DEFAULT_PASSWORD);
-    if(data->conf & CONF_HTTP) {
-      data->conf |= CONF_USERPWD;
+    if(conn->protocol&PROT_HTTP) {
+      data->bits.user_passwd = 1; /* enable user+password */
     }
   }
-  else if(!(data->conf & CONF_USERPWD) &&
-         (data->conf & (CONF_FTP|CONF_HTTP)) ) {
+  else if(!(data->bits.user_passwd) &&
+         (conn->protocol & (PROT_FTP|PROT_HTTP)) ) {
     /* This is a FTP or HTTP URL, and we haven't got the user+password in
        the extra parameter, we will now try to extract the possible
        user+password pair in a string like:
        ftp://user:password@ftp.my.site:8021/README */
     char *ptr=NULL; /* assign to remove possible warnings */
-    if(':' == *name) {
+    if(':' == *conn->name) {
       failf(data, "URL malformat: user can't be zero length");
-      return URG_URL_MALFORMAT_USER;
+      return CURLE_URL_MALFORMAT_USER;
     }
-    if((1 <= sscanf(name, "%127[^:]:%127[^@]",
-                   data->user, data->passwd)) && (ptr=strchr(name, '@'))) {
-      name = ++ptr;
-      data->conf |= CONF_USERPWD;
+    if((1 <= sscanf(conn->name, "%127[^:]:%127[^@]",
+                   data->user, data->passwd)) &&
+       (ptr=strchr(conn->name, '@'))) {
+      conn->name = ++ptr;
+      data->bits.user_passwd=1; /* enable user+password */
     }
     else {
       strcpy(data->user, CURL_DEFAULT_USER);
@@ -1051,19 +1026,19 @@ static UrgError _urlget(struct UrlData *data)
     }
   }
 
-  if(!(data->conf & CONF_PROXY)) {
+  if(!data->bits.httpproxy) {
     /* If not connecting via a proxy, extract the port from the URL, if it is
      * there, thus overriding any defaults that might have been set above. */
-    tmp = strchr(name, ':');
+    tmp = strchr(conn->name, ':');
     if (tmp) {
       *tmp++ = '\0';
       data->port = atoi(tmp);
     }
     
     /* Connect to target host right on */
-    if(!(hp = GetHost(data, name))) {
-      failf(data, "Couldn't resolv host '%s'", name);
-      return URG_COULDNT_RESOLVE_HOST;
+    if(!(conn->hp = GetHost(data, conn->name))) {
+      failf(data, "Couldn't resolv host '%s'", conn->name);
+      return CURLE_COULDNT_RESOLVE_HOST;
     }
   }
   else {
@@ -1079,12 +1054,12 @@ static UrgError _urlget(struct UrlData *data)
 
     if(NULL == proxydup) {
       failf(data, "memory shortage");
-      return URG_OUT_OF_MEMORY;
+      return CURLE_OUT_OF_MEMORY;
     }
 
     /* we use proxy all right, but we wanna know the remote port for SSL
        reasons */
-    tmp = strchr(name, ':');
+    tmp = strchr(conn->name, ':');
     if (tmp) {
       *tmp++ = '\0'; /* cut off the name there */
       data->remote_port = atoi(tmp);
@@ -1111,9 +1086,9 @@ static UrgError _urlget(struct UrlData *data)
     }
 
     /* connect to proxy */
-    if(!(hp = GetHost(data, proxyptr))) {
+    if(!(conn->hp = GetHost(data, proxyptr))) {
       failf(data, "Couldn't resolv proxy '%s'", proxyptr);
-      return URG_COULDNT_RESOLVE_PROXY;
+      return CURLE_COULDNT_RESOLVE_PROXY;
     }
 
     free(proxydup); /* free the duplicate pointer and not the modified */
@@ -1122,14 +1097,16 @@ static UrgError _urlget(struct UrlData *data)
 
   data->firstsocket = socket(AF_INET, SOCK_STREAM, 0);
 
-  memset((char *) &serv_addr, '\0', sizeof(serv_addr));
-  memcpy((char *)&(serv_addr.sin_addr), hp->h_addr, hp->h_length);
-  serv_addr.sin_family = hp->h_addrtype;
-
-  serv_addr.sin_port = htons(data->port);
+  memset((char *) &conn->serv_addr, '\0', sizeof(conn->serv_addr));
+  memcpy((char *)&(conn->serv_addr.sin_addr),
+         conn->hp->h_addr, conn->hp->h_length);
+  conn->serv_addr.sin_family = conn->hp->h_addrtype;
+  conn->serv_addr.sin_port = htons(data->port);
 
-  if (connect(data->firstsocket, (struct sockaddr *) &serv_addr,
-             sizeof(serv_addr)) < 0) {
+  if (connect(data->firstsocket,
+              (struct sockaddr *) &(conn->serv_addr),
+              sizeof(conn->serv_addr)
+              ) < 0) {
     switch(errno) {
 #ifdef ECONNREFUSED
       /* this should be made nicer */
@@ -1146,10 +1123,10 @@ static UrgError _urlget(struct UrlData *data)
       failf(data, "Can't connect to server: %d", errno);
       break;
     }
-    return URG_COULDNT_CONNECT;
+    return CURLE_COULDNT_CONNECT;
   }
 
-  if(data->conf & CONF_PROXYUSERPWD) {
+  if(data->bits.proxy_user_passwd) {
     char authorization[512];
     sprintf(data->buffer, "%s:%s", data->proxyuser, data->proxypasswd);
     base64Encode(data->buffer, authorization);
@@ -1157,74 +1134,27 @@ static UrgError _urlget(struct UrlData *data)
     data->ptr_proxyuserpwd = maprintf("Proxy-authorization: Basic %s\015\012",
                                      authorization);
   }
-  if(data->conf & (CONF_HTTPS|CONF_HTTP|CONF_PROXY)) {
+  if((conn->protocol&PROT_HTTP) || data->bits.httpproxy) {
     if(data->useragent) {
       data->ptr_uagent = maprintf("User-Agent: %s\015\012", data->useragent);
     }
   }
 
-
-  /* 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 (data->conf & CONF_HTTPS) {
-     if (data->conf & CONF_PROXY) {
-
-        /* OK, now send the connect statment */
-        sendf(data->firstsocket, data,
-              "CONNECT %s:%d HTTP/1.0\015\012"
-              "%s"
-             "%s"
-              "\r\n",
-              data->hostname, data->remote_port,
-              (data->conf&CONF_PROXYUSERPWD)?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 URG_READ_ERROR;
-         }
-       }
-        infof (data, "Proxy has replied to CONNECT request\n");
-     }
-
-      /* now, perform the SSL initialization for this socket */
-     if(UrgSSLConnect (data)) {
-       return URG_SSL_CONNECT_ERROR;
-     }
+  if(conn->curl_connect) {
+    /* is there a post-connect() procedure? */
+    result = conn->curl_connect(conn);
   }
+
   pgrsTime(data, TIMER_CONNECT);
 
-  now = tvnow(); /* time this *after* the connect is done */
-  bytecount = 0;
+  conn->now = tvnow(); /* time this *after* the connect is done */
+  conn->bytecount = 0;
   
   /* Figure out the ip-number and the first host name it shows: */
   {
     struct in_addr in;
-    (void) memcpy(&in.s_addr, *hp->h_addr_list, sizeof (in.s_addr));
-    infof(data, "Connected to %s (%s)\n", hp->h_name, inet_ntoa(in));
+    (void) memcpy(&in.s_addr, *conn->hp->h_addr_list, sizeof (in.s_addr));
+    infof(data, "Connected to %s (%s)\n", conn->hp->h_name, inet_ntoa(in));
   }
 
 #if 0 /* Kerberos experiements! Beware! Take cover! */
@@ -1243,36 +1173,67 @@ static UrgError _urlget(struct UrlData *data)
   }
 #endif
 
-  if((data->conf&(CONF_FTP|CONF_PROXY)) == CONF_FTP) {
-    result = ftp(data, &bytecount, data->user, data->passwd, ppath);
-    if(result)
-      return result;
+  return CURLE_OK;
+}
+
+CURLcode curl_done(CURLconnect *c_connect)
+{
+  struct connectdata *conn = c_connect;
+  struct UrlData *data;
+  CURLcode result;
+
+  if(!conn || (conn->handle!= STRUCT_CONNECT)) {
+    return CURLE_BAD_FUNCTION_ARGUMENT;
   }
-  else if(data->conf & CONF_TELNET) {
-    result=telnet(data);
-    if(result)
-      return result;
+  if(conn->state != CONN_DO) {
+    /* This can only be called after a curl_do() */
+    return CURLE_BAD_CALLING_ORDER;
   }
-  else if (data->conf & CONF_LDAP) {
-    result = ldap(data, path, &bytecount);
-    if (result)
-      return result;
+  data = conn->data;
+
+  /* this calls the protocol-specific function pointer previously set */
+  if(conn->curl_done)
+    result = conn->curl_done(conn);
+  else
+    result = CURLE_OK;
+
+  pgrsDone(data); /* done with the operation */
+
+  conn->state = CONN_DONE;
+
+  return result;
+}
+
+CURLcode curl_do(CURLconnect *in_conn)
+{
+  struct connectdata *conn = in_conn;
+  CURLcode result;
+
+  if(!conn || (conn->handle!= STRUCT_CONNECT)) {
+    return CURLE_BAD_FUNCTION_ARGUMENT;
   }
-  else if (data->conf & CONF_DICT) {
-    result = dict(data, path, &bytecount);
-    if(result)
-      return result;
+  if(conn->state != CONN_INIT) {
+    return CURLE_BAD_CALLING_ORDER;
   }
-  else {
-    result = http(data, ppath, name, &bytecount);
-    if(result)
+
+  if(conn->curl_do) {
+    /* generic protocol-specific function pointer set in curl_connect() */
+    result = conn->curl_do(conn);
+    if(result) {
+      conn->state = CONN_ERROR;
       return result;
+    }
   }
-  if(bytecount) {
-    double ittook = tvdiff (tvnow(), now);
+
+  conn->state = CONN_DO; /* we have entered this state */
+
+#if 0
+  if(conn->bytecount) {
+    double ittook = tvdiff (tvnow(), conn->now);
     infof(data, "%i bytes transfered in %.3lf seconds (%.0lf bytes/sec).\n",
-          bytecount, ittook, (double)bytecount/(ittook!=0.0?ittook:1));
+          conn->bytecount, ittook, (double)conn->bytecount/(ittook!=0.0?ittook:1));
   }
-  return URG_OK;
+#endif
+  return CURLE_OK;
 }
 
index e69de29..334fa97 100644 (file)
--- a/lib/url.h
+++ b/lib/url.h
@@ -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
index 0515d68..debaaa9 100644 (file)
@@ -67,6 +67,7 @@
 #define CURL_DEFAULT_PASSWORD "curl_by_Daniel.Stenberg@haxx.nu"
 
 #include "cookie.h"
+#include "formdata.h"
     
 #ifdef USE_SSLEAY
 /* SSLeay stuff usually in /usr/local/ssl/include */
 #endif
 #endif
 
+#include <netinet/in.h>
+
 #include "timeval.h"
 
+
+
 /* Download buffer size, keep it fairly big for speed reasons */
 #define BUFSIZE (1024*50)
 
    of need. */
 #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 {
   long lastshow; /* time() of the last displayed progress meter or NULL to
                     force redraw at next call */
@@ -121,42 +208,160 @@ struct Progress {
   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 {
+  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 *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 */
   char *url;   /* what to get */
   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
                           CONF_PORT to use this */
   unsigned short remote_port; /* what remote port to connect to, not the proxy
                                 port! */
-  char *proxy; /* if proxy, set it here, set CONF_PROXY to use this */
-  long conf;   /* configure flags */
+  struct Configbits bits; /* new-style (v7) flag data */
+
   char *userpwd;  /* <user:password>, if used */
-  char *proxyuserpwd;  /* Proxy <user:password>, if used */
   char *range; /* range, if used. See README for detailed specification on
                   this syntax. */
   char *postfields; /* if POST, set the fields' values here */
   char *referer;
-  char *errorbuffer; /* store failure messages in here */
   char *useragent;   /* User-Agent string */
 
   char *ftpport; /* port to send with the PORT command */
 
- /* function that stores the output:*/
-  size_t (*fwrite)(char *buffer,
-                   size_t size,
-                   size_t nitems,
-                   FILE *outstream);
+  /* function that stores the output:*/
+  write_callback fwrite;
 
   /* function that reads the input:*/
-  size_t (*fread)(char *buffer,
-                  size_t size,
-                  size_t nitems,
-                  FILE *outstream);
+  read_callback fread;
+
+  /* function that wants progress information */
+  progress_callback fprogress;
+  void *progress_client; /* pointer to pass to the progress callback */
 
   long timeout; /* in seconds, 0 means no timeout */
   long infilesize; /* size of file to upload, -1 means unknown */
index 73be0d7..ea54b2a 100644 (file)
@@ -58,7 +58,7 @@ char *curl_version(void)
 #ifdef USE_SSLEAY
 
 #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>>20)&0xff,
           (SSLEAY_VERSION_NUMBER>>12)&0xf);
index 415d9e2..d863062 100644 (file)
@@ -41,6 +41,7 @@
 #include <stdio.h>
 #include <string.h>
 
+#include "strequal.h"
 #include "writeout.h"
 
 typedef enum {
index d730bbf..faf0477 100644 (file)
@@ -1,3 +1,5 @@
+#ifndef __WRITEOUT_H
+#define __WRITEOUT_H
 /*****************************************************************************
  *                                  _   _ ____  _     
  *  Project                     ___| | | |  _ \| |    
@@ -41,3 +43,5 @@
 #include "urldata.h"
 
 void WriteOut(struct UrlData *data);
+
+#endif
diff --git a/maketgz b/maketgz
index 6ad429b..79982d0 100755 (executable)
--- a/maketgz
+++ b/maketgz
@@ -7,15 +7,24 @@ read 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?"
 read curlversion
 
 HEADER=include/curl/curl.h
 CHEADER=src/version.h
 
-
 # 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
 cp -p $HEADER $HEADER.old
index 561142e..21a799a 100644 (file)
@@ -4,7 +4,7 @@
 
 # Some flags needed when trying to cause warnings ;-)
 # CFLAGS = -Wall -pedantic
-CPPFLAGS = -DGLOBURL -DCURL_SEPARATORS
+#CPPFLAGS = -DGLOBURL -DCURL_SEPARATORS
 
 INCLUDES = -I$(top_srcdir)/include
 
index ba60773..55d3e3a 100644 (file)
@@ -2,6 +2,9 @@
 /* Define if you have the strcasecmp function.  */
 /*#define HAVE_STRCASECMP 1*/
 
+/* Define if you have the stricmp function.  */
+#define HAVE_STRICMP 1
+
 /* Define cpu-machine-OS */
 #define OS "win32"
 
index dde2486..316d3e3 100644 (file)
@@ -9,725 +9,694 @@ puts (
 "                            | (__| |_| |  _ <| |___ \n"
 "                             \\___|\\___/|_| \\_\\_____|\n"
 "NAME\n"
-"       curl  -  get  a  URL with FTP, TELNET, LDAP, GOPHER, DICT,\n"
-"       FILE, HTTP or HTTPS syntax.\n"
+"     curl - get a URL with FTP, TELNET, LDAP, GOPHER, DICT, FILE,\n"
+"     HTTP or HTTPS syntax.\n"
 "\n"
 "SYNOPSIS\n"
-"       curl [options] url\n"
+"     curl [options] url\n"
 "\n"
 "DESCRIPTION\n"
-"       curl is a client  to  get  documents/files  from  servers,\n"
-"       using  any  of  the  supported  protocols.  The command is\n"
-"       designed to work without user interaction or any  kind  of\n"
-"       interactivity.\n"
+"     curl is a client to get documents/files from servers,  using\n"
+"     any  of  the supported protocols. The command is designed to\n"
+"     work without user interaction or any kind of  interactivity.\n"
 "\n"
-"       curl offers a busload of useful tricks like proxy support,\n"
-"       user authentication, ftp upload, HTTP post,  SSL  (https:)\n"
-"       connections, cookies, file transfer resume and more.\n"
+"     curl  offers  a busload of useful tricks like proxy support,\n"
+"     user authentication, ftp upload,  HTTP  post,  SSL  (https:)\n"
+"     connections, cookies, file transfer resume and more.\n"
 "\n"
 "URL\n"
-"       The  URL  syntax  is  protocol  dependent.  You'll  find a\n"
-"       detailed description in RFC 2396.\n"
+"     The URL syntax is protocol dependent. You'll find a detailed\n"
+"     description in RFC 2396.\n"
 "\n"
-"       You can specify multiple URLs or parts of URLs by  writing\n"
-"       part sets within braces as in:\n"
+"     You can specify multiple URLs or parts of  URLs  by  writing\n"
+"     part sets within braces as in:\n"
 "\n"
-"        http://site.{one,two,three}.com\n"
+"      http://site.{one,two,three}.com\n"
 "\n"
-"       or  you  can get sequences of alphanumeric series by using\n"
-"       [] as in:\n"
+"     or  you can get sequences of alphanumeric series by using []\n"
+"     as in:\n"
 "\n"
-"        ftp://ftp.numericals.com/file[1-100].txt\n"
-"        ftp://ftp.numericals.com/file[001-100].txt    (with lead-\n"
-"       ing zeros)\n"
-"        ftp://ftp.letters.com/file[a-z].txt\n"
+"      ftp://ftp.numericals.com/file[1-100].txt\n"
+"      ftp://ftp.numericals.com/file[001-100].txt    (with leading\n"
+"     zeros)\n"
+"      ftp://ftp.letters.com/file[a-z].txt\n"
 "\n"
-"       It  is  possible  to  specify up to 9 sets or series for a\n"
-"       URL, but no nesting is supported at the moment:\n"
+"     It  is possible to specify up to 9 sets or series for a URL,\n"
+"     but no nesting is supported at the moment:\n"
 "\n"
-"        http://www.any.org/archive[1996-1999]/vol-\n"
-"       ume[1-4]part{a,b,c,index}.html\n"
+"      http://www.any.org/archive[1996-1999]/vol­\n"
+"     ume[1-4]part{a,b,c,index}.html\n"
 "\n"
 "OPTIONS\n"
-"       -a/--append\n"
-"              (FTP)  When  used  in  a ftp upload, this will tell\n"
-"              curl to append to the target file instead of  over-\n"
-"              writing  it.  If the file doesn't exist, it will be\n"
-"              created.\n"
-"\n"
-"       -A/--user-agent <agent string>\n"
-"              (HTTP) Specify the User-Agent string to send to the\n"
-"              HTTP  server.  Some badly done CGIs fail if its not\n"
-"              set to \"Mozilla/4.0\".   To  encode  blanks  in  the\n"
-"              string,  surround  the  string  with  single  quote\n"
-"              marks.  This can also be set with  the  -H/--header\n"
-"              flag of course.\n"
-"       -b/--cookie <name=data>\n"
-"              (HTTP)  Pass  the  data  to  the  HTTP  server as a\n"
-"              cookie.  It  is  supposedly  the  data   previously\n"
-"              received  from  the server in a \"Set-Cookie:\" line.\n"
-"              The data should be  in  the  format  \"NAME1=VALUE1;\n"
-"              NAME2=VALUE2\".\n"
-"\n"
-"              If no '=' letter is used in the line, it is treated\n"
-"              as a filename to  use  to  read  previously  stored\n"
-"              cookie  lines  from,  which  should be used in this\n"
-"              session if they match. Using this method also acti-\n"
-"              vates  the  \"cookie  parser\"  which  will make curl\n"
-"              record incoming cookies too, which may be handy  if\n"
-"              you're   using   this   in   combination  with  the\n"
-"              -L/--location option. The file format of  the  file\n"
-"              to  read  cookies from should be plain HTTP headers\n"
-"              or the netscape cookie file format.\n"
-"\n"
-"              NOTE that the file specified  with  -b/--cookie  is\n"
-"              only  used  as  input. No cookies will be stored in\n"
-"              the file. To store cookies, save the  HTTP  headers\n"
-"              to a file using -D/--dump-header!\n"
-"\n"
-"       -B/--ftp-ascii\n"
-"              (FTP/LDAP)  Use  ASCII transfer when getting an FTP\n"
-"              file or LDAP  info.  For  FTP,  this  can  also  be\n"
-"              enforced  by using an URL that ends with \";type=A\".\n"
-"\n"
-"       -c/--continue\n"
-"              Continue/Resume  a  previous  file  transfer.  This\n"
-"              instructs  curl  to  continue appending data on the\n"
-"              file where it was previously left, possibly because\n"
-"              of a broken connection to the server. There must be\n"
-"              a named physical file to  append  to  for  this  to\n"
-"              work.  Note: Upload resume is depening on a command\n"
-"              named SIZE not always present in all  ftp  servers!\n"
-"              Upload resume is for FTP only.  HTTP resume is only\n"
-"              possible with HTTP/1.1 or later servers.\n"
-"\n"
-"       -C/--continue-at <offset>\n"
-"              Continue/Resume a previous  file  transfer  at  the\n"
-"              given  offset. The given offset is the exact number\n"
-"              of bytes that will  be  skipped  counted  from  the\n"
-"              beginning  of  the  source file before it is trans-\n"
-"              fered to the destination.  If  used  with  uploads,\n"
-"              the  ftp  server  command  SIZE will not be used by\n"
-"              curl. Upload resume is for FTP only.   HTTP  resume\n"
-"              is only possible with HTTP/1.1 or later servers.\n"
-"\n"
-"       -d/--data <data>\n"
-"              (HTTP)  Sends  the specified data in a POST request\n"
-"              to the HTTP server. Note  that  the  data  is  sent\n"
-"              exactly as specified with no extra processing.  The\n"
-"              data is expected to  be  \"url-encoded\".  This  will\n"
-"              cause curl to pass the data to the server using the\n"
-"              content-type     application/x-www-form-urlencoded.\n"
-"              Compare to -F.\n"
-"\n"
-"              If  you  start the data with the letter @, the rest\n"
-"              should be a file name to read the data from,  or  -\n"
-"              if  you want curl to read the data from stdin.  The\n"
-"              contents of the file must already be url-encoded.\n"
-"\n"
-"       -D/--dump-header <file>\n"
-"              (HTTP/FTP) Write the HTTP  headers  to  this  file.\n"
-"              Write  the  FTP file info to this file if -I/--head\n"
-"              is used.\n"
-"\n"
-"              This option is handy to use when you want to  store\n"
-"              the  cookies  that  a  HTTP  site sends to you. The\n"
-"              cookies could then be read in a second curl  invoke\n"
-"              by using the -b/--cookie option!\n"
-"\n"
-"       -e/--referer <URL>\n"
-"              (HTTP)  Sends the \"Referer Page\" information to the\n"
-"              HTTP server. Some badly done CGIs fail if it's  not\n"
-"              set. This can also be set with the -H/--header flag\n"
-"              of course.\n"
-"\n"
-"       -E/--cert <certificate[:password]>\n"
-"              (HTTPS) Tells curl to use the specified certificate\n"
-"              file  when  getting a file with HTTPS. The certifi-\n"
-"              cate must be in PEM format.  If the optional  pass-\n"
-"              word isn't specified, it will be queried for on the\n"
-"              terminal. Note that this certificate is the private\n"
-"              key and the private certificate concatenated!\n"
-"\n"
-"       -f/--fail\n"
-"              (HTTP)  Fail  silently (no output at all) on server\n"
-"              errors. This is mostly done  like  this  to  better\n"
-"              enable  scripts  etc  to  better  deal  with failed\n"
-"              attempts. In normal cases when a HTTP server  fails\n"
-"              to  deliver  a document, it returns a HTML document\n"
-"              stating so (which  often  also  describes  why  and\n"
-"              more).  This flag will prevent curl from outputting\n"
-"              that and fail silently instead.\n"
-"\n"
-"       -F/--form <name=content>\n"
-"              (HTTP) This lets curl emulate a filled in  form  in\n"
-"              which  a  user  has pressed the submit button. This\n"
-"              causes curl to POST  data  using  the  content-type\n"
-"              multipart/form-data   according  to  RFC1867.  This\n"
-"              enables uploading of binary files etc. To force the\n"
-"              'content'  part  to be read from a file, prefix the\n"
-"              file name with an @ sign.  Example,  to  send  your\n"
-"              password  file  to  the server, where 'password' is\n"
-"              the name of the  form-field  to  which  /etc/passwd\n"
-"              will be the input:\n"
-"              curl -F password=@/etc/passwd www.mypasswords.com\n"
-"\n"
-"              To  read  the file's content from stdin insted of a\n"
-"              file, use - where the file name should've been.\n"
-"\n"
-"       -h/--help\n"
-"              Usage help.\n"
-"\n"
-"       -H/--header <header>\n"
-"              (HTTP) Extra header to use when getting a web page.\n"
-"              You  may  specify any number of extra headers. Note\n"
-"              that if you should add a custom header that has the\n"
-"              same  name  as  one of the internal ones curl would\n"
-"              use,  your  externally  set  header  will  be  used\n"
-"              instead  of  the  internal  one. This allows you to\n"
-"              make even trickier stuff than curl  would  normally\n"
-"              do.  You  should not replace internally set headers\n"
-"              without knowing perfectly well what you're doing.\n"
-"\n"
-"       -i/--include\n"
-"              (HTTP) Include the HTTP-header in the  output.  The\n"
-"              HTTP-header  includes things like server-name, date\n"
-"              of the document, HTTP-version and more...\n"
-"\n"
-"       -I/--head\n"
-"              (HTTP/FTP) Fetch the HTTP-header only! HTTP-servers\n"
-"              feature  the  command  HEAD  which this uses to get\n"
-"              nothing but the header of a document. When used  on\n"
-"              a FTP file, curl displays the file size only.\n"
-"\n"
-"       -K/--config <config file>\n"
-"              Specify  which  config  file to read curl arguments\n"
-"              from. The config file is a text file in which  com-\n"
-"              mand  line arguments can be written which then will\n"
-"              be used as if they were written on the actual  com-\n"
-"              mand  line. If the first column of a config line is\n"
-"              a '#' character, the  rest  of  the  line  will  be\n"
-"              treated as a comment.\n"
-"\n"
-"              Specify  the  filename as '-' to make curl read the\n"
-"              file from stdin.\n"
-"\n"
-"       -l/--list-only\n"
-"              (FTP) When listing an FTP  directory,  this  switch\n"
-"              forces  a name-only view.  Especially useful if you\n"
-"              want to machine-parse the contents of an FTP direc-\n"
-"              tory  since the normal directory view doesn't use a\n"
-"              standard look or format.\n"
-"\n"
-"       -L/--location\n"
-"              (HTTP/HTTPS)  If  the  server  reports   that   the\n"
-"              requested  page has a different location (indicated\n"
-"              with the header line Location:) this flag will  let\n"
-"              curl attempt to reattempt the get on the new place.\n"
-"              If used together with -i or -I,  headers  from  all\n"
-"              requested pages will be shown.\n"
-"\n"
-"       -m/--max-time <seconds>\n"
-"              Maximum  time  in  seconds that you allow the whole\n"
-"              operation to take.  This is useful  for  preventing\n"
-"              your  batch jobs from hanging for hours due to slow\n"
-"              networks or links going down.   This  doesn't  work\n"
-"              properly in win32 systems.\n"
-"\n"
-"       -M/--manual\n"
-"              Manual. Display the huge help text.\n"
-"\n"
-"       -n/--netrc\n"
-"              Makes  curl scan the .netrc file in the user's home\n"
-"              directory for login name and password. This is typ-\n"
-"              ically  used  for  ftp  on unix. If used with http,\n"
-"              curl will enable user authentication. See  netrc(5)\n"
-"              for  details on the file format. Curl will not com-\n"
-"              plain if that file hasn't the right permissions (it\n"
-"              should  not be world nor group readable). The envi-\n"
-"              ronment variable \"HOME\" is used to  find  the  home\n"
-"              directory.\n"
-"\n"
-"              A  quick  and very simple example of how to setup a\n"
-"              .netrc  to  allow  curl  to  ftp  to  the   machine\n"
-"              host.domain.com with user name\n"
-"\n"
-"              machine host.domain.com user myself password secret\n"
-"\n"
-"       -N/--no-buffer\n"
-"              Disables the buffering of  the  output  stream.  In\n"
-"              normal  work  situations,  curl will use a standard\n"
-"              buffered output stream that will  have  the  effect\n"
-"              that  it will output the data in chunks, not neces-\n"
-"              sarily exactly when the data arrives.   Using  this\n"
-"              option will disable that buffering.\n"
-"\n"
-"       -o/--output <file>\n"
-"              Write  output  to  <file> instead of stdout. If you\n"
-"              are using {} or [] to fetch multiple documents, you\n"
-"              can  use  '#'  followed  by  a number in the <file>\n"
-"              specifier. That variable will be replaced with  the\n"
-"              current string for the URL being fetched. Like in:\n"
-"\n"
-"                curl http://{one,two}.site.com -o \"file_#1.txt\"\n"
-"\n"
-"              or use several variables like:\n"
-"\n"
-"                curl http://{site,host}.host[1-5].com -o \"#1_#2\"\n"
-"\n"
-"       -O/--remote-name\n"
-"              Write  output to a local file named like the remote\n"
-"              file we get. (Only the file part of the remote file\n"
-"              is used, the path is cut off.)\n"
-"\n"
-"       -P/--ftpport <address>\n"
-"              (FTP)  Reverses  the  initiator/listener roles when\n"
-"              connecting with ftp. This switch makes Curl use the\n"
-"              PORT  command  instead  of  PASV. In practice, PORT\n"
-"              tells the server to connect to the client's  speci-\n"
-"              fied  address  and port, while PASV asks the server\n"
-"              for an ip address and port to connect to. <address>\n"
-"              should be one of:\n"
-"\n"
-"              interface   i.e \"eth0\" to specify which interface's\n"
-"                          IP address you want to use  (Unix only)\n"
-"\n"
-"              IP address  i.e  \"192.168.10.1\" to specify exact IP\n"
-"                          number\n"
-"\n"
-"              host name   i.e \"my.host.domain\" to specify machine\n"
-"\n"
-"              -           (any  single-letter  string) to make it\n"
-"                          pick the machine's default\n"
-"\n"
-"       -q     If used as the first parameter on the command line,\n"
-"              the $HOME/.curlrc file will not be read and used as\n"
-"              a config file.\n"
-"\n"
-"       -Q/--quote <comand>\n"
-"              (FTP) Send an arbitrary command to the  remote  FTP\n"
-"              server,  by  using the QUOTE command of the server.\n"
-"              Not all servers support this command, and  the  set\n"
-"              of  QUOTE  commands are server specific! Quote com-\n"
-"              mands are sent BEFORE the transfer is taking place.\n"
-"              To  make  commands  take  place  after a successful\n"
-"              transfer, prefix them with  a  dash  '-'.  You  may\n"
-"              specify any amount of commands to be run before and\n"
-"              after the transfer. If the server  returns  failure\n"
-"              for  one of the commands, the entire operation will\n"
-"              be aborted.\n"
-"\n"
-"       -r/--range <range>\n"
-"              (HTTP/FTP) Retrieve a byte  range  (i.e  a  partial\n"
-"              document) from a HTTP/1.1 or FTP server. Ranges can\n"
-"              be specified in a number of ways.\n"
-"\n"
-"              0-499     specifies the first 500 bytes\n"
-"\n"
-"              500-999   specifies the second 500 bytes\n"
-"\n"
-"              -500      specifies the last 500 bytes\n"
-"\n"
-"              9500      specifies the bytes from offset 9500  and\n"
-"                        forward\n"
-"\n"
-"              0-0,-1    specifies   the   first   and  last  byte\n"
-"                        only(*)(H)\n"
-"\n"
-"              500-700,600-799\n"
-"                        specifies 300 bytes from offset 500(H)\n"
-"\n"
-"              100-199,500-599\n"
-"                        specifies   two   separate   100    bytes\n"
-"                        ranges(*)(H)\n"
-"\n"
-"       (*) = NOTE that this will cause the server to reply with a\n"
-"       multipart response!\n"
-"\n"
-"       You should also be aware that many HTTP/1.1 servers do not\n"
-"       have this feature enabled, so that when you attempt to get\n"
-"       a range, you'll instead get the whole document.\n"
-"\n"
-"       FTP range downloads only support the simple syntax 'start-\n"
-"       stop'  (optionally  with  one  of the numbers omitted). It\n"
-"       depends on the non-RFC command SIZE.\n"
-"\n"
-"       -s/--silent\n"
-"              Silent mode. Don't show  progress  meter  or  error\n"
-"              messages.  Makes Curl mute.\n"
-"\n"
-"       -S/--show-error\n"
-"              When  used with -s it makes curl show error message\n"
-"              if it fails.\n"
-"\n"
-"       -t/--upload\n"
-"              Transfer the stdin data to the specified file. Curl\n"
-"              will read everything from stdin until EOF and store\n"
-"              with the supplied  name.  If  this  is  used  on  a\n"
-"              http(s) server, the PUT command will be used.\n"
-"\n"
-"       -T/--upload-file <file>\n"
-"              Like  -t,  but  this  transfers the specified local\n"
-"              file. If there is no file  part  in  the  specified\n"
-"              URL,  Curl  will  append  the local file name. NOTE\n"
-"              that you must use a trailing / on the  last  direc-\n"
-"              tory  to really prove to Curl that there is no file\n"
-"              name or curl will think that  your  last  directory\n"
-"              name is the remote file name to use. That will most\n"
-"              likely cause the upload operation to fail. If  this\n"
-"              is  used  on a http(s) server, the PUT command will\n"
-"              be used.\n"
-"\n"
-"       -u/--user <user:password>\n"
-"              Specify user and password to use when fetching. See\n"
-"              README.curl  for  detailed  examples  of how to use\n"
-"              this. If no password is specified,  curl  will  ask\n"
-"              for it interactively.\n"
-"\n"
-"       -U/--proxy-user <user:password>\n"
-"              Specify   user   and  password  to  use  for  Proxy\n"
-"              authentication. If no password is  specified,  curl\n"
-"              will ask for it interactively.\n"
-"\n"
-"       -v/--verbose\n"
-"              Makes  the  fetching more verbose/talkative. Mostly\n"
-"              usable for debugging. Lines starting with '>' means\n"
-"              data  sent by curl, '<' means data received by curl\n"
-"              that is hidden in normal cases and  lines  starting\n"
-"              with '*' means additional info provided by curl.\n"
-"\n"
-"       -V/--version\n"
-"              Displays  the  full  version  of  curl, libcurl and\n"
-"              other 3rd party  libraries  linked  with  the  exe-\n"
-"              cutable.\n"
-"\n"
-"       -w/--write-out <format>\n"
-"              Defines  what to display after a completed and suc-\n"
-"              cessful operation. The format is a string that  may\n"
-"              contain  plain  text mixed with any number of vari-\n"
-"              ables. The string can be specified as \"string\",  to\n"
-"              get  read  from  a  particular  file you specify it\n"
-"              \"@filename\" and to tell curl  to  read  the  format\n"
-"              from stdin you write \"@-\".\n"
-"\n"
-"              The  variables present in the output format will be\n"
-"              substituted by the value or text that  curl  thinks\n"
-"              fit,  as  described below. All variables are speci-\n"
-"              fied like %{variable_name} and to output a normal %\n"
-"              you  just write them like %%. You can output a new-\n"
-"              line by using \\n, a carrige return with  \\r  and  a\n"
-"              tab space with \\t.\n"
-"\n"
-"              NOTE:  The  %-letter  is  a  special  letter in the\n"
-"              win32-environment, where all occurrences of %  must\n"
-"              be doubled when using this option.\n"
-"\n"
-"              Available variables are at this point:\n"
-"\n"
-"              url_effective  The  URL that was fetched last. This\n"
-"                             is mostly meaningful if you've  told\n"
-"                             curl to follow location: headers.\n"
-"\n"
-"              http_code      The numerical code that was found in\n"
-"                             the last retrieved HTTP(S) page.\n"
-"\n"
-"              time_total     The total time, in seconds, that the\n"
-"                             full operation lasted. The time will\n"
-"                             be displayed with millisecond  reso-\n"
-"                             lution.\n"
-"\n"
-"              time_namelookup\n"
-"                             The  time,  in seconds, it took from\n"
-"                             the start until the  name  resolving\n"
-"                             was completed.\n"
-"              time_connect   The  time,  in seconds, it took from\n"
-"                             the start until the connect  to  the\n"
-"                             remote  host  (or  proxy)  was  com-\n"
-"                             pleted.\n"
-"\n"
-"              time_pretransfer\n"
-"                             The time, in seconds, it  took  from\n"
-"                             the start until the file transfer is\n"
-"                             just about to begin.  This  includes\n"
-"                             all  pre-transfer commands and nego-\n"
-"                             tiations that are  specific  to  the\n"
-"                             particular protocol(s) involved.\n"
-"\n"
-"              size_download  The  total amount of bytes that were\n"
-"                             downloaded.\n"
-"\n"
-"              size_upload    The total amount of bytes that  were\n"
-"                             uploaded.\n"
-"\n"
-"              speed_download The average download speed that curl\n"
-"                             measured for the complete  download.\n"
-"\n"
-"              speed_upload   The  average  upload speed that curl\n"
-"                             measured for the complete  download.\n"
-"\n"
-"       -x/--proxy <proxyhost[:port]>\n"
-"              Use  specified  proxy.  If  the  port number is not\n"
-"              specified, it is assumed at port 1080.\n"
-"\n"
-"       -X/--request <command>\n"
-"              (HTTP) Specifies a custom request to use when  com-\n"
-"              municating  with  the  HTTP  server.  The specified\n"
-"              request will be used instead of the  standard  GET.\n"
-"              Read  the  HTTP  1.1  specification for details and\n"
-"              explanations.\n"
-"\n"
-"              (FTP) Specifies a custom FTP command to use instead\n"
-"              of LIST when doing file lists with ftp.\n"
-"\n"
-"       -y/--speed-time <time>\n"
-"              If  a download is slower than speed-limit bytes per\n"
-"              second during a  speed-time  period,  the  download\n"
-"              gets  aborted.  If  speed-time is used, the default\n"
-"              speed-limit will be 1 unless set with -y.\n"
-"\n"
-"       -Y/--speed-limit <speed>\n"
-"              If a download is slower than this given  speed,  in\n"
-"              bytes  per  second,  for speed-time seconds it gets\n"
-"              aborted. speed-time is set with -Y and is 30 if not\n"
-"              set.\n"
-"\n"
-"       -z/--time-cond <date expression>\n"
-"              (HTTP) Request to get a file that has been modified\n"
-"              later than the given time and date, or one that has\n"
-"              been modified before that time. The date expression\n"
-"              can be all sorts of date strings or if  it  doesn't\n"
-"              match  any  internal ones, it tries to get the time\n"
-"              from a given file name instead! See the GNU date(1)\n"
-"              man page for date expression details.\n"
-"\n"
-"              Start  the  date expression with a dash (-) to make\n"
-"              it request for a document that is  older  than  the\n"
-"              given  date/time,  default  is  a  document that is\n"
-"              newer than the specified date/time.\n"
-"\n"
-"       -3/--sslv3\n"
-"              (HTTPS) Forces curl to use SSL version 3 when nego-\n"
-"              tiating with a remote SSL server.\n"
-"\n"
-"       -2/--sslv2\n"
-"              (HTTPS) Forces curl to use SSL version 2 when nego-\n"
-"              tiating with a remote SSL server.\n"
-"\n"
-"       -#/--progress-bar\n"
-"              Make  curl  display  progress  information   as   a\n"
-"              progress bar instead of the default statistics.\n"
-"\n"
-"       --crlf (FTP)  Convert LF to CRLF in upload. Useful for MVS\n"
-"              (OS/390).\n"
-"\n"
-"       --stderr <file>\n"
-"              Redirect all writes to stderr to the specified file\n"
-"              instead.  If  the  file  name is a plain '-', it is\n"
-"              instead written to stdout. This option has no point\n"
-"              when  you're  using a shell with decent redirecting\n"
-"              capabilities.\n"
+"     -a/--append\n"
+"          (FTP) When used in a ftp upload, this will tell curl to\n"
+"          append to the target file instead of overwriting it. If\n"
+"          the file doesn't exist, it will be created.\n"
+"\n"
+"     -A/--user-agent <agent string>\n"
+"          (HTTP)  Specify  the  User-Agent  string to send to the\n"
+"          HTTP server. Some badly done CGIs fail if its  not  set\n"
+"          to \"Mozilla/4.0\".  To encode blanks in the string, sur­\n"
+"          round the string with single  quote  marks.   This  can\n"
+"          also be set with the -H/--header flag of course.\n"
+"     -b/--cookie <name=data>\n"
+"          (HTTP) Pass the data to the HTTP server as a cookie. It\n"
+"          is supposedly the data  previously  received  from  the\n"
+"          server  in a \"Set-Cookie:\" line.  The data should be in\n"
+"          the format \"NAME1=VALUE1; NAME2=VALUE2\".\n"
+"\n"
+"          If no '=' letter is used in the line, it is treated  as\n"
+"          a  filename  to  use  to  read previously stored cookie\n"
+"          lines from, which should be used  in  this  session  if\n"
+"          they  match.  Using  this  method  also  activates  the\n"
+"          \"cookie parser\" which will make  curl  record  incoming\n"
+"          cookies too, which may be handy if you're using this in\n"
+"          combination with the  -L/--location  option.  The  file\n"
+"          format of the file to read cookies from should be plain\n"
+"          HTTP headers or the netscape cookie file format.\n"
+"\n"
+"          NOTE that the file specified with -b/--cookie  is  only\n"
+"          used  as  input. No cookies will be stored in the file.\n"
+"          To store cookies, save the HTTP headers to a file using\n"
+"          -D/--dump-header!\n"
+"\n"
+"     -B/--ftp-ascii\n"
+"          (FTP/LDAP)  Use ASCII transfer when getting an FTP file\n"
+"          or LDAP info. For FTP, this can  also  be  enforced  by\n"
+"          using an URL that ends with \";type=A\".\n"
+"\n"
+"     -c/--continue\n"
+"          Continue/Resume   a   previous   file   transfer.  This\n"
+"          instructs curl to continue appending data on  the  file\n"
+"          where  it  was  previously  left, possibly because of a\n"
+"          broken connection to the server. There must be a  named\n"
+"          physical  file  to  append  to for this to work.  Note:\n"
+"          Upload resume is depening on a command named  SIZE  not\n"
+"          always present in all ftp servers! Upload resume is for\n"
+"          FTP only.  HTTP resume is only possible  with  HTTP/1.1\n"
+"          or later servers.\n"
+"\n"
+"     -C/--continue-at <offset>\n"
+"          Continue/Resume  a  previous file transfer at the given\n"
+"          offset. The given offset is the exact number  of  bytes\n"
+"          that  will be skipped counted from the beginning of the\n"
+"          source file before it is transfered to the destination.\n"
+"          If  used with uploads, the ftp server command SIZE will\n"
+"          not be used by curl. Upload resume  is  for  FTP  only.\n"
+"          HTTP  resume  is  only  possible with HTTP/1.1 or later\n"
+"          servers.\n"
+"\n"
+"     -d/--data <data>\n"
+"          (HTTP) Sends the specified data in a  POST  request  to\n"
+"          the  HTTP server. Note that the data is sent exactly as\n"
+"          specified  with  no  extra  processing.   The  data  is\n"
+"          expected  to  be \"url-encoded\". This will cause curl to\n"
+"          pass the data to  the  server  using  the  content-type\n"
+"          application/x-www-form-urlencoded. Compare to -F.\n"
+"\n"
+"          If  you  start  the  data  with  the letter @, the rest\n"
+"          should be a file name to read the data from,  or  -  if\n"
+"          you  want  curl  to read the data from stdin.  The con­\n"
+"          tents of the file must already be url-encoded.\n"
+"\n"
+"     -D/--dump-header <file>\n"
+"          (HTTP/FTP) Write the HTTP headers to this  file.  Write\n"
+"          the FTP file info to this file if -I/--head is used.\n"
+"\n"
+"          This  option is handy to use when you want to store the\n"
+"          cookies that a HTTP site  sends  to  you.  The  cookies\n"
+"          could then be read in a second curl invoke by using the\n"
+"          -b/--cookie option!\n"
+"\n"
+"     -e/--referer <URL>\n"
+"          (HTTP) Sends the \"Referer Page\" information to the HTTP\n"
+"          server. Some badly done CGIs fail if it's not set. This\n"
+"          can also be set with the -H/--header flag of course.\n"
+"\n"
+"     -E/--cert <certificate[:password]>\n"
+"          (HTTPS) Tells curl to  use  the  specified  certificate\n"
+"          file  when  getting  a file with HTTPS. The certificate\n"
+"          must be in PEM format.  If the optional password  isn't\n"
+"          specified, it will be queried for on the terminal. Note\n"
+"          that this certificate is the private key and  the  pri­\n"
+"          vate certificate concatenated!\n"
+"\n"
+"     -f/--fail\n"
+"          (HTTP)  Fail  silently  (no  output  at  all) on server\n"
+"          errors. This is mostly done like this to better  enable\n"
+"          scripts  etc  to  better  deal with failed attempts. In\n"
+"          normal cases when a HTTP server fails to deliver a doc­\n"
+"          ument,  it  returns  a  HTML document stating so (which\n"
+"          often also describes why and more). This flag will pre­\n"
+"          vent  curl  from  outputting  that  and  fail  silently\n"
+"          instead.\n"
+"\n"
+"     -F/--form <name=content>\n"
+"          (HTTP) This lets curl emulate a filled in form in which\n"
+"          a  user has pressed the submit button. This causes curl\n"
+"          to POST data using the content-type multipart/form-data\n"
+"          according  to RFC1867. This enables uploading of binary\n"
+"          files etc. To force the 'content' part to be read  from\n"
+"          a  file,  prefix the file name with an @ sign. Example,\n"
+"          to send your password file to the server, where  'pass­\n"
+"          word'   is   the   name  of  the  form-field  to  which\n"
+"          /etc/passwd will be the input:\n"
+"\n"
+"          curl -F password=@/etc/passwd www.mypasswords.com\n"
+"          To read the file's content from stdin insted of a file,\n"
+"          use - where the file name should've been.\n"
+"\n"
+"     -h/--help\n"
+"          Usage help.\n"
+"\n"
+"     -H/--header <header>\n"
+"          (HTTP) Extra header to use when getting a web page. You\n"
+"          may specify any number of extra headers. Note  that  if\n"
+"          you  should  add a custom header that has the same name\n"
+"          as one of the internal ones curl would use, your exter­\n"
+"          nally  set  header will be used instead of the internal\n"
+"          one. This allows you to make even trickier  stuff  than\n"
+"          curl  would  normally do. You should not replace inter­\n"
+"          nally set headers without knowing perfectly  well  what\n"
+"          you're doing.\n"
+"\n"
+"     -i/--include\n"
+"          (HTTP) Include the HTTP-header in the output. The HTTP-\n"
+"          header includes things like server-name,  date  of  the\n"
+"          document, HTTP-version and more...\n"
+"\n"
+"     -I/--head\n"
+"          (HTTP/FTP)  Fetch  the  HTTP-header  only! HTTP-servers\n"
+"          feature the command HEAD which this uses to get nothing\n"
+"          but  the header of a document. When used on a FTP file,\n"
+"          curl displays the file size only.\n"
+"\n"
+"     -K/--config <config file>\n"
+"          Specify which config file to read curl arguments  from.\n"
+"          The  config  file  is a text file in which command line\n"
+"          arguments can be written which then will be used as  if\n"
+"          they  were  written  on the actual command line. If the\n"
+"          first column of a config line is a '#'  character,  the\n"
+"          rest of the line will be treated as a comment.\n"
+"\n"
+"          Specify  the filename as '-' to make curl read the file\n"
+"          from stdin.\n"
+"\n"
+"     -l/--list-only\n"
+"          (FTP) When listing an FTP directory, this switch forces\n"
+"          a  name-only  view.   Especially  useful if you want to\n"
+"          machine-parse the contents of an  FTP  directory  since\n"
+"          the  normal  directory view doesn't use a standard look\n"
+"          or format.\n"
+"\n"
+"     -L/--location\n"
+"          (HTTP/HTTPS) If the server reports that  the  requested\n"
+"          page  has  a  different  location  (indicated  with the\n"
+"          header line Location:) this flag will let curl  attempt\n"
+"          to reattempt the get on the new place. If used together\n"
+"          with -i or -I, headers from all requested pages will be\n"
+"          shown.\n"
+"\n"
+"     -m/--max-time <seconds>\n"
+"          Maximum time in seconds that you allow the whole opera­\n"
+"          tion to take.  This is useful for preventing your batch\n"
+"          jobs  from  hanging  for  hours due to slow networks or\n"
+"          links going down.  This doesn't work properly in  win32\n"
+"          systems.\n"
+"\n"
+"     -M/--manual\n"
+"          Manual. Display the huge help text.\n"
+"\n"
+"     -n/--netrc\n"
+"          Makes  curl  scan  the  .netrc  file in the user's home\n"
+"          directory for login name and password.  This  is  typi­\n"
+"          cally  used  for  ftp  on unix. If used with http, curl\n"
+"          will  enable  user  authentication.  See  netrc(5)  for\n"
+"          details  on  the file format. Curl will not complain if\n"
+"          that file hasn't the right permissions (it  should  not\n"
+"          be  world nor group readable). The environment variable\n"
+"          \"HOME\" is used to find the home directory.\n"
+"\n"
+"          A quick and very simple  example  of  how  to  setup  a\n"
+"          .netrc   to   allow   curl   to   ftp  to  the  machine\n"
+"          host.domain.com with user name\n"
+"\n"
+"          machine host.domain.com login myself password secret\n"
+"\n"
+"     -N/--no-buffer\n"
+"          Disables the buffering of the output stream. In  normal\n"
+"          work situations, curl will use a standard buffered out­\n"
+"          put stream that will have the effect that it will  out­\n"
+"          put  the  data  in chunks, not necessarily exactly when\n"
+"          the data arrives.  Using this option will disable  that\n"
+"          buffering.\n"
+"\n"
+"     -o/--output <file>\n"
+"          Write  output  to  <file> instead of stdout. If you are\n"
+"          using {} or [] to fetch multiple documents, you can use\n"
+"          '#'  followed by a number in the <file> specifier. That\n"
+"          variable will be replaced with the current  string  for\n"
+"          the URL being fetched. Like in:\n"
+"\n"
+"            curl http://{one,two}.site.com -o \"file_#1.txt\"\n"
+"\n"
+"          or use several variables like:\n"
+"\n"
+"            curl http://{site,host}.host[1-5].com -o \"#1_#2\"\n"
+"\n"
+"     -O/--remote-name\n"
+"          Write output to a local file named like the remote file\n"
+"          we get. (Only the file part of the remote file is used,\n"
+"          the path is cut off.)\n"
+"\n"
+"     -P/--ftpport <address>\n"
+"          (FTP)  Reverses  the initiator/listener roles when con­\n"
+"          necting with ftp. This switch makes Curl use  the  PORT\n"
+"          command  instead  of  PASV. In practice, PORT tells the\n"
+"          server to connect to the client's specified address and\n"
+"          port,  while PASV asks the server for an ip address and\n"
+"          port to connect to. <address> should be one of:\n"
+"\n"
+"          interface   i.e \"eth0\" to specify which interface's  IP\n"
+"                      address you want to use  (Unix only)\n"
+"\n"
+"          IP address  i.e \"192.168.10.1\" to specify exact IP num­\n"
+"                      ber\n"
+"\n"
+"          host name   i.e \"my.host.domain\" to specify machine\n"
+"\n"
+"          -           (any single-letter string) to make it  pick\n"
+"                      the machine's default\n"
+"\n"
+"     -q   If used as the first parameter on the command line, the\n"
+"          $HOME/.curlrc file will not be read and used as a  con­\n"
+"          fig file.\n"
+"\n"
+"     -Q/--quote <comand>\n"
+"          (FTP)  Send  an  arbitrary  command  to  the remote FTP\n"
+"          server, by using the QUOTE command of the  server.  Not\n"
+"          all  servers support this command, and the set of QUOTE\n"
+"          commands are server specific! Quote commands  are  sent\n"
+"          BEFORE  the  transfer is taking place. To make commands\n"
+"          take place after a  successful  transfer,  prefix  them\n"
+"          with a dash '-'. You may specify any amount of commands\n"
+"          to be run before and after the transfer. If the  server\n"
+"          returns  failure  for  one  of the commands, the entire\n"
+"          operation will be aborted.\n"
+"\n"
+"     -r/--range <range>\n"
+"          (HTTP/FTP) Retrieve a byte range (i.e a  partial  docu­\n"
+"          ment)  from  a  HTTP/1.1  or  FTP server. Ranges can be\n"
+"          specified in a number of ways.\n"
+"\n"
+"          0-499     specifies the first 500 bytes\n"
+"\n"
+"          500-999   specifies the second 500 bytes\n"
+"\n"
+"          -500      specifies the last 500 bytes\n"
+"\n"
+"          9500      specifies the bytes from offset 9500 and for­\n"
+"                    ward\n"
+"\n"
+"          0-0,-1    specifies the first and last byte only(*)(H)\n"
+"          500-700,600-799\n"
+"                    specifies 300 bytes from offset 500(H)\n"
+"\n"
+"          100-199,500-599\n"
+"                    specifies two separate 100 bytes ranges(*)(H)\n"
+"\n"
+"     (*) = NOTE that this will cause the server to reply  with  a\n"
+"     multipart response!\n"
+"\n"
+"     You  should  also be aware that many HTTP/1.1 servers do not\n"
+"     have this feature enabled, so that when you attempt to get a\n"
+"     range, you'll instead get the whole document.\n"
+"\n"
+"     FTP  range  downloads only support the simple syntax 'start-\n"
+"     stop' (optionally with  one  of  the  numbers  omitted).  It\n"
+"     depends on the non-RFC command SIZE.\n"
+"\n"
+"     -s/--silent\n"
+"          Silent  mode.  Don't  show progress meter or error mes­\n"
+"          sages.  Makes Curl mute.\n"
+"\n"
+"     -S/--show-error\n"
+"          When used with -s it makes curl show error  message  if\n"
+"          it fails.\n"
+"\n"
+"     -t/--upload\n"
+"          Transfer  the  stdin  data  to the specified file. Curl\n"
+"          will read everything from stdin  until  EOF  and  store\n"
+"          with  the  supplied  name. If this is used on a http(s)\n"
+"          server, the PUT command will be used.\n"
+"\n"
+"     -T/--upload-file <file>\n"
+"          Like -t, but this transfers the specified  local  file.\n"
+"          If  there  is  no  file part in the specified URL, Curl\n"
+"          will append the local file name. NOTE that you must use\n"
+"          a  trailing  / on the last directory to really prove to\n"
+"          Curl that there is no file name or curl will think that\n"
+"          your  last  directory  name  is the remote file name to\n"
+"          use. That will most likely cause the  upload  operation\n"
+"          to  fail.  If this is used on a http(s) server, the PUT\n"
+"          command will be used.\n"
+"\n"
+"     -u/--user <user:password>\n"
+"          Specify user and password to  use  when  fetching.  See\n"
+"          README.curl  for  detailed examples of how to use this.\n"
+"          If no password is  specified,  curl  will  ask  for  it\n"
+"          interactively.\n"
+"\n"
+"     -U/--proxy-user <user:password>\n"
+"          Specify  user and password to use for Proxy authentica­\n"
+"          tion. If no password is specified, curl will ask for it\n"
+"          interactively.\n"
+"     -v/--verbose\n"
+"          Makes   the  fetching  more  verbose/talkative.  Mostly\n"
+"          usable for debugging. Lines  starting  with  '>'  means\n"
+"          data sent by curl, '<' means data received by curl that\n"
+"          is hidden in normal cases and lines starting  with  '*'\n"
+"          means additional info provided by curl.\n"
+"\n"
+"     -V/--version\n"
+"          Displays  the  full  version of curl, libcurl and other\n"
+"          3rd party libraries linked with the executable.\n"
+"\n"
+"     -w/--write-out <format>\n"
+"          Defines what to display after a completed and  success­\n"
+"          ful  operation. The format is a string that may contain\n"
+"          plain text mixed with  any  number  of  variables.  The\n"
+"          string can be specified as \"string\", to get read from a\n"
+"          particular file you specify it \"@filename\" and to  tell\n"
+"          curl to read the format from stdin you write \"@-\".\n"
+"\n"
+"          The variables present in the output format will be sub­\n"
+"          stituted by the value or text that curl thinks fit,  as\n"
+"          described  below.  All  variables  are  specified  like\n"
+"          %{variable_name} and to output  a  normal  %  you  just\n"
+"          write  them  like %%. You can output a newline by using\n"
+"          \\n, a carrige return with \\r and a tab space with \\t.\n"
+"\n"
+"          NOTE:  The  %-letter  is  a  special  letter   in   the\n"
+"          win32-environment,  where  all occurrences of % must be\n"
+"          doubled when using this option.\n"
+"\n"
+"          Available variables are at this point:\n"
+"\n"
+"          url_effective  The URL that was fetched last.  This  is\n"
+"                         mostly meaningful if you've told curl to\n"
+"                         follow location: headers.\n"
+"\n"
+"          http_code      The numerical code that was found in the\n"
+"                         last retrieved HTTP(S) page.\n"
+"\n"
+"          time_total     The  total  time,  in  seconds, that the\n"
+"                         full operation lasted. The time will  be\n"
+"                         displayed with millisecond resolution.\n"
+"\n"
+"          time_namelookup\n"
+"                         The  time,  in seconds, it took from the\n"
+"                         start until the name resolving was  com­\n"
+"                         pleted.\n"
+"\n"
+"          time_connect   The  time,  in seconds, it took from the\n"
+"                         start until the connect  to  the  remote\n"
+"                         host (or proxy) was completed.\n"
+"          time_pretransfer\n"
+"                         The  time,  in seconds, it took from the\n"
+"                         start until the file  transfer  is  just\n"
+"                         about  to  begin. This includes all pre-\n"
+"                         transfer commands and negotiations  that\n"
+"                         are  specific  to  the particular proto­\n"
+"                         col(s) involved.\n"
+"\n"
+"          size_download  The total  amount  of  bytes  that  were\n"
+"                         downloaded.\n"
+"\n"
+"          size_upload    The  total  amount  of  bytes  that were\n"
+"                         uploaded.\n"
+"\n"
+"          speed_download The average  download  speed  that  curl\n"
+"                         measured for the complete download.\n"
+"\n"
+"          speed_upload   The  average upload speed that curl mea­\n"
+"                         sured for the complete download.\n"
+"\n"
+"     -x/--proxy <proxyhost[:port]>\n"
+"          Use specified proxy. If the port number is  not  speci­\n"
+"          fied, it is assumed at port 1080.\n"
+"\n"
+"     -X/--request <command>\n"
+"          (HTTP)  Specifies a custom request to use when communi­\n"
+"          cating with the HTTP  server.   The  specified  request\n"
+"          will be used instead of the standard GET. Read the HTTP\n"
+"          1.1 specification for details and explanations.\n"
+"\n"
+"          (FTP) Specifies a custom FTP command to use instead  of\n"
+"          LIST when doing file lists with ftp.\n"
+"\n"
+"     -y/--speed-time <time>\n"
+"          If a download is slower than speed-limit bytes per sec­\n"
+"          ond during  a  speed-time  period,  the  download  gets\n"
+"          aborted. If speed-time is used, the default speed-limit\n"
+"          will be 1 unless set with -y.\n"
+"\n"
+"     -Y/--speed-limit <speed>\n"
+"          If a download is slower than this given speed, in bytes\n"
+"          per  second,  for  speed-time  seconds it gets aborted.\n"
+"          speed-time is set with -Y and is 30 if not set.\n"
+"\n"
+"     -z/--time-cond <date expression>\n"
+"          (HTTP) Request to get a file  that  has  been  modified\n"
+"          later  than  the  given  time and date, or one that has\n"
+"          been modified before that time. The date expression can\n"
+"          be all sorts of date strings or if it doesn't match any\n"
+"          internal ones, it tries to get the time  from  a  given\n"
+"          file  name  instead!  See  the GNU date(1) man page for\n"
+"          date expression details.\n"
+"          Start the date expression with a dash (-)  to  make  it\n"
+"          request  for  a  document  that is older than the given\n"
+"          date/time, default is a document that is newer than the\n"
+"          specified date/time.\n"
+"\n"
+"     -3/--sslv3\n"
+"          (HTTPS) Forces curl to use SSL version 3 when negotiat­\n"
+"          ing with a remote SSL server.\n"
+"\n"
+"     -2/--sslv2\n"
+"          (HTTPS) Forces curl to use SSL version 2 when negotiat­\n"
+"          ing with a remote SSL server.\n"
+"\n"
+"     -#/--progress-bar\n"
+"          Make  curl  display  progress information as a progress\n"
+"          bar instead of the default statistics.\n"
+"\n"
+"     --crlf\n"
+"          (FTP) Convert LF to CRLF  in  upload.  Useful  for  MVS\n"
+"          (OS/390).\n"
+"\n"
+"     --stderr <file>\n"
+"          Redirect  all  writes  to  stderr to the specified file\n"
+"          instead. If the file name is a plain '-', it is instead\n"
+"          written to stdout. This option has no point when you're\n"
+"          using a shell with decent redirecting capabilities.\n"
 "\n"
 "FILES\n"
-"       ~/.curlrc\n"
-"              Default config file.\n"
+"     ~/.curlrc\n"
+"          Default config file.\n"
 "\n"
 "ENVIRONMENT\n"
-"       HTTP_PROXY [protocol://]<host>[:port]\n"
-"              Sets proxy server to use for HTTP.\n"
+"     HTTP_PROXY [protocol://]<host>[:port]\n"
+"          Sets proxy server to use for HTTP.\n"
 "\n"
-"       HTTPS_PROXY [protocol://]<host>[:port]\n"
-"              Sets proxy server to use for HTTPS.\n"
+"     HTTPS_PROXY [protocol://]<host>[:port]\n"
+"          Sets proxy server to use for HTTPS.\n"
 "\n"
-"       FTP_PROXY [protocol://]<host>[:port]\n"
-"              Sets proxy server to use for FTP.\n"
+"     FTP_PROXY [protocol://]<host>[:port]\n"
+"          Sets proxy server to use for FTP.\n"
 "\n"
-"       GOPHER_PROXY [protocol://]<host>[:port]\n"
-"              Sets proxy server to use for GOPHER.\n"
+"     GOPHER_PROXY [protocol://]<host>[:port]\n"
+"          Sets proxy server to use for GOPHER.\n"
 "\n"
-"       ALL_PROXY [protocol://]<host>[:port]\n"
-"              Sets proxy server to use  if  no  protocol-specific\n"
-"              proxy is set.\n"
-"       NO_PROXY <comma-separated list of hosts>\n"
-"              list  of  host  names that shouldn't go through any\n"
-"              proxy. If set to a asterisk '*'  only,  it  matches\n"
-"              all hosts.\n"
+"     ALL_PROXY [protocol://]<host>[:port]\n"
+"          Sets proxy server to use if no protocol-specific  proxy\n"
+"          is set.\n"
 "\n"
-"       COLUMNS <integer>\n"
-"              The  width  of  the  terminal.   This variable only\n"
-"              affects curl  when  the  --progress-bar  option  is\n"
-"              used.\n"
+"     NO_PROXY <comma-separated list of hosts>\n"
+"          list of host names that shouldn't go through any proxy.\n"
+"          If set to a asterisk '*' only, it matches all hosts.\n"
+"     COLUMNS <integer>\n"
+"          The width of the terminal.  This variable only  affects\n"
+"          curl when the --progress-bar option is used.\n"
 "\n"
 "EXIT CODES\n"
-"       There  exists  a  bunch of different error codes and their\n"
-"       corresponding error messages that may  appear  during  bad\n"
-"       conditions.  At  the  time of this writing, the exit codes\n"
-"       are:\n"
+"     There exists a bunch of different error codes and their cor­\n"
+"     responding error messages that may appear during bad  condi­\n"
+"     tions. At the time of this writing, the exit codes are:\n"
 "\n"
-"       1      Unsupported protocol. This build  of  curl  has  no\n"
-"              support for this protocol.\n"
+"     1    Unsupported protocol. This build of curl has no support\n"
+"          for this protocol.\n"
 "\n"
-"       2      Failed to initialize.\n"
+"     2    Failed to initialize.\n"
 "\n"
-"       3      URL malformat. The syntax was not correct.\n"
+"     3    URL malformat. The syntax was not correct.\n"
 "\n"
-"       4      URL  user  malformatted.  The  user-part of the URL\n"
-"              syntax was not correct.\n"
+"     4    URL user malformatted. The user-part of the URL  syntax\n"
+"          was not correct.\n"
 "\n"
-"       5      Couldn't resolve proxy. The given proxy host  could\n"
-"              not be resolved.\n"
+"     5    Couldn't  resolve proxy. The given proxy host could not\n"
+"          be resolved.\n"
 "\n"
-"       6      Couldn't  resolve  host.  The given remote host was\n"
-"              not resolved.\n"
+"     6    Couldn't resolve host. The given remote  host  was  not\n"
+"          resolved.\n"
 "\n"
-"       7      Failed to connect to host.\n"
+"     7    Failed to connect to host.\n"
 "\n"
-"       8      FTP weird server reply. The server sent  data  curl\n"
-"              couldn't parse.\n"
+"     8    FTP  weird  server  reply.  The  server  sent data curl\n"
+"          couldn't parse.\n"
 "\n"
-"       9      FTP access denied. The server denied login.\n"
+"     9    FTP access denied. The server denied login.\n"
 "\n"
-"       10     FTP  user/password  incorrect.  Either  one or both\n"
-"              were not accepted by the server.\n"
+"     10   FTP user/password incorrect. Either one  or  both  were\n"
+"          not accepted by the server.\n"
 "\n"
-"       11     FTP weird PASS reply. Curl couldn't parse the reply\n"
-"              sent to the PASS request.\n"
+"     11   FTP  weird  PASS  reply.  Curl couldn't parse the reply\n"
+"          sent to the PASS request.\n"
 "\n"
-"       12     FTP weird USER reply. Curl couldn't parse the reply\n"
-"              sent to the USER request.\n"
+"     12   FTP weird USER reply. Curl  couldn't  parse  the  reply\n"
+"          sent to the USER request.\n"
 "\n"
-"       13     FTP weird PASV reply, Curl couldn't parse the reply\n"
-"              sent to the PASV request.\n"
+"     13   FTP  weird  PASV  reply,  Curl couldn't parse the reply\n"
+"          sent to the PASV request.\n"
 "\n"
-"       14     FTP  weird  227  formay.  Curl  couldn't  parse the\n"
-"              227-line the server sent.\n"
-"       15     FTP can't get host. Couldn't resolve the host IP we\n"
-"              got in the 227-line.\n"
+"     14   FTP weird 227 formay. Curl couldn't parse the  227-line\n"
+"          the server sent.\n"
 "\n"
-"       16     FTP  can't  reconnect. Couldn't connect to the host\n"
-"              we got in the 227-line.\n"
+"     15   FTP can't get host. Couldn't resolve the host IP we got\n"
+"          in the 227-line.\n"
 "\n"
-"       17     FTP couldn't set binary. Couldn't  change  transfer\n"
-"              method to binary.\n"
+"     16   FTP can't reconnect. Couldn't connect to  the  host  we\n"
+"          got in the 227-line.\n"
+"     17   FTP  couldn't  set  binary.  Couldn't  change  transfer\n"
+"          method to binary.\n"
 "\n"
-"       18     Partial  file.  Only  a part of the file was trans-\n"
-"              fered.\n"
+"     18   Partial file. Only a part of the file was transfered.\n"
 "\n"
-"       19     FTP couldn't RETR file. The RETR command failed.\n"
+"     19   FTP couldn't RETR file. The RETR command failed.\n"
 "\n"
-"       20     FTP write error. The transfer was reported  bad  by\n"
-"              the server.\n"
+"     20   FTP write error. The transfer was reported bad  by  the\n"
+"          server.\n"
 "\n"
-"       21     FTP  quote  error.  A  quote command returned error\n"
-"              from the server.\n"
+"     21   FTP  quote  error.  A quote command returned error from\n"
+"          the server.\n"
 "\n"
-"       22     HTTP not found. The requested page was  not  found.\n"
-"              This return code only appears if --fail is used.\n"
+"     22   HTTP not found. The requested page was not found.  This\n"
+"          return code only appears if --fail is used.\n"
 "\n"
-"       23     Write  error.  Curl  couldn't write data to a local\n"
-"              filesystem or similar.\n"
+"     23   Write  error.  Curl  couldn't  write  data  to  a local\n"
+"          filesystem or similar.\n"
 "\n"
-"       24     Malformat user. User name badly specified.\n"
+"     24   Malformat user. User name badly specified.\n"
 "\n"
-"       25     FTP couldn't STOR file. The server denied the  STOR\n"
-"              operation.\n"
+"     25   FTP couldn't STOR file.  The  server  denied  the  STOR\n"
+"          operation.\n"
 "\n"
-"       26     Read error. Various reading problems.\n"
+"     26   Read error. Various reading problems.\n"
 "\n"
-"       27     Out  of memory. A memory allocation request failed.\n"
+"     27   Out of memory. A memory allocation request failed.\n"
 "\n"
-"       28     Operation timeout. The  specified  time-out  period\n"
-"              was reached according to the conditions.\n"
+"     28   Operation  timeout.  The  specified time-out period was\n"
+"          reached according to the conditions.\n"
 "\n"
-"       29     FTP  couldn't  set  ASCII.  The  server returned an\n"
-"              unknown reply.\n"
+"     29   FTP couldn't set ASCII. The server returned an  unknown\n"
+"          reply.\n"
 "\n"
-"       30     FTP PORT failed. The PORT command failed.\n"
+"     30   FTP PORT failed. The PORT command failed.\n"
 "\n"
-"       31     FTP couldn't use REST. The REST command failed.\n"
+"     31   FTP couldn't use REST. The REST command failed.\n"
 "\n"
-"       32     FTP couldn't use SIZE. The SIZE command failed. The\n"
-"              command  is  an  extension to the original FTP spec\n"
-"              RFC 959.\n"
+"     32   FTP  couldn't  use  SIZE.  The SIZE command failed. The\n"
+"          command is an extension to the original  FTP  spec  RFC\n"
+"          959.\n"
 "\n"
-"       33     HTTP range error. The range \"command\" didn't  work.\n"
+"     33   HTTP range error. The range \"command\" didn't work.\n"
 "\n"
-"       34     HTTP  post  error. Internal post-request generation\n"
-"              error.\n"
-"       35     SSL connect error. The SSL handshaking failed.\n"
+"     34   HTTP   post  error.  Internal  post-request  generation\n"
+"          error.\n"
 "\n"
-"       36     FTP bad download resume. Couldn't continue an  ear-\n"
-"              lier aborted download.\n"
+"     35   SSL connect error. The SSL handshaking failed.\n"
 "\n"
-"       37     FILE  couldn't  read file. Failed to open the file.\n"
-"              Permissions?\n"
+"     36   FTP bad download resume. Couldn't continue  an  earlier\n"
+"          aborted download.\n"
+"     37   FILE  couldn't read file. Failed to open the file. Per­\n"
+"          missions?\n"
 "\n"
-"       38     LDAP cannot bind. LDAP bind operation failed.\n"
+"     38   LDAP cannot bind. LDAP bind operation failed.\n"
 "\n"
-"       39     LDAP search failed.\n"
+"     39   LDAP search failed.\n"
 "\n"
-"       40     Library not found. The LDAP library was not  found.\n"
+"     40   Library not found. The LDAP library was not found.\n"
 "\n"
-"       41     Function  not  found.  A required LDAP function was\n"
-"              not found.\n"
+"     41   Function not found. A required LDAP  function  was  not\n"
+"          found.\n"
 "\n"
-"       XX     There will appear more error codes here  in  future\n"
-"              releases.  The  existing  ones  are  meant to never\n"
-"              change.\n"
+"     XX   There  will  appear  more  error  codes  here in future\n"
+"          releases. The existing ones are meant to never  change.\n"
 "\n"
 "BUGS\n"
-"       If you do find  any  (or  have  other  suggestions),  mail\n"
-"       Daniel Stenberg <Daniel.Stenberg@haxx.nu>.\n"
+"     If  you do find any (or have other suggestions), mail Daniel\n"
+"     Stenberg <Daniel.Stenberg@haxx.nu>.\n"
 "\n"
 "AUTHORS / CONTRIBUTORS\n"
-"        - Daniel Stenberg <Daniel.Stenberg@haxx.nu>\n"
-"        - Rafael Sagula <sagula@inf.ufrgs.br>\n"
-"        - Sampo Kellomaki <sampo@iki.fi>\n"
-"        - Linas Vepstas <linas@linas.org>\n"
-"        - Bjorn Reese <breese@mail1.stofanet.dk>\n"
-"        - Johan Anderson <johan@homemail.com>\n"
-"        - Kjell Ericson <Kjell.Ericson@haxx,nu>\n"
-"        - Troy Engel <tengel@sonic.net>\n"
-"        - Ryan Nelson <ryan@inch.com>\n"
-"        - Bjorn Stenberg <Bjorn.Stenberg@haxx.nu>\n"
-"        - Angus Mackay <amackay@gus.ml.org>\n"
-"        - Eric Young <eay@cryptsoft.com>\n"
-"        - Simon Dick <simond@totally.irrelevant.org>\n"
-"        - Oren Tirosh <oren@monty.hishome.net>\n"
-"        - Steven G. Johnson <stevenj@alum.mit.edu>\n"
-"        - Gilbert Ramirez Jr. <gram@verdict.uthscsa.edu>\n"
-"        - Andr's Garc'a <ornalux@redestb.es>\n"
-"        - Douglas E. Wegscheid <wegscd@whirlpool.com>\n"
-"        - Mark Butler <butlerm@xmission.com>\n"
-"        - Eric Thelin <eric@generation-i.com>\n"
-"        - Marc Boucher <marc@mbsi.ca>\n"
-"        - Greg Onufer <Greg.Onufer@Eng.Sun.COM>\n"
-"        - Doug Kaufman <dkaufman@rahul.net>\n"
-"        - David Eriksson <david@2good.com>\n"
-"        - Ralph Beckmann <rabe@uni-paderborn.de>\n"
-"        - T. Yamada <tai@imasy.or.jp>\n"
-"        - Lars J. Aas <larsa@sim.no>\n"
-"        - J\"rn Hartroth <Joern.Hartroth@telekom.de>\n"
-"        - Matthew Clarke <clamat@van.maves.ca>\n"
-"        - Linus Nielsen <Linus.Nielsen@haxx.nu>\n"
-"        - Felix von Leitner <felix@convergence.de>\n"
-"        - Dan Zitter <dzitter@zitter.net>\n"
-"        - Jongki Suwandi <Jongki.Suwandi@eng.sun.com>\n"
-"        - Chris Maltby <chris@aurema.com>\n"
-"        - Ron Zapp <rzapper@yahoo.com>\n"
-"        - Paul Marquis <pmarquis@iname.com>\n"
-"        - Ellis Pritchard <ellis@citria.com>\n"
-"        - Damien Adant <dams@usa.net>\n"
-"        - Chris <cbayliss@csc.come>\n"
-"        - Marco G. Salvagno <mgs@whiz.cjb.net>\n"
+"      - Daniel Stenberg <Daniel.Stenberg@haxx.nu>\n"
+"      - Rafael Sagula <sagula@inf.ufrgs.br>\n"
+"      - Sampo Kellomaki <sampo@iki.fi>\n"
+"      - Linas Vepstas <linas@linas.org>\n"
+"      - Bjorn Reese <breese@mail1.stofanet.dk>\n"
+"      - Johan Anderson <johan@homemail.com>\n"
+"      - Kjell Ericson <Kjell.Ericson@haxx,nu>\n"
+"      - Troy Engel <tengel@sonic.net>\n"
+"      - Ryan Nelson <ryan@inch.com>\n"
+"      - Bjorn Stenberg <Bjorn.Stenberg@haxx.nu>\n"
+"      - Angus Mackay <amackay@gus.ml.org>\n"
+"      - Eric Young <eay@cryptsoft.com>\n"
+"      - Simon Dick <simond@totally.irrelevant.org>\n"
+"      - Oren Tirosh <oren@monty.hishome.net>\n"
+"      - Steven G. Johnson <stevenj@alum.mit.edu>\n"
+"      - Gilbert Ramirez Jr. <gram@verdict.uthscsa.edu>\n"
+"      - Andrés García <ornalux@redestb.es>\n"
+"      - Douglas E. Wegscheid <wegscd@whirlpool.com>\n"
+"      - Mark Butler <butlerm@xmission.com>\n"
+"      - Eric Thelin <eric@generation-i.com>\n"
+"      - Marc Boucher <marc@mbsi.ca>\n"
+"      - Greg Onufer <Greg.Onufer@Eng.Sun.COM>\n"
+"      - Doug Kaufman <dkaufman@rahul.net>\n"
+"      - David Eriksson <david@2good.com>\n"
+"      - Ralph Beckmann <rabe@uni-paderborn.de>\n"
+"      - T. Yamada <tai@imasy.or.jp>\n"
+"      - Lars J. Aas <larsa@sim.no>\n"
+"      - Jörn Hartroth <Joern.Hartroth@telekom.de>\n"
+"      - Matthew Clarke <clamat@van.maves.ca>\n"
+"      - Linus Nielsen <Linus.Nielsen@haxx.nu>\n"
+"      - Felix von Leitner <felix@convergence.de>\n"
+"      - Dan Zitter <dzitter@zitter.net>\n"
+"      - Jongki Suwandi <Jongki.Suwandi@eng.sun.com>\n"
+"      - Chris Maltby <chris@aurema.com>\n"
+"      - Ron Zapp <rzapper@yahoo.com>\n"
+"      - Paul Marquis <pmarquis@iname.com>\n"
+"      - Ellis Pritchard <ellis@citria.com>\n"
+"      - Damien Adant <dams@usa.net>\n"
+"      - Chris <cbayliss@csc.come>\n"
+"      - Marco G. Salvagno <mgs@whiz.cjb.net>\n"
 "\n"
 "WWW\n"
-"       http://curl.haxx.nu\n"
+"     http://curl.haxx.nu\n"
 "\n"
 "FTP\n"
-"       ftp://ftp.sunet.se/pub/www/utilities/curl/\n"
+"     ftp://ftp.sunet.se/pub/www/utilities/curl/\n"
 "\n"
 "SEE ALSO\n"
-"       ftp(1), wget(1), snarf(1)\n"
+"     ftp(1), wget(1), snarf(1)\n"
 "\n"
 "LATEST VERSION\n"
 "\n"
@@ -925,6 +894,41 @@ puts (
 "        curl -d \"name=Rafael%20Sagula&phone=3320780\" \\\n"
 "                http://www.where.com/guest.cgi\n"
 "\n"
+"  How to post a form with curl, lesson #1:\n"
+"\n"
+"  Dig out all the <input> tags in the form that you want to fill in. (There's\n"
+"  a perl program called formfind.pl on the curl site that helps with this).\n"
+"\n"
+"  If there's a \"normal\" post, you use -d to post. -d takes a full \"post\n"
+"  string\", which is in the format\n"
+"\n"
+"        <variable1>=<data1>&<variable2>=<data2>&...\n"
+"\n"
+"  The 'variable' names are the names set with \"name=\" in the <input> tags, and\n"
+"  the data is the contents you want to fill in for the inputs. The data *must*\n"
+"  be properly URL encoded. That means you replace space with + and that you\n"
+"  write weird letters with %XX where XX is the hexadecimal representation of\n"
+"  the letter's ASCII code.\n"
+"\n"
+"  Example:\n"
+"\n"
+"  (page located at http://www.formpost.com/getthis/\n"
+"\n"
+"        <form action=\"post.cgi\" method=\"post\">\n"
+"        <input name=user size=10>\n"
+"        <input name=pass type=password size=10>\n"
+"        <input name=id type=hidden value=\"blablabla\">\n"
+"        <input name=ding value=\"submit\">\n"
+"        </form>\n"
+"\n"
+"  We want to enter user 'foobar' with password '12345'.\n"
+"\n"
+"  To post to this, you enter a curl command line like:\n"
+"\n"
+"        curl -d \"user=foobar&pass=12345&id=blablabla&dig=submit\"  (continues)\n"
+"          http://www.formpost.com/getthis/post.cgi\n"
+"\n"
+"\n"
 "  While -d uses the application/x-www-form-urlencoded mime-type, generally\n"
 "  understood by CGI's and similar, curl also supports the more capable\n"
 "  multipart/form-data type. This latter type supports things like file upload.\n"
index 523a38e..d629de9 100644 (file)
@@ -46,6 +46,8 @@
 #include <ctype.h>
 
 #include <curl/curl.h>
+#include <curl/types.h> /* new for v7 */
+#include <curl/easy.h> /* new for v7 */
 #include <curl/mprintf.h>
 #include "../lib/getdate.h"
 
 #include <unistd.h>
 #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
 /* Ultrix doesn't have strdup(), so make a quick clone: */
 char *strdup(char *str)
@@ -113,7 +134,7 @@ static UrgError win32_init(void)
   if (err != 0) 
     /* Tell the user that we couldn't find a useable */ 
     /* winsock.dll.     */ 
-    return URG_FAILED_INIT; 
+    return CURLE_FAILED_INIT; 
     
   /* Confirm that the Windows Sockets DLL supports 1.1.*/ 
   /* Note that if the DLL supports versions greater */ 
@@ -127,13 +148,13 @@ static UrgError win32_init(void)
 
     /* winsock.dll. */ 
     WSACleanup(); 
-    return URG_FAILED_INIT; 
+    return CURLE_FAILED_INIT; 
   }
-  return URG_OK;
+  return CURLE_OK;
 }
 /* The Windows Sockets DLL is acceptable. Proceed. */ 
 #else
-static UrgError win32_init(void) { return URG_OK; }
+static CURLcode win32_init(void) { return CURLE_OK; }
 #define win32_cleanup()
 #endif
 
@@ -143,7 +164,7 @@ static UrgError win32_init(void) { return URG_OK; }
  * _any_ libcurl usage. If this fails, *NO* libcurl functions may be
  * used, or havoc may be the result.
  */
-UrgError main_init(void)
+CURLcode main_init(void)
 {
   return win32_init();
 }
@@ -297,7 +318,10 @@ static void GetStr(char **string,
 {
   if(*string)
     free(*string);
-  *string = strdup(value);
+  if(value && *value)
+    *string = strdup(value);
+  else
+    *string = NULL;
 }
 
 static char *file2string(FILE *file)
@@ -420,7 +444,7 @@ static int getparameter(char *flag, /* f or -long-flag */
        if(parse) {
          /* this is the second match, we can't continue! */
          helpf("option --%s is ambiguous\n", &flag[1]);
-         return URG_FAILED_INIT;
+         return CURLE_FAILED_INIT;
        }
        parse = aliases[j].letter;
        hit = j;
@@ -428,7 +452,7 @@ static int getparameter(char *flag, /* f or -long-flag */
     }
     if(hit < 0) {
       helpf("unknown option -%s.\n", flag);
-      return URG_FAILED_INIT;
+      return CURLE_FAILED_INIT;
     }    
   }
   else {
@@ -454,18 +478,18 @@ static int getparameter(char *flag, /* f or -long-flag */
       }
       if(hit < 0) {
        helpf("unknown option -%c.\n", letter);
-       return URG_FAILED_INIT;      
+       return CURLE_FAILED_INIT;      
       }
     }
     if(hit < 0) {
       helpf("unknown option -%c.\n", letter);
-      return URG_FAILED_INIT;
+      return CURLE_FAILED_INIT;
     }    
     if(!nextarg && aliases[hit].extraparam) {
       helpf("option -%s/--%s requires an extra argument!\n",
            aliases[hit].letter,
            aliases[hit].lname);
-      return URG_FAILED_INIT;
+      return CURLE_FAILED_INIT;
     }
     else if(nextarg && aliases[hit].extraparam)
       *usedarg = TRUE; /* mark it as used */
@@ -491,7 +515,7 @@ static int getparameter(char *flag, /* f or -long-flag */
         break;
       }
       now=time(NULL);
-      config->condtime=get_date(nextarg, &now);
+      config->condtime=curl_getdate(nextarg, &now);
       if(-1 == config->condtime) {
         /* now let's see if it is a file name to get the time from instead! */
         struct stat statbuf;
@@ -586,7 +610,6 @@ static int getparameter(char *flag, /* f or -long-flag */
       break;
     case 'e':
       GetStr(&config->referer, nextarg);
-      config->conf |= CONF_REFERER;
       break;
     case 'E':
       {
@@ -610,13 +633,12 @@ static int getparameter(char *flag, /* f or -long-flag */
       if(curl_FormParse(nextarg,
                         &config->httppost,
                         &config->last_post))
-       return URG_FAILED_INIT;    
-      config->conf |= CONF_HTTPPOST; /* no toggle, OR! */
+       return CURLE_FAILED_INIT;    
       break;
 
     case 'h': /* h for help */
       help();
-      return URG_FAILED_INIT;
+      return CURLE_FAILED_INIT;
     case 'H':
       head = (struct HttpHeader *)malloc(sizeof(struct HttpHeader));
       if(head) {
@@ -659,7 +681,7 @@ static int getparameter(char *flag, /* f or -long-flag */
       break;
     case 'M': /* M for manual, huge help */
       hugehelp();
-      return URG_FAILED_INIT;
+      return CURLE_FAILED_INIT;
     case 'n':
       /* pick info from .netrc, if this is used for http, curl will
         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.
         NOTE: this is a changed behaviour since the released 4.1!
         */
-      config->conf |= CONF_FTPPORT;
       GetStr(&config->ftpport, nextarg);
       break;
 #if 0
@@ -712,7 +733,6 @@ static int getparameter(char *flag, /* f or -long-flag */
     case 'r':
       /* byte range requested */
       GetStr(&config->range, nextarg);
-      config->conf |= CONF_RANGE;
       break;
     case 's':
       /* don't show progress meter, don't show errors : */
@@ -735,19 +755,17 @@ static int getparameter(char *flag, /* f or -long-flag */
     case 'u':
       /* user:password  */
       GetStr(&config->userpwd, nextarg);
-      config->conf |= CONF_USERPWD;
       break;
     case 'U':
       /* Proxy user:password  */
       GetStr(&config->proxyuserpwd, nextarg);
-      config->conf |= CONF_PROXYUSERPWD;
       break;
     case 'v':
       config->conf ^= CONF_VERBOSE; /* talk a lot */
       break;
     case 'V':
       printf(CURL_ID "%s\n", curl_version());
-      return URG_FAILED_INIT;
+      return CURLE_FAILED_INIT;
     case 'w':
       /* get the output string */
       if('@' == *nextarg) {
@@ -768,14 +786,7 @@ static int getparameter(char *flag, /* f or -long-flag */
       break;
     case 'x':
       /* proxy */
-      if(!*nextarg) {
-       /* disable proxy when no proxy is given */
-       config->conf &= ~CONF_PROXY;
-      }
-      else { 
-       config->conf |= CONF_PROXY;
-       GetStr(&config->proxy, nextarg);
-      }
+      GetStr(&config->proxy, nextarg);
       break;
     case 'X':
       /* HTTP request */
@@ -799,13 +810,13 @@ static int getparameter(char *flag, /* f or -long-flag */
        helpf("Unknown option '%c'\n", letter);
       else
        helpf("Unknown option\n"); /* short help blurb */
-      return URG_FAILED_INIT;
+      return CURLE_FAILED_INIT;
     }
     hit = -1;
 
   } 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 */
 
     if(!home || (strlen(home)>(sizeof(filebuffer)-strlen(CURLRC))))
-      return URG_OK;
+      return CURLE_OK;
 
     sprintf(filebuffer, "%s%s%s", home, DIR_CHAR, CURLRC);
 
@@ -894,7 +905,7 @@ static int parseconfig(char *filename,
     if(file != stdin)
       fclose(file);
   }
-  return URG_OK;
+  return CURLE_OK;
 }
 
 struct OutStruct {
@@ -944,7 +955,8 @@ int main(int argc, char *argv[])
   int infilesize=-1; /* -1 means unknown */
   bool stillflags=TRUE;
 
-  int res=URG_OK;
+  CURL *curl;
+  int res=CURLE_OK;
   int i;
 
   outs.stream = stdout;
@@ -981,7 +993,7 @@ int main(int argc, char *argv[])
 
   if ((argc < 2)  && !config.url) {
     helpf(NULL);
-    return URG_FAILED_INIT;
+    return CURLE_FAILED_INIT;
   }
 
   /* Parse options */
@@ -1014,7 +1026,7 @@ int main(int argc, char *argv[])
     else {
       if(url) {
        helpf("only one URL is supported!\n");
-       return URG_FAILED_INIT;
+       return CURLE_FAILED_INIT;
       }
       url = argv[i];
     }
@@ -1027,7 +1039,7 @@ int main(int argc, char *argv[])
   
   if(!url) {
     helpf("no URL specified!\n");
-    return URG_FAILED_INIT;
+    return CURLE_FAILED_INIT;
   }
 #if 0
   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
      in pattern set */
   res = glob_url(&urls, url, &urlnum);
-  if(res != URG_OK)
+  if(res != CURLE_OK)
     return res;
 
   outfiles = config.outfile;           /* save outfile pattern befor expansion */
@@ -1058,7 +1070,7 @@ int main(int argc, char *argv[])
 
   if(config.outfile && config.infile) {
     helpf("you can't both upload and download!\n");
-    return URG_FAILED_INIT;
+    return CURLE_FAILED_INIT;
   }
  
   if (config.outfile || config.remotefile) {
@@ -1077,7 +1089,7 @@ int main(int argc, char *argv[])
       config.outfile = strrchr(config.outfile, '/');
       if(!config.outfile || !strlen(++config.outfile)) {
         helpf("Remote file name has no length!\n");
-        return URG_WRITE_ERROR;
+        return CURLE_WRITE_ERROR;
       }
     }
     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");
       if (!outs.stream) {
         helpf("Can't open '%s'!\n", config.outfile);
-        return URG_WRITE_ERROR;
+        return CURLE_WRITE_ERROR;
       }
     }
     else {
@@ -1127,7 +1139,7 @@ int main(int argc, char *argv[])
       urlbuffer=(char *)malloc(strlen(url) + strlen(config.infile) + 3);
       if(!urlbuffer) {
         helpf("out of memory\n");
-        return URG_OUT_OF_MEMORY;
+        return CURLE_OUT_OF_MEMORY;
       }
       if(ptr)
         /* there is a trailing slash on the URL */
@@ -1142,7 +1154,7 @@ int main(int argc, char *argv[])
     infd=(FILE *) fopen(config.infile, "rb");
     if (!infd || stat(config.infile, &fileinfo)) {
       helpf("Can't open '%s'!\n", config.infile);
-      return URG_READ_ERROR;
+      return CURLE_READ_ERROR;
     }
     infilesize=fileinfo.st_size;
 
@@ -1189,48 +1201,121 @@ int main(int argc, char *argv[])
 
   main_init();
 
-  res = curl_urlget(URGTAG_FILE, (FILE *)&outs,  /* where to store */
-                    URGTAG_WRITEFUNCTION, my_fwrite, /* what call to write */
-                    URGTAG_INFILE, infd, /* for uploads */
-                    URGTAG_INFILESIZE, infilesize, /* size of uploaded file */
-                    URGTAG_URL, url,     /* what to fetch */
-                    URGTAG_PROXY, config.proxy, /* proxy to use */
-                    URGTAG_FLAGS, config.conf, /* flags */
-                    URGTAG_USERPWD, config.userpwd, /* user + passwd */
-                    URGTAG_PROXYUSERPWD, config.proxyuserpwd, /* Proxy user + passwd */
-                    URGTAG_RANGE, config.range, /* range of document */
-                    URGTAG_ERRORBUFFER, errorbuffer,
-                    URGTAG_TIMEOUT, config.timeout,
-                    URGTAG_POSTFIELDS, config.postfields,
-                    URGTAG_REFERER, config.referer,
-                    URGTAG_USERAGENT, config.useragent,
-                    URGTAG_FTPPORT, config.ftpport,
-                    URGTAG_LOW_SPEED_LIMIT, config.low_speed_limit,
-                    URGTAG_LOW_SPEED_TIME, config.low_speed_time,
-                    URGTAG_RESUME_FROM, config.use_resume?config.resume_from:0,
-                    URGTAG_COOKIE, config.cookie,
-                    URGTAG_HTTPHEADER, config.headers,
-                    URGTAG_HTTPPOST, config.httppost,
-                    URGTAG_SSLCERT, config.cert,
-                    URGTAG_SSLCERTPASSWD, config.cert_passwd,
-                    URGTAG_CRLF, config.crlf,
-                    URGTAG_QUOTE, config.quote,
-                    URGTAG_POSTQUOTE, config.postquote,
-                    URGTAG_WRITEHEADER, config.headerfile?&heads:NULL,
-                    URGTAG_COOKIEFILE, config.cookiefile,
-                    URGTAG_SSLVERSION, config.ssl_version,
-                    URGTAG_TIMECONDITION, config.timecond,
-                    URGTAG_TIMEVALUE, config.condtime,
-                    URGTAG_CUSTOMREQUEST, config.customrequest,
-                    URGTAG_STDERR, config.errors,
-                    URGTAG_PROGRESSMODE, config.progressmode,
-                    URGTAG_WRITEINFO, config.writeout,
-                    URGTAG_DONE); /* always terminate the list of tags */
+#if 0
+  /* This is code left from the pre-v7 time, left here mainly as a reminder
+     and possibly as a warning! ;-) */
+
+  res = curl_urlget(CURLOPT_FILE, (FILE *)&outs,  /* where to store */
+                    CURLOPT_WRITEFUNCTION, my_fwrite, /* what call to write */
+                    CURLOPT_INFILE, infd, /* for uploads */
+                    CURLOPT_INFILESIZE, infilesize, /* size of uploaded file */
+                    CURLOPT_URL, url,     /* what to fetch */
+                    CURLOPT_PROXY, config.proxy, /* proxy to use */
+                    CURLOPT_FLAGS, config.conf, /* flags */
+                    CURLOPT_USERPWD, config.userpwd, /* user + passwd */
+                    CURLOPT_PROXYUSERPWD, config.proxyuserpwd, /* Proxy user + passwd */
+                    CURLOPT_RANGE, config.range, /* range of document */
+                    CURLOPT_ERRORBUFFER, errorbuffer,
+                    CURLOPT_TIMEOUT, config.timeout,
+                    CURLOPT_POSTFIELDS, config.postfields,
+                    CURLOPT_REFERER, config.referer,
+                    CURLOPT_USERAGENT, config.useragent,
+                    CURLOPT_FTPPORT, config.ftpport,
+                    CURLOPT_LOW_SPEED_LIMIT, config.low_speed_limit,
+                    CURLOPT_LOW_SPEED_TIME, config.low_speed_time,
+                    CURLOPT_RESUME_FROM, config.use_resume?config.resume_from:0,
+                    CURLOPT_COOKIE, config.cookie,
+                    CURLOPT_HTTPHEADER, config.headers,
+                    CURLOPT_HTTPPOST, config.httppost,
+                    CURLOPT_SSLCERT, config.cert,
+                    CURLOPT_SSLCERTPASSWD, config.cert_passwd,
+                    CURLOPT_CRLF, config.crlf,
+                    CURLOPT_QUOTE, config.quote,
+                    CURLOPT_POSTQUOTE, config.postquote,
+                    CURLOPT_WRITEHEADER, config.headerfile?&heads:NULL,
+                    CURLOPT_COOKIEFILE, config.cookiefile,
+                    CURLOPT_SSLVERSION, config.ssl_version,
+                    CURLOPT_TIMECONDITION, config.timecond,
+                    CURLOPT_TIMEVALUE, config.condtime,
+                    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
 
-  main_free();
 
-  if((res!=URG_OK) && config.showerror)
-    fprintf(config.errors, "curl: (%d) %s\n", res, errorbuffer);
+    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();
 
   if((config.errors != stderr) &&
      (config.errors != stdout))
index 9f41340..85acfa9 100644 (file)
@@ -69,18 +69,18 @@ int glob_set(char *pattern, int pos) {
     switch (*pattern) {
     case '\0':                         /* URL ended while set was still open */
       printf("error: unmatched brace at pos %d\n", pos);
-      exit (URG_URL_MALFORMAT);
+      exit (CURLE_URL_MALFORMAT);
     case '{':
     case '[':                          /* no nested expressions at this time */
       printf("error: nested braces not supported %d\n", pos);
-      exit (URG_URL_MALFORMAT);
+      exit (CURLE_URL_MALFORMAT);
     case ',':
     case '}':                          /* set element completed */
       *buf = '\0';
       pat->content.Set.elements = realloc(pat->content.Set.elements, (pat->content.Set.size + 1) * sizeof(char*));
       if (!pat->content.Set.elements) {
        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.size;
@@ -95,11 +95,11 @@ int glob_set(char *pattern, int pos) {
       break;
     case ']':                          /* illegal closing bracket */
       printf("error: illegal pattern at pos %d\n", pos);
-      exit (URG_URL_MALFORMAT);
+      exit (CURLE_URL_MALFORMAT);
     case '\\':                         /* escaped character, skip '\' */
       if (*(buf+1) == '\0') {          /* but no escaping of '\0'! */
        printf("error: illegal pattern at pos %d\n", pos);
-       exit (URG_URL_MALFORMAT);
+       exit (CURLE_URL_MALFORMAT);
       }
       ++pattern;
       ++pos;                           /* intentional fallthrough */
@@ -108,7 +108,7 @@ int glob_set(char *pattern, int pos) {
       ++pos;
     }
   }
-  exit (URG_FAILED_INIT);
+  exit (CURLE_FAILED_INIT);
 }
 
 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') {
       /* the pattern is not well-formed */ 
       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;
     /* 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) {
       /* the pattern is not well-formed */ 
       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 */
       c = pattern;  
@@ -161,7 +161,7 @@ int glob_range(char *pattern, int pos) {
       glob_word(c, pos + (c - pattern));
   }
   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) {
@@ -174,14 +174,14 @@ int glob_word(char *pattern, int pos) {
   while (*pattern != '\0' && *pattern != '{' && *pattern != '[') {
     if (*pattern == '}' || *pattern == ']') {
       printf("illegal character at position %d\n", pos);
-      exit (URG_URL_MALFORMAT);
+      exit (CURLE_URL_MALFORMAT);
     }
     if (*pattern == '\\') {            /* escape character, skip '\' */
       ++pattern;
       ++pos;
       if (*pattern == '\0') {          /* but no escaping of '\0'! */
        printf("illegal character at position %d\n", pos);
-       exit (URG_URL_MALFORMAT);
+       exit (CURLE_URL_MALFORMAT);
       }
     }
     *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 */
   }
   printf("internal error\n");
-  exit (URG_FAILED_INIT);
+  exit (CURLE_FAILED_INIT);
 }
 
 int glob_url(URLGlob** glob, char* url, int *urlnum)
 {
   if (strlen(url)>URL_MAX_LENGTH) {
     printf("Illegally sized URL\n");
-    return URG_URL_MALFORMAT;
+    return CURLE_URL_MALFORMAT;
   }
 
   glob_expand = (URLGlob*)malloc(sizeof(URLGlob));
   glob_expand->size = 0;
   *urlnum = glob_word(url, 1);
   *glob = glob_expand;
-  return URG_OK;
+  return CURLE_OK;
 }
 
 char *next_url(URLGlob *glob)
@@ -258,7 +258,7 @@ char *next_url(URLGlob *glob)
        break;
       default:
        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! */
@@ -287,7 +287,7 @@ char *next_url(URLGlob *glob)
        break;
       default:
        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) ||
          *filename == '0') {           /* only '#1' ... '#9' allowed */
        printf("illegal matching expression\n");
-       exit(URG_URL_MALFORMAT);
+       exit(CURLE_URL_MALFORMAT);
       }
       i = *filename - '1';
       if (i + 1 > glob.size / 2) {
        printf("match against nonexisting pattern\n");
-       exit(URG_URL_MALFORMAT);
+       exit(CURLE_URL_MALFORMAT);
       }
       pat = glob.pattern[i];
       switch (pat.type) {
@@ -327,7 +327,7 @@ char *match_url(char *filename, URLGlob glob) {
        break;
       default:
        printf("internal error: invalid pattern type (%d)\n", pat.type);
-       exit (URG_FAILED_INIT);
+       exit (CURLE_FAILED_INIT);
       }
       ++filename;
     }
index 7eb55d7..96c57e3 100644 (file)
@@ -1,3 +1,3 @@
 #define CURL_NAME "curl"
-#define CURL_VERSION "6.5.2"
+#define CURL_VERSION "7.0beta"
 #define CURL_ID CURL_NAME " " CURL_VERSION " (" OS ") "