Compare commits

...

12 Commits

Author SHA1 Message Date
Daniel Stenberg
cb5f6e18e6 7.9.3-pre3 2002-01-17 14:34:26 +00:00
Daniel Stenberg
b798e7a5ae correct ssl version, fixed ssl writes, solved time-out disconnect without
text, fixed dns cache problem, made it compile with openssl before 0.9.5
again and extended libcurl-the-guide a bit more
2002-01-17 14:25:49 +00:00
Daniel Stenberg
5deab7ad27 more text added 2002-01-17 14:24:25 +00:00
Daniel Stenberg
12cdfd282d added a comment about this example only works with 7.9.3 and newer libs 2002-01-17 13:45:19 +00:00
Daniel Stenberg
eba8035e12 Richard Archer made it compile and build with OpenSSL versions prior to
0.9.5
2002-01-17 10:40:13 +00:00
Daniel Stenberg
edcbf4350b include our own sprintf() prototype to make it return sensible data on
all platforms, I also edited a few data types slightly to prevent my
compiler from warning on comparisions between signed and unsigned values
2002-01-17 08:03:48 +00:00
Sterling Hughes
9289ea471f Get this working, still need to check for leaks and such, but should be
fine..
2002-01-17 07:38:25 +00:00
Sterling Hughes
7d06185aa6 Make the keys for hostcache entries be in the format::
host:port, so accessing curl.haxx.se on port 80 would yield a key value
of ::
curl.haxx.se:80
2002-01-17 06:55:37 +00:00
Daniel Stenberg
01ecb1d7e7 filled-in text in the "Building" chapter and added a "libcurl with C++"
chapter
2002-01-17 00:27:56 +00:00
Daniel Stenberg
e177f14595 SSL writes passed back a silly length... 2002-01-16 23:28:58 +00:00
Daniel Stenberg
5c6eddcadd fixed time-out returned without error text set 2002-01-16 22:26:01 +00:00
Daniel Stenberg
b3b4786990 Kevin Roth's SSLeay() patch, slight edited by me. Works with OpenSSL 0.9.5
now.
2002-01-16 17:45:08 +00:00
10 changed files with 275 additions and 27 deletions

26
CHANGES
View File

