aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorDaniel Stenberg <daniel@haxx.se>2000-05-22 14:12:12 +0000
committerDaniel Stenberg <daniel@haxx.se>2000-05-22 14:12:12 +0000
commit96dde76b99897352aa3d0877a0b621a9e605733e (patch)
tree4fdab47b4c9769405aa799bf65971c31abf2de6b /lib
parentfb9d1ff00f76836dd66725de869656c5fa53b071 (diff)
moved here from the newlib branch
Diffstat (limited to 'lib')
-rw-r--r--lib/Makefile.am4
-rw-r--r--lib/Makefile.in8
-rw-r--r--lib/cookie.c9
-rw-r--r--lib/dict.c30
-rw-r--r--lib/dict.h3
-rw-r--r--lib/download.c509
-rw-r--r--lib/download.h4
-rw-r--r--lib/escape.c9
-rw-r--r--lib/escape.h2
-rw-r--r--lib/file.c30
-rw-r--r--lib/file.h2
-rw-r--r--lib/formdata.c15
-rw-r--r--lib/ftp.c436
-rw-r--r--lib/ftp.h8
-rw-r--r--lib/getdate.c4
-rw-r--r--lib/getdate.h25
-rw-r--r--lib/getdate.y4
-rw-r--r--lib/getenv.c30
-rw-r--r--lib/http.c246
-rw-r--r--lib/http.h5
-rw-r--r--lib/ldap.c38
-rw-r--r--lib/ldap.h3
-rw-r--r--lib/netrc.c1
-rw-r--r--lib/progress.c231
-rw-r--r--lib/progress.h5
-rw-r--r--lib/sendf.c4
-rw-r--r--lib/setup.h4
-rw-r--r--lib/speedcheck.c6
-rw-r--r--lib/speedcheck.h2
-rw-r--r--lib/ssluse.c6
-rw-r--r--lib/telnet.c36
-rw-r--r--lib/telnet.h3
-rw-r--r--lib/url.c1005
-rw-r--r--lib/url.h44
-rw-r--r--lib/urldata.h235
-rw-r--r--lib/version.c2
-rw-r--r--lib/writeout.c1
-rw-r--r--lib/writeout.h4
38 files changed, 1456 insertions, 1557 deletions
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 3951d88a0..02f25152e 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -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
diff --git a/lib/Makefile.in b/lib/Makefile.in
index 84be952ee..aece159e1 100644
--- a/lib/Makefile.in
+++ b/lib/Makefile.in
@@ -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 $@
diff --git a/lib/cookie.c b/lib/cookie.c
index 00497bc94..8038dafe3 100644
--- a/lib/cookie.c
+++ b/lib/cookie.c
@@ -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 */
diff --git a/lib/dict.c b/lib/dict.c
index cf604ec5b..c9721bd85 100644
--- a/lib/dict.c
+++ b/lib/dict.c
@@ -92,12 +92,17 @@
#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;
}
diff --git a/lib/dict.h b/lib/dict.h
index edff0c434..85e6e3b09 100644
--- a/lib/dict.h
+++ b/lib/dict.h
@@ -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
diff --git a/lib/download.c b/lib/download.c
index 380330b1b..d7ba12b36 100644
--- a/lib/download.c
+++ b/lib/download.c
@@ -78,20 +78,16 @@
#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;
}
-
-
+
diff --git a/lib/download.h b/lib/download.h
index 414085df4..86ba03498 100644
--- a/lib/download.h
+++ b/lib/download.h
@@ -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 */
diff --git a/lib/escape.c b/lib/escape.c
index 274cd2dcd..6ac8847a6 100644
--- a/lib/escape.c
+++ b/lib/escape.c
@@ -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 = ' ';
diff --git a/lib/escape.h b/lib/escape.h
index bca4d8bd9..5c080c209 100644
--- a/lib/escape.h
+++ b/lib/escape.h
@@ -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
diff --git a/lib/file.c b/lib/file.c
index af966016b..532a65fb3 100644
--- a/lib/file.c
+++ b/lib/file.c
@@ -100,23 +100,25 @@
#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;
}
diff --git a/lib/file.h b/lib/file.h
index eeaeef4f4..e6ad0e6ce 100644
--- a/lib/file.h
+++ b/lib/file.h
@@ -40,6 +40,6 @@
*
* ------------------------------------------------------------
****************************************************************************/
-UrgError file(struct UrlData *data, char *path, long *bytecountp);
+CURLcode file(struct connectdata *conn);
#endif
diff --git a/lib/formdata.c b/lib/formdata.c
index eff0212e4..fb6ad0f69 100644
--- a/lib/formdata.c
+++ b/lib/formdata.c
@@ -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;
}
diff --git a/lib/ftp.c b/lib/ftp.c
index 4af86fb48..0844cc78a 100644
--- 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;
}
diff --git a/lib/ftp.h b/lib/ftp.h
index b7d265927..3eb73e15f 100644
--- a/lib/ftp.h
+++ b/lib/ftp.h
@@ -40,11 +40,9 @@
*
* ------------------------------------------------------------
****************************************************************************/
-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);
diff --git a/lib/getdate.c b/lib/getdate.c
index 021ed851d..75efdcfb6 100644
--- a/lib/getdate.c
+++ b/lib/getdate.c
@@ -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
diff --git a/lib/getdate.h b/lib/getdate.h
index 674c474f1..ebb6d2c5a 100644
--- a/lib/getdate.h
+++ b/lib/getdate.h
@@ -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));
diff --git a/lib/getdate.y b/lib/getdate.y
index efcf04255..80f10120c 100644
--- a/lib/getdate.y
+++ b/lib/getdate.y
@@ -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
diff --git a/lib/getenv.c b/lib/getenv.c
index e39d3c194..54b0118b6 100644
--- a/lib/getenv.c
+++ b/lib/getenv.c
@@ -22,18 +22,6 @@
* 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>
@@ -47,24 +35,6 @@
* $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>
diff --git a/lib/http.c b/lib/http.c
index 3f030b4a1..0f41e7c09 100644
--- a/lib/http.c
+++ b/lib/http.c
@@ -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;
}
diff --git a/lib/http.h b/lib/http.h
index be35842cf..6a4d8c835 100644
--- a/lib/http.h
+++ b/lib/http.h
@@ -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
diff --git a/lib/ldap.c b/lib/ldap.c
index dde15873a..e38135cc5 100644
--- a/lib/ldap.c
+++ b/lib/ldap.c
@@ -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;
}
}
}
diff --git a/lib/ldap.h b/lib/ldap.h
index d88880ede..0fcacc0b8 100644
--- a/lib/ldap.h
+++ b/lib/ldap.h
@@ -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 */
diff --git a/lib/netrc.c b/lib/netrc.c
index f0e1382fe..73d94ab77 100644
--- a/lib/netrc.c
+++ b/lib/netrc.c
@@ -56,6 +56,7 @@
#include "setup.h"
#include "getenv.h"
+#include "strequal.h"
/* Debug this single source file with:
'make netrc' then run './netrc'!
diff --git a/lib/progress.c b/lib/progress.c
index 1bb5aec0c..35847fab4 100644
--- a/lib/progress.c
+++ b/lib/progress.c
@@ -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;
}
diff --git a/lib/progress.h b/lib/progress.h
index 8c407f76c..f4e0dcfaa 100644
--- a/lib/progress.h
+++ b/lib/progress.h
@@ -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);
diff --git a/lib/sendf.c b/lib/sendf.c
index 387984d9d..42c344dcf 100644
--- a/lib/sendf.c
+++ b/lib/sendf.c
@@ -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));
diff --git a/lib/setup.h b/lib/setup.h
index 083e89093..c800fa8d3 100644
--- a/lib/setup.h
+++ b/lib/setup.h
@@ -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
diff --git a/lib/speedcheck.c b/lib/speedcheck.c
index 5647b50e2..48772b39c 100644
--- a/lib/speedcheck.c
+++ b/lib/speedcheck.c
@@ -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;
}
diff --git a/lib/speedcheck.h b/lib/speedcheck.h
index 27e7ba2f6..e07bdbcc6 100644
--- a/lib/speedcheck.h
+++ b/lib/speedcheck.h
@@ -44,7 +44,7 @@
#include "timeval.h"
-UrgError speedcheck(struct UrlData *data,
+CURLcode speedcheck(struct UrlData *data,
struct timeval now);
#endif
diff --git a/lib/ssluse.c b/lib/ssluse.c
index 0eae0a93c..6eb9b77bb 100644
--- a/lib/ssluse.c
+++ b/lib/ssluse.c
@@ -38,6 +38,12 @@
* ------------------------------------------------------------
****************************************************************************/
+/*
+ * The original SSL code was written by
+ * Linas Vepstas <linas@linas.org> and Sampo Kellomaki <sampo@iki.fi>
+ */
+
+
#include <string.h>
#include <stdlib.h>
diff --git a/lib/telnet.c b/lib/telnet.c
index 8ca12450d..68571829d 100644
--- a/lib/telnet.c
+++ b/lib/telnet.c
@@ -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;
}
diff --git a/lib/telnet.h b/lib/telnet.h
index 25b7f2d29..f9d55b78b 100644
--- a/lib/telnet.h
+++ b/lib/telnet.h
@@ -40,6 +40,7 @@
*
* ------------------------------------------------------------
****************************************************************************/
-UrgError telnet(struct UrlData *data);
+CURLcode telnet(struct connectdata *conn);
+CURLcode telnet_done(struct connectdata *conn);
#endif
diff --git a/lib/url.c b/lib/url.c
index 75dd89559..5938c5771 100644
--- a/lib/url.c
+++ b/lib/url.c
@@ -38,11 +38,6 @@
* ------------------------------------------------------------
****************************************************************************/
-/*
- * SSL code intially written by
- * Linas Vepstas <linas@linas.org> and Sampo Kellomaki <sampo@iki.fi>
- */
-
/* -- WIN32 approved -- */
#include <stdio.h>
#include <string.h>
@@ -116,6 +111,8 @@
#include "getpass.h"
#include "progress.h"
#include "cookie.h"
+#include "strequal.h"
+#include "writeout.h"
/* And now for the protocols */
#include "ftp.h"
@@ -124,81 +121,28 @@
#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;
}
diff --git a/lib/url.h b/lib/url.h
index e69de29bb..334fa9767 100644
--- 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
diff --git a/lib/urldata.h b/lib/urldata.h
index 0515d6817..debaaa9b5 100644
--- a/lib/urldata.h
+++ b/lib/urldata.h
@@ -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 */
@@ -87,8 +88,12 @@
#endif
#endif
+#include <netinet/in.h>
+
#include "timeval.h"
+
+
/* Download buffer size, keep it fairly big for speed reasons */
#define BUFSIZE (1024*50)
@@ -96,6 +101,88 @@
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 */
diff --git a/lib/version.c b/lib/version.c
index 73be0d7f9..ea54b2a49 100644
--- a/lib/version.c
+++ b/lib/version.c
@@ -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);
diff --git a/lib/writeout.c b/lib/writeout.c
index 415d9e2ce..d86306286 100644
--- a/lib/writeout.c
+++ b/lib/writeout.c
@@ -41,6 +41,7 @@
#include <stdio.h>
#include <string.h>
+#include "strequal.h"
#include "writeout.h"
typedef enum {
diff --git a/lib/writeout.h b/lib/writeout.h
index d730bbfff..faf047709 100644
--- a/lib/writeout.h
+++ b/lib/writeout.h
@@ -1,3 +1,5 @@
+#ifndef __WRITEOUT_H
+#define __WRITEOUT_H
/*****************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
@@ -41,3 +43,5 @@
#include "urldata.h"
void WriteOut(struct UrlData *data);
+
+#endif