Compare commits
139 Commits
curl-7_9_2
...
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 | ||
![]() |
fbe2907599 | ||
![]() |
343da8d4b3 | ||
![]() |
8d97792dbc | ||
![]() |
8d07c87be7 | ||
![]() |
ed21701df3 | ||
![]() |
df01507582 | ||
![]() |
f2bda5fd5b | ||
![]() |
cba9838e8f | ||
![]() |
b6dba9f5dd | ||
![]() |
6e9d1617c6 | ||
![]() |
ea811fee52 | ||
![]() |
7391fd8f6a | ||
![]() |
6c00c58f2a | ||
![]() |
4931fbce49 | ||
![]() |
fefc7ea600 | ||
![]() |
d220389647 | ||
![]() |
a1f910c159 | ||
![]() |
e4866563de | ||
![]() |
47f45aa229 | ||
![]() |
affe334675 | ||
![]() |
ee7e184e26 | ||
![]() |
bec0ebacf1 | ||
![]() |
5bd6d631c6 | ||
![]() |
fd1799f3bb | ||
![]() |
d84a0c51e0 | ||
![]() |
d9a7c7de51 | ||
![]() |
d57e09889a | ||
![]() |
eecb86bfb0 | ||
![]() |
0b1197936c | ||
![]() |
b545ac6391 | ||
![]() |
a922132e4a | ||
![]() |
9474e8d6d2 | ||
![]() |
6328428568 | ||
![]() |
ea9a88a9b8 | ||
![]() |
aec7358ca4 | ||
![]() |
3c334b2bb6 | ||
![]() |
75bba0da92 | ||
![]() |
c0bfe7be15 | ||
![]() |
22ac08e06d | ||
![]() |
87037136ef | ||
![]() |
2182e37433 | ||
![]() |
1de82b220d | ||
![]() |
bd878756fc | ||
![]() |
8d7f402efb | ||
![]() |
d3299beec7 | ||
![]() |
f9192db358 | ||
![]() |
c69c0c0446 | ||
![]() |
deb2911c0e | ||
![]() |
e31a306a38 | ||
![]() |
d9a7773011 | ||
![]() |
2b14916813 | ||
![]() |
1d1530e14c | ||
![]() |
b4fdc025a8 | ||
![]() |
f1c14fe0b4 | ||
![]() |
38306cda54 | ||
![]() |
5a0f0023cf | ||
![]() |
6dcdb8b821 | ||
![]() |
781f52a287 | ||
![]() |
f75ff58b4b | ||
![]() |
ae9bf16dee | ||
![]() |
17a8bf212f | ||
![]() |
4fc76afef4 | ||
![]() |
a31155a72a | ||
![]() |
75601f7924 | ||
![]() |
8b6314ccfb | ||
![]() |
6de7dc5879 | ||
![]() |
6aaee5f23b | ||
![]() |
dd06dcebe1 | ||
![]() |
b35c26b751 | ||
![]() |
128f341635 | ||
![]() |
e48bc1be48 | ||
![]() |
0077b9c0a2 | ||
![]() |
fe37fb5921 | ||
![]() |
221ecd0a30 | ||
![]() |
560492707d | ||
![]() |
dfdf4916fa | ||
![]() |
97a8c98886 | ||
![]() |
62fb70e9d1 | ||
![]() |
8a9098a36c | ||
![]() |
28027c2aa2 | ||
![]() |
d60029d66e | ||
![]() |
226fe8bdf9 | ||
![]() |
33237b4502 | ||
![]() |
af6c394785 | ||
![]() |
558d12d7f6 | ||
![]() |
bfa8a6da26 | ||
![]() |
aa6b3d22a2 | ||
![]() |
2eb355733f | ||
![]() |
e66cdacb93 | ||
![]() |
c67f2da283 | ||
![]() |
e192261788 | ||
![]() |
c63ca99c1c | ||
![]() |
1c99c4ad11 | ||
![]() |
bbcfc10677 | ||
![]() |
47e67eab26 | ||
![]() |
650b95045d | ||
![]() |
5603134e58 | ||
![]() |
d12fd897cb | ||
![]() |
5e95203a5d | ||
![]() |
cad4a571ce |
230
CHANGES
230
CHANGES
@@ -6,6 +6,236 @@
|
|||||||
|
|
||||||
History of Changes
|
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
|
||||||
|
sockets in the upload section. While doing this, I've now separated the
|
||||||
|
connection oriented buffers to have one for downloads and one for uploads
|
||||||
|
(as two can happen simultaneously). I also shrunk the buffers to 20K
|
||||||
|
each. As we have a scratch buffer twice the size of the upload buffer, we
|
||||||
|
arrived at 80K for buffers compared with the previous 150K.
|
||||||
|
|
||||||
|
- Added the --cc option to curl-config command as it enables so very cool
|
||||||
|
one-liners. Have a go a this one, building the simple.c example:
|
||||||
|
|
||||||
|
$ `curl-config --cc --cflags --libs` -o example simple.c
|
||||||
|
|
||||||
|
Daniel (14 January 2002)
|
||||||
|
- I made all socket reads (recv) handle EWOULDBLOCK. I hope nicely. Now we
|
||||||
|
only need to address all writes (send) too and then I'm ready for another
|
||||||
|
pre-release...
|
||||||
|
|
||||||
|
- Stoned Elipot patched the in_addr_t configure test to make it work better on
|
||||||
|
more platforms.
|
||||||
|
|
||||||
|
Daniel (9 January 2002)
|
||||||
|
- Cris Bailiff found out that filling up curl's SSL session cache caused a
|
||||||
|
crash!
|
||||||
|
|
||||||
|
- Posted the curl questionnaire on the web site. If you haven't posted your
|
||||||
|
opinions there yet, go there and do it now while it is still there:
|
||||||
|
|
||||||
|
http://curl.haxx.se/q/
|
||||||
|
|
||||||
|
- Georg Horn quickly found out that the SSL reading no longer worked as
|
||||||
|
supposed since the switch to non-blocking sockets. I've made a quick patch
|
||||||
|
(for reading only) but we should improve it even further.
|
||||||
|
|
||||||
|
Version 7.9.3-pre1
|
||||||
|
|
||||||
|
Daniel (7 January 2002)
|
||||||
|
- I made the 'bool' typedef use an "unsigned char". It makes it the same on
|
||||||
|
all platforms, no matter what the platform thinks the default format for
|
||||||
|
char is. This was noticed since we made a silly comparison involving such a
|
||||||
|
bool variable, and only one compiler/platform combination (on Debian Linux)
|
||||||
|
complained about it (that happened to have its char unsigned by default).
|
||||||
|
|
||||||
|
- Bug report #495290 identified a cookie parsing problem that was corrected.
|
||||||
|
When a Set-Cookie: line is received without a trailing semicolon, libcurl
|
||||||
|
didn't read the last "name=value" pair of the line, leading to confusions...
|
||||||
|
|
||||||
|
- Sterling committed his updated DNS cache code.
|
||||||
|
|
||||||
|
- I worked with Georg Horn and comments from G<>tz Babin-Ebell and switched
|
||||||
|
curl's socket operations completely over to non-blocking for the entire
|
||||||
|
operation (previously we used non-blocking only for the connection phase).
|
||||||
|
We had to do this to make the SSL connection phase timeout properly without
|
||||||
|
the use of signals. A little extra code to deal with this was added.
|
||||||
|
|
||||||
|
- T. Bharath pointed out a slightly obscure cookie engine flaw.
|
||||||
|
|
||||||
|
- Pete Su pointed out that libcurl didn't treat HTTP code 204 as it should.
|
||||||
|
204-replies never provides a response-body. This resulted in bad persistant
|
||||||
|
behavior when 204 was received.
|
||||||
|
|
||||||
|
Daniel (5 January 2002)
|
||||||
|
- SM updated the VC++ library Makefiles for the new source files.
|
||||||
|
|
||||||
|
Daniel (4 January 2002)
|
||||||
|
- I discovered that we wrongly used inet_ntoa() (instead of inet_ntoa_r() in
|
||||||
|
two places in the source code). One happened with VERBOSE set on connects,
|
||||||
|
and the other when VERBOSE was on and krb4 over nat was used... I honestly
|
||||||
|
don't think anyone has suffered from these mistakes.
|
||||||
|
|
||||||
|
- I replaced a lot of silly occurances of printf() to instead use the more
|
||||||
|
appropriate Curl_infof() or Curl_failf(). The krb4 and telnet code were
|
||||||
|
affected.
|
||||||
|
|
||||||
|
- Philip Gladstone found a few more problems with 64-bit archs (the 64-bit
|
||||||
|
sparc on solaris 8).
|
||||||
|
|
||||||
|
- After discussions on the libcurl list with Raoul Cridlig, I just made FTP
|
||||||
|
response lines get passed to the header callback if such a one is
|
||||||
|
registered. It'll make it possible for any application to get all the
|
||||||
|
responses an FTP server sends to libcurl.
|
||||||
|
|
||||||
|
Daniel (3 January 2002)
|
||||||
|
- Sterling Hughes brought a few buckets of code. Now, libcurl will
|
||||||
|
automatically cache DNS lookups and re-use the previous results first if any
|
||||||
|
such is available. It greatly improves speed when doing many repeated
|
||||||
|
operations to the same host.
|
||||||
|
|
||||||
|
- As the test case uses --include and then --head, I had to modify src/main.c
|
||||||
|
to deal with this situation slightly better than previously. When done, we
|
||||||
|
have 100% good tests again in the main branch.
|
||||||
|
|
||||||
|
Daniel (2 January 2002)
|
||||||
|
- Made test case 25 run again in the multi-dev branch. But it seems that the
|
||||||
|
changes done on dec-20 made test case 104 cease to work (in both branches).
|
||||||
|
|
||||||
|
- Philip Gladstone pointed out a few portability problems in the source code
|
||||||
|
that didn't compile on 64-bit sparcs using Sun's native compiler...
|
||||||
|
|
||||||
|
Daniel (20 December 2001)
|
||||||
|
- Bj<42>rn Stenberg caught an unpleasent (but hard-to-find) bug that could cause
|
||||||
|
libcurl to hang on transfers over proxy, when the proxy was specified with
|
||||||
|
an environment variable!
|
||||||
|
|
||||||
|
- Added code to make ftp operations treat the NO_BODY and HEADERS options
|
||||||
|
better:
|
||||||
|
|
||||||
|
NO_BODY set TRUE and HEADERS set TRUE:
|
||||||
|
Return a set of headers with file info
|
||||||
|
|
||||||
|
NO_BODY set FALSE
|
||||||
|
Transfer data as usual, HEADERS is ignored
|
||||||
|
|
||||||
|
NO_BODY set TRUE and HEADERS set FALSE
|
||||||
|
Don't transfer any data, don't return any headers. Just perform the set
|
||||||
|
of FTP commands.
|
||||||
|
|
||||||
|
Daniel (17 December 2001)
|
||||||
|
- G<>tz Babin-Ebell dove into the dark dungeons of the OpenSSL ENGINE stuff and
|
||||||
|
made libcurl support it! This allows libcurl to do SSL connections with the
|
||||||
|
private key stored in external hardware.
|
||||||
|
|
||||||
|
To make this good, he had to add a bunch of new library options that'll be
|
||||||
|
useful to others as well:
|
||||||
|
|
||||||
|
CURLOPT_SSLCERTTYPE set SSL cert type (PEM/DER)
|
||||||
|
CURLOPT_SSLKEY set SSL private key (file)
|
||||||
|
CURLOPT_SSLKEYTYPE: set SSL key type (PEM/DER/ENG)
|
||||||
|
CURLOPT_SSLKEYPASSWD: set the passphrase for your private key
|
||||||
|
(CURLOPT_SSLCERTPASSWD is an alias)
|
||||||
|
CURLOPT_SSLENGINE: set the name of the crypto engine
|
||||||
|
(returns CURLE_SSL_ENGINE_NOTFOUND on error)
|
||||||
|
CURLOPT_SSLENGINE_DEFAULT: set the default engine
|
||||||
|
|
||||||
|
There are two new failure codes:
|
||||||
|
|
||||||
|
CURLE_SSL_ENGINE_NOTFOUND
|
||||||
|
CURLE_SSL_ENGINE_SETFAILED
|
||||||
|
|
||||||
|
Daniel (14 December 2001)
|
||||||
|
- We have "branched" the source-tree at a few places. Checkout the CVS sources
|
||||||
|
with the 'multi-dev' label to get the latest multi interface development
|
||||||
|
tree. The idea is to only branch affected files and to restrict the branch
|
||||||
|
to the v8 multi interface development only.
|
||||||
|
|
||||||
|
*NOTE* that if we get bug reports and patches etc, we might need to apply
|
||||||
|
them in both branches!
|
||||||
|
|
||||||
|
The multi-dev branch is what we are gonna use as main branch in the future
|
||||||
|
if it turns out successful. Thus, we must maintain both now in case we need
|
||||||
|
them. The current main branch will be used if we want to release a 7.9.3 or
|
||||||
|
perhaps a 7.10 release before version 8. Which is very likely.
|
||||||
|
|
||||||
|
- Marcus Webster provided code for the new CURLFORM_CONTENTHEADER option for
|
||||||
|
curl_formadd(), that lets an application add a set of headers for that
|
||||||
|
particular part in a multipart/form-post. He also provided a section to the
|
||||||
|
man page that describes the new option.
|
||||||
|
|
||||||
|
Daniel (11 December 2001)
|
||||||
|
- Ben Greear made me aware of the fact that the Curl_failf() usage internally
|
||||||
|
was a bit sloppy with adding newlines or not to the error messages. Let's
|
||||||
|
once and for all say that they do not belong there!
|
||||||
|
|
||||||
|
- When uploading files with -T to give a local file name, and you end the URL
|
||||||
|
with a slash to have the local file name used remote too, we now no longer
|
||||||
|
use the local directory as well. Only the file part of the -T file name
|
||||||
|
will be appended to the right of the slash in the URL.
|
||||||
|
|
||||||
|
Daniel (7 December 2001)
|
||||||
|
- Michal Bonino pointed out that Digital Unix doesn't have gmtime_r so the
|
||||||
|
link failed. Added a configure check and corrected source code.
|
||||||
|
|
||||||
Version 7.9.2
|
Version 7.9.2
|
||||||
|
|
||||||
Daniel (5 December 2001)
|
Daniel (5 December 2001)
|
||||||
|
835
CHANGES.0
835
CHANGES.0
@@ -1,838 +1,3 @@
|
|||||||
Daniel (28 December 1999):
|
|
||||||
- Tim Verhoeven correctly identified that curl
|
|
||||||
doesn't support URL formatted file names when getting ftp. Now, there's a
|
|
||||||
problem with getting very weird file names off FTP servers. RFC 959 defines
|
|
||||||
that the file name syntax to use should be the same as in the native OS of
|
|
||||||
the server. Since we don't know the peer server system we currently just
|
|
||||||
translate the URL syntax into plain letters. It is still better and with
|
|
||||||
the solaris 2.6-supplied ftp server it works with spaces in the file names.
|
|
||||||
|
|
||||||
Daniel (27 December 1999):
|
|
||||||
- When curl parsed cookies straight off a remote site, it corrupted the input
|
|
||||||
data, which, if the downloaded headers were stored made very odd characters
|
|
||||||
in the saved data. Correctly identified and reported by Paul Harrington.
|
|
||||||
|
|
||||||
Daniel (13 December 1999):
|
|
||||||
- General cleanups in the library interface. There had been some bad kludges
|
|
||||||
added during times of stress and I did my best to clean them off. It was
|
|
||||||
both regarding the lib API as well as include file confusions.
|
|
||||||
|
|
||||||
Daniel (3 December 1999):
|
|
||||||
- A small --stderr bug was reported by Eetu Ojanen...
|
|
||||||
|
|
||||||
- who also brought the suggestion of extending the -X flag to ftp list as
|
|
||||||
well. So, now it is and the long option is now --request instead. It is
|
|
||||||
only for ftp list for now (and the former http stuff too of course).
|
|
||||||
|
|
||||||
Lars J. Aas (24 November 1999):
|
|
||||||
- Patched curl to compile and build under BeOS. Doesn't work yet though!
|
|
||||||
|
|
||||||
- Corrected the Makefile.am files to allow putting object files in
|
|
||||||
different directories than the sources.
|
|
||||||
|
|
||||||
Version 6.3.1
|
|
||||||
|
|
||||||
Daniel (23 November 1999):
|
|
||||||
- I've had this major disk crash. My good old trust-worthy source disk died
|
|
||||||
along with the machine that hosted it. Thank goodness most of all the
|
|
||||||
things I've done are either backed up elsewhere or stored in this CVS
|
|
||||||
server!
|
|
||||||
|
|
||||||
- Michael S. Steuer pointed out a bug in the -F handling
|
|
||||||
that made curl hang if you posted an empty variable such as '-F name='. It
|
|
||||||
was one of those old bugs that never have worked properly...
|
|
||||||
|
|
||||||
- Jason Baietto pointed out a general flaw in the HTTP
|
|
||||||
download. Curl didn't complain if it was prematurely aborted before the
|
|
||||||
entire download was completed. It does now.
|
|
||||||
|
|
||||||
Daniel (19 November 1999):
|
|
||||||
- Chris Maltby very accurately criticized the lack of
|
|
||||||
return code checks on the fwrite() calls. I did a thorough check for all
|
|
||||||
occurrences and corrected this.
|
|
||||||
|
|
||||||
Daniel (17 November 1999):
|
|
||||||
- Paul Harrington pointed out that the -m/--max-time option
|
|
||||||
doesn't work for the slow system calls like gethostbyname()... I don't have
|
|
||||||
any good fix yet, just a slightly less bad one that makes curl exit hard
|
|
||||||
when the timeout is reached.
|
|
||||||
|
|
||||||
- Bjorn Reese helped me point out a possible problem that might be the reason
|
|
||||||
why Thomas Hurst experience problems in his Amiga version.
|
|
||||||
|
|
||||||
Daniel (12 November 1999):
|
|
||||||
- I found a crash in the new cookie file parser. It crashed when you gave
|
|
||||||
a plain http header file as input...
|
|
||||||
|
|
||||||
Version 6.3
|
|
||||||
|
|
||||||
Daniel (10 November 1999):
|
|
||||||
- I kind of found out that the HTTP time-conditional GETs (-z) aren't always
|
|
||||||
respected by the web server and the document is therefore sent in whole
|
|
||||||
again, even though it doesn't match the requested condition. After reading
|
|
||||||
section 13.3.4 of RFC 2616, I think I'm doing the right thing now when I do
|
|
||||||
my own check as well. If curl thinks the condition isn't met, the transfer
|
|
||||||
is aborted prematurely (after all the headers have been received).
|
|
||||||
|
|
||||||
- After comments from Robert Linden I also rewrote some parts of the man page
|
|
||||||
to better describe how the -F works.
|
|
||||||
|
|
||||||
- Michael Anti put up a new curl download mirror in
|
|
||||||
China: http://www.pshowing.com/curl/
|
|
||||||
|
|
||||||
- I added the list of download mirrors to the README file
|
|
||||||
|
|
||||||
- I did add more explanations to the man page
|
|
||||||
|
|
||||||
Daniel (8 November 1999):
|
|
||||||
- I made the -b/--cookie option capable of reading netscape formatted cookie
|
|
||||||
files as well as normal http-header files. It should be able to
|
|
||||||
transparently figure out what kind of file it got as input.
|
|
||||||
|
|
||||||
Daniel (29 October 1999):
|
|
||||||
- Another one of Sebastiaan van Erk's ideas (that has been requested before
|
|
||||||
but I seem to have forgotten who it was), is to add support for ranges in
|
|
||||||
FTP downloads. As usual, one request is just a request, when they're two
|
|
||||||
it is a demand. I've added simple support for X-Y style fetches. X has to
|
|
||||||
be the lower number, though you may omit one of the numbers. Use the -r/
|
|
||||||
--range switch (previously HTTP-only).
|
|
||||||
|
|
||||||
- Sebastiaan van Erk suggested that curl should be
|
|
||||||
able to show the file size of a specified file. I think this is a splendid
|
|
||||||
idea and the -I flag is now working for FTP. It displays the file size in
|
|
||||||
this manner:
|
|
||||||
Content-Length: XXXX
|
|
||||||
As it resembles normal headers, and leaves us the opportunity to add more
|
|
||||||
info in that display if we can come up with more in the future! It also
|
|
||||||
makes sense since if you access ftp through a HTTP proxy, you'd get the
|
|
||||||
file size the same way.
|
|
||||||
|
|
||||||
I changed the order of the QUOTE command executions. They're now executed
|
|
||||||
just after the login and before any other command. I made this to enable
|
|
||||||
quote commands to run before the -I stuff is done too.
|
|
||||||
|
|
||||||
- I found out that -D/--dump-header and -V/--version weren't documented in
|
|
||||||
the man page.
|
|
||||||
|
|
||||||
- Many HTTP/1.1 servers do not support ranges. Don't ask me why. I did add
|
|
||||||
some text about this in the man page for the range option. The thread in
|
|
||||||
the mailing list that started this was initiated by Michael Anti.
|
|
||||||
|
|
||||||
- I get reports about nroff crashes on solaris 2.6+ when displaying the curl
|
|
||||||
man page. Switch to gnroff instead, it is reported to work(!). Adam Barclay
|
|
||||||
reported and brought the suggestion.
|
|
||||||
|
|
||||||
- In a dialogue with Johannes G. Kristinsson we came
|
|
||||||
up with the idea to let -H/--header specified headers replace the
|
|
||||||
internally generated headers, if you happened to select to add a header
|
|
||||||
that curl normally uses by itself. The advantage with this is not entirely
|
|
||||||
obvious, but in Johannes' case it means that he can use another Host: than
|
|
||||||
the one curl would set.
|
|
||||||
|
|
||||||
Daniel (27 October 1999):
|
|
||||||
- Jongki Suwandi brought a nice patch for (yet another) crash when following
|
|
||||||
a location:. This time you had to follow a https:// server's redirect to
|
|
||||||
get the core.
|
|
||||||
|
|
||||||
Version 6.2
|
|
||||||
|
|
||||||
Daniel (21 October 1999):
|
|
||||||
- I think I managed to remove the suspicious (nil) that has been seen just
|
|
||||||
before the "Host:" in HTTP requests when -v was used.
|
|
||||||
- I found out that if you followed a location: when using a proxy, without
|
|
||||||
having specified http:// in the URL, the protocol part was added once again
|
|
||||||
when moving to the next URL! (The protocol part has to be added to the
|
|
||||||
URL when going through a proxy since it has no protocol-guessing system
|
|
||||||
such as curl has.)
|
|
||||||
- Benjamin Ritcey reported a core dump under solaris 2.6
|
|
||||||
with OpenSSL 0.9.4. It turned out this was due to a bad free() in main.c
|
|
||||||
that occurred after the download was done and completed.
|
|
||||||
- Benjamin found ftp downloads to show the first line of the download meter
|
|
||||||
to get written twice, and I removed that problem. It was introduced with
|
|
||||||
the multiple URL support.
|
|
||||||
- Dan Zitter correctly pointed out that curl 6.1 and earlier versions didn't
|
|
||||||
honor RFC 2616 chapter 4 section 2, "Message Headers": "...Field names are
|
|
||||||
case-insensitive..." HTTP header parsing assumed a certain casing. Dan
|
|
||||||
also provided me with a patch that corrected this, which I took the liberty
|
|
||||||
of editing slightly.
|
|
||||||
- Dan Zitter also provided a nice patch for config.guess to better recognize
|
|
||||||
the Mac OS X
|
|
||||||
- Dan also corrected a minor problem in the lib/Makefile that caused linking
|
|
||||||
to fail on OS X.
|
|
||||||
|
|
||||||
Daniel (19 October 1999):
|
|
||||||
- Len Marinaccio came up with some problems with curl. Since Windows has a
|
|
||||||
crippled shell, it can't redirect stderr and that causes trouble. I added
|
|
||||||
--stderr today which allows the user to redirect the stderr stream to a
|
|
||||||
file or stdout.
|
|
||||||
|
|
||||||
Daniel (18 October 1999):
|
|
||||||
- The configure script now understands the '--without-ssl' flag, which now
|
|
||||||
totally disable SSL/https support. Previously it wasn't possible to force
|
|
||||||
the configure script to leave SSL alone. The previous functionality has
|
|
||||||
been retained. Troy Engel helped test this new one.
|
|
||||||
|
|
||||||
Version 6.1
|
|
||||||
|
|
||||||
Daniel (17 October 1999):
|
|
||||||
- I ifdef'ed or commented all the zlib stuff in the sources and configure
|
|
||||||
script. It turned out we needed to mock more with zlib than I initially
|
|
||||||
thought, to make it capable of downloading compressed HTTP documents and
|
|
||||||
uncompress them on the fly. I didn't mean the zlib parts of curl to become
|
|
||||||
more than minor so this means I halt the zlib expedition for now and wait
|
|
||||||
until someone either writes the code or zlib gets updated and better
|
|
||||||
adjusted for this kind of usage. I won't get into details here, but a
|
|
||||||
short a summary is suitable:
|
|
||||||
- zlib can't automatically detect whether to use zlib or gzip
|
|
||||||
decompression methods.
|
|
||||||
- zlib is very neat for reading gzipped files from a file descriptor,
|
|
||||||
although not as nice for reading buffer-based data such as we would
|
|
||||||
want it.
|
|
||||||
- there are still some problems with the win32 version when reading from
|
|
||||||
a file descriptor if that is a socket
|
|
||||||
|
|
||||||
Daniel (14 October 1999):
|
|
||||||
- Moved the (external) include files for libcurl into a subdirectory named
|
|
||||||
curl and adjusted all #include lines to use <curl/XXXX> to maintain a
|
|
||||||
better name space and control of the headers. This has been requested.
|
|
||||||
|
|
||||||
Daniel (12 October 1999):
|
|
||||||
- I modified the 'maketgz' script to perform a 'make' too before a release
|
|
||||||
archive is put together in an attempt to make the time stamps better and
|
|
||||||
hopefully avoid the double configure-running that use to occur.
|
|
||||||
|
|
||||||
Daniel (11 October 1999):
|
|
||||||
- Applied J<>rn's patches that fixes zlib for mingw32 compiles as well as
|
|
||||||
some other missing zlib #ifdef and more text on the multiple URL docs in
|
|
||||||
the man page.
|
|
||||||
|
|
||||||
Version 6.1beta
|
|
||||||
|
|
||||||
Daniel (6 October 1999):
|
|
||||||
- Douglas E. Wegscheid sent me a patch that made the exact same thing as I
|
|
||||||
just made: the -d switch is now capable of reading post data from a named
|
|
||||||
file or stdin. Use it similarly to the -F. To read the post data from a
|
|
||||||
given file:
|
|
||||||
|
|
||||||
curl -d @path/to/filename www.postsite.com
|
|
||||||
|
|
||||||
or let curl read it out from stdin:
|
|
||||||
|
|
||||||
curl -d @- www.postit.com
|
|
||||||
|
|
||||||
J<>rn Hartroth (3 October 1999):
|
|
||||||
- Brought some more patches for multiple URL functionality. The MIME
|
|
||||||
separation ideas are almost scrapped now, and a custom separator is being
|
|
||||||
used instead. This is still compile-time "flagged".
|
|
||||||
|
|
||||||
Daniel
|
|
||||||
- Updated curl.1 with multiple URL info.
|
|
||||||
|
|
||||||
Daniel (30 September 1999):
|
|
||||||
- Felix von Leitner brought openssl-check fixes for configure.in to work
|
|
||||||
out-of-the-box when the openssl files are installed in the system default
|
|
||||||
dirs.
|
|
||||||
|
|
||||||
Daniel (28 September 1999)
|
|
||||||
- Added libz functionality. This should enable decompressing gzip, compress
|
|
||||||
or deflate encoding HTTP documents. It also makes curl send an accept that
|
|
||||||
it accepts that kind of encoding. Compressed contents usually shortens
|
|
||||||
download time. I *need* someone to tell me a site that uses compressed HTTP
|
|
||||||
documents so that I can test this out properly.
|
|
||||||
|
|
||||||
- As a result of the adding of zlib awareness, I changed the version string
|
|
||||||
a little. I plan to add openldap version reporting in there too.
|
|
||||||
|
|
||||||
Daniel (17 September 1999)
|
|
||||||
- Made the -F option allow stdin when specifying files. By using '-' instead
|
|
||||||
of file name, the data will be read from stdin.
|
|
||||||
|
|
||||||
Version 6.0
|
|
||||||
|
|
||||||
Daniel (13 September 1999)
|
|
||||||
- Added -X/--http-request <request> to enable any HTTP command to be sent.
|
|
||||||
Do not that your server has to support the exact string you enter. This
|
|
||||||
should possibly a string like DELETE or TRACE.
|
|
||||||
|
|
||||||
- Applied Douglas' mingw32-fixes for the makefiles.
|
|
||||||
|
|
||||||
Daniel (10 September 1999)
|
|
||||||
- Douglas E. Wegscheid pointed out a problem. Curl didn't check the FTP
|
|
||||||
servers return code properly after the --quote commands were issued. It
|
|
||||||
took anything non 200 as an error, when all 2XX codes should be accepted as
|
|
||||||
OK.
|
|
||||||
|
|
||||||
- Sending cookies to the same site in multiple lines like curl used to do
|
|
||||||
turned out to be bad and breaking the cookie specs. Curl now sends all
|
|
||||||
cookies on a single Cookie: line. Curl is not yet RFC 2109 compliant, but I
|
|
||||||
doubt that many servers do use that syntax (yet).
|
|
||||||
|
|
||||||
Daniel (8 September 1999)
|
|
||||||
- J<>rn helped me make sure it still compiles nicely with mingw32 under win32.
|
|
||||||
|
|
||||||
Daniel (7 September 1999)
|
|
||||||
- FTP upload through proxy is now turned into a HTTP PUT. Requested by
|
|
||||||
Stefan Kanthak.
|
|
||||||
|
|
||||||
- Added the ldap files to the .m32 makefile.
|
|
||||||
|
|
||||||
Daniel (3 September 1999)
|
|
||||||
- Made cookie matching work while using HTTP proxy.
|
|
||||||
|
|
||||||
Bjorn Reese (31 August 1999)
|
|
||||||
- Passed his ldap:// patch. Note that this requires the openldap shared
|
|
||||||
library to be installed and that LD_LIBRARY_PATH points to the
|
|
||||||
directory where the lib will be found when curl is run with a
|
|
||||||
ldap:// URL.
|
|
||||||
|
|
||||||
J<>rn Hartroth (31 August 1999)
|
|
||||||
- Made the Mingw32 makefiles into single files.
|
|
||||||
- Made file:// work for Win32. The same code is now used for unix as well for
|
|
||||||
performance reasons.
|
|
||||||
|
|
||||||
Douglas E. Wegscheid (30 August 1999)
|
|
||||||
- Patched the Mingw32 makefiles for SSL builds.
|
|
||||||
|
|
||||||
Matthew Clarke (30 August 1999)
|
|
||||||
- Made a cool patch for configure.in to allow --with-ssl to specify the
|
|
||||||
root dir of the openssl installation, as in
|
|
||||||
|
|
||||||
./configure --with-ssl=/usr/ssl_here
|
|
||||||
|
|
||||||
- Corrected the 'reconf' script to work better with some shells.
|
|
||||||
|
|
||||||
J<>rn Hartroth (26 August 1999)
|
|
||||||
- Fixed the Mingw32 makefiles in lib/ and corrected the file.c for win32
|
|
||||||
compiles.
|
|
||||||
|
|
||||||
Version 5.11
|
|
||||||
|
|
||||||
Daniel (25 August 1999)
|
|
||||||
- John Weismiller pointed out a bug in the header-line
|
|
||||||
realloc() system in download.c.
|
|
||||||
|
|
||||||
- I added lib/file.[ch] to offer a first, simple, file:// support. It
|
|
||||||
probably won't do much good on win32 system at this point, but I see it
|
|
||||||
as a start.
|
|
||||||
|
|
||||||
- Made the release archives get a Makefile in the root dir, which can be
|
|
||||||
used to start the compiling/building process easier. I haven't really
|
|
||||||
changed any INSTALL text yet, I wanted to get some feed-back on this
|
|
||||||
first.
|
|
||||||
|
|
||||||
Daniel (17 August 1999)
|
|
||||||
- Another Location: bug. Curl didn't do proper relative locations if the
|
|
||||||
original URL had cgi-parameters that contained a slash. Nusu's page
|
|
||||||
again.
|
|
||||||
|
|
||||||
- Corrected the NO_PROXY usage. It is a list of substrings that if one of
|
|
||||||
them matches the tail of the host name it should connect to, curl should
|
|
||||||
not use a proxy to connect there. Pointed out to me by Douglas
|
|
||||||
E. Wegscheid. I also changed the README text a little regarding this.
|
|
||||||
|
|
||||||
Daniel (16 August 1999)
|
|
||||||
- Fixed a memory bug with http-servers that sent Location: to a Location:
|
|
||||||
page. Nusu's page showed this too.
|
|
||||||
|
|
||||||
- Made cookies work a lot better. Setting the same cookie name several times
|
|
||||||
used to add more cookies instead of replacing the former one which it
|
|
||||||
should've. Nusu <nus at intergorj.ro> brought me an URL that made this
|
|
||||||
painfully visible...
|
|
||||||
|
|
||||||
Troy (15 August 1999)
|
|
||||||
- Brought new .spec files as well as a patch for configure.in that lets the
|
|
||||||
configure script find the openssl files better, even when the include
|
|
||||||
files are in /usr/include/openssl
|
|
||||||
|
|
||||||
Version 5.10
|
|
||||||
|
|
||||||
Daniel (13 August 1999)
|
|
||||||
- SSL_CTX_set_default_passwd_cb() has been modified in the 0.9.4 version of
|
|
||||||
OpenSSL. Now why couldn't they simply add a *new* function instead of
|
|
||||||
modifying the parameters of an already existing function? This way, we get
|
|
||||||
a compiler warning if compiling with 0.9.4 but not with earlier. So, I had
|
|
||||||
to come up with a #if construction that deals with this...
|
|
||||||
|
|
||||||
- Made curl output the SSL version number get displayed properly with 0.9.4.
|
|
||||||
|
|
||||||
Troy (12 August 1999)
|
|
||||||
- Added MingW32 (GCC-2.95) support under Win32. The INSTALL file was also
|
|
||||||
a bit rearranged.
|
|
||||||
|
|
||||||
Daniel (12 August 1999)
|
|
||||||
- I had to copy a good <arpa/telnet.h> include file into the curl source
|
|
||||||
tree to enable the silly win32 systems to compile. The distribution rights
|
|
||||||
allows us to do that as long as the file remains unmodified.
|
|
||||||
|
|
||||||
- I corrected a few minor things that made the compiler complain when
|
|
||||||
-Wall -pedantic was used.
|
|
||||||
|
|
||||||
- I'm moving the official curl web page to http://curl.haxx.nu. I think it
|
|
||||||
will make it easier to remember as it is a lot shorter and less cryptic.
|
|
||||||
The old one still works and shows the same info.
|
|
||||||
|
|
||||||
Daniel (11 August 1999)
|
|
||||||
- Albert Chin-A-Young mailed me another correction for NROFF in the
|
|
||||||
configure.in that is supposed to be better for IRIX users.
|
|
||||||
|
|
||||||
Daniel (10 August 1999)
|
|
||||||
- Albert Chin-A-Young helped me with some stupid Makefile things, as well as
|
|
||||||
some fiddling with the getdate.c stuff that he had problems with under
|
|
||||||
HP-UX v10. getdate.y will now be compiled into getdate.c if the appropriate
|
|
||||||
yacc or bison is found by the configure script. Since this is slightly new,
|
|
||||||
we need to test the output getdate.c with win32 systems to make sure it
|
|
||||||
still compiles there.
|
|
||||||
|
|
||||||
Daniel (5 August 1999)
|
|
||||||
- I've just setup a new mailing list with the intention to keep discussions
|
|
||||||
around libcurl development in it. I mainly expect it to be for thoughts and
|
|
||||||
brainstorming around a "next generation" library, rather than nitpicking
|
|
||||||
about the current implementation or details in the current libcurl.
|
|
||||||
|
|
||||||
To join our happy bunch of future-looking geeks, enter 'subscribe
|
|
||||||
<address>' in the body of a mail and send it to
|
|
||||||
libcurl-request@listserv.fts.frontec.se. Curl bug reports, the usual curl
|
|
||||||
talk and everything else should still be kept in this mailing list. I've
|
|
||||||
started to archive this mailing list and have put the libcurl web page at
|
|
||||||
www.fts.frontec.se/~dast/libcurl/.
|
|
||||||
|
|
||||||
- Stefan Kanthak contacted me regarding a few problems in the configure
|
|
||||||
script which he discovered when trying to make curl compile and build under
|
|
||||||
Siemens SINIX-Z V5.42B2004!
|
|
||||||
|
|
||||||
- Marcus Klein very accurately informed me that src/version.h was not present
|
|
||||||
in the CVS repository. Oh, how silly...
|
|
||||||
|
|
||||||
- Linus Nielsen rewrote the telnet:// part and now curl offers limited telnet
|
|
||||||
support. If you run curl like 'curl telnet://host' you'll get all output on
|
|
||||||
the screen and curl will read input from stdin. You'll be able to login and
|
|
||||||
run commands etc, but since the output is buffered, expect to get a little
|
|
||||||
weird output.
|
|
||||||
|
|
||||||
This is still in its infancy and it might get changed. We need your
|
|
||||||
feed-back and input in how this is best done.
|
|
||||||
|
|
||||||
WIN32 NOTE: I bet we'll get problems when trying to compile the current
|
|
||||||
lib/telnet.c on win32, but I think we can sort them out in time.
|
|
||||||
|
|
||||||
- David Sanderson reported that FORCE_ALLOCA_H or HAVE_ALLOCA_H must be
|
|
||||||
defined for getdate.c to compile properly on HP-UX 11.0. I updated the
|
|
||||||
configure script to check for alloca.h which should make it.
|
|
||||||
|
|
||||||
Daniel (4 August 1999)
|
|
||||||
- I finally got to understand Marcus Klein's ftp download resume problem,
|
|
||||||
which turns out to be due to different outputs from different ftp
|
|
||||||
servers. It makes ftp download resuming a little trickier, but I've made
|
|
||||||
some modifications I really believe will work for most ftp servers and I do
|
|
||||||
hope you report if you have problems with this!
|
|
||||||
|
|
||||||
- Added text about file transfer resuming to README.curl.
|
|
||||||
|
|
||||||
Daniel (2 August 1999)
|
|
||||||
- Applied a progress-bar patch from Lars J. Aas. It offers
|
|
||||||
a new styled progress bar enabled with -#/--progress-bar.
|
|
||||||
|
|
||||||
T. Yamada <tai at imasy.or.jp> (30 July 1999)
|
|
||||||
- It breaks with segfault when 1) curl is using .netrc to obtain
|
|
||||||
username/password (option '-n'), and 2) is automatically redirected to
|
|
||||||
another location (option '-L').
|
|
||||||
|
|
||||||
There is a small bug in lib/url.c (block starting from line 641), which
|
|
||||||
tries to take out username/password from user- supplied command-line
|
|
||||||
argument ('-u' option). This block is never executed on first attempt since
|
|
||||||
CONF_USERPWD bit isn't set at first, but curl later turns it on when it
|
|
||||||
checks for CONF_NETRC bit. So when curl tries to redo everything due to
|
|
||||||
redirection, it segfaults trying to access *data->userpwd.
|
|
||||||
|
|
||||||
Version 5.9.1
|
|
||||||
|
|
||||||
Daniel (30 July 1999)
|
|
||||||
- Steve Walch pointed out that there is a memory leak in the formdata
|
|
||||||
functions. I added a FormFree() function that is now used and supposed to
|
|
||||||
correct this flaw.
|
|
||||||
|
|
||||||
- Mark Wotton reported:
|
|
||||||
'curl -L https://www.cwa.com.au/' core dumps. I managed to cure this by
|
|
||||||
correcting the cleanup procedure. The bug seems to be gone with my OpenSSL
|
|
||||||
0.9.2b, although still occurs when I run the ~100 years old SSLeay 0.8.0. I
|
|
||||||
don't know whether it is curl or SSLeay that is to blame for that.
|
|
||||||
|
|
||||||
- Marcus Klein:
|
|
||||||
Reported an FTP upload resume bug that I really can't repeat nor understand.
|
|
||||||
I leave it here so that it won't be forgotten.
|
|
||||||
|
|
||||||
Daniel (29 July 1999)
|
|
||||||
- Costya Shulyupin suggested support for longer URLs when following Location:
|
|
||||||
and I could only agree and fix it!
|
|
||||||
|
|
||||||
- Leigh Purdie found a problem in the upload/POST department. It turned out
|
|
||||||
that http.c accidentaly cleared the pointer instead of the byte counter
|
|
||||||
when supposed to.
|
|
||||||
|
|
||||||
- Costya Shulyupin pointed out a problem with port numbers and Location:. If
|
|
||||||
you had a server at a non-standard port that redirected to an URL using a
|
|
||||||
standard port number, curl still used that first port number.
|
|
||||||
|
|
||||||
- Ralph Beckmann pointed out a problem when using both CONF_FOLLOWLOCATION
|
|
||||||
and CONF_FAILONERROR simultaneously. Since the CONF_FAILONERROR exits on
|
|
||||||
the 302-code that the follow location header outputs it will never show any
|
|
||||||
html on location: pages. I have now made it look for >=400 codes if
|
|
||||||
CONF_FOLLOWLOCATION is set.
|
|
||||||
|
|
||||||
- 'struct slist' is now renamed to 'struct curl_slist' (as suggested by Ralph
|
|
||||||
Beckmann).
|
|
||||||
|
|
||||||
- Joshua Swink and Rick Welykochy were the first to point out to me that the
|
|
||||||
latest OpenSSL package now have moved the standard include path. It is now
|
|
||||||
in /usr/local/ssl/include/openssl and I have now modified the --enable-ssl
|
|
||||||
option for the configure script to use that as the primary path, and I
|
|
||||||
leave the former path too to work with older packages of OpenSSL too.
|
|
||||||
|
|
||||||
Daniel (9 June 1999)
|
|
||||||
- I finally understood the IRIX problem and now it seem to compile on it!
|
|
||||||
I am gonna remove those #define strcasecmp() things once and for all now.
|
|
||||||
|
|
||||||
Daniel (4 June 1999)
|
|
||||||
- I adjusted the FTP reply 227 parser to make the PASV command work better
|
|
||||||
with more ftp servers. Appearantly the Roxen Challanger server replied
|
|
||||||
something curl 5.9 could deal with! :-( Reported by Ashley Reid-Montanaro
|
|
||||||
and Mark Butler brought a solution for it.
|
|
||||||
|
|
||||||
Daniel (26 May 1999)
|
|
||||||
- Rearranged. README is new, the old one is now README.curl and I added a
|
|
||||||
README.libcurl with text I got from Ralph Beckmann.
|
|
||||||
|
|
||||||
- I also updated the INSTALL text.
|
|
||||||
|
|
||||||
Daniel (25 May 1999)
|
|
||||||
- David Jonathan Lowsky correctly pointed out that curl didn't properly deal
|
|
||||||
with form posting where the variable shouldn't have any content, as in curl
|
|
||||||
-F "form=" www.site.com. It was now fixed.
|
|
||||||
|
|
||||||
Version 5.9
|
|
||||||
|
|
||||||
Daniel (22 May 1999)
|
|
||||||
- I've got a bug report from Aaron Scarisbrick in which he states he has some
|
|
||||||
problems with -L under FreeBSD 3.0. I have previously got another bug
|
|
||||||
report from Stefan Grether which points at an error with similar sympthoms
|
|
||||||
when using win32. I made the allocation of the new url string a bit faster
|
|
||||||
and different, don't know if it actually improves anything though...
|
|
||||||
|
|
||||||
Daniel (20 May 1999)
|
|
||||||
- Made the cookie parser deal with CRLF newlines too.
|
|
||||||
|
|
||||||
Daniel (19 May 1999)
|
|
||||||
- Download() didn't properly deal with failing return codes from the sread()
|
|
||||||
function. Adam Coyne found the problem in the win32 version, and Troy Engel
|
|
||||||
helped me out isolating it.
|
|
||||||
|
|
||||||
Daniel (16 May 1999)
|
|
||||||
- Richard Adams pointed out a bug I introduced in 5.8. --dump-header doesn't
|
|
||||||
work anymore! :-/ I fixed it now.
|
|
||||||
|
|
||||||
- After a suggestion by Joshua Swink I added -S / --show-error to force curl
|
|
||||||
to display the error message in case of an error, even if -s/--silent was
|
|
||||||
used.
|
|
||||||
|
|
||||||
Daniel (10 May 1999)
|
|
||||||
- I moved the stuff concerning HTTP, DICT and TELNET it their own source
|
|
||||||
files now. It is a beginning on my clean-up of the sources to make them
|
|
||||||
layer all those protocols better to enable more to be added easier in the
|
|
||||||
future!
|
|
||||||
|
|
||||||
- Leon Breedt sent me some files I've not put into the main curl
|
|
||||||
archive. They're for creating the Debian package thingie. He also sent me a
|
|
||||||
debian package that I've made available for download at the web page
|
|
||||||
|
|
||||||
Daniel (9 May 1999)
|
|
||||||
- Made it compile on cygwin too.
|
|
||||||
|
|
||||||
Troy Engel (7 May 1999)
|
|
||||||
- Brought a series of patches to allow curl to compile smoothly on MSVC++ 6
|
|
||||||
again!
|
|
||||||
|
|
||||||
Daniel (6 May 1999)
|
|
||||||
- I changed the #ifdef HAVE_STRFTIME placement for the -z code so that it
|
|
||||||
will be easier to discover systems that don't have that function and thus
|
|
||||||
can't use -z successfully. Made the strftime() get used if WIN32 is defined
|
|
||||||
too.
|
|
||||||
|
|
||||||
Version 5.8
|
|
||||||
|
|
||||||
Daniel (5 May 1999)
|
|
||||||
- I've had it with this autoconf/automake mess. It seems to work allright
|
|
||||||
for most people who don't have automake installed, but for those who have
|
|
||||||
there are problems all over.
|
|
||||||
|
|
||||||
I've got like five different bug reports on this only the last
|
|
||||||
week... Claudio Neves and Federico Bianchi and root <duggerj001 at
|
|
||||||
hawaii.rr.com> are some of them reporting this.
|
|
||||||
|
|
||||||
Currently, I have no really good fix since I want to use automake myself to
|
|
||||||
generate the Makefile.in files. I've found out that the @SHELL@-problems
|
|
||||||
can often be fixed by manually invoking 'automake' in the archive root
|
|
||||||
before you run ./configure... I've hacked my maketgz script now to fiddle
|
|
||||||
a bit with this and my tests seem to work better than before at least!
|
|
||||||
|
|
||||||
Daniel (4 May 1999)
|
|
||||||
- mkhelp.pl has been doing badly lately. I corrected a case problem in
|
|
||||||
the regexes.
|
|
||||||
|
|
||||||
- I've now remade the -o option to not touch the file unless it needs to.
|
|
||||||
I had to do this to make -z option really fine, since now you can make a
|
|
||||||
curl fetch and use a local copy's time when downloading to that file, as
|
|
||||||
in:
|
|
||||||
|
|
||||||
curl -z dump -o dump remote.site.com/file.html
|
|
||||||
|
|
||||||
This will only get the file if the remote one is newer than the local.
|
|
||||||
I'm aware that this alters previous behaviour a little. Some scripts out
|
|
||||||
there may depend on that the file is always touched...
|
|
||||||
|
|
||||||
- Corrected a bug in the SSLv2/v3 selection.
|
|
||||||
|
|
||||||
- Felix von Leitner requested that curl should be able to send
|
|
||||||
"If-Modified-Since" headers, which indeed is a fair idea. I implemented it
|
|
||||||
right away! Try -z <expression> where expression is a full GNU date
|
|
||||||
expression or a file name to get the date from!
|
|
||||||
|
|
||||||
Stephan Lagerholm (30 Apr 1999)
|
|
||||||
- Pointed out a problem with the src/Makefile for FreeBSD. The RM variable
|
|
||||||
isn't set and causes the make to fail.
|
|
||||||
|
|
||||||
Daniel (26 April 1999)
|
|
||||||
- Am I silly or what? Irving Wolfe pointed out to me that the curl version
|
|
||||||
number was not set properly. Hasn't been since 5.6. This was due to a bug
|
|
||||||
in my maketgz script!
|
|
||||||
|
|
||||||
David Eriksson (25 Apr 1999)
|
|
||||||
- Found a bug in cookies.c that made it crash at times.
|
|
||||||
|
|
||||||
Version 5.7.1
|
|
||||||
|
|
||||||
Doug Kaufman (23 Apr 1999)
|
|
||||||
- Brought two sunos 4 fixes. One of them being the hostip.c fix mentioned
|
|
||||||
below and the other one a correction in include/stdcheaders.h
|
|
||||||
|
|
||||||
- Added a paragraph about compiling with the US-version of openssl to the
|
|
||||||
INSTALL file.
|
|
||||||
|
|
||||||
Daniel
|
|
||||||
- New mailing list address. Info updated on the web page as well as in the
|
|
||||||
README file
|
|
||||||
|
|
||||||
Greg Onufer (20 Apr 1999)
|
|
||||||
- hostip.c didn't compile properly on SunOS 5.5.1.
|
|
||||||
It needs an #include <sys/types.h>
|
|
||||||
|
|
||||||
Version 5.7
|
|
||||||
|
|
||||||
Daniel (Apr 20 1999)
|
|
||||||
- Decided to upload a non-beta version right now!
|
|
||||||
|
|
||||||
- Made curl support any-length HTTP headers. The destination buffer is now
|
|
||||||
simply enlarged every time it turns out to be too small!
|
|
||||||
|
|
||||||
- Added the FAQ file to the archive. Still a bit smallish, but it is a
|
|
||||||
start.
|
|
||||||
|
|
||||||
Eric Thelin (15 Apr 1999)
|
|
||||||
- Made -D accept '-' instead of filename to write to stdout.
|
|
||||||
|
|
||||||
Version 5.6.3beta
|
|
||||||
|
|
||||||
Daniel (Apr 12 1999)
|
|
||||||
|
|
||||||
- Changed two #ifdef WIN32 to better #ifdef <errorcode> when connect()ing
|
|
||||||
in url.c and ftp.c. Makes cygwin32 deal with them better too. We should
|
|
||||||
try to get some decent win32-replacement there. Anyone?
|
|
||||||
|
|
||||||
- The old -3/--crlf option is now ONLY --crlf!
|
|
||||||
|
|
||||||
- I changed the "SSL fix" to a more lame one, but that doesn't remove as
|
|
||||||
much functionality. Now I've enabled the lib to select what SSL version it
|
|
||||||
should try first. Appearantly some older SSL-servers don't like when you
|
|
||||||
talk v3 with them so you need to be able to force curl to talk v2 from the
|
|
||||||
start. The fix dated April 6 and posted on the mailing list forced curl to
|
|
||||||
use v2 at all times using a modern OpenSSL version, but we don't really
|
|
||||||
want such a crippled solution.
|
|
||||||
|
|
||||||
- Marc Boucher sent me a patch that corrected a math error for the
|
|
||||||
"Curr.Speed" progress meter.
|
|
||||||
|
|
||||||
- Eric Thelin sent me a patch that enables '-K -' to read a config file from
|
|
||||||
stdin.
|
|
||||||
|
|
||||||
- I found out we didn't close the file properly before so I added it!
|
|
||||||
|
|
||||||
Daniel (Apr 9 1999)
|
|
||||||
- Yu Xin pointed out a problem with ftp download resume. It didn't work at
|
|
||||||
all! ;-O
|
|
||||||
|
|
||||||
Daniel (Apr 6 1999)
|
|
||||||
- Corrected the version string part generated for the SSL version.
|
|
||||||
|
|
||||||
- I found a way to make some other SSL page work with openssl 0.9.1+ that
|
|
||||||
previously didn't (ssleay 0.8.0 works with it though!). Trying to get
|
|
||||||
some real info from the OpenSSL guys to see how I should do to behave the
|
|
||||||
best way. SSLeay 0.8.0 shouldn't be that much in use anyway these days!
|
|
||||||
|
|
||||||
Version 5.6.2beta
|
|
||||||
|
|
||||||
Daniel (Apr 4 1999)
|
|
||||||
- Finally have curl more cookie "aware". Now read carefully. This is how
|
|
||||||
it works.
|
|
||||||
To make curl read cookies from an already existing file, in plain header-
|
|
||||||
format (like from the headers of a previous fetch) invoke curl with the
|
|
||||||
-b flag like:
|
|
||||||
|
|
||||||
curl -b file http://site/foo.html
|
|
||||||
|
|
||||||
Curl will then use all cookies it finds matching. The old style that sets
|
|
||||||
a single cookie with -b is still supported and is used if the string
|
|
||||||
following -b includes a '=' letter, as in "-b name=daniel".
|
|
||||||
|
|
||||||
To make curl read the cookies sent in combination with a location: (which
|
|
||||||
sites often do) point curl to read a non-existing file at first (i.e
|
|
||||||
to start with no existing cookies), like:
|
|
||||||
|
|
||||||
curl -b nowhere http://site/setcookieandrelocate.html
|
|
||||||
|
|
||||||
- Added a paragraph in the TODO file about the SSL problems recently
|
|
||||||
reported. Evidently, some kind of SSL-problem curl may need to address.
|
|
||||||
|
|
||||||
- Better "Location:" following.
|
|
||||||
|
|
||||||
Douglas E. Wegscheid (Tue, 30 Mar 1999)
|
|
||||||
- A subsecond display patch.
|
|
||||||
|
|
||||||
Daniel (Mar 14 1999)
|
|
||||||
- I've separated the version number of libcurl and curl now. To make
|
|
||||||
things a little easier, I decided to start the curl numbering from
|
|
||||||
5.6 and the former version number known as "curl" is now the one
|
|
||||||
set for libcurl.
|
|
||||||
|
|
||||||
- Removed the 'enable-no-pass' from configure, I doubt anyone wanted
|
|
||||||
that.
|
|
||||||
|
|
||||||
- Made lots of tiny adjustments to compile smoothly with cygwin under
|
|
||||||
win32. It's a killer for porting this to win32, bye bye VC++! ;-)
|
|
||||||
Compiles and builds out-of-the-box now. See the new wordings in
|
|
||||||
INSTALL for details.
|
|
||||||
|
|
||||||
- Beginning experiments with downloading multiple document from a http
|
|
||||||
server while remaining connected.
|
|
||||||
|
|
||||||
Version 5.6beta
|
|
||||||
|
|
||||||
Daniel (Mar 13 1999)
|
|
||||||
- Since I've changed so much, I thought I'd just go ahead and implement the
|
|
||||||
suggestion from Douglas E. Wegscheid. -D or --dump-header is now storing
|
|
||||||
HTTP headers separately in the specified file.
|
|
||||||
|
|
||||||
- Added new text to INSTALL on what to do to build this on win32 now.
|
|
||||||
|
|
||||||
- Aaargh. I had to take a step back and prefix the shared #include files
|
|
||||||
in the sources with "../include/" to please VC++...
|
|
||||||
|
|
||||||
Daniel (Mar 12 1999)
|
|
||||||
- Split the url.c source into many tiny sources for better readability
|
|
||||||
and smaller size.
|
|
||||||
|
|
||||||
Daniel (Mar 11 1999)
|
|
||||||
- Started to change stuff for a move to make libcurl and a more separate
|
|
||||||
curl application that uses the libcurl. Made the libcurl sources into
|
|
||||||
the new lib directory while the curl application will remain in src as
|
|
||||||
before. New makefiles, adjusted configure script and so.
|
|
||||||
|
|
||||||
libcurl.a built quickly and easily. I better make a better interface to
|
|
||||||
the lib functions though.
|
|
||||||
|
|
||||||
The new root dir include/ is supposed to contain the public information
|
|
||||||
about the new libcurl. It is a little ugly so far :-)
|
|
||||||
|
|
||||||
|
|
||||||
Daniel (Mar 1 1999)
|
|
||||||
- Todd Kaufmann sent me a good link to Netscape's cookie spec as well as the
|
|
||||||
info that RFC 2109 specifies how to use them. The link is now in the
|
|
||||||
README and the RFC in the RESOURCES.
|
|
||||||
|
|
||||||
Daniel (Feb 23 1999)
|
|
||||||
- Finally made configure accept --with-ssl to look for SSL libs and includes
|
|
||||||
in the "standard" place /usr/local/ssl...
|
|
||||||
|
|
||||||
Daniel (Feb 22 1999)
|
|
||||||
- Verified that curl linked fine with OpenSSL 0.9.1c which seems to be
|
|
||||||
the most recent.
|
|
||||||
|
|
||||||
Henri Gomez (Fri Feb 5 1999)
|
|
||||||
- Sent in an updated curl-ssl.spec. I still miss the script that builds an
|
|
||||||
RPM automatically...
|
|
||||||
|
|
||||||
Version 5.5.1
|
|
||||||
|
|
||||||
Mark Butler (27 Jan 1999)
|
|
||||||
- Corrected problems in Download().
|
|
||||||
|
|
||||||
Danitel Stenberg (25 Jan 1999)
|
|
||||||
- Jeremie Petit pointed out a few flaws in the source that prevented it from
|
|
||||||
compile warning free with the native compiler under Digital Unix v4.0d.
|
|
||||||
|
|
||||||
Version 5.5
|
|
||||||
|
|
||||||
Daniel Stenberg (15 Jan 1999)
|
|
||||||
- Added Bjorns small text to the README about the DICT protocol.
|
|
||||||
|
|
||||||
Daniel Stenberg (11 Jan 1999)
|
|
||||||
- <jswink at softcom.net> reported about the win32-versioin: "Doesn't use
|
|
||||||
ALL_PROXY environment variable". Turned out to be because of the static-
|
|
||||||
buffer nature of the win32 environment variable calls!
|
|
||||||
|
|
||||||
Bjorn Reese (10 Jan 1999)
|
|
||||||
- I have attached a simple addition for the DICT protocol (RFC 2229).
|
|
||||||
It performs dictionary lookups. The output still needs to be better
|
|
||||||
formatted.
|
|
||||||
|
|
||||||
To test it try (the exact format, and more examples are described in
|
|
||||||
the RFC)
|
|
||||||
|
|
||||||
dict://dict.org/m:hello
|
|
||||||
dict://dict.org/m:hello::soundex
|
|
||||||
|
|
||||||
|
|
||||||
Vicente Garcia (10 Jan 1999)
|
|
||||||
- Corrected the progress meter for files larger than 20MB.
|
|
||||||
|
|
||||||
Daniel Stenberg (7 Jan 1999)
|
|
||||||
- Corrected the -t and -T help texts. They claimed to be FTP only.
|
|
||||||
|
|
||||||
Version 5.4
|
|
||||||
|
|
||||||
Daniel Stenberg
|
|
||||||
(7 Jan 1999)
|
|
||||||
- Irving Wolfe reported that curl -s didn't always supress the progress
|
|
||||||
reporting. It was the form post that autoamtically always switched it on
|
|
||||||
again. This is now corrected!
|
|
||||||
|
|
||||||
(4 Jan 1999)
|
|
||||||
- Andreas Kostyrka suggested I'd add PUT and he helped me out to test it. If
|
|
||||||
you use -t or -T now on a http or https server, PUT will be used for file
|
|
||||||
upload.
|
|
||||||
|
|
||||||
I removed the former use of -T with HTTP. I doubt anyone ever really used
|
|
||||||
that.
|
|
||||||
|
|
||||||
(4 Jan 1999)
|
|
||||||
- Erik Jacobsen found a width bug in the mprintf() function. I corrected it
|
|
||||||
now.
|
|
||||||
|
|
||||||
(4 Jan 1999)
|
|
||||||
- As John V. Chow pointed out to me, curl accepted very limited URL sizes. It
|
|
||||||
should now accept path parts that are up to at least 4096 bytes.
|
|
||||||
|
|
||||||
- Somehow I screwed up when applying the AIX fix from Gilbert Ramirez, so
|
|
||||||
I redid that now.
|
|
||||||
|
|
||||||
Version 5.3a (win32 only)
|
Version 5.3a (win32 only)
|
||||||
|
|
||||||
Troy Engel
|
Troy Engel
|
||||||
|
835
CHANGES.1999
Normal file
835
CHANGES.1999
Normal file
@@ -0,0 +1,835 @@
|
|||||||
|
Daniel (28 December 1999):
|
||||||
|
- Tim Verhoeven correctly identified that curl
|
||||||
|
doesn't support URL formatted file names when getting ftp. Now, there's a
|
||||||
|
problem with getting very weird file names off FTP servers. RFC 959 defines
|
||||||
|
that the file name syntax to use should be the same as in the native OS of
|
||||||
|
the server. Since we don't know the peer server system we currently just
|
||||||
|
translate the URL syntax into plain letters. It is still better and with
|
||||||
|
the solaris 2.6-supplied ftp server it works with spaces in the file names.
|
||||||
|
|
||||||
|
Daniel (27 December 1999):
|
||||||
|
- When curl parsed cookies straight off a remote site, it corrupted the input
|
||||||
|
data, which, if the downloaded headers were stored made very odd characters
|
||||||
|
in the saved data. Correctly identified and reported by Paul Harrington.
|
||||||
|
|
||||||
|
Daniel (13 December 1999):
|
||||||
|
- General cleanups in the library interface. There had been some bad kludges
|
||||||
|
added during times of stress and I did my best to clean them off. It was
|
||||||
|
both regarding the lib API as well as include file confusions.
|
||||||
|
|
||||||
|
Daniel (3 December 1999):
|
||||||
|
- A small --stderr bug was reported by Eetu Ojanen...
|
||||||
|
|
||||||
|
- who also brought the suggestion of extending the -X flag to ftp list as
|
||||||
|
well. So, now it is and the long option is now --request instead. It is
|
||||||
|
only for ftp list for now (and the former http stuff too of course).
|
||||||
|
|
||||||
|
Lars J. Aas (24 November 1999):
|
||||||
|
- Patched curl to compile and build under BeOS. Doesn't work yet though!
|
||||||
|
|
||||||
|
- Corrected the Makefile.am files to allow putting object files in
|
||||||
|
different directories than the sources.
|
||||||
|
|
||||||
|
Version 6.3.1
|
||||||
|
|
||||||
|
Daniel (23 November 1999):
|
||||||
|
- I've had this major disk crash. My good old trust-worthy source disk died
|
||||||
|
along with the machine that hosted it. Thank goodness most of all the
|
||||||
|
things I've done are either backed up elsewhere or stored in this CVS
|
||||||
|
server!
|
||||||
|
|
||||||
|
- Michael S. Steuer pointed out a bug in the -F handling
|
||||||
|
that made curl hang if you posted an empty variable such as '-F name='. It
|
||||||
|
was one of those old bugs that never have worked properly...
|
||||||
|
|
||||||
|
- Jason Baietto pointed out a general flaw in the HTTP
|
||||||
|
download. Curl didn't complain if it was prematurely aborted before the
|
||||||
|
entire download was completed. It does now.
|
||||||
|
|
||||||
|
Daniel (19 November 1999):
|
||||||
|
- Chris Maltby very accurately criticized the lack of
|
||||||
|
return code checks on the fwrite() calls. I did a thorough check for all
|
||||||
|
occurrences and corrected this.
|
||||||
|
|
||||||
|
Daniel (17 November 1999):
|
||||||
|
- Paul Harrington pointed out that the -m/--max-time option
|
||||||
|
doesn't work for the slow system calls like gethostbyname()... I don't have
|
||||||
|
any good fix yet, just a slightly less bad one that makes curl exit hard
|
||||||
|
when the timeout is reached.
|
||||||
|
|
||||||
|
- Bjorn Reese helped me point out a possible problem that might be the reason
|
||||||
|
why Thomas Hurst experience problems in his Amiga version.
|
||||||
|
|
||||||
|
Daniel (12 November 1999):
|
||||||
|
- I found a crash in the new cookie file parser. It crashed when you gave
|
||||||
|
a plain http header file as input...
|
||||||
|
|
||||||
|
Version 6.3
|
||||||
|
|
||||||
|
Daniel (10 November 1999):
|
||||||
|
- I kind of found out that the HTTP time-conditional GETs (-z) aren't always
|
||||||
|
respected by the web server and the document is therefore sent in whole
|
||||||
|
again, even though it doesn't match the requested condition. After reading
|
||||||
|
section 13.3.4 of RFC 2616, I think I'm doing the right thing now when I do
|
||||||
|
my own check as well. If curl thinks the condition isn't met, the transfer
|
||||||
|
is aborted prematurely (after all the headers have been received).
|
||||||
|
|
||||||
|
- After comments from Robert Linden I also rewrote some parts of the man page
|
||||||
|
to better describe how the -F works.
|
||||||
|
|
||||||
|
- Michael Anti put up a new curl download mirror in
|
||||||
|
China: http://www.pshowing.com/curl/
|
||||||
|
|
||||||
|
- I added the list of download mirrors to the README file
|
||||||
|
|
||||||
|
- I did add more explanations to the man page
|
||||||
|
|
||||||
|
Daniel (8 November 1999):
|
||||||
|
- I made the -b/--cookie option capable of reading netscape formatted cookie
|
||||||
|
files as well as normal http-header files. It should be able to
|
||||||
|
transparently figure out what kind of file it got as input.
|
||||||
|
|
||||||
|
Daniel (29 October 1999):
|
||||||
|
- Another one of Sebastiaan van Erk's ideas (that has been requested before
|
||||||
|
but I seem to have forgotten who it was), is to add support for ranges in
|
||||||
|
FTP downloads. As usual, one request is just a request, when they're two
|
||||||
|
it is a demand. I've added simple support for X-Y style fetches. X has to
|
||||||
|
be the lower number, though you may omit one of the numbers. Use the -r/
|
||||||
|
--range switch (previously HTTP-only).
|
||||||
|
|
||||||
|
- Sebastiaan van Erk suggested that curl should be
|
||||||
|
able to show the file size of a specified file. I think this is a splendid
|
||||||
|
idea and the -I flag is now working for FTP. It displays the file size in
|
||||||
|
this manner:
|
||||||
|
Content-Length: XXXX
|
||||||
|
As it resembles normal headers, and leaves us the opportunity to add more
|
||||||
|
info in that display if we can come up with more in the future! It also
|
||||||
|
makes sense since if you access ftp through a HTTP proxy, you'd get the
|
||||||
|
file size the same way.
|
||||||
|
|
||||||
|
I changed the order of the QUOTE command executions. They're now executed
|
||||||
|
just after the login and before any other command. I made this to enable
|
||||||
|
quote commands to run before the -I stuff is done too.
|
||||||
|
|
||||||
|
- I found out that -D/--dump-header and -V/--version weren't documented in
|
||||||
|
the man page.
|
||||||
|
|
||||||
|
- Many HTTP/1.1 servers do not support ranges. Don't ask me why. I did add
|
||||||
|
some text about this in the man page for the range option. The thread in
|
||||||
|
the mailing list that started this was initiated by Michael Anti.
|
||||||
|
|
||||||
|
- I get reports about nroff crashes on solaris 2.6+ when displaying the curl
|
||||||
|
man page. Switch to gnroff instead, it is reported to work(!). Adam Barclay
|
||||||
|
reported and brought the suggestion.
|
||||||
|
|
||||||
|
- In a dialogue with Johannes G. Kristinsson we came
|
||||||
|
up with the idea to let -H/--header specified headers replace the
|
||||||
|
internally generated headers, if you happened to select to add a header
|
||||||
|
that curl normally uses by itself. The advantage with this is not entirely
|
||||||
|
obvious, but in Johannes' case it means that he can use another Host: than
|
||||||
|
the one curl would set.
|
||||||
|
|
||||||
|
Daniel (27 October 1999):
|
||||||
|
- Jongki Suwandi brought a nice patch for (yet another) crash when following
|
||||||
|
a location:. This time you had to follow a https:// server's redirect to
|
||||||
|
get the core.
|
||||||
|
|
||||||
|
Version 6.2
|
||||||
|
|
||||||
|
Daniel (21 October 1999):
|
||||||
|
- I think I managed to remove the suspicious (nil) that has been seen just
|
||||||
|
before the "Host:" in HTTP requests when -v was used.
|
||||||
|
- I found out that if you followed a location: when using a proxy, without
|
||||||
|
having specified http:// in the URL, the protocol part was added once again
|
||||||
|
when moving to the next URL! (The protocol part has to be added to the
|
||||||
|
URL when going through a proxy since it has no protocol-guessing system
|
||||||
|
such as curl has.)
|
||||||
|
- Benjamin Ritcey reported a core dump under solaris 2.6
|
||||||
|
with OpenSSL 0.9.4. It turned out this was due to a bad free() in main.c
|
||||||
|
that occurred after the download was done and completed.
|
||||||
|
- Benjamin found ftp downloads to show the first line of the download meter
|
||||||
|
to get written twice, and I removed that problem. It was introduced with
|
||||||
|
the multiple URL support.
|
||||||
|
- Dan Zitter correctly pointed out that curl 6.1 and earlier versions didn't
|
||||||
|
honor RFC 2616 chapter 4 section 2, "Message Headers": "...Field names are
|
||||||
|
case-insensitive..." HTTP header parsing assumed a certain casing. Dan
|
||||||
|
also provided me with a patch that corrected this, which I took the liberty
|
||||||
|
of editing slightly.
|
||||||
|
- Dan Zitter also provided a nice patch for config.guess to better recognize
|
||||||
|
the Mac OS X
|
||||||
|
- Dan also corrected a minor problem in the lib/Makefile that caused linking
|
||||||
|
to fail on OS X.
|
||||||
|
|
||||||
|
Daniel (19 October 1999):
|
||||||
|
- Len Marinaccio came up with some problems with curl. Since Windows has a
|
||||||
|
crippled shell, it can't redirect stderr and that causes trouble. I added
|
||||||
|
--stderr today which allows the user to redirect the stderr stream to a
|
||||||
|
file or stdout.
|
||||||
|
|
||||||
|
Daniel (18 October 1999):
|
||||||
|
- The configure script now understands the '--without-ssl' flag, which now
|
||||||
|
totally disable SSL/https support. Previously it wasn't possible to force
|
||||||
|
the configure script to leave SSL alone. The previous functionality has
|
||||||
|
been retained. Troy Engel helped test this new one.
|
||||||
|
|
||||||
|
Version 6.1
|
||||||
|
|
||||||
|
Daniel (17 October 1999):
|
||||||
|
- I ifdef'ed or commented all the zlib stuff in the sources and configure
|
||||||
|
script. It turned out we needed to mock more with zlib than I initially
|
||||||
|
thought, to make it capable of downloading compressed HTTP documents and
|
||||||
|
uncompress them on the fly. I didn't mean the zlib parts of curl to become
|
||||||
|
more than minor so this means I halt the zlib expedition for now and wait
|
||||||
|
until someone either writes the code or zlib gets updated and better
|
||||||
|
adjusted for this kind of usage. I won't get into details here, but a
|
||||||
|
short a summary is suitable:
|
||||||
|
- zlib can't automatically detect whether to use zlib or gzip
|
||||||
|
decompression methods.
|
||||||
|
- zlib is very neat for reading gzipped files from a file descriptor,
|
||||||
|
although not as nice for reading buffer-based data such as we would
|
||||||
|
want it.
|
||||||
|
- there are still some problems with the win32 version when reading from
|
||||||
|
a file descriptor if that is a socket
|
||||||
|
|
||||||
|
Daniel (14 October 1999):
|
||||||
|
- Moved the (external) include files for libcurl into a subdirectory named
|
||||||
|
curl and adjusted all #include lines to use <curl/XXXX> to maintain a
|
||||||
|
better name space and control of the headers. This has been requested.
|
||||||
|
|
||||||
|
Daniel (12 October 1999):
|
||||||
|
- I modified the 'maketgz' script to perform a 'make' too before a release
|
||||||
|
archive is put together in an attempt to make the time stamps better and
|
||||||
|
hopefully avoid the double configure-running that use to occur.
|
||||||
|
|
||||||
|
Daniel (11 October 1999):
|
||||||
|
- Applied J<>rn's patches that fixes zlib for mingw32 compiles as well as
|
||||||
|
some other missing zlib #ifdef and more text on the multiple URL docs in
|
||||||
|
the man page.
|
||||||
|
|
||||||
|
Version 6.1beta
|
||||||
|
|
||||||
|
Daniel (6 October 1999):
|
||||||
|
- Douglas E. Wegscheid sent me a patch that made the exact same thing as I
|
||||||
|
just made: the -d switch is now capable of reading post data from a named
|
||||||
|
file or stdin. Use it similarly to the -F. To read the post data from a
|
||||||
|
given file:
|
||||||
|
|
||||||
|
curl -d @path/to/filename www.postsite.com
|
||||||
|
|
||||||
|
or let curl read it out from stdin:
|
||||||
|
|
||||||
|
curl -d @- www.postit.com
|
||||||
|
|
||||||
|
J<>rn Hartroth (3 October 1999):
|
||||||
|
- Brought some more patches for multiple URL functionality. The MIME
|
||||||
|
separation ideas are almost scrapped now, and a custom separator is being
|
||||||
|
used instead. This is still compile-time "flagged".
|
||||||
|
|
||||||
|
Daniel
|
||||||
|
- Updated curl.1 with multiple URL info.
|
||||||
|
|
||||||
|
Daniel (30 September 1999):
|
||||||
|
- Felix von Leitner brought openssl-check fixes for configure.in to work
|
||||||
|
out-of-the-box when the openssl files are installed in the system default
|
||||||
|
dirs.
|
||||||
|
|
||||||
|
Daniel (28 September 1999)
|
||||||
|
- Added libz functionality. This should enable decompressing gzip, compress
|
||||||
|
or deflate encoding HTTP documents. It also makes curl send an accept that
|
||||||
|
it accepts that kind of encoding. Compressed contents usually shortens
|
||||||
|
download time. I *need* someone to tell me a site that uses compressed HTTP
|
||||||
|
documents so that I can test this out properly.
|
||||||
|
|
||||||
|
- As a result of the adding of zlib awareness, I changed the version string
|
||||||
|
a little. I plan to add openldap version reporting in there too.
|
||||||
|
|
||||||
|
Daniel (17 September 1999)
|
||||||
|
- Made the -F option allow stdin when specifying files. By using '-' instead
|
||||||
|
of file name, the data will be read from stdin.
|
||||||
|
|
||||||
|
Version 6.0
|
||||||
|
|
||||||
|
Daniel (13 September 1999)
|
||||||
|
- Added -X/--http-request <request> to enable any HTTP command to be sent.
|
||||||
|
Do not that your server has to support the exact string you enter. This
|
||||||
|
should possibly a string like DELETE or TRACE.
|
||||||
|
|
||||||
|
- Applied Douglas' mingw32-fixes for the makefiles.
|
||||||
|
|
||||||
|
Daniel (10 September 1999)
|
||||||
|
- Douglas E. Wegscheid pointed out a problem. Curl didn't check the FTP
|
||||||
|
servers return code properly after the --quote commands were issued. It
|
||||||
|
took anything non 200 as an error, when all 2XX codes should be accepted as
|
||||||
|
OK.
|
||||||
|
|
||||||
|
- Sending cookies to the same site in multiple lines like curl used to do
|
||||||
|
turned out to be bad and breaking the cookie specs. Curl now sends all
|
||||||
|
cookies on a single Cookie: line. Curl is not yet RFC 2109 compliant, but I
|
||||||
|
doubt that many servers do use that syntax (yet).
|
||||||
|
|
||||||
|
Daniel (8 September 1999)
|
||||||
|
- J<>rn helped me make sure it still compiles nicely with mingw32 under win32.
|
||||||
|
|
||||||
|
Daniel (7 September 1999)
|
||||||
|
- FTP upload through proxy is now turned into a HTTP PUT. Requested by
|
||||||
|
Stefan Kanthak.
|
||||||
|
|
||||||
|
- Added the ldap files to the .m32 makefile.
|
||||||
|
|
||||||
|
Daniel (3 September 1999)
|
||||||
|
- Made cookie matching work while using HTTP proxy.
|
||||||
|
|
||||||
|
Bjorn Reese (31 August 1999)
|
||||||
|
- Passed his ldap:// patch. Note that this requires the openldap shared
|
||||||
|
library to be installed and that LD_LIBRARY_PATH points to the
|
||||||
|
directory where the lib will be found when curl is run with a
|
||||||
|
ldap:// URL.
|
||||||
|
|
||||||
|
J<>rn Hartroth (31 August 1999)
|
||||||
|
- Made the Mingw32 makefiles into single files.
|
||||||
|
- Made file:// work for Win32. The same code is now used for unix as well for
|
||||||
|
performance reasons.
|
||||||
|
|
||||||
|
Douglas E. Wegscheid (30 August 1999)
|
||||||
|
- Patched the Mingw32 makefiles for SSL builds.
|
||||||
|
|
||||||
|
Matthew Clarke (30 August 1999)
|
||||||
|
- Made a cool patch for configure.in to allow --with-ssl to specify the
|
||||||
|
root dir of the openssl installation, as in
|
||||||
|
|
||||||
|
./configure --with-ssl=/usr/ssl_here
|
||||||
|
|
||||||
|
- Corrected the 'reconf' script to work better with some shells.
|
||||||
|
|
||||||
|
J<>rn Hartroth (26 August 1999)
|
||||||
|
- Fixed the Mingw32 makefiles in lib/ and corrected the file.c for win32
|
||||||
|
compiles.
|
||||||
|
|
||||||
|
Version 5.11
|
||||||
|
|
||||||
|
Daniel (25 August 1999)
|
||||||
|
- John Weismiller pointed out a bug in the header-line
|
||||||
|
realloc() system in download.c.
|
||||||
|
|
||||||
|
- I added lib/file.[ch] to offer a first, simple, file:// support. It
|
||||||
|
probably won't do much good on win32 system at this point, but I see it
|
||||||
|
as a start.
|
||||||
|
|
||||||
|
- Made the release archives get a Makefile in the root dir, which can be
|
||||||
|
used to start the compiling/building process easier. I haven't really
|
||||||
|
changed any INSTALL text yet, I wanted to get some feed-back on this
|
||||||
|
first.
|
||||||
|
|
||||||
|
Daniel (17 August 1999)
|
||||||
|
- Another Location: bug. Curl didn't do proper relative locations if the
|
||||||
|
original URL had cgi-parameters that contained a slash. Nusu's page
|
||||||
|
again.
|
||||||
|
|
||||||
|
- Corrected the NO_PROXY usage. It is a list of substrings that if one of
|
||||||
|
them matches the tail of the host name it should connect to, curl should
|
||||||
|
not use a proxy to connect there. Pointed out to me by Douglas
|
||||||
|
E. Wegscheid. I also changed the README text a little regarding this.
|
||||||
|
|
||||||
|
Daniel (16 August 1999)
|
||||||
|
- Fixed a memory bug with http-servers that sent Location: to a Location:
|
||||||
|
page. Nusu's page showed this too.
|
||||||
|
|
||||||
|
- Made cookies work a lot better. Setting the same cookie name several times
|
||||||
|
used to add more cookies instead of replacing the former one which it
|
||||||
|
should've. Nusu <nus at intergorj.ro> brought me an URL that made this
|
||||||
|
painfully visible...
|
||||||
|
|
||||||
|
Troy (15 August 1999)
|
||||||
|
- Brought new .spec files as well as a patch for configure.in that lets the
|
||||||
|
configure script find the openssl files better, even when the include
|
||||||
|
files are in /usr/include/openssl
|
||||||
|
|
||||||
|
Version 5.10
|
||||||
|
|
||||||
|
Daniel (13 August 1999)
|
||||||
|
- SSL_CTX_set_default_passwd_cb() has been modified in the 0.9.4 version of
|
||||||
|
OpenSSL. Now why couldn't they simply add a *new* function instead of
|
||||||
|
modifying the parameters of an already existing function? This way, we get
|
||||||
|
a compiler warning if compiling with 0.9.4 but not with earlier. So, I had
|
||||||
|
to come up with a #if construction that deals with this...
|
||||||
|
|
||||||
|
- Made curl output the SSL version number get displayed properly with 0.9.4.
|
||||||
|
|
||||||
|
Troy (12 August 1999)
|
||||||
|
- Added MingW32 (GCC-2.95) support under Win32. The INSTALL file was also
|
||||||
|
a bit rearranged.
|
||||||
|
|
||||||
|
Daniel (12 August 1999)
|
||||||
|
- I had to copy a good <arpa/telnet.h> include file into the curl source
|
||||||
|
tree to enable the silly win32 systems to compile. The distribution rights
|
||||||
|
allows us to do that as long as the file remains unmodified.
|
||||||
|
|
||||||
|
- I corrected a few minor things that made the compiler complain when
|
||||||
|
-Wall -pedantic was used.
|
||||||
|
|
||||||
|
- I'm moving the official curl web page to http://curl.haxx.nu. I think it
|
||||||
|
will make it easier to remember as it is a lot shorter and less cryptic.
|
||||||
|
The old one still works and shows the same info.
|
||||||
|
|
||||||
|
Daniel (11 August 1999)
|
||||||
|
- Albert Chin-A-Young mailed me another correction for NROFF in the
|
||||||
|
configure.in that is supposed to be better for IRIX users.
|
||||||
|
|
||||||
|
Daniel (10 August 1999)
|
||||||
|
- Albert Chin-A-Young helped me with some stupid Makefile things, as well as
|
||||||
|
some fiddling with the getdate.c stuff that he had problems with under
|
||||||
|
HP-UX v10. getdate.y will now be compiled into getdate.c if the appropriate
|
||||||
|
yacc or bison is found by the configure script. Since this is slightly new,
|
||||||
|
we need to test the output getdate.c with win32 systems to make sure it
|
||||||
|
still compiles there.
|
||||||
|
|
||||||
|
Daniel (5 August 1999)
|
||||||
|
- I've just setup a new mailing list with the intention to keep discussions
|
||||||
|
around libcurl development in it. I mainly expect it to be for thoughts and
|
||||||
|
brainstorming around a "next generation" library, rather than nitpicking
|
||||||
|
about the current implementation or details in the current libcurl.
|
||||||
|
|
||||||
|
To join our happy bunch of future-looking geeks, enter 'subscribe
|
||||||
|
<address>' in the body of a mail and send it to
|
||||||
|
libcurl-request@listserv.fts.frontec.se. Curl bug reports, the usual curl
|
||||||
|
talk and everything else should still be kept in this mailing list. I've
|
||||||
|
started to archive this mailing list and have put the libcurl web page at
|
||||||
|
www.fts.frontec.se/~dast/libcurl/.
|
||||||
|
|
||||||
|
- Stefan Kanthak contacted me regarding a few problems in the configure
|
||||||
|
script which he discovered when trying to make curl compile and build under
|
||||||
|
Siemens SINIX-Z V5.42B2004!
|
||||||
|
|
||||||
|
- Marcus Klein very accurately informed me that src/version.h was not present
|
||||||
|
in the CVS repository. Oh, how silly...
|
||||||
|
|
||||||
|
- Linus Nielsen rewrote the telnet:// part and now curl offers limited telnet
|
||||||
|
support. If you run curl like 'curl telnet://host' you'll get all output on
|
||||||
|
the screen and curl will read input from stdin. You'll be able to login and
|
||||||
|
run commands etc, but since the output is buffered, expect to get a little
|
||||||
|
weird output.
|
||||||
|
|
||||||
|
This is still in its infancy and it might get changed. We need your
|
||||||
|
feed-back and input in how this is best done.
|
||||||
|
|
||||||
|
WIN32 NOTE: I bet we'll get problems when trying to compile the current
|
||||||
|
lib/telnet.c on win32, but I think we can sort them out in time.
|
||||||
|
|
||||||
|
- David Sanderson reported that FORCE_ALLOCA_H or HAVE_ALLOCA_H must be
|
||||||
|
defined for getdate.c to compile properly on HP-UX 11.0. I updated the
|
||||||
|
configure script to check for alloca.h which should make it.
|
||||||
|
|
||||||
|
Daniel (4 August 1999)
|
||||||
|
- I finally got to understand Marcus Klein's ftp download resume problem,
|
||||||
|
which turns out to be due to different outputs from different ftp
|
||||||
|
servers. It makes ftp download resuming a little trickier, but I've made
|
||||||
|
some modifications I really believe will work for most ftp servers and I do
|
||||||
|
hope you report if you have problems with this!
|
||||||
|
|
||||||
|
- Added text about file transfer resuming to README.curl.
|
||||||
|
|
||||||
|
Daniel (2 August 1999)
|
||||||
|
- Applied a progress-bar patch from Lars J. Aas. It offers
|
||||||
|
a new styled progress bar enabled with -#/--progress-bar.
|
||||||
|
|
||||||
|
T. Yamada <tai at imasy.or.jp> (30 July 1999)
|
||||||
|
- It breaks with segfault when 1) curl is using .netrc to obtain
|
||||||
|
username/password (option '-n'), and 2) is automatically redirected to
|
||||||
|
another location (option '-L').
|
||||||
|
|
||||||
|
There is a small bug in lib/url.c (block starting from line 641), which
|
||||||
|
tries to take out username/password from user- supplied command-line
|
||||||
|
argument ('-u' option). This block is never executed on first attempt since
|
||||||
|
CONF_USERPWD bit isn't set at first, but curl later turns it on when it
|
||||||
|
checks for CONF_NETRC bit. So when curl tries to redo everything due to
|
||||||
|
redirection, it segfaults trying to access *data->userpwd.
|
||||||
|
|
||||||
|
Version 5.9.1
|
||||||
|
|
||||||
|
Daniel (30 July 1999)
|
||||||
|
- Steve Walch pointed out that there is a memory leak in the formdata
|
||||||
|
functions. I added a FormFree() function that is now used and supposed to
|
||||||
|
correct this flaw.
|
||||||
|
|
||||||
|
- Mark Wotton reported:
|
||||||
|
'curl -L https://www.cwa.com.au/' core dumps. I managed to cure this by
|
||||||
|
correcting the cleanup procedure. The bug seems to be gone with my OpenSSL
|
||||||
|
0.9.2b, although still occurs when I run the ~100 years old SSLeay 0.8.0. I
|
||||||
|
don't know whether it is curl or SSLeay that is to blame for that.
|
||||||
|
|
||||||
|
- Marcus Klein:
|
||||||
|
Reported an FTP upload resume bug that I really can't repeat nor understand.
|
||||||
|
I leave it here so that it won't be forgotten.
|
||||||
|
|
||||||
|
Daniel (29 July 1999)
|
||||||
|
- Costya Shulyupin suggested support for longer URLs when following Location:
|
||||||
|
and I could only agree and fix it!
|
||||||
|
|
||||||
|
- Leigh Purdie found a problem in the upload/POST department. It turned out
|
||||||
|
that http.c accidentaly cleared the pointer instead of the byte counter
|
||||||
|
when supposed to.
|
||||||
|
|
||||||
|
- Costya Shulyupin pointed out a problem with port numbers and Location:. If
|
||||||
|
you had a server at a non-standard port that redirected to an URL using a
|
||||||
|
standard port number, curl still used that first port number.
|
||||||
|
|
||||||
|
- Ralph Beckmann pointed out a problem when using both CONF_FOLLOWLOCATION
|
||||||
|
and CONF_FAILONERROR simultaneously. Since the CONF_FAILONERROR exits on
|
||||||
|
the 302-code that the follow location header outputs it will never show any
|
||||||
|
html on location: pages. I have now made it look for >=400 codes if
|
||||||
|
CONF_FOLLOWLOCATION is set.
|
||||||
|
|
||||||
|
- 'struct slist' is now renamed to 'struct curl_slist' (as suggested by Ralph
|
||||||
|
Beckmann).
|
||||||
|
|
||||||
|
- Joshua Swink and Rick Welykochy were the first to point out to me that the
|
||||||
|
latest OpenSSL package now have moved the standard include path. It is now
|
||||||
|
in /usr/local/ssl/include/openssl and I have now modified the --enable-ssl
|
||||||
|
option for the configure script to use that as the primary path, and I
|
||||||
|
leave the former path too to work with older packages of OpenSSL too.
|
||||||
|
|
||||||
|
Daniel (9 June 1999)
|
||||||
|
- I finally understood the IRIX problem and now it seem to compile on it!
|
||||||
|
I am gonna remove those #define strcasecmp() things once and for all now.
|
||||||
|
|
||||||
|
Daniel (4 June 1999)
|
||||||
|
- I adjusted the FTP reply 227 parser to make the PASV command work better
|
||||||
|
with more ftp servers. Appearantly the Roxen Challanger server replied
|
||||||
|
something curl 5.9 could deal with! :-( Reported by Ashley Reid-Montanaro
|
||||||
|
and Mark Butler brought a solution for it.
|
||||||
|
|
||||||
|
Daniel (26 May 1999)
|
||||||
|
- Rearranged. README is new, the old one is now README.curl and I added a
|
||||||
|
README.libcurl with text I got from Ralph Beckmann.
|
||||||
|
|
||||||
|
- I also updated the INSTALL text.
|
||||||
|
|
||||||
|
Daniel (25 May 1999)
|
||||||
|
- David Jonathan Lowsky correctly pointed out that curl didn't properly deal
|
||||||
|
with form posting where the variable shouldn't have any content, as in curl
|
||||||
|
-F "form=" www.site.com. It was now fixed.
|
||||||
|
|
||||||
|
Version 5.9
|
||||||
|
|
||||||
|
Daniel (22 May 1999)
|
||||||
|
- I've got a bug report from Aaron Scarisbrick in which he states he has some
|
||||||
|
problems with -L under FreeBSD 3.0. I have previously got another bug
|
||||||
|
report from Stefan Grether which points at an error with similar sympthoms
|
||||||
|
when using win32. I made the allocation of the new url string a bit faster
|
||||||
|
and different, don't know if it actually improves anything though...
|
||||||
|
|
||||||
|
Daniel (20 May 1999)
|
||||||
|
- Made the cookie parser deal with CRLF newlines too.
|
||||||
|
|
||||||
|
Daniel (19 May 1999)
|
||||||
|
- Download() didn't properly deal with failing return codes from the sread()
|
||||||
|
function. Adam Coyne found the problem in the win32 version, and Troy Engel
|
||||||
|
helped me out isolating it.
|
||||||
|
|
||||||
|
Daniel (16 May 1999)
|
||||||
|
- Richard Adams pointed out a bug I introduced in 5.8. --dump-header doesn't
|
||||||
|
work anymore! :-/ I fixed it now.
|
||||||
|
|
||||||
|
- After a suggestion by Joshua Swink I added -S / --show-error to force curl
|
||||||
|
to display the error message in case of an error, even if -s/--silent was
|
||||||
|
used.
|
||||||
|
|
||||||
|
Daniel (10 May 1999)
|
||||||
|
- I moved the stuff concerning HTTP, DICT and TELNET it their own source
|
||||||
|
files now. It is a beginning on my clean-up of the sources to make them
|
||||||
|
layer all those protocols better to enable more to be added easier in the
|
||||||
|
future!
|
||||||
|
|
||||||
|
- Leon Breedt sent me some files I've not put into the main curl
|
||||||
|
archive. They're for creating the Debian package thingie. He also sent me a
|
||||||
|
debian package that I've made available for download at the web page
|
||||||
|
|
||||||
|
Daniel (9 May 1999)
|
||||||
|
- Made it compile on cygwin too.
|
||||||
|
|
||||||
|
Troy Engel (7 May 1999)
|
||||||
|
- Brought a series of patches to allow curl to compile smoothly on MSVC++ 6
|
||||||
|
again!
|
||||||
|
|
||||||
|
Daniel (6 May 1999)
|
||||||
|
- I changed the #ifdef HAVE_STRFTIME placement for the -z code so that it
|
||||||
|
will be easier to discover systems that don't have that function and thus
|
||||||
|
can't use -z successfully. Made the strftime() get used if WIN32 is defined
|
||||||
|
too.
|
||||||
|
|
||||||
|
Version 5.8
|
||||||
|
|
||||||
|
Daniel (5 May 1999)
|
||||||
|
- I've had it with this autoconf/automake mess. It seems to work allright
|
||||||
|
for most people who don't have automake installed, but for those who have
|
||||||
|
there are problems all over.
|
||||||
|
|
||||||
|
I've got like five different bug reports on this only the last
|
||||||
|
week... Claudio Neves and Federico Bianchi and root <duggerj001 at
|
||||||
|
hawaii.rr.com> are some of them reporting this.
|
||||||
|
|
||||||
|
Currently, I have no really good fix since I want to use automake myself to
|
||||||
|
generate the Makefile.in files. I've found out that the @SHELL@-problems
|
||||||
|
can often be fixed by manually invoking 'automake' in the archive root
|
||||||
|
before you run ./configure... I've hacked my maketgz script now to fiddle
|
||||||
|
a bit with this and my tests seem to work better than before at least!
|
||||||
|
|
||||||
|
Daniel (4 May 1999)
|
||||||
|
- mkhelp.pl has been doing badly lately. I corrected a case problem in
|
||||||
|
the regexes.
|
||||||
|
|
||||||
|
- I've now remade the -o option to not touch the file unless it needs to.
|
||||||
|
I had to do this to make -z option really fine, since now you can make a
|
||||||
|
curl fetch and use a local copy's time when downloading to that file, as
|
||||||
|
in:
|
||||||
|
|
||||||
|
curl -z dump -o dump remote.site.com/file.html
|
||||||
|
|
||||||
|
This will only get the file if the remote one is newer than the local.
|
||||||
|
I'm aware that this alters previous behaviour a little. Some scripts out
|
||||||
|
there may depend on that the file is always touched...
|
||||||
|
|
||||||
|
- Corrected a bug in the SSLv2/v3 selection.
|
||||||
|
|
||||||
|
- Felix von Leitner requested that curl should be able to send
|
||||||
|
"If-Modified-Since" headers, which indeed is a fair idea. I implemented it
|
||||||
|
right away! Try -z <expression> where expression is a full GNU date
|
||||||
|
expression or a file name to get the date from!
|
||||||
|
|
||||||
|
Stephan Lagerholm (30 Apr 1999)
|
||||||
|
- Pointed out a problem with the src/Makefile for FreeBSD. The RM variable
|
||||||
|
isn't set and causes the make to fail.
|
||||||
|
|
||||||
|
Daniel (26 April 1999)
|
||||||
|
- Am I silly or what? Irving Wolfe pointed out to me that the curl version
|
||||||
|
number was not set properly. Hasn't been since 5.6. This was due to a bug
|
||||||
|
in my maketgz script!
|
||||||
|
|
||||||
|
David Eriksson (25 Apr 1999)
|
||||||
|
- Found a bug in cookies.c that made it crash at times.
|
||||||
|
|
||||||
|
Version 5.7.1
|
||||||
|
|
||||||
|
Doug Kaufman (23 Apr 1999)
|
||||||
|
- Brought two sunos 4 fixes. One of them being the hostip.c fix mentioned
|
||||||
|
below and the other one a correction in include/stdcheaders.h
|
||||||
|
|
||||||
|
- Added a paragraph about compiling with the US-version of openssl to the
|
||||||
|
INSTALL file.
|
||||||
|
|
||||||
|
Daniel
|
||||||
|
- New mailing list address. Info updated on the web page as well as in the
|
||||||
|
README file
|
||||||
|
|
||||||
|
Greg Onufer (20 Apr 1999)
|
||||||
|
- hostip.c didn't compile properly on SunOS 5.5.1.
|
||||||
|
It needs an #include <sys/types.h>
|
||||||
|
|
||||||
|
Version 5.7
|
||||||
|
|
||||||
|
Daniel (Apr 20 1999)
|
||||||
|
- Decided to upload a non-beta version right now!
|
||||||
|
|
||||||
|
- Made curl support any-length HTTP headers. The destination buffer is now
|
||||||
|
simply enlarged every time it turns out to be too small!
|
||||||
|
|
||||||
|
- Added the FAQ file to the archive. Still a bit smallish, but it is a
|
||||||
|
start.
|
||||||
|
|
||||||
|
Eric Thelin (15 Apr 1999)
|
||||||
|
- Made -D accept '-' instead of filename to write to stdout.
|
||||||
|
|
||||||
|
Version 5.6.3beta
|
||||||
|
|
||||||
|
Daniel (Apr 12 1999)
|
||||||
|
|
||||||
|
- Changed two #ifdef WIN32 to better #ifdef <errorcode> when connect()ing
|
||||||
|
in url.c and ftp.c. Makes cygwin32 deal with them better too. We should
|
||||||
|
try to get some decent win32-replacement there. Anyone?
|
||||||
|
|
||||||
|
- The old -3/--crlf option is now ONLY --crlf!
|
||||||
|
|
||||||
|
- I changed the "SSL fix" to a more lame one, but that doesn't remove as
|
||||||
|
much functionality. Now I've enabled the lib to select what SSL version it
|
||||||
|
should try first. Appearantly some older SSL-servers don't like when you
|
||||||
|
talk v3 with them so you need to be able to force curl to talk v2 from the
|
||||||
|
start. The fix dated April 6 and posted on the mailing list forced curl to
|
||||||
|
use v2 at all times using a modern OpenSSL version, but we don't really
|
||||||
|
want such a crippled solution.
|
||||||
|
|
||||||
|
- Marc Boucher sent me a patch that corrected a math error for the
|
||||||
|
"Curr.Speed" progress meter.
|
||||||
|
|
||||||
|
- Eric Thelin sent me a patch that enables '-K -' to read a config file from
|
||||||
|
stdin.
|
||||||
|
|
||||||
|
- I found out we didn't close the file properly before so I added it!
|
||||||
|
|
||||||
|
Daniel (Apr 9 1999)
|
||||||
|
- Yu Xin pointed out a problem with ftp download resume. It didn't work at
|
||||||
|
all! ;-O
|
||||||
|
|
||||||
|
Daniel (Apr 6 1999)
|
||||||
|
- Corrected the version string part generated for the SSL version.
|
||||||
|
|
||||||
|
- I found a way to make some other SSL page work with openssl 0.9.1+ that
|
||||||
|
previously didn't (ssleay 0.8.0 works with it though!). Trying to get
|
||||||
|
some real info from the OpenSSL guys to see how I should do to behave the
|
||||||
|
best way. SSLeay 0.8.0 shouldn't be that much in use anyway these days!
|
||||||
|
|
||||||
|
Version 5.6.2beta
|
||||||
|
|
||||||
|
Daniel (Apr 4 1999)
|
||||||
|
- Finally have curl more cookie "aware". Now read carefully. This is how
|
||||||
|
it works.
|
||||||
|
To make curl read cookies from an already existing file, in plain header-
|
||||||
|
format (like from the headers of a previous fetch) invoke curl with the
|
||||||
|
-b flag like:
|
||||||
|
|
||||||
|
curl -b file http://site/foo.html
|
||||||
|
|
||||||
|
Curl will then use all cookies it finds matching. The old style that sets
|
||||||
|
a single cookie with -b is still supported and is used if the string
|
||||||
|
following -b includes a '=' letter, as in "-b name=daniel".
|
||||||
|
|
||||||
|
To make curl read the cookies sent in combination with a location: (which
|
||||||
|
sites often do) point curl to read a non-existing file at first (i.e
|
||||||
|
to start with no existing cookies), like:
|
||||||
|
|
||||||
|
curl -b nowhere http://site/setcookieandrelocate.html
|
||||||
|
|
||||||
|
- Added a paragraph in the TODO file about the SSL problems recently
|
||||||
|
reported. Evidently, some kind of SSL-problem curl may need to address.
|
||||||
|
|
||||||
|
- Better "Location:" following.
|
||||||
|
|
||||||
|
Douglas E. Wegscheid (Tue, 30 Mar 1999)
|
||||||
|
- A subsecond display patch.
|
||||||
|
|
||||||
|
Daniel (Mar 14 1999)
|
||||||
|
- I've separated the version number of libcurl and curl now. To make
|
||||||
|
things a little easier, I decided to start the curl numbering from
|
||||||
|
5.6 and the former version number known as "curl" is now the one
|
||||||
|
set for libcurl.
|
||||||
|
|
||||||
|
- Removed the 'enable-no-pass' from configure, I doubt anyone wanted
|
||||||
|
that.
|
||||||
|
|
||||||
|
- Made lots of tiny adjustments to compile smoothly with cygwin under
|
||||||
|
win32. It's a killer for porting this to win32, bye bye VC++! ;-)
|
||||||
|
Compiles and builds out-of-the-box now. See the new wordings in
|
||||||
|
INSTALL for details.
|
||||||
|
|
||||||
|
- Beginning experiments with downloading multiple document from a http
|
||||||
|
server while remaining connected.
|
||||||
|
|
||||||
|
Version 5.6beta
|
||||||
|
|
||||||
|
Daniel (Mar 13 1999)
|
||||||
|
- Since I've changed so much, I thought I'd just go ahead and implement the
|
||||||
|
suggestion from Douglas E. Wegscheid. -D or --dump-header is now storing
|
||||||
|
HTTP headers separately in the specified file.
|
||||||
|
|
||||||
|
- Added new text to INSTALL on what to do to build this on win32 now.
|
||||||
|
|
||||||
|
- Aaargh. I had to take a step back and prefix the shared #include files
|
||||||
|
in the sources with "../include/" to please VC++...
|
||||||
|
|
||||||
|
Daniel (Mar 12 1999)
|
||||||
|
- Split the url.c source into many tiny sources for better readability
|
||||||
|
and smaller size.
|
||||||
|
|
||||||
|
Daniel (Mar 11 1999)
|
||||||
|
- Started to change stuff for a move to make libcurl and a more separate
|
||||||
|
curl application that uses the libcurl. Made the libcurl sources into
|
||||||
|
the new lib directory while the curl application will remain in src as
|
||||||
|
before. New makefiles, adjusted configure script and so.
|
||||||
|
|
||||||
|
libcurl.a built quickly and easily. I better make a better interface to
|
||||||
|
the lib functions though.
|
||||||
|
|
||||||
|
The new root dir include/ is supposed to contain the public information
|
||||||
|
about the new libcurl. It is a little ugly so far :-)
|
||||||
|
|
||||||
|
|
||||||
|
Daniel (Mar 1 1999)
|
||||||
|
- Todd Kaufmann sent me a good link to Netscape's cookie spec as well as the
|
||||||
|
info that RFC 2109 specifies how to use them. The link is now in the
|
||||||
|
README and the RFC in the RESOURCES.
|
||||||
|
|
||||||
|
Daniel (Feb 23 1999)
|
||||||
|
- Finally made configure accept --with-ssl to look for SSL libs and includes
|
||||||
|
in the "standard" place /usr/local/ssl...
|
||||||
|
|
||||||
|
Daniel (Feb 22 1999)
|
||||||
|
- Verified that curl linked fine with OpenSSL 0.9.1c which seems to be
|
||||||
|
the most recent.
|
||||||
|
|
||||||
|
Henri Gomez (Fri Feb 5 1999)
|
||||||
|
- Sent in an updated curl-ssl.spec. I still miss the script that builds an
|
||||||
|
RPM automatically...
|
||||||
|
|
||||||
|
Version 5.5.1
|
||||||
|
|
||||||
|
Mark Butler (27 Jan 1999)
|
||||||
|
- Corrected problems in Download().
|
||||||
|
|
||||||
|
Danitel Stenberg (25 Jan 1999)
|
||||||
|
- Jeremie Petit pointed out a few flaws in the source that prevented it from
|
||||||
|
compile warning free with the native compiler under Digital Unix v4.0d.
|
||||||
|
|
||||||
|
Version 5.5
|
||||||
|
|
||||||
|
Daniel Stenberg (15 Jan 1999)
|
||||||
|
- Added Bjorns small text to the README about the DICT protocol.
|
||||||
|
|
||||||
|
Daniel Stenberg (11 Jan 1999)
|
||||||
|
- <jswink at softcom.net> reported about the win32-versioin: "Doesn't use
|
||||||
|
ALL_PROXY environment variable". Turned out to be because of the static-
|
||||||
|
buffer nature of the win32 environment variable calls!
|
||||||
|
|
||||||
|
Bjorn Reese (10 Jan 1999)
|
||||||
|
- I have attached a simple addition for the DICT protocol (RFC 2229).
|
||||||
|
It performs dictionary lookups. The output still needs to be better
|
||||||
|
formatted.
|
||||||
|
|
||||||
|
To test it try (the exact format, and more examples are described in
|
||||||
|
the RFC)
|
||||||
|
|
||||||
|
dict://dict.org/m:hello
|
||||||
|
dict://dict.org/m:hello::soundex
|
||||||
|
|
||||||
|
|
||||||
|
Vicente Garcia (10 Jan 1999)
|
||||||
|
- Corrected the progress meter for files larger than 20MB.
|
||||||
|
|
||||||
|
Daniel Stenberg (7 Jan 1999)
|
||||||
|
- Corrected the -t and -T help texts. They claimed to be FTP only.
|
||||||
|
|
||||||
|
Version 5.4
|
||||||
|
|
||||||
|
Daniel Stenberg
|
||||||
|
(7 Jan 1999)
|
||||||
|
- Irving Wolfe reported that curl -s didn't always supress the progress
|
||||||
|
reporting. It was the form post that autoamtically always switched it on
|
||||||
|
again. This is now corrected!
|
||||||
|
|
||||||
|
(4 Jan 1999)
|
||||||
|
- Andreas Kostyrka suggested I'd add PUT and he helped me out to test it. If
|
||||||
|
you use -t or -T now on a http or https server, PUT will be used for file
|
||||||
|
upload.
|
||||||
|
|
||||||
|
I removed the former use of -T with HTTP. I doubt anyone ever really used
|
||||||
|
that.
|
||||||
|
|
||||||
|
(4 Jan 1999)
|
||||||
|
- Erik Jacobsen found a width bug in the mprintf() function. I corrected it
|
||||||
|
now.
|
||||||
|
|
||||||
|
(4 Jan 1999)
|
||||||
|
- As John V. Chow pointed out to me, curl accepted very limited URL sizes. It
|
||||||
|
should now accept path parts that are up to at least 4096 bytes.
|
||||||
|
|
||||||
|
- Somehow I screwed up when applying the AIX fix from Gilbert Ramirez, so
|
||||||
|
I redid that now.
|
||||||
|
|
40
CVS-INFO
40
CVS-INFO
@@ -10,14 +10,10 @@ This file is only present in the CVS - never in release archives. It contains
|
|||||||
information about other files and things that the CVS repository keeps in its
|
information about other files and things that the CVS repository keeps in its
|
||||||
inner sanctum.
|
inner sanctum.
|
||||||
|
|
||||||
Use autoconf 2.50 and no earlier. Also, try having automake 1.5 and libtool
|
Compile and build instructions follow below.
|
||||||
1.4.1 at least.
|
|
||||||
|
|
||||||
You will need perl to generate the src/hugehelp.c file. The file
|
|
||||||
src/hugehelp.c.cvs is a one-shot file that you can rename to src/hugehelp.c if
|
|
||||||
you really can't generate the true file yourself!
|
|
||||||
|
|
||||||
CHANGES.0 contains ancient changes.
|
CHANGES.0 contains ancient changes.
|
||||||
|
CHANGES.$year contains changes for the particular year.
|
||||||
|
|
||||||
memanalyze.pl is for analyzing the output generated by curl if -DMALLOCDEBUG
|
memanalyze.pl is for analyzing the output generated by curl if -DMALLOCDEBUG
|
||||||
is used when compiling
|
is used when compiling
|
||||||
@@ -26,12 +22,38 @@ you really can't generate the true file yourself!
|
|||||||
|
|
||||||
Makefile.dist is included as the root Makefile in distribution archives
|
Makefile.dist is included as the root Makefile in distribution archives
|
||||||
|
|
||||||
perl/contrib/ is a subdirectory with various perl scripts
|
perl/ is a subdirectory with various perl scripts
|
||||||
|
|
||||||
java/ is a subdirectory with the Java interface to libcurl
|
|
||||||
|
|
||||||
To build after having extracted everything from CVS, do this:
|
To build after having extracted everything from CVS, do this:
|
||||||
|
|
||||||
./buildconf
|
./buildconf
|
||||||
./configure
|
./configure
|
||||||
make
|
make
|
||||||
|
|
||||||
|
REQUIREMENTS
|
||||||
|
|
||||||
|
You need the following software installed:
|
||||||
|
|
||||||
|
o autoconf 2.50 (or later)
|
||||||
|
o automake 1.5 (or later)
|
||||||
|
o libtool 1.4 (or later)
|
||||||
|
o GNU m4 (required by autoconf)
|
||||||
|
|
||||||
|
o nroff + perl (if you don't have nroff and perl and you for some reason
|
||||||
|
don't want to install them, you can rename the source file
|
||||||
|
src/hugehelp.c.cvs to src/hugehelp.c and avoid having to generate this
|
||||||
|
file. This will of course give you an older version of the file that isn't
|
||||||
|
up-to-date. That file was checked in once and won't be updated very
|
||||||
|
regularly.)
|
||||||
|
|
||||||
|
MAC OS X
|
||||||
|
|
||||||
|
For Mac OS X users, Guido Neitzer write down the following step-by-step guide:
|
||||||
|
|
||||||
|
1. Install fink (http://fink.sourceforge.net)
|
||||||
|
2. Update fink to the newest version (with the installed fink)
|
||||||
|
3. Install the latest version of autoconf, automake and m4 with fink
|
||||||
|
4. Install version 1.4.1 of libtool - you find it in the "unstable" section
|
||||||
|
(read the manual to see how to get unstable versions)
|
||||||
|
5. Get cURL from the cvs
|
||||||
|
6. Build cURL with "./buildconf", "./configure", "make", "sudo make install"
|
||||||
|
@@ -11,7 +11,7 @@ EXTRA_DIST = \
|
|||||||
|
|
||||||
bin_SCRIPTS = curl-config
|
bin_SCRIPTS = curl-config
|
||||||
|
|
||||||
SUBDIRS = docs lib src include tests packages
|
SUBDIRS = docs lib src include tests packages multi
|
||||||
|
|
||||||
# create a root makefile in the distribution:
|
# create a root makefile in the distribution:
|
||||||
dist-hook:
|
dist-hook:
|
||||||
|
@@ -176,7 +176,7 @@ AC_DEFUN([TYPE_IN_ADDR_T],
|
|||||||
AC_DEFINE_UNQUOTED(in_addr_t, $curl_cv_in_addr_t_equiv,
|
AC_DEFINE_UNQUOTED(in_addr_t, $curl_cv_in_addr_t_equiv,
|
||||||
[type to use in place of in_addr_t if not defined])],
|
[type to use in place of in_addr_t if not defined])],
|
||||||
[#include <sys/types.h>
|
[#include <sys/types.h>
|
||||||
#include <sys/socket.h>,
|
#include <sys/socket.h>
|
||||||
#include <arpa/inet.h>])
|
#include <arpa/inet.h>])
|
||||||
])
|
])
|
||||||
|
|
||||||
|
@@ -5,7 +5,7 @@ die(){
|
|||||||
exit
|
exit
|
||||||
}
|
}
|
||||||
|
|
||||||
automake || die "The command 'automake $MAKEFILES' failed"
|
|
||||||
aclocal || die "The command 'aclocal' failed"
|
aclocal || die "The command 'aclocal' failed"
|
||||||
autoheader || die "The command 'autoheader' failed"
|
autoheader || die "The command 'autoheader' failed"
|
||||||
autoconf || die "The command 'autoconf' failed"
|
autoconf || die "The command 'autoconf' failed"
|
||||||
|
automake || die "The command 'automake $MAKEFILES' failed"
|
||||||
|
13
configure.in
13
configure.in
@@ -69,7 +69,7 @@ AC_ARG_ENABLE(debug,
|
|||||||
*) AC_MSG_RESULT(yes)
|
*) AC_MSG_RESULT(yes)
|
||||||
|
|
||||||
CPPFLAGS="$CPPFLAGS -DMALLOCDEBUG"
|
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 ],
|
esac ],
|
||||||
AC_MSG_RESULT(no)
|
AC_MSG_RESULT(no)
|
||||||
@@ -392,6 +392,10 @@ else
|
|||||||
OPENSSL_ENABLED=1)
|
OPENSSL_ENABLED=1)
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
dnl Check for the OpenSSL engine header, it is kind of "separated"
|
||||||
|
dnl from the main SSL check
|
||||||
|
AC_CHECK_HEADERS(openssl/engine.h)
|
||||||
|
|
||||||
AC_SUBST(OPENSSL_ENABLED)
|
AC_SUBST(OPENSSL_ENABLED)
|
||||||
|
|
||||||
fi
|
fi
|
||||||
@@ -469,6 +473,8 @@ else
|
|||||||
dnl is there a localtime_r()
|
dnl is there a localtime_r()
|
||||||
CURL_CHECK_LOCALTIME_R()
|
CURL_CHECK_LOCALTIME_R()
|
||||||
|
|
||||||
|
AC_CHECK_FUNCS( gmtime_r )
|
||||||
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
dnl **********************************************************************
|
dnl **********************************************************************
|
||||||
@@ -518,9 +524,9 @@ AC_HEADER_TIME
|
|||||||
# mprintf() checks:
|
# mprintf() checks:
|
||||||
|
|
||||||
# check for 'long double'
|
# check for 'long double'
|
||||||
AC_CHECK_SIZEOF(long double, 8)
|
# AC_CHECK_SIZEOF(long double, 8)
|
||||||
# check for 'long long'
|
# check for 'long long'
|
||||||
AC_CHECK_SIZEOF(long long, 4)
|
# AC_CHECK_SIZEOF(long long, 4)
|
||||||
|
|
||||||
# check for ssize_t
|
# check for ssize_t
|
||||||
AC_CHECK_TYPE(ssize_t, int)
|
AC_CHECK_TYPE(ssize_t, int)
|
||||||
@@ -591,6 +597,7 @@ AC_CONFIG_FILES([Makefile \
|
|||||||
include/Makefile \
|
include/Makefile \
|
||||||
include/curl/Makefile \
|
include/curl/Makefile \
|
||||||
src/Makefile \
|
src/Makefile \
|
||||||
|
multi/Makefile \
|
||||||
lib/Makefile \
|
lib/Makefile \
|
||||||
tests/Makefile \
|
tests/Makefile \
|
||||||
tests/data/Makefile \
|
tests/data/Makefile \
|
||||||
|
@@ -16,6 +16,7 @@ Usage: curl-config [OPTION]
|
|||||||
|
|
||||||
Available values for OPTION include:
|
Available values for OPTION include:
|
||||||
|
|
||||||
|
--cc compiler
|
||||||
--cflags pre-processor and compiler flags
|
--cflags pre-processor and compiler flags
|
||||||
--feature newline separated list of enabled features
|
--feature newline separated list of enabled features
|
||||||
--help display this help and exit
|
--help display this help and exit
|
||||||
@@ -42,6 +43,10 @@ while test $# -gt 0; do
|
|||||||
esac
|
esac
|
||||||
|
|
||||||
case "$1" in
|
case "$1" in
|
||||||
|
--cc)
|
||||||
|
echo @CC@
|
||||||
|
;;
|
||||||
|
|
||||||
--prefix)
|
--prefix)
|
||||||
echo $prefix
|
echo $prefix
|
||||||
;;
|
;;
|
||||||
|
10
docs/BUGS
10
docs/BUGS
@@ -23,11 +23,16 @@ BUGS
|
|||||||
|
|
||||||
When reporting a bug, you should include information that will help us
|
When reporting a bug, you should include information that will help us
|
||||||
understand what's wrong, what you expected to happen and how to repeat the
|
understand what's wrong, what you expected to happen and how to repeat the
|
||||||
bad behaviour. You therefore need to supply your operating system's name and
|
bad behavior. You therefore need to supply your operating system's name and
|
||||||
version number (uname -a under a unix is fine), what version of curl you're
|
version number (uname -a under a unix is fine), what version of curl you're
|
||||||
using (curl -V is fine), what URL you were working with and anything else
|
using (curl -V is fine), what URL you were working with and anything else
|
||||||
you think matters.
|
you think matters.
|
||||||
|
|
||||||
|
Since curl deals with networks, it often helps us a lot if you include a
|
||||||
|
protocol debug dump with your bug report. The output you get by using the -v
|
||||||
|
flag. Usually, you also get more info by using -i so that is likely to be
|
||||||
|
useful when reporting bugs as well.
|
||||||
|
|
||||||
If curl crashed, causing a core dump (in unix), there is hardly any use to
|
If curl crashed, causing a core dump (in unix), there is hardly any use to
|
||||||
send that huge file to anyone of us. Unless we have an exact same system
|
send that huge file to anyone of us. Unless we have an exact same system
|
||||||
setup as you, we can't do much with it. What we instead ask of you is to get
|
setup as you, we can't do much with it. What we instead ask of you is to get
|
||||||
@@ -36,8 +41,7 @@ BUGS
|
|||||||
The address and how to subscribe to the mailing list is detailed in the
|
The address and how to subscribe to the mailing list is detailed in the
|
||||||
MANUAL file.
|
MANUAL file.
|
||||||
|
|
||||||
How To Get A Stack Trace
|
HOW TO GET A STACK TRACE
|
||||||
========================
|
|
||||||
|
|
||||||
First, you must make sure that you compile all sources with -g and that you
|
First, you must make sure that you compile all sources with -g and that you
|
||||||
don't 'strip' the final executable. Try to avoid optimizing the code as
|
don't 'strip' the final executable. Try to avoid optimizing the code as
|
||||||
|
45
docs/FAQ
45
docs/FAQ
@@ -1,4 +1,4 @@
|
|||||||
Updated: November 27, 2001 (http://curl.haxx.se/docs/faq.shtml)
|
Updated: January 22, 2002 (http://curl.haxx.se/docs/faq.shtml)
|
||||||
_ _ ____ _
|
_ _ ____ _
|
||||||
___| | | | _ \| |
|
___| | | | _ \| |
|
||||||
/ __| | | | |_) | |
|
/ __| | | | |_) | |
|
||||||
@@ -33,7 +33,7 @@ FAQ
|
|||||||
3.6 Does curl support javascript, ASP, XML, XHTML or HTML version Y?
|
3.6 Does curl support javascript, ASP, XML, XHTML or HTML version Y?
|
||||||
3.7 Can I use curl to delete/rename a file through FTP?
|
3.7 Can I use curl to delete/rename a file through FTP?
|
||||||
3.8 How do I tell curl to follow HTTP redirects?
|
3.8 How do I tell curl to follow HTTP redirects?
|
||||||
3.9 How do I use curl in PHP, Perl, Tcl, Ruby or Java?
|
3.9 How do I use curl in my favourite programming language?
|
||||||
3.10 What about SOAP, WebDAV, XML-RPC or similar protocols over HTTP?
|
3.10 What about SOAP, WebDAV, XML-RPC or similar protocols over HTTP?
|
||||||
3.11 How do I POST with a different Content-Type?
|
3.11 How do I POST with a different Content-Type?
|
||||||
3.12 Why do FTP specific features over HTTP proxy fail?
|
3.12 Why do FTP specific features over HTTP proxy fail?
|
||||||
@@ -49,6 +49,7 @@ FAQ
|
|||||||
4.5.3 "403 Forbidden"
|
4.5.3 "403 Forbidden"
|
||||||
4.5.4 "404 Not Found"
|
4.5.4 "404 Not Found"
|
||||||
4.5.5 "405 Method Not Allowed"
|
4.5.5 "405 Method Not Allowed"
|
||||||
|
4.5.6 "301 Moved Permanently"
|
||||||
4.6 Can you tell me what error code 142 means?
|
4.6 Can you tell me what error code 142 means?
|
||||||
4.7 How do I keep user names and passwords secret in Curl command lines?
|
4.7 How do I keep user names and passwords secret in Curl command lines?
|
||||||
4.8 I found a bug!
|
4.8 I found a bug!
|
||||||
@@ -162,9 +163,8 @@ FAQ
|
|||||||
|
|
||||||
1.6 What do you get for making cURL?
|
1.6 What do you get for making cURL?
|
||||||
|
|
||||||
Project cURL is entirely free and open, without any commercial interests or
|
Project cURL is entirely free and open. No person gets paid in any way for
|
||||||
money involved. No person gets paid in any way for developing curl. We all
|
developing curl. We all do this voluntarily on our spare time.
|
||||||
do this voluntarily on our spare time.
|
|
||||||
|
|
||||||
We get some help from companies. Contactor Data hosts the curl web site and
|
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
|
the main mailing list, Haxx owns the curl web site's domain and
|
||||||
@@ -334,11 +334,12 @@ FAQ
|
|||||||
|
|
||||||
curl -L http://redirector.com
|
curl -L http://redirector.com
|
||||||
|
|
||||||
3.9 How do I use curl in PHP, Perl, Tcl, Ruby or Java?
|
3.9 How do I use curl in my favourite programming language?
|
||||||
|
|
||||||
There exist many language-interfaces for curl that integrates it better with
|
There exist many language interfaces/bindings for curl that integrates it
|
||||||
various languages. If you are fluid in a script language, you may very well
|
better with various languages. If you are fluid in a script language, you
|
||||||
opt to use such an interface instead of using the command line tool.
|
may very well opt to use such an interface instead of using the command line
|
||||||
|
tool.
|
||||||
|
|
||||||
At the time of writing, there are bindings for the five language mentioned
|
At the time of writing, there are bindings for the five language mentioned
|
||||||
above, but chances are there are even more by the time you read this. Or you
|
above, but chances are there are even more by the time you read this. Or you
|
||||||
@@ -349,16 +350,9 @@ FAQ
|
|||||||
|
|
||||||
http://curl.haxx.se/libcurl/
|
http://curl.haxx.se/libcurl/
|
||||||
|
|
||||||
PHP4 has the ability to use libcurl as an internal module if built with that
|
In December 2001, there are interfaces available for the following
|
||||||
option enabled. You then get a set of extra functions that can be used
|
languages: C/C++, Cocoa, Dylan, Java, Perl, PHP, Python, Rexx, Ruby, Scheme
|
||||||
within your PHP programs. You find all details about those functions in the
|
and Tcl. By the time you read this, additional ones may have appeared!
|
||||||
curl section in the PHP manual, see the online version at:
|
|
||||||
|
|
||||||
http://www.php.net/manual/ref.curl.php
|
|
||||||
|
|
||||||
PHP also offers the option to run a command line, and then you can of course
|
|
||||||
invoke the curl tool using a command line. This is the way to use curl if
|
|
||||||
you're using PHP3 or PHP4 built without curl module support.
|
|
||||||
|
|
||||||
3.10 What about SOAP, WebDAV, XML-RPC or similar protocols over HTTP?
|
3.10 What about SOAP, WebDAV, XML-RPC or similar protocols over HTTP?
|
||||||
|
|
||||||
@@ -386,7 +380,7 @@ FAQ
|
|||||||
|
|
||||||
There is one exception to this rule, and that is if you can "tunnel through"
|
There is one exception to this rule, and that is if you can "tunnel through"
|
||||||
the given HTTP proxy. Proxy tunneling is enabled with a special option (-p)
|
the given HTTP proxy. Proxy tunneling is enabled with a special option (-p)
|
||||||
and is generally not available as proxy admins usuable disable tunneling to
|
and is generally not available as proxy admins usually disable tunneling to
|
||||||
other ports than 443 (which is used for HTTPS access through proxies).
|
other ports than 443 (which is used for HTTPS access through proxies).
|
||||||
|
|
||||||
4. Running Problems
|
4. Running Problems
|
||||||
@@ -478,6 +472,17 @@ FAQ
|
|||||||
identified by the Request-URI. The response MUST include an Allow header
|
identified by the Request-URI. The response MUST include an Allow header
|
||||||
containing a list of valid methods for the requested resource.
|
containing a list of valid methods for the requested resource.
|
||||||
|
|
||||||
|
4.5.6 "301 Moved Permanently"
|
||||||
|
|
||||||
|
If you get this return code and an HTML outpt similar to this:
|
||||||
|
|
||||||
|
<H1>Moved Permanently</H1> The document has moved <A
|
||||||
|
HREF="http://same_url_now_with_a_trailing_slash/">here</A>.
|
||||||
|
|
||||||
|
it might be because you request a directory URL but without the trailing
|
||||||
|
slash. Try the same operation again _with_ the trailing URL, or use the
|
||||||
|
-L/--location option to follow the redirection.
|
||||||
|
|
||||||
4.6. Can you tell me what error code 142 means?
|
4.6. Can you tell me what error code 142 means?
|
||||||
|
|
||||||
All error codes that are larger than the highest documented error code means
|
All error codes that are larger than the highest documented error code means
|
||||||
|
22
docs/INSTALL
22
docs/INSTALL
@@ -179,8 +179,8 @@ Win32
|
|||||||
to use out-of-the-box.
|
to use out-of-the-box.
|
||||||
|
|
||||||
Microsoft note: add /Zm200 to the compiler options to increase the
|
Microsoft note: add /Zm200 to the compiler options to increase the
|
||||||
compiler's memory allocation limit, as the hugehelp.c won't compile
|
compiler's memory allocation limit, as the hugehelp.c won't compile
|
||||||
due to "too long puts string".
|
due to "too long puts string".
|
||||||
|
|
||||||
|
|
||||||
With SSL:
|
With SSL:
|
||||||
@@ -322,6 +322,20 @@ VMS
|
|||||||
13-jul-2001
|
13-jul-2001
|
||||||
N. Baggus
|
N. Baggus
|
||||||
|
|
||||||
|
QNX
|
||||||
|
===
|
||||||
|
(This section was graciously brought to us by David Bentham)
|
||||||
|
|
||||||
|
As QNX is targetted for resource constrained environments, the QNX headers
|
||||||
|
set conservative limits. This includes the FD_SETSIZE macro, set by default
|
||||||
|
to 32. Socket descriptors returned within the CURL library may exceed this,
|
||||||
|
resulting in memory faults/SIGSEGV crashes when passed into select(..)
|
||||||
|
calls using fd_set macros.
|
||||||
|
|
||||||
|
A good all-round solution to this is to override the default when building
|
||||||
|
libcurl, by overriding CFLAGS during configure, example
|
||||||
|
# configure CFLAGS='-DFD_SETSIZE=64 -g -O2'
|
||||||
|
|
||||||
CROSS COMPILE
|
CROSS COMPILE
|
||||||
=============
|
=============
|
||||||
|
|
||||||
@@ -364,7 +378,8 @@ CROSS COMPILE
|
|||||||
PORTS
|
PORTS
|
||||||
=====
|
=====
|
||||||
This is a probably incomplete list of known hardware and operating systems
|
This is a probably incomplete list of known hardware and operating systems
|
||||||
that curl has been compiled for:
|
that curl has been compiled for. If you know one system curl compiles and
|
||||||
|
runs on, that isn't listed, please let us know!
|
||||||
|
|
||||||
- Alpha DEC OSF 4
|
- Alpha DEC OSF 4
|
||||||
- Alpha Digital UNIX v3.2
|
- Alpha Digital UNIX v3.2
|
||||||
@@ -391,6 +406,7 @@ PORTS
|
|||||||
- Ultrix 4.3a
|
- Ultrix 4.3a
|
||||||
- i386 BeOS
|
- i386 BeOS
|
||||||
- i386 FreeBSD
|
- i386 FreeBSD
|
||||||
|
- i386 HURD
|
||||||
- i386 Linux 1.3, 2.0, 2.2, 2.3, 2.4
|
- i386 Linux 1.3, 2.0, 2.2, 2.3, 2.4
|
||||||
- i386 NetBSD
|
- i386 NetBSD
|
||||||
- i386 OS/2
|
- i386 OS/2
|
||||||
|
@@ -601,15 +601,15 @@ RESUMING FILE TRANSFERS
|
|||||||
|
|
||||||
Continue downloading a document:
|
Continue downloading a document:
|
||||||
|
|
||||||
curl -c -o file ftp://ftp.server.com/path/file
|
curl -C - -o file ftp://ftp.server.com/path/file
|
||||||
|
|
||||||
Continue uploading a document(*1):
|
Continue uploading a document(*1):
|
||||||
|
|
||||||
curl -c -T file ftp://ftp.server.com/path/file
|
curl -C - -T file ftp://ftp.server.com/path/file
|
||||||
|
|
||||||
Continue downloading a document from a web server(*2):
|
Continue downloading a document from a web server(*2):
|
||||||
|
|
||||||
curl -c -o file http://www.server.com/
|
curl -C - -o file http://www.server.com/
|
||||||
|
|
||||||
(*1) = This requires that the ftp server supports the non-standard command
|
(*1) = This requires that the ftp server supports the non-standard command
|
||||||
SIZE. If it doesn't, curl will say so.
|
SIZE. If it doesn't, curl will say so.
|
||||||
|
@@ -76,3 +76,6 @@ that have contributed with non-trivial parts:
|
|||||||
- Tomasz Lacki <Tomasz.Lacki@primark.pl>
|
- Tomasz Lacki <Tomasz.Lacki@primark.pl>
|
||||||
- Georg Huettenegger <georg@ist.org>
|
- Georg Huettenegger <georg@ist.org>
|
||||||
- John Lask <johnlask@hotmail.com>
|
- John Lask <johnlask@hotmail.com>
|
||||||
|
- Eric Lavigne <erlavigne@wanadoo.fr>
|
||||||
|
- Marcus Webster <marcus.webster@phocis.com>
|
||||||
|
- G<>tz Babin-Ebell <babin<69>ebell@trustcenter.de>
|
||||||
|
84
docs/TODO
84
docs/TODO
@@ -19,10 +19,7 @@ TODO
|
|||||||
|
|
||||||
* The new 'multi' interface is being designed. Work out the details, start
|
* The new 'multi' interface is being designed. Work out the details, start
|
||||||
implementing and write test applications!
|
implementing and write test applications!
|
||||||
[http://curl.haxx.se/dev/multi.h]
|
[http://curl.haxx.se/lxr/source/lib/multi.h]
|
||||||
|
|
||||||
* Add a name resolve cache to libcurl to make repeated fetches to the same
|
|
||||||
host name (when persitancy isn't available) faster.
|
|
||||||
|
|
||||||
* Introduce another callback interface for upload/download that makes one
|
* Introduce another callback interface for upload/download that makes one
|
||||||
less copy of data and thus a faster operation.
|
less copy of data and thus a faster operation.
|
||||||
@@ -33,11 +30,36 @@ TODO
|
|||||||
telnet, ldap, dict or file.
|
telnet, ldap, dict or file.
|
||||||
|
|
||||||
* Add asynchronous name resolving. http://curl.haxx.se/dev/async-resolver.txt
|
* 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.
|
||||||
|
|
||||||
|
* 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
|
DOCUMENTATION
|
||||||
|
|
||||||
* Document all CURLcode error codes, why they happen and what most likely
|
* 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
|
FTP
|
||||||
|
|
||||||
@@ -52,11 +74,7 @@ TODO
|
|||||||
already working http dito works. It of course requires that 'MDTM' works,
|
already working http dito works. It of course requires that 'MDTM' works,
|
||||||
and it isn't a standard FTP command.
|
and it isn't a standard FTP command.
|
||||||
|
|
||||||
* Suggested on the mailing list: CURLOPT_FTP_MKDIR...!
|
* Add FTPS support with SSL for the data connection too.
|
||||||
|
|
||||||
* 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!
|
|
||||||
|
|
||||||
HTTP
|
HTTP
|
||||||
|
|
||||||
@@ -81,34 +99,53 @@ TODO
|
|||||||
http://www.innovation.ch/java/ntlm.html that contains detailed reverse-
|
http://www.innovation.ch/java/ntlm.html that contains detailed reverse-
|
||||||
engineered info.
|
engineered info.
|
||||||
|
|
||||||
* RFC2617 compliance, "Digest Access Authentication"
|
* RFC2617 compliance, "Digest Access Authentication" A valid test page seem
|
||||||
A valid test page seem to exist at:
|
to exist at: http://hopf.math.nwu.edu/testpage/digest/ And some friendly
|
||||||
http://hopf.math.nwu.edu/testpage/digest/
|
person's server source code is available at
|
||||||
And some friendly person's server source code is available at
|
http://hopf.math.nwu.edu/digestauth/index.html Then there's the Apache
|
||||||
http://hopf.math.nwu.edu/digestauth/index.html
|
mod_digest source code too of course. It seems as if Netscape doesn't
|
||||||
Then there's the Apache mod_digest source code too of course. It seems as
|
support this, and not many servers do. Although this is a lot better
|
||||||
if Netscape doesn't support this, and not many servers do. Although this is
|
authentication method than the more common "Basic". Basic sends the
|
||||||
a lot better authentication method than the more common "Basic". Basic
|
password in cleartext over the network, this "Digest" method uses a
|
||||||
sends the password in cleartext over the network, this "Digest" method uses
|
challange-response protocol which increases security quite a lot.
|
||||||
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
|
TELNET
|
||||||
|
|
||||||
* Make TELNET work on windows98!
|
* 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
|
SSL
|
||||||
|
|
||||||
* Add an interface to libcurl that enables "session IDs" to get
|
* Add an interface to libcurl that enables "session IDs" to get
|
||||||
exported/imported. Cris Bailiff said: "OpenSSL has functions which can
|
exported/imported. Cris Bailiff said: "OpenSSL has functions which can
|
||||||
serialise the current SSL state to a buffer of your choice, and
|
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
|
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.
|
* Make curl's SSL layer option capable of using other free SSL libraries.
|
||||||
Such as the Mozilla Security Services
|
Such as the Mozilla Security Services
|
||||||
(http://www.mozilla.org/projects/security/pki/nss/) and GNUTLS
|
(http://www.mozilla.org/projects/security/pki/nss/) and GNUTLS
|
||||||
(http://gnutls.hellug.gr/)
|
(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
|
CLIENT
|
||||||
|
|
||||||
* "curl ftp://site.com/*.txt"
|
* "curl ftp://site.com/*.txt"
|
||||||
@@ -117,6 +154,11 @@ TODO
|
|||||||
the same syntax to specify several files to get uploaded (using the same
|
the same syntax to specify several files to get uploaded (using the same
|
||||||
persistant connection), using -T.
|
persistant connection), using -T.
|
||||||
|
|
||||||
|
* 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
|
TEST SUITE
|
||||||
|
|
||||||
* Extend the test suite to include more protocols. The telnet could just do
|
* Extend the test suite to include more protocols. The telnet could just do
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
.\" nroff -man curl-config.1
|
.\" nroff -man curl-config.1
|
||||||
.\" Written by Daniel Stenberg
|
.\" 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
|
.SH NAME
|
||||||
curl-config \- Get information about a libcurl installation
|
curl-config \- Get information about a libcurl installation
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
@@ -11,6 +11,8 @@ curl-config \- Get information about a libcurl installation
|
|||||||
.B curl-config
|
.B curl-config
|
||||||
displays information about a previous curl and libcurl installation.
|
displays information about a previous curl and libcurl installation.
|
||||||
.SH OPTIONS
|
.SH OPTIONS
|
||||||
|
.IP "--cc"
|
||||||
|
Displays the compiler used to build libcurl.
|
||||||
.IP "--cflags"
|
.IP "--cflags"
|
||||||
Set of compiler options (CFLAGS) to use when compiling files that use
|
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.
|
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"
|
.SH "EXAMPLES"
|
||||||
What linker options do I need when I link with libcurl?
|
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?
|
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?
|
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?
|
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"
|
.SH "SEE ALSO"
|
||||||
.BR curl (1)
|
.BR curl (1)
|
||||||
|
12
docs/curl.1
12
docs/curl.1
@@ -4,8 +4,7 @@
|
|||||||
.\"
|
.\"
|
||||||
.TH curl 1 "30 Nov 2001" "Curl 7.9.2" "Curl Manual"
|
.TH curl 1 "30 Nov 2001" "Curl 7.9.2" "Curl Manual"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
curl \- get a URL with FTP, TELNET, LDAP, GOPHER, DICT, FILE, HTTP or
|
curl \- transfer a URL
|
||||||
HTTPS syntax.
|
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
.B curl [options]
|
.B curl [options]
|
||||||
.I [URL...]
|
.I [URL...]
|
||||||
@@ -677,7 +676,7 @@ If this option is used several times, the last one will be used.
|
|||||||
Default config file.
|
Default config file.
|
||||||
|
|
||||||
.SH ENVIRONMENT
|
.SH ENVIRONMENT
|
||||||
.IP "HTTP_PROXY [protocol://]<host>[:port]"
|
.IP "http_proxy [protocol://]<host>[:port]"
|
||||||
Sets proxy server to use for HTTP.
|
Sets proxy server to use for HTTP.
|
||||||
.IP "HTTPS_PROXY [protocol://]<host>[:port]"
|
.IP "HTTPS_PROXY [protocol://]<host>[:port]"
|
||||||
Sets proxy server to use for HTTPS.
|
Sets proxy server to use for HTTPS.
|
||||||
@@ -688,11 +687,8 @@ Sets proxy server to use for GOPHER.
|
|||||||
.IP "ALL_PROXY [protocol://]<host>[:port]"
|
.IP "ALL_PROXY [protocol://]<host>[:port]"
|
||||||
Sets proxy server to use if no protocol-specific proxy is set.
|
Sets proxy server to use if no protocol-specific proxy is set.
|
||||||
.IP "NO_PROXY <comma-separated list of hosts>"
|
.IP "NO_PROXY <comma-separated list of hosts>"
|
||||||
list of host names that shouldn't go through any proxy. If set to a
|
list of host names that shouldn't go through any proxy. If set to a asterisk
|
||||||
asterisk '*' only, it matches all hosts.
|
'*' only, it matches all hosts.
|
||||||
.IP "COLUMNS <integer>"
|
|
||||||
The width of the terminal. This variable only affects curl when the
|
|
||||||
--progress-bar option is used.
|
|
||||||
.SH EXIT CODES
|
.SH EXIT CODES
|
||||||
There exists a bunch of different error codes and their corresponding error
|
There exists a bunch of different error codes and their corresponding error
|
||||||
messages that may appear during bad conditions. At the time of this writing,
|
messages that may appear during bad conditions. At the time of this writing,
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
.\" nroff -man [file]
|
.\" nroff -man [file]
|
||||||
.\" $Id$
|
.\" $Id$
|
||||||
.\"
|
.\"
|
||||||
.TH curl_easy_setopt 3 "30 Nov 2001" "libcurl 7.9.2" "libcurl Manual"
|
.TH curl_easy_setopt 3 "10 Dec 2001" "libcurl 7.9.2" "libcurl Manual"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
curl_easy_setopt - Set curl easy-session options
|
curl_easy_setopt - Set curl easy-session options
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
@@ -77,9 +77,8 @@ function gets called by libcurl as soon as it needs to read data in order to
|
|||||||
send it to the peer. The data area pointed at by the pointer \fIptr\fP may be
|
send it to the peer. The data area pointed at by the pointer \fIptr\fP may be
|
||||||
filled with at most \fIsize\fP multiplied with \fInmemb\fP number of
|
filled with at most \fIsize\fP multiplied with \fInmemb\fP number of
|
||||||
bytes. Your function must return the actual number of bytes that you stored in
|
bytes. Your function must return the actual number of bytes that you stored in
|
||||||
that memory area. Returning -1 will signal an error to the library and cause
|
that memory area. Returning 0 will signal end-of-file to the library and cause
|
||||||
it to abort the current transfer immediately (with a \fICURLE_READ_ERROR\fP
|
it to stop the current transfer.
|
||||||
return code).
|
|
||||||
.TP
|
.TP
|
||||||
.B CURLOPT_INFILESIZE
|
.B CURLOPT_INFILESIZE
|
||||||
When uploading a file to a remote site, this option should be used to tell
|
When uploading a file to a remote site, this option should be used to tell
|
||||||
@@ -320,13 +319,54 @@ with \fIcurl_easy_cleanup(3)\fP.
|
|||||||
.TP
|
.TP
|
||||||
.B CURLOPT_SSLCERT
|
.B CURLOPT_SSLCERT
|
||||||
Pass a pointer to a zero terminated string as parameter. The string should be
|
Pass a pointer to a zero terminated string as parameter. The string should be
|
||||||
the file name of your certificate in PEM format.
|
the file name of your certificate. The default format is "PEM" and can be
|
||||||
|
changed with \fICURLOPT_SSLCERTTYPE\fP.
|
||||||
|
.TP
|
||||||
|
.B CURLOPT_SSLCERTTYPE
|
||||||
|
Pass a pointer to a zero terminated string as parameter. The string should be
|
||||||
|
the format of your certificate. Supported formats are "PEM" and "DER".
|
||||||
.TP
|
.TP
|
||||||
.B CURLOPT_SSLCERTPASSWD
|
.B CURLOPT_SSLCERTPASSWD
|
||||||
Pass a pointer to a zero terminated string as parameter. It will be used as
|
Pass a pointer to a zero terminated string as parameter. It will be used as
|
||||||
the password required to use the CURLOPT_SSLCERT certificate. If the password
|
the password required to use the CURLOPT_SSLCERT certificate. If the password
|
||||||
is not supplied, you will be prompted for it. \fICURLOPT_PASSWDFUNCTION\fP can
|
is not supplied, you will be prompted for it. \fICURLOPT_PASSWDFUNCTION\fP can
|
||||||
be used to set your own prompt function.
|
be used to set your own prompt function.
|
||||||
|
|
||||||
|
\fBNOTE:\fPThis option is replaced by \fICURLOPT_SSLKEYPASSWD\fP and only
|
||||||
|
cept for backward compatibility. You never needed a pass phrase to load
|
||||||
|
a certificate but you need one to load your private key.
|
||||||
|
.TP
|
||||||
|
.B CURLOPT_SSLKEY
|
||||||
|
Pass a pointer to a zero terminated string as parameter. The string should be
|
||||||
|
the file name of your private key. The default format is "PEM" and can be
|
||||||
|
changed with \fICURLOPT_SSLKEYTYPE\fP.
|
||||||
|
.TP
|
||||||
|
.B CURLOPT_SSLKEYTYPE
|
||||||
|
Pass a pointer to a zero terminated string as parameter. The string should be
|
||||||
|
the format of your private key. Supported formats are "PEM", "DER" and "ENG".
|
||||||
|
|
||||||
|
\fBNOTE:\fPThe format "ENG" enables you to load the private key from a crypto
|
||||||
|
engine. in this case \fICURLOPT_SSLKEY\fP is used as an identifier passed to
|
||||||
|
the engine. You have to set the crypto engine with \fICURLOPT_SSL_ENGINE\fP.
|
||||||
|
.TP
|
||||||
|
.B CURLOPT_SSLKEYASSWD
|
||||||
|
Pass a pointer to a zero terminated string as parameter. It will be used as
|
||||||
|
the password required to use the \fICURLOPT_SSLKEY\fP private key. If the password
|
||||||
|
is not supplied, you will be prompted for it. \fICURLOPT_PASSWDFUNCTION\fP can
|
||||||
|
be used to set your own prompt function.
|
||||||
|
.TP
|
||||||
|
.B CURLOPT_SSL_ENGINE
|
||||||
|
Pass a pointer to a zero terminated string as parameter. It will be used as
|
||||||
|
the identifier for the crypto engine you want to use for your private key.
|
||||||
|
|
||||||
|
\fBNOTE:\fPIf the crypto device cannot be loaded, \fICURLE_SSL_ENGINE_NOTFOUND\fP
|
||||||
|
is returned.
|
||||||
|
.TP
|
||||||
|
.B CURLOPT_SSL_ENGINEDEFAULT
|
||||||
|
Sets the actual crypto engine as the default for (asymetric) crypto operations.
|
||||||
|
|
||||||
|
\fBNOTE:\fPIf the crypto device cannot be set, \fICURLE_SSL_ENGINE_SETFAILED\fP
|
||||||
|
is returned.
|
||||||
.TP
|
.TP
|
||||||
.B CURLOPT_CRLF
|
.B CURLOPT_CRLF
|
||||||
Convert Unix newlines to CRLF newlines on FTP uploads.
|
Convert Unix newlines to CRLF newlines on FTP uploads.
|
||||||
|
@@ -58,6 +58,13 @@ are allowed. The effect of this parameter is the same as giving multiple
|
|||||||
\fBCURLFORM_FILE\fP options possibly with \fBCURLFORM_CONTENTTYPE\fP after or
|
\fBCURLFORM_FILE\fP options possibly with \fBCURLFORM_CONTENTTYPE\fP after or
|
||||||
before each \fBCURLFORM_FILE\fP option.
|
before each \fBCURLFORM_FILE\fP option.
|
||||||
|
|
||||||
|
Should you need to specify extra headers for the form POST section, use
|
||||||
|
\fBCURLFORM_CONTENTHEADER\fP. This takes a curl_slist prepared in the usual way
|
||||||
|
using \fBcurl_slist_append\fP and appends the list of headers to those Curl
|
||||||
|
automatically generates for \fBCURLFORM_CONTENTTYPE\fP and the content
|
||||||
|
disposition. The list must exist while the POST occurs, if you free it before
|
||||||
|
the post completes you may experience problems.
|
||||||
|
|
||||||
The last argument in such an array must always be \fBCURLFORM_END\fP.
|
The last argument in such an array must always be \fBCURLFORM_END\fP.
|
||||||
|
|
||||||
The pointers \fI*firstitem\fP and \fI*lastitem\fP should both be pointing to
|
The pointers \fI*firstitem\fP and \fI*lastitem\fP should both be pointing to
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
.\" nroff -man [file]
|
.\" nroff -man [file]
|
||||||
.\" $Id$
|
.\" $Id$
|
||||||
.\"
|
.\"
|
||||||
.TH curl_formparse 3 "21 May 2001" "libcurl 7.7.4" "libcurl Manual"
|
.TH curl_formparse 3 "17 Dec 2001" "libcurl 7.9.2" "libcurl Manual"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
curl_formparse - add a section to a multipart/formdata HTTP POST:
|
curl_formparse - add a section to a multipart/formdata HTTP POST:
|
||||||
deprecated (use curl_formadd instead)
|
deprecated (use curl_formadd instead)
|
||||||
@@ -13,75 +13,6 @@ deprecated (use curl_formadd instead)
|
|||||||
.BI "struct HttpPost ** " lastitem ");"
|
.BI "struct HttpPost ** " lastitem ");"
|
||||||
.ad
|
.ad
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
curl_formparse() is used to append sections when building a multipart/formdata
|
This has been removed deliberately. The \fBcurl_formadd\fP has been introduced
|
||||||
HTTP POST (sometimes refered to as rfc1867-style posts). Append one section at
|
to replace this function. Do not use this. Convert to the new function
|
||||||
a time until you've added all the sections you want included and then you pass
|
now. curl_formparse() will be removed from a future version of libcurl.
|
||||||
the \fIfirstitem\fP pointer as parameter to \fBCURLOPT_HTTPPOST\fP.
|
|
||||||
\fIlastitem\fP is set after each call and on repeated invokes it should be
|
|
||||||
left as set to allow repeated invokes to find the end of the list in a faster
|
|
||||||
way. \fIstring\fP must be a zero terminated string abiding to the syntax
|
|
||||||
described in a section below
|
|
||||||
|
|
||||||
The pointers \fI*firstitem\fP and \fI*lastitem\fP should both be pointing to
|
|
||||||
NULL in the first call to this function. All list-data will be allocated by
|
|
||||||
the function itself. You must call \fIcurl_formfree\fP after the form post has
|
|
||||||
been done to free the resources again.
|
|
||||||
|
|
||||||
This function will copy all input data and keep its own version of it
|
|
||||||
allocated until you call \fIcurl_formfree\fP. When you've passed the pointer
|
|
||||||
to \fIcurl_easy_setopt\fP, you must not free the list until after you've
|
|
||||||
called \fIcurl_easy_cleanup\fP for the curl handle.
|
|
||||||
|
|
||||||
See example below.
|
|
||||||
.SH "FORM PARSE STRINGS"
|
|
||||||
The
|
|
||||||
.I string
|
|
||||||
parameter must be using one of the following patterns. Note that the []
|
|
||||||
letters should not be included in the real-life string.
|
|
||||||
.TP 0.8i
|
|
||||||
.B [name]=[contents]
|
|
||||||
Add a form field named 'name' with the contents 'contents'. This is the
|
|
||||||
typcial contents of the HTML tag <input type=text>.
|
|
||||||
.TP
|
|
||||||
.B [name]=@[filename]
|
|
||||||
Add a form field named 'name' with the contents as read from the local file
|
|
||||||
named 'filename'. This is the typcial contents of the HTML tag <input
|
|
||||||
type=file>.
|
|
||||||
.TP
|
|
||||||
.B [name]=@[filename1,filename2,...]
|
|
||||||
Add a form field named 'name' with the contents as read from the local files
|
|
||||||
named 'filename1' and 'filename2'. This is identical to the upper, except that
|
|
||||||
you get the contents of several files in one section.
|
|
||||||
.TP
|
|
||||||
.B [name]=@[filename];[type=<content-type>]
|
|
||||||
Whenever you specify a file to read from, you can optionally specify the
|
|
||||||
content-type as well. The content-type is passed to the server together with
|
|
||||||
the contents of the file. curl_formparse() will guess content-type for a
|
|
||||||
number of well-known extensions and otherwise it will set it to binary. You
|
|
||||||
can override the internal decision by using this option.
|
|
||||||
.TP
|
|
||||||
.B [name]=@[filename1,filename2,...];[type=<content-type>]
|
|
||||||
When you specify several files to read the contents from, you can set the
|
|
||||||
content-type for all of them in the same way as with a single file.
|
|
||||||
.PP
|
|
||||||
.SH RETURN VALUE
|
|
||||||
Returns non-zero if an error occurs.
|
|
||||||
.SH EXAMPLE
|
|
||||||
|
|
||||||
HttpPost* post = NULL;
|
|
||||||
HttpPost* last = NULL;
|
|
||||||
|
|
||||||
/* Add an image section */
|
|
||||||
curl_formparse("picture=@my-face.jpg", &post, &last);
|
|
||||||
/* Add a normal text section */
|
|
||||||
curl_formparse("name=FooBar", &post, &last);
|
|
||||||
/* Set the form info */
|
|
||||||
curl_easy_setopt(curl, CURLOPT_HTTPPOST, post);
|
|
||||||
|
|
||||||
.SH "SEE ALSO"
|
|
||||||
.BR curl_easy_setopt "(3), "
|
|
||||||
.BR curl_formadd "(3), "
|
|
||||||
.BR curl_formfree "(3)
|
|
||||||
.SH BUGS
|
|
||||||
Surely there are some, you tell me!
|
|
||||||
|
|
||||||
|
@@ -6,7 +6,8 @@ AUTOMAKE_OPTIONS = foreign no-dependencies
|
|||||||
|
|
||||||
EXTRA_DIST = README curlgtk.c sepheaders.c simple.c postit.c postit2.c \
|
EXTRA_DIST = README curlgtk.c sepheaders.c simple.c postit.c postit2.c \
|
||||||
win32sockets.c persistant.c ftpget.c Makefile.example \
|
win32sockets.c persistant.c ftpget.c Makefile.example \
|
||||||
multithread.c getinmemory.c ftpupload.c httpput.c
|
multithread.c getinmemory.c ftpupload.c httpput.c \
|
||||||
|
simplessl.c ftpgetresp.c http-post.c
|
||||||
|
|
||||||
all:
|
all:
|
||||||
@echo "done"
|
@echo "done"
|
||||||
|
@@ -10,6 +10,10 @@ them for submission in future packages and on the web site.
|
|||||||
The Makefile.example is an example makefile that could be used to build these
|
The Makefile.example is an example makefile that could be used to build these
|
||||||
examples. Just edit the file according to your system and requirements first.
|
examples. Just edit the file according to your system and requirements first.
|
||||||
|
|
||||||
|
Most examples should build fine using a command line like this:
|
||||||
|
|
||||||
|
$ gcc `curl-config --cflags` `curl-config --libs` -o example example.c
|
||||||
|
|
||||||
Try the php/examples/ directory for PHP programming snippets!
|
Try the php/examples/ directory for PHP programming snippets!
|
||||||
|
|
||||||
*PLEASE* do not use the curl.haxx.se site as a test target for your libcurl
|
*PLEASE* do not use the curl.haxx.se site as a test target for your libcurl
|
||||||
|
@@ -14,31 +14,70 @@
|
|||||||
#include <curl/types.h>
|
#include <curl/types.h>
|
||||||
#include <curl/easy.h>
|
#include <curl/easy.h>
|
||||||
|
|
||||||
/* to make this work under windows, use the win32-functions from the
|
/*
|
||||||
win32socket.c file as well */
|
* This is an example showing how to get a single file from an FTP server.
|
||||||
|
* It delays the actual destination file creation until the first write
|
||||||
|
* callback so that it won't create an empty file in case the remote file
|
||||||
|
* doesn't exist or something else fails.
|
||||||
|
*/
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
struct FtpFile {
|
||||||
|
char *filename;
|
||||||
|
FILE *stream;
|
||||||
|
};
|
||||||
|
|
||||||
|
int my_fwrite(void *buffer, size_t size, size_t nmemb, void *stream)
|
||||||
|
{
|
||||||
|
struct FtpFile *out=(struct FtpFile *)stream;
|
||||||
|
if(out && !out->stream) {
|
||||||
|
/* open file for writing */
|
||||||
|
out->stream=fopen(out->filename, "wb");
|
||||||
|
if(!out->stream)
|
||||||
|
return -1; /* failure, can't open file to write */
|
||||||
|
}
|
||||||
|
return fwrite(buffer, size, nmemb, out->stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main(void)
|
||||||
{
|
{
|
||||||
CURL *curl;
|
CURL *curl;
|
||||||
CURLcode res;
|
CURLcode res;
|
||||||
FILE *ftpfile;
|
struct FtpFile ftpfile={
|
||||||
|
"curl.tar.gz", /* name to store the file as if succesful */
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
/* local file name to store the file as */
|
curl_global_init(CURL_GLOBAL_DEFAULT);
|
||||||
ftpfile = fopen("curl.tar.gz", "wb"); /* b is binary for win */
|
|
||||||
|
|
||||||
curl = curl_easy_init();
|
curl = curl_easy_init();
|
||||||
if(curl) {
|
if(curl) {
|
||||||
/* Get curl 7.7 from sunet.se's FTP site: */
|
/* Get curl 7.9.2 from sunet.se's FTP site: */
|
||||||
curl_easy_setopt(curl, CURLOPT_URL,
|
curl_easy_setopt(curl, CURLOPT_URL,
|
||||||
"ftp://ftp.sunet.se/pub/www/utilities/curl/curl-7.7.tar.gz");
|
"ftp://ftp.sunet.se/pub/www/utilities/curl/curl-7.9.2.tar.gz");
|
||||||
curl_easy_setopt(curl, CURLOPT_FILE, ftpfile);
|
/* Define our callback to get called when there's data to be written */
|
||||||
|
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, my_fwrite);
|
||||||
|
/* Set a pointer to our struct to pass to the callback */
|
||||||
|
curl_easy_setopt(curl, CURLOPT_FILE, &ftpfile);
|
||||||
|
|
||||||
|
/* Switch on full protocol/debug output */
|
||||||
|
curl_easy_setopt(curl, CURLOPT_VERBOSE, TRUE);
|
||||||
|
|
||||||
res = curl_easy_perform(curl);
|
res = curl_easy_perform(curl);
|
||||||
|
|
||||||
/* always cleanup */
|
/* always cleanup */
|
||||||
curl_easy_cleanup(curl);
|
curl_easy_cleanup(curl);
|
||||||
|
|
||||||
|
if(CURLE_OK != res) {
|
||||||
|
/* we failed */
|
||||||
|
fprintf(stderr, "curl told us %d\n", res);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fclose(ftpfile); /* close the local file */
|
if(ftpfile.stream)
|
||||||
|
fclose(ftpfile.stream); /* close the local file */
|
||||||
|
|
||||||
|
curl_global_cleanup();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
61
docs/examples/ftpgetresp.c
Normal file
61
docs/examples/ftpgetresp.c
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* _ _ ____ _
|
||||||
|
* Project ___| | | | _ \| |
|
||||||
|
* / __| | | | |_) | |
|
||||||
|
* | (__| |_| | _ <| |___
|
||||||
|
* \___|\___/|_| \_\_____|
|
||||||
|
*
|
||||||
|
* $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <curl/curl.h>
|
||||||
|
#include <curl/types.h>
|
||||||
|
#include <curl/easy.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Similar to ftpget.c but this also stores the received response-lines
|
||||||
|
* in a separate file using our own callback!
|
||||||
|
*
|
||||||
|
* This functionality was introduced in libcurl 7.9.3.
|
||||||
|
*/
|
||||||
|
|
||||||
|
size_t
|
||||||
|
write_response(void *ptr, size_t size, size_t nmemb, void *data)
|
||||||
|
{
|
||||||
|
FILE *writehere = (FILE *)data;
|
||||||
|
return fwrite(ptr, size, nmemb, writehere);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
CURL *curl;
|
||||||
|
CURLcode res;
|
||||||
|
FILE *ftpfile;
|
||||||
|
FILE *respfile;
|
||||||
|
|
||||||
|
/* local file name to store the file as */
|
||||||
|
ftpfile = fopen("ftp-list", "wb"); /* b is binary, needed on win32 */
|
||||||
|
|
||||||
|
/* local file name to store the FTP server's response lines in */
|
||||||
|
respfile = fopen("ftp-responses", "wb"); /* b is binary, needed on win32 */
|
||||||
|
|
||||||
|
curl = curl_easy_init();
|
||||||
|
if(curl) {
|
||||||
|
/* Get a file listing from sunet */
|
||||||
|
curl_easy_setopt(curl, CURLOPT_URL, "ftp://ftp.sunet.se/");
|
||||||
|
curl_easy_setopt(curl, CURLOPT_FILE, ftpfile);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, write_response);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_WRITEHEADER, respfile);
|
||||||
|
res = curl_easy_perform(curl);
|
||||||
|
|
||||||
|
/* always cleanup */
|
||||||
|
curl_easy_cleanup(curl);
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(ftpfile); /* close the local file */
|
||||||
|
fclose(respfile); /* close the response file */
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
35
docs/examples/http-post.c
Normal file
35
docs/examples/http-post.c
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* _ _ ____ _
|
||||||
|
* Project ___| | | | _ \| |
|
||||||
|
* / __| | | | |_) | |
|
||||||
|
* | (__| |_| | _ <| |___
|
||||||
|
* \___|\___/|_| \_\_____|
|
||||||
|
*
|
||||||
|
* $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <curl/curl.h>
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
CURL *curl;
|
||||||
|
CURLcode res;
|
||||||
|
|
||||||
|
curl = curl_easy_init();
|
||||||
|
if(curl) {
|
||||||
|
/* First set the URL that is about to receive our POST. This URL can
|
||||||
|
just as well be a https:// URL if that is what should receive the
|
||||||
|
data. */
|
||||||
|
curl_easy_setopt(curl, CURLOPT_URL, "http://postit.example.com/moo.cgi");
|
||||||
|
/* Now specify the POST data */
|
||||||
|
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "name=daniel&project=curl");
|
||||||
|
|
||||||
|
/* Perform the request, res will get the return code */
|
||||||
|
res = curl_easy_perform(curl);
|
||||||
|
|
||||||
|
/* always cleanup */
|
||||||
|
curl_easy_cleanup(curl);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
@@ -9,27 +9,16 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#include <curl/curl.h>
|
#include <curl/curl.h>
|
||||||
#include <curl/types.h>
|
|
||||||
#include <curl/easy.h>
|
|
||||||
|
|
||||||
/* to make this work under windows, use the win32-functions from the
|
int main(void)
|
||||||
win32socket.c file as well */
|
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
|
||||||
{
|
{
|
||||||
CURL *curl;
|
CURL *curl;
|
||||||
CURLcode res;
|
CURLcode res;
|
||||||
FILE *headerfile;
|
|
||||||
|
|
||||||
headerfile = fopen("dumpit", "w");
|
|
||||||
|
|
||||||
curl = curl_easy_init();
|
curl = curl_easy_init();
|
||||||
if(curl) {
|
if(curl) {
|
||||||
/* what call to write: */
|
|
||||||
curl_easy_setopt(curl, CURLOPT_URL, "curl.haxx.se");
|
curl_easy_setopt(curl, CURLOPT_URL, "curl.haxx.se");
|
||||||
curl_easy_setopt(curl, CURLOPT_WRITEHEADER, headerfile);
|
|
||||||
res = curl_easy_perform(curl);
|
res = curl_easy_perform(curl);
|
||||||
|
|
||||||
/* always cleanup */
|
/* always cleanup */
|
||||||
|
118
docs/examples/simplessl.c
Normal file
118
docs/examples/simplessl.c
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* _ _ ____ _
|
||||||
|
* Project ___| | | | _ \| |
|
||||||
|
* / __| | | | |_) | |
|
||||||
|
* | (__| |_| | _ <| |___
|
||||||
|
* \___|\___/|_| \_\_____|
|
||||||
|
*
|
||||||
|
* $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <curl/curl.h>
|
||||||
|
#include <curl/types.h>
|
||||||
|
#include <curl/easy.h>
|
||||||
|
|
||||||
|
|
||||||
|
/* some requirements for this to work:
|
||||||
|
1. set pCertFile to the file with the client certificate
|
||||||
|
2. if the key is passphrase protected, set pPassphrase to the
|
||||||
|
passphrase you use
|
||||||
|
3. if you are using a crypto engine:
|
||||||
|
3.1. set a #define USE_ENGINE
|
||||||
|
3.2. set pEngine to the name of the crypto engine you use
|
||||||
|
3.3. set pKeyName to the key identifier you want to use
|
||||||
|
4. if you don't use a crypto engine:
|
||||||
|
4.1. set pKeyName to the file name of your client key
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
CURL *curl;
|
||||||
|
CURLcode res;
|
||||||
|
FILE *headerfile;
|
||||||
|
|
||||||
|
const char *pCertFile = "testcert.pem";
|
||||||
|
const char *pCACertFile="cacert.pem"
|
||||||
|
|
||||||
|
const char *pKeyName;
|
||||||
|
const char *pKeyType;
|
||||||
|
|
||||||
|
const char *pEngine;
|
||||||
|
|
||||||
|
#if USE_ENGINE
|
||||||
|
pKeyName = "rsa_test";
|
||||||
|
pKeyType = "ENG";
|
||||||
|
pEngine = "chil"; /* for nChiper HSM... */
|
||||||
|
#else
|
||||||
|
pKeyName = "testkey.pem";
|
||||||
|
pKeyType = "PEM";
|
||||||
|
pEngine = NULL;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
const char *pPassphrase = NULL;
|
||||||
|
|
||||||
|
headerfile = fopen("dumpit", "w");
|
||||||
|
|
||||||
|
curl_global_init(CURL_GLOBAL_DEFAULT);
|
||||||
|
|
||||||
|
curl = curl_easy_init();
|
||||||
|
if(curl) {
|
||||||
|
/* what call to write: */
|
||||||
|
curl_easy_setopt(curl, CURLOPT_URL, "HTTPS://curl.haxx.se");
|
||||||
|
curl_easy_setopt(curl, CURLOPT_WRITEHEADER, headerfile);
|
||||||
|
|
||||||
|
while(1) /* do some ugly short cut... */
|
||||||
|
{
|
||||||
|
if (pEngine) /* use crypto engine */
|
||||||
|
{
|
||||||
|
if (curl_easy_setopt(curl, CURLOPT_SSLENGINE,pEngine) != CURLE_OK)
|
||||||
|
{ /* load the crypto engine */
|
||||||
|
fprintf(stderr,"can't set crypto engine\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (curl_easy_setopt(curl, CURLOPT_SSLENGINE_DEFAULT,1) != CURLE_OK)
|
||||||
|
{ /* set the crypto engine as default */
|
||||||
|
/* only needed for the first time you load
|
||||||
|
a engine in a curl object... */
|
||||||
|
fprintf(stderr,"can't set crypto engine as default\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* cert is stored PEM coded in file... */
|
||||||
|
/* since PEM is default, we needn't set it for PEM */
|
||||||
|
curl_easy_setopt(curl,CURLOPT_SSLCERTTYPE,"PEM");
|
||||||
|
/* set the cert for client authentication */
|
||||||
|
curl_easy_setopt(curl,CURLOPT_SSLCERT,pCertFile);
|
||||||
|
/* sorry, for engine we must set the passphrase
|
||||||
|
(if the key has one...) */
|
||||||
|
if (pPassphrase)
|
||||||
|
curl_easy_setopt(curl,CURLOPT_SSLKEYPASSWD,pPassphrase);
|
||||||
|
/* if we use a key stored in a crypto engine,
|
||||||
|
we must set the key type to "ENG" */
|
||||||
|
curl_easy_setopt(curl,CURLOPT_SSLKEYTYPE,pKeyType);
|
||||||
|
/* set the private key (file or ID in engine) */
|
||||||
|
curl_easy_setopt(curl,CURLOPT_SSLKEY,pKeyName);
|
||||||
|
/* set the file with the certs vaildating the server */
|
||||||
|
curl_easy_setopt(curl,CURLOPT_CAINFO,pCACertFile);
|
||||||
|
/* disconnect if we can't validate server's cert */
|
||||||
|
curl_easy_setopt(curl,CURLOPT_SSL_VERIFYPEER,1);
|
||||||
|
|
||||||
|
res = curl_easy_perform(curl);
|
||||||
|
break; /* we are done... */
|
||||||
|
}
|
||||||
|
/* always cleanup */
|
||||||
|
curl_easy_cleanup(curl);
|
||||||
|
}
|
||||||
|
|
||||||
|
curl_global_cleanup();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
529
docs/libcurl-the-guide
Normal file
529
docs/libcurl-the-guide
Normal file
@@ -0,0 +1,529 @@
|
|||||||
|
$Id$
|
||||||
|
_ _ ____ _
|
||||||
|
___| | | | _ \| |
|
||||||
|
/ __| | | | |_) | |
|
||||||
|
| (__| |_| | _ <| |___
|
||||||
|
\___|\___/|_| \_\_____|
|
||||||
|
|
||||||
|
PROGRAMMING WITH LIBCURL
|
||||||
|
|
||||||
|
About this Document
|
||||||
|
|
||||||
|
This document will attempt to describe the general principle and some basic
|
||||||
|
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.
|
||||||
|
|
||||||
|
This document will refer to 'the user' as the person writing the source code
|
||||||
|
that uses libcurl. That would probably be you or someone in your position.
|
||||||
|
What will be generally refered to as 'the program' will be the collected
|
||||||
|
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
|
||||||
|
|
||||||
|
The program must initialize some of the libcurl functionality globally. That
|
||||||
|
means it should be done exactly once, no matter how many times you intend to
|
||||||
|
use the library. Once for your program's entire life time. This is done using
|
||||||
|
|
||||||
|
curl_global_init()
|
||||||
|
|
||||||
|
and it takes one parameter which is a bit pattern that tells libcurl what to
|
||||||
|
intialize. Using CURL_GLOBAL_ALL will make it initialize all known internal
|
||||||
|
sub modules, and might be a good default option. The current two bits that
|
||||||
|
are specified are:
|
||||||
|
|
||||||
|
CURL_GLOBAL_WIN32 which only does anything on Windows machines. When used on
|
||||||
|
a Windows machine, it'll make libcurl intialize the win32 socket
|
||||||
|
stuff. Without having that initialized properly, your program cannot use
|
||||||
|
sockets properly. You should only do this once for each application, so if
|
||||||
|
your program already does this or of another library in use does it, you
|
||||||
|
should not tell libcurl to do this as well.
|
||||||
|
|
||||||
|
CURL_GLOBAL_SSL which only does anything on libcurls compiled and built
|
||||||
|
SSL-enabled. On these systems, this will make libcurl init OpenSSL properly
|
||||||
|
for this application. This is only needed to do once for each application so
|
||||||
|
if your program or another library already does this, this bit should not be
|
||||||
|
needed.
|
||||||
|
|
||||||
|
libcurl has a default protection mechanism that detects if curl_global_init()
|
||||||
|
hasn't been called by the time curl_easy_perform() is called and if that is
|
||||||
|
the case, libcurl runs the function itself with a guessed bit pattern. Please
|
||||||
|
note that depending solely on this is not considered nice nor very good.
|
||||||
|
|
||||||
|
When the program no longer uses libcurl, it should call
|
||||||
|
curl_global_cleanup(), which is the opposite of the init call. It will then
|
||||||
|
do the reversed operations to cleanup the resources the curl_global_init()
|
||||||
|
call initialized.
|
||||||
|
|
||||||
|
Repeated calls to curl_global_init() and curl_global_cleanup() should be
|
||||||
|
avoided. They should be called once each.
|
||||||
|
|
||||||
|
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'.
|
||||||
|
|
||||||
|
Future libcurls will also offer the multi interface. More about that
|
||||||
|
interface, what it is targeted for and how to use it is still only debated on
|
||||||
|
the libcurl mailing list and developer web pages. Join up to discuss and
|
||||||
|
figure out!
|
||||||
|
|
||||||
|
To use the easy interface, you must first create yourself an easy handle. You
|
||||||
|
need one handle for each easy session you want to perform. Basicly, you
|
||||||
|
should use one handle for every thread you plan to use for transferring. You
|
||||||
|
must never share the same handle in multiple threads.
|
||||||
|
|
||||||
|
Get an easy handle with
|
||||||
|
|
||||||
|
easyhandle = curl_easy_init();
|
||||||
|
|
||||||
|
It returns an easy handle. Using that you proceed to the next step: setting
|
||||||
|
up your preferred actions. A handle is just a logic entity for the upcoming
|
||||||
|
transfer or series of transfers. One of the most basic properties to set in
|
||||||
|
the handle is the URL. You set your preferred URL to transfer with
|
||||||
|
CURLOPT_URL in a manner similar to:
|
||||||
|
|
||||||
|
curl_easy_setopt(easyhandle, CURLOPT_URL, "http://curl.haxx.se/");
|
||||||
|
|
||||||
|
Let's assume for a while that you want to receive data as the URL indentifies
|
||||||
|
a remote resource you want to get here. Since you write a sort of application
|
||||||
|
that needs this transfer, I assume that you would like to get the data passed
|
||||||
|
to you directly instead of simply getting it passed to stdout. So, you write
|
||||||
|
your own function that matches this prototype:
|
||||||
|
|
||||||
|
size_t write_data(void *buffer, size_t size, size_t nmemb, void *userp);
|
||||||
|
|
||||||
|
You tell libcurl to pass all data to this function by issuing a function
|
||||||
|
similar to this:
|
||||||
|
|
||||||
|
curl_easy_setopt(easyhandle, CURLOPT_WRITEFUNCTION, write_data);
|
||||||
|
|
||||||
|
You can control what data your function get in the forth argument by setting
|
||||||
|
another property:
|
||||||
|
|
||||||
|
curl_easy_setopt(easyhandle, CURLOPT_FILE, &internal_struct);
|
||||||
|
|
||||||
|
Using that property, you can easily pass local data between your application
|
||||||
|
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:
|
||||||
|
|
||||||
|
success = curl_easy_perform(easyhandle);
|
||||||
|
|
||||||
|
The curl_easy_perform() will connect to the remote site, do the necessary
|
||||||
|
commands and receive the transfer. Whenever it receives data, it calls the
|
||||||
|
callback function we previously set. The function may get one byte at a time,
|
||||||
|
or it may get many kilobytes at once. libcurl delivers as much as possible as
|
||||||
|
often as possible. Your callback function should return the number of bytes
|
||||||
|
it "took care of". If that is not the exact same amount of bytes that was
|
||||||
|
passed to it, libcurl will abort the operation and return with an error code.
|
||||||
|
|
||||||
|
When the transfer is complete, the function returns a return code that
|
||||||
|
informs you if it succeeded in its mission or not. If a return code isn't
|
||||||
|
enough for you, you can use the CURLOPT_ERRORBUFFER to point libcurl to a
|
||||||
|
buffer of yours where it'll store a human readable error message as well.
|
||||||
|
|
||||||
|
If you then want to transfer another file, the handle is ready to be used
|
||||||
|
again. Mind you, it is even preferred that you re-use an existing handle if
|
||||||
|
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
|
||||||
|
have set the wrong libcurl option or misunderstood what the libcurl option
|
||||||
|
actually does, or the remote server might return non-standard replies that
|
||||||
|
confuse the library which then confuses your program.
|
||||||
|
|
||||||
|
There's one golden rule when these things occur: set the CURLOPT_VERBOSE
|
||||||
|
option to TRUE. It'll cause the library to spew out the entire protocol
|
||||||
|
details it sends, some internal info and some received protcol data as well
|
||||||
|
(especially when using FTP). If you're using HTTP, adding the headers in the
|
||||||
|
received output to study is also a clever way to get a better understanding
|
||||||
|
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
|
||||||
|
uploading to a remote FTP site is very similar to uploading data to a HTTP
|
||||||
|
server with a PUT request.
|
||||||
|
|
||||||
|
Of course, first you either create an easy handle or you re-use one existing
|
||||||
|
one. Then you set the URL to operate on just like before. This is the remote
|
||||||
|
URL, that we now will upload.
|
||||||
|
|
||||||
|
Since we write an application, we most likely want libcurl to get the upload
|
||||||
|
data by asking us for it. To make it do that, we set the read callback and
|
||||||
|
the custom pointer libcurl will pass to our read callback. The read callback
|
||||||
|
should have a prototype similar to:
|
||||||
|
|
||||||
|
size_t function(char *bufptr, size_t size, size_t nitems, void *userp);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
curl_easy_setopt(easyhandle, CURLOPT_INFILE, &filedata);
|
||||||
|
|
||||||
|
Tell libcurl that we want to upload:
|
||||||
|
|
||||||
|
curl_easy_setopt(easyhandle, CURLOPT_UPLOAD, TRUE);
|
||||||
|
|
||||||
|
A few protocols won't behave properly when uploads are done without any prior
|
||||||
|
knowledge of the expected file size. HTTP PUT is one example [1]. So, set the
|
||||||
|
upload file size using the CURLOPT_INFILESIZE like this:
|
||||||
|
|
||||||
|
curl_easy_setopt(easyhandle, CURLOPT_INFILESIZE, file_size);
|
||||||
|
|
||||||
|
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
|
||||||
|
fast as possible. The callback should return the number of bytes it wrote in
|
||||||
|
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:
|
||||||
|
|
||||||
|
[1] = HTTP PUT without knowing the size prior to transfer is indeed possible,
|
||||||
|
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>
|
# include <time.h>
|
||||||
#else
|
#else
|
||||||
# include <sys/types.h>
|
# include <sys/types.h>
|
||||||
# if TIME_WITH_SYS_TIME
|
# ifdef TIME_WITH_SYS_TIME
|
||||||
# include <sys/time.h>
|
# include <sys/time.h>
|
||||||
# include <time.h>
|
# include <time.h>
|
||||||
# else
|
# else
|
||||||
# if HAVE_SYS_TIME_H
|
# ifdef HAVE_SYS_TIME_H
|
||||||
# include <sys/time.h>
|
# include <sys/time.h>
|
||||||
# else
|
# else
|
||||||
# include <time.h>
|
# include <time.h>
|
||||||
@@ -62,6 +62,7 @@ struct HttpPost {
|
|||||||
char *contents; /* pointer to allocated data contents */
|
char *contents; /* pointer to allocated data contents */
|
||||||
long contentslength; /* length of contents field */
|
long contentslength; /* length of contents field */
|
||||||
char *contenttype; /* Content-Type */
|
char *contenttype; /* Content-Type */
|
||||||
|
struct curl_slist* contentheader; /* list of extra headers for this form */
|
||||||
struct HttpPost *more; /* if one field name has more than one file, this
|
struct HttpPost *more; /* if one field name has more than one file, this
|
||||||
link should link to following files */
|
link should link to following files */
|
||||||
long flags; /* as defined below */
|
long flags; /* as defined below */
|
||||||
@@ -155,6 +156,8 @@ typedef enum {
|
|||||||
CURLE_OBSOLETE, /* 50 - removed after 7.7.3 */
|
CURLE_OBSOLETE, /* 50 - removed after 7.7.3 */
|
||||||
CURLE_SSL_PEER_CERTIFICATE, /* 51 - peer's certificate wasn't ok */
|
CURLE_SSL_PEER_CERTIFICATE, /* 51 - peer's certificate wasn't ok */
|
||||||
CURLE_GOT_NOTHING, /* 52 - when this is a specific error */
|
CURLE_GOT_NOTHING, /* 52 - when this is a specific error */
|
||||||
|
CURLE_SSL_ENGINE_NOTFOUND, /* 53 - SSL crypto engine not found */
|
||||||
|
CURLE_SSL_ENGINE_SETFAILED, /* 54 - can not set SSL crypto engine as default */
|
||||||
|
|
||||||
CURL_LAST /* never use! */
|
CURL_LAST /* never use! */
|
||||||
} CURLcode;
|
} CURLcode;
|
||||||
@@ -278,8 +281,10 @@ typedef enum {
|
|||||||
/* name of the file keeping your private SSL-certificate */
|
/* name of the file keeping your private SSL-certificate */
|
||||||
CINIT(SSLCERT, OBJECTPOINT, 25),
|
CINIT(SSLCERT, OBJECTPOINT, 25),
|
||||||
|
|
||||||
/* password for the SSL-certificate */
|
/* password for the SSL-private key, keep this for compatibility */
|
||||||
CINIT(SSLCERTPASSWD, OBJECTPOINT, 26),
|
CINIT(SSLCERTPASSWD, OBJECTPOINT, 26),
|
||||||
|
/* password for the SSL private key */
|
||||||
|
CINIT(SSLKEYPASSWD, OBJECTPOINT, 26),
|
||||||
|
|
||||||
/* send TYPE parameter? */
|
/* send TYPE parameter? */
|
||||||
CINIT(CRLF, LONG, 27),
|
CINIT(CRLF, LONG, 27),
|
||||||
@@ -466,6 +471,29 @@ typedef enum {
|
|||||||
PASV command. */
|
PASV command. */
|
||||||
CINIT(FTP_USE_EPSV, LONG, 85),
|
CINIT(FTP_USE_EPSV, LONG, 85),
|
||||||
|
|
||||||
|
/* type of the file keeping your SSL-certificate ("DER", "PEM", "ENG") */
|
||||||
|
CINIT(SSLCERTTYPE, OBJECTPOINT, 86),
|
||||||
|
|
||||||
|
/* name of the file keeping your private SSL-key */
|
||||||
|
CINIT(SSLKEY, OBJECTPOINT, 87),
|
||||||
|
|
||||||
|
/* type of the file keeping your private SSL-key ("DER", "PEM", "ENG") */
|
||||||
|
CINIT(SSLKEYTYPE, OBJECTPOINT, 88),
|
||||||
|
|
||||||
|
/* crypto engine for the SSL-sub system */
|
||||||
|
CINIT(SSLENGINE, OBJECTPOINT, 89),
|
||||||
|
|
||||||
|
/* set the crypto engine for the SSL-sub system as default
|
||||||
|
the param has no meaning...
|
||||||
|
*/
|
||||||
|
CINIT(SSLENGINE_DEFAULT, LONG, 90),
|
||||||
|
|
||||||
|
/* Non-zero value means to use the global dns cache */
|
||||||
|
CINIT(DNS_USE_GLOBAL_CACHE, LONG, 91),
|
||||||
|
|
||||||
|
/* DNS cache timeout */
|
||||||
|
CINIT(DNS_CACHE_TIMEOUT, LONG, 92),
|
||||||
|
|
||||||
CURLOPT_LASTENTRY /* the last unusued */
|
CURLOPT_LASTENTRY /* the last unusued */
|
||||||
} CURLoption;
|
} CURLoption;
|
||||||
|
|
||||||
@@ -543,6 +571,7 @@ typedef enum {
|
|||||||
CFINIT(ARRAY_START), /* below are the options allowed within a array */
|
CFINIT(ARRAY_START), /* below are the options allowed within a array */
|
||||||
CFINIT(FILE),
|
CFINIT(FILE),
|
||||||
CFINIT(CONTENTTYPE),
|
CFINIT(CONTENTTYPE),
|
||||||
|
CFINIT(CONTENTHEADER),
|
||||||
CFINIT(END),
|
CFINIT(END),
|
||||||
CFINIT(ARRAY_END), /* up are the options allowed within a array */
|
CFINIT(ARRAY_END), /* up are the options allowed within a array */
|
||||||
|
|
||||||
@@ -584,8 +613,8 @@ CURLcode curl_global_init(long flags);
|
|||||||
void curl_global_cleanup(void);
|
void curl_global_cleanup(void);
|
||||||
|
|
||||||
/* This is the version number */
|
/* This is the version number */
|
||||||
#define LIBCURL_VERSION "7.9.2"
|
#define LIBCURL_VERSION "7.9.3"
|
||||||
#define LIBCURL_VERSION_NUM 0x070902
|
#define LIBCURL_VERSION_NUM 0x070903
|
||||||
|
|
||||||
/* linked-list structure for the CURLOPT_QUOTE option (and other) */
|
/* linked-list structure for the CURLOPT_QUOTE option (and other) */
|
||||||
struct curl_slist {
|
struct curl_slist {
|
||||||
|
@@ -56,7 +56,9 @@ escape.c mprintf.c telnet.c \
|
|||||||
escape.h getpass.c netrc.c telnet.h \
|
escape.h getpass.c netrc.c telnet.h \
|
||||||
getinfo.c getinfo.h transfer.c strequal.c strequal.h easy.c \
|
getinfo.c getinfo.h transfer.c strequal.c strequal.h easy.c \
|
||||||
security.h security.c krb4.c krb4.h memdebug.c memdebug.h inet_ntoa_r.h \
|
security.h security.c krb4.c krb4.h memdebug.c memdebug.h inet_ntoa_r.h \
|
||||||
http_chunks.c http_chunks.h strtok.c strtok.h connect.c connect.h
|
http_chunks.c http_chunks.h strtok.c strtok.h connect.c connect.h \
|
||||||
|
llist.c llist.h hash.c hash.h multi.c multi.h
|
||||||
|
|
||||||
|
|
||||||
noinst_HEADERS = setup.h transfer.h
|
noinst_HEADERS = setup.h transfer.h
|
||||||
|
|
||||||
|
@@ -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 \
|
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 \
|
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 \
|
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 \
|
libcurl_a_OBJECTS = file.o timeval.o base64.o hostip.o progress.o \
|
||||||
formdata.o cookie.o http.o sendf.o ftp.o url.o dict.o if2ip.o \
|
formdata.o cookie.o http.o sendf.o ftp.o url.o dict.o if2ip.o \
|
||||||
speedcheck.o getdate.o transfer.o ldap.o ssluse.o version.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 \
|
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 \
|
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)
|
LIBRARIES = $(libcurl_a_LIBRARIES)
|
||||||
SOURCES = $(libcurl_a_SOURCES)
|
SOURCES = $(libcurl_a_SOURCES)
|
||||||
|
@@ -193,8 +193,9 @@ X_OBJS= \
|
|||||||
$(DIROBJ)\easy.obj \
|
$(DIROBJ)\easy.obj \
|
||||||
$(DIROBJ)\strequal.obj \
|
$(DIROBJ)\strequal.obj \
|
||||||
$(DIROBJ)\strtok.obj \
|
$(DIROBJ)\strtok.obj \
|
||||||
$(DIROBJ)\connect.obj
|
$(DIROBJ)\connect.obj \
|
||||||
|
$(DIROBJ)\hash.obj \
|
||||||
|
$(DIROBJ)\llist.obj
|
||||||
|
|
||||||
all : $(TARGET)
|
all : $(TARGET)
|
||||||
|
|
||||||
|
@@ -193,7 +193,7 @@ static CURLcode bindlocal(struct connectdata *conn,
|
|||||||
#ifdef HAVE_INET_NTOA
|
#ifdef HAVE_INET_NTOA
|
||||||
|
|
||||||
#ifndef INADDR_NONE
|
#ifndef INADDR_NONE
|
||||||
#define INADDR_NONE (unsigned long) ~0
|
#define INADDR_NONE (in_addr_t) ~0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct SessionHandle *data = conn->data;
|
struct SessionHandle *data = conn->data;
|
||||||
@@ -207,14 +207,14 @@ static CURLcode bindlocal(struct connectdata *conn,
|
|||||||
char *hostdataptr=NULL;
|
char *hostdataptr=NULL;
|
||||||
size_t size;
|
size_t size;
|
||||||
char myhost[256] = "";
|
char myhost[256] = "";
|
||||||
unsigned long in;
|
in_addr_t in;
|
||||||
|
|
||||||
if(Curl_if2ip(data->set.device, myhost, sizeof(myhost))) {
|
if(Curl_if2ip(data->set.device, myhost, sizeof(myhost))) {
|
||||||
h = Curl_getaddrinfo(data, myhost, 0, &hostdataptr);
|
h = Curl_resolv(data, myhost, 0, &hostdataptr);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if(strlen(data->set.device)>1) {
|
if(strlen(data->set.device)>1) {
|
||||||
h = Curl_getaddrinfo(data, data->set.device, 0, &hostdataptr);
|
h = Curl_resolv(data, data->set.device, 0, &hostdataptr);
|
||||||
}
|
}
|
||||||
if(h) {
|
if(h) {
|
||||||
/* we know data->set.device is shorter than the myhost array */
|
/* we know data->set.device is shorter than the myhost array */
|
||||||
@@ -229,14 +229,13 @@ static CURLcode bindlocal(struct connectdata *conn,
|
|||||||
hostent_buf,
|
hostent_buf,
|
||||||
sizeof(hostent_buf));
|
sizeof(hostent_buf));
|
||||||
*/
|
*/
|
||||||
if(hostdataptr)
|
|
||||||
free(hostdataptr); /* allocated by Curl_getaddrinfo() */
|
|
||||||
return CURLE_HTTP_PORT_FAILED;
|
return CURLE_HTTP_PORT_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
infof(data, "We bind local end to %s\n", myhost);
|
infof(data, "We bind local end to %s\n", myhost);
|
||||||
|
|
||||||
if ( (in=inet_addr(myhost)) != INADDR_NONE ) {
|
in=inet_addr(myhost);
|
||||||
|
if (INADDR_NONE != in) {
|
||||||
|
|
||||||
if ( h ) {
|
if ( h ) {
|
||||||
memset((char *)&sa, 0, sizeof(sa));
|
memset((char *)&sa, 0, sizeof(sa));
|
||||||
@@ -284,7 +283,7 @@ static CURLcode bindlocal(struct connectdata *conn,
|
|||||||
failf(data, "Insufficient kernel memory was available: %d", errno);
|
failf(data, "Insufficient kernel memory was available: %d", errno);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
failf(data, "errno %d\n", errno);
|
failf(data, "errno %d", errno);
|
||||||
break;
|
break;
|
||||||
} /* end of switch(errno) */
|
} /* end of switch(errno) */
|
||||||
|
|
||||||
@@ -303,9 +302,6 @@ static CURLcode bindlocal(struct connectdata *conn,
|
|||||||
return CURLE_HTTP_PORT_FAILED;
|
return CURLE_HTTP_PORT_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(hostdataptr)
|
|
||||||
free(hostdataptr); /* allocated by Curl_getaddrinfo() */
|
|
||||||
|
|
||||||
return CURLE_OK;
|
return CURLE_OK;
|
||||||
|
|
||||||
} /* end of device selection support */
|
} /* end of device selection support */
|
||||||
@@ -373,9 +369,11 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */
|
|||||||
/* subtract the passed time */
|
/* subtract the passed time */
|
||||||
timeout_ms -= (long)has_passed;
|
timeout_ms -= (long)has_passed;
|
||||||
|
|
||||||
if(timeout_ms < 0)
|
if(timeout_ms < 0) {
|
||||||
/* a precaution, no need to continue if time already is up */
|
/* a precaution, no need to continue if time already is up */
|
||||||
|
failf(data, "Connection time-out");
|
||||||
return CURLE_OPERATION_TIMEOUTED;
|
return CURLE_OPERATION_TIMEOUTED;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ENABLE_IPV6
|
#ifdef ENABLE_IPV6
|
||||||
@@ -452,8 +450,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */
|
|||||||
return CURLE_COULDNT_CONNECT;
|
return CURLE_COULDNT_CONNECT;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* now disable the non-blocking mode again */
|
/* leave the socket in non-blocking mode */
|
||||||
Curl_nonblock(sockfd, FALSE);
|
|
||||||
|
|
||||||
if(addr)
|
if(addr)
|
||||||
*addr = ai; /* the address we ended up connected to */
|
*addr = ai; /* the address we ended up connected to */
|
||||||
@@ -559,8 +556,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */
|
|||||||
return CURLE_COULDNT_CONNECT;
|
return CURLE_COULDNT_CONNECT;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* now disable the non-blocking mode again */
|
/* leave the socket in non-blocking mode */
|
||||||
Curl_nonblock(sockfd, FALSE);
|
|
||||||
|
|
||||||
if(addr)
|
if(addr)
|
||||||
/* this is the address we've connected to */
|
/* this is the address we've connected to */
|
||||||
|
14
lib/cookie.c
14
lib/cookie.c
@@ -194,6 +194,11 @@ Curl_cookie_add(struct CookieInfo *c,
|
|||||||
while(ptr && *ptr && isspace((int)*ptr))
|
while(ptr && *ptr && isspace((int)*ptr))
|
||||||
ptr++;
|
ptr++;
|
||||||
semiptr=strchr(ptr, ';'); /* now, find the next semicolon */
|
semiptr=strchr(ptr, ';'); /* now, find the next semicolon */
|
||||||
|
|
||||||
|
if(!semiptr && *ptr)
|
||||||
|
/* There are no more semicolons, but there's a final name=value pair
|
||||||
|
coming up */
|
||||||
|
semiptr=ptr;
|
||||||
} while(semiptr);
|
} while(semiptr);
|
||||||
|
|
||||||
if(NULL == co->domain)
|
if(NULL == co->domain)
|
||||||
@@ -377,8 +382,15 @@ Curl_cookie_add(struct CookieInfo *c,
|
|||||||
|
|
||||||
free(co); /* free the newly alloced memory */
|
free(co); /* free the newly alloced memory */
|
||||||
co = clist; /* point to the previous struct instead */
|
co = clist; /* point to the previous struct instead */
|
||||||
}
|
|
||||||
|
|
||||||
|
/* We have replaced a cookie, now skip the rest of the list but
|
||||||
|
make sure the 'lastc' pointer is properly set */
|
||||||
|
do {
|
||||||
|
lastc = clist;
|
||||||
|
clist = clist->next;
|
||||||
|
} while(clist);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
lastc = clist;
|
lastc = clist;
|
||||||
clist = clist->next;
|
clist = clist->next;
|
||||||
|
@@ -151,6 +151,10 @@ SOURCE=.\getpass.c
|
|||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\hash.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
SOURCE=.\hostip.c
|
SOURCE=.\hostip.c
|
||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
@@ -179,6 +183,10 @@ SOURCE=.\libcurl.def
|
|||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\llist.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
SOURCE=.\memdebug.c
|
SOURCE=.\memdebug.c
|
||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
@@ -121,7 +121,7 @@ CURLcode Curl_dict(struct connectdata *conn)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ((word == NULL) || (*word == (char)0)) {
|
if ((word == NULL) || (*word == (char)0)) {
|
||||||
failf(data, "lookup word is missing\n");
|
failf(data, "lookup word is missing");
|
||||||
}
|
}
|
||||||
if ((database == NULL) || (*database == (char)0)) {
|
if ((database == NULL) || (*database == (char)0)) {
|
||||||
database = (char *)"!";
|
database = (char *)"!";
|
||||||
@@ -174,7 +174,7 @@ CURLcode Curl_dict(struct connectdata *conn)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ((word == NULL) || (*word == (char)0)) {
|
if ((word == NULL) || (*word == (char)0)) {
|
||||||
failf(data, "lookup word is missing\n");
|
failf(data, "lookup word is missing");
|
||||||
}
|
}
|
||||||
if ((database == NULL) || (*database == (char)0)) {
|
if ((database == NULL) || (*database == (char)0)) {
|
||||||
database = (char *)"!";
|
database = (char *)"!";
|
||||||
|
15
lib/easy.c
15
lib/easy.c
@@ -76,6 +76,7 @@
|
|||||||
#include "ssluse.h"
|
#include "ssluse.h"
|
||||||
#include "url.h"
|
#include "url.h"
|
||||||
#include "getinfo.h"
|
#include "getinfo.h"
|
||||||
|
#include "hostip.h"
|
||||||
|
|
||||||
#define _MPRINTF_REPLACE /* use our functions only */
|
#define _MPRINTF_REPLACE /* use our functions only */
|
||||||
#include <curl/mprintf.h>
|
#include <curl/mprintf.h>
|
||||||
@@ -162,6 +163,8 @@ void curl_global_cleanup(void)
|
|||||||
if (!initialized)
|
if (!initialized)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
Curl_global_host_cache_dtor();
|
||||||
|
|
||||||
if (init_flags & CURL_GLOBAL_SSL)
|
if (init_flags & CURL_GLOBAL_SSL)
|
||||||
Curl_SSL_cleanup();
|
Curl_SSL_cleanup();
|
||||||
|
|
||||||
@@ -230,12 +233,24 @@ CURLcode curl_easy_perform(CURL *curl)
|
|||||||
{
|
{
|
||||||
struct SessionHandle *data = (struct SessionHandle *)curl;
|
struct SessionHandle *data = (struct SessionHandle *)curl;
|
||||||
|
|
||||||
|
if (!data->hostcache) {
|
||||||
|
if (Curl_global_host_cache_use(data)) {
|
||||||
|
data->hostcache = Curl_global_host_cache_get();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
data->hostcache = curl_hash_alloc(7, Curl_freeaddrinfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return Curl_perform(data);
|
return Curl_perform(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void curl_easy_cleanup(CURL *curl)
|
void curl_easy_cleanup(CURL *curl)
|
||||||
{
|
{
|
||||||
struct SessionHandle *data = (struct SessionHandle *)curl;
|
struct SessionHandle *data = (struct SessionHandle *)curl;
|
||||||
|
if (!Curl_global_host_cache_use(data)) {
|
||||||
|
curl_hash_destroy(data->hostcache);
|
||||||
|
}
|
||||||
Curl_close(data);
|
Curl_close(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -396,15 +396,16 @@ int curl_formparse(char *input,
|
|||||||
* Returns newly allocated HttpPost on success and NULL if malloc failed.
|
* Returns newly allocated HttpPost on success and NULL if malloc failed.
|
||||||
*
|
*
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
static struct HttpPost * AddHttpPost (char * name,
|
static struct HttpPost * AddHttpPost(char * name,
|
||||||
long namelength,
|
long namelength,
|
||||||
char * value,
|
char * value,
|
||||||
long contentslength,
|
long contentslength,
|
||||||
char *contenttype,
|
char *contenttype,
|
||||||
long flags,
|
long flags,
|
||||||
struct HttpPost *parent_post,
|
struct curl_slist* contentHeader,
|
||||||
struct HttpPost **httppost,
|
struct HttpPost *parent_post,
|
||||||
struct HttpPost **last_post)
|
struct HttpPost **httppost,
|
||||||
|
struct HttpPost **last_post)
|
||||||
{
|
{
|
||||||
struct HttpPost *post;
|
struct HttpPost *post;
|
||||||
post = (struct HttpPost *)malloc(sizeof(struct HttpPost));
|
post = (struct HttpPost *)malloc(sizeof(struct HttpPost));
|
||||||
@@ -415,6 +416,7 @@ static struct HttpPost * AddHttpPost (char * name,
|
|||||||
post->contents = value;
|
post->contents = value;
|
||||||
post->contentslength = contentslength;
|
post->contentslength = contentslength;
|
||||||
post->contenttype = contenttype;
|
post->contenttype = contenttype;
|
||||||
|
post->contentheader = contentHeader;
|
||||||
post->flags = flags;
|
post->flags = flags;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -823,6 +825,21 @@ FORMcode FormAdd(struct HttpPost **httppost,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case CURLFORM_CONTENTHEADER:
|
||||||
|
{
|
||||||
|
struct curl_slist* list = NULL;
|
||||||
|
if( array_state )
|
||||||
|
list = (struct curl_slist*)array_value;
|
||||||
|
else
|
||||||
|
list = va_arg(params,struct curl_slist*);
|
||||||
|
|
||||||
|
if( current_form->contentheader )
|
||||||
|
return_value = FORMADD_OPTION_TWICE;
|
||||||
|
else
|
||||||
|
current_form->contentheader = list;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
fprintf (stderr, "got unknown CURLFORM_OPTION: %d\n", option);
|
fprintf (stderr, "got unknown CURLFORM_OPTION: %d\n", option);
|
||||||
return_value = FORMADD_UNKNOWN_OPTION;
|
return_value = FORMADD_UNKNOWN_OPTION;
|
||||||
@@ -872,13 +889,16 @@ FORMcode FormAdd(struct HttpPost **httppost,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( (post = AddHttpPost(form->name, form->namelength,
|
post = AddHttpPost(form->name, form->namelength,
|
||||||
form->value, form->contentslength,
|
form->value, form->contentslength,
|
||||||
form->contenttype, form->flags,
|
form->contenttype, form->flags,
|
||||||
post, httppost,
|
form->contentheader,
|
||||||
last_post)) == NULL) {
|
post, httppost,
|
||||||
|
last_post);
|
||||||
|
|
||||||
|
if(!post)
|
||||||
return_value = FORMADD_MEMORY;
|
return_value = FORMADD_MEMORY;
|
||||||
}
|
|
||||||
if (form->contenttype)
|
if (form->contenttype)
|
||||||
prevtype = form->contenttype;
|
prevtype = form->contenttype;
|
||||||
}
|
}
|
||||||
@@ -1029,6 +1049,8 @@ struct FormData *Curl_getFormData(struct HttpPost *post,
|
|||||||
int size =0;
|
int size =0;
|
||||||
char *boundary;
|
char *boundary;
|
||||||
char *fileboundary=NULL;
|
char *fileboundary=NULL;
|
||||||
|
struct curl_slist* curList;
|
||||||
|
|
||||||
|
|
||||||
if(!post)
|
if(!post)
|
||||||
return NULL; /* no input => no output! */
|
return NULL; /* no input => no output! */
|
||||||
@@ -1090,6 +1112,13 @@ struct FormData *Curl_getFormData(struct HttpPost *post,
|
|||||||
file->contenttype);
|
file->contenttype);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
curList = file->contentheader;
|
||||||
|
while( curList ) {
|
||||||
|
/* Process the additional headers specified for this form */
|
||||||
|
size += AddFormDataf( &form, "\r\n%s", curList->data );
|
||||||
|
curList = curList->next;
|
||||||
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
/* The header Content-Transfer-Encoding: seems to confuse some receivers
|
/* The header Content-Transfer-Encoding: seems to confuse some receivers
|
||||||
* (like the built-in PHP engine). While I can't see any reason why it
|
* (like the built-in PHP engine). While I can't see any reason why it
|
||||||
@@ -1126,10 +1155,13 @@ struct FormData *Curl_getFormData(struct HttpPost *post,
|
|||||||
}
|
}
|
||||||
if(fileread != stdin)
|
if(fileread != stdin)
|
||||||
fclose(fileread);
|
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 */
|
/* include the contents we got */
|
||||||
size += AddFormData(&form, post->contents, post->contentslength);
|
size += AddFormData(&form, post->contents, post->contentslength);
|
||||||
}
|
}
|
||||||
|
@@ -44,6 +44,7 @@ typedef struct FormInfo {
|
|||||||
long contentslength;
|
long contentslength;
|
||||||
char *contenttype;
|
char *contenttype;
|
||||||
long flags;
|
long flags;
|
||||||
|
struct curl_slist* contentheader;
|
||||||
struct FormInfo *more;
|
struct FormInfo *more;
|
||||||
} FormInfo;
|
} FormInfo;
|
||||||
|
|
||||||
|
127
lib/ftp.c
127
lib/ftp.c
@@ -84,6 +84,10 @@
|
|||||||
#include "ssluse.h"
|
#include "ssluse.h"
|
||||||
#include "connect.h"
|
#include "connect.h"
|
||||||
|
|
||||||
|
#if defined(HAVE_INET_NTOA_R) && !defined(HAVE_INET_NTOA_R_DECL)
|
||||||
|
#include "inet_ntoa_r.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#define _MPRINTF_REPLACE /* use our functions only */
|
#define _MPRINTF_REPLACE /* use our functions only */
|
||||||
#include <curl/mprintf.h>
|
#include <curl/mprintf.h>
|
||||||
|
|
||||||
@@ -192,9 +196,12 @@ int Curl_GetFTPResponse(char *buf,
|
|||||||
char *line_start;
|
char *line_start;
|
||||||
int code=0; /* default "error code" to return */
|
int code=0; /* default "error code" to return */
|
||||||
|
|
||||||
#define SELECT_OK 0
|
#define SELECT_OK 0
|
||||||
#define SELECT_ERROR 1
|
#define SELECT_ERROR 1 /* select() problems */
|
||||||
#define SELECT_TIMEOUT 2
|
#define SELECT_TIMEOUT 2 /* took too long */
|
||||||
|
#define SELECT_MEMORY 3 /* no available memory */
|
||||||
|
#define SELECT_CALLBACK 4 /* aborted by callback */
|
||||||
|
|
||||||
int error = SELECT_OK;
|
int error = SELECT_OK;
|
||||||
|
|
||||||
struct FTP *ftp = conn->proto.ftp;
|
struct FTP *ftp = conn->proto.ftp;
|
||||||
@@ -260,9 +267,16 @@ int Curl_GetFTPResponse(char *buf,
|
|||||||
ftp->cache = NULL; /* clear the pointer */
|
ftp->cache = NULL; /* clear the pointer */
|
||||||
ftp->cache_size = 0; /* zero the size just in case */
|
ftp->cache_size = 0; /* zero the size just in case */
|
||||||
}
|
}
|
||||||
else if(CURLE_OK != Curl_read(conn, sockfd, ptr,
|
else {
|
||||||
BUFSIZE-nread, &gotbytes))
|
int res = Curl_read(conn, sockfd, ptr,
|
||||||
keepon = FALSE;
|
BUFSIZE-nread, &gotbytes);
|
||||||
|
if(res < 0)
|
||||||
|
/* EWOULDBLOCK */
|
||||||
|
continue; /* go looping again */
|
||||||
|
|
||||||
|
if(CURLE_OK != res)
|
||||||
|
keepon = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
if(!keepon)
|
if(!keepon)
|
||||||
;
|
;
|
||||||
@@ -283,6 +297,7 @@ int Curl_GetFTPResponse(char *buf,
|
|||||||
if(*ptr=='\n') {
|
if(*ptr=='\n') {
|
||||||
/* a newline is CRLF in ftp-talk, so the CR is ignored as
|
/* a newline is CRLF in ftp-talk, so the CR is ignored as
|
||||||
the line isn't really terminated until the LF comes */
|
the line isn't really terminated until the LF comes */
|
||||||
|
CURLcode result;
|
||||||
|
|
||||||
/* output debug output if that is requested */
|
/* output debug output if that is requested */
|
||||||
if(data->set.verbose) {
|
if(data->set.verbose) {
|
||||||
@@ -291,6 +306,16 @@ int Curl_GetFTPResponse(char *buf,
|
|||||||
/* no need to output LF here, it is part of the data */
|
/* no need to output LF here, it is part of the data */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We pass all response-lines to the callback function registered
|
||||||
|
* for "headers". The response lines can be seen as a kind of
|
||||||
|
* headers.
|
||||||
|
*/
|
||||||
|
result = Curl_client_write(data, CLIENTWRITE_HEADER,
|
||||||
|
line_start, perline);
|
||||||
|
if(result)
|
||||||
|
return -SELECT_CALLBACK;
|
||||||
|
|
||||||
#define lastline(line) (isdigit((int)line[0]) && isdigit((int)line[1]) && \
|
#define lastline(line) (isdigit((int)line[0]) && isdigit((int)line[1]) && \
|
||||||
isdigit((int)line[2]) && (' ' == line[3]))
|
isdigit((int)line[2]) && (' ' == line[3]))
|
||||||
|
|
||||||
@@ -324,7 +349,7 @@ int Curl_GetFTPResponse(char *buf,
|
|||||||
if(ftp->cache)
|
if(ftp->cache)
|
||||||
memcpy(ftp->cache, line_start, ftp->cache_size);
|
memcpy(ftp->cache, line_start, ftp->cache_size);
|
||||||
else
|
else
|
||||||
return CURLE_OUT_OF_MEMORY; /**BANG**/
|
return -SELECT_MEMORY; /**BANG**/
|
||||||
}
|
}
|
||||||
} /* there was data */
|
} /* there was data */
|
||||||
} /* if(no error) */
|
} /* if(no error) */
|
||||||
@@ -333,7 +358,7 @@ int Curl_GetFTPResponse(char *buf,
|
|||||||
if(!error)
|
if(!error)
|
||||||
code = atoi(buf);
|
code = atoi(buf);
|
||||||
|
|
||||||
#if KRB4
|
#ifdef KRB4
|
||||||
/* handle the security-oriented responses 6xx ***/
|
/* handle the security-oriented responses 6xx ***/
|
||||||
/* FIXME: some errorchecking perhaps... ***/
|
/* FIXME: some errorchecking perhaps... ***/
|
||||||
switch(code) {
|
switch(code) {
|
||||||
@@ -847,13 +872,17 @@ ftp_pasv_verbose(struct connectdata *conn,
|
|||||||
#ifdef HAVE_INET_NTOA_R
|
#ifdef HAVE_INET_NTOA_R
|
||||||
char ntoa_buf[64];
|
char ntoa_buf[64];
|
||||||
#endif
|
#endif
|
||||||
char hostent_buf[9000];
|
/* The array size trick below is to make this a large chunk of memory
|
||||||
|
suitably 8-byte aligned on 64-bit platforms. This was thoughtfully
|
||||||
|
suggested by Philip Gladstone. */
|
||||||
|
long bigbuf[9000 / sizeof(long)];
|
||||||
|
|
||||||
#if defined(HAVE_INET_ADDR)
|
#if defined(HAVE_INET_ADDR)
|
||||||
in_addr_t address;
|
in_addr_t address;
|
||||||
# if defined(HAVE_GETHOSTBYADDR_R)
|
# if defined(HAVE_GETHOSTBYADDR_R)
|
||||||
int h_errnop;
|
int h_errnop;
|
||||||
# endif
|
# endif
|
||||||
|
char *hostent_buf = (char *)bigbuf; /* get a char * to the buffer */
|
||||||
|
|
||||||
address = inet_addr(newhost);
|
address = inet_addr(newhost);
|
||||||
# ifdef HAVE_GETHOSTBYADDR_R
|
# ifdef HAVE_GETHOSTBYADDR_R
|
||||||
@@ -882,7 +911,7 @@ ftp_pasv_verbose(struct connectdata *conn,
|
|||||||
# ifdef HAVE_GETHOSTBYADDR_R_7
|
# ifdef HAVE_GETHOSTBYADDR_R_7
|
||||||
/* Solaris and IRIX */
|
/* Solaris and IRIX */
|
||||||
answer = gethostbyaddr_r((char *) &address, sizeof(address), AF_INET,
|
answer = gethostbyaddr_r((char *) &address, sizeof(address), AF_INET,
|
||||||
(struct hostent *)hostent_buf,
|
(struct hostent *)bigbuf,
|
||||||
hostent_buf + sizeof(*answer),
|
hostent_buf + sizeof(*answer),
|
||||||
sizeof(hostent_buf) - sizeof(*answer),
|
sizeof(hostent_buf) - sizeof(*answer),
|
||||||
&h_errnop);
|
&h_errnop);
|
||||||
@@ -1169,30 +1198,30 @@ CURLcode ftp_use_port(struct connectdata *conn)
|
|||||||
struct sockaddr_in sa;
|
struct sockaddr_in sa;
|
||||||
struct hostent *h=NULL;
|
struct hostent *h=NULL;
|
||||||
char *hostdataptr=NULL;
|
char *hostdataptr=NULL;
|
||||||
size_t size;
|
|
||||||
unsigned short porttouse;
|
unsigned short porttouse;
|
||||||
char myhost[256] = "";
|
char myhost[256] = "";
|
||||||
|
|
||||||
if(data->set.ftpport) {
|
if(data->set.ftpport) {
|
||||||
if(Curl_if2ip(data->set.ftpport, myhost, sizeof(myhost))) {
|
if(Curl_if2ip(data->set.ftpport, myhost, sizeof(myhost))) {
|
||||||
h = Curl_getaddrinfo(data, myhost, 0, &hostdataptr);
|
h = Curl_resolv(data, myhost, 0, &hostdataptr);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if(strlen(data->set.ftpport)>1)
|
int len = strlen(data->set.ftpport);
|
||||||
h = Curl_getaddrinfo(data, data->set.ftpport, 0, &hostdataptr);
|
if(len>1)
|
||||||
|
h = Curl_resolv(data, data->set.ftpport, 0, &hostdataptr);
|
||||||
if(h)
|
if(h)
|
||||||
strcpy(myhost, data->set.ftpport); /* buffer overflow risk */
|
strcpy(myhost, data->set.ftpport); /* buffer overflow risk */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(! *myhost) {
|
if(! *myhost) {
|
||||||
h=Curl_getaddrinfo(data,
|
char *tmp_host = getmyhost(myhost, sizeof(myhost));
|
||||||
getmyhost(myhost, sizeof(myhost)),
|
h=Curl_resolv(data, tmp_host, 0, &hostdataptr);
|
||||||
0, &hostdataptr);
|
|
||||||
}
|
}
|
||||||
infof(data, "We connect from %s\n", myhost);
|
infof(data, "We connect from %s\n", myhost);
|
||||||
|
|
||||||
if ( h ) {
|
if ( h ) {
|
||||||
if( (portsock = socket(AF_INET, SOCK_STREAM, 0)) >= 0 ) {
|
if( (portsock = socket(AF_INET, SOCK_STREAM, 0)) >= 0 ) {
|
||||||
|
int size;
|
||||||
|
|
||||||
/* we set the secondary socket variable to this for now, it
|
/* we set the secondary socket variable to this for now, it
|
||||||
is only so that the cleanup function will close it in case
|
is only so that the cleanup function will close it in case
|
||||||
@@ -1211,10 +1240,10 @@ CURLcode ftp_use_port(struct connectdata *conn)
|
|||||||
if(bind(portsock, (struct sockaddr *)&sa, size) >= 0) {
|
if(bind(portsock, (struct sockaddr *)&sa, size) >= 0) {
|
||||||
/* we succeeded to bind */
|
/* we succeeded to bind */
|
||||||
struct sockaddr_in add;
|
struct sockaddr_in add;
|
||||||
size = sizeof(add);
|
socklen_t socksize = sizeof(add);
|
||||||
|
|
||||||
if(getsockname(portsock, (struct sockaddr *) &add,
|
if(getsockname(portsock, (struct sockaddr *) &add,
|
||||||
(socklen_t *)&size)<0) {
|
&socksize)<0) {
|
||||||
failf(data, "getsockname() failed");
|
failf(data, "getsockname() failed");
|
||||||
return CURLE_FTP_PORT_FAILED;
|
return CURLE_FTP_PORT_FAILED;
|
||||||
}
|
}
|
||||||
@@ -1237,9 +1266,6 @@ CURLcode ftp_use_port(struct connectdata *conn)
|
|||||||
free(hostdataptr);
|
free(hostdataptr);
|
||||||
return CURLE_FTP_PORT_FAILED;
|
return CURLE_FTP_PORT_FAILED;
|
||||||
}
|
}
|
||||||
if(hostdataptr)
|
|
||||||
/* free the memory used for name lookup */
|
|
||||||
Curl_freeaddrinfo(hostdataptr);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
failf(data, "could't find my own IP address (%s)", myhost);
|
failf(data, "could't find my own IP address (%s)", myhost);
|
||||||
@@ -1431,7 +1457,7 @@ CURLcode ftp_use_pasv(struct connectdata *conn)
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* normal, direct, ftp connection */
|
/* normal, direct, ftp connection */
|
||||||
addr = Curl_getaddrinfo(data, newhostp, newport, &hostdataptr);
|
addr = Curl_resolv(data, newhostp, newport, &hostdataptr);
|
||||||
if(!addr) {
|
if(!addr) {
|
||||||
failf(data, "Can't resolve new host %s", newhost);
|
failf(data, "Can't resolve new host %s", newhost);
|
||||||
return CURLE_FTP_CANT_GET_HOST;
|
return CURLE_FTP_CANT_GET_HOST;
|
||||||
@@ -1450,9 +1476,6 @@ CURLcode ftp_use_pasv(struct connectdata *conn)
|
|||||||
/* this just dumps information about this second connection */
|
/* this just dumps information about this second connection */
|
||||||
ftp_pasv_verbose(conn, conninfo, newhost, connectport);
|
ftp_pasv_verbose(conn, conninfo, newhost, connectport);
|
||||||
|
|
||||||
if(hostdataptr)
|
|
||||||
Curl_freeaddrinfo(hostdataptr);
|
|
||||||
|
|
||||||
if(CURLE_OK != result)
|
if(CURLE_OK != result)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
@@ -1517,9 +1540,10 @@ CURLcode ftp_perform(struct connectdata *conn)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we have selected NOBODY, it means that we only want file information.
|
/* If we have selected NOBODY and HEADER, it means that we only want file
|
||||||
Which in FTP can't be much more than the file size! */
|
information. Which in FTP can't be much more than the file size and
|
||||||
if(data->set.no_body) {
|
date. */
|
||||||
|
if(data->set.no_body && data->set.include_header) {
|
||||||
/* The SIZE command is _not_ RFC 959 specified, and therefor many servers
|
/* The SIZE command is _not_ RFC 959 specified, and therefor many servers
|
||||||
may not support it! It is however the only way we have to get a file's
|
may not support it! It is however the only way we have to get a file's
|
||||||
size! */
|
size! */
|
||||||
@@ -1565,20 +1589,27 @@ CURLcode ftp_perform(struct connectdata *conn)
|
|||||||
return CURLE_OK;
|
return CURLE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(data->set.no_body)
|
||||||
|
/* don't transfer the data */
|
||||||
|
;
|
||||||
/* Get us a second connection up and connected */
|
/* Get us a second connection up and connected */
|
||||||
if(data->set.ftp_use_port)
|
else if(data->set.ftp_use_port) {
|
||||||
/* We have chosen to use the PORT command */
|
/* We have chosen to use the PORT command */
|
||||||
result = ftp_use_port(conn);
|
result = ftp_use_port(conn);
|
||||||
else
|
if(CURLE_OK == result)
|
||||||
|
/* we have the data connection ready */
|
||||||
|
infof(data, "Connected the data stream with PORT!\n");
|
||||||
|
}
|
||||||
|
else {
|
||||||
/* We have chosen (this is default) to use the PASV command */
|
/* We have chosen (this is default) to use the PASV command */
|
||||||
result = ftp_use_pasv(conn);
|
result = ftp_use_pasv(conn);
|
||||||
|
if(CURLE_OK == result)
|
||||||
|
infof(data, "Connected the data stream with PASV!\n");
|
||||||
|
}
|
||||||
|
|
||||||
if(result)
|
if(result)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
/* we have the data connection ready */
|
|
||||||
infof(data, "Connected the data stream!\n");
|
|
||||||
|
|
||||||
if(data->set.upload) {
|
if(data->set.upload) {
|
||||||
|
|
||||||
/* Set type to binary (unless specified ASCII) */
|
/* Set type to binary (unless specified ASCII) */
|
||||||
@@ -1634,7 +1665,7 @@ CURLcode ftp_perform(struct connectdata *conn)
|
|||||||
|
|
||||||
passed += actuallyread;
|
passed += actuallyread;
|
||||||
if(actuallyread != readthisamountnow) {
|
if(actuallyread != readthisamountnow) {
|
||||||
failf(data, "Could only read %d bytes from the input\n", passed);
|
failf(data, "Could only read %d bytes from the input", passed);
|
||||||
return CURLE_FTP_COULDNT_USE_REST;
|
return CURLE_FTP_COULDNT_USE_REST;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1701,7 +1732,7 @@ CURLcode ftp_perform(struct connectdata *conn)
|
|||||||
return result;
|
return result;
|
||||||
|
|
||||||
}
|
}
|
||||||
else {
|
else if(!data->set.no_body) {
|
||||||
/* Retrieve file or directory */
|
/* Retrieve file or directory */
|
||||||
bool dirlist=FALSE;
|
bool dirlist=FALSE;
|
||||||
long downloadsize=-1;
|
long downloadsize=-1;
|
||||||
@@ -2027,9 +2058,11 @@ CURLcode Curl_ftp(struct connectdata *conn)
|
|||||||
CURLcode Curl_ftpsendf(struct connectdata *conn,
|
CURLcode Curl_ftpsendf(struct connectdata *conn,
|
||||||
const char *fmt, ...)
|
const char *fmt, ...)
|
||||||
{
|
{
|
||||||
size_t bytes_written;
|
ssize_t bytes_written;
|
||||||
char s[256];
|
char s[256];
|
||||||
size_t write_len;
|
ssize_t write_len;
|
||||||
|
char *sptr=s;
|
||||||
|
CURLcode res = CURLE_OK;
|
||||||
|
|
||||||
va_list ap;
|
va_list ap;
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
@@ -2043,9 +2076,23 @@ CURLcode Curl_ftpsendf(struct connectdata *conn,
|
|||||||
|
|
||||||
bytes_written=0;
|
bytes_written=0;
|
||||||
write_len = strlen(s);
|
write_len = strlen(s);
|
||||||
Curl_write(conn, conn->firstsocket, s, write_len, &bytes_written);
|
|
||||||
|
|
||||||
return (bytes_written==write_len)?CURLE_OK:CURLE_WRITE_ERROR;
|
do {
|
||||||
|
res = Curl_write(conn, conn->firstsocket, sptr, write_len,
|
||||||
|
&bytes_written);
|
||||||
|
|
||||||
|
if(CURLE_OK != res)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if(bytes_written != write_len) {
|
||||||
|
write_len -= bytes_written;
|
||||||
|
sptr += bytes_written;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
} while(1);
|
||||||
|
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
|
119
lib/getdate.c
119
lib/getdate.c
@@ -45,6 +45,11 @@
|
|||||||
# endif
|
# endif
|
||||||
#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
|
/* 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
|
itself, there is no need to #define static in this file. Even if
|
||||||
the code were included in the Emacs executable, it probably
|
the code were included in the Emacs executable, it probably
|
||||||
@@ -223,7 +228,7 @@ static int yyRelSeconds;
|
|||||||
static int yyRelYear;
|
static int yyRelYear;
|
||||||
|
|
||||||
|
|
||||||
#line 206 "getdate.y"
|
#line 211 "getdate.y"
|
||||||
typedef union {
|
typedef union {
|
||||||
int Number;
|
int Number;
|
||||||
enum _MERIDIAN Meridian;
|
enum _MERIDIAN Meridian;
|
||||||
@@ -306,11 +311,11 @@ static const short yyrhs[] = { -1,
|
|||||||
|
|
||||||
#if YYDEBUG != 0
|
#if YYDEBUG != 0
|
||||||
static const short yyrline[] = { 0,
|
static const short yyrline[] = { 0,
|
||||||
222, 223, 226, 229, 232, 235, 238, 241, 244, 250,
|
227, 228, 231, 234, 237, 240, 243, 246, 249, 255,
|
||||||
256, 265, 271, 283, 286, 289, 295, 299, 303, 309,
|
261, 270, 276, 288, 291, 294, 300, 304, 308, 314,
|
||||||
313, 331, 337, 343, 347, 352, 356, 363, 371, 374,
|
318, 336, 342, 348, 352, 357, 361, 368, 376, 379,
|
||||||
377, 380, 383, 386, 389, 392, 395, 398, 401, 404,
|
382, 385, 388, 391, 394, 397, 400, 403, 406, 409,
|
||||||
407, 410, 413, 416, 419, 422, 425, 430, 463, 467
|
412, 415, 418, 421, 424, 427, 430, 435, 468, 472
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -934,37 +939,37 @@ yyreduce:
|
|||||||
switch (yyn) {
|
switch (yyn) {
|
||||||
|
|
||||||
case 3:
|
case 3:
|
||||||
#line 226 "getdate.y"
|
#line 231 "getdate.y"
|
||||||
{
|
{
|
||||||
yyHaveTime++;
|
yyHaveTime++;
|
||||||
;
|
;
|
||||||
break;}
|
break;}
|
||||||
case 4:
|
case 4:
|
||||||
#line 229 "getdate.y"
|
#line 234 "getdate.y"
|
||||||
{
|
{
|
||||||
yyHaveZone++;
|
yyHaveZone++;
|
||||||
;
|
;
|
||||||
break;}
|
break;}
|
||||||
case 5:
|
case 5:
|
||||||
#line 232 "getdate.y"
|
#line 237 "getdate.y"
|
||||||
{
|
{
|
||||||
yyHaveDate++;
|
yyHaveDate++;
|
||||||
;
|
;
|
||||||
break;}
|
break;}
|
||||||
case 6:
|
case 6:
|
||||||
#line 235 "getdate.y"
|
#line 240 "getdate.y"
|
||||||
{
|
{
|
||||||
yyHaveDay++;
|
yyHaveDay++;
|
||||||
;
|
;
|
||||||
break;}
|
break;}
|
||||||
case 7:
|
case 7:
|
||||||
#line 238 "getdate.y"
|
#line 243 "getdate.y"
|
||||||
{
|
{
|
||||||
yyHaveRel++;
|
yyHaveRel++;
|
||||||
;
|
;
|
||||||
break;}
|
break;}
|
||||||
case 9:
|
case 9:
|
||||||
#line 244 "getdate.y"
|
#line 249 "getdate.y"
|
||||||
{
|
{
|
||||||
yyHour = yyvsp[-1].Number;
|
yyHour = yyvsp[-1].Number;
|
||||||
yyMinutes = 0;
|
yyMinutes = 0;
|
||||||
@@ -973,7 +978,7 @@ case 9:
|
|||||||
;
|
;
|
||||||
break;}
|
break;}
|
||||||
case 10:
|
case 10:
|
||||||
#line 250 "getdate.y"
|
#line 255 "getdate.y"
|
||||||
{
|
{
|
||||||
yyHour = yyvsp[-3].Number;
|
yyHour = yyvsp[-3].Number;
|
||||||
yyMinutes = yyvsp[-1].Number;
|
yyMinutes = yyvsp[-1].Number;
|
||||||
@@ -982,7 +987,7 @@ case 10:
|
|||||||
;
|
;
|
||||||
break;}
|
break;}
|
||||||
case 11:
|
case 11:
|
||||||
#line 256 "getdate.y"
|
#line 261 "getdate.y"
|
||||||
{
|
{
|
||||||
yyHour = yyvsp[-3].Number;
|
yyHour = yyvsp[-3].Number;
|
||||||
yyMinutes = yyvsp[-1].Number;
|
yyMinutes = yyvsp[-1].Number;
|
||||||
@@ -994,7 +999,7 @@ case 11:
|
|||||||
;
|
;
|
||||||
break;}
|
break;}
|
||||||
case 12:
|
case 12:
|
||||||
#line 265 "getdate.y"
|
#line 270 "getdate.y"
|
||||||
{
|
{
|
||||||
yyHour = yyvsp[-5].Number;
|
yyHour = yyvsp[-5].Number;
|
||||||
yyMinutes = yyvsp[-3].Number;
|
yyMinutes = yyvsp[-3].Number;
|
||||||
@@ -1003,7 +1008,7 @@ case 12:
|
|||||||
;
|
;
|
||||||
break;}
|
break;}
|
||||||
case 13:
|
case 13:
|
||||||
#line 271 "getdate.y"
|
#line 276 "getdate.y"
|
||||||
{
|
{
|
||||||
yyHour = yyvsp[-5].Number;
|
yyHour = yyvsp[-5].Number;
|
||||||
yyMinutes = yyvsp[-3].Number;
|
yyMinutes = yyvsp[-3].Number;
|
||||||
@@ -1016,53 +1021,53 @@ case 13:
|
|||||||
;
|
;
|
||||||
break;}
|
break;}
|
||||||
case 14:
|
case 14:
|
||||||
#line 283 "getdate.y"
|
#line 288 "getdate.y"
|
||||||
{
|
{
|
||||||
yyTimezone = yyvsp[0].Number;
|
yyTimezone = yyvsp[0].Number;
|
||||||
;
|
;
|
||||||
break;}
|
break;}
|
||||||
case 15:
|
case 15:
|
||||||
#line 286 "getdate.y"
|
#line 291 "getdate.y"
|
||||||
{
|
{
|
||||||
yyTimezone = yyvsp[0].Number - 60;
|
yyTimezone = yyvsp[0].Number - 60;
|
||||||
;
|
;
|
||||||
break;}
|
break;}
|
||||||
case 16:
|
case 16:
|
||||||
#line 290 "getdate.y"
|
#line 295 "getdate.y"
|
||||||
{
|
{
|
||||||
yyTimezone = yyvsp[-1].Number - 60;
|
yyTimezone = yyvsp[-1].Number - 60;
|
||||||
;
|
;
|
||||||
break;}
|
break;}
|
||||||
case 17:
|
case 17:
|
||||||
#line 295 "getdate.y"
|
#line 300 "getdate.y"
|
||||||
{
|
{
|
||||||
yyDayOrdinal = 1;
|
yyDayOrdinal = 1;
|
||||||
yyDayNumber = yyvsp[0].Number;
|
yyDayNumber = yyvsp[0].Number;
|
||||||
;
|
;
|
||||||
break;}
|
break;}
|
||||||
case 18:
|
case 18:
|
||||||
#line 299 "getdate.y"
|
#line 304 "getdate.y"
|
||||||
{
|
{
|
||||||
yyDayOrdinal = 1;
|
yyDayOrdinal = 1;
|
||||||
yyDayNumber = yyvsp[-1].Number;
|
yyDayNumber = yyvsp[-1].Number;
|
||||||
;
|
;
|
||||||
break;}
|
break;}
|
||||||
case 19:
|
case 19:
|
||||||
#line 303 "getdate.y"
|
#line 308 "getdate.y"
|
||||||
{
|
{
|
||||||
yyDayOrdinal = yyvsp[-1].Number;
|
yyDayOrdinal = yyvsp[-1].Number;
|
||||||
yyDayNumber = yyvsp[0].Number;
|
yyDayNumber = yyvsp[0].Number;
|
||||||
;
|
;
|
||||||
break;}
|
break;}
|
||||||
case 20:
|
case 20:
|
||||||
#line 309 "getdate.y"
|
#line 314 "getdate.y"
|
||||||
{
|
{
|
||||||
yyMonth = yyvsp[-2].Number;
|
yyMonth = yyvsp[-2].Number;
|
||||||
yyDay = yyvsp[0].Number;
|
yyDay = yyvsp[0].Number;
|
||||||
;
|
;
|
||||||
break;}
|
break;}
|
||||||
case 21:
|
case 21:
|
||||||
#line 313 "getdate.y"
|
#line 318 "getdate.y"
|
||||||
{
|
{
|
||||||
/* Interpret as YYYY/MM/DD if $1 >= 1000, otherwise as MM/DD/YY.
|
/* 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
|
The goal in recognizing YYYY/MM/DD is solely to support legacy
|
||||||
@@ -1083,7 +1088,7 @@ case 21:
|
|||||||
;
|
;
|
||||||
break;}
|
break;}
|
||||||
case 22:
|
case 22:
|
||||||
#line 331 "getdate.y"
|
#line 336 "getdate.y"
|
||||||
{
|
{
|
||||||
/* ISO 8601 format. yyyy-mm-dd. */
|
/* ISO 8601 format. yyyy-mm-dd. */
|
||||||
yyYear = yyvsp[-2].Number;
|
yyYear = yyvsp[-2].Number;
|
||||||
@@ -1092,7 +1097,7 @@ case 22:
|
|||||||
;
|
;
|
||||||
break;}
|
break;}
|
||||||
case 23:
|
case 23:
|
||||||
#line 337 "getdate.y"
|
#line 342 "getdate.y"
|
||||||
{
|
{
|
||||||
/* e.g. 17-JUN-1992. */
|
/* e.g. 17-JUN-1992. */
|
||||||
yyDay = yyvsp[-2].Number;
|
yyDay = yyvsp[-2].Number;
|
||||||
@@ -1101,14 +1106,14 @@ case 23:
|
|||||||
;
|
;
|
||||||
break;}
|
break;}
|
||||||
case 24:
|
case 24:
|
||||||
#line 343 "getdate.y"
|
#line 348 "getdate.y"
|
||||||
{
|
{
|
||||||
yyMonth = yyvsp[-1].Number;
|
yyMonth = yyvsp[-1].Number;
|
||||||
yyDay = yyvsp[0].Number;
|
yyDay = yyvsp[0].Number;
|
||||||
;
|
;
|
||||||
break;}
|
break;}
|
||||||
case 25:
|
case 25:
|
||||||
#line 347 "getdate.y"
|
#line 352 "getdate.y"
|
||||||
{
|
{
|
||||||
yyMonth = yyvsp[-3].Number;
|
yyMonth = yyvsp[-3].Number;
|
||||||
yyDay = yyvsp[-2].Number;
|
yyDay = yyvsp[-2].Number;
|
||||||
@@ -1116,14 +1121,14 @@ case 25:
|
|||||||
;
|
;
|
||||||
break;}
|
break;}
|
||||||
case 26:
|
case 26:
|
||||||
#line 352 "getdate.y"
|
#line 357 "getdate.y"
|
||||||
{
|
{
|
||||||
yyMonth = yyvsp[0].Number;
|
yyMonth = yyvsp[0].Number;
|
||||||
yyDay = yyvsp[-1].Number;
|
yyDay = yyvsp[-1].Number;
|
||||||
;
|
;
|
||||||
break;}
|
break;}
|
||||||
case 27:
|
case 27:
|
||||||
#line 356 "getdate.y"
|
#line 361 "getdate.y"
|
||||||
{
|
{
|
||||||
yyMonth = yyvsp[-1].Number;
|
yyMonth = yyvsp[-1].Number;
|
||||||
yyDay = yyvsp[-2].Number;
|
yyDay = yyvsp[-2].Number;
|
||||||
@@ -1131,7 +1136,7 @@ case 27:
|
|||||||
;
|
;
|
||||||
break;}
|
break;}
|
||||||
case 28:
|
case 28:
|
||||||
#line 363 "getdate.y"
|
#line 368 "getdate.y"
|
||||||
{
|
{
|
||||||
yyRelSeconds = -yyRelSeconds;
|
yyRelSeconds = -yyRelSeconds;
|
||||||
yyRelMinutes = -yyRelMinutes;
|
yyRelMinutes = -yyRelMinutes;
|
||||||
@@ -1142,115 +1147,115 @@ case 28:
|
|||||||
;
|
;
|
||||||
break;}
|
break;}
|
||||||
case 30:
|
case 30:
|
||||||
#line 374 "getdate.y"
|
#line 379 "getdate.y"
|
||||||
{
|
{
|
||||||
yyRelYear += yyvsp[-1].Number * yyvsp[0].Number;
|
yyRelYear += yyvsp[-1].Number * yyvsp[0].Number;
|
||||||
;
|
;
|
||||||
break;}
|
break;}
|
||||||
case 31:
|
case 31:
|
||||||
#line 377 "getdate.y"
|
#line 382 "getdate.y"
|
||||||
{
|
{
|
||||||
yyRelYear += yyvsp[-1].Number * yyvsp[0].Number;
|
yyRelYear += yyvsp[-1].Number * yyvsp[0].Number;
|
||||||
;
|
;
|
||||||
break;}
|
break;}
|
||||||
case 32:
|
case 32:
|
||||||
#line 380 "getdate.y"
|
#line 385 "getdate.y"
|
||||||
{
|
{
|
||||||
yyRelYear += yyvsp[0].Number;
|
yyRelYear += yyvsp[0].Number;
|
||||||
;
|
;
|
||||||
break;}
|
break;}
|
||||||
case 33:
|
case 33:
|
||||||
#line 383 "getdate.y"
|
#line 388 "getdate.y"
|
||||||
{
|
{
|
||||||
yyRelMonth += yyvsp[-1].Number * yyvsp[0].Number;
|
yyRelMonth += yyvsp[-1].Number * yyvsp[0].Number;
|
||||||
;
|
;
|
||||||
break;}
|
break;}
|
||||||
case 34:
|
case 34:
|
||||||
#line 386 "getdate.y"
|
#line 391 "getdate.y"
|
||||||
{
|
{
|
||||||
yyRelMonth += yyvsp[-1].Number * yyvsp[0].Number;
|
yyRelMonth += yyvsp[-1].Number * yyvsp[0].Number;
|
||||||
;
|
;
|
||||||
break;}
|
break;}
|
||||||
case 35:
|
case 35:
|
||||||
#line 389 "getdate.y"
|
#line 394 "getdate.y"
|
||||||
{
|
{
|
||||||
yyRelMonth += yyvsp[0].Number;
|
yyRelMonth += yyvsp[0].Number;
|
||||||
;
|
;
|
||||||
break;}
|
break;}
|
||||||
case 36:
|
case 36:
|
||||||
#line 392 "getdate.y"
|
#line 397 "getdate.y"
|
||||||
{
|
{
|
||||||
yyRelDay += yyvsp[-1].Number * yyvsp[0].Number;
|
yyRelDay += yyvsp[-1].Number * yyvsp[0].Number;
|
||||||
;
|
;
|
||||||
break;}
|
break;}
|
||||||
case 37:
|
case 37:
|
||||||
#line 395 "getdate.y"
|
#line 400 "getdate.y"
|
||||||
{
|
{
|
||||||
yyRelDay += yyvsp[-1].Number * yyvsp[0].Number;
|
yyRelDay += yyvsp[-1].Number * yyvsp[0].Number;
|
||||||
;
|
;
|
||||||
break;}
|
break;}
|
||||||
case 38:
|
case 38:
|
||||||
#line 398 "getdate.y"
|
#line 403 "getdate.y"
|
||||||
{
|
{
|
||||||
yyRelDay += yyvsp[0].Number;
|
yyRelDay += yyvsp[0].Number;
|
||||||
;
|
;
|
||||||
break;}
|
break;}
|
||||||
case 39:
|
case 39:
|
||||||
#line 401 "getdate.y"
|
#line 406 "getdate.y"
|
||||||
{
|
{
|
||||||
yyRelHour += yyvsp[-1].Number * yyvsp[0].Number;
|
yyRelHour += yyvsp[-1].Number * yyvsp[0].Number;
|
||||||
;
|
;
|
||||||
break;}
|
break;}
|
||||||
case 40:
|
case 40:
|
||||||
#line 404 "getdate.y"
|
#line 409 "getdate.y"
|
||||||
{
|
{
|
||||||
yyRelHour += yyvsp[-1].Number * yyvsp[0].Number;
|
yyRelHour += yyvsp[-1].Number * yyvsp[0].Number;
|
||||||
;
|
;
|
||||||
break;}
|
break;}
|
||||||
case 41:
|
case 41:
|
||||||
#line 407 "getdate.y"
|
#line 412 "getdate.y"
|
||||||
{
|
{
|
||||||
yyRelHour += yyvsp[0].Number;
|
yyRelHour += yyvsp[0].Number;
|
||||||
;
|
;
|
||||||
break;}
|
break;}
|
||||||
case 42:
|
case 42:
|
||||||
#line 410 "getdate.y"
|
#line 415 "getdate.y"
|
||||||
{
|
{
|
||||||
yyRelMinutes += yyvsp[-1].Number * yyvsp[0].Number;
|
yyRelMinutes += yyvsp[-1].Number * yyvsp[0].Number;
|
||||||
;
|
;
|
||||||
break;}
|
break;}
|
||||||
case 43:
|
case 43:
|
||||||
#line 413 "getdate.y"
|
#line 418 "getdate.y"
|
||||||
{
|
{
|
||||||
yyRelMinutes += yyvsp[-1].Number * yyvsp[0].Number;
|
yyRelMinutes += yyvsp[-1].Number * yyvsp[0].Number;
|
||||||
;
|
;
|
||||||
break;}
|
break;}
|
||||||
case 44:
|
case 44:
|
||||||
#line 416 "getdate.y"
|
#line 421 "getdate.y"
|
||||||
{
|
{
|
||||||
yyRelMinutes += yyvsp[0].Number;
|
yyRelMinutes += yyvsp[0].Number;
|
||||||
;
|
;
|
||||||
break;}
|
break;}
|
||||||
case 45:
|
case 45:
|
||||||
#line 419 "getdate.y"
|
#line 424 "getdate.y"
|
||||||
{
|
{
|
||||||
yyRelSeconds += yyvsp[-1].Number * yyvsp[0].Number;
|
yyRelSeconds += yyvsp[-1].Number * yyvsp[0].Number;
|
||||||
;
|
;
|
||||||
break;}
|
break;}
|
||||||
case 46:
|
case 46:
|
||||||
#line 422 "getdate.y"
|
#line 427 "getdate.y"
|
||||||
{
|
{
|
||||||
yyRelSeconds += yyvsp[-1].Number * yyvsp[0].Number;
|
yyRelSeconds += yyvsp[-1].Number * yyvsp[0].Number;
|
||||||
;
|
;
|
||||||
break;}
|
break;}
|
||||||
case 47:
|
case 47:
|
||||||
#line 425 "getdate.y"
|
#line 430 "getdate.y"
|
||||||
{
|
{
|
||||||
yyRelSeconds += yyvsp[0].Number;
|
yyRelSeconds += yyvsp[0].Number;
|
||||||
;
|
;
|
||||||
break;}
|
break;}
|
||||||
case 48:
|
case 48:
|
||||||
#line 431 "getdate.y"
|
#line 436 "getdate.y"
|
||||||
{
|
{
|
||||||
if (yyHaveTime && yyHaveDate && !yyHaveRel)
|
if (yyHaveTime && yyHaveDate && !yyHaveRel)
|
||||||
yyYear = yyvsp[0].Number;
|
yyYear = yyvsp[0].Number;
|
||||||
@@ -1283,13 +1288,13 @@ case 48:
|
|||||||
;
|
;
|
||||||
break;}
|
break;}
|
||||||
case 49:
|
case 49:
|
||||||
#line 464 "getdate.y"
|
#line 469 "getdate.y"
|
||||||
{
|
{
|
||||||
yyval.Meridian = MER24;
|
yyval.Meridian = MER24;
|
||||||
;
|
;
|
||||||
break;}
|
break;}
|
||||||
case 50:
|
case 50:
|
||||||
#line 468 "getdate.y"
|
#line 473 "getdate.y"
|
||||||
{
|
{
|
||||||
yyval.Meridian = yyvsp[0].Meridian;
|
yyval.Meridian = yyvsp[0].Meridian;
|
||||||
;
|
;
|
||||||
@@ -1516,7 +1521,7 @@ yyerrhandle:
|
|||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
#line 473 "getdate.y"
|
#line 478 "getdate.y"
|
||||||
|
|
||||||
|
|
||||||
/* Include this file down here because bison inserts code above which
|
/* Include this file down here because bison inserts code above which
|
||||||
@@ -2126,11 +2131,3 @@ main (ac, av)
|
|||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
}
|
}
|
||||||
#endif /* defined (TEST) */
|
#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
|
||||||
#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
|
/* 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
|
itself, there is no need to #define static in this file. Even if
|
||||||
the code were included in the Emacs executable, it probably
|
the code were included in the Emacs executable, it probably
|
||||||
|
@@ -55,7 +55,6 @@ char *GetEnv(const char *variable)
|
|||||||
if (env && strcmp("HOME",variable) == 0) {
|
if (env && strcmp("HOME",variable) == 0) {
|
||||||
env = decc$translate_vms(env);
|
env = decc$translate_vms(env);
|
||||||
}
|
}
|
||||||
/* printf ("Getenv: %s=%s\n",variable,env); */
|
|
||||||
#else
|
#else
|
||||||
/* no length control */
|
/* no length control */
|
||||||
char *env = getenv(variable);
|
char *env = getenv(variable);
|
||||||
|
285
lib/hash.c
Normal file
285
lib/hash.c
Normal file
@@ -0,0 +1,285 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* _ _ ____ _
|
||||||
|
* Project ___| | | | _ \| |
|
||||||
|
* / __| | | | |_) | |
|
||||||
|
* | (__| |_| | _ <| |___
|
||||||
|
* \___|\___/|_| \_\_____|
|
||||||
|
*
|
||||||
|
* Copyright (C) 2001, 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.
|
||||||
|
*
|
||||||
|
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||||
|
* copies of the Software, and permit persons to whom the Software is
|
||||||
|
* furnished to do so, under the terms of the MPL or the MIT/X-derivate
|
||||||
|
* licenses. You may pick one of these licenses.
|
||||||
|
*
|
||||||
|
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||||
|
* KIND, either express or implied.
|
||||||
|
*
|
||||||
|
* $Id$
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#include "setup.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "hash.h"
|
||||||
|
#include "llist.h"
|
||||||
|
|
||||||
|
#ifdef MALLOCDEBUG
|
||||||
|
/* this must be the last include file */
|
||||||
|
#include "memdebug.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
static unsigned long
|
||||||
|
curl_hash_str(const char *key, unsigned int key_length)
|
||||||
|
{
|
||||||
|
register unsigned long h = 0;
|
||||||
|
register unsigned long g;
|
||||||
|
register char *p = (char *) key;
|
||||||
|
register char *end = (char *) key + key_length;
|
||||||
|
|
||||||
|
while (p < end) {
|
||||||
|
h = (h << 4) + *p++;
|
||||||
|
if ((g = (h & 0xF0000000))) {
|
||||||
|
h = h ^ (g >> 24);
|
||||||
|
h = h ^ g;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned long
|
||||||
|
curl_hash_num(unsigned long key)
|
||||||
|
{
|
||||||
|
key += ~(key << 15);
|
||||||
|
key ^= (key >> 10);
|
||||||
|
key += (key << 3);
|
||||||
|
key ^= (key >> 6);
|
||||||
|
key += (key << 11);
|
||||||
|
key ^= (key >> 16);
|
||||||
|
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
hash_element_dtor(void *u, void *ele)
|
||||||
|
{
|
||||||
|
curl_hash_element *e = (curl_hash_element *) ele;
|
||||||
|
curl_hash *h = (curl_hash *) u;
|
||||||
|
|
||||||
|
if (e->key.type == CURL_HASH_KEY_IS_STRING) {
|
||||||
|
free(e->key.value.str.val);
|
||||||
|
}
|
||||||
|
h->dtor(e->ptr);
|
||||||
|
|
||||||
|
free(e);
|
||||||
|
e = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
curl_hash_init(curl_hash *h, int slots, curl_hash_dtor dtor)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
h->dtor = dtor;
|
||||||
|
h->size = 0;
|
||||||
|
h->slots = slots;
|
||||||
|
|
||||||
|
h->table = (curl_llist **) malloc(slots * sizeof(curl_llist *));
|
||||||
|
for (i = 0; i < h->slots; ++i) {
|
||||||
|
h->table[i] = curl_llist_alloc((curl_llist_dtor) hash_element_dtor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
curl_hash *
|
||||||
|
curl_hash_alloc(int slots, curl_hash_dtor dtor)
|
||||||
|
{
|
||||||
|
curl_hash *h;
|
||||||
|
|
||||||
|
h = (curl_hash *)malloc(sizeof(curl_hash));
|
||||||
|
if(NULL == h)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
curl_hash_init(h, slots, dtor);
|
||||||
|
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define FIND_SLOT(__h, __s_key, __s_key_len, __n_key) \
|
||||||
|
((__s_key ? curl_hash_str(__s_key, __s_key_len) : curl_hash_num(__n_key)) % (__h)->slots)
|
||||||
|
|
||||||
|
#define KEY_CREATE(__k, __s_key, __s_key_len, __n_key, __dup) \
|
||||||
|
if (__s_key) { \
|
||||||
|
if (__dup) { \
|
||||||
|
(__k)->value.str.val = (char *) malloc(__s_key_len); \
|
||||||
|
memcpy((__k)->value.str.val, __s_key, __s_key_len); \
|
||||||
|
} else { \
|
||||||
|
(__k)->value.str.val = __s_key; \
|
||||||
|
} \
|
||||||
|
(__k)->value.str.len = __s_key_len; \
|
||||||
|
(__k)->type = CURL_HASH_KEY_IS_STRING; \
|
||||||
|
} else { \
|
||||||
|
(__k)->value.num = __n_key; \
|
||||||
|
(__k)->type = CURL_HASH_KEY_IS_NUM; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define MIN(a, b) (a > b ? b : a)
|
||||||
|
|
||||||
|
static int
|
||||||
|
curl_hash_key_compare(curl_hash_key *key1, curl_hash_key *key2)
|
||||||
|
{
|
||||||
|
if (key1->type == CURL_HASH_KEY_IS_NUM) {
|
||||||
|
if (key2->type == CURL_HASH_KEY_IS_STRING)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (key1->value.num == key2->value.num)
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
if (key2->type == CURL_HASH_KEY_IS_NUM)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (memcmp(key1->value.str.val, key2->value.str.val,
|
||||||
|
MIN(key1->value.str.len, key2->value.str.len)) == 0)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
curl_hash_add_or_update(curl_hash *h, char *str_key, unsigned int str_key_len,
|
||||||
|
unsigned long num_key, const void *p)
|
||||||
|
{
|
||||||
|
curl_hash_element *e;
|
||||||
|
curl_hash_key tmp;
|
||||||
|
curl_llist *l;
|
||||||
|
curl_llist_element *le;
|
||||||
|
int slot;
|
||||||
|
|
||||||
|
slot = FIND_SLOT(h, str_key, str_key_len, num_key);
|
||||||
|
l = h->table[slot];
|
||||||
|
KEY_CREATE(&tmp, str_key, str_key_len, num_key, 0);
|
||||||
|
for (le = CURL_LLIST_HEAD(l); le != NULL; le = CURL_LLIST_NEXT(le)) {
|
||||||
|
if (curl_hash_key_compare(&tmp, &((curl_hash_element *) CURL_LLIST_VALP(le))->key)) {
|
||||||
|
curl_hash_element *to_update = CURL_LLIST_VALP(le);
|
||||||
|
h->dtor(to_update->ptr);
|
||||||
|
to_update->ptr = (void *) p;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
e = (curl_hash_element *) malloc(sizeof(curl_hash_element));
|
||||||
|
KEY_CREATE(&e->key, str_key, str_key_len, num_key, 1);
|
||||||
|
e->ptr = (void *) p;
|
||||||
|
|
||||||
|
if (curl_llist_insert_next(l, CURL_LLIST_TAIL(l), e)) {
|
||||||
|
++h->size;
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
curl_hash_extended_delete(curl_hash *h, char *str_key, unsigned int str_key_len,
|
||||||
|
unsigned long num_key)
|
||||||
|
{
|
||||||
|
curl_llist *l;
|
||||||
|
curl_llist_element *le;
|
||||||
|
curl_hash_key tmp;
|
||||||
|
int slot;
|
||||||
|
|
||||||
|
slot = FIND_SLOT(h, str_key, str_key_len, num_key);
|
||||||
|
l = h->table[slot];
|
||||||
|
|
||||||
|
KEY_CREATE(&tmp, str_key, str_key_len, num_key, 0);
|
||||||
|
for (le = CURL_LLIST_HEAD(l); le != NULL; le = CURL_LLIST_NEXT(le)) {
|
||||||
|
if (curl_hash_key_compare(&tmp, &((curl_hash_element *) CURL_LLIST_VALP(le))->key)) {
|
||||||
|
curl_llist_remove(l, le, (void *) h);
|
||||||
|
--h->size;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
curl_hash_extended_find(curl_hash *h, char *str_key, unsigned int str_key_len,
|
||||||
|
unsigned long num_key, void **p)
|
||||||
|
{
|
||||||
|
curl_llist *l;
|
||||||
|
curl_llist_element *le;
|
||||||
|
curl_hash_key tmp;
|
||||||
|
int slot;
|
||||||
|
|
||||||
|
slot = FIND_SLOT(h, str_key, str_key_len, num_key);
|
||||||
|
l = h->table[slot];
|
||||||
|
|
||||||
|
KEY_CREATE(&tmp, str_key, str_key_len, num_key, 0);
|
||||||
|
for (le = CURL_LLIST_HEAD(l); le != NULL; le = CURL_LLIST_NEXT(le)) {
|
||||||
|
if (curl_hash_key_compare(&tmp, &((curl_hash_element *) CURL_LLIST_VALP(le))->key)) {
|
||||||
|
*p = ((curl_hash_element *) CURL_LLIST_VALP(le))->ptr;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
curl_hash_apply(curl_hash *h, void *user, void (*cb)(void *, curl_hash_element *))
|
||||||
|
{
|
||||||
|
curl_llist_element *le;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < h->slots; ++i) {
|
||||||
|
for (le = CURL_LLIST_HEAD(h->table[i]); le != NULL; le = CURL_LLIST_NEXT(le)) {
|
||||||
|
cb(user, (curl_hash_element *) CURL_LLIST_VALP(le));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
curl_hash_clean(curl_hash *h)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < h->slots; ++i) {
|
||||||
|
curl_llist_destroy(h->table[i], (void *) h);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(h->table);
|
||||||
|
h->table = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
curl_hash_count(curl_hash *h)
|
||||||
|
{
|
||||||
|
return h->size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
curl_hash_destroy(curl_hash *h)
|
||||||
|
{
|
||||||
|
if (!h) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
curl_hash_clean(h);
|
||||||
|
free(h);
|
||||||
|
h = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* local variables:
|
||||||
|
* eval: (load-file "../curl-mode.el")
|
||||||
|
* end:
|
||||||
|
* vim600: fdm=marker
|
||||||
|
* vim: et sw=2 ts=2 sts=2 tw=78
|
||||||
|
*/
|
85
lib/hash.h
Normal file
85
lib/hash.h
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
#ifndef __HASH_H
|
||||||
|
#define __HASH_H
|
||||||
|
/*****************************************************************************
|
||||||
|
* _ _ ____ _
|
||||||
|
* Project ___| | | | _ \| |
|
||||||
|
* / __| | | | |_) | |
|
||||||
|
* | (__| |_| | _ <| |___
|
||||||
|
* \___|\___/|_| \_\_____|
|
||||||
|
*
|
||||||
|
* Copyright (C) 2000, 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.
|
||||||
|
*
|
||||||
|
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||||
|
* copies of the Software, and permit persons to whom the Software is
|
||||||
|
* furnished to do so, under the terms of the MPL or the MIT/X-derivate
|
||||||
|
* licenses. You may pick one of these licenses.
|
||||||
|
*
|
||||||
|
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||||
|
* KIND, either express or implied.
|
||||||
|
*
|
||||||
|
* $Id$
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#include "setup.h"
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#include "llist.h"
|
||||||
|
|
||||||
|
#define CURL_HASH_KEY_IS_STRING 0
|
||||||
|
#define CURL_HASH_KEY_IS_NUM 1
|
||||||
|
|
||||||
|
typedef void (*curl_hash_dtor)(void *);
|
||||||
|
|
||||||
|
typedef struct _curl_hash {
|
||||||
|
curl_llist **table;
|
||||||
|
curl_hash_dtor dtor;
|
||||||
|
int slots;
|
||||||
|
size_t size;
|
||||||
|
} curl_hash;
|
||||||
|
|
||||||
|
typedef struct _curl_hash_key {
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
char *val;
|
||||||
|
unsigned int len;
|
||||||
|
} str;
|
||||||
|
|
||||||
|
unsigned long num;
|
||||||
|
} value;
|
||||||
|
|
||||||
|
int type;
|
||||||
|
} curl_hash_key;
|
||||||
|
|
||||||
|
typedef struct _curl_hash_element {
|
||||||
|
curl_hash_key key;
|
||||||
|
void *ptr;
|
||||||
|
} curl_hash_element;
|
||||||
|
|
||||||
|
|
||||||
|
void curl_hash_init(curl_hash *h, int slots, curl_hash_dtor dtor);
|
||||||
|
curl_hash *curl_hash_alloc(int slots, curl_hash_dtor dtor);
|
||||||
|
int curl_hash_add_or_update(curl_hash *h, char *str_key, unsigned int str_key_len,
|
||||||
|
unsigned long num_key, const void *p);
|
||||||
|
int curl_hash_extended_delete(curl_hash *h, char *str_key, unsigned int str_key_len,
|
||||||
|
unsigned long num_key);
|
||||||
|
int curl_hash_extended_find(curl_hash *h, char *str_key, unsigned int str_key_len,
|
||||||
|
unsigned long num_key, void **p);
|
||||||
|
void curl_hash_apply(curl_hash *h, void *user, void (*cb)(void *, curl_hash_element *));
|
||||||
|
size_t curl_hash_count(curl_hash *h);
|
||||||
|
void curl_hash_clean(curl_hash *h);
|
||||||
|
void curl_hash_destroy(curl_hash *h);
|
||||||
|
|
||||||
|
#define curl_hash_find(h, key, key_len, p) curl_hash_extended_find(h, key, key_len, 0, p)
|
||||||
|
#define curl_hash_delete(h, key, key_len) curl_hash_extended_delete(h, key, key_len, 0)
|
||||||
|
#define curl_hash_add(h, key, key_len, p) curl_hash_add_or_update(h, key, key_len, 0, p)
|
||||||
|
#define curl_hash_update curl_hash_add
|
||||||
|
#define curl_hash_index_find(h, key, p) curl_hash_extended_find(h, NULL, 0, key, p)
|
||||||
|
#define curl_hash_index_delete(h, key) curl_hash_extended_delete(h, NULL, 0, key)
|
||||||
|
#define curl_hash_index_add(h, key, p) curl_hash_add_or_update(h, NULL, 0, key, p)
|
||||||
|
#define curl_hash_index_update curl_hash_index_add
|
||||||
|
|
||||||
|
#endif
|
170
lib/hostip.c
170
lib/hostip.c
@@ -58,6 +58,10 @@
|
|||||||
#include "urldata.h"
|
#include "urldata.h"
|
||||||
#include "sendf.h"
|
#include "sendf.h"
|
||||||
#include "hostip.h"
|
#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)
|
#if defined(HAVE_INET_NTOA_R) && !defined(HAVE_INET_NTOA_R_DECL)
|
||||||
#include "inet_ntoa_r.h"
|
#include "inet_ntoa_r.h"
|
||||||
@@ -68,6 +72,151 @@
|
|||||||
#include "memdebug.h"
|
#include "memdebug.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static curl_hash hostname_cache;
|
||||||
|
static int host_cache_initialized;
|
||||||
|
|
||||||
|
void Curl_global_host_cache_init(void)
|
||||||
|
{
|
||||||
|
if (!host_cache_initialized) {
|
||||||
|
curl_hash_init(&hostname_cache, 7, Curl_freeaddrinfo);
|
||||||
|
host_cache_initialized = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
curl_hash *Curl_global_host_cache_get(void)
|
||||||
|
{
|
||||||
|
return &hostname_cache;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Curl_global_host_cache_dtor(void)
|
||||||
|
{
|
||||||
|
if (host_cache_initialized) {
|
||||||
|
curl_hash_clean(&hostname_cache);
|
||||||
|
host_cache_initialized = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct curl_dns_cache_entry {
|
||||||
|
Curl_addrinfo *addr;
|
||||||
|
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;
|
||||||
|
ssize_t entry_len;
|
||||||
|
time_t now;
|
||||||
|
|
||||||
|
/* If the host cache timeout is 0, we don't do DNS cach'ing
|
||||||
|
so fall through */
|
||||||
|
if (data->set.dns_cache_timeout == 0) {
|
||||||
|
return Curl_getaddrinfo(data, hostname, port, bufp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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 (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) {
|
||||||
|
_hostcache_return(p->addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
_hostcache_return(p->addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create a new cache entry */
|
||||||
|
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);
|
||||||
|
_hostcache_return(NULL);
|
||||||
|
}
|
||||||
|
p->timestamp = now;
|
||||||
|
|
||||||
|
/* Save it in our host cache */
|
||||||
|
curl_hash_update(data->hostcache, entry_id, entry_len+1, (const void *) p);
|
||||||
|
|
||||||
|
_hostcache_return(p->addr);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is a wrapper function for freeing name information in a protocol
|
* This is a wrapper function for freeing name information in a protocol
|
||||||
* independent way. This takes care of using the appropriate underlaying
|
* independent way. This takes care of using the appropriate underlaying
|
||||||
@@ -75,11 +224,15 @@
|
|||||||
*/
|
*/
|
||||||
void Curl_freeaddrinfo(void *freethis)
|
void Curl_freeaddrinfo(void *freethis)
|
||||||
{
|
{
|
||||||
|
struct curl_dns_cache_entry *p = (struct curl_dns_cache_entry *) freethis;
|
||||||
|
|
||||||
#ifdef ENABLE_IPV6
|
#ifdef ENABLE_IPV6
|
||||||
freeaddrinfo(freethis);
|
freeaddrinfo(p->addr);
|
||||||
#else
|
#else
|
||||||
free(freethis);
|
free(p->addr);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
free(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --- resolve name or IP-number --- */
|
/* --- resolve name or IP-number --- */
|
||||||
@@ -102,7 +255,7 @@ int curl_getaddrinfo(char *hostname, char *service,
|
|||||||
/* success */
|
/* success */
|
||||||
if(logfile)
|
if(logfile)
|
||||||
fprintf(logfile, "ADDR %s:%d getaddrinfo() = %p\n",
|
fprintf(logfile, "ADDR %s:%d getaddrinfo() = %p\n",
|
||||||
source, line, *result);
|
source, line, (void *)*result);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if(logfile)
|
if(logfile)
|
||||||
@@ -118,7 +271,7 @@ void curl_freeaddrinfo(struct addrinfo *freethis,
|
|||||||
(freeaddrinfo)(freethis);
|
(freeaddrinfo)(freethis);
|
||||||
if(logfile)
|
if(logfile)
|
||||||
fprintf(logfile, "ADDR %s:%d freeaddrinfo(%p)\n",
|
fprintf(logfile, "ADDR %s:%d freeaddrinfo(%p)\n",
|
||||||
source, line, freethis);
|
source, line, (void *)freethis);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -265,7 +418,7 @@ Curl_addrinfo *Curl_getaddrinfo(struct SessionHandle *data,
|
|||||||
char **bufp)
|
char **bufp)
|
||||||
{
|
{
|
||||||
struct hostent *h = NULL;
|
struct hostent *h = NULL;
|
||||||
unsigned long in;
|
in_addr_t in;
|
||||||
int ret; /* this variable is unused on several platforms but used on some */
|
int ret; /* this variable is unused on several platforms but used on some */
|
||||||
|
|
||||||
#define CURL_NAMELOOKUP_SIZE 9000
|
#define CURL_NAMELOOKUP_SIZE 9000
|
||||||
@@ -273,10 +426,10 @@ Curl_addrinfo *Curl_getaddrinfo(struct SessionHandle *data,
|
|||||||
* everything. OSF1 is known to require at least 8872 bytes. The buffer
|
* everything. OSF1 is known to require at least 8872 bytes. The buffer
|
||||||
* required for storing all possible aliases and IP numbers is according to
|
* required for storing all possible aliases and IP numbers is according to
|
||||||
* Stevens' Unix Network Programming 2nd editor, p. 304: 8192 bytes! */
|
* 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)
|
if(!buf)
|
||||||
return NULL; /* major failure */
|
return NULL; /* major failure */
|
||||||
*bufp = buf;
|
*bufp = (char *)buf;
|
||||||
|
|
||||||
port=0; /* unused in IPv4 code */
|
port=0; /* unused in IPv4 code */
|
||||||
ret = 0; /* to prevent the compiler warning */
|
ret = 0; /* to prevent the compiler warning */
|
||||||
@@ -306,7 +459,7 @@ Curl_addrinfo *Curl_getaddrinfo(struct SessionHandle *data,
|
|||||||
/* Solaris, IRIX and more */
|
/* Solaris, IRIX and more */
|
||||||
if ((h = gethostbyname_r(hostname,
|
if ((h = gethostbyname_r(hostname,
|
||||||
(struct hostent *)buf,
|
(struct hostent *)buf,
|
||||||
buf + sizeof(struct hostent),
|
(char *)buf + sizeof(struct hostent),
|
||||||
CURL_NAMELOOKUP_SIZE - sizeof(struct hostent),
|
CURL_NAMELOOKUP_SIZE - sizeof(struct hostent),
|
||||||
&h_errnop)) == NULL )
|
&h_errnop)) == NULL )
|
||||||
#endif
|
#endif
|
||||||
@@ -372,3 +525,4 @@ Curl_addrinfo *Curl_getaddrinfo(struct SessionHandle *data,
|
|||||||
* vim600: fdm=marker
|
* vim600: fdm=marker
|
||||||
* vim: et sw=2 ts=2 sts=2 tw=78
|
* vim: et sw=2 ts=2 sts=2 tw=78
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
13
lib/hostip.h
13
lib/hostip.h
@@ -23,10 +23,23 @@
|
|||||||
* $Id$
|
* $Id$
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#include "hash.h"
|
||||||
|
|
||||||
struct addrinfo;
|
struct addrinfo;
|
||||||
struct hostent;
|
struct hostent;
|
||||||
struct SessionHandle;
|
struct SessionHandle;
|
||||||
|
|
||||||
|
void Curl_global_host_cache_init(void);
|
||||||
|
void Curl_global_host_cache_dtor(void);
|
||||||
|
curl_hash *Curl_global_host_cache_get(void);
|
||||||
|
|
||||||
|
#define Curl_global_host_cache_use(__p) ((__p)->set.global_dns_cache)
|
||||||
|
|
||||||
|
Curl_addrinfo *Curl_resolv(struct SessionHandle *data,
|
||||||
|
char *hostname,
|
||||||
|
int port,
|
||||||
|
char **bufp);
|
||||||
|
|
||||||
/* Get name info */
|
/* Get name info */
|
||||||
Curl_addrinfo *Curl_getaddrinfo(struct SessionHandle *data,
|
Curl_addrinfo *Curl_getaddrinfo(struct SessionHandle *data,
|
||||||
char *hostname,
|
char *hostname,
|
||||||
|
51
lib/http.c
51
lib/http.c
@@ -128,8 +128,10 @@ static
|
|||||||
CURLcode add_buffer_send(int sockfd, struct connectdata *conn, send_buffer *in,
|
CURLcode add_buffer_send(int sockfd, struct connectdata *conn, send_buffer *in,
|
||||||
long *bytes_written)
|
long *bytes_written)
|
||||||
{
|
{
|
||||||
size_t amount;
|
ssize_t amount;
|
||||||
CURLcode result;
|
CURLcode res;
|
||||||
|
char *ptr;
|
||||||
|
int size;
|
||||||
|
|
||||||
if(conn->data->set.verbose) {
|
if(conn->data->set.verbose) {
|
||||||
fputs("> ", conn->data->set.err);
|
fputs("> ", conn->data->set.err);
|
||||||
@@ -137,7 +139,25 @@ CURLcode add_buffer_send(int sockfd, struct connectdata *conn, send_buffer *in,
|
|||||||
fwrite(in->buffer, in->size_used, 1, conn->data->set.err);
|
fwrite(in->buffer, in->size_used, 1, conn->data->set.err);
|
||||||
}
|
}
|
||||||
|
|
||||||
result = Curl_write(conn, sockfd, in->buffer, in->size_used, &amount);
|
/* The looping below is required since we use non-blocking sockets, but due
|
||||||
|
to the circumstances we will just loop and try again and again etc */
|
||||||
|
|
||||||
|
ptr = in->buffer;
|
||||||
|
size = in->size_used;
|
||||||
|
do {
|
||||||
|
res = Curl_write(conn, sockfd, ptr, size, &amount);
|
||||||
|
|
||||||
|
if(CURLE_OK != res)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if(amount != size) {
|
||||||
|
size += amount;
|
||||||
|
ptr += amount;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
|
||||||
|
} while(1);
|
||||||
|
|
||||||
if(in->buffer)
|
if(in->buffer)
|
||||||
free(in->buffer);
|
free(in->buffer);
|
||||||
@@ -145,7 +165,7 @@ CURLcode add_buffer_send(int sockfd, struct connectdata *conn, send_buffer *in,
|
|||||||
|
|
||||||
*bytes_written = amount;
|
*bytes_written = amount;
|
||||||
|
|
||||||
return result;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -235,6 +255,7 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn,
|
|||||||
int subversion=0;
|
int subversion=0;
|
||||||
struct SessionHandle *data=conn->data;
|
struct SessionHandle *data=conn->data;
|
||||||
CURLcode result;
|
CURLcode result;
|
||||||
|
int res;
|
||||||
|
|
||||||
int nread; /* total size read */
|
int nread; /* total size read */
|
||||||
int perline; /* count bytes per line */
|
int perline; /* count bytes per line */
|
||||||
@@ -317,8 +338,12 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn,
|
|||||||
* to read, but when we use Curl_read() it may do so. Do confirm
|
* to read, but when we use Curl_read() it may do so. Do confirm
|
||||||
* that this is still ok and then remove this comment!
|
* that this is still ok and then remove this comment!
|
||||||
*/
|
*/
|
||||||
if(CURLE_OK != Curl_read(conn, tunnelsocket, ptr, BUFSIZE-nread,
|
res= Curl_read(conn, tunnelsocket, ptr, BUFSIZE-nread,
|
||||||
&gotbytes))
|
&gotbytes);
|
||||||
|
if(res< 0)
|
||||||
|
/* EWOULDBLOCK */
|
||||||
|
continue; /* go loop yourself */
|
||||||
|
else if(res)
|
||||||
keepon = FALSE;
|
keepon = FALSE;
|
||||||
else if(gotbytes <= 0) {
|
else if(gotbytes <= 0) {
|
||||||
keepon = FALSE;
|
keepon = FALSE;
|
||||||
@@ -449,7 +474,7 @@ CURLcode Curl_http_done(struct connectdata *conn)
|
|||||||
if(0 == (http->readbytecount + conn->headerbytecount)) {
|
if(0 == (http->readbytecount + conn->headerbytecount)) {
|
||||||
/* nothing was read from the HTTP server, this can't be right
|
/* nothing was read from the HTTP server, this can't be right
|
||||||
so we return an error here */
|
so we return an error here */
|
||||||
failf(data, "Empty reply from server\n");
|
failf(data, "Empty reply from server");
|
||||||
return CURLE_GOT_NOTHING;
|
return CURLE_GOT_NOTHING;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -610,7 +635,7 @@ CURLcode Curl_http(struct connectdata *conn)
|
|||||||
|
|
||||||
passed += actuallyread;
|
passed += actuallyread;
|
||||||
if(actuallyread != readthisamountnow) {
|
if(actuallyread != readthisamountnow) {
|
||||||
failf(data, "Could only read %d bytes from the input\n",
|
failf(data, "Could only read %d bytes from the input",
|
||||||
passed);
|
passed);
|
||||||
return CURLE_READ_ERROR;
|
return CURLE_READ_ERROR;
|
||||||
}
|
}
|
||||||
@@ -621,7 +646,7 @@ CURLcode Curl_http(struct connectdata *conn)
|
|||||||
data->set.infilesize -= conn->resume_from;
|
data->set.infilesize -= conn->resume_from;
|
||||||
|
|
||||||
if(data->set.infilesize <= 0) {
|
if(data->set.infilesize <= 0) {
|
||||||
failf(data, "File already completely uploaded\n");
|
failf(data, "File already completely uploaded");
|
||||||
return CURLE_PARTIAL_FILE;
|
return CURLE_PARTIAL_FILE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -735,10 +760,8 @@ CURLcode Curl_http(struct connectdata *conn)
|
|||||||
* equal to UTC (Coordinated Universal Time)." (see page 20 of RFC2616).
|
* equal to UTC (Coordinated Universal Time)." (see page 20 of RFC2616).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef HAVE_LOCALTIME_R
|
#ifdef HAVE_GMTIME_R
|
||||||
/* thread-safe version */
|
/* thread-safe version */
|
||||||
/* We assume that the presense of localtime_r() proves the presense
|
|
||||||
of gmtime_r() which is a bit ugly but might work */
|
|
||||||
struct tm keeptime;
|
struct tm keeptime;
|
||||||
thistime = (struct tm *)gmtime_r(&data->set.timevalue, &keeptime);
|
thistime = (struct tm *)gmtime_r(&data->set.timevalue, &keeptime);
|
||||||
#else
|
#else
|
||||||
@@ -795,7 +818,7 @@ CURLcode Curl_http(struct connectdata *conn)
|
|||||||
char contentType[256];
|
char contentType[256];
|
||||||
int linelength=0;
|
int linelength=0;
|
||||||
if(Curl_FormInit(&http->form, http->sendit)) {
|
if(Curl_FormInit(&http->form, http->sendit)) {
|
||||||
failf(data, "Internal HTTP POST error!\n");
|
failf(data, "Internal HTTP POST error!");
|
||||||
return CURLE_HTTP_POST_ERROR;
|
return CURLE_HTTP_POST_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -826,7 +849,7 @@ CURLcode Curl_http(struct connectdata *conn)
|
|||||||
1,
|
1,
|
||||||
(FILE *)&http->form);
|
(FILE *)&http->form);
|
||||||
if(linelength == -1) {
|
if(linelength == -1) {
|
||||||
failf(data, "Could not get Content-Type header line!\n");
|
failf(data, "Could not get Content-Type header line!");
|
||||||
return CURLE_HTTP_POST_ERROR;
|
return CURLE_HTTP_POST_ERROR;
|
||||||
}
|
}
|
||||||
add_buffer(req_buffer, contentType, linelength);
|
add_buffer(req_buffer, contentType, linelength);
|
||||||
|
71
lib/krb4.c
71
lib/krb4.c
@@ -57,6 +57,10 @@
|
|||||||
#include "ftp.h"
|
#include "ftp.h"
|
||||||
#include "sendf.h"
|
#include "sendf.h"
|
||||||
|
|
||||||
|
#if defined(HAVE_INET_NTOA_R) && !defined(HAVE_INET_NTOA_R_DECL)
|
||||||
|
#include "inet_ntoa_r.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
/* The last #include file should be: */
|
/* The last #include file should be: */
|
||||||
#ifdef MALLOCDEBUG
|
#ifdef MALLOCDEBUG
|
||||||
#include "memdebug.h"
|
#include "memdebug.h"
|
||||||
@@ -193,10 +197,10 @@ krb4_auth(void *app_data, struct connectdata *conn)
|
|||||||
int checksum;
|
int checksum;
|
||||||
u_int32_t cs;
|
u_int32_t cs;
|
||||||
struct krb4_data *d = app_data;
|
struct krb4_data *d = app_data;
|
||||||
struct sockaddr_in *localaddr = (struct sockaddr_in *)LOCAL_ADDR;
|
|
||||||
char *host = conn->hostaddr->h_name;
|
char *host = conn->hostaddr->h_name;
|
||||||
ssize_t nread;
|
ssize_t nread;
|
||||||
int l = sizeof(conn->local_addr);
|
int l = sizeof(conn->local_addr);
|
||||||
|
struct SessionHandle *data = conn->data;
|
||||||
|
|
||||||
if(getsockname(conn->firstsocket,
|
if(getsockname(conn->firstsocket,
|
||||||
(struct sockaddr *)LOCAL_ADDR, &l) < 0)
|
(struct sockaddr *)LOCAL_ADDR, &l) < 0)
|
||||||
@@ -207,80 +211,76 @@ krb4_auth(void *app_data, struct connectdata *conn)
|
|||||||
if(ret == KDC_PR_UNKNOWN)
|
if(ret == KDC_PR_UNKNOWN)
|
||||||
ret = mk_auth(d, &adat, "rcmd", host, checksum);
|
ret = mk_auth(d, &adat, "rcmd", host, checksum);
|
||||||
if(ret) {
|
if(ret) {
|
||||||
printf("%s\n", krb_get_err_text(ret));
|
Curl_infof(data, "%s\n", krb_get_err_text(ret));
|
||||||
return AUTH_CONTINUE;
|
return AUTH_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_KRB_GET_OUR_IP_FOR_REALM
|
#ifdef HAVE_KRB_GET_OUR_IP_FOR_REALM
|
||||||
if (krb_get_config_bool("nat_in_use")) {
|
if (krb_get_config_bool("nat_in_use")) {
|
||||||
|
struct sockaddr_in *localaddr = (struct sockaddr_in *)LOCAL_ADDR;
|
||||||
struct in_addr natAddr;
|
struct in_addr natAddr;
|
||||||
|
|
||||||
if (krb_get_our_ip_for_realm(krb_realmofhost(host),
|
if (krb_get_our_ip_for_realm(krb_realmofhost(host),
|
||||||
&natAddr) != KSUCCESS
|
&natAddr) != KSUCCESS
|
||||||
&& krb_get_our_ip_for_realm(NULL, &natAddr) != KSUCCESS)
|
&& krb_get_our_ip_for_realm(NULL, &natAddr) != KSUCCESS)
|
||||||
printf("Can't get address for realm %s\n",
|
Curl_infof(data, "Can't get address for realm %s\n",
|
||||||
krb_realmofhost(host));
|
krb_realmofhost(host));
|
||||||
else {
|
else {
|
||||||
if (natAddr.s_addr != localaddr->sin_addr.s_addr) {
|
if (natAddr.s_addr != localaddr->sin_addr.s_addr) {
|
||||||
printf("Using NAT IP address (%s) for kerberos 4\n",
|
#ifdef HAVE_INET_NTOA_R
|
||||||
(char *)inet_ntoa(natAddr));
|
char ntoa_buf[64];
|
||||||
|
char *ip = (char *)inet_ntoa_r(natAddr, ntoa_buf, sizeof(ntoa_buf));
|
||||||
|
#else
|
||||||
|
char *ip = (char *)inet_ntoa(natAddr);
|
||||||
|
#endif
|
||||||
|
Curl_infof(data, "Using NAT IP address (%s) for kerberos 4\n", ip);
|
||||||
localaddr->sin_addr = natAddr;
|
localaddr->sin_addr = natAddr;
|
||||||
|
|
||||||
/*
|
|
||||||
* This not the best place to do this, but it is here we know that
|
|
||||||
* (probably) NAT is in use! */
|
|
||||||
|
|
||||||
/*passivemode = 1;***/
|
|
||||||
/*printf("Setting: Passive mode on.\n");***/
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*printf("Local address is %s\n", inet_ntoa(localaddr->sin_addr));***/
|
|
||||||
/*printf("Remote address is %s\n", inet_ntoa(remoteaddr->sin_addr));***/
|
|
||||||
|
|
||||||
if(Curl_base64_encode(adat.dat, adat.length, &p) < 0) {
|
if(Curl_base64_encode(adat.dat, adat.length, &p) < 0) {
|
||||||
printf("Out of memory base64-encoding.\n");
|
Curl_failf(data, "Out of memory base64-encoding");
|
||||||
return AUTH_CONTINUE;
|
return AUTH_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(Curl_ftpsendf(conn, "ADAT %s", p))
|
if(Curl_ftpsendf(conn, "ADAT %s", p))
|
||||||
return -2;
|
return -2;
|
||||||
|
|
||||||
nread = Curl_GetFTPResponse(conn->data->state.buffer, conn, NULL);
|
nread = Curl_GetFTPResponse(data->state.buffer, conn, NULL);
|
||||||
if(nread < 0)
|
if(nread < 0)
|
||||||
return -1;
|
return -1;
|
||||||
free(p);
|
free(p);
|
||||||
|
|
||||||
if(/*ret != COMPLETE*/conn->data->state.buffer[0] != '2'){
|
if(data->state.buffer[0] != '2'){
|
||||||
printf("Server didn't accept auth data.\n");
|
Curl_failf(data, "Server didn't accept auth data");
|
||||||
return AUTH_ERROR;
|
return AUTH_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
p = strstr(conn->data->state.buffer, "ADAT=");
|
p = strstr(data->state.buffer, "ADAT=");
|
||||||
if(!p){
|
if(!p) {
|
||||||
printf("Remote host didn't send adat reply.\n");
|
Curl_failf(data, "Remote host didn't send adat reply");
|
||||||
return AUTH_ERROR;
|
return AUTH_ERROR;
|
||||||
}
|
}
|
||||||
p += 5;
|
p += 5;
|
||||||
len = Curl_base64_decode(p, adat.dat);
|
len = Curl_base64_decode(p, adat.dat);
|
||||||
if(len < 0){
|
if(len < 0) {
|
||||||
printf("Failed to decode base64 from server.\n");
|
Curl_failf(data, "Failed to decode base64 from server");
|
||||||
return AUTH_ERROR;
|
return AUTH_ERROR;
|
||||||
}
|
}
|
||||||
adat.length = len;
|
adat.length = len;
|
||||||
ret = krb_rd_safe(adat.dat, adat.length, &d->key,
|
ret = krb_rd_safe(adat.dat, adat.length, &d->key,
|
||||||
(struct sockaddr_in *)hisctladdr,
|
(struct sockaddr_in *)hisctladdr,
|
||||||
(struct sockaddr_in *)myctladdr, &msg_data);
|
(struct sockaddr_in *)myctladdr, &msg_data);
|
||||||
if(ret){
|
if(ret) {
|
||||||
printf("Error reading reply from server: %s.\n",
|
Curl_failf(data, "Error reading reply from server: %s",
|
||||||
krb_get_err_text(ret));
|
krb_get_err_text(ret));
|
||||||
return AUTH_ERROR;
|
return AUTH_ERROR;
|
||||||
}
|
}
|
||||||
krb_get_int(msg_data.app_data, &cs, 4, 0);
|
krb_get_int(msg_data.app_data, &cs, 4, 0);
|
||||||
if(cs - checksum != 1){
|
if(cs - checksum != 1) {
|
||||||
printf("Bad checksum returned from server.\n");
|
Curl_failf(data, "Bad checksum returned from server");
|
||||||
return AUTH_ERROR;
|
return AUTH_ERROR;
|
||||||
}
|
}
|
||||||
return AUTH_OK;
|
return AUTH_OK;
|
||||||
@@ -321,15 +321,14 @@ void Curl_krb_kauth(struct connectdata *conn)
|
|||||||
if(nread < 0)
|
if(nread < 0)
|
||||||
return /*CURLE_OPERATION_TIMEOUTED*/;
|
return /*CURLE_OPERATION_TIMEOUTED*/;
|
||||||
|
|
||||||
if(/*ret != CONTINUE*/conn->data->state.buffer[0] != '3'){
|
if(conn->data->state.buffer[0] != '3'){
|
||||||
Curl_set_command_prot(conn, save);
|
Curl_set_command_prot(conn, save);
|
||||||
/*code = -1;***/
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
p = strstr(conn->data->state.buffer, "T=");
|
p = strstr(conn->data->state.buffer, "T=");
|
||||||
if(!p) {
|
if(!p) {
|
||||||
printf("Bad reply from server.\n");
|
Curl_failf(conn->data, "Bad reply from server");
|
||||||
Curl_set_command_prot(conn, save);
|
Curl_set_command_prot(conn, save);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -337,7 +336,7 @@ void Curl_krb_kauth(struct connectdata *conn)
|
|||||||
p += 2;
|
p += 2;
|
||||||
tmp = Curl_base64_decode(p, &tkt.dat);
|
tmp = Curl_base64_decode(p, &tkt.dat);
|
||||||
if(tmp < 0) {
|
if(tmp < 0) {
|
||||||
printf("Failed to decode base64 in reply.\n");
|
Curl_failf(conn->data, "Failed to decode base64 in reply.\n");
|
||||||
Curl_set_command_prot(conn, save);
|
Curl_set_command_prot(conn, save);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -346,7 +345,7 @@ void Curl_krb_kauth(struct connectdata *conn)
|
|||||||
|
|
||||||
p = strstr(conn->data->state.buffer, "P=");
|
p = strstr(conn->data->state.buffer, "P=");
|
||||||
if(!p) {
|
if(!p) {
|
||||||
printf("Bad reply from server.\n");
|
Curl_failf(conn->data, "Bad reply from server");
|
||||||
Curl_set_command_prot(conn, save);
|
Curl_set_command_prot(conn, save);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -374,7 +373,7 @@ void Curl_krb_kauth(struct connectdata *conn)
|
|||||||
memset(schedule, 0, sizeof(schedule));
|
memset(schedule, 0, sizeof(schedule));
|
||||||
memset(passwd, 0, sizeof(passwd));
|
memset(passwd, 0, sizeof(passwd));
|
||||||
if(Curl_base64_encode(tktcopy.dat, tktcopy.length, &p) < 0) {
|
if(Curl_base64_encode(tktcopy.dat, tktcopy.length, &p) < 0) {
|
||||||
failf(conn->data, "Out of memory base64-encoding.\n");
|
failf(conn->data, "Out of memory base64-encoding.");
|
||||||
Curl_set_command_prot(conn, save);
|
Curl_set_command_prot(conn, save);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
168
lib/llist.c
Normal file
168
lib/llist.c
Normal file
@@ -0,0 +1,168 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* _ _ ____ _
|
||||||
|
* Project ___| | | | _ \| |
|
||||||
|
* / __| | | | |_) | |
|
||||||
|
* | (__| |_| | _ <| |___
|
||||||
|
* \___|\___/|_| \_\_____|
|
||||||
|
*
|
||||||
|
* Copyright (C) 2001, 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.
|
||||||
|
*
|
||||||
|
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||||
|
* copies of the Software, and permit persons to whom the Software is
|
||||||
|
* furnished to do so, under the terms of the MPL or the MIT/X-derivate
|
||||||
|
* licenses. You may pick one of these licenses.
|
||||||
|
*
|
||||||
|
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||||
|
* KIND, either express or implied.
|
||||||
|
*
|
||||||
|
* $Id$
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#include "setup.h"
|
||||||
|
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "llist.h"
|
||||||
|
|
||||||
|
#ifdef MALLOCDEBUG
|
||||||
|
/* this must be the last include file */
|
||||||
|
#include "memdebug.h"
|
||||||
|
#endif
|
||||||
|
void
|
||||||
|
curl_llist_init(curl_llist *l, curl_llist_dtor dtor)
|
||||||
|
{
|
||||||
|
l->size = 0;
|
||||||
|
l->dtor = dtor;
|
||||||
|
l->head = NULL;
|
||||||
|
l->tail = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
curl_llist *
|
||||||
|
curl_llist_alloc(curl_llist_dtor dtor)
|
||||||
|
{
|
||||||
|
curl_llist *list;
|
||||||
|
|
||||||
|
list = (curl_llist *)malloc(sizeof(curl_llist));
|
||||||
|
if(NULL == list)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
curl_llist_init(list, dtor);
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
curl_llist_insert_next(curl_llist *list, curl_llist_element *e, const void *p)
|
||||||
|
{
|
||||||
|
curl_llist_element *ne;
|
||||||
|
|
||||||
|
ne = (curl_llist_element *) malloc(sizeof(curl_llist_element));
|
||||||
|
ne->ptr = (void *) p;
|
||||||
|
if (list->size == 0) {
|
||||||
|
list->head = ne;
|
||||||
|
list->head->prev = NULL;
|
||||||
|
list->head->next = NULL;
|
||||||
|
list->tail = ne;
|
||||||
|
} else {
|
||||||
|
ne->next = e->next;
|
||||||
|
ne->prev = e;
|
||||||
|
if (e->next) {
|
||||||
|
e->next->prev = ne;
|
||||||
|
} else {
|
||||||
|
list->tail = ne;
|
||||||
|
}
|
||||||
|
e->next = ne;
|
||||||
|
}
|
||||||
|
|
||||||
|
++list->size;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
curl_llist_insert_prev(curl_llist *list, curl_llist_element *e, const void *p)
|
||||||
|
{
|
||||||
|
curl_llist_element *ne;
|
||||||
|
|
||||||
|
ne = (curl_llist_element *) malloc(sizeof(curl_llist_element));
|
||||||
|
ne->ptr = (void *) p;
|
||||||
|
if (list->size == 0) {
|
||||||
|
list->head = ne;
|
||||||
|
list->head->prev = NULL;
|
||||||
|
list->head->next = NULL;
|
||||||
|
list->tail = ne;
|
||||||
|
} else {
|
||||||
|
ne->next = e;
|
||||||
|
ne->prev = e->prev;
|
||||||
|
if (e->prev)
|
||||||
|
e->prev->next = ne;
|
||||||
|
else
|
||||||
|
list->head = ne;
|
||||||
|
e->prev = ne;
|
||||||
|
}
|
||||||
|
|
||||||
|
++list->size;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
curl_llist_remove(curl_llist *list, curl_llist_element *e, void *user)
|
||||||
|
{
|
||||||
|
if (e == NULL || list->size == 0)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (e == list->head) {
|
||||||
|
list->head = e->next;
|
||||||
|
|
||||||
|
if (list->head == NULL)
|
||||||
|
list->tail = NULL;
|
||||||
|
else
|
||||||
|
e->next->prev = NULL;
|
||||||
|
} else {
|
||||||
|
e->prev->next = e->next;
|
||||||
|
if (!e->next)
|
||||||
|
list->tail = e->prev;
|
||||||
|
else
|
||||||
|
e->next->prev = e->prev;
|
||||||
|
}
|
||||||
|
|
||||||
|
list->dtor(user, e->ptr);
|
||||||
|
free(e);
|
||||||
|
--list->size;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
curl_llist_remove_next(curl_llist *list, curl_llist_element *e, void *user)
|
||||||
|
{
|
||||||
|
return curl_llist_remove(list, e->next, user);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
curl_llist_remove_prev(curl_llist *list, curl_llist_element *e, void *user)
|
||||||
|
{
|
||||||
|
return curl_llist_remove(list, e->prev, user);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
curl_llist_count(curl_llist *list)
|
||||||
|
{
|
||||||
|
return list->size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
curl_llist_destroy(curl_llist *list, void *user)
|
||||||
|
{
|
||||||
|
while (list->size > 0) {
|
||||||
|
curl_llist_remove(list, CURL_LLIST_TAIL(list), user);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(list);
|
||||||
|
list = NULL;
|
||||||
|
}
|
64
lib/llist.h
Normal file
64
lib/llist.h
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
#ifndef __LLIST_H
|
||||||
|
#define __LLIST_H
|
||||||
|
/*****************************************************************************
|
||||||
|
* _ _ ____ _
|
||||||
|
* Project ___| | | | _ \| |
|
||||||
|
* / __| | | | |_) | |
|
||||||
|
* | (__| |_| | _ <| |___
|
||||||
|
* \___|\___/|_| \_\_____|
|
||||||
|
*
|
||||||
|
* Copyright (C) 2001, 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.
|
||||||
|
*
|
||||||
|
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||||
|
* copies of the Software, and permit persons to whom the Software is
|
||||||
|
* furnished to do so, under the terms of the MPL or the MIT/X-derivate
|
||||||
|
* licenses. You may pick one of these licenses.
|
||||||
|
*
|
||||||
|
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||||
|
* KIND, either express or implied.
|
||||||
|
*
|
||||||
|
* $Id$
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#include "setup.h"
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
typedef void (*curl_llist_dtor)(void *, void *);
|
||||||
|
|
||||||
|
typedef struct _curl_llist_element {
|
||||||
|
void *ptr;
|
||||||
|
|
||||||
|
struct _curl_llist_element *prev;
|
||||||
|
struct _curl_llist_element *next;
|
||||||
|
} curl_llist_element;
|
||||||
|
|
||||||
|
typedef struct _curl_llist {
|
||||||
|
curl_llist_element *head;
|
||||||
|
curl_llist_element *tail;
|
||||||
|
|
||||||
|
curl_llist_dtor dtor;
|
||||||
|
|
||||||
|
size_t size;
|
||||||
|
} curl_llist;
|
||||||
|
|
||||||
|
void curl_llist_init(curl_llist *, curl_llist_dtor);
|
||||||
|
curl_llist *curl_llist_alloc(curl_llist_dtor);
|
||||||
|
int curl_llist_insert_next(curl_llist *, curl_llist_element *, const void *);
|
||||||
|
int curl_llist_insert_prev(curl_llist *, curl_llist_element *, const void *);
|
||||||
|
int curl_llist_remove(curl_llist *, curl_llist_element *, void *);
|
||||||
|
int curl_llist_remove_next(curl_llist *, curl_llist_element *, void *);
|
||||||
|
size_t curl_llist_count(curl_llist *);
|
||||||
|
void curl_llist_destroy(curl_llist *, void *);
|
||||||
|
|
||||||
|
#define CURL_LLIST_HEAD(__l) ((__l)->head)
|
||||||
|
#define CURL_LLIST_TAIL(__l) ((__l)->tail)
|
||||||
|
#define CURL_LLIST_NEXT(__e) ((__e)->next)
|
||||||
|
#define CURL_LLIST_PREV(__e) ((__e)->prev)
|
||||||
|
#define CURL_LLIST_VALP(__e) ((__e)->ptr)
|
||||||
|
#define CURL_LLIST_IS_TAIL(__e) ((__e)->next ? 0 : 1)
|
||||||
|
#define CURL_LLIST_IS_HEAD(__e) ((__e)->prev ? 0 : 1)
|
||||||
|
|
||||||
|
#endif
|
@@ -1,6 +1,14 @@
|
|||||||
#ifdef MALLOCDEBUG
|
#ifdef MALLOCDEBUG
|
||||||
|
|
||||||
|
#include "setup.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_SYS_TYPES_H
|
||||||
|
#include <sys/types.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_SYS_SOCKET_H
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
#endif
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#ifdef HAVE_MEMORY_H
|
#ifdef HAVE_MEMORY_H
|
||||||
#include <memory.h>
|
#include <memory.h>
|
||||||
|
@@ -24,73 +24,11 @@
|
|||||||
* - Max 128 parameters
|
* - Max 128 parameters
|
||||||
* - No 'long double' support.
|
* - No 'long double' support.
|
||||||
*
|
*
|
||||||
*************************************************************************
|
* 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/
|
||||||
* 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
|
|
||||||
*
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
#include "setup.h"
|
#include "setup.h"
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
@@ -100,6 +38,15 @@
|
|||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <string.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: */
|
/* The last #include file should be: */
|
||||||
#ifdef MALLOCDEBUG
|
#ifdef MALLOCDEBUG
|
||||||
#include "memdebug.h"
|
#include "memdebug.h"
|
||||||
@@ -1191,7 +1138,7 @@ int main()
|
|||||||
{
|
{
|
||||||
char buffer[129];
|
char buffer[129];
|
||||||
char *ptr;
|
char *ptr;
|
||||||
#ifdef SIZEOF_LONG_LONG
|
#if SIZEOF_LONG_LONG>0
|
||||||
long long hullo;
|
long long hullo;
|
||||||
dprintf("%3$12s %1$s %2$qd %4$d\n", "daniel", hullo, "stenberg", 65);
|
dprintf("%3$12s %1$s %2$qd %4$d\n", "daniel", hullo, "stenberg", 65);
|
||||||
#endif
|
#endif
|
||||||
|
110
lib/multi.c
110
lib/multi.c
@@ -22,10 +22,16 @@
|
|||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
#include "setup.h"
|
#include "setup.h"
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
#include <curl/curl.h>
|
#include <curl/curl.h>
|
||||||
|
|
||||||
#include "multi.h" /* will become <curl/multi.h> soon */
|
#include "multi.h" /* will become <curl/multi.h> soon */
|
||||||
|
|
||||||
|
#include "urldata.h"
|
||||||
|
#include "transfer.h"
|
||||||
|
#include "url.h"
|
||||||
|
|
||||||
struct Curl_message {
|
struct Curl_message {
|
||||||
/* the 'CURLMsg' is the part that is visible to the external user */
|
/* the 'CURLMsg' is the part that is visible to the external user */
|
||||||
struct CURLMsg extmsg;
|
struct CURLMsg extmsg;
|
||||||
@@ -48,7 +54,9 @@ struct Curl_one_easy {
|
|||||||
struct Curl_one_easy *next;
|
struct Curl_one_easy *next;
|
||||||
struct Curl_one_easy *prev;
|
struct Curl_one_easy *prev;
|
||||||
|
|
||||||
CURL *easy_handle; /* this is the easy handle for this unit */
|
struct SessionHandle *easy_handle; /* the easy handle for this unit */
|
||||||
|
struct connectdata *easy_conn; /* the "unit's" connection */
|
||||||
|
|
||||||
CURLMstate state; /* the handle's state */
|
CURLMstate state; /* the handle's state */
|
||||||
CURLcode result; /* previous result */
|
CURLcode result; /* previous result */
|
||||||
};
|
};
|
||||||
@@ -74,7 +82,8 @@ struct Curl_multi {
|
|||||||
struct Curl_message *msgs;
|
struct Curl_message *msgs;
|
||||||
/* amount of messages in the queue */
|
/* amount of messages in the queue */
|
||||||
int num_msgs;
|
int num_msgs;
|
||||||
|
/* Hostname cache */
|
||||||
|
curl_hash *hostcache;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -134,7 +143,7 @@ CURLMcode curl_multi_add_handle(CURLM *multi_handle,
|
|||||||
/* increase the node-counter */
|
/* increase the node-counter */
|
||||||
multi->num_easy++;
|
multi->num_easy++;
|
||||||
|
|
||||||
return CURLM_OK;
|
return CURLM_CALL_MULTI_PERFORM;
|
||||||
}
|
}
|
||||||
|
|
||||||
CURLMcode curl_multi_remove_handle(CURLM *multi_handle,
|
CURLMcode curl_multi_remove_handle(CURLM *multi_handle,
|
||||||
@@ -190,23 +199,30 @@ CURLMcode curl_multi_fdset(CURLM *multi_handle,
|
|||||||
and then we must make sure that is done. */
|
and then we must make sure that is done. */
|
||||||
struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
|
struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
|
||||||
struct Curl_one_easy *easy;
|
struct Curl_one_easy *easy;
|
||||||
|
int this_max_fd=-1;
|
||||||
|
|
||||||
if(!GOOD_MULTI_HANDLE(multi))
|
if(!GOOD_MULTI_HANDLE(multi))
|
||||||
return CURLM_BAD_HANDLE;
|
return CURLM_BAD_HANDLE;
|
||||||
|
|
||||||
|
*max_fd = -1; /* so far none! */
|
||||||
|
|
||||||
easy=multi->easy.next;
|
easy=multi->easy.next;
|
||||||
while(easy) {
|
while(easy) {
|
||||||
switch(easy->state) {
|
switch(easy->state) {
|
||||||
case CURLM_STATE_INIT:
|
default:
|
||||||
case CURLM_STATE_CONNECT:
|
|
||||||
case CURLM_STATE_DO:
|
|
||||||
case CURLM_STATE_DONE:
|
|
||||||
/* we want curl_multi_perform() to get called, but we don't have any
|
|
||||||
file descriptors to set */
|
|
||||||
break;
|
break;
|
||||||
case CURLM_STATE_PERFORM:
|
case CURLM_STATE_PERFORM:
|
||||||
/* This should have a set of file descriptors for us to set. */
|
/* This should have a set of file descriptors for us to set. */
|
||||||
/* after the transfer is done, go DONE */
|
/* after the transfer is done, go DONE */
|
||||||
|
|
||||||
|
Curl_single_fdset(easy->easy_conn,
|
||||||
|
read_fd_set, write_fd_set,
|
||||||
|
exc_fd_set, &this_max_fd);
|
||||||
|
|
||||||
|
/* remember the maximum file descriptor */
|
||||||
|
if(this_max_fd > *max_fd)
|
||||||
|
*max_fd = this_max_fd;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
easy = easy->next; /* check next handle */
|
easy = easy->next; /* check next handle */
|
||||||
@@ -220,50 +236,73 @@ CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
|
|||||||
struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
|
struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
|
||||||
struct Curl_one_easy *easy;
|
struct Curl_one_easy *easy;
|
||||||
bool done;
|
bool done;
|
||||||
|
CURLMcode result=CURLM_OK;
|
||||||
|
|
||||||
|
*running_handles = 0; /* bump this once for every living handle */
|
||||||
|
|
||||||
if(!GOOD_MULTI_HANDLE(multi))
|
if(!GOOD_MULTI_HANDLE(multi))
|
||||||
return CURLM_BAD_HANDLE;
|
return CURLM_BAD_HANDLE;
|
||||||
|
|
||||||
easy=multi->easy.next;
|
easy=multi->easy.next;
|
||||||
while(easy) {
|
while(easy) {
|
||||||
|
|
||||||
switch(easy->state) {
|
switch(easy->state) {
|
||||||
case CURLM_STATE_INIT:
|
case CURLM_STATE_INIT:
|
||||||
/* init this transfer. Hm, uh, I can't think of anything to init
|
/* init this transfer. */
|
||||||
right now, let's skip over to CONNECT at once!
|
easy->result=Curl_pretransfer(easy->easy_handle);
|
||||||
|
if(CURLE_OK == easy->result) {
|
||||||
easy->result = Curl_init(easy->easy_handle);
|
/* after init, go CONNECT */
|
||||||
if(CURLE_OK == easy->result)
|
easy->state = CURLM_STATE_CONNECT;
|
||||||
*/
|
result = CURLM_CALL_MULTI_PERFORM;
|
||||||
/* after init, go CONNECT */
|
}
|
||||||
easy->state = CURLM_STATE_CONNECT;
|
|
||||||
break;
|
break;
|
||||||
case CURLM_STATE_CONNECT:
|
case CURLM_STATE_CONNECT:
|
||||||
/* connect */
|
if (Curl_global_host_cache_use(easy->easy_handle)) {
|
||||||
easy->result = Curl_connect(easy->easy_handle);
|
easy->easy_handle->hostcache = Curl_global_host_cache_get();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (multi->hostcache == NULL) {
|
||||||
|
multi->hostcache = curl_hash_alloc(7, Curl_freeaddrinfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
easy->easy_handle->hostcache = multi->hostcache;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Connect. We get a connection identifier filled in. */
|
||||||
|
easy->result = Curl_connect(easy->easy_handle, &easy->easy_conn);
|
||||||
|
|
||||||
/* after connect, go DO */
|
/* after connect, go DO */
|
||||||
if(CURLE_OK == easy->result)
|
if(CURLE_OK == easy->result) {
|
||||||
easy->state = CURLM_STATE_DO;
|
easy->state = CURLM_STATE_DO;
|
||||||
|
result = CURLM_CALL_MULTI_PERFORM;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case CURLM_STATE_DO:
|
case CURLM_STATE_DO:
|
||||||
/* Do the fetch or put request */
|
/* Do the fetch or put request */
|
||||||
easy->result = Curl_do(easy->easy_handle);
|
easy->result = Curl_do(&easy->easy_conn);
|
||||||
/* after do, go PERFORM */
|
/* after do, go PERFORM */
|
||||||
if(CURLE_OK == easy->result)
|
if(CURLE_OK == easy->result) {
|
||||||
easy->state = CURLM_STATE_PERFORM;
|
if(CURLE_OK == Curl_readwrite_init(easy->easy_conn)) {
|
||||||
|
easy->state = CURLM_STATE_PERFORM;
|
||||||
|
result = CURLM_CALL_MULTI_PERFORM;
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case CURLM_STATE_PERFORM:
|
case CURLM_STATE_PERFORM:
|
||||||
/* read/write data if it is ready to do so */
|
/* read/write data if it is ready to do so */
|
||||||
easy->result = Curl_readwrite(easy->easy_handle, &done);
|
easy->result = Curl_readwrite(easy->easy_conn, &done);
|
||||||
/* hm, when we follow redirects, we may need to go back to the CONNECT
|
/* hm, when we follow redirects, we may need to go back to the CONNECT
|
||||||
state */
|
state */
|
||||||
/* after the transfer is done, go DONE */
|
/* after the transfer is done, go DONE */
|
||||||
if(TRUE == done)
|
if(TRUE == done) {
|
||||||
|
/* call this even if the readwrite function returned error */
|
||||||
|
easy->result = Curl_posttransfer(easy->easy_handle);
|
||||||
easy->state = CURLM_STATE_DONE;
|
easy->state = CURLM_STATE_DONE;
|
||||||
|
result = CURLM_CALL_MULTI_PERFORM;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case CURLM_STATE_DONE:
|
case CURLM_STATE_DONE:
|
||||||
/* post-transfer command */
|
/* post-transfer command */
|
||||||
easy->result = Curl_done(easy->easy_handle);
|
easy->result = Curl_done(easy->easy_conn);
|
||||||
/* after we have DONE what we're supposed to do, go COMPLETED */
|
/* after we have DONE what we're supposed to do, go COMPLETED */
|
||||||
if(CURLE_OK == easy->result)
|
if(CURLE_OK == easy->result)
|
||||||
easy->state = CURLM_STATE_COMPLETED;
|
easy->state = CURLM_STATE_COMPLETED;
|
||||||
@@ -274,7 +313,10 @@ CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
|
|||||||
/* This node should be delinked from the list now and we should post
|
/* This node should be delinked from the list now and we should post
|
||||||
an information message that we are complete. */
|
an information message that we are complete. */
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
return CURLM_INTERNAL_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if((CURLM_STATE_COMPLETED != easy->state) &&
|
if((CURLM_STATE_COMPLETED != easy->state) &&
|
||||||
(CURLE_OK != easy->result)) {
|
(CURLE_OK != easy->result)) {
|
||||||
/*
|
/*
|
||||||
@@ -283,10 +325,13 @@ CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
|
|||||||
*/
|
*/
|
||||||
easy->state = CURLM_STATE_COMPLETED;
|
easy->state = CURLM_STATE_COMPLETED;
|
||||||
}
|
}
|
||||||
|
else if(CURLM_STATE_COMPLETED != easy->state)
|
||||||
|
/* this one still lives! */
|
||||||
|
(*running_handles)++;
|
||||||
|
|
||||||
easy = easy->next; /* operate on next handle */
|
easy = easy->next; /* operate on next handle */
|
||||||
}
|
}
|
||||||
return CURLM_OK;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
CURLMcode curl_multi_cleanup(CURLM *multi_handle)
|
CURLMcode curl_multi_cleanup(CURLM *multi_handle)
|
||||||
@@ -294,7 +339,7 @@ CURLMcode curl_multi_cleanup(CURLM *multi_handle)
|
|||||||
struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
|
struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
|
||||||
if(GOOD_MULTI_HANDLE(multi)) {
|
if(GOOD_MULTI_HANDLE(multi)) {
|
||||||
multi->type = 0; /* not good anymore */
|
multi->type = 0; /* not good anymore */
|
||||||
|
curl_hash_destroy(multi->hostcache);
|
||||||
/* remove all easy handles */
|
/* remove all easy handles */
|
||||||
|
|
||||||
free(multi);
|
free(multi);
|
||||||
@@ -307,3 +352,10 @@ CURLMcode curl_multi_cleanup(CURLM *multi_handle)
|
|||||||
|
|
||||||
CURLMsg *curl_multi_info_read(CURLM *multi_handle, int *msgs_in_queue);
|
CURLMsg *curl_multi_info_read(CURLM *multi_handle, int *msgs_in_queue);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* local variables:
|
||||||
|
* eval: (load-file "../curl-mode.el")
|
||||||
|
* end:
|
||||||
|
* vim600: fdm=marker
|
||||||
|
* vim: et sw=2 ts=2 sts=2 tw=78
|
||||||
|
*/
|
||||||
|
@@ -50,15 +50,17 @@
|
|||||||
#ifdef HAVE_SYS_SOCKET_H
|
#ifdef HAVE_SYS_SOCKET_H
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#endif
|
#endif
|
||||||
#include <curl/types.h>
|
#include <curl/curl.h>
|
||||||
|
|
||||||
typedef void CURLM;
|
typedef void CURLM;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
CURLM_CALL_MULTI_PERFORM=-1, /* please call curl_multi_perform() soon */
|
||||||
CURLM_OK,
|
CURLM_OK,
|
||||||
CURLM_BAD_HANDLE, /* the passed-in handle is not a valid CURLM handle */
|
CURLM_BAD_HANDLE, /* the passed-in handle is not a valid CURLM handle */
|
||||||
CURLM_BAD_EASY_HANDLE, /* an easy handle was not good/valid */
|
CURLM_BAD_EASY_HANDLE, /* an easy handle was not good/valid */
|
||||||
CURLM_OUT_OF_MEMORY, /* if you ever get this, you're in deep sh*t */
|
CURLM_OUT_OF_MEMORY, /* if you ever get this, you're in deep sh*t */
|
||||||
|
CURLM_INTERNAL_ERROR, /* this is a libcurl bug */
|
||||||
CURLM_LAST
|
CURLM_LAST
|
||||||
} CURLMcode;
|
} CURLMcode;
|
||||||
|
|
||||||
|
@@ -157,7 +157,7 @@ int Curl_parsenetrc(char *host,
|
|||||||
}
|
}
|
||||||
else if(state_password) {
|
else if(state_password) {
|
||||||
strncpy(password, tok, PASSWORDSIZE-1);
|
strncpy(password, tok, PASSWORDSIZE-1);
|
||||||
#if _NETRC_DEBUG
|
#ifdef _NETRC_DEBUG
|
||||||
printf("PASSWORD: %s\n", password);
|
printf("PASSWORD: %s\n", password);
|
||||||
#endif
|
#endif
|
||||||
state_password=0;
|
state_password=0;
|
||||||
|
@@ -362,11 +362,11 @@ Curl_sec_vfprintf(struct connectdata *conn, FILE *f, const char *fmt, va_list ap
|
|||||||
conn);
|
conn);
|
||||||
free(buf);
|
free(buf);
|
||||||
if(len < 0) {
|
if(len < 0) {
|
||||||
failf(conn->data, "Failed to encode command.\n");
|
failf(conn->data, "Failed to encode command.");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if(Curl_base64_encode(enc, len, &buf) < 0){
|
if(Curl_base64_encode(enc, len, &buf) < 0){
|
||||||
failf(conn->data, "Out of memory base64-encoding.\n");
|
failf(conn->data, "Out of memory base64-encoding.");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if(conn->command_prot == prot_safe)
|
if(conn->command_prot == prot_safe)
|
||||||
@@ -421,7 +421,7 @@ sec_prot_internal(struct connectdata *conn, int level)
|
|||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if(conn->data->state.buffer[0] != '2'){
|
if(conn->data->state.buffer[0] != '2'){
|
||||||
failf(conn->data, "Failed to set protection buffer size.\n");
|
failf(conn->data, "Failed to set protection buffer size.");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
conn->buffer_size = s;
|
conn->buffer_size = s;
|
||||||
@@ -441,7 +441,7 @@ sec_prot_internal(struct connectdata *conn, int level)
|
|||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if(conn->data->state.buffer[0] != '2'){
|
if(conn->data->state.buffer[0] != '2'){
|
||||||
failf(conn->data, "Failed to set protection level.\n");
|
failf(conn->data, "Failed to set protection level.");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
109
lib/sendf.c
109
lib/sendf.c
@@ -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
|
* In order to be useful for every potential user, curl and libcurl are
|
||||||
* dual-licensed under the MPL and the MIT/X-derivate licenses.
|
* dual-licensed under the MPL and the MIT/X-derivate licenses.
|
||||||
@@ -26,6 +26,11 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_SYS_TYPES_H
|
||||||
|
#include <sys/types.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_SYS_SOCKET_H
|
#ifdef HAVE_SYS_SOCKET_H
|
||||||
#include <sys/socket.h> /* required for send() & recv() prototypes */
|
#include <sys/socket.h> /* required for send() & recv() prototypes */
|
||||||
@@ -137,8 +142,9 @@ void Curl_infof(struct SessionHandle *data, const char *fmt, ...)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Curl_failf() is for messages stating why we failed, the LAST one will be
|
/* Curl_failf() is for messages stating why we failed.
|
||||||
returned for the user (if requested) */
|
* The message SHALL NOT include any LF or CR.
|
||||||
|
*/
|
||||||
|
|
||||||
void Curl_failf(struct SessionHandle *data, const char *fmt, ...)
|
void Curl_failf(struct SessionHandle *data, const char *fmt, ...)
|
||||||
{
|
{
|
||||||
@@ -156,7 +162,7 @@ CURLcode Curl_sendf(int sockfd, struct connectdata *conn,
|
|||||||
const char *fmt, ...)
|
const char *fmt, ...)
|
||||||
{
|
{
|
||||||
struct SessionHandle *data = conn->data;
|
struct SessionHandle *data = conn->data;
|
||||||
size_t bytes_written;
|
ssize_t bytes_written;
|
||||||
CURLcode result;
|
CURLcode result;
|
||||||
char *s;
|
char *s;
|
||||||
va_list ap;
|
va_list ap;
|
||||||
@@ -183,26 +189,32 @@ CURLcode Curl_sendf(int sockfd, struct connectdata *conn,
|
|||||||
*/
|
*/
|
||||||
CURLcode Curl_write(struct connectdata *conn, int sockfd,
|
CURLcode Curl_write(struct connectdata *conn, int sockfd,
|
||||||
void *mem, size_t len,
|
void *mem, size_t len,
|
||||||
size_t *written)
|
ssize_t *written)
|
||||||
{
|
{
|
||||||
size_t bytes_written;
|
ssize_t bytes_written;
|
||||||
|
|
||||||
#ifdef USE_SSLEAY
|
#ifdef USE_SSLEAY
|
||||||
/* SSL_write() is said to return 'int' while write() and send() returns
|
/* SSL_write() is said to return 'int' while write() and send() returns
|
||||||
'size_t' */
|
'size_t' */
|
||||||
int ssl_bytes;
|
|
||||||
if (conn->ssl.use) {
|
if (conn->ssl.use) {
|
||||||
int loop=100; /* just a precaution to never loop endlessly */
|
int err;
|
||||||
while(loop--) {
|
int rc = SSL_write(conn->ssl.handle, mem, len);
|
||||||
ssl_bytes = SSL_write(conn->ssl.handle, mem, len);
|
|
||||||
if((0 >= ssl_bytes) ||
|
if(rc < 0) {
|
||||||
(SSL_ERROR_WANT_WRITE != SSL_get_error(conn->ssl.handle,
|
err = SSL_get_error(conn->ssl.handle, rc);
|
||||||
ssl_bytes) )) {
|
|
||||||
/* this converts from signed to unsigned... */
|
switch(err) {
|
||||||
bytes_written = ssl_bytes;
|
case SSL_ERROR_WANT_READ:
|
||||||
break;
|
case SSL_ERROR_WANT_WRITE:
|
||||||
|
/* this is basicly the EWOULDBLOCK equivalent */
|
||||||
|
*written = 0;
|
||||||
|
return CURLE_OK;
|
||||||
}
|
}
|
||||||
|
/* a true error */
|
||||||
|
failf(conn->data, "SSL_write() return error %d\n", err);
|
||||||
|
return CURLE_WRITE_ERROR;
|
||||||
}
|
}
|
||||||
|
bytes_written = rc;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
#endif
|
#endif
|
||||||
@@ -212,13 +224,27 @@ CURLcode Curl_write(struct connectdata *conn, int sockfd,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif /* KRB4 */
|
#endif /* KRB4 */
|
||||||
|
{
|
||||||
bytes_written = swrite(sockfd, mem, len);
|
bytes_written = swrite(sockfd, mem, len);
|
||||||
|
}
|
||||||
|
if(-1 == bytes_written) {
|
||||||
|
#ifdef WIN32
|
||||||
|
if(WSAEWOULDBLOCK == GetLastError())
|
||||||
|
#else
|
||||||
|
if(EWOULDBLOCK == errno)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
/* this is just a case of EWOULDBLOCK */
|
||||||
|
*written=0;
|
||||||
|
return CURLE_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
#ifdef USE_SSLEAY
|
#ifdef USE_SSLEAY
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
*written = bytes_written;
|
*written = bytes_written;
|
||||||
return (bytes_written==len)?CURLE_OK:CURLE_WRITE_ERROR;
|
return (-1 != bytes_written)?CURLE_OK:CURLE_WRITE_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* client_write() sends data to the write callback(s)
|
/* client_write() sends data to the write callback(s)
|
||||||
@@ -262,26 +288,47 @@ CURLcode Curl_client_write(struct SessionHandle *data,
|
|||||||
return CURLE_OK;
|
return CURLE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Internal read-from-socket function. This is meant to deal with plain
|
* Internal read-from-socket function. This is meant to deal with plain
|
||||||
* sockets, SSL sockets and kerberos sockets.
|
* sockets, SSL sockets and kerberos sockets.
|
||||||
|
*
|
||||||
|
* If the read would block (EWOULDBLOCK) we return -1. Otherwise we return
|
||||||
|
* a regular CURLcode value.
|
||||||
*/
|
*/
|
||||||
CURLcode Curl_read(struct connectdata *conn, int sockfd,
|
int Curl_read(struct connectdata *conn,
|
||||||
char *buf, size_t buffersize,
|
int sockfd,
|
||||||
ssize_t *n)
|
char *buf,
|
||||||
|
size_t buffersize,
|
||||||
|
ssize_t *n)
|
||||||
{
|
{
|
||||||
ssize_t nread;
|
ssize_t nread;
|
||||||
|
|
||||||
#ifdef USE_SSLEAY
|
#ifdef USE_SSLEAY
|
||||||
if (conn->ssl.use) {
|
if (conn->ssl.use) {
|
||||||
int loop=100; /* just a precaution to never loop endlessly */
|
bool loop=TRUE;
|
||||||
while(loop--) {
|
int err;
|
||||||
|
do {
|
||||||
nread = SSL_read(conn->ssl.handle, buf, buffersize);
|
nread = SSL_read(conn->ssl.handle, buf, buffersize);
|
||||||
if((-1 != nread) ||
|
|
||||||
(SSL_ERROR_WANT_READ != SSL_get_error(conn->ssl.handle, nread) ))
|
if(nread > 0)
|
||||||
|
/* successful read */
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
err = SSL_get_error(conn->ssl.handle, nread);
|
||||||
|
|
||||||
|
switch(err) {
|
||||||
|
case SSL_ERROR_NONE: /* this is not an error */
|
||||||
|
case SSL_ERROR_ZERO_RETURN: /* no more data */
|
||||||
|
loop=0; /* get out of loop */
|
||||||
|
break;
|
||||||
|
case SSL_ERROR_WANT_READ:
|
||||||
|
case SSL_ERROR_WANT_WRITE:
|
||||||
|
/* if there's data pending, then we re-invoke SSL_read() */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} while(0);
|
||||||
|
if(loop && SSL_pending(conn->ssl.handle))
|
||||||
|
return -1; /* basicly EWOULDBLOCK */
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
#endif
|
#endif
|
||||||
@@ -291,6 +338,16 @@ CURLcode Curl_read(struct connectdata *conn, int sockfd,
|
|||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
nread = sread (sockfd, buf, buffersize);
|
nread = sread (sockfd, buf, buffersize);
|
||||||
|
|
||||||
|
if(-1 == nread) {
|
||||||
|
#ifdef WIN32
|
||||||
|
if(WSAEWOULDBLOCK == GetLastError())
|
||||||
|
#else
|
||||||
|
if(EWOULDBLOCK == errno)
|
||||||
|
#endif
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef USE_SSLEAY
|
#ifdef USE_SSLEAY
|
||||||
}
|
}
|
||||||
#endif /* USE_SSLEAY */
|
#endif /* USE_SSLEAY */
|
||||||
|
@@ -45,12 +45,12 @@ CURLcode Curl_client_write(struct SessionHandle *data, int type, char *ptr,
|
|||||||
size_t len);
|
size_t len);
|
||||||
|
|
||||||
/* internal read-function, does plain socket, SSL and krb4 */
|
/* internal read-function, does plain socket, SSL and krb4 */
|
||||||
CURLcode Curl_read(struct connectdata *conn, int sockfd,
|
int Curl_read(struct connectdata *conn, int sockfd,
|
||||||
char *buf, size_t buffersize,
|
char *buf, size_t buffersize,
|
||||||
ssize_t *n);
|
ssize_t *n);
|
||||||
/* internal write-function, does plain socket, SSL and krb4 */
|
/* internal write-function, does plain socket, SSL and krb4 */
|
||||||
CURLcode Curl_write(struct connectdata *conn, int sockfd,
|
CURLcode Curl_write(struct connectdata *conn, int sockfd,
|
||||||
void *mem, size_t len,
|
void *mem, size_t len,
|
||||||
size_t *written);
|
ssize_t *written);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -34,9 +34,9 @@
|
|||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
|
|
||||||
#ifdef VMS
|
#ifdef VMS
|
||||||
#include "config-vms.h"
|
#include "../config-vms.h"
|
||||||
#else
|
#else
|
||||||
#include "config.h" /* the configure script results */
|
#include "../config.h" /* the configure script results */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#else
|
#else
|
||||||
@@ -46,13 +46,14 @@
|
|||||||
#endif
|
#endif
|
||||||
#ifdef macintosh
|
#ifdef macintosh
|
||||||
/* hand-modified MacOS config.h! */
|
/* hand-modified MacOS config.h! */
|
||||||
#include "config-mac.h"
|
#include "../config-mac.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef __cplusplus /* (rabe) */
|
#ifndef __cplusplus /* (rabe) */
|
||||||
typedef char bool;
|
typedef unsigned char bool;
|
||||||
|
#define typedef_bool
|
||||||
#endif /* (rabe) */
|
#endif /* (rabe) */
|
||||||
|
|
||||||
#ifdef NEED_REENTRANT
|
#ifdef NEED_REENTRANT
|
||||||
|
249
lib/ssluse.c
249
lib/ssluse.c
@@ -5,7 +5,7 @@
|
|||||||
* | (__| |_| | _ <| |___
|
* | (__| |_| | _ <| |___
|
||||||
* \___|\___/|_| \_\_____|
|
* \___|\___/|_| \_\_____|
|
||||||
*
|
*
|
||||||
* Copyright (C) 2000, Daniel Stenberg, <daniel@haxx.se>, et al.
|
* Copyright (C) 2001, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||||
*
|
*
|
||||||
* In order to be useful for every potential user, curl and libcurl are
|
* In order to be useful for every potential user, curl and libcurl are
|
||||||
* dual-licensed under the MPL and the MIT/X-derivate licenses.
|
* dual-licensed under the MPL and the MIT/X-derivate licenses.
|
||||||
@@ -22,11 +22,12 @@
|
|||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The original SSL code was written by
|
* The original SSL code for curl was written by
|
||||||
* Linas Vepstas <linas@linas.org> and Sampo Kellomaki <sampo@iki.fi>
|
* Linas Vepstas <linas@linas.org> and Sampo Kellomaki <sampo@iki.fi>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "setup.h"
|
#include "setup.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
@@ -42,6 +43,12 @@
|
|||||||
#include "memdebug.h"
|
#include "memdebug.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if OPENSSL_VERSION_NUMBER >= 0x0090581fL
|
||||||
|
#define HAVE_SSL_GET1_SESSION 1
|
||||||
|
#else
|
||||||
|
#undef HAVE_SSL_GET1_SESSION
|
||||||
|
#endif
|
||||||
|
|
||||||
#if OPENSSL_VERSION_NUMBER >= 0x00904100L
|
#if OPENSSL_VERSION_NUMBER >= 0x00904100L
|
||||||
#define HAVE_USERDATA_IN_PWD_CALLBACK 1
|
#define HAVE_USERDATA_IN_PWD_CALLBACK 1
|
||||||
#else
|
#else
|
||||||
@@ -171,37 +178,59 @@ int random_the_seed(struct connectdata *conn)
|
|||||||
return nread;
|
return nread;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef SSL_FILETYPE_ENGINE
|
||||||
|
#define SSL_FILETYPE_ENGINE 42
|
||||||
|
#endif
|
||||||
|
static int do_file_type(const char *type)
|
||||||
|
{
|
||||||
|
if (!type || !type[0])
|
||||||
|
return SSL_FILETYPE_PEM;
|
||||||
|
if (curl_strequal(type, "PEM"))
|
||||||
|
return SSL_FILETYPE_PEM;
|
||||||
|
if (curl_strequal(type, "DER"))
|
||||||
|
return SSL_FILETYPE_ASN1;
|
||||||
|
if (curl_strequal(type, "ENG"))
|
||||||
|
return SSL_FILETYPE_ENGINE;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
int cert_stuff(struct connectdata *conn,
|
int cert_stuff(struct connectdata *conn,
|
||||||
char *cert_file,
|
char *cert_file,
|
||||||
char *key_file)
|
const char *cert_type,
|
||||||
|
char *key_file,
|
||||||
|
const char *key_type)
|
||||||
{
|
{
|
||||||
struct SessionHandle *data = conn->data;
|
struct SessionHandle *data = conn->data;
|
||||||
|
int file_type;
|
||||||
|
|
||||||
if (cert_file != NULL) {
|
if (cert_file != NULL) {
|
||||||
SSL *ssl;
|
SSL *ssl;
|
||||||
X509 *x509;
|
X509 *x509;
|
||||||
|
|
||||||
if(data->set.cert_passwd) {
|
if(data->set.key_passwd) {
|
||||||
#ifndef HAVE_USERDATA_IN_PWD_CALLBACK
|
#ifndef HAVE_USERDATA_IN_PWD_CALLBACK
|
||||||
/*
|
/*
|
||||||
* If password has been given, we store that in the global
|
* If password has been given, we store that in the global
|
||||||
* area (*shudder*) for a while:
|
* area (*shudder*) for a while:
|
||||||
*/
|
*/
|
||||||
strcpy(global_passwd, data->set.cert_passwd);
|
strcpy(global_passwd, data->set.key_passwd);
|
||||||
#else
|
#else
|
||||||
/*
|
/*
|
||||||
* We set the password in the callback userdata
|
* We set the password in the callback userdata
|
||||||
*/
|
*/
|
||||||
SSL_CTX_set_default_passwd_cb_userdata(conn->ssl.ctx, data->set.cert_passwd);
|
SSL_CTX_set_default_passwd_cb_userdata(conn->ssl.ctx,
|
||||||
|
data->set.key_passwd);
|
||||||
#endif
|
#endif
|
||||||
/* Set passwd callback: */
|
/* Set passwd callback: */
|
||||||
SSL_CTX_set_default_passwd_cb(conn->ssl.ctx, passwd_callback);
|
SSL_CTX_set_default_passwd_cb(conn->ssl.ctx, passwd_callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
if (SSL_CTX_use_certificate_file(conn->ssl.ctx,
|
if (SSL_CTX_use_certificate_file(conn->ssl.ctx,
|
||||||
cert_file,
|
cert_file,
|
||||||
SSL_FILETYPE_PEM) != 1) {
|
SSL_FILETYPE_PEM) != 1) {
|
||||||
failf(data, "unable to set certificate file (wrong password?)\n");
|
failf(data, "unable to set certificate file (wrong password?)");
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
if (key_file == NULL)
|
if (key_file == NULL)
|
||||||
@@ -210,9 +239,86 @@ int cert_stuff(struct connectdata *conn,
|
|||||||
if (SSL_CTX_use_PrivateKey_file(conn->ssl.ctx,
|
if (SSL_CTX_use_PrivateKey_file(conn->ssl.ctx,
|
||||||
key_file,
|
key_file,
|
||||||
SSL_FILETYPE_PEM) != 1) {
|
SSL_FILETYPE_PEM) != 1) {
|
||||||
failf(data, "unable to set public key file\n");
|
failf(data, "unable to set public key file");
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
/* The '#ifdef 0' section above was removed on 17-dec-2001 */
|
||||||
|
|
||||||
|
file_type = do_file_type(cert_type);
|
||||||
|
|
||||||
|
switch(file_type) {
|
||||||
|
case SSL_FILETYPE_PEM:
|
||||||
|
case SSL_FILETYPE_ASN1:
|
||||||
|
if (SSL_CTX_use_certificate_file(conn->ssl.ctx,
|
||||||
|
cert_file,
|
||||||
|
file_type) != 1) {
|
||||||
|
failf(data, "unable to set certificate file (wrong password?)");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SSL_FILETYPE_ENGINE:
|
||||||
|
failf(data, "file type ENG for certificate not implemented");
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
default:
|
||||||
|
failf(data, "not supported file type '%s' for certificate", cert_type);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
file_type = do_file_type(key_type);
|
||||||
|
|
||||||
|
switch(file_type) {
|
||||||
|
case SSL_FILETYPE_PEM:
|
||||||
|
if (key_file == NULL)
|
||||||
|
/* cert & key can only be in PEM case in the same file */
|
||||||
|
key_file=cert_file;
|
||||||
|
case SSL_FILETYPE_ASN1:
|
||||||
|
if (SSL_CTX_use_PrivateKey_file(conn->ssl.ctx,
|
||||||
|
key_file,
|
||||||
|
file_type) != 1) {
|
||||||
|
failf(data, "unable to set private key file\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SSL_FILETYPE_ENGINE:
|
||||||
|
#ifdef HAVE_OPENSSL_ENGINE_H
|
||||||
|
{ /* XXXX still needs some work */
|
||||||
|
EVP_PKEY *priv_key = NULL;
|
||||||
|
if (conn && conn->data && conn->data->engine) {
|
||||||
|
if (!key_file || !key_file[0]) {
|
||||||
|
failf(data, "no key set to load from crypto engine\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
priv_key = ENGINE_load_private_key(conn->data->engine,key_file,
|
||||||
|
data->set.key_passwd);
|
||||||
|
if (!priv_key) {
|
||||||
|
failf(data, "failed to load private key from crypto engine\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (SSL_CTX_use_PrivateKey(conn->ssl.ctx, priv_key) != 1) {
|
||||||
|
failf(data, "unable to set private key\n");
|
||||||
|
EVP_PKEY_free(priv_key);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EVP_PKEY_free(priv_key); /* we don't need the handle any more... */
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
failf(data, "crypto engine not set, can't load private key\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
failf(data, "file type ENG for private key not supported\n");
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
failf(data, "not supported file type for private key\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
ssl=SSL_new(conn->ssl.ctx);
|
ssl=SSL_new(conn->ssl.ctx);
|
||||||
x509=SSL_get_certificate(ssl);
|
x509=SSL_get_certificate(ssl);
|
||||||
@@ -229,7 +335,7 @@ int cert_stuff(struct connectdata *conn,
|
|||||||
/* Now we know that a key and cert have been set against
|
/* Now we know that a key and cert have been set against
|
||||||
* the SSL context */
|
* the SSL context */
|
||||||
if (!SSL_CTX_check_private_key(conn->ssl.ctx)) {
|
if (!SSL_CTX_check_private_key(conn->ssl.ctx)) {
|
||||||
failf(data, "Private key does not match the certificate public key\n");
|
failf(data, "Private key does not match the certificate public key");
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
#ifndef HAVE_USERDATA_IN_PWD_CALLBACK
|
#ifndef HAVE_USERDATA_IN_PWD_CALLBACK
|
||||||
@@ -269,6 +375,10 @@ void Curl_SSL_init(void)
|
|||||||
|
|
||||||
init_ssl++; /* never again */
|
init_ssl++; /* never again */
|
||||||
|
|
||||||
|
#ifdef HAVE_ENGINE_LOAD_BUILTIN_ENGINES
|
||||||
|
ENGINE_load_builtin_engines();
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Lets get nice error messages */
|
/* Lets get nice error messages */
|
||||||
SSL_load_error_strings();
|
SSL_load_error_strings();
|
||||||
|
|
||||||
@@ -293,6 +403,10 @@ void Curl_SSL_cleanup(void)
|
|||||||
table. */
|
table. */
|
||||||
EVP_cleanup();
|
EVP_cleanup();
|
||||||
|
|
||||||
|
#ifdef HAVE_ENGINE_cleanup
|
||||||
|
ENGINE_cleanup();
|
||||||
|
#endif
|
||||||
|
|
||||||
init_ssl=0; /* not inited any more */
|
init_ssl=0; /* not inited any more */
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
@@ -428,6 +542,13 @@ int Curl_SSL_Close_All(struct SessionHandle *data)
|
|||||||
/* free the cache data */
|
/* free the cache data */
|
||||||
free(data->state.session);
|
free(data->state.session);
|
||||||
}
|
}
|
||||||
|
#ifdef HAVE_OPENSSL_ENGINE_H
|
||||||
|
if (data->engine)
|
||||||
|
{
|
||||||
|
ENGINE_free(data->engine);
|
||||||
|
data->engine = NULL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -437,23 +558,39 @@ int Curl_SSL_Close_All(struct SessionHandle *data)
|
|||||||
static int Store_SSL_Session(struct connectdata *conn)
|
static int Store_SSL_Session(struct connectdata *conn)
|
||||||
{
|
{
|
||||||
SSL_SESSION *ssl_sessionid;
|
SSL_SESSION *ssl_sessionid;
|
||||||
struct curl_ssl_session *store;
|
|
||||||
int i;
|
int i;
|
||||||
struct SessionHandle *data=conn->data; /* the mother of all structs */
|
struct SessionHandle *data=conn->data; /* the mother of all structs */
|
||||||
|
struct curl_ssl_session *store = &data->state.session[0];
|
||||||
int oldest_age=data->state.session[0].age; /* zero if unused */
|
int oldest_age=data->state.session[0].age; /* zero if unused */
|
||||||
|
|
||||||
/* ask OpenSSL, say please */
|
/* ask OpenSSL, say please */
|
||||||
|
|
||||||
|
#ifdef HAVE_SSL_GET1_SESSION
|
||||||
ssl_sessionid = SSL_get1_session(conn->ssl.handle);
|
ssl_sessionid = SSL_get1_session(conn->ssl.handle);
|
||||||
|
|
||||||
/* SSL_get1_session() will increment the reference
|
/* SSL_get1_session() will increment the reference
|
||||||
count and the session will stay in memory until explicitly freed with
|
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
|
/* Now we should add the session ID and the host name to the cache, (remove
|
||||||
the oldest if necessary) */
|
the oldest if necessary) */
|
||||||
|
|
||||||
/* find an empty slot for us, or find the oldest */
|
/* find an empty slot for us, or find the oldest */
|
||||||
for(i=0; (i<data->set.ssl.numsessions) && data->state.session[i].sessionid; i++) {
|
for(i=1; (i<data->set.ssl.numsessions) &&
|
||||||
|
data->state.session[i].sessionid; i++) {
|
||||||
if(data->state.session[i].age < oldest_age) {
|
if(data->state.session[i].age < oldest_age) {
|
||||||
oldest_age = data->state.session[i].age;
|
oldest_age = data->state.session[i].age;
|
||||||
store = &data->state.session[i];
|
store = &data->state.session[i];
|
||||||
@@ -569,7 +706,11 @@ Curl_SSLConnect(struct connectdata *conn)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(data->set.cert) {
|
if(data->set.cert) {
|
||||||
if (!cert_stuff(conn, data->set.cert, data->set.cert)) {
|
if (!cert_stuff(conn,
|
||||||
|
data->set.cert,
|
||||||
|
data->set.cert_type,
|
||||||
|
data->set.key,
|
||||||
|
data->set.key_type)) {
|
||||||
/* failf() is already done in cert_stuff() */
|
/* failf() is already done in cert_stuff() */
|
||||||
return CURLE_SSL_CONNECT_ERROR;
|
return CURLE_SSL_CONNECT_ERROR;
|
||||||
}
|
}
|
||||||
@@ -578,7 +719,7 @@ Curl_SSLConnect(struct connectdata *conn)
|
|||||||
if(data->set.ssl.cipher_list) {
|
if(data->set.ssl.cipher_list) {
|
||||||
if (!SSL_CTX_set_cipher_list(conn->ssl.ctx,
|
if (!SSL_CTX_set_cipher_list(conn->ssl.ctx,
|
||||||
data->set.ssl.cipher_list)) {
|
data->set.ssl.cipher_list)) {
|
||||||
failf(data, "failed setting cipher list\n");
|
failf(data, "failed setting cipher list");
|
||||||
return CURLE_SSL_CONNECT_ERROR;
|
return CURLE_SSL_CONNECT_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -591,7 +732,7 @@ Curl_SSLConnect(struct connectdata *conn)
|
|||||||
if (!SSL_CTX_load_verify_locations(conn->ssl.ctx,
|
if (!SSL_CTX_load_verify_locations(conn->ssl.ctx,
|
||||||
data->set.ssl.CAfile,
|
data->set.ssl.CAfile,
|
||||||
data->set.ssl.CApath)) {
|
data->set.ssl.CApath)) {
|
||||||
failf(data,"error setting cerficate verify locations\n");
|
failf(data,"error setting cerficate verify locations");
|
||||||
return CURLE_SSL_CONNECT_ERROR;
|
return CURLE_SSL_CONNECT_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -617,8 +758,80 @@ Curl_SSLConnect(struct connectdata *conn)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* pass the raw socket into the SSL layers */
|
/* pass the raw socket into the SSL layers */
|
||||||
SSL_set_fd (conn->ssl.handle, conn->firstsocket);
|
SSL_set_fd(conn->ssl.handle, conn->firstsocket);
|
||||||
err = SSL_connect (conn->ssl.handle);
|
|
||||||
|
do {
|
||||||
|
int what;
|
||||||
|
fd_set writefd;
|
||||||
|
fd_set readfd;
|
||||||
|
struct timeval interval;
|
||||||
|
long timeout_ms;
|
||||||
|
|
||||||
|
err = SSL_connect(conn->ssl.handle);
|
||||||
|
|
||||||
|
what = SSL_get_error(conn->ssl.handle, err);
|
||||||
|
|
||||||
|
FD_ZERO(&writefd);
|
||||||
|
FD_ZERO(&readfd);
|
||||||
|
|
||||||
|
if(SSL_ERROR_WANT_READ == what)
|
||||||
|
FD_SET(conn->firstsocket, &readfd);
|
||||||
|
else if(SSL_ERROR_WANT_WRITE == what)
|
||||||
|
FD_SET(conn->firstsocket, &writefd);
|
||||||
|
else
|
||||||
|
break; /* untreated error */
|
||||||
|
|
||||||
|
/* Find out if any timeout is set. If not, use 300 seconds.
|
||||||
|
Otherwise, figure out the most strict timeout of the two possible one
|
||||||
|
and then how much time that has elapsed to know how much time we
|
||||||
|
allow for the connect call */
|
||||||
|
if(data->set.timeout || data->set.connecttimeout) {
|
||||||
|
double has_passed;
|
||||||
|
|
||||||
|
/* Evaluate in milliseconds how much time that has passed */
|
||||||
|
has_passed = Curl_tvdiff(Curl_tvnow(), data->progress.start);
|
||||||
|
|
||||||
|
#ifndef min
|
||||||
|
#define min(a, b) ((a) < (b) ? (a) : (b))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* get the most strict timeout of the ones converted to milliseconds */
|
||||||
|
if(data->set.timeout &&
|
||||||
|
(data->set.timeout>data->set.connecttimeout))
|
||||||
|
timeout_ms = data->set.timeout*1000;
|
||||||
|
else
|
||||||
|
timeout_ms = data->set.connecttimeout*1000;
|
||||||
|
|
||||||
|
/* subtract the passed time */
|
||||||
|
timeout_ms -= (long)has_passed;
|
||||||
|
|
||||||
|
if(timeout_ms < 0) {
|
||||||
|
/* a precaution, no need to continue if time already is up */
|
||||||
|
failf(data, "SSL connection timeout");
|
||||||
|
return CURLE_OPERATION_TIMEOUTED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
/* no particular time-out has been set */
|
||||||
|
timeout_ms=300000; /* milliseconds, default to five minutes */
|
||||||
|
|
||||||
|
interval.tv_sec = timeout_ms/1000;
|
||||||
|
timeout_ms -= interval.tv_sec*1000;
|
||||||
|
|
||||||
|
interval.tv_usec = timeout_ms*1000;
|
||||||
|
|
||||||
|
what = select(conn->firstsocket+1, &readfd, &writefd, NULL, &interval);
|
||||||
|
if(what > 0)
|
||||||
|
/* reabable or writable, go loop yourself */
|
||||||
|
continue;
|
||||||
|
else if(0 == what) {
|
||||||
|
/* timeout */
|
||||||
|
failf(data, "SSL connection timeout");
|
||||||
|
return CURLE_OPERATION_TIMEOUTED;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
break; /* get out of loop */
|
||||||
|
} while(1);
|
||||||
|
|
||||||
/* 1 is fine
|
/* 1 is fine
|
||||||
0 is "not successful but was shut down controlled"
|
0 is "not successful but was shut down controlled"
|
||||||
@@ -713,7 +926,7 @@ Curl_SSLConnect(struct connectdata *conn)
|
|||||||
if(data->set.ssl.verifypeer) {
|
if(data->set.ssl.verifypeer) {
|
||||||
data->set.ssl.certverifyresult=SSL_get_verify_result(conn->ssl.handle);
|
data->set.ssl.certverifyresult=SSL_get_verify_result(conn->ssl.handle);
|
||||||
if (data->set.ssl.certverifyresult != X509_V_OK) {
|
if (data->set.ssl.certverifyresult != X509_V_OK) {
|
||||||
failf(data, "SSL certificate verify result: %d\n",
|
failf(data, "SSL certificate verify result: %d",
|
||||||
data->set.ssl.certverifyresult);
|
data->set.ssl.certverifyresult);
|
||||||
retcode = CURLE_SSL_PEER_CERTIFICATE;
|
retcode = CURLE_SSL_PEER_CERTIFICATE;
|
||||||
}
|
}
|
||||||
|
64
lib/telnet.c
64
lib/telnet.c
@@ -226,9 +226,9 @@ static void printoption(struct SessionHandle *data,
|
|||||||
if (cmd == IAC)
|
if (cmd == IAC)
|
||||||
{
|
{
|
||||||
if (TELCMD_OK(option))
|
if (TELCMD_OK(option))
|
||||||
printf("%s IAC %s\n", direction, TELCMD(option));
|
Curl_infof(data, "%s IAC %s\n", direction, TELCMD(option));
|
||||||
else
|
else
|
||||||
printf("%s IAC %d\n", direction, option);
|
Curl_infof(data, "%s IAC %d\n", direction, option);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -244,12 +244,12 @@ static void printoption(struct SessionHandle *data,
|
|||||||
opt = NULL;
|
opt = NULL;
|
||||||
|
|
||||||
if(opt)
|
if(opt)
|
||||||
printf("%s %s %s\n", direction, fmt, opt);
|
Curl_infof(data, "%s %s %s\n", direction, fmt, opt);
|
||||||
else
|
else
|
||||||
printf("%s %s %d\n", direction, fmt, option);
|
Curl_infof(data, "%s %s %d\n", direction, fmt, option);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
printf("%s %d %d\n", direction, cmd, option);
|
Curl_infof(data, "%s %d %d\n", direction, cmd, option);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -638,7 +638,7 @@ static void printsub(struct SessionHandle *data,
|
|||||||
{
|
{
|
||||||
if (direction)
|
if (direction)
|
||||||
{
|
{
|
||||||
printf("%s IAC SB ", (direction == '<')? "RCVD":"SENT");
|
Curl_infof(data, "%s IAC SB ", (direction == '<')? "RCVD":"SENT");
|
||||||
if (length >= 3)
|
if (length >= 3)
|
||||||
{
|
{
|
||||||
int j;
|
int j;
|
||||||
@@ -648,27 +648,27 @@ static void printsub(struct SessionHandle *data,
|
|||||||
|
|
||||||
if (i != IAC || j != SE)
|
if (i != IAC || j != SE)
|
||||||
{
|
{
|
||||||
printf("(terminated by ");
|
Curl_infof(data, "(terminated by ");
|
||||||
if (TELOPT_OK(i))
|
if (TELOPT_OK(i))
|
||||||
printf("%s ", TELOPT(i));
|
Curl_infof(data, "%s ", TELOPT(i));
|
||||||
else if (TELCMD_OK(i))
|
else if (TELCMD_OK(i))
|
||||||
printf("%s ", TELCMD(i));
|
Curl_infof(data, "%s ", TELCMD(i));
|
||||||
else
|
else
|
||||||
printf("%d ", i);
|
Curl_infof(data, "%d ", i);
|
||||||
if (TELOPT_OK(j))
|
if (TELOPT_OK(j))
|
||||||
printf("%s", TELOPT(j));
|
Curl_infof(data, "%s", TELOPT(j));
|
||||||
else if (TELCMD_OK(j))
|
else if (TELCMD_OK(j))
|
||||||
printf("%s", TELCMD(j));
|
Curl_infof(data, "%s", TELCMD(j));
|
||||||
else
|
else
|
||||||
printf("%d", j);
|
Curl_infof(data, "%d", j);
|
||||||
printf(", not IAC SE!) ");
|
Curl_infof(data, ", not IAC SE!) ");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
length -= 2;
|
length -= 2;
|
||||||
}
|
}
|
||||||
if (length < 1)
|
if (length < 1)
|
||||||
{
|
{
|
||||||
printf("(Empty suboption?)");
|
Curl_infof(data, "(Empty suboption?)");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -677,28 +677,28 @@ static void printsub(struct SessionHandle *data,
|
|||||||
case TELOPT_TTYPE:
|
case TELOPT_TTYPE:
|
||||||
case TELOPT_XDISPLOC:
|
case TELOPT_XDISPLOC:
|
||||||
case TELOPT_NEW_ENVIRON:
|
case TELOPT_NEW_ENVIRON:
|
||||||
printf("%s", TELOPT(pointer[0]));
|
Curl_infof(data, "%s", TELOPT(pointer[0]));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printf("%s (unsupported)", TELOPT(pointer[0]));
|
Curl_infof(data, "%s (unsupported)", TELOPT(pointer[0]));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
printf("%d (unknown)", pointer[i]);
|
Curl_infof(data, "%d (unknown)", pointer[i]);
|
||||||
|
|
||||||
switch(pointer[1]) {
|
switch(pointer[1]) {
|
||||||
case TELQUAL_IS:
|
case TELQUAL_IS:
|
||||||
printf(" IS");
|
Curl_infof(data, " IS");
|
||||||
break;
|
break;
|
||||||
case TELQUAL_SEND:
|
case TELQUAL_SEND:
|
||||||
printf(" SEND");
|
Curl_infof(data, " SEND");
|
||||||
break;
|
break;
|
||||||
case TELQUAL_INFO:
|
case TELQUAL_INFO:
|
||||||
printf(" INFO/REPLY");
|
Curl_infof(data, " INFO/REPLY");
|
||||||
break;
|
break;
|
||||||
case TELQUAL_NAME:
|
case TELQUAL_NAME:
|
||||||
printf(" NAME");
|
Curl_infof(data, " NAME");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -706,21 +706,21 @@ static void printsub(struct SessionHandle *data,
|
|||||||
case TELOPT_TTYPE:
|
case TELOPT_TTYPE:
|
||||||
case TELOPT_XDISPLOC:
|
case TELOPT_XDISPLOC:
|
||||||
pointer[length] = 0;
|
pointer[length] = 0;
|
||||||
printf(" \"%s\"", &pointer[2]);
|
Curl_infof(data, " \"%s\"", &pointer[2]);
|
||||||
break;
|
break;
|
||||||
case TELOPT_NEW_ENVIRON:
|
case TELOPT_NEW_ENVIRON:
|
||||||
if(pointer[1] == TELQUAL_IS) {
|
if(pointer[1] == TELQUAL_IS) {
|
||||||
printf(" ");
|
Curl_infof(data, " ");
|
||||||
for(i = 3;i < length;i++) {
|
for(i = 3;i < length;i++) {
|
||||||
switch(pointer[i]) {
|
switch(pointer[i]) {
|
||||||
case NEW_ENV_VAR:
|
case NEW_ENV_VAR:
|
||||||
printf(", ");
|
Curl_infof(data, ", ");
|
||||||
break;
|
break;
|
||||||
case NEW_ENV_VALUE:
|
case NEW_ENV_VALUE:
|
||||||
printf(" = ");
|
Curl_infof(data, " = ");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printf("%c", pointer[i]);
|
Curl_infof(data, "%c", pointer[i]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -728,13 +728,13 @@ static void printsub(struct SessionHandle *data,
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
for (i = 2; i < length; i++)
|
for (i = 2; i < length; i++)
|
||||||
printf(" %.2x", pointer[i]);
|
Curl_infof(data, " %.2x", pointer[i]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (direction)
|
if (direction)
|
||||||
{
|
{
|
||||||
printf("\n");
|
Curl_infof(data, "\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1090,7 +1090,7 @@ CURLcode Curl_telnet(struct connectdata *conn)
|
|||||||
{
|
{
|
||||||
unsigned char outbuf[2];
|
unsigned char outbuf[2];
|
||||||
int out_count = 0;
|
int out_count = 0;
|
||||||
size_t bytes_written;
|
ssize_t bytes_written;
|
||||||
char *buffer = buf;
|
char *buffer = buf;
|
||||||
|
|
||||||
if(!ReadFile(stdin_handle, buf, 255, &nread, NULL)) {
|
if(!ReadFile(stdin_handle, buf, 255, &nread, NULL)) {
|
||||||
@@ -1116,6 +1116,7 @@ CURLcode Curl_telnet(struct connectdata *conn)
|
|||||||
{
|
{
|
||||||
if(events.lNetworkEvents & FD_READ)
|
if(events.lNetworkEvents & FD_READ)
|
||||||
{
|
{
|
||||||
|
/* This reallu OUGHT to check its return code. */
|
||||||
Curl_read(conn, sockfd, buf, BUFSIZE - 1, &nread);
|
Curl_read(conn, sockfd, buf, BUFSIZE - 1, &nread);
|
||||||
|
|
||||||
telrcv(conn, (unsigned char *)buf, nread);
|
telrcv(conn, (unsigned char *)buf, nread);
|
||||||
@@ -1159,7 +1160,7 @@ CURLcode Curl_telnet(struct connectdata *conn)
|
|||||||
if(FD_ISSET(0, &readfd)) { /* read from stdin */
|
if(FD_ISSET(0, &readfd)) { /* read from stdin */
|
||||||
unsigned char outbuf[2];
|
unsigned char outbuf[2];
|
||||||
int out_count = 0;
|
int out_count = 0;
|
||||||
size_t bytes_written;
|
ssize_t bytes_written;
|
||||||
char *buffer = buf;
|
char *buffer = buf;
|
||||||
|
|
||||||
nread = read(0, buf, 255);
|
nread = read(0, buf, 255);
|
||||||
@@ -1176,6 +1177,7 @@ CURLcode Curl_telnet(struct connectdata *conn)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(FD_ISSET(sockfd, &readfd)) {
|
if(FD_ISSET(sockfd, &readfd)) {
|
||||||
|
/* This OUGHT to check the return code... */
|
||||||
Curl_read(conn, sockfd, buf, BUFSIZE - 1, &nread);
|
Curl_read(conn, sockfd, buf, BUFSIZE - 1, &nread);
|
||||||
|
|
||||||
/* if we receive 0 or less here, the server closed the connection and
|
/* if we receive 0 or less here, the server closed the connection and
|
||||||
|
1604
lib/transfer.c
1604
lib/transfer.c
File diff suppressed because it is too large
Load Diff
@@ -7,7 +7,7 @@
|
|||||||
* | (__| |_| | _ <| |___
|
* | (__| |_| | _ <| |___
|
||||||
* \___|\___/|_| \_\_____|
|
* \___|\___/|_| \_\_____|
|
||||||
*
|
*
|
||||||
* Copyright (C) 2000, Daniel Stenberg, <daniel@haxx.se>, et al.
|
* Copyright (C) 2001, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||||
*
|
*
|
||||||
* In order to be useful for every potential user, curl and libcurl are
|
* In order to be useful for every potential user, curl and libcurl are
|
||||||
* dual-licensed under the MPL and the MIT/X-derivate licenses.
|
* dual-licensed under the MPL and the MIT/X-derivate licenses.
|
||||||
@@ -24,6 +24,17 @@
|
|||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
CURLcode Curl_perform(struct SessionHandle *data);
|
CURLcode Curl_perform(struct SessionHandle *data);
|
||||||
|
|
||||||
|
CURLcode Curl_pretransfer(struct SessionHandle *data);
|
||||||
|
CURLcode Curl_posttransfer(struct SessionHandle *data);
|
||||||
|
|
||||||
|
CURLcode Curl_readwrite(struct connectdata *conn, bool *done);
|
||||||
|
void Curl_single_fdset(struct connectdata *conn,
|
||||||
|
fd_set *read_fd_set,
|
||||||
|
fd_set *write_fd_set,
|
||||||
|
fd_set *exc_fd_set,
|
||||||
|
int *max_fd);
|
||||||
|
CURLcode Curl_readwrite_init(struct connectdata *conn);
|
||||||
|
|
||||||
/* This sets up a forthcoming transfer */
|
/* This sets up a forthcoming transfer */
|
||||||
CURLcode
|
CURLcode
|
||||||
Curl_Transfer (struct connectdata *data,
|
Curl_Transfer (struct connectdata *data,
|
||||||
|
168
lib/url.c
168
lib/url.c
@@ -110,6 +110,10 @@
|
|||||||
|
|
||||||
#include <curl/types.h>
|
#include <curl/types.h>
|
||||||
|
|
||||||
|
#if defined(HAVE_INET_NTOA_R) && !defined(HAVE_INET_NTOA_R_DECL)
|
||||||
|
#include "inet_ntoa_r.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#define _MPRINTF_REPLACE /* use our functions only */
|
#define _MPRINTF_REPLACE /* use our functions only */
|
||||||
#include <curl/mprintf.h>
|
#include <curl/mprintf.h>
|
||||||
|
|
||||||
@@ -247,6 +251,8 @@ CURLcode Curl_open(struct SessionHandle **curl)
|
|||||||
data->set.httpreq = HTTPREQ_GET; /* Default HTTP request */
|
data->set.httpreq = HTTPREQ_GET; /* Default HTTP request */
|
||||||
data->set.ftp_use_epsv = TRUE; /* FTP defaults to EPSV operations */
|
data->set.ftp_use_epsv = TRUE; /* FTP defaults to EPSV operations */
|
||||||
|
|
||||||
|
data->set.dns_cache_timeout = 60; /* Timeout every 60 seconds by default */
|
||||||
|
|
||||||
/* make libcurl quiet by default: */
|
/* make libcurl quiet by default: */
|
||||||
data->set.hide_progress = TRUE; /* CURLOPT_NOPROGRESS changes these */
|
data->set.hide_progress = TRUE; /* CURLOPT_NOPROGRESS changes these */
|
||||||
data->progress.flags |= PGRS_HIDE;
|
data->progress.flags |= PGRS_HIDE;
|
||||||
@@ -280,6 +286,19 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, ...)
|
|||||||
va_start(param, option);
|
va_start(param, option);
|
||||||
|
|
||||||
switch(option) {
|
switch(option) {
|
||||||
|
case CURLOPT_DNS_CACHE_TIMEOUT:
|
||||||
|
data->set.dns_cache_timeout = va_arg(param, int);
|
||||||
|
break;
|
||||||
|
case CURLOPT_DNS_USE_GLOBAL_CACHE:
|
||||||
|
{
|
||||||
|
int use_cache = va_arg(param, int);
|
||||||
|
if (use_cache) {
|
||||||
|
Curl_global_host_cache_init();
|
||||||
|
}
|
||||||
|
|
||||||
|
data->set.global_dns_cache = use_cache;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case CURLOPT_SSL_CIPHER_LIST:
|
case CURLOPT_SSL_CIPHER_LIST:
|
||||||
/* set a list of cipher we want to use in the SSL connection */
|
/* set a list of cipher we want to use in the SSL connection */
|
||||||
data->set.ssl.cipher_list = va_arg(param, char *);
|
data->set.ssl.cipher_list = va_arg(param, char *);
|
||||||
@@ -790,11 +809,75 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, ...)
|
|||||||
*/
|
*/
|
||||||
data->set.cert = va_arg(param, char *);
|
data->set.cert = va_arg(param, char *);
|
||||||
break;
|
break;
|
||||||
case CURLOPT_SSLCERTPASSWD:
|
case CURLOPT_SSLCERTTYPE:
|
||||||
/*
|
/*
|
||||||
* String that holds the SSL certificate password.
|
* String that holds file type of the SSL certificate to use
|
||||||
*/
|
*/
|
||||||
data->set.cert_passwd = va_arg(param, char *);
|
data->set.cert_type = va_arg(param, char *);
|
||||||
|
break;
|
||||||
|
case CURLOPT_SSLKEY:
|
||||||
|
/*
|
||||||
|
* String that holds file name of the SSL certificate to use
|
||||||
|
*/
|
||||||
|
data->set.key = va_arg(param, char *);
|
||||||
|
break;
|
||||||
|
case CURLOPT_SSLKEYTYPE:
|
||||||
|
/*
|
||||||
|
* String that holds file type of the SSL certificate to use
|
||||||
|
*/
|
||||||
|
data->set.key_type = va_arg(param, char *);
|
||||||
|
break;
|
||||||
|
case CURLOPT_SSLKEYPASSWD:
|
||||||
|
/*
|
||||||
|
* String that holds the SSL private key password.
|
||||||
|
*/
|
||||||
|
data->set.key_passwd = va_arg(param, char *);
|
||||||
|
break;
|
||||||
|
case CURLOPT_SSLENGINE:
|
||||||
|
/*
|
||||||
|
* String that holds the SSL crypto engine.
|
||||||
|
*/
|
||||||
|
#ifdef HAVE_OPENSSL_ENGINE_H
|
||||||
|
{
|
||||||
|
const char *cpTemp = va_arg(param, char *);
|
||||||
|
ENGINE *e;
|
||||||
|
if (cpTemp && cpTemp[0]) {
|
||||||
|
e = ENGINE_by_id(cpTemp);
|
||||||
|
if (e) {
|
||||||
|
if (data->engine) {
|
||||||
|
ENGINE_free(data->engine);
|
||||||
|
}
|
||||||
|
data->engine = e;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
failf(data, "SSL Engine '%s' not found", cpTemp);
|
||||||
|
return CURLE_SSL_ENGINE_NOTFOUND;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
return CURLE_SSL_ENGINE_NOTFOUND;
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
case CURLOPT_SSLENGINE_DEFAULT:
|
||||||
|
/*
|
||||||
|
* flag to set engine as default.
|
||||||
|
*/
|
||||||
|
#ifdef HAVE_OPENSSL_ENGINE_H
|
||||||
|
if (data->engine) {
|
||||||
|
if (ENGINE_set_default(data->engine, ENGINE_METHOD_ALL) > 0) {
|
||||||
|
#ifdef DEBUG
|
||||||
|
fprintf(stderr,"set default crypto engine\n");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
#ifdef DEBUG
|
||||||
|
failf(data, "set default crypto engine failed");
|
||||||
|
#endif
|
||||||
|
return CURLE_SSL_ENGINE_SETFAILED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
case CURLOPT_CRLF:
|
case CURLOPT_CRLF:
|
||||||
/*
|
/*
|
||||||
@@ -876,9 +959,6 @@ CURLcode Curl_disconnect(struct connectdata *conn)
|
|||||||
if(conn->proto.generic)
|
if(conn->proto.generic)
|
||||||
free(conn->proto.generic);
|
free(conn->proto.generic);
|
||||||
|
|
||||||
if(conn->hostent_buf) /* host name info */
|
|
||||||
Curl_freeaddrinfo(conn->hostent_buf);
|
|
||||||
|
|
||||||
if(conn->newurl)
|
if(conn->newurl)
|
||||||
free(conn->newurl);
|
free(conn->newurl);
|
||||||
|
|
||||||
@@ -1153,8 +1233,7 @@ static CURLcode ConnectPlease(struct connectdata *conn)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static CURLcode CreateConnection(struct SessionHandle *data,
|
static CURLcode CreateConnection(struct SessionHandle *data,
|
||||||
struct connectdata **in_connect,
|
struct connectdata **in_connect)
|
||||||
bool allow_port) /* allow set.use_port? */
|
|
||||||
{
|
{
|
||||||
char *tmp;
|
char *tmp;
|
||||||
char *buf;
|
char *buf;
|
||||||
@@ -1164,6 +1243,9 @@ static CURLcode CreateConnection(struct SessionHandle *data,
|
|||||||
struct connectdata *conn_temp;
|
struct connectdata *conn_temp;
|
||||||
char endbracket;
|
char endbracket;
|
||||||
int urllen;
|
int urllen;
|
||||||
|
#ifdef HAVE_INET_NTOA_R
|
||||||
|
char ntoa_buf[64];
|
||||||
|
#endif
|
||||||
#ifdef HAVE_ALARM
|
#ifdef HAVE_ALARM
|
||||||
unsigned int prev_alarm;
|
unsigned int prev_alarm;
|
||||||
#endif
|
#endif
|
||||||
@@ -1502,6 +1584,7 @@ static CURLcode CreateConnection(struct SessionHandle *data,
|
|||||||
/* we have a proxy here to set */
|
/* we have a proxy here to set */
|
||||||
data->change.proxy = proxy;
|
data->change.proxy = proxy;
|
||||||
data->change.proxy_alloc=TRUE; /* this needs to be freed later */
|
data->change.proxy_alloc=TRUE; /* this needs to be freed later */
|
||||||
|
conn->bits.httpproxy = TRUE;
|
||||||
}
|
}
|
||||||
} /* if (!nope) - it wasn't specified non-proxy */
|
} /* if (!nope) - it wasn't specified non-proxy */
|
||||||
} /* NO_PROXY wasn't specified or '*' */
|
} /* NO_PROXY wasn't specified or '*' */
|
||||||
@@ -1552,7 +1635,8 @@ static CURLcode CreateConnection(struct SessionHandle *data,
|
|||||||
*************************************************************/
|
*************************************************************/
|
||||||
|
|
||||||
if (strequal(conn->protostr, "HTTP")) {
|
if (strequal(conn->protostr, "HTTP")) {
|
||||||
conn->port = (data->set.use_port && allow_port)?data->set.use_port:PORT_HTTP;
|
conn->port = (data->set.use_port && data->state.allow_port)?
|
||||||
|
data->set.use_port:PORT_HTTP;
|
||||||
conn->remote_port = PORT_HTTP;
|
conn->remote_port = PORT_HTTP;
|
||||||
conn->protocol |= PROT_HTTP;
|
conn->protocol |= PROT_HTTP;
|
||||||
conn->curl_do = Curl_http;
|
conn->curl_do = Curl_http;
|
||||||
@@ -1562,7 +1646,8 @@ static CURLcode CreateConnection(struct SessionHandle *data,
|
|||||||
else if (strequal(conn->protostr, "HTTPS")) {
|
else if (strequal(conn->protostr, "HTTPS")) {
|
||||||
#ifdef USE_SSLEAY
|
#ifdef USE_SSLEAY
|
||||||
|
|
||||||
conn->port = (data->set.use_port && allow_port)?data->set.use_port:PORT_HTTPS;
|
conn->port = (data->set.use_port && data->state.allow_port)?
|
||||||
|
data->set.use_port:PORT_HTTPS;
|
||||||
conn->remote_port = PORT_HTTPS;
|
conn->remote_port = PORT_HTTPS;
|
||||||
conn->protocol |= PROT_HTTP|PROT_HTTPS|PROT_SSL;
|
conn->protocol |= PROT_HTTP|PROT_HTTPS|PROT_SSL;
|
||||||
|
|
||||||
@@ -1577,7 +1662,8 @@ static CURLcode CreateConnection(struct SessionHandle *data,
|
|||||||
#endif /* !USE_SSLEAY */
|
#endif /* !USE_SSLEAY */
|
||||||
}
|
}
|
||||||
else if (strequal(conn->protostr, "GOPHER")) {
|
else if (strequal(conn->protostr, "GOPHER")) {
|
||||||
conn->port = (data->set.use_port && allow_port)?data->set.use_port:PORT_GOPHER;
|
conn->port = (data->set.use_port && data->state.allow_port)?
|
||||||
|
data->set.use_port:PORT_GOPHER;
|
||||||
conn->remote_port = PORT_GOPHER;
|
conn->remote_port = PORT_GOPHER;
|
||||||
/* Skip /<item-type>/ in path if present */
|
/* Skip /<item-type>/ in path if present */
|
||||||
if (isdigit((int)conn->path[1])) {
|
if (isdigit((int)conn->path[1])) {
|
||||||
@@ -1603,7 +1689,8 @@ static CURLcode CreateConnection(struct SessionHandle *data,
|
|||||||
#endif /* !USE_SSLEAY */
|
#endif /* !USE_SSLEAY */
|
||||||
}
|
}
|
||||||
|
|
||||||
conn->port = (data->set.use_port && allow_port)?data->set.use_port:PORT_FTP;
|
conn->port = (data->set.use_port && data->state.allow_port)?
|
||||||
|
data->set.use_port:PORT_FTP;
|
||||||
conn->remote_port = PORT_FTP;
|
conn->remote_port = PORT_FTP;
|
||||||
conn->protocol |= PROT_FTP;
|
conn->protocol |= PROT_FTP;
|
||||||
|
|
||||||
@@ -1658,21 +1745,24 @@ static CURLcode CreateConnection(struct SessionHandle *data,
|
|||||||
/* telnet testing factory */
|
/* telnet testing factory */
|
||||||
conn->protocol |= PROT_TELNET;
|
conn->protocol |= PROT_TELNET;
|
||||||
|
|
||||||
conn->port = (data->set.use_port && allow_port)?data->set.use_port: PORT_TELNET;
|
conn->port = (data->set.use_port && data->state.allow_port)?
|
||||||
|
data->set.use_port: PORT_TELNET;
|
||||||
conn->remote_port = PORT_TELNET;
|
conn->remote_port = PORT_TELNET;
|
||||||
conn->curl_do = Curl_telnet;
|
conn->curl_do = Curl_telnet;
|
||||||
conn->curl_done = Curl_telnet_done;
|
conn->curl_done = Curl_telnet_done;
|
||||||
}
|
}
|
||||||
else if (strequal(conn->protostr, "DICT")) {
|
else if (strequal(conn->protostr, "DICT")) {
|
||||||
conn->protocol |= PROT_DICT;
|
conn->protocol |= PROT_DICT;
|
||||||
conn->port = (data->set.use_port && allow_port)?data->set.use_port:PORT_DICT;
|
conn->port = (data->set.use_port && data->state.allow_port)?
|
||||||
|
data->set.use_port:PORT_DICT;
|
||||||
conn->remote_port = PORT_DICT;
|
conn->remote_port = PORT_DICT;
|
||||||
conn->curl_do = Curl_dict;
|
conn->curl_do = Curl_dict;
|
||||||
conn->curl_done = NULL; /* no DICT-specific done */
|
conn->curl_done = NULL; /* no DICT-specific done */
|
||||||
}
|
}
|
||||||
else if (strequal(conn->protostr, "LDAP")) {
|
else if (strequal(conn->protostr, "LDAP")) {
|
||||||
conn->protocol |= PROT_LDAP;
|
conn->protocol |= PROT_LDAP;
|
||||||
conn->port = (data->set.use_port && allow_port)?data->set.use_port:PORT_LDAP;
|
conn->port = (data->set.use_port && data->state.allow_port)?
|
||||||
|
data->set.use_port:PORT_LDAP;
|
||||||
conn->remote_port = PORT_LDAP;
|
conn->remote_port = PORT_LDAP;
|
||||||
conn->curl_do = Curl_ldap;
|
conn->curl_do = Curl_ldap;
|
||||||
conn->curl_done = NULL; /* no LDAP-specific done */
|
conn->curl_done = NULL; /* no LDAP-specific done */
|
||||||
@@ -1995,8 +2085,8 @@ static CURLcode CreateConnection(struct SessionHandle *data,
|
|||||||
/* Resolve target host right on */
|
/* Resolve target host right on */
|
||||||
if(!conn->hostaddr) {
|
if(!conn->hostaddr) {
|
||||||
/* it might already be set if reusing a connection */
|
/* it might already be set if reusing a connection */
|
||||||
conn->hostaddr = Curl_getaddrinfo(data, conn->name, conn->port,
|
conn->hostaddr = Curl_resolv(data, conn->name, conn->port,
|
||||||
&conn->hostent_buf);
|
&conn->hostent_buf);
|
||||||
}
|
}
|
||||||
if(!conn->hostaddr) {
|
if(!conn->hostaddr) {
|
||||||
failf(data, "Couldn't resolve host '%s'", conn->name);
|
failf(data, "Couldn't resolve host '%s'", conn->name);
|
||||||
@@ -2010,8 +2100,8 @@ static CURLcode CreateConnection(struct SessionHandle *data,
|
|||||||
|
|
||||||
/* resolve proxy */
|
/* resolve proxy */
|
||||||
/* it might already be set if reusing a connection */
|
/* it might already be set if reusing a connection */
|
||||||
conn->hostaddr = Curl_getaddrinfo(data, conn->proxyhost, conn->port,
|
conn->hostaddr = Curl_resolv(data, conn->proxyhost, conn->port,
|
||||||
&conn->hostent_buf);
|
&conn->hostent_buf);
|
||||||
|
|
||||||
if(!conn->hostaddr) {
|
if(!conn->hostaddr) {
|
||||||
failf(data, "Couldn't resolve proxy '%s'", conn->proxyhost);
|
failf(data, "Couldn't resolve proxy '%s'", conn->proxyhost);
|
||||||
@@ -2146,7 +2236,12 @@ static CURLcode CreateConnection(struct SessionHandle *data,
|
|||||||
struct in_addr in;
|
struct in_addr in;
|
||||||
(void) memcpy(&in.s_addr, &conn->serv_addr.sin_addr, sizeof (in.s_addr));
|
(void) memcpy(&in.s_addr, &conn->serv_addr.sin_addr, sizeof (in.s_addr));
|
||||||
infof(data, "Connected to %s (%s)\n", conn->hostaddr->h_name,
|
infof(data, "Connected to %s (%s)\n", conn->hostaddr->h_name,
|
||||||
inet_ntoa(in));
|
#if defined(HAVE_INET_NTOA_R)
|
||||||
|
inet_ntoa_r(in, ntoa_buf, sizeof(ntoa_buf))
|
||||||
|
#else
|
||||||
|
inet_ntoa(in)
|
||||||
|
#endif
|
||||||
|
);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -2166,14 +2261,13 @@ static CURLcode CreateConnection(struct SessionHandle *data,
|
|||||||
}
|
}
|
||||||
|
|
||||||
CURLcode Curl_connect(struct SessionHandle *data,
|
CURLcode Curl_connect(struct SessionHandle *data,
|
||||||
struct connectdata **in_connect,
|
struct connectdata **in_connect)
|
||||||
bool allow_port)
|
|
||||||
{
|
{
|
||||||
CURLcode code;
|
CURLcode code;
|
||||||
struct connectdata *conn;
|
struct connectdata *conn;
|
||||||
|
|
||||||
/* call the stuff that needs to be called */
|
/* call the stuff that needs to be called */
|
||||||
code = CreateConnection(data, in_connect, allow_port);
|
code = CreateConnection(data, in_connect);
|
||||||
|
|
||||||
if(CURLE_OK != code) {
|
if(CURLE_OK != code) {
|
||||||
/* We're not allowed to return failure with memory left allocated
|
/* We're not allowed to return failure with memory left allocated
|
||||||
@@ -2229,14 +2323,38 @@ CURLcode Curl_done(struct connectdata *conn)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
CURLcode Curl_do(struct connectdata *conn)
|
CURLcode Curl_do(struct connectdata **connp)
|
||||||
{
|
{
|
||||||
CURLcode result=CURLE_OK;
|
CURLcode result=CURLE_OK;
|
||||||
|
struct connectdata *conn = *connp;
|
||||||
|
struct SessionHandle *data=conn->data;
|
||||||
|
|
||||||
if(conn->curl_do)
|
if(conn->curl_do) {
|
||||||
/* generic protocol-specific function pointer set in curl_connect() */
|
/* generic protocol-specific function pointer set in curl_connect() */
|
||||||
result = conn->curl_do(conn);
|
result = conn->curl_do(conn);
|
||||||
|
|
||||||
|
/* This was formerly done in transfer.c, but we better do it here */
|
||||||
|
|
||||||
|
if((CURLE_WRITE_ERROR == result) && conn->bits.reuse) {
|
||||||
|
/* This was a re-use of a connection and we got a write error in the
|
||||||
|
* DO-phase. Then we DISCONNECT this connection and have another attempt
|
||||||
|
* to CONNECT and then DO again! The retry cannot possibly find another
|
||||||
|
* connection to re-use, since we only keep one possible connection for
|
||||||
|
* each. */
|
||||||
|
|
||||||
|
infof(data, "Re-used connection seems dead, get a new one\n");
|
||||||
|
|
||||||
|
conn->bits.close = TRUE; /* enforce close of this connetion */
|
||||||
|
result = Curl_done(conn); /* we are so done with this */
|
||||||
|
if(CURLE_OK == result) {
|
||||||
|
/* Now, redo the connect and get a new connection */
|
||||||
|
result = Curl_connect(data, connp);
|
||||||
|
if(CURLE_OK == result)
|
||||||
|
/* ... finally back to actually retry the DO phase */
|
||||||
|
result = conn->curl_do(*connp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
10
lib/url.h
10
lib/url.h
@@ -7,7 +7,7 @@
|
|||||||
* | (__| |_| | _ <| |___
|
* | (__| |_| | _ <| |___
|
||||||
* \___|\___/|_| \_\_____|
|
* \___|\___/|_| \_\_____|
|
||||||
*
|
*
|
||||||
* Copyright (C) 2000, Daniel Stenberg, <daniel@haxx.se>, et al.
|
* Copyright (C) 2001, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||||
*
|
*
|
||||||
* In order to be useful for every potential user, curl and libcurl are
|
* In order to be useful for every potential user, curl and libcurl are
|
||||||
* dual-licensed under the MPL and the MIT/X-derivate licenses.
|
* dual-licensed under the MPL and the MIT/X-derivate licenses.
|
||||||
@@ -29,11 +29,9 @@
|
|||||||
|
|
||||||
CURLcode Curl_open(struct SessionHandle **curl);
|
CURLcode Curl_open(struct SessionHandle **curl);
|
||||||
CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, ...);
|
CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, ...);
|
||||||
CURLcode Curl_close(struct SessionHandle *data); /* the opposite of curl_open() */
|
CURLcode Curl_close(struct SessionHandle *data); /* opposite of curl_open() */
|
||||||
CURLcode Curl_connect(struct SessionHandle *,
|
CURLcode Curl_connect(struct SessionHandle *, struct connectdata **);
|
||||||
struct connectdata **,
|
CURLcode Curl_do(struct connectdata **);
|
||||||
bool allow_port);
|
|
||||||
CURLcode Curl_do(struct connectdata *);
|
|
||||||
CURLcode Curl_done(struct connectdata *);
|
CURLcode Curl_done(struct connectdata *);
|
||||||
CURLcode Curl_disconnect(struct connectdata *);
|
CURLcode Curl_disconnect(struct connectdata *);
|
||||||
|
|
||||||
|
104
lib/urldata.h
104
lib/urldata.h
@@ -27,6 +27,7 @@
|
|||||||
|
|
||||||
#include "setup.h"
|
#include "setup.h"
|
||||||
#include "hostip.h"
|
#include "hostip.h"
|
||||||
|
#include "hash.h"
|
||||||
|
|
||||||
#define PORT_FTP 21
|
#define PORT_FTP 21
|
||||||
#define PORT_TELNET 23
|
#define PORT_TELNET 23
|
||||||
@@ -58,6 +59,9 @@
|
|||||||
#include "openssl/pem.h"
|
#include "openssl/pem.h"
|
||||||
#include "openssl/ssl.h"
|
#include "openssl/ssl.h"
|
||||||
#include "openssl/err.h"
|
#include "openssl/err.h"
|
||||||
|
#ifdef HAVE_OPENSSL_ENGINE_H
|
||||||
|
#include <openssl/engine.h>
|
||||||
|
#endif
|
||||||
#else
|
#else
|
||||||
#include "rsa.h"
|
#include "rsa.h"
|
||||||
#include "crypto.h"
|
#include "crypto.h"
|
||||||
@@ -79,7 +83,7 @@
|
|||||||
#include "http_chunks.h" /* for the structs and enum stuff */
|
#include "http_chunks.h" /* for the structs and enum stuff */
|
||||||
|
|
||||||
/* Download buffer size, keep it fairly big for speed reasons */
|
/* Download buffer size, keep it fairly big for speed reasons */
|
||||||
#define BUFSIZE (1024*50)
|
#define BUFSIZE (1024*20)
|
||||||
|
|
||||||
/* Defaul upload buffer size, keep it smallish to get faster progress meter
|
/* Defaul upload buffer size, keep it smallish to get faster progress meter
|
||||||
updates. This is just default, it is dynamic and adjusts to the upload
|
updates. This is just default, it is dynamic and adjusts to the upload
|
||||||
@@ -111,6 +115,9 @@ enum protection_level {
|
|||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef HAVE_OPENSSL_ENGINE_H
|
||||||
|
typedef void ENGINE;
|
||||||
|
#endif
|
||||||
/* struct for data related to SSL and SSL connections */
|
/* struct for data related to SSL and SSL connections */
|
||||||
struct ssl_connect_data {
|
struct ssl_connect_data {
|
||||||
bool use; /* use ssl encrypted communications TRUE/FALSE */
|
bool use; /* use ssl encrypted communications TRUE/FALSE */
|
||||||
@@ -205,6 +212,58 @@ struct ConnectBits {
|
|||||||
complete */
|
complete */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This struct is all the previously local variables from Curl_perform() moved
|
||||||
|
* to struct to allow the function to return and get re-invoked better without
|
||||||
|
* losing state.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct Curl_transfer_keeper {
|
||||||
|
int bytecount; /* total number of bytes read */
|
||||||
|
int writebytecount; /* number of bytes written */
|
||||||
|
long contentlength; /* size of incoming data */
|
||||||
|
struct timeval start; /* transfer started at this time */
|
||||||
|
struct timeval now; /* current time */
|
||||||
|
bool header; /* incoming data has HTTP header */
|
||||||
|
int headerline; /* counts header lines to better track the
|
||||||
|
first one */
|
||||||
|
char *hbufp; /* points at *end* of header line */
|
||||||
|
int hbuflen;
|
||||||
|
char *str; /* within buf */
|
||||||
|
char *str_start; /* within buf */
|
||||||
|
char *end_ptr; /* within buf */
|
||||||
|
char *p; /* within headerbuff */
|
||||||
|
bool content_range; /* set TRUE if Content-Range: was found */
|
||||||
|
int offset; /* possible resume offset read from the
|
||||||
|
Content-Range: header */
|
||||||
|
int httpcode; /* error code from the 'HTTP/1.? XXX' line */
|
||||||
|
int httpversion; /* the HTTP version*10 */
|
||||||
|
bool write_after_100_header; /* should we enable the write after
|
||||||
|
we received a 100-continue/timeout
|
||||||
|
or directly */
|
||||||
|
|
||||||
|
/* for the low speed checks: */
|
||||||
|
time_t timeofdoc;
|
||||||
|
long bodywrites;
|
||||||
|
int writetype;
|
||||||
|
|
||||||
|
/* the highest fd we use + 1 */
|
||||||
|
struct SessionHandle *data;
|
||||||
|
struct connectdata *conn;
|
||||||
|
char *buf;
|
||||||
|
char *uploadbuf;
|
||||||
|
int maxfd;
|
||||||
|
|
||||||
|
/* the file descriptors to play with */
|
||||||
|
fd_set readfd;
|
||||||
|
fd_set writefd;
|
||||||
|
fd_set rkeepfd;
|
||||||
|
fd_set wkeepfd;
|
||||||
|
int keepon;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The connectdata struct contains all fields and variables that should be
|
* The connectdata struct contains all fields and variables that should be
|
||||||
* unique for an entire connection.
|
* unique for an entire connection.
|
||||||
@@ -349,6 +408,18 @@ struct connectdata {
|
|||||||
void *generic;
|
void *generic;
|
||||||
} proto;
|
} proto;
|
||||||
|
|
||||||
|
/* This struct is inited when needed */
|
||||||
|
struct Curl_transfer_keeper keep;
|
||||||
|
|
||||||
|
/* 'upload_present' is used to keep a byte counter of how much data there is
|
||||||
|
still left in the buffer, aimed for upload. */
|
||||||
|
int upload_present;
|
||||||
|
|
||||||
|
/* 'upload_fromhere' is used as a read-pointer when we uploaded parts of a
|
||||||
|
buffer, so the next read should read from where this pointer points to,
|
||||||
|
and the 'upload_present' contains the number of bytes available at this
|
||||||
|
position */
|
||||||
|
char *upload_fromhere;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -435,8 +506,8 @@ struct UrlState {
|
|||||||
char *headerbuff; /* allocated buffer to store headers in */
|
char *headerbuff; /* allocated buffer to store headers in */
|
||||||
int headersize; /* size of the allocation */
|
int headersize; /* size of the allocation */
|
||||||
|
|
||||||
char buffer[BUFSIZE+1]; /* buffer with size BUFSIZE */
|
char buffer[BUFSIZE+1]; /* download buffer */
|
||||||
|
char uploadbuffer[BUFSIZE+1]; /* upload buffer */
|
||||||
double current_speed; /* the ProgressShow() funcion sets this */
|
double current_speed; /* the ProgressShow() funcion sets this */
|
||||||
|
|
||||||
bool this_is_a_follow; /* this is a followed Location: request */
|
bool this_is_a_follow; /* this is a followed Location: request */
|
||||||
@@ -454,6 +525,13 @@ struct UrlState {
|
|||||||
bool errorbuf; /* Set to TRUE if the error buffer is already filled in.
|
bool errorbuf; /* Set to TRUE if the error buffer is already filled in.
|
||||||
This must be set to FALSE every time _easy_perform() is
|
This must be set to FALSE every time _easy_perform() is
|
||||||
called. */
|
called. */
|
||||||
|
|
||||||
|
#ifdef HAVE_SIGNAL
|
||||||
|
/* storage for the previous bag^H^H^HSIGPIPE signal handler :-) */
|
||||||
|
void (*prev_signal)(int sig);
|
||||||
|
#endif
|
||||||
|
bool allow_port; /* Is set.use_port allowed to take effect or not. This
|
||||||
|
is always set TRUE when curl_easy_perform() is called. */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -525,8 +603,12 @@ struct UserDefined {
|
|||||||
char *cookie; /* HTTP cookie string to send */
|
char *cookie; /* HTTP cookie string to send */
|
||||||
struct curl_slist *headers; /* linked list of extra headers */
|
struct curl_slist *headers; /* linked list of extra headers */
|
||||||
struct HttpPost *httppost; /* linked list of POST data */
|
struct HttpPost *httppost; /* linked list of POST data */
|
||||||
char *cert; /* PEM-formatted certificate */
|
char *cert; /* certificate */
|
||||||
char *cert_passwd; /* plain text certificate password */
|
char *cert_type; /* format for certificate (default: PEM) */
|
||||||
|
char *key; /* private key */
|
||||||
|
char *key_type; /* format for private key (default: PEM) */
|
||||||
|
char *key_passwd; /* plain text private key password */
|
||||||
|
char *crypto_engine; /* name of the crypto engine to use */
|
||||||
char *cookiejar; /* dump all cookies to this file */
|
char *cookiejar; /* dump all cookies to this file */
|
||||||
bool crlf; /* convert crlf on ftp upload(?) */
|
bool crlf; /* convert crlf on ftp upload(?) */
|
||||||
struct curl_slist *quote; /* before the transfer */
|
struct curl_slist *quote; /* before the transfer */
|
||||||
@@ -546,6 +628,8 @@ struct UserDefined {
|
|||||||
char *krb4_level; /* what security level */
|
char *krb4_level; /* what security level */
|
||||||
struct ssl_config_data ssl; /* user defined SSL stuff */
|
struct ssl_config_data ssl; /* user defined SSL stuff */
|
||||||
|
|
||||||
|
int dns_cache_timeout; /* DNS cache timeout */
|
||||||
|
|
||||||
/* Here follows boolean settings that define how to behave during
|
/* Here follows boolean settings that define how to behave during
|
||||||
this session. They are STATIC, set by libcurl users or at least initially
|
this session. They are STATIC, set by libcurl users or at least initially
|
||||||
and they don't change during operations. */
|
and they don't change during operations. */
|
||||||
@@ -559,7 +643,9 @@ struct UserDefined {
|
|||||||
bool hide_progress;
|
bool hide_progress;
|
||||||
bool http_fail_on_error;
|
bool http_fail_on_error;
|
||||||
bool http_follow_location;
|
bool http_follow_location;
|
||||||
bool http_include_header;
|
bool include_header;
|
||||||
|
#define http_include_header include_header /* former name */
|
||||||
|
|
||||||
bool http_set_referer;
|
bool http_set_referer;
|
||||||
bool http_auto_referer; /* set "correct" referer when following location: */
|
bool http_auto_referer; /* set "correct" referer when following location: */
|
||||||
bool no_body;
|
bool no_body;
|
||||||
@@ -572,6 +658,8 @@ struct UserDefined {
|
|||||||
bool reuse_fresh; /* do not re-use an existing connection */
|
bool reuse_fresh; /* do not re-use an existing connection */
|
||||||
bool expect100header; /* TRUE if we added Expect: 100-continue */
|
bool expect100header; /* TRUE if we added Expect: 100-continue */
|
||||||
bool ftp_use_epsv; /* if EPSV is to be attempted or not */
|
bool ftp_use_epsv; /* if EPSV is to be attempted or not */
|
||||||
|
|
||||||
|
bool global_dns_cache;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -586,6 +674,7 @@ struct UserDefined {
|
|||||||
* 'struct urlstate' instead. */
|
* 'struct urlstate' instead. */
|
||||||
|
|
||||||
struct SessionHandle {
|
struct SessionHandle {
|
||||||
|
curl_hash *hostcache;
|
||||||
struct UserDefined set; /* values set by the libcurl user */
|
struct UserDefined set; /* values set by the libcurl user */
|
||||||
struct DynamicStatic change; /* possibly modified userdefined data */
|
struct DynamicStatic change; /* possibly modified userdefined data */
|
||||||
|
|
||||||
@@ -594,6 +683,9 @@ struct SessionHandle {
|
|||||||
struct UrlState state; /* struct for fields used for state info and
|
struct UrlState state; /* struct for fields used for state info and
|
||||||
other dynamic purposes */
|
other dynamic purposes */
|
||||||
struct PureInfo info; /* stats, reports and info data */
|
struct PureInfo info; /* stats, reports and info data */
|
||||||
|
#ifdef USE_SSLEAY
|
||||||
|
ENGINE* engine;
|
||||||
|
#endif /* USE_SSLEAY */
|
||||||
};
|
};
|
||||||
|
|
||||||
#define LIBCURL_NAME "libcurl"
|
#define LIBCURL_NAME "libcurl"
|
||||||
|
@@ -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
|
* In order to be useful for every potential user, curl and libcurl are
|
||||||
* dual-licensed under the MPL and the MIT/X-derivate licenses.
|
* dual-licensed under the MPL and the MIT/X-derivate licenses.
|
||||||
@@ -38,20 +38,28 @@ char *curl_version(void)
|
|||||||
|
|
||||||
#ifdef USE_SSLEAY
|
#ifdef USE_SSLEAY
|
||||||
|
|
||||||
#if (SSLEAY_VERSION_NUMBER >= 0x906000)
|
#if (SSLEAY_VERSION_NUMBER >= 0x905000)
|
||||||
{
|
{
|
||||||
char sub[2];
|
char sub[2];
|
||||||
|
unsigned long ssleay_value;
|
||||||
sub[1]='\0';
|
sub[1]='\0';
|
||||||
if(SSLEAY_VERSION_NUMBER&0xff0) {
|
ssleay_value=SSLeay();
|
||||||
sub[0]=((SSLEAY_VERSION_NUMBER>>4)&0xff) + 'a' -1;
|
if(ssleay_value < 0x906000) {
|
||||||
}
|
ssleay_value=SSLEAY_VERSION_NUMBER;
|
||||||
else
|
|
||||||
sub[0]='\0';
|
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)",
|
sprintf(ptr, " (OpenSSL %lx.%lx.%lx%s)",
|
||||||
(SSLEAY_VERSION_NUMBER>>28)&0xf,
|
(ssleay_value>>28)&0xf,
|
||||||
(SSLEAY_VERSION_NUMBER>>20)&0xff,
|
(ssleay_value>>20)&0xff,
|
||||||
(SSLEAY_VERSION_NUMBER>>12)&0xff,
|
(ssleay_value>>12)&0xff,
|
||||||
sub);
|
sub);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
21
multi/Makefile.am
Normal file
21
multi/Makefile.am
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
#
|
||||||
|
# $Id$
|
||||||
|
#
|
||||||
|
|
||||||
|
INCLUDES = -I$(top_srcdir)/include
|
||||||
|
|
||||||
|
bin_PROGRAMS = app single double
|
||||||
|
|
||||||
|
app_SOURCES = app.c
|
||||||
|
app_LDADD = ../lib/libcurl.la
|
||||||
|
app_DEPENDENCIES = ../lib/libcurl.la
|
||||||
|
|
||||||
|
single_SOURCES = single.c
|
||||||
|
single_LDADD = ../lib/libcurl.la
|
||||||
|
single_DEPENDENCIES = ../lib/libcurl.la
|
||||||
|
|
||||||
|
double_SOURCES = double.c
|
||||||
|
double_LDADD = ../lib/libcurl.la
|
||||||
|
double_DEPENDENCIES = ../lib/libcurl.la
|
||||||
|
|
||||||
|
AUTOMAKE_OPTIONS = foreign no-dependencies
|
92
multi/app.c
Normal file
92
multi/app.c
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
/*
|
||||||
|
* This is an example application source code using the multi interface.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
/* somewhat unix-specific */
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
|
||||||
|
/* To start with, we include the header from the lib directory. This should
|
||||||
|
later of course be moved to the proper include dir. */
|
||||||
|
#include "../lib/multi.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Download a HTTP file and upload an FTP file simultaneously.
|
||||||
|
*/
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
CURL *http_handle;
|
||||||
|
CURL *ftp_handle;
|
||||||
|
CURLM *multi_handle;
|
||||||
|
|
||||||
|
int still_running; /* keep number of running handles */
|
||||||
|
|
||||||
|
http_handle = curl_easy_init();
|
||||||
|
ftp_handle = curl_easy_init();
|
||||||
|
|
||||||
|
/* set the options (I left out a few, you'll get the point anyway) */
|
||||||
|
curl_easy_setopt(http_handle, CURLOPT_URL, "http://website.com");
|
||||||
|
|
||||||
|
curl_easy_setopt(ftp_handle, CURLOPT_URL, "ftp://ftpsite.com");
|
||||||
|
curl_easy_setopt(ftp_handle, CURLOPT_UPLOAD, TRUE);
|
||||||
|
|
||||||
|
/* init a multi stack */
|
||||||
|
multi_handle = curl_multi_init();
|
||||||
|
|
||||||
|
/* add the individual transfers */
|
||||||
|
curl_multi_add_handle(multi_handle, http_handle);
|
||||||
|
curl_multi_add_handle(multi_handle, ftp_handle);
|
||||||
|
|
||||||
|
/* we start some action by calling perform right away */
|
||||||
|
while(CURLM_CALL_MULTI_PERFORM ==
|
||||||
|
curl_multi_perform(multi_handle, &still_running));
|
||||||
|
|
||||||
|
while(still_running) {
|
||||||
|
struct timeval timeout;
|
||||||
|
int rc; /* select() return code */
|
||||||
|
|
||||||
|
fd_set fdread;
|
||||||
|
fd_set fdwrite;
|
||||||
|
fd_set fdexcep;
|
||||||
|
int maxfd;
|
||||||
|
|
||||||
|
FD_ZERO(&fdread);
|
||||||
|
FD_ZERO(&fdwrite);
|
||||||
|
FD_ZERO(&fdexcep);
|
||||||
|
|
||||||
|
/* set a suitable timeout to play around with */
|
||||||
|
timeout.tv_sec = 1;
|
||||||
|
timeout.tv_usec = 0;
|
||||||
|
|
||||||
|
/* get file descriptors from the transfers */
|
||||||
|
curl_multi_fdset(multi_handle, &fdread, &fdwrite, &fdexcep, &maxfd);
|
||||||
|
|
||||||
|
rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
|
||||||
|
|
||||||
|
switch(rc) {
|
||||||
|
case -1:
|
||||||
|
/* select error */
|
||||||
|
break;
|
||||||
|
case 0:
|
||||||
|
/* timeout, do something else */
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* one or more of curl's file descriptors say there's data to read
|
||||||
|
or write */
|
||||||
|
curl_multi_perform(multi_handle, &still_running);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
curl_multi_cleanup(multi_handle);
|
||||||
|
|
||||||
|
curl_easy_cleanup(http_handle);
|
||||||
|
curl_easy_cleanup(ftp_handle);
|
||||||
|
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
87
multi/double.c
Normal file
87
multi/double.c
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
/*
|
||||||
|
* This is a simple example using the multi interface.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
/* somewhat unix-specific */
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
/* To start with, we include the header from the lib directory. This should
|
||||||
|
later of course be moved to the proper include dir. */
|
||||||
|
#include "../lib/multi.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Simply download two HTTP files!
|
||||||
|
*/
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
CURL *http_handle;
|
||||||
|
CURL *http_handle2;
|
||||||
|
CURLM *multi_handle;
|
||||||
|
|
||||||
|
int still_running; /* keep number of running handles */
|
||||||
|
|
||||||
|
http_handle = curl_easy_init();
|
||||||
|
http_handle2 = curl_easy_init();
|
||||||
|
|
||||||
|
/* set options */
|
||||||
|
curl_easy_setopt(http_handle, CURLOPT_URL, "http://www.haxx.se/");
|
||||||
|
|
||||||
|
/* set options */
|
||||||
|
curl_easy_setopt(http_handle2, CURLOPT_URL, "http://localhost/");
|
||||||
|
|
||||||
|
/* init a multi stack */
|
||||||
|
multi_handle = curl_multi_init();
|
||||||
|
|
||||||
|
/* add the individual transfers */
|
||||||
|
curl_multi_add_handle(multi_handle, http_handle);
|
||||||
|
curl_multi_add_handle(multi_handle, http_handle2);
|
||||||
|
|
||||||
|
/* we start some action by calling perform right away */
|
||||||
|
while(CURLM_CALL_MULTI_PERFORM ==
|
||||||
|
curl_multi_perform(multi_handle, &still_running));
|
||||||
|
|
||||||
|
while(still_running) {
|
||||||
|
struct timeval timeout;
|
||||||
|
int rc; /* select() return code */
|
||||||
|
|
||||||
|
fd_set fdread;
|
||||||
|
fd_set fdwrite;
|
||||||
|
fd_set fdexcep;
|
||||||
|
int maxfd;
|
||||||
|
|
||||||
|
FD_ZERO(&fdread);
|
||||||
|
FD_ZERO(&fdwrite);
|
||||||
|
FD_ZERO(&fdexcep);
|
||||||
|
|
||||||
|
/* set a suitable timeout to play around with */
|
||||||
|
timeout.tv_sec = 1;
|
||||||
|
timeout.tv_usec = 0;
|
||||||
|
|
||||||
|
/* get file descriptors from the transfers */
|
||||||
|
curl_multi_fdset(multi_handle, &fdread, &fdwrite, &fdexcep, &maxfd);
|
||||||
|
|
||||||
|
rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
|
||||||
|
|
||||||
|
switch(rc) {
|
||||||
|
case -1:
|
||||||
|
/* select error */
|
||||||
|
break;
|
||||||
|
case 0:
|
||||||
|
default:
|
||||||
|
/* timeout or readable/writable sockets */
|
||||||
|
curl_multi_perform(multi_handle, &still_running);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
curl_multi_cleanup(multi_handle);
|
||||||
|
|
||||||
|
curl_easy_cleanup(http_handle);
|
||||||
|
curl_easy_cleanup(http_handle2);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
80
multi/single.c
Normal file
80
multi/single.c
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
/*
|
||||||
|
* This is a very simple example using the multi interface.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
/* somewhat unix-specific */
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
/* To start with, we include the header from the lib directory. This should
|
||||||
|
later of course be moved to the proper include dir. */
|
||||||
|
#include "../lib/multi.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Simply download a HTTP file.
|
||||||
|
*/
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
CURL *http_handle;
|
||||||
|
CURLM *multi_handle;
|
||||||
|
|
||||||
|
int still_running; /* keep number of running handles */
|
||||||
|
|
||||||
|
http_handle = curl_easy_init();
|
||||||
|
|
||||||
|
/* set the options (I left out a few, you'll get the point anyway) */
|
||||||
|
curl_easy_setopt(http_handle, CURLOPT_URL, "http://www.haxx.se/");
|
||||||
|
|
||||||
|
/* init a multi stack */
|
||||||
|
multi_handle = curl_multi_init();
|
||||||
|
|
||||||
|
/* add the individual transfers */
|
||||||
|
curl_multi_add_handle(multi_handle, http_handle);
|
||||||
|
|
||||||
|
/* we start some action by calling perform right away */
|
||||||
|
while(CURLM_CALL_MULTI_PERFORM ==
|
||||||
|
curl_multi_perform(multi_handle, &still_running));
|
||||||
|
|
||||||
|
while(still_running) {
|
||||||
|
struct timeval timeout;
|
||||||
|
int rc; /* select() return code */
|
||||||
|
|
||||||
|
fd_set fdread;
|
||||||
|
fd_set fdwrite;
|
||||||
|
fd_set fdexcep;
|
||||||
|
int maxfd;
|
||||||
|
|
||||||
|
FD_ZERO(&fdread);
|
||||||
|
FD_ZERO(&fdwrite);
|
||||||
|
FD_ZERO(&fdexcep);
|
||||||
|
|
||||||
|
/* set a suitable timeout to play around with */
|
||||||
|
timeout.tv_sec = 1;
|
||||||
|
timeout.tv_usec = 0;
|
||||||
|
|
||||||
|
/* get file descriptors from the transfers */
|
||||||
|
curl_multi_fdset(multi_handle, &fdread, &fdwrite, &fdexcep, &maxfd);
|
||||||
|
|
||||||
|
rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
|
||||||
|
|
||||||
|
switch(rc) {
|
||||||
|
case -1:
|
||||||
|
/* select error */
|
||||||
|
break;
|
||||||
|
case 0:
|
||||||
|
default:
|
||||||
|
/* timeout or readable/writable sockets */
|
||||||
|
curl_multi_perform(multi_handle, &still_running);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
curl_multi_cleanup(multi_handle);
|
||||||
|
|
||||||
|
curl_easy_cleanup(http_handle);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
10
perl/README
10
perl/README
@@ -10,8 +10,14 @@ Perl
|
|||||||
elegantly used from within it. You can either invoke external curl command
|
elegantly used from within it. You can either invoke external curl command
|
||||||
line or use the curl interface.
|
line or use the curl interface.
|
||||||
|
|
||||||
Georg Horn's Perl interface to curl is available in the Curl_easy/
|
The latest release of Curl_easy, a Perl interface to curl is available from
|
||||||
subdirectory. Using the Curl::easy module is just straightforward and
|
|
||||||
|
http://curl.haxx.se/libcurl/perl/
|
||||||
|
|
||||||
|
(Georg Horn's original version of Curl_easy, supporting curl versions
|
||||||
|
before 7.7 is still available from: http://www.koblenz-net.de/~horn/export/ )
|
||||||
|
|
||||||
|
Using the Curl::easy module is just straightforward and
|
||||||
works much like using libcurl in a C programm, so please refer to the
|
works much like using libcurl in a C programm, so please refer to the
|
||||||
documentation of libcurl. Have a look at test.pl to get an idea of how
|
documentation of libcurl. Have a look at test.pl to get an idea of how
|
||||||
to start.
|
to start.
|
||||||
|
130
src/main.c
130
src/main.c
@@ -77,7 +77,9 @@
|
|||||||
#define DEFAULT_MAXREDIRS 50L
|
#define DEFAULT_MAXREDIRS 50L
|
||||||
|
|
||||||
#ifndef __cplusplus /* (rabe) */
|
#ifndef __cplusplus /* (rabe) */
|
||||||
|
#ifndef typedef_bool
|
||||||
typedef char bool;
|
typedef char bool;
|
||||||
|
#endif
|
||||||
#endif /* (rabe) */
|
#endif /* (rabe) */
|
||||||
|
|
||||||
#define CURL_PROGRESS_STATS 0 /* default progress display */
|
#define CURL_PROGRESS_STATS 0 /* default progress display */
|
||||||
@@ -318,6 +320,11 @@ static void help(void)
|
|||||||
" --egd-file <file> EGD socket path for random data (SSL)\n"
|
" --egd-file <file> EGD socket path for random data (SSL)\n"
|
||||||
" -e/--referer Referer page (H)");
|
" -e/--referer Referer page (H)");
|
||||||
puts(" -E/--cert <cert[:passwd]> Specifies your certificate file and password (HTTPS)\n"
|
puts(" -E/--cert <cert[:passwd]> Specifies your certificate file and password (HTTPS)\n"
|
||||||
|
" --cert-type <type> Specifies your certificate file type (DER/PEM/ENG) (HTTPS)\n"
|
||||||
|
" --key <key> Specifies your private key file (HTTPS)\n"
|
||||||
|
" --key-type <type> Specifies your private key file type (DER/PEM/ENG) (HTTPS)\n"
|
||||||
|
" --pass <pass> Specifies your passphrase for the private key (HTTPS)");
|
||||||
|
puts(" --engine <eng> Specifies the crypto engine to use (HTTPS)\n"
|
||||||
" --cacert <file> CA certifciate to verify peer against (SSL)\n"
|
" --cacert <file> CA certifciate to verify peer against (SSL)\n"
|
||||||
" --ciphers <list> What SSL ciphers to use (SSL)\n"
|
" --ciphers <list> What SSL ciphers to use (SSL)\n"
|
||||||
" --connect-timeout <seconds> Maximum time allowed for connection\n"
|
" --connect-timeout <seconds> Maximum time allowed for connection\n"
|
||||||
@@ -420,8 +427,12 @@ struct Configurable {
|
|||||||
|
|
||||||
char *cipher_list;
|
char *cipher_list;
|
||||||
char *cert;
|
char *cert;
|
||||||
|
char *cert_type;
|
||||||
char *cacert;
|
char *cacert;
|
||||||
char *cert_passwd;
|
char *key;
|
||||||
|
char *key_type;
|
||||||
|
char *key_passwd;
|
||||||
|
char *engine;
|
||||||
bool crlf;
|
bool crlf;
|
||||||
char *customrequest;
|
char *customrequest;
|
||||||
char *krb4level;
|
char *krb4level;
|
||||||
@@ -884,6 +895,11 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */
|
|||||||
{"e", "referer", TRUE},
|
{"e", "referer", TRUE},
|
||||||
{"E", "cert", TRUE},
|
{"E", "cert", TRUE},
|
||||||
{"Ea", "cacert", TRUE},
|
{"Ea", "cacert", TRUE},
|
||||||
|
{"Eb","cert-type", TRUE},
|
||||||
|
{"Ec","key", TRUE},
|
||||||
|
{"Ed","key-type", TRUE},
|
||||||
|
{"Ee","pass", TRUE},
|
||||||
|
{"Ef","engine", TRUE},
|
||||||
{"f", "fail", FALSE},
|
{"f", "fail", FALSE},
|
||||||
{"F", "form", TRUE},
|
{"F", "form", TRUE},
|
||||||
{"g", "globoff", FALSE},
|
{"g", "globoff", FALSE},
|
||||||
@@ -1180,35 +1196,53 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'E':
|
case 'E':
|
||||||
if(subletter == 'a') {
|
switch(subletter) {
|
||||||
|
case 'a': /* CA info PEM file */
|
||||||
/* CA info PEM file */
|
/* CA info PEM file */
|
||||||
GetStr(&config->cacert, nextarg);
|
GetStr(&config->cacert, nextarg);
|
||||||
}
|
break;
|
||||||
else {
|
case 'b': /* cert file type */
|
||||||
char *ptr = strchr(nextarg, ':');
|
GetStr(&config->cert_type, nextarg);
|
||||||
/* Since we live in a world of weirdness and confusion, the win32
|
break;
|
||||||
dudes can use : when using drive letters and thus
|
case 'c': /* private key file */
|
||||||
c:\file:password needs to work. In order not to break
|
GetStr(&config->key, nextarg);
|
||||||
compatibility, we still use : as separator, but we try to detect
|
break;
|
||||||
when it is used for a file name! On windows. */
|
case 'd': /* private key file type */
|
||||||
|
GetStr(&config->key_type, nextarg);
|
||||||
|
break;
|
||||||
|
case 'e': /* private key passphrase */
|
||||||
|
GetStr(&config->key_passwd, nextarg);
|
||||||
|
break;
|
||||||
|
case 'f': /* crypto engine */
|
||||||
|
GetStr(&config->engine, nextarg);
|
||||||
|
break;
|
||||||
|
default: /* certificate file */
|
||||||
|
{
|
||||||
|
char *ptr = strchr(nextarg, ':');
|
||||||
|
/* Since we live in a world of weirdness and confusion, the win32
|
||||||
|
dudes can use : when using drive letters and thus
|
||||||
|
c:\file:password needs to work. In order not to break
|
||||||
|
compatibility, we still use : as separator, but we try to detect
|
||||||
|
when it is used for a file name! On windows. */
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
if(ptr &&
|
if(ptr &&
|
||||||
(ptr == &nextarg[1]) &&
|
(ptr == &nextarg[1]) &&
|
||||||
(nextarg[2] == '\\') &&
|
(nextarg[2] == '\\') &&
|
||||||
(isalpha((int)nextarg[0])) )
|
(isalpha((int)nextarg[0])) )
|
||||||
/* colon in the second column, followed by a backslash, and the
|
/* colon in the second column, followed by a backslash, and the
|
||||||
first character is an alphabetic letter:
|
first character is an alphabetic letter:
|
||||||
|
|
||||||
this is a drive letter colon */
|
this is a drive letter colon */
|
||||||
ptr = strchr(&nextarg[3], ':'); /* find the next one instead */
|
ptr = strchr(&nextarg[3], ':'); /* find the next one instead */
|
||||||
#endif
|
#endif
|
||||||
if(ptr) {
|
if(ptr) {
|
||||||
/* we have a password too */
|
/* we have a password too */
|
||||||
*ptr=0;
|
*ptr=0;
|
||||||
ptr++;
|
ptr++;
|
||||||
GetStr(&config->cert_passwd, ptr);
|
GetStr(&config->key_passwd, ptr);
|
||||||
}
|
}
|
||||||
GetStr(&config->cert, nextarg);
|
GetStr(&config->cert, nextarg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'f':
|
case 'f':
|
||||||
@@ -1245,10 +1279,23 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */
|
|||||||
config->conf ^= CONF_HEADER; /* include the HTTP header as well */
|
config->conf ^= CONF_HEADER; /* include the HTTP header as well */
|
||||||
break;
|
break;
|
||||||
case 'I':
|
case 'I':
|
||||||
config->conf ^= CONF_HEADER; /* include the HTTP header in the output */
|
/*
|
||||||
config->conf ^= CONF_NOBODY; /* don't fetch the body at all */
|
* This is a bit tricky. We either SET both bits, or we clear both
|
||||||
if(SetHTTPrequest(HTTPREQ_HEAD, &config->httpreq))
|
* bits. Let's not make any other outcomes from this.
|
||||||
return PARAM_BAD_USE;
|
*/
|
||||||
|
if((CONF_HEADER|CONF_NOBODY) !=
|
||||||
|
(config->conf&(CONF_HEADER|CONF_NOBODY)) ) {
|
||||||
|
/* one of them weren't set, set both */
|
||||||
|
config->conf |= (CONF_HEADER|CONF_NOBODY);
|
||||||
|
if(SetHTTPrequest(HTTPREQ_HEAD, &config->httpreq))
|
||||||
|
return PARAM_BAD_USE;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* both were set, clear both */
|
||||||
|
config->conf &= ~(CONF_HEADER|CONF_NOBODY);
|
||||||
|
if(SetHTTPrequest(HTTPREQ_GET, &config->httpreq))
|
||||||
|
return PARAM_BAD_USE;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 'K':
|
case 'K':
|
||||||
res = parseconfig(nextarg, config);
|
res = parseconfig(nextarg, config);
|
||||||
@@ -2091,17 +2138,29 @@ operate(struct Configurable *config, int argc, char *argv[])
|
|||||||
to be able to do so, we have to create a new URL in another
|
to be able to do so, we have to create a new URL in another
|
||||||
buffer.*/
|
buffer.*/
|
||||||
|
|
||||||
urlbuffer=(char *)malloc(strlen(url) + strlen(config->infile) + 3);
|
/* We only want the part of the local path that is on the right
|
||||||
|
side of the rightmost slash and backslash. */
|
||||||
|
char *filep = strrchr(config->infile, '/');
|
||||||
|
char *file2 = strrchr(filep?filep:config->infile, '\\');
|
||||||
|
|
||||||
|
if(file2)
|
||||||
|
filep = file2+1;
|
||||||
|
else if(filep)
|
||||||
|
filep++;
|
||||||
|
else
|
||||||
|
filep = config->infile;
|
||||||
|
|
||||||
|
urlbuffer=(char *)malloc(strlen(url) + strlen(filep) + 3);
|
||||||
if(!urlbuffer) {
|
if(!urlbuffer) {
|
||||||
helpf("out of memory\n");
|
helpf("out of memory\n");
|
||||||
return CURLE_OUT_OF_MEMORY;
|
return CURLE_OUT_OF_MEMORY;
|
||||||
}
|
}
|
||||||
if(ptr)
|
if(ptr)
|
||||||
/* there is a trailing slash on the URL */
|
/* there is a trailing slash on the URL */
|
||||||
sprintf(urlbuffer, "%s%s", url, config->infile);
|
sprintf(urlbuffer, "%s%s", url, filep);
|
||||||
else
|
else
|
||||||
/* thers is no trailing slash on the URL */
|
/* thers is no trailing slash on the URL */
|
||||||
sprintf(urlbuffer, "%s/%s", url, config->infile);
|
sprintf(urlbuffer, "%s/%s", url, filep);
|
||||||
|
|
||||||
url = urlbuffer; /* use our new URL instead! */
|
url = urlbuffer; /* use our new URL instead! */
|
||||||
}
|
}
|
||||||
@@ -2202,6 +2261,8 @@ operate(struct Configurable *config, int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
curl_easy_setopt(curl, CURLOPT_SSLENGINE, config->engine);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_SSLENGINE_DEFAULT, 1);
|
||||||
|
|
||||||
curl_easy_setopt(curl, CURLOPT_FILE, (FILE *)&outs); /* where to store */
|
curl_easy_setopt(curl, CURLOPT_FILE, (FILE *)&outs); /* where to store */
|
||||||
/* what call to write: */
|
/* what call to write: */
|
||||||
@@ -2249,7 +2310,10 @@ operate(struct Configurable *config, int argc, char *argv[])
|
|||||||
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, config->headers);
|
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, config->headers);
|
||||||
curl_easy_setopt(curl, CURLOPT_HTTPPOST, config->httppost);
|
curl_easy_setopt(curl, CURLOPT_HTTPPOST, config->httppost);
|
||||||
curl_easy_setopt(curl, CURLOPT_SSLCERT, config->cert);
|
curl_easy_setopt(curl, CURLOPT_SSLCERT, config->cert);
|
||||||
curl_easy_setopt(curl, CURLOPT_SSLCERTPASSWD, config->cert_passwd);
|
curl_easy_setopt(curl, CURLOPT_SSLCERTTYPE, config->cert_type);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_SSLKEY, config->key);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_SSLKEYTYPE, config->key_type);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_SSLKEYPASSWD, config->key_passwd);
|
||||||
|
|
||||||
if(config->cacert) {
|
if(config->cacert) {
|
||||||
curl_easy_setopt(curl, CURLOPT_CAINFO, config->cacert);
|
curl_easy_setopt(curl, CURLOPT_CAINFO, config->cacert);
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
#ifndef __SETUP_H
|
#ifndef __CLIENT_SETUP_H
|
||||||
#define __SETUP_H
|
#define __CLIENT_SETUP_H
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
* _ _ ____ _
|
* _ _ ____ _
|
||||||
* Project ___| | | | _ \| |
|
* Project ___| | | | _ \| |
|
||||||
|
@@ -1,3 +1,3 @@
|
|||||||
#define CURL_NAME "curl"
|
#define CURL_NAME "curl"
|
||||||
#define CURL_VERSION "7.9.2"
|
#define CURL_VERSION "7.9.3"
|
||||||
#define CURL_ID CURL_NAME " " CURL_VERSION " (" OS ") "
|
#define CURL_ID CURL_NAME " " CURL_VERSION " (" OS ") "
|
||||||
|
@@ -14,8 +14,10 @@ specified, that will be checked/used if specified. This document includes all
|
|||||||
the subsections currently supported.
|
the subsections currently supported.
|
||||||
|
|
||||||
<reply>
|
<reply>
|
||||||
<data>
|
<data [nocheck=1]>
|
||||||
data to sent to the client on its request
|
data to sent to the client on its request and later verified that it arrived
|
||||||
|
safely. Set the nocheck=1 to prevent the test script to verify the arrival
|
||||||
|
of this data.
|
||||||
</data>
|
</data>
|
||||||
<datacheck>
|
<datacheck>
|
||||||
if the data is sent but this is what should be checked afterwards
|
if the data is sent but this is what should be checked afterwards
|
||||||
@@ -30,16 +32,20 @@ reply is sent
|
|||||||
<postcmd>
|
<postcmd>
|
||||||
special purpose server-command to control its behavior *after* the
|
special purpose server-command to control its behavior *after* the
|
||||||
reply is sent
|
reply is sent
|
||||||
</oistcmd>
|
</postcmd>
|
||||||
</reply>
|
</reply>
|
||||||
|
|
||||||
<client>
|
<client>
|
||||||
<name>
|
<name>
|
||||||
test case description
|
test case description
|
||||||
</name>
|
</name>
|
||||||
<command>
|
<command [option=no-output]>
|
||||||
command line to run, there's a bunch of %variables that get replaced
|
command line to run, there's a bunch of %variables that get replaced
|
||||||
accordingly. more about them elsewhere
|
accordingly. more about them elsewhere
|
||||||
|
|
||||||
|
Set 'option=no-output' to prevent the test script to slap on the --output
|
||||||
|
argument that directs the output to a file. The --output is also not added if
|
||||||
|
the client/stdout section is used.
|
||||||
</command>
|
</command>
|
||||||
<file name="log/filename">
|
<file name="log/filename">
|
||||||
this creates the named file with this content before the test case is run
|
this creates the named file with this content before the test case is run
|
||||||
@@ -59,6 +65,9 @@ changing protocol data such as port numbers or user-agent strings.
|
|||||||
<protocol>
|
<protocol>
|
||||||
the protocol dump curl should transmit
|
the protocol dump curl should transmit
|
||||||
</protocol>
|
</protocol>
|
||||||
|
<stdout>
|
||||||
|
This verfies that this data was passed to stdout.
|
||||||
|
</stdout>
|
||||||
<file name="log/filename">
|
<file name="log/filename">
|
||||||
the file's contents must be identical to this
|
the file's contents must be identical to this
|
||||||
</file>
|
</file>
|
||||||
|
@@ -13,5 +13,5 @@ test102 test111 test120 test16 test21 test30 test400 test7 \
|
|||||||
test103 test112 test121 test17 test22 test300 test401 test8 \
|
test103 test112 test121 test17 test22 test300 test401 test8 \
|
||||||
test104 test113 test122 test18 test23 test301 test402 test9 \
|
test104 test113 test122 test18 test23 test301 test402 test9 \
|
||||||
test105 test114 test123 test19 test24 test302 test43 \
|
test105 test114 test123 test19 test24 test302 test43 \
|
||||||
test106 test115 test124 test190 test25 test303 test44 \
|
test106 test115 test124 test190 test25 test303 test44 test38 \
|
||||||
test107 test116 test125 test2 test26 test33 test45 test126
|
test107 test116 test125 test2 test26 test33 test45 test126
|
||||||
|
49
tests/data/test38
Normal file
49
tests/data/test38
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
# Server-side
|
||||||
|
<reply>
|
||||||
|
<data nocheck=1>
|
||||||
|
HTTP/1.0 200 Mooo
|
||||||
|
Date: Mon, 13 Nov 2000 13:41:09 GMT
|
||||||
|
Server: myown/1.0
|
||||||
|
Connection: close
|
||||||
|
|
||||||
|
todelooooo lalalala yada yada, we know nothing about ranges ;-)
|
||||||
|
</data>
|
||||||
|
</reply>
|
||||||
|
|
||||||
|
# Client-side
|
||||||
|
<client>
|
||||||
|
<name>
|
||||||
|
HTTP resume request without server supporting it
|
||||||
|
</name>
|
||||||
|
<command option="no-output">
|
||||||
|
http://%HOSTIP:%HOSTPORT/want/38 -C - -i -o log/fewl.txt
|
||||||
|
</command>
|
||||||
|
<file name="log/fewl.txt">
|
||||||
|
This text is here to simulate a partly downloaded file to resume
|
||||||
|
download on.
|
||||||
|
</file>
|
||||||
|
</client>
|
||||||
|
|
||||||
|
# Verify data after the test has been "shot"
|
||||||
|
<verify>
|
||||||
|
<errorcode>
|
||||||
|
33
|
||||||
|
</errorcode>
|
||||||
|
<strip>
|
||||||
|
^User-Agent:.*
|
||||||
|
</strip>
|
||||||
|
<protocol>
|
||||||
|
GET /want/38 HTTP/1.1
|
||||||
|
Range: bytes=78-
|
||||||
|
Host: 127.0.0.1:8999
|
||||||
|
Pragma: no-cache
|
||||||
|
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*
|
||||||
|
|
||||||
|
</protocol>
|
||||||
|
|
||||||
|
# the download target file must remain untouched
|
||||||
|
<file name="log/fewl.txt">
|
||||||
|
This text is here to simulate a partly downloaded file to resume
|
||||||
|
download on.
|
||||||
|
</file>
|
||||||
|
</verify>
|
@@ -3,6 +3,9 @@
|
|||||||
|
|
||||||
my @xml;
|
my @xml;
|
||||||
|
|
||||||
|
my $warning=0;
|
||||||
|
my $trace=0;
|
||||||
|
|
||||||
sub getpartattr {
|
sub getpartattr {
|
||||||
my ($section, $part)=@_;
|
my ($section, $part)=@_;
|
||||||
|
|
||||||
@@ -63,12 +66,21 @@ sub getpart {
|
|||||||
$inside--;
|
$inside--;
|
||||||
}
|
}
|
||||||
elsif((1==$inside) && ($_ =~ /^ *\<\/$section/)) {
|
elsif((1==$inside) && ($_ =~ /^ *\<\/$section/)) {
|
||||||
|
if($trace) {
|
||||||
|
print STDERR "*** getpart.pm: $section/$part returned data!\n";
|
||||||
|
}
|
||||||
|
if(!@this && $warning) {
|
||||||
|
print STDERR "*** getpart.pm: $section/$part returned empty!\n";
|
||||||
|
}
|
||||||
return @this;
|
return @this;
|
||||||
}
|
}
|
||||||
elsif(2==$inside) {
|
elsif(2==$inside) {
|
||||||
push @this, $_;
|
push @this, $_;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if($warning) {
|
||||||
|
print STDERR "*** getpart.pm: $section/$part returned empty!\n";
|
||||||
|
}
|
||||||
return @this; #empty!
|
return @this; #empty!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -68,6 +68,8 @@ my $debugprotocol;
|
|||||||
my $anyway;
|
my $anyway;
|
||||||
my $gdbthis; # run test case with gdb debugger
|
my $gdbthis; # run test case with gdb debugger
|
||||||
my $keepoutfiles; # keep stdout and stderr files after tests
|
my $keepoutfiles; # keep stdout and stderr files after tests
|
||||||
|
my $listonly; # only list the tests
|
||||||
|
|
||||||
my $pwd; # current working directory
|
my $pwd; # current working directory
|
||||||
|
|
||||||
chomp($pwd = `pwd`);
|
chomp($pwd = `pwd`);
|
||||||
@@ -427,14 +429,6 @@ sub singletest {
|
|||||||
|
|
||||||
my $CURLOUT="$LOGDIR/curl$testnum.out"; # curl output if not stdout
|
my $CURLOUT="$LOGDIR/curl$testnum.out"; # curl output if not stdout
|
||||||
|
|
||||||
# remove previous server output logfile
|
|
||||||
unlink($SERVERIN);
|
|
||||||
|
|
||||||
if(@ftpservercmd) {
|
|
||||||
# write the instructions to file
|
|
||||||
writearray($FTPDCMD, \@ftpservercmd);
|
|
||||||
}
|
|
||||||
|
|
||||||
# name of the test
|
# name of the test
|
||||||
my @testname= getpart("client", "name");
|
my @testname= getpart("client", "name");
|
||||||
|
|
||||||
@@ -445,6 +439,18 @@ sub singletest {
|
|||||||
print "[$name]\n";
|
print "[$name]\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if($listonly) {
|
||||||
|
return 0; # look successful
|
||||||
|
}
|
||||||
|
|
||||||
|
# remove previous server output logfile
|
||||||
|
unlink($SERVERIN);
|
||||||
|
|
||||||
|
if(@ftpservercmd) {
|
||||||
|
# write the instructions to file
|
||||||
|
writearray($FTPDCMD, \@ftpservercmd);
|
||||||
|
}
|
||||||
|
|
||||||
# get the command line options to use
|
# get the command line options to use
|
||||||
my ($cmd, @blaha)= getpart("client", "command");
|
my ($cmd, @blaha)= getpart("client", "command");
|
||||||
|
|
||||||
@@ -477,9 +483,17 @@ sub singletest {
|
|||||||
writearray($filename, \@inputfile);
|
writearray($filename, \@inputfile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
my %cmdhash = getpartattr("client", "command");
|
||||||
|
|
||||||
my $out="";
|
my $out="";
|
||||||
if (!@validstdout) {
|
|
||||||
$out="--output $CURLOUT ";
|
if($cmdhash{'option'} eq "no-output") {
|
||||||
|
#print "*** We don't slap on --output\n";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (!@validstdout) {
|
||||||
|
$out="--output $CURLOUT ";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# run curl, add -v for debug information output
|
# run curl, add -v for debug information output
|
||||||
@@ -775,6 +789,10 @@ do {
|
|||||||
# continue anyway, even if a test fail
|
# continue anyway, even if a test fail
|
||||||
$anyway=1;
|
$anyway=1;
|
||||||
}
|
}
|
||||||
|
elsif($ARGV[0] eq "-l") {
|
||||||
|
# lists the test case names only
|
||||||
|
$listonly=1;
|
||||||
|
}
|
||||||
elsif($ARGV[0] eq "-k") {
|
elsif($ARGV[0] eq "-k") {
|
||||||
# keep stdout and stderr files after tests
|
# keep stdout and stderr files after tests
|
||||||
$keepoutfiles=1;
|
$keepoutfiles=1;
|
||||||
@@ -788,6 +806,7 @@ Usage: runtests.pl [options]
|
|||||||
-g run the test case with gdb
|
-g run the test case with gdb
|
||||||
-h this help text
|
-h this help text
|
||||||
-k keep stdout and stderr files present after tests
|
-k keep stdout and stderr files present after tests
|
||||||
|
-l list all test case names/descriptions
|
||||||
-s short output
|
-s short output
|
||||||
-v verbose output
|
-v verbose output
|
||||||
[num] like "5 6 9" or " 5 to 22 " to run those tests only
|
[num] like "5 6 9" or " 5 to 22 " to run those tests only
|
||||||
@@ -821,7 +840,9 @@ if($testthis[0] ne "") {
|
|||||||
# Output curl version and host info being tested
|
# Output curl version and host info being tested
|
||||||
#
|
#
|
||||||
|
|
||||||
displaydata();
|
if(!$listonly) {
|
||||||
|
displaydata();
|
||||||
|
}
|
||||||
|
|
||||||
#######################################################################
|
#######################################################################
|
||||||
# clear and create logging directory:
|
# clear and create logging directory:
|
||||||
@@ -912,7 +933,8 @@ for(keys %run) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if($total) {
|
if($total) {
|
||||||
print "$ok tests out of $total reported OK\n";
|
printf("$ok tests out of $total reported OK: %d%%\n",
|
||||||
|
$ok/$total*100);
|
||||||
|
|
||||||
if($ok != $total) {
|
if($ok != $total) {
|
||||||
print "These test cases failed: $failed\n";
|
print "These test cases failed: $failed\n";
|
||||||
|
Reference in New Issue
Block a user