@@ -6,6 +6,32 @@
History of Changes
Daniel (17 January 2002)
- docs/libcurl-the-guide is a new tutorial for our libcurl programming
friends.
- Richard Archer brought back the ability to compile and build with OpenSSL
versions before 0.9.5.
[http://sourceforge.net/tracker/?func=detail&atid=100976&aid=504163&group_id=976]
- The DNS cache code didn't take the port number into account, which made it
work rather bad on IPv6-enabled hosts (especially when doing passive
FTP). Sterling fixed it.
Daniel (16 January 2002)
- Georg Horn pointed out a timed out transfer without error text. I found it
and corrected it.
- SSL writes didn't work, they return an uninitialized value that caused
havoc all over. Georg Horn experienced this.
- Kevin Roth patched the curl_version() function to use the proper OpenSSL
function for version information. This way, curl will report the version of
the SSL library actually running right now, not the one that had its headers
installed when libcurl was built. Mainly intersting when running with shared
OpenSSL libraries.
Version 7.9.3-pre2
Daniel (16 January 2002)
- Mofied the main transfer loop and related stuff to deal with non-blocking

View File

@@ -28,6 +28,9 @@
4.2. if the format of the key file is DER, set pKeyType to "DER"
!! verify of the server certificate is not implemented here !!
**** This example only works with libcurl 7.9.3 and later! ****
*/
int main(int argc, char **argv)

View File

@@ -10,7 +10,7 @@ PROGRAMMING WITH LIBCURL
About this Document
This document will attempt to describe the general principle and some basic
approach to consider when programming with libcurl. The text will focus
approaches to consider when programming with libcurl. The text will focus
mainly on the C/C++ interface but might apply fairly well on other interfaces
as well as they usually follow the C one pretty closely.
@@ -23,12 +23,57 @@ About this Document
Building
There are many different ways to build C programs. This chapter will assume
a unix-style build process. If you use a different build system, you can
still read this to get general information that may apply to your
environment as well.
Compiling the Program
Your compiler needs to know where the libcurl headers are
located. Therefore you must set your compiler's include path to point to
the directory where you installed them. The 'curl-config'[3] tool can be
used to get this information:
$ curl-config --cflags
Linking the Program with libcurl
When having compiled the program, you need to link your object files to
create a single executable. For that to succeed, you need to link with
libcurl and possibly also with other libraries that libcurl itself depends
on. Like OpenSSL librararies, but even some standard OS libraries may be
needed on the command line. To figure out which flags to use, once again
the 'curl-config' tool comes to the rescue:
$ curl-config --libs
SSL or Not
libcurl can be built and customized in many ways. One of the things that
varies from different libraries and builds is the support for SSL-based
transfers, like HTTPS and FTPS. If OpenSSL was detected properly at
build-time, libcurl will be built with SSL support. To figure out if an
installed libcurl has been built with SSL support enabled, use
'curl-config' like this:
$ curl-config --feature
And if SSL is supported, the keyword 'SSL' will be written to stdout,
possibly together with a few other features that can be on and off on
different libcurls.
Portable Code in a Portable World
The people behind libcurl have put a considerable effort to make libcurl work
on a large amount of different operating systems and environments.
You program libcurl the same way on all platforms that libcurl runs on. There
are only very few minor considerations that differs. If you just make sure to
write your code portable enough, you may very well create yourself a very
portable program. libcurl shouldn't stop you from that.
Global Preparation
@@ -118,6 +163,19 @@ Handle the easy libcurl
and the function that gets invoked by libcurl. libcurl itself won't touch the
data you pass with CURLOPT_FILE.
libcurl offers its own default internal callback that'll take care of the
data if you don't set the callback with CURLOPT_WRITEFUNCTION. It will then
simply output the received data to stdout. You can have the default callback
write the data to a different file handle by passing a 'FILE *' to a file
opened for writing with the CURLOPT_FILE option.
Now, we need to take a step back and have a deep breath. Here's one of those
rare platform-dependent nitpicks. Did you spot it? On some platforms[2],
libcurl won't be able to operate on files opened by the program. Thus, if you
use the default callback and pass in a an open file with CURLOPT_FILE, it
will crash. You should therefore avoid this to make your program run fine
virtually everywhere.
There are of course many more options you can set, and we'll get back to a
few of them later. Let's instead continue to the actual transfer:
@@ -141,6 +199,7 @@ Handle the easy libcurl
you intend to make another transfer. libcurl will then attempt to re-use the
previous
When It Doesn't Work
There will always be times when the transfer fails for some reason. You might
@@ -156,6 +215,14 @@ When It Doesn't Work
wht the server behaves the way it does. Include headers in the normal body
output with CURLOPT_HEADER set TRUE.
Of course there are bugs left. We need to get to know about them to be able
to fix them, so we're quite dependent on your bug reports! When you do report
suspected bugs in libcurl, please include as much details you possibly can: a
protocol dump that CURLOPT_VERBOSE produces, library version, as much as
possible of your code that uses libcurl, operating system name and version,
compiler name and version etc.
Upload Data to a Remote Site
libcurl tries to keep a protocol independent approach to most transfers, thus
@@ -200,6 +267,50 @@ Upload Data to a Remote Site
the buffer. Returning 0 will signal the end of the upload.
Passwords
Many protocols use or even require that user name and password are provided
to be able to download or upload the data of your choice. libcurl offers
several ways to specify them.
[ URL, options, callback ]
Showing Progress
libcurl with C++
There's basicly only one thing to keep in mind when using C++ instead of C
when interfacing libcurl:
"The Callbacks Must Be Plain C"
So if you want a write callback set in libcurl, you should put it within
'extern'. Similar to this:
extern "C" {
size_t write_data(void *ptr, size_t size, size_t nmemb,
void *ourpointer)
{
/* do what you want with the data */
}
}
This will of course effectively turn the callback code into C. There won't be
any "this" pointer available etc.
Security Considerations
Certificates and Other SSL Tricks
Future
-----
Footnotes:
@@ -207,3 +318,11 @@ Footnotes:
but libcurl does not support the chunked transfers on uploading that is
necessary for this feature to work. We'd gratefully appreciate patches
that bring this functionality...
[2] = This happens on Windows machines when libcurl is built and used as a
DLL. However, you can still do this on Windows if you link with a static
library.
[3] = The curl-config tool is generated at build-time (on unix-like systems)
and should be installed with the 'make install' or similar instruction
that installs the library, header files, man pages etc.

View File

@@ -613,7 +613,7 @@ CURLcode curl_global_init(long flags);
void curl_global_cleanup(void);
/* This is the version number */
#define LIBCURL_VERSION "7.9.3-pre2"
#define LIBCURL_VERSION "7.9.3-pre3"
#define LIBCURL_VERSION_NUM 0x070903
/* linked-list structure for the CURLOPT_QUOTE option (and other) */

View File

@@ -369,10 +369,12 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */
/* subtract the passed time */
timeout_ms -= (long)has_passed;
if(timeout_ms < 0)
if(timeout_ms < 0) {
/* a precaution, no need to continue if time already is up */
failf(data, "Connection time-out");
return CURLE_OPERATION_TIMEOUTED;
}
}
#ifdef ENABLE_IPV6
/*

View File

@@ -60,6 +60,9 @@
#include "hostip.h"
#include "hash.h"
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
#if defined(HAVE_INET_NTOA_R) && !defined(HAVE_INET_NTOA_R_DECL)
#include "inet_ntoa_r.h"
#endif
@@ -98,13 +101,71 @@ struct curl_dns_cache_entry {
time_t timestamp;
};
/* count the number of characters that an integer takes up */
static int _num_chars(int i)
{
int chars = 0;
/* While the number divided by 10 is greater than one,
* re-divide the number by 10, and increment the number of
* characters by 1.
*
* this relies on the fact that for every multiple of 10,
* a new digit is added onto every number
*/
do {
chars++;
i = (int) i / 10;
} while (i > 1);
return chars;
}
/* Create a hostcache id */
static char *
_create_hostcache_id(char *server, int port, ssize_t *entry_len)
{
char *id = NULL;
/* Get the length of the new entry id */
*entry_len = *entry_len + /* Hostname length */
1 + /* The ':' seperator */
_num_chars(port); /* The number of characters the port will take up */
/* Allocate the new entry id */
id = malloc(*entry_len + 1);
if (!id) {
return NULL;
}
/* Create the new entry */
/* If sprintf() doesn't return the entry length, that signals failure */
if (sprintf(id, "%s:%d", server, port) != *entry_len) {
/* Free the allocated id, set length to zero and return NULL */
*entry_len = 0;
free(id);
return NULL;
}
return id;
}
/* Macro to save redundant free'ing of entry_id */
#define _hostcache_return(__v) \
{ \
free(entry_id); \
return (__v); \
}
Curl_addrinfo *Curl_resolv(struct SessionHandle *data,
char *hostname,
int port,
char **bufp)
{
char *entry_id = NULL;
struct curl_dns_cache_entry *p = NULL;
size_t hostname_len;
ssize_t entry_len;
time_t now;
/* If the host cache timeout is 0, we don't do DNS cach'ing
@@ -113,40 +174,47 @@ Curl_addrinfo *Curl_resolv(struct SessionHandle *data,
return Curl_getaddrinfo(data, hostname, port, bufp);
}
hostname_len = strlen(hostname)+1;
/* Create an entry id, based upon the hostname and port */
entry_len = strlen(hostname);
entry_id = _create_hostcache_id(hostname, port, &entry_len);
/* If we can't create the entry id, don't cache, just fall-through
to the plain Curl_getaddrinfo() */
if (!entry_id) {
return Curl_getaddrinfo(data, hostname, port, bufp);
}
time(&now);
/* See if its already in our dns cache */
if (curl_hash_find(data->hostcache, hostname, hostname_len, (void **) &p)) {
if (entry_id && curl_hash_find(data->hostcache, entry_id, entry_len+1, (void **) &p)) {
/* Do we need to check for a cache timeout? */
if (data->set.dns_cache_timeout != -1) {
/* Return if the entry has not timed out */
if ((now - p->timestamp) < data->set.dns_cache_timeout) {
return p->addr;
_hostcache_return(p->addr);
}
}
else {
return p->addr;
_hostcache_return(p->addr);
}
}
/* Create a new cache entry */
p = (struct curl_dns_cache_entry *)
malloc(sizeof(struct curl_dns_cache_entry));
if (!p)
return NULL;
p = (struct curl_dns_cache_entry *) malloc(sizeof(struct curl_dns_cache_entry));
if (!p) {
_hostcache_return(NULL);
}
p->addr = Curl_getaddrinfo(data, hostname, port, bufp);
if (!p->addr) {
free(p);
return NULL;
_hostcache_return(NULL);
}
p->timestamp = now;
/* Save it in our host cache */
curl_hash_update(data->hostcache, hostname, hostname_len, (const void *) p);
curl_hash_update(data->hostcache, entry_id, entry_len+1, (const void *) p);
return p->addr;
_hostcache_return(p->addr);
}
/*

View File

@@ -212,6 +212,7 @@ CURLcode Curl_write(struct connectdata *conn, int sockfd,
failf(conn->data, "SSL_write() return error %d\n", err);
return CURLE_WRITE_ERROR;
}
bytes_written = rc;
}
else {
#endif

View File

@@ -43,6 +43,12 @@
#include "memdebug.h"
#endif
#if OPENSSL_VERSION_NUMBER >= 0x0090581fL
#define HAVE_SSL_GET1_SESSION 1
#else
#undef HAVE_SSL_GET1_SESSION
#endif
#if OPENSSL_VERSION_NUMBER >= 0x00904100L
#define HAVE_USERDATA_IN_PWD_CALLBACK 1
#else
@@ -558,11 +564,26 @@ static int Store_SSL_Session(struct connectdata *conn)
int oldest_age=data->state.session[0].age; /* zero if unused */
/* ask OpenSSL, say please */
#ifdef HAVE_SSL_GET1_SESSION
ssl_sessionid = SSL_get1_session(conn->ssl.handle);
/* SSL_get1_session() will increment the reference
count and the session will stay in memory until explicitly freed with
SSL_SESSION_free(3), regardless of its state. */
SSL_SESSION_free(3), regardless of its state.
This function was introduced in openssl 0.9.5a. */
#else
ssl_sessionid = SSL_get_session(conn->ssl.handle);
/* if SSL_get1_session() is unavailable, use SSL_get_session().
This is an inferior option because the session can be flushed
at any time by openssl. It is included only so curl compiles
under versions of openssl < 0.9.5a.
WARNING: How curl behaves if it's session is flushed is
untested.
*/
#endif
/* Now we should add the session ID and the host name to the cache, (remove
the oldest if necessary) */

View File

@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 2000, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 2002, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* In order to be useful for every potential user, curl and libcurl are
* dual-licensed under the MPL and the MIT/X-derivate licenses.
@@ -38,20 +38,28 @@ char *curl_version(void)
#ifdef USE_SSLEAY
#if (SSLEAY_VERSION_NUMBER >= 0x906000)
#if (SSLEAY_VERSION_NUMBER >= 0x905000)
{
char sub[2];
unsigned long ssleay_value;
sub[1]='\0';
if(SSLEAY_VERSION_NUMBER&0xff0) {
sub[0]=((SSLEAY_VERSION_NUMBER>>4)&0xff) + 'a' -1;
ssleay_value=SSLeay();
if(ssleay_value < 0x906000) {
ssleay_value=SSLEAY_VERSION_NUMBER;
sub[0]='\0';
}
else {
if(ssleay_value&0xff0) {
sub[0]=((ssleay_value>>4)&0xff) + 'a' -1;
}
else
sub[0]='\0';
}
sprintf(ptr, " (OpenSSL %lx.%lx.%lx%s)",
(SSLEAY_VERSION_NUMBER>>28)&0xf,
(SSLEAY_VERSION_NUMBER>>20)&0xff,
(SSLEAY_VERSION_NUMBER>>12)&0xff,
(ssleay_value>>28)&0xf,
(ssleay_value>>20)&0xff,
(ssleay_value>>12)&0xff,
sub);
}

View File

@@ -1,3 +1,3 @@
#define CURL_NAME "curl"
#define CURL_VERSION "7.9.3-pre2"
#define CURL_VERSION "7.9.3-pre3"
#define CURL_ID CURL_NAME " " CURL_VERSION " (" OS ") "