Compare commits
39 Commits
curl-7_9_3
...
curl-7_9_3
Author | SHA1 | Date | |
---|---|---|---|
![]() |
7e16ec8724 | ||
![]() |
8c459156f8 | ||
![]() |
2db894807b | ||
![]() |
95ceeb6e0b | ||
![]() |
c9c00d2a23 | ||
![]() |
1afe49864d | ||
![]() |
6924bee3a0 | ||
![]() |
39d4552dab | ||
![]() |
a23c63738f | ||
![]() |
e911945c55 | ||
![]() |
6d58d13710 | ||
![]() |
0b177cb165 | ||
![]() |
3e31b619de | ||
![]() |
f925979b2f | ||
![]() |
49f7fa82b9 | ||
![]() |
e4cd4cf3f3 | ||
![]() |
e74b20926d | ||
![]() |
a312127c91 | ||
![]() |
1dc5bf4f73 | ||
![]() |
01cfe670c5 | ||
![]() |
fd307bfe29 | ||
![]() |
a00de093a7 | ||
![]() |
7bfe853af3 | ||
![]() |
cbaecca8e9 | ||
![]() |
8edfb370a8 | ||
![]() |
4c08c8f7db | ||
![]() |
c174680a03 | ||
![]() |
cb5f6e18e6 | ||
![]() |
b798e7a5ae | ||
![]() |
5deab7ad27 | ||
![]() |
12cdfd282d | ||
![]() |
eba8035e12 | ||
![]() |
edcbf4350b | ||
![]() |
9289ea471f | ||
![]() |
7d06185aa6 | ||
![]() |
01ecb1d7e7 | ||
![]() |
e177f14595 | ||
![]() |
5c6eddcadd | ||
![]() |
b3b4786990 |
57
CHANGES
57
CHANGES
@@ -6,6 +6,63 @@
|
||||
|
||||
History of Changes
|
||||
|
||||
Version 7.9.3
|
||||
|
||||
Daniel (23 January 2002)
|
||||
- Andr<64>s Garc<72>a found a persistancy problem when doing HTTP HEAD, that made
|
||||
curl "hang" until the connection was closed by the server. This problem has
|
||||
been introduced in 7.9.3 due to internal rewrites, this was not present in
|
||||
7.9.2.
|
||||
|
||||
Version 7.9.3-pre4
|
||||
|
||||
Daniel (19 January 2002)
|
||||
- Antonio filed bug report #505514 and provided a fix! When doing multipart
|
||||
formposts, libcurl would include an error text in the actual post if a
|
||||
specified file wasn't found. This is not libcurl's job. Instead we add an
|
||||
empty part.
|
||||
|
||||
Daniel (18 January 2002)
|
||||
- Played around with stricter compiler warnings for gcc (when ./configure
|
||||
--enable-debug is used) and changed some minor things to stop the warnings.
|
||||
|
||||
- Commented out the 'long long' and 'long double' checks in configure.in, as
|
||||
we don't currently use them anyway and the code in lib/mprintf.c that use
|
||||
them causes warnings.
|
||||
|
||||
- Saul Good and jonatan pointed out Mac OS X build problems with pre3 and how
|
||||
to correct them. Two compiler warnings were removed as well.
|
||||
|
||||
- Andr<64>s Garc<72>a fixed two minor mingw32 building problems.
|
||||
|
||||
Version 7.9.3-pre3
|
||||
|
||||
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 could make a transfer time-out 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
|
||||
|
@@ -69,7 +69,7 @@ AC_ARG_ENABLE(debug,
|
||||
*) AC_MSG_RESULT(yes)
|
||||
|
||||
CPPFLAGS="$CPPFLAGS -DMALLOCDEBUG"
|
||||
CFLAGS="-W -Wall -Wwrite-strings -pedantic -g"
|
||||
CFLAGS="-W -Wall -Wwrite-strings -pedantic -Wundef -Wpointer-arith -Wcast-align -Wnested-externs -g"
|
||||
;;
|
||||
esac ],
|
||||
AC_MSG_RESULT(no)
|
||||
@@ -524,9 +524,9 @@ AC_HEADER_TIME
|
||||
# mprintf() checks:
|
||||
|
||||
# check for 'long double'
|
||||
AC_CHECK_SIZEOF(long double, 8)
|
||||
# AC_CHECK_SIZEOF(long double, 8)
|
||||
# check for 'long long'
|
||||
AC_CHECK_SIZEOF(long long, 4)
|
||||
# AC_CHECK_SIZEOF(long long, 4)
|
||||
|
||||
# check for ssize_t
|
||||
AC_CHECK_TYPE(ssize_t, int)
|
||||
|
7
docs/FAQ
7
docs/FAQ
@@ -1,4 +1,4 @@
|
||||
Updated: December 21, 2001 (http://curl.haxx.se/docs/faq.shtml)
|
||||
Updated: January 22, 2002 (http://curl.haxx.se/docs/faq.shtml)
|
||||
_ _ ____ _
|
||||
___| | | | _ \| |
|
||||
/ __| | | | |_) | |
|
||||
@@ -163,9 +163,8 @@ FAQ
|
||||
|
||||
1.6 What do you get for making cURL?
|
||||
|
||||
Project cURL is entirely free and open, without any commercial interests or
|
||||
money involved. No person gets paid in any way for developing curl. We all
|
||||
do this voluntarily on our spare time.
|
||||
Project cURL is entirely free and open. No person gets paid in any way for
|
||||
developing curl. We all do this voluntarily on our spare time.
|
||||
|
||||
We get some help from companies. Contactor Data hosts the curl web site and
|
||||
the main mailing list, Haxx owns the curl web site's domain and
|
||||
|
88
docs/TODO
88
docs/TODO
@@ -19,10 +19,7 @@ TODO
|
||||
|
||||
* The new 'multi' interface is being designed. Work out the details, start
|
||||
implementing and write test applications!
|
||||
[http://curl.haxx.se/dev/multi.h]
|
||||
|
||||
* Add a name resolve cache to libcurl to make repeated fetches to the same
|
||||
host name (when persitancy isn't available) faster.
|
||||
[http://curl.haxx.se/lxr/source/lib/multi.h]
|
||||
|
||||
* Introduce another callback interface for upload/download that makes one
|
||||
less copy of data and thus a faster operation.
|
||||
@@ -33,13 +30,36 @@ TODO
|
||||
telnet, ldap, dict or file.
|
||||
|
||||
* Add asynchronous name resolving. http://curl.haxx.se/dev/async-resolver.txt
|
||||
This should be made to work on most of the supported platforms, or
|
||||
otherwise it isn't really interesting.
|
||||
|
||||
* Strip any trailing CR from the error message when Curl_failf() is used.
|
||||
* Data sharing. Tell which easy handles within a multi handle that should
|
||||
share cookies, connection cache, dns cache, ssl session cache.
|
||||
|
||||
* Mutexes. By adding mutex callback support, the 'data sharing' mentioned
|
||||
above can be made between several easy handles running in different threads
|
||||
too. The actual mutex implementations will be left for the application to
|
||||
implement, libcurl will merely call 'getmutex' and 'leavemutex' callbacks.
|
||||
|
||||
* No-faster-then-this transfers. Many people have limited bandwidth and they
|
||||
want the ability to make sure their transfers never use more bandwith than
|
||||
they think is good.
|
||||
|
||||
* Set the SO_KEEPALIVE socket option to make libcurl notice and disconnect
|
||||
very long time idle connections.
|
||||
|
||||
* Make sure we don't ever loop because of non-blocking sockets return
|
||||
EWOULDBLOCK or similar. This concerns the HTTP request sending, the FTP
|
||||
command sending etc.
|
||||
|
||||
* Go through the code and verify that libcurl deals with big files >2GB and
|
||||
>4GB all over. Bug reports indicate that it doesn't currently work
|
||||
properly.
|
||||
|
||||
DOCUMENTATION
|
||||
|
||||
* Document all CURLcode error codes, why they happen and what most likely
|
||||
will make them not happen again.
|
||||
will make them not happen again. In a libcurl point of view.
|
||||
|
||||
FTP
|
||||
|
||||
@@ -54,11 +74,7 @@ TODO
|
||||
already working http dito works. It of course requires that 'MDTM' works,
|
||||
and it isn't a standard FTP command.
|
||||
|
||||
* Suggested on the mailing list: CURLOPT_FTP_MKDIR...!
|
||||
|
||||
* Always use the FTP SIZE command before downloading, as that makes it more
|
||||
likely that we know the size when downloading. Some sites support SIZE but
|
||||
don't show the size in the RETR response!
|
||||
* Add FTPS support with SSL for the data connection too.
|
||||
|
||||
HTTP
|
||||
|
||||
@@ -83,34 +99,53 @@ TODO
|
||||
http://www.innovation.ch/java/ntlm.html that contains detailed reverse-
|
||||
engineered info.
|
||||
|
||||
* RFC2617 compliance, "Digest Access Authentication"
|
||||
A valid test page seem to exist at:
|
||||
http://hopf.math.nwu.edu/testpage/digest/
|
||||
And some friendly person's server source code is available at
|
||||
http://hopf.math.nwu.edu/digestauth/index.html
|
||||
Then there's the Apache mod_digest source code too of course. It seems as
|
||||
if Netscape doesn't support this, and not many servers do. Although this is
|
||||
a lot better authentication method than the more common "Basic". Basic
|
||||
sends the password in cleartext over the network, this "Digest" method uses
|
||||
a challange-response protocol which increases security quite a lot.
|
||||
* RFC2617 compliance, "Digest Access Authentication" A valid test page seem
|
||||
to exist at: http://hopf.math.nwu.edu/testpage/digest/ And some friendly
|
||||
person's server source code is available at
|
||||
http://hopf.math.nwu.edu/digestauth/index.html Then there's the Apache
|
||||
mod_digest source code too of course. It seems as if Netscape doesn't
|
||||
support this, and not many servers do. Although this is a lot better
|
||||
authentication method than the more common "Basic". Basic sends the
|
||||
password in cleartext over the network, this "Digest" method uses a
|
||||
challange-response protocol which increases security quite a lot.
|
||||
|
||||
* Pipelining. Sending multiple requests before the previous one(s) are done.
|
||||
This could possibly be implemented using the multi interface to queue
|
||||
requests and the response data.
|
||||
|
||||
TELNET
|
||||
|
||||
* Make TELNET work on windows98!
|
||||
|
||||
* Reading input (to send to the remote server) on stdin is a crappy solution
|
||||
for library purposes. We need to invent a good way for the application to
|
||||
be able to provide the data to send.
|
||||
|
||||
* Move the telnet support's network select() loop go away and merge the code
|
||||
into the main transfer loop. Until this is done, the multi interface won't
|
||||
work for telnet.
|
||||
|
||||
SSL
|
||||
|
||||
* Add an interface to libcurl that enables "session IDs" to get
|
||||
exported/imported. Cris Bailiff said: "OpenSSL has functions which can
|
||||
serialise the current SSL state to a buffer of your choice, and
|
||||
recover/reset the state from such a buffer at a later date - this is used
|
||||
by mod_ssl for apache to implement and SSL session ID cache"
|
||||
by mod_ssl for apache to implement and SSL session ID cache". This whole
|
||||
idea might become moot if we enable the 'data sharing' as mentioned in the
|
||||
LIBCURL label above.
|
||||
|
||||
* Make curl's SSL layer option capable of using other free SSL libraries.
|
||||
Such as the Mozilla Security Services
|
||||
(http://www.mozilla.org/projects/security/pki/nss/) and GNUTLS
|
||||
(http://gnutls.hellug.gr/)
|
||||
|
||||
LDAP
|
||||
|
||||
* Look over the implementation. The looping will have to "go away" from the
|
||||
lib/ldap.c source file and get moved to the main network code so that the
|
||||
multi interface and friends will work for LDAP as well.
|
||||
|
||||
CLIENT
|
||||
|
||||
* "curl ftp://site.com/*.txt"
|
||||
@@ -119,11 +154,10 @@ TODO
|
||||
the same syntax to specify several files to get uploaded (using the same
|
||||
persistant connection), using -T.
|
||||
|
||||
* Say you have a list of FTP addresses to download in a file named
|
||||
ftp-list.txt: "cat ftp-list.txt | xargs curl -O -O -O [...]". curl _needs_
|
||||
an "-Oalways" flag -- all addresses on the command line use the base
|
||||
filename to store locally. Else a script must precount the # of URLs,
|
||||
construct the proper number of "-O"s...
|
||||
* When the multi interface has been implemented and proved to work, the
|
||||
client could be told to use maximum N simultaneous transfers and then just
|
||||
make sure that happens. It should of course not make more than one
|
||||
connection to the same remote host.
|
||||
|
||||
TEST SUITE
|
||||
|
||||
|
@@ -2,7 +2,7 @@
|
||||
.\" nroff -man curl-config.1
|
||||
.\" Written by Daniel Stenberg
|
||||
.\"
|
||||
.TH curl-config 1 "16 August 2001" "Curl 7.8.1" "curl-config manual"
|
||||
.TH curl-config 1 "21 January 2002" "Curl 7.9.3" "curl-config manual"
|
||||
.SH NAME
|
||||
curl-config \- Get information about a libcurl installation
|
||||
.SH SYNOPSIS
|
||||
@@ -11,6 +11,8 @@ curl-config \- Get information about a libcurl installation
|
||||
.B curl-config
|
||||
displays information about a previous curl and libcurl installation.
|
||||
.SH OPTIONS
|
||||
.IP "--cc"
|
||||
Displays the compiler used to build libcurl.
|
||||
.IP "--cflags"
|
||||
Set of compiler options (CFLAGS) to use when compiling files that use
|
||||
libcurl. Currently that is only thw include path to the curl include files.
|
||||
@@ -38,18 +40,23 @@ major, minor, patch. So that libcurl 7.7.4 would appear as 070704 and libcurl
|
||||
.SH "EXAMPLES"
|
||||
What linker options do I need when I link with libcurl?
|
||||
|
||||
curl-config --libs
|
||||
$ curl-config --libs
|
||||
|
||||
What compiler options do I need when I compile using libcurl functions?
|
||||
|
||||
curl-config --cflags
|
||||
$ curl-config --cflags
|
||||
|
||||
How do I know if libcurl was built with SSL support?
|
||||
|
||||
curl-config --feature | grep SSL
|
||||
$ curl-config --feature | grep SSL
|
||||
|
||||
What's the installed libcurl version?
|
||||
|
||||
curl-config --version
|
||||
$ curl-config --version
|
||||
|
||||
How do I build a single file with a one-line command?
|
||||
|
||||
$ `curl-config --cc --cflags --libs` -o example example.c
|
||||
|
||||
.SH "SEE ALSO"
|
||||
.BR curl (1)
|
||||
|
@@ -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)
|
||||
|
@@ -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.
|
||||
|
||||
@@ -20,15 +20,62 @@ About this Document
|
||||
source code that you write that is using libcurl for transfers. The program
|
||||
is outside libcurl and libcurl is outside of the program.
|
||||
|
||||
To get the more details on all options and functions described herein, please
|
||||
refer to their respective man pages.
|
||||
|
||||
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
|
||||
|
||||
@@ -69,7 +116,7 @@ Global Preparation
|
||||
Repeated calls to curl_global_init() and curl_global_cleanup() should be
|
||||
avoided. They should be called once each.
|
||||
|
||||
Handle the easy libcurl
|
||||
Handle the Easy libcurl
|
||||
|
||||
libcurl version 7 is oriented around the so called easy interface. All
|
||||
operations in the easy interface are prefixed with 'curl_easy'.
|
||||
@@ -118,6 +165,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 +201,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 +217,19 @@ 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.
|
||||
|
||||
Getting some in-depth knowledge about the protocols involved is never wrong,
|
||||
and if you're trying to funny things, you might very well understand libcurl
|
||||
and how to use it better if you study the appropriate RFC documents at least
|
||||
briefly.
|
||||
|
||||
|
||||
Upload Data to a Remote Site
|
||||
|
||||
libcurl tries to keep a protocol independent approach to most transfers, thus
|
||||
@@ -171,12 +245,13 @@ Upload Data to a Remote Site
|
||||
the custom pointer libcurl will pass to our read callback. The read callback
|
||||
should have a prototype similar to:
|
||||
|
||||
size_t function(char *buffer, size_t size, size_t nitems, void *userp);
|
||||
size_t function(char *bufptr, size_t size, size_t nitems, void *userp);
|
||||
|
||||
Where buffer is the pointer to a buffer we fill in with data to upload and
|
||||
size*nitems is the size of the buffer. The 'userp' pointer is the custom
|
||||
pointer we set to point to a struct of ours to pass private data between the
|
||||
application and the callback.
|
||||
Where bufptr is the pointer to a buffer we fill in with data to upload and
|
||||
size*nitems is the size of the buffer and therefore also the maximum amount
|
||||
of data we can return to libcurl in this call. The 'userp' pointer is the
|
||||
custom pointer we set to point to a struct of ours to pass private data
|
||||
between the application and the callback.
|
||||
|
||||
curl_easy_setopt(easyhandle, CURLOPT_READFUNCTION, read_function);
|
||||
|
||||
@@ -192,7 +267,7 @@ Upload Data to a Remote Site
|
||||
|
||||
curl_easy_setopt(easyhandle, CURLOPT_INFILESIZE, file_size);
|
||||
|
||||
So, then you call curl_easy_perform() this time, it'll perform all necessary
|
||||
When you call curl_easy_perform() this time, it'll perform all the necessary
|
||||
operations and when it has invoked the upload it'll call your supplied
|
||||
callback to get the data to upload. The program should return as much data as
|
||||
possible in every invoke, as that is likely to make the upload perform as
|
||||
@@ -200,6 +275,243 @@ 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.
|
||||
|
||||
Most protocols support that you specify the name and password in the URL
|
||||
itself. libcurl will detect this and use them accordingly. This is written
|
||||
like this:
|
||||
|
||||
protocol://user:password@example.com/path/
|
||||
|
||||
If you need any odd letters in your user name or password, you should enter
|
||||
them URL encoded, as %XX where XX is a two-digit hexadecimal number.
|
||||
|
||||
libcurl also provides options to set various passwords. The user name and
|
||||
password as shown embedded in the URL can instead get set with the
|
||||
CURLOPT_USERPWD option. The argument passed to libcurl should be a char * to
|
||||
a string in the format "user:password:". In a manner like this:
|
||||
|
||||
curl_easy_setopt(easyhandle, CURLOPT_USERPWD, "myname:thesecret");
|
||||
|
||||
Another case where name and password might be needed at times, is for those
|
||||
users who need to athenticate themselves to a proxy they use. libcurl offers
|
||||
another option for this, the CURLOPT_PROXYUSERPWD. It is used quite similar
|
||||
to the CURLOPT_USERPWD option like this:
|
||||
|
||||
curl_easy_setopt(easyhandle, CURLOPT_PROXYUSERPWD, "myname:thesecret");
|
||||
|
||||
There's a long time unix "standard" way of storing ftp user names and
|
||||
passwords, namely in the $HOME/.netrc file. The file should be made private
|
||||
so that only the user may read it (see also the "Security Considerations"
|
||||
chapter), as it might contain the password in plain text. libcurl has the
|
||||
ability to use this file to figure out what set of user name and password to
|
||||
use for a particular host. As an extension to the normal functionality,
|
||||
libcurl also supports this file for non-FTP protocols such as HTTP. To make
|
||||
curl use this file, use the CURLOPT_NETRC option:
|
||||
|
||||
curl_easy_setopt(easyhandle, CURLOPT_NETRC, TRUE);
|
||||
|
||||
And a very basic example of how such a .netrc file may look like:
|
||||
|
||||
machine myhost.mydomain.com
|
||||
login userlogin
|
||||
password secretword
|
||||
|
||||
All these examples have been cases where the password has been optional, or
|
||||
at least you could leave it out and have libcurl attempt to do its job
|
||||
without it. There are times when the password isn't optional, like when
|
||||
you're using an SSL private key for secure transfers.
|
||||
|
||||
You can in this situation either pass a password to libcurl to use to unlock
|
||||
the private key, or you can let libcurl prompt the user for it. If you prefer
|
||||
to ask the user, then you can provide your own callback function that will be
|
||||
called when libcurl wants the password. That way, you can control how the
|
||||
question will appear to the user.
|
||||
|
||||
To pass the known private key password to libcurl:
|
||||
|
||||
curl_easy_setopt(easyhandle, CURLOPT_SSLKEYPASSWD, "keypassword");
|
||||
|
||||
To make a password callback:
|
||||
|
||||
int enter_passwd(void *ourp, const char *prompt, char *buffer, int len);
|
||||
curl_easy_setopt(easyhandle, CURLOPT_PASSWDFUNCTION, enter_passwd);
|
||||
|
||||
|
||||
HTTP POSTing
|
||||
|
||||
We get many questions regarding how to issue HTTP POSTs with libcurl the
|
||||
proper way. This chapter will thus include examples using both different
|
||||
versions of HTTP POST that libcurl supports.
|
||||
|
||||
The first version is the simple POST, the most common version, that most HTML
|
||||
pages using the <form> tag uses. We provide a pointer to the data and tell
|
||||
libcurl to post it all to the remote site:
|
||||
|
||||
char *data="name=daniel&project=curl";
|
||||
curl_easy_setopt(easyhandle, CURLOPT_POSTFIELDS, data);
|
||||
curl_easy_setopt(easyhandle, CURLOPT_URL, "http://posthere.com/");
|
||||
|
||||
curl_easy_perform(easyhandle); /* post away! */
|
||||
|
||||
Simple enough, huh? Ok, so what if you want to post binary data that also
|
||||
requires you to set the Content-Type: header of the post? Well, binary posts
|
||||
prevents libcurl from being able to do strlen() on the data to figure out the
|
||||
size, so therefore we must tell libcurl the size of the post data. Setting
|
||||
headers in libcurl requests are done in a generic way, by building a list of
|
||||
our own headers and then passing that list to libcurl.
|
||||
|
||||
struct curl_slist *headers=NULL;
|
||||
headers = curl_slist_append(headers, "Content-Type: text/xml");
|
||||
|
||||
/* post binary data */
|
||||
curl_easy_setopt(easyhandle, CURLOPT_POSTFIELD, binaryptr);
|
||||
|
||||
/* set the size of the postfields data */
|
||||
curl_easy_setopt(easyhandle, CURLOPT_POSTFIELDSIZE, 23);
|
||||
|
||||
/* pass our list of custom made headers */
|
||||
curl_easy_setopt(easyhandle, CURLOPT_HTTPHEADER, headers);
|
||||
|
||||
curl_easy_perform(easyhandle); /* post away! */
|
||||
|
||||
curl_slist_free_all(headers); /* free the header list */
|
||||
|
||||
While the simple examples above cover the majority of all cases where HTTP
|
||||
POST operations are required, they don't do multipart formposts. Multipart
|
||||
formposts were introduced as a better way to post (possibly large) binary
|
||||
data and was first documented in the RFC1867. They're called multipart
|
||||
because they're built by a chain of parts, each being a single unit. Each
|
||||
part has its own name and contents. You can in fact create and post a
|
||||
multipart formpost with the regular libcurl POST support described above, but
|
||||
that would require that you build a formpost yourself and provide to
|
||||
libcurl. To make that easier, libcurl provides curl_formadd(). Using this
|
||||
function, you add parts to the form. When you're done adding parts, you post
|
||||
the whole form.
|
||||
|
||||
The following example sets two simple text parts with plain textual contents,
|
||||
and then a file with binary contents and upload the whole thing.
|
||||
|
||||
struct HttpPost *post=NULL;
|
||||
struct HttpPost *last=NULL;
|
||||
curl_formadd(&post, &last,
|
||||
CURLFORM_COPYNAME, "name",
|
||||
CURLFORM_COPYCONTENTS, "daniel", CURLFORM_END);
|
||||
curl_formadd(&post, &last,
|
||||
CURLFORM_COPYNAME, "project",
|
||||
CURLFORM_COPYCONTENTS, "curl", CURLFORM_END);
|
||||
curl_formadd(&post, &last,
|
||||
CURLFORM_COPYNAME, "logotype-image",
|
||||
CURLFORM_FILECONTENT, "curl.png", CURLFORM_END);
|
||||
|
||||
/* Set the form info */
|
||||
curl_easy_setopt(easyhandle, CURLOPT_HTTPPOST, post);
|
||||
|
||||
curl_easy_perform(easyhandle); /* post away! */
|
||||
|
||||
/* free the post data again */
|
||||
curl_formfree(post);
|
||||
|
||||
The multipart formposts are a chain of parts using MIME-style separators and
|
||||
headers. That means that each of these separate parts get a few headers set
|
||||
that describes its individual content-type, size etc. Now, to enable your
|
||||
application to handicraft this formpost even more, libcurl allows you to
|
||||
supply your own custom headers to an individual form part. You can of course
|
||||
supply headers to as many parts you like, but this little example will show
|
||||
how you have set headers to one specific part when you add that to post
|
||||
handle:
|
||||
|
||||
struct curl_slist *headers=NULL;
|
||||
headers = curl_slist_append(headers, "Content-Type: text/xml");
|
||||
|
||||
curl_formadd(&post, &last,
|
||||
CURLFORM_COPYNAME, "logotype-image",
|
||||
CURLFORM_FILECONTENT, "curl.xml",
|
||||
CURLFORM_CONTENTHEADER, headers,
|
||||
CURLFORM_END);
|
||||
|
||||
curl_easy_perform(easyhandle); /* post away! */
|
||||
|
||||
curl_formfree(post); /* free post */
|
||||
curl_slist_free_all(post); /* free custom header list */
|
||||
|
||||
|
||||
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.
|
||||
|
||||
|
||||
Proxies
|
||||
|
||||
What "proxy" means according to Merriam-Webster: "a person authorized to act
|
||||
for another" but also "the agency, function, or office of a deputy who acts
|
||||
as a substitute for another".
|
||||
|
||||
Proxies are exceedingly common these days. Companies often only offer
|
||||
internet access to employees through their HTTP proxies. Network clients or
|
||||
user-agents ask the proxy for docuements, the proxy does the actual request
|
||||
and then it returns them.
|
||||
|
||||
libcurl has full support for HTTP proxies, so when a given URL is wanted,
|
||||
libcurl will ask the proxy for it instead of trying to connect to the actual
|
||||
host identified in the URL.
|
||||
|
||||
The fact that the proxy is a HTTP proxy puts certain restrictions on what can
|
||||
actually happen. A requested URL that might not be a HTTP URL will be still
|
||||
be passed to the HTTP proxy to deliver back to libcurl. This happens
|
||||
transparantly, and an application may not need to know. I say "may", because
|
||||
at times it is very important to understand that all operations over a HTTP
|
||||
proxy is using the HTTP protocol. For example, you can't invoke your own
|
||||
custom FTP commands or even proper FTP directory listings.
|
||||
|
||||
To tell libcurl to use a proxy at a given port number:
|
||||
|
||||
curl_easy_setopt(easyhandle, CURLOPT_PROXY, "proxy-host.com:8080");
|
||||
|
||||
Some proxies require user authentication before allowing a request, and you
|
||||
pass that information similar to this:
|
||||
|
||||
curl_easy_setopt(easyhandle, CURLOPT_PROXYUSERPWD, "user:password");
|
||||
|
||||
[ environment variables, SSL, tunneling, automatic proxy config (.pac) ]
|
||||
|
||||
|
||||
Security Considerations
|
||||
|
||||
[ ps output, netrc plain text, plain text protocols / base64 ]
|
||||
|
||||
|
||||
Certificates and Other SSL Tricks
|
||||
|
||||
|
||||
Future
|
||||
|
||||
|
||||
|
||||
-----
|
||||
Footnotes:
|
||||
|
||||
@@ -207,3 +519,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.
|
||||
|
@@ -30,11 +30,11 @@
|
||||
# include <time.h>
|
||||
#else
|
||||
# include <sys/types.h>
|
||||
# if TIME_WITH_SYS_TIME
|
||||
# ifdef TIME_WITH_SYS_TIME
|
||||
# include <sys/time.h>
|
||||
# include <time.h>
|
||||
# else
|
||||
# if HAVE_SYS_TIME_H
|
||||
# ifdef HAVE_SYS_TIME_H
|
||||
# include <sys/time.h>
|
||||
# else
|
||||
# include <time.h>
|
||||
@@ -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"
|
||||
#define LIBCURL_VERSION_NUM 0x070903
|
||||
|
||||
/* linked-list structure for the CURLOPT_QUOTE option (and other) */
|
||||
|
@@ -35,14 +35,14 @@ libcurl_a_SOURCES = arpa_telnet.h file.c getpass.h netrc.h timeval.c base64.c \
|
||||
ldap.h ssluse.h escape.c getenv.h mprintf.c telnet.c escape.h getpass.c netrc.c \
|
||||
telnet.h getinfo.c strequal.c strequal.h easy.c security.h \
|
||||
security.c krb4.h krb4.c memdebug.h memdebug.c inet_ntoa_r.h http_chunks.h http_chunks.c \
|
||||
strtok.c connect.c
|
||||
strtok.c connect.c hash.c llist.c
|
||||
|
||||
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 transfer.o ldap.o ssluse.o version.o \
|
||||
getenv.o escape.o mprintf.o telnet.o getpass.o netrc.o getinfo.o \
|
||||
strequal.o easy.o security.o krb4.o memdebug.o http_chunks.o \
|
||||
strtok.o connect.o
|
||||
strtok.o connect.o hash.o llist.o
|
||||
|
||||
LIBRARIES = $(libcurl_a_LIBRARIES)
|
||||
SOURCES = $(libcurl_a_SOURCES)
|
||||
|
@@ -369,9 +369,11 @@ 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
|
||||
|
@@ -1155,10 +1155,13 @@ struct FormData *Curl_getFormData(struct HttpPost *post,
|
||||
}
|
||||
if(fileread != stdin)
|
||||
fclose(fileread);
|
||||
} else {
|
||||
size += AddFormData(&form, "[File wasn't found by client]", 0);
|
||||
}
|
||||
} else {
|
||||
else {
|
||||
/* File wasn't found, add a nothing field! */
|
||||
size += AddFormData(&form, "", 0);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* include the contents we got */
|
||||
size += AddFormData(&form, post->contents, post->contentslength);
|
||||
}
|
||||
|
@@ -358,7 +358,7 @@ int Curl_GetFTPResponse(char *buf,
|
||||
if(!error)
|
||||
code = atoi(buf);
|
||||
|
||||
#if KRB4
|
||||
#ifdef KRB4
|
||||
/* handle the security-oriented responses 6xx ***/
|
||||
/* FIXME: some errorchecking perhaps... ***/
|
||||
switch(code) {
|
||||
@@ -911,7 +911,7 @@ ftp_pasv_verbose(struct connectdata *conn,
|
||||
# ifdef HAVE_GETHOSTBYADDR_R_7
|
||||
/* Solaris and IRIX */
|
||||
answer = gethostbyaddr_r((char *) &address, sizeof(address), AF_INET,
|
||||
(struct hostent *)hostent_buf,
|
||||
(struct hostent *)bigbuf,
|
||||
hostent_buf + sizeof(*answer),
|
||||
sizeof(hostent_buf) - sizeof(*answer),
|
||||
&h_errnop);
|
||||
|
119
lib/getdate.c
119
lib/getdate.c
@@ -45,6 +45,11 @@
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef YYDEBUG
|
||||
/* to satisfy gcc -Wundef, we set this to 0 */
|
||||
#define YYDEBUG 0
|
||||
#endif
|
||||
|
||||
/* Since the code of getdate.y is not included in the Emacs executable
|
||||
itself, there is no need to #define static in this file. Even if
|
||||
the code were included in the Emacs executable, it probably
|
||||
@@ -223,7 +228,7 @@ static int yyRelSeconds;
|
||||
static int yyRelYear;
|
||||
|
||||
|
||||
#line 206 "getdate.y"
|
||||
#line 211 "getdate.y"
|
||||
typedef union {
|
||||
int Number;
|
||||
enum _MERIDIAN Meridian;
|
||||
@@ -306,11 +311,11 @@ static const short yyrhs[] = { -1,
|
||||
|
||||
#if YYDEBUG != 0
|
||||
static const short yyrline[] = { 0,
|
||||
222, 223, 226, 229, 232, 235, 238, 241, 244, 250,
|
||||
256, 265, 271, 283, 286, 289, 295, 299, 303, 309,
|
||||
313, 331, 337, 343, 347, 352, 356, 363, 371, 374,
|
||||
377, 380, 383, 386, 389, 392, 395, 398, 401, 404,
|
||||
407, 410, 413, 416, 419, 422, 425, 430, 463, 467
|
||||
227, 228, 231, 234, 237, 240, 243, 246, 249, 255,
|
||||
261, 270, 276, 288, 291, 294, 300, 304, 308, 314,
|
||||
318, 336, 342, 348, 352, 357, 361, 368, 376, 379,
|
||||
382, 385, 388, 391, 394, 397, 400, 403, 406, 409,
|
||||
412, 415, 418, 421, 424, 427, 430, 435, 468, 472
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -934,37 +939,37 @@ yyreduce:
|
||||
switch (yyn) {
|
||||
|
||||
case 3:
|
||||
#line 226 "getdate.y"
|
||||
#line 231 "getdate.y"
|
||||
{
|
||||
yyHaveTime++;
|
||||
;
|
||||
break;}
|
||||
case 4:
|
||||
#line 229 "getdate.y"
|
||||
#line 234 "getdate.y"
|
||||
{
|
||||
yyHaveZone++;
|
||||
;
|
||||
break;}
|
||||
case 5:
|
||||
#line 232 "getdate.y"
|
||||
#line 237 "getdate.y"
|
||||
{
|
||||
yyHaveDate++;
|
||||
;
|
||||
break;}
|
||||
case 6:
|
||||
#line 235 "getdate.y"
|
||||
#line 240 "getdate.y"
|
||||
{
|
||||
yyHaveDay++;
|
||||
;
|
||||
break;}
|
||||
case 7:
|
||||
#line 238 "getdate.y"
|
||||
#line 243 "getdate.y"
|
||||
{
|
||||
yyHaveRel++;
|
||||
;
|
||||
break;}
|
||||
case 9:
|
||||
#line 244 "getdate.y"
|
||||
#line 249 "getdate.y"
|
||||
{
|
||||
yyHour = yyvsp[-1].Number;
|
||||
yyMinutes = 0;
|
||||
@@ -973,7 +978,7 @@ case 9:
|
||||
;
|
||||
break;}
|
||||
case 10:
|
||||
#line 250 "getdate.y"
|
||||
#line 255 "getdate.y"
|
||||
{
|
||||
yyHour = yyvsp[-3].Number;
|
||||
yyMinutes = yyvsp[-1].Number;
|
||||
@@ -982,7 +987,7 @@ case 10:
|
||||
;
|
||||
break;}
|
||||
case 11:
|
||||
#line 256 "getdate.y"
|
||||
#line 261 "getdate.y"
|
||||
{
|
||||
yyHour = yyvsp[-3].Number;
|
||||
yyMinutes = yyvsp[-1].Number;
|
||||
@@ -994,7 +999,7 @@ case 11:
|
||||
;
|
||||
break;}
|
||||
case 12:
|
||||
#line 265 "getdate.y"
|
||||
#line 270 "getdate.y"
|
||||
{
|
||||
yyHour = yyvsp[-5].Number;
|
||||
yyMinutes = yyvsp[-3].Number;
|
||||
@@ -1003,7 +1008,7 @@ case 12:
|
||||
;
|
||||
break;}
|
||||
case 13:
|
||||
#line 271 "getdate.y"
|
||||
#line 276 "getdate.y"
|
||||
{
|
||||
yyHour = yyvsp[-5].Number;
|
||||
yyMinutes = yyvsp[-3].Number;
|
||||
@@ -1016,53 +1021,53 @@ case 13:
|
||||
;
|
||||
break;}
|
||||
case 14:
|
||||
#line 283 "getdate.y"
|
||||
#line 288 "getdate.y"
|
||||
{
|
||||
yyTimezone = yyvsp[0].Number;
|
||||
;
|
||||
break;}
|
||||
case 15:
|
||||
#line 286 "getdate.y"
|
||||
#line 291 "getdate.y"
|
||||
{
|
||||
yyTimezone = yyvsp[0].Number - 60;
|
||||
;
|
||||
break;}
|
||||
case 16:
|
||||
#line 290 "getdate.y"
|
||||
#line 295 "getdate.y"
|
||||
{
|
||||
yyTimezone = yyvsp[-1].Number - 60;
|
||||
;
|
||||
break;}
|
||||
case 17:
|
||||
#line 295 "getdate.y"
|
||||
#line 300 "getdate.y"
|
||||
{
|
||||
yyDayOrdinal = 1;
|
||||
yyDayNumber = yyvsp[0].Number;
|
||||
;
|
||||
break;}
|
||||
case 18:
|
||||
#line 299 "getdate.y"
|
||||
#line 304 "getdate.y"
|
||||
{
|
||||
yyDayOrdinal = 1;
|
||||
yyDayNumber = yyvsp[-1].Number;
|
||||
;
|
||||
break;}
|
||||
case 19:
|
||||
#line 303 "getdate.y"
|
||||
#line 308 "getdate.y"
|
||||
{
|
||||
yyDayOrdinal = yyvsp[-1].Number;
|
||||
yyDayNumber = yyvsp[0].Number;
|
||||
;
|
||||
break;}
|
||||
case 20:
|
||||
#line 309 "getdate.y"
|
||||
#line 314 "getdate.y"
|
||||
{
|
||||
yyMonth = yyvsp[-2].Number;
|
||||
yyDay = yyvsp[0].Number;
|
||||
;
|
||||
break;}
|
||||
case 21:
|
||||
#line 313 "getdate.y"
|
||||
#line 318 "getdate.y"
|
||||
{
|
||||
/* Interpret as YYYY/MM/DD if $1 >= 1000, otherwise as MM/DD/YY.
|
||||
The goal in recognizing YYYY/MM/DD is solely to support legacy
|
||||
@@ -1083,7 +1088,7 @@ case 21:
|
||||
;
|
||||
break;}
|
||||
case 22:
|
||||
#line 331 "getdate.y"
|
||||
#line 336 "getdate.y"
|
||||
{
|
||||
/* ISO 8601 format. yyyy-mm-dd. */
|
||||
yyYear = yyvsp[-2].Number;
|
||||
@@ -1092,7 +1097,7 @@ case 22:
|
||||
;
|
||||
break;}
|
||||
case 23:
|
||||
#line 337 "getdate.y"
|
||||
#line 342 "getdate.y"
|
||||
{
|
||||
/* e.g. 17-JUN-1992. */
|
||||
yyDay = yyvsp[-2].Number;
|
||||
@@ -1101,14 +1106,14 @@ case 23:
|
||||
;
|
||||
break;}
|
||||
case 24:
|
||||
#line 343 "getdate.y"
|
||||
#line 348 "getdate.y"
|
||||
{
|
||||
yyMonth = yyvsp[-1].Number;
|
||||
yyDay = yyvsp[0].Number;
|
||||
;
|
||||
break;}
|
||||
case 25:
|
||||
#line 347 "getdate.y"
|
||||
#line 352 "getdate.y"
|
||||
{
|
||||
yyMonth = yyvsp[-3].Number;
|
||||
yyDay = yyvsp[-2].Number;
|
||||
@@ -1116,14 +1121,14 @@ case 25:
|
||||
;
|
||||
break;}
|
||||
case 26:
|
||||
#line 352 "getdate.y"
|
||||
#line 357 "getdate.y"
|
||||
{
|
||||
yyMonth = yyvsp[0].Number;
|
||||
yyDay = yyvsp[-1].Number;
|
||||
;
|
||||
break;}
|
||||
case 27:
|
||||
#line 356 "getdate.y"
|
||||
#line 361 "getdate.y"
|
||||
{
|
||||
yyMonth = yyvsp[-1].Number;
|
||||
yyDay = yyvsp[-2].Number;
|
||||
@@ -1131,7 +1136,7 @@ case 27:
|
||||
;
|
||||
break;}
|
||||
case 28:
|
||||
#line 363 "getdate.y"
|
||||
#line 368 "getdate.y"
|
||||
{
|
||||
yyRelSeconds = -yyRelSeconds;
|
||||
yyRelMinutes = -yyRelMinutes;
|
||||
@@ -1142,115 +1147,115 @@ case 28:
|
||||
;
|
||||
break;}
|
||||
case 30:
|
||||
#line 374 "getdate.y"
|
||||
#line 379 "getdate.y"
|
||||
{
|
||||
yyRelYear += yyvsp[-1].Number * yyvsp[0].Number;
|
||||
;
|
||||
break;}
|
||||
case 31:
|
||||
#line 377 "getdate.y"
|
||||
#line 382 "getdate.y"
|
||||
{
|
||||
yyRelYear += yyvsp[-1].Number * yyvsp[0].Number;
|
||||
;
|
||||
break;}
|
||||
case 32:
|
||||
#line 380 "getdate.y"
|
||||
#line 385 "getdate.y"
|
||||
{
|
||||
yyRelYear += yyvsp[0].Number;
|
||||
;
|
||||
break;}
|
||||
case 33:
|
||||
#line 383 "getdate.y"
|
||||
#line 388 "getdate.y"
|
||||
{
|
||||
yyRelMonth += yyvsp[-1].Number * yyvsp[0].Number;
|
||||
;
|
||||
break;}
|
||||
case 34:
|
||||
#line 386 "getdate.y"
|
||||
#line 391 "getdate.y"
|
||||
{
|
||||
yyRelMonth += yyvsp[-1].Number * yyvsp[0].Number;
|
||||
;
|
||||
break;}
|
||||
case 35:
|
||||
#line 389 "getdate.y"
|
||||
#line 394 "getdate.y"
|
||||
{
|
||||
yyRelMonth += yyvsp[0].Number;
|
||||
;
|
||||
break;}
|
||||
case 36:
|
||||
#line 392 "getdate.y"
|
||||
#line 397 "getdate.y"
|
||||
{
|
||||
yyRelDay += yyvsp[-1].Number * yyvsp[0].Number;
|
||||
;
|
||||
break;}
|
||||
case 37:
|
||||
#line 395 "getdate.y"
|
||||
#line 400 "getdate.y"
|
||||
{
|
||||
yyRelDay += yyvsp[-1].Number * yyvsp[0].Number;
|
||||
;
|
||||
break;}
|
||||
case 38:
|
||||
#line 398 "getdate.y"
|
||||
#line 403 "getdate.y"
|
||||
{
|
||||
yyRelDay += yyvsp[0].Number;
|
||||
;
|
||||
break;}
|
||||
case 39:
|
||||
#line 401 "getdate.y"
|
||||
#line 406 "getdate.y"
|
||||
{
|
||||
yyRelHour += yyvsp[-1].Number * yyvsp[0].Number;
|
||||
;
|
||||
break;}
|
||||
case 40:
|
||||
#line 404 "getdate.y"
|
||||
#line 409 "getdate.y"
|
||||
{
|
||||
yyRelHour += yyvsp[-1].Number * yyvsp[0].Number;
|
||||
;
|
||||
break;}
|
||||
case 41:
|
||||
#line 407 "getdate.y"
|
||||
#line 412 "getdate.y"
|
||||
{
|
||||
yyRelHour += yyvsp[0].Number;
|
||||
;
|
||||
break;}
|
||||
case 42:
|
||||
#line 410 "getdate.y"
|
||||
#line 415 "getdate.y"
|
||||
{
|
||||
yyRelMinutes += yyvsp[-1].Number * yyvsp[0].Number;
|
||||
;
|
||||
break;}
|
||||
case 43:
|
||||
#line 413 "getdate.y"
|
||||
#line 418 "getdate.y"
|
||||
{
|
||||
yyRelMinutes += yyvsp[-1].Number * yyvsp[0].Number;
|
||||
;
|
||||
break;}
|
||||
case 44:
|
||||
#line 416 "getdate.y"
|
||||
#line 421 "getdate.y"
|
||||
{
|
||||
yyRelMinutes += yyvsp[0].Number;
|
||||
;
|
||||
break;}
|
||||
case 45:
|
||||
#line 419 "getdate.y"
|
||||
#line 424 "getdate.y"
|
||||
{
|
||||
yyRelSeconds += yyvsp[-1].Number * yyvsp[0].Number;
|
||||
;
|
||||
break;}
|
||||
case 46:
|
||||
#line 422 "getdate.y"
|
||||
#line 427 "getdate.y"
|
||||
{
|
||||
yyRelSeconds += yyvsp[-1].Number * yyvsp[0].Number;
|
||||
;
|
||||
break;}
|
||||
case 47:
|
||||
#line 425 "getdate.y"
|
||||
#line 430 "getdate.y"
|
||||
{
|
||||
yyRelSeconds += yyvsp[0].Number;
|
||||
;
|
||||
break;}
|
||||
case 48:
|
||||
#line 431 "getdate.y"
|
||||
#line 436 "getdate.y"
|
||||
{
|
||||
if (yyHaveTime && yyHaveDate && !yyHaveRel)
|
||||
yyYear = yyvsp[0].Number;
|
||||
@@ -1283,13 +1288,13 @@ case 48:
|
||||
;
|
||||
break;}
|
||||
case 49:
|
||||
#line 464 "getdate.y"
|
||||
#line 469 "getdate.y"
|
||||
{
|
||||
yyval.Meridian = MER24;
|
||||
;
|
||||
break;}
|
||||
case 50:
|
||||
#line 468 "getdate.y"
|
||||
#line 473 "getdate.y"
|
||||
{
|
||||
yyval.Meridian = yyvsp[0].Meridian;
|
||||
;
|
||||
@@ -1516,7 +1521,7 @@ yyerrhandle:
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
#line 473 "getdate.y"
|
||||
#line 478 "getdate.y"
|
||||
|
||||
|
||||
/* Include this file down here because bison inserts code above which
|
||||
@@ -2126,11 +2131,3 @@ main (ac, av)
|
||||
/* NOTREACHED */
|
||||
}
|
||||
#endif /* defined (TEST) */
|
||||
|
||||
/*
|
||||
* local variables:
|
||||
* eval: (load-file "../curl-mode.el")
|
||||
* end:
|
||||
* vim600: fdm=marker
|
||||
* vim: et sw=2 ts=2 sts=2 tw=78
|
||||
*/
|
||||
|
@@ -21,6 +21,11 @@
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef YYDEBUG
|
||||
/* to satisfy gcc -Wundef, we set this to 0 */
|
||||
#define YYDEBUG 0
|
||||
#endif
|
||||
|
||||
/* Since the code of getdate.y is not included in the Emacs executable
|
||||
itself, there is no need to #define static in this file. Even if
|
||||
the code were included in the Emacs executable, it probably
|
||||
|
@@ -101,7 +101,10 @@ curl_hash_alloc(int slots, curl_hash_dtor dtor)
|
||||
{
|
||||
curl_hash *h;
|
||||
|
||||
h = malloc(sizeof(curl_hash));
|
||||
h = (curl_hash *)malloc(sizeof(curl_hash));
|
||||
if(NULL == h)
|
||||
return NULL;
|
||||
|
||||
curl_hash_init(h, slots, dtor);
|
||||
|
||||
return h;
|
||||
|
98
lib/hostip.c
98
lib/hostip.c
@@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -358,10 +426,10 @@ Curl_addrinfo *Curl_getaddrinfo(struct SessionHandle *data,
|
||||
* everything. OSF1 is known to require at least 8872 bytes. The buffer
|
||||
* required for storing all possible aliases and IP numbers is according to
|
||||
* Stevens' Unix Network Programming 2nd editor, p. 304: 8192 bytes! */
|
||||
char *buf = (char *)malloc(CURL_NAMELOOKUP_SIZE);
|
||||
int *buf = (int *)malloc(CURL_NAMELOOKUP_SIZE);
|
||||
if(!buf)
|
||||
return NULL; /* major failure */
|
||||
*bufp = buf;
|
||||
*bufp = (char *)buf;
|
||||
|
||||
port=0; /* unused in IPv4 code */
|
||||
ret = 0; /* to prevent the compiler warning */
|
||||
@@ -391,7 +459,7 @@ Curl_addrinfo *Curl_getaddrinfo(struct SessionHandle *data,
|
||||
/* Solaris, IRIX and more */
|
||||
if ((h = gethostbyname_r(hostname,
|
||||
(struct hostent *)buf,
|
||||
buf + sizeof(struct hostent),
|
||||
(char *)buf + sizeof(struct hostent),
|
||||
CURL_NAMELOOKUP_SIZE - sizeof(struct hostent),
|
||||
&h_errnop)) == NULL )
|
||||
#endif
|
||||
|
@@ -46,7 +46,10 @@ curl_llist_alloc(curl_llist_dtor dtor)
|
||||
{
|
||||
curl_llist *list;
|
||||
|
||||
list = malloc(sizeof(curl_llist));
|
||||
list = (curl_llist *)malloc(sizeof(curl_llist));
|
||||
if(NULL == list)
|
||||
return NULL;
|
||||
|
||||
curl_llist_init(list, dtor);
|
||||
|
||||
return list;
|
||||
|
@@ -24,73 +24,11 @@
|
||||
* - Max 128 parameters
|
||||
* - No 'long double' support.
|
||||
*
|
||||
*************************************************************************
|
||||
*
|
||||
*
|
||||
* 1998/01/10 (v2.8)
|
||||
* Daniel
|
||||
* - Updated version number.
|
||||
* - Corrected a static non-zero prefixed width problem.
|
||||
*
|
||||
* 1998/11/17 - Daniel
|
||||
* Added daprintf() and dvaprintf() for allocated printf() and vprintf().
|
||||
* They return an allocated buffer with the result inside. The result must
|
||||
* be free()ed!
|
||||
*
|
||||
* 1998/08/23 - breese
|
||||
*
|
||||
* Converted all non-printable (and non-whitespace) characters into
|
||||
* their decimal ASCII value preceeded by a '\' character
|
||||
* (this only applies to snprintf family so far)
|
||||
*
|
||||
* Added %S (which is the same as %#s)
|
||||
*
|
||||
* 1998/05/05 (v2.7)
|
||||
*
|
||||
* Fixed precision and width qualifiers (%.*s)
|
||||
*
|
||||
* Added support for snprintf()
|
||||
*
|
||||
* Quoting (%#s) is disabled for the (nil) pointer
|
||||
*
|
||||
* 1997/06/09 (v2.6)
|
||||
*
|
||||
* %#s means that the string will be quoted with "
|
||||
* (I was getting tired of writing \"%s\" all the time)
|
||||
*
|
||||
* [ERR] for strings changed to (nil)
|
||||
*
|
||||
* v2.5
|
||||
* - Added C++ support
|
||||
* - Prepended all internal functions with dprintf_
|
||||
* - Defined the booleans
|
||||
*
|
||||
* v2.4
|
||||
* - Added dvsprintf(), dvfprintf() and dvprintf().
|
||||
* - Made the formatting function available with the name _formatf() to enable
|
||||
* other *printf()-inspired functions. (I considered adding a dmsprintf()
|
||||
* that works like sprintf() but allocates the destination string and
|
||||
* possibly enlarges it itself, but things like that should be done with the
|
||||
* new _formatf() instead.)
|
||||
*
|
||||
* v2.3
|
||||
* - Small modifications to make it compile nicely at both Daniel's and
|
||||
* Bjorn's place.
|
||||
*
|
||||
* v2.2
|
||||
* - Made it work with text to the right of the last %!
|
||||
* - Introduced dprintf(), dsprintf() and dfprintf().
|
||||
* - Float/double support enabled. This system is currently using the ordinary
|
||||
* sprintf() function. NOTE that positional parameters, widths and precisions
|
||||
* will still work like it should since the d-system takes care of that and
|
||||
* passes that information re-formatted to the old sprintf().
|
||||
*
|
||||
* v2.1
|
||||
* - Fixed space padding (i.e %d was extra padded previously)
|
||||
* - long long output is supported
|
||||
* - alternate output is done correct like in %#08x
|
||||
*
|
||||
****************************************************************************/
|
||||
* If you ever want truly portable and good *printf() clones, the project that
|
||||
* took on from here is named 'Trio' and you find more details on the trio web
|
||||
* page at http://daniel.haxx.se/trio/
|
||||
*/
|
||||
|
||||
|
||||
#include "setup.h"
|
||||
#include <sys/types.h>
|
||||
@@ -100,6 +38,15 @@
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifndef SIZEOF_LONG_LONG
|
||||
/* prevents warnings on picky compilers */
|
||||
#define SIZEOF_LONG_LONG 0
|
||||
#endif
|
||||
#ifndef SIZEOF_LONG_DOUBLE
|
||||
#define SIZEOF_LONG_DOUBLE 0
|
||||
#endif
|
||||
|
||||
|
||||
/* The last #include file should be: */
|
||||
#ifdef MALLOCDEBUG
|
||||
#include "memdebug.h"
|
||||
@@ -1191,7 +1138,7 @@ int main()
|
||||
{
|
||||
char buffer[129];
|
||||
char *ptr;
|
||||
#ifdef SIZEOF_LONG_LONG
|
||||
#if SIZEOF_LONG_LONG>0
|
||||
long long hullo;
|
||||
dprintf("%3$12s %1$s %2$qd %4$d\n", "daniel", hullo, "stenberg", 65);
|
||||
#endif
|
||||
|
@@ -157,7 +157,7 @@ int Curl_parsenetrc(char *host,
|
||||
}
|
||||
else if(state_password) {
|
||||
strncpy(password, tok, PASSWORDSIZE-1);
|
||||
#if _NETRC_DEBUG
|
||||
#ifdef _NETRC_DEBUG
|
||||
printf("PASSWORD: %s\n", password);
|
||||
#endif
|
||||
state_password=0;
|
||||
|
@@ -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.
|
||||
@@ -26,6 +26,8 @@
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
@@ -212,6 +214,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
|
||||
@@ -226,7 +229,7 @@ CURLcode Curl_write(struct connectdata *conn, int sockfd,
|
||||
}
|
||||
if(-1 == bytes_written) {
|
||||
#ifdef WIN32
|
||||
if(EWOULDBLOCK == GetLastError())
|
||||
if(WSAEWOULDBLOCK == GetLastError())
|
||||
#else
|
||||
if(EWOULDBLOCK == errno)
|
||||
#endif
|
||||
@@ -338,7 +341,7 @@ int Curl_read(struct connectdata *conn,
|
||||
|
||||
if(-1 == nread) {
|
||||
#ifdef WIN32
|
||||
if(EWOULDBLOCK == GetLastError())
|
||||
if(WSAEWOULDBLOCK == GetLastError())
|
||||
#else
|
||||
if(EWOULDBLOCK == errno)
|
||||
#endif
|
||||
|
23
lib/ssluse.c
23
lib/ssluse.c
@@ -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) */
|
||||
|
@@ -356,10 +356,11 @@ CURLcode Curl_readwrite(struct connectdata *conn,
|
||||
* If we requested a "no body", this is a good time to get
|
||||
* out and return home.
|
||||
*/
|
||||
if(data->set.no_body)
|
||||
return CURLE_OK;
|
||||
bool stop_reading = FALSE;
|
||||
|
||||
if(!conn->bits.close) {
|
||||
if(data->set.no_body)
|
||||
stop_reading = TRUE;
|
||||
else if(!conn->bits.close) {
|
||||
/* If this is not the last request before a close, we must
|
||||
set the maximum download size to the size of the
|
||||
expected document or else, we won't know when to stop
|
||||
@@ -370,10 +371,18 @@ CURLcode Curl_readwrite(struct connectdata *conn,
|
||||
/* If max download size is *zero* (nothing) we already
|
||||
have nothing and can safely return ok now! */
|
||||
if(0 == conn->maxdownload)
|
||||
return CURLE_OK;
|
||||
stop_reading = TRUE;
|
||||
|
||||
/* What to do if the size is *not* known? */
|
||||
}
|
||||
|
||||
if(stop_reading) {
|
||||
/* we make sure that this socket isn't read more now */
|
||||
k->keepon &= ~KEEP_READ;
|
||||
FD_ZERO(&k->rkeepfd);
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
break; /* exit header line loop */
|
||||
}
|
||||
|
||||
|
@@ -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;
|
||||
}
|
||||
else
|
||||
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);
|
||||
}
|
||||
|
||||
|
@@ -1,3 +1,3 @@
|
||||
#define CURL_NAME "curl"
|
||||
#define CURL_VERSION "7.9.3-pre2"
|
||||
#define CURL_VERSION "7.9.3"
|
||||
#define CURL_ID CURL_NAME " " CURL_VERSION " (" OS ") "
|
||||
|
Reference in New Issue
Block a user