Compare commits
227 Commits
curl-7_16_
...
curl-7_16_
Author | SHA1 | Date | |
---|---|---|---|
![]() |
ef442d5803 | ||
![]() |
8680e010c2 | ||
![]() |
4d8dcf7b77 | ||
![]() |
abdbd3100f | ||
![]() |
ddace02efe | ||
![]() |
1f4c8c4f09 | ||
![]() |
8162b32bad | ||
![]() |
daf527b276 | ||
![]() |
ee51c07be6 | ||
![]() |
856ba4c6c6 | ||
![]() |
b3e23373bd | ||
![]() |
e5adab39b1 | ||
![]() |
d31153584e | ||
![]() |
823d296e12 | ||
![]() |
e09450103b | ||
![]() |
fbc4407583 | ||
![]() |
a79e5d7925 | ||
![]() |
82491d5c06 | ||
![]() |
b6f889085d | ||
![]() |
cdbbb7d900 | ||
![]() |
2bf4d9a22c | ||
![]() |
f1918aa343 | ||
![]() |
56580fc6f8 | ||
![]() |
2e6600425e | ||
![]() |
cc021fc200 | ||
![]() |
e6aed92742 | ||
![]() |
02fb4d96d1 | ||
![]() |
43e3c5e5fa | ||
![]() |
4f496f2f70 | ||
![]() |
d681bc7520 | ||
![]() |
f21a2b3270 | ||
![]() |
5f5a28d20e | ||
![]() |
89f9cb4041 | ||
![]() |
2b280bcc69 | ||
![]() |
1c0224be42 | ||
![]() |
dbdb7fa55a | ||
![]() |
83a43bea8a | ||
![]() |
abb4cdafe9 | ||
![]() |
2b7bcf2505 | ||
![]() |
5aefdd93cb | ||
![]() |
4b27fae069 | ||
![]() |
10a13eba72 | ||
![]() |
44ac2776ae | ||
![]() |
36e3e6ed16 | ||
![]() |
5f9cbc4209 | ||
![]() |
3239f059b8 | ||
![]() |
45bac25d90 | ||
![]() |
354c8dcd82 | ||
![]() |
b1e4cc370d | ||
![]() |
2293474b90 | ||
![]() |
9e1aef7183 | ||
![]() |
f68323da7d | ||
![]() |
a61aafa325 | ||
![]() |
33bea767eb | ||
![]() |
9ab7cda010 | ||
![]() |
6da70628c6 | ||
![]() |
3bae748256 | ||
![]() |
521c4b303d | ||
![]() |
a2effd123a | ||
![]() |
7b704e173c | ||
![]() |
6045d051d7 | ||
![]() |
cfe00ed4ad | ||
![]() |
0b4bdcf18f | ||
![]() |
8cade952bf | ||
![]() |
385e612fa5 | ||
![]() |
1886388791 | ||
![]() |
32fe5b14ec | ||
![]() |
bbdc483671 | ||
![]() |
f11d3c329c | ||
![]() |
b0d13fa4cb | ||
![]() |
0fb5a65a58 | ||
![]() |
c8afb02b4c | ||
![]() |
869d65337e | ||
![]() |
277df1c6b1 | ||
![]() |
5ec5b95f54 | ||
![]() |
9e61c904ac | ||
![]() |
7efb955fd0 | ||
![]() |
75899741b9 | ||
![]() |
d465199411 | ||
![]() |
55123424c8 | ||
![]() |
f5e4a78b59 | ||
![]() |
7515a75206 | ||
![]() |
4750e6f3c5 | ||
![]() |
b7aaa4d907 | ||
![]() |
e61e09f658 | ||
![]() |
058e993acb | ||
![]() |
359d500908 | ||
![]() |
cb42855445 | ||
![]() |
d8ff0336a5 | ||
![]() |
0682d25da5 | ||
![]() |
d86d14074d | ||
![]() |
8500397cf1 | ||
![]() |
bd600fbebe | ||
![]() |
064bbb999f | ||
![]() |
bedc61ac45 | ||
![]() |
61a6992559 | ||
![]() |
ebee2e323d | ||
![]() |
b2f8de571f | ||
![]() |
cb4a5f5a2b | ||
![]() |
1beb7de7e0 | ||
![]() |
89ab5f4380 | ||
![]() |
439b84c782 | ||
![]() |
0e899d7728 | ||
![]() |
1a85fb2bd0 | ||
![]() |
8d11767048 | ||
![]() |
fcccf9aa0d | ||
![]() |
72bd027537 | ||
![]() |
1d44c9ccc1 | ||
![]() |
33831759b5 | ||
![]() |
6fe932b255 | ||
![]() |
8da02df8e0 | ||
![]() |
587c99351d | ||
![]() |
88c8d72a21 | ||
![]() |
cf99fed17a | ||
![]() |
ca48b6bf35 | ||
![]() |
4dcd606b47 | ||
![]() |
393ddd6e1f | ||
![]() |
840e796aa9 | ||
![]() |
5fd096da8d | ||
![]() |
eb29c5c285 | ||
![]() |
1eb286e43e | ||
![]() |
ae76ebe2d1 | ||
![]() |
e4505aefd9 | ||
![]() |
d6b0612882 | ||
![]() |
4c65eb0af8 | ||
![]() |
318a8258fd | ||
![]() |
17ae28e0fe | ||
![]() |
3c4f622479 | ||
![]() |
3ce43764be | ||
![]() |
b555c60e49 | ||
![]() |
2336d010ef | ||
![]() |
b9af0d89d5 | ||
![]() |
6f2afe0c30 | ||
![]() |
d8c61d459e | ||
![]() |
7ae5ebbeb2 | ||
![]() |
7335b71dfb | ||
![]() |
9583b03074 | ||
![]() |
3c81d5f125 | ||
![]() |
688699a046 | ||
![]() |
090f5a9a45 | ||
![]() |
da58d03ff7 | ||
![]() |
9ea3831c08 | ||
![]() |
a46f55b9de | ||
![]() |
a634f64400 | ||
![]() |
bcd8a3b240 | ||
![]() |
04d5d1895c | ||
![]() |
abd2775a70 | ||
![]() |
73226415fc | ||
![]() |
ab160ef445 | ||
![]() |
268fe09322 | ||
![]() |
7a557e984a | ||
![]() |
f1a55cbe6d | ||
![]() |
1e35d95df8 | ||
![]() |
d8387b418d | ||
![]() |
adea16a294 | ||
![]() |
7f2d5cab2d | ||
![]() |
c6ff612f6e | ||
![]() |
8db353e1d7 | ||
![]() |
e6978117a7 | ||
![]() |
5dcb055077 | ||
![]() |
0b5e1a9b2f | ||
![]() |
2e17a97474 | ||
![]() |
74ddbd8a3b | ||
![]() |
b8039a821b | ||
![]() |
438312f00e | ||
![]() |
381ccaa391 | ||
![]() |
3204494883 | ||
![]() |
e264f699d4 | ||
![]() |
68d4b77d44 | ||
![]() |
e1ac99af1f | ||
![]() |
be0d17e812 | ||
![]() |
4eb35406f4 | ||
![]() |
624745ab20 | ||
![]() |
9354822e09 | ||
![]() |
17d4f9513e | ||
![]() |
f830d77307 | ||
![]() |
a03c76b228 | ||
![]() |
35ad61429d | ||
![]() |
b5b3d9e5c7 | ||
![]() |
6e682c2b01 | ||
![]() |
7e2ea2ece0 | ||
![]() |
01926d66d7 | ||
![]() |
69f7d0a0ce | ||
![]() |
d1c84705ec | ||
![]() |
3274908551 | ||
![]() |
c730934498 | ||
![]() |
471a8b223b | ||
![]() |
47ee9202c3 | ||
![]() |
1bcbe89802 | ||
![]() |
bf57e9bb12 | ||
![]() |
318a7584f3 | ||
![]() |
961ec228d4 | ||
![]() |
a777eb3d81 | ||
![]() |
7f79b52dae | ||
![]() |
db680edc26 | ||
![]() |
e6ce80458f | ||
![]() |
cdcb123aa8 | ||
![]() |
78081a1652 | ||
![]() |
7408976b15 | ||
![]() |
763bb73cc3 | ||
![]() |
1dee2cd55e | ||
![]() |
426ecfd136 | ||
![]() |
4913baed16 | ||
![]() |
675f6a8901 | ||
![]() |
2147284cad | ||
![]() |
7f1870da5f | ||
![]() |
2149a095f7 | ||
![]() |
e8d21adbaa | ||
![]() |
fa28531322 | ||
![]() |
deef85ca9a | ||
![]() |
4f4427ff41 | ||
![]() |
0ed285e84d | ||
![]() |
905ca77c9e | ||
![]() |
61043c7e74 | ||
![]() |
4545c9f22f | ||
![]() |
ad772d7b48 | ||
![]() |
a56ef92729 | ||
![]() |
561d01c450 | ||
![]() |
c6c8a30da1 | ||
![]() |
914dbeb12c | ||
![]() |
56dc90eaab | ||
![]() |
f51c567de3 | ||
![]() |
9b2acca63e | ||
![]() |
afcd9f1b1c | ||
![]() |
755ccbc468 | ||
![]() |
0af7aec211 | ||
![]() |
ee085ad6bd |
287
CHANGES
287
CHANGES
@@ -6,6 +6,293 @@
|
||||
|
||||
Changelog
|
||||
|
||||
Version 7.16.1 (29 January 2007)
|
||||
|
||||
Daniel (29 January 2007)
|
||||
- Michael Wallner reported that when doing a CONNECT with a custom User-Agent
|
||||
header, you got _two_ User-Agent headers in the CONNECT request...! Added
|
||||
test case 287 to verify the fix.
|
||||
|
||||
Daniel (28 January 2007)
|
||||
- curl_easy_reset() now resets the CA bundle path correctly.
|
||||
|
||||
- David McCreedy fixed the Curl command line tool for HTTP on non-ASCII
|
||||
platforms.
|
||||
|
||||
Daniel (25 January 2007)
|
||||
- Added the --libcurl [file] option to curl. Append this option to any
|
||||
ordinary curl command line, and you will get a libcurl-using source code
|
||||
written to the file that does the equivalent operation of what your command
|
||||
line operation does!
|
||||
|
||||
Dan F (24 January 2007)
|
||||
- Fixed a dangling pointer problem that prevented the http_proxy environment
|
||||
variable from being properly used in many cases (and caused test case 63
|
||||
to fail).
|
||||
|
||||
Daniel (23 January 2007)
|
||||
- David McCreedy did NTLM changes mainly for non-ASCII platforms:
|
||||
|
||||
#1
|
||||
There's a compilation error in http_ntlm.c if USE_NTLM2SESSION is NOT
|
||||
defined. I noticed this while testing various configurations. Line 867 of
|
||||
the current http_ntlm.c is a closing bracket for an if/else pair that only
|
||||
gets compiled in if USE_NTLM2SESSION is defined. But this closing bracket
|
||||
wasn't in an #ifdef so the code fails to compile unless USE_NTLM2SESSION was
|
||||
defined. Lines 198 and 140 of my patch wraps that closing bracket in an
|
||||
#ifdef USE_NTLM2SESSION.
|
||||
|
||||
#2
|
||||
I noticed several picky compiler warnings when DEBUG_ME is defined. I've
|
||||
fixed them with casting. By the way, DEBUG_ME was a huge help in
|
||||
understanding this code.
|
||||
|
||||
#3
|
||||
Hopefully the last non-ASCII conversion patch for libcurl in a while. I
|
||||
changed the "NTLMSSP" literal to hex since this signature must always be in
|
||||
ASCII.
|
||||
|
||||
Conversion code was strategically added where necessary. And the
|
||||
Curl_base64_encode calls were changed so the binary "blobs" http_ntlm.c
|
||||
creates are NOT translated on non-ASCII platforms.
|
||||
|
||||
Dan F (22 January 2007)
|
||||
- Converted (most of) the test data files into genuine XML. A handful still
|
||||
are not, due mainly to the lack of support for XML character entities
|
||||
(e.g. & => & ). This will make it easier to validate test files using
|
||||
tools like xmllint, as well as to edit and view them using XML tools.
|
||||
|
||||
Daniel (16 January 2007)
|
||||
- Armel Asselin improved libcurl to behave a lot better when an easy handle
|
||||
doing an FTP transfer is removed from a multi handle before completion. The
|
||||
fix also fixed the "alive counter" to be correct on "premature removal" for
|
||||
all protocols.
|
||||
|
||||
Dan F (16 January 2007)
|
||||
- Fixed a small memory leak in tftp uploads discovered by curl's memory leak
|
||||
detector. Also changed tftp downloads to URL-unescape the downloaded
|
||||
file name.
|
||||
|
||||
Daniel (14 January 2007)
|
||||
- David McCreedy provided libcurl changes for doing HTTP communication on
|
||||
non-ASCII platforms. It does add some complexity, most notably with more
|
||||
#ifdefs, but I want to see this supported added and I can't see how we can
|
||||
add it without the extra stuff added.
|
||||
|
||||
- Setting CURLOPT_COOKIELIST to "ALL" when no cookies at all was present,
|
||||
libcurl would crash when trying to read a NULL pointer.
|
||||
|
||||
Daniel (12 January 2007)
|
||||
- Toby Peterson found a nasty bug that prevented (lib)curl from properly
|
||||
downloading (most) things that were larger than 4GB on 32 bit systems. Matt
|
||||
Witherspoon helped as narrow down the problem.
|
||||
|
||||
Daniel (5 January 2007)
|
||||
- Linus Nielsen Feltzing introduced the --ftp-ssl-ccc command line option to
|
||||
curl that uses the new CURLOPT_FTP_SSL_CCC option in libcurl. If enabled, it
|
||||
will make libcurl shutdown SSL/TLS after the authentication is done on a
|
||||
FTP-SSL operation.
|
||||
|
||||
Daniel (4 January 2007)
|
||||
- David McCreedy made changes to allow base64 encoding/decoding to work on
|
||||
non-ASCII platforms.
|
||||
|
||||
Daniel (3 January 2007)
|
||||
- Matt Witherspoon fixed the flaw which made libcurl 7.16.0 always store
|
||||
downloaded data in two buffers, just to be able to deal with a special HTTP
|
||||
pipelining case. That is now only activated for pipelined transfers. In
|
||||
Matt's case, it showed as a considerable performance difference,
|
||||
|
||||
Daniel (2 January 2007)
|
||||
- Victor Snezhko helped us fix bug report #1603712
|
||||
(http://curl.haxx.se/bug/view.cgi?id=1603712) (known bug #36) --limit-rate
|
||||
(CURLOPT_MAX_SEND_SPEED_LARGE and CURLOPT_MAX_RECV_SPEED_LARGE) are broken
|
||||
on Windows (since 7.16.0, but that's when they were introduced as previous
|
||||
to that the limiting logic was made in the application only and not in the
|
||||
library). It was actually also broken on select()-based systems (as apposed
|
||||
to poll()) but we haven't had any such reports. We now use select(), Sleep()
|
||||
or delay() properly to sleep a while without waiting for anything input or
|
||||
output when the rate limiting is activated with the easy interface.
|
||||
|
||||
- Modified libcurl.pc.in to use Libs.private for the libs libcurl itself needs
|
||||
to get built static. It has been mentioned before and was again brought to
|
||||
our attention by Nathanael Nerode who filed debian bug report #405226
|
||||
(http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=405226).
|
||||
|
||||
Daniel (29 December 2006)
|
||||
- Make curl_easy_duphandle() set the magic number in the new handle.
|
||||
|
||||
Daniel (22 December 2006)
|
||||
- Robert Foreman provided a prime example snippet showing how libcurl would
|
||||
get confused and not acknowledge the 'no_proxy' variable properly once it
|
||||
had used the proxy and you re-used the same easy handle. I made sure the
|
||||
proxy name is properly stored in the connect struct rather than the
|
||||
sessionhandle/easy struct.
|
||||
|
||||
- David McCreedy fixed a bad call to getsockname() that wrongly used a size_t
|
||||
variable to point to when it should be a socklen_t.
|
||||
|
||||
- When setting a proxy with environment variables and (for example) running
|
||||
'curl [URL]' with a URL without a protocol prefix, curl would not send a
|
||||
correct request as it failed to add the protocol prefix.
|
||||
|
||||
Daniel (21 December 2006)
|
||||
- Robson Braga Araujo reported bug #1618359
|
||||
(http://curl.haxx.se/bug/view.cgi?id=1618359) and subsequently provided a
|
||||
patch for it: when downloading 2 zero byte files in a row, curl 7.16.0
|
||||
enters an infinite loop, while curl 7.16.1-20061218 does one additional
|
||||
unnecessary request.
|
||||
|
||||
Fix: During the "Major overhaul introducing http pipelining support and
|
||||
shared connection cache within the multi handle." change, headerbytecount
|
||||
was moved to live in the Curl_transfer_keeper structure. But that structure
|
||||
is reset in the Transfer method, losing the information that we had about
|
||||
the header size. This patch moves it back to the connectdata struct.
|
||||
|
||||
Daniel (16 December 2006)
|
||||
- Brendan Jurd provided a fix that now prevents libcurl from getting a SIGPIPE
|
||||
during certain conditions when GnuTLS is used.
|
||||
|
||||
Daniel (11 December 2006)
|
||||
- Alexey Simak found out that when doing FTP with the multi interface and
|
||||
something went wrong like it got a bad response code back from the server,
|
||||
libcurl would leak memory. Added test case 538 to verify the fix.
|
||||
|
||||
I also noted that the connection would get cached in that case, which
|
||||
doesn't make sense since it cannot be re-use when the authentication has
|
||||
failed. I fixed that issue too at the same time, and also that the path
|
||||
would be "remembered" in vain for cases where the connection was about to
|
||||
get closed.
|
||||
|
||||
Daniel (6 December 2006)
|
||||
- Sebastien Willemijns reported bug #1603712
|
||||
(http://curl.haxx.se/bug/view.cgi?id=1603712) which is about connections
|
||||
getting cut off prematurely when --limit-rate is used. While I found no such
|
||||
problems in my tests nor in my reading of the code, I found that the
|
||||
--limit-rate code was severly flawed (since it was moved into the lib, since
|
||||
7.15.5) when used with the easy interface and it didn't work as documented
|
||||
so I reworked it somewhat and now it works for my tests.
|
||||
|
||||
Daniel (5 December 2006)
|
||||
- Stefan Krause pointed out a compiler warning with a picky MSCV compiler when
|
||||
passing a curl_off_t argument to the Curl_read_rewind() function which takes
|
||||
an size_t argument. Curl_read_rewind() also had debug code left in it and it
|
||||
was put in a different source file with no good reason when only used from
|
||||
one single spot.
|
||||
|
||||
- Sh Diao reported that CURLOPT_CLOSEPOLICY doesn't work, and indeed, there is
|
||||
no code present in the library that receives the option. Since it was not
|
||||
possible to use, we know that no current users exist and thus we simply
|
||||
removed it from the docs and made the code always use the default path of
|
||||
the code.
|
||||
|
||||
- Jared Lundell filed bug report #1604956
|
||||
(http://curl.haxx.se/bug/view.cgi?id=1604956) which identified setting
|
||||
CURLOPT_MAXCONNECTS to zero caused libcurl to SIGSEGV. Starting now, libcurl
|
||||
will always internally use no less than 1 entry in the connection cache.
|
||||
|
||||
- Sh Diao reported that CURLOPT_FORBID_REUSE no works, and indeed it broke in
|
||||
the 7.16.0 release.
|
||||
|
||||
- Martin Skinner brought back bug report #1230118 to haunt us once again.
|
||||
(http://curl.haxx.se/bug/view.cgi?id=1230118) curl_getdate() did not work
|
||||
properly for all input dates on Windows. It was mostly seen on some TZ time
|
||||
zones using DST. Luckily, Martin also provided a fix.
|
||||
|
||||
- Alexey Simak filed bug report #1600447
|
||||
(http://curl.haxx.se/bug/view.cgi?id=1600447) in which he noted that active
|
||||
FTP connections don't work with the multi interface. The problem is here
|
||||
that the multi interface state machine has a state during which it can wait
|
||||
for the data connection to connect, but the active connection is not done in
|
||||
the same step in the sequence as the passive one is so it doesn't quite work
|
||||
for active. The active FTP code still use a blocking function to allow the
|
||||
remote server to connect.
|
||||
|
||||
The fix (work-around is a better word) for this problem is to set the
|
||||
boolean prematurely that the data connection is completed, so that the "wait
|
||||
for connect" phase ends at once.
|
||||
|
||||
The proper fix, left for the future, is of course to make the active FTP
|
||||
case to act in a non-blocking way too.
|
||||
|
||||
- Matt Witherspoon fixed a problem case when the CPU load went to 100% when a
|
||||
HTTP upload was disconnected:
|
||||
|
||||
"What appears to be happening is that my system (Linux 2.6.17 and 2.6.13) is
|
||||
setting *only* POLLHUP on poll() when the conditions in my previous mail
|
||||
occur. As you can see, select.c:Curl_select() does not check for POLLHUP. So
|
||||
basically what was happening, is poll() was returning immediately (with
|
||||
POLLHUP set), but when Curl_select() looked at the bits, neither POLLERR or
|
||||
POLLOUT was set. This still caused Curl_readwrite() to be called, which
|
||||
quickly returned. Then the transfer() loop kept continuing at full speed
|
||||
forever."
|
||||
|
||||
Daniel (1 December 2006)
|
||||
- Toon Verwaest reported that there are servers that send the Content-Range:
|
||||
header in a third, not suppported by libcurl, format and we agreed that we
|
||||
could make the parser more forgiving to accept all the three found
|
||||
variations.
|
||||
|
||||
Daniel (25 November 2006)
|
||||
- Venkat Akella found out that libcurl did not like HTTP responses that simply
|
||||
responded with a single status line and no headers nor body. Starting now, a
|
||||
HTTP response on a persistent connection (i.e not set to be closed after the
|
||||
response has been taken care of) must have Content-Length or chunked
|
||||
encoding set, or libcurl will simply assume that there is no body.
|
||||
|
||||
To my horror I learned that we had no less than 57(!) test cases that did bad
|
||||
HTTP responses like this, and even the test http server (sws) responded badly
|
||||
when queried by the test system if it is the test system. So although the
|
||||
actual fix for the problem was tiny, going through all the newly failing test
|
||||
cases got really painful and boring.
|
||||
|
||||
Daniel (24 November 2006)
|
||||
- James Housley did lots of work and introduced SFTP downloads.
|
||||
|
||||
Daniel (13 November 2006)
|
||||
- Ron in bug #1595348 (http://curl.haxx.se/bug/view.cgi?id=1595348) pointed
|
||||
out a stack overwrite (and the corresponding fix) on 64bit Windows when
|
||||
dealing with HTTP chunked encoding.
|
||||
|
||||
Daniel (9 November 2006)
|
||||
- Nir Soffer updated libcurl.framework.make:
|
||||
o fix symlinks, should link to Versions, not to ./Versions
|
||||
o indentation improvments
|
||||
|
||||
- Dmitriy Sergeyev found a SIGSEGV with his test04.c example posted on 7 Nov
|
||||
2006. It turned out we wrongly assumed that the connection cache was present
|
||||
when tearing down a connection.
|
||||
|
||||
- Ciprian Badescu found a SIGSEGV when doing multiple TFTP transfers using the
|
||||
multi interface, but I could also repeat it doing multiple sequential ones
|
||||
with the easy interface. Using Ciprian's test case, I could fix it.
|
||||
|
||||
Daniel (8 November 2006)
|
||||
- Bradford Bruce reported that when setting CURLOPT_DEBUGFUNCTION without
|
||||
CURLOPT_VERBOSE set to non-zero, you still got a few debug messages from the
|
||||
SSL handshake. This is now stopped.
|
||||
|
||||
Daniel (7 November 2006)
|
||||
- Olaf fixed a leftover problem with the CONNECT fix of his that would leave a
|
||||
wrong error message in the error message buffer.
|
||||
|
||||
Daniel (3 November 2006)
|
||||
- Olaf Stueben provided a patch that I edited slightly. It fixes the notorious
|
||||
KNOWN_BUGS #25, which happens when a proxy closes the connection when
|
||||
libcurl has sent CONNECT, as part of an authentication negotiation. Starting
|
||||
now, libcurl will re-connect accordingly and continue the authentication as
|
||||
it should.
|
||||
|
||||
Daniel (2 November 2006)
|
||||
- James Housley brought support for SCP transfers, based on the libssh2 library
|
||||
for the actual network protocol stuff.
|
||||
|
||||
Added these new curl_easy_setopt() options:
|
||||
|
||||
CURLOPT_SSH_AUTH_TYPES
|
||||
CURLOPT_SSH_PUBLIC_KEYFILE
|
||||
CURLOPT_SSH_PRIVATE_KEYFILE
|
||||
|
||||
Version 7.16.0 (30 October 2006)
|
||||
|
||||
Daniel (25 October 2006)
|
||||
|
2
COPYING
2
COPYING
@@ -1,6 +1,6 @@
|
||||
COPYRIGHT AND PERMISSION NOTICE
|
||||
|
||||
Copyright (c) 1996 - 2006, Daniel Stenberg, <daniel@haxx.se>.
|
||||
Copyright (c) 1996 - 2007, Daniel Stenberg, <daniel@haxx.se>.
|
||||
|
||||
All rights reserved.
|
||||
|
||||
|
@@ -5,7 +5,7 @@
|
||||
# | (__| |_| | _ <| |___
|
||||
# \___|\___/|_| \_\_____|
|
||||
#
|
||||
# Copyright (C) 1998 - 2005, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
# Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
#
|
||||
# This software is licensed as described in the file COPYING, which
|
||||
# you should have received as part of this distribution. The terms
|
||||
@@ -73,6 +73,14 @@ mingw32-ssl:
|
||||
$(MAKE) -C lib -f Makefile.m32 SSL=1 ZLIB=1
|
||||
$(MAKE) -C src -f Makefile.m32 SSL=1 ZLIB=1
|
||||
|
||||
mingw32-ssh2-ssl:
|
||||
$(MAKE) -C lib -f Makefile.m32 SSH2=1 SSL=1 ZLIB=1
|
||||
$(MAKE) -C src -f Makefile.m32 SSH2=1 SSL=1 ZLIB=1
|
||||
|
||||
mingw32-ssh2-ssl-sspi:
|
||||
$(MAKE) -C lib -f Makefile.m32 SSH2=1 SSL=1 SSPI=1 ZLIB=1
|
||||
$(MAKE) -C src -f Makefile.m32 SSH2=1 SSL=1 SSPI=1 ZLIB=1
|
||||
|
||||
mingw32-clean:
|
||||
$(MAKE) -C lib -f Makefile.m32 clean
|
||||
$(MAKE) -C src -f Makefile.m32 clean
|
||||
@@ -212,6 +220,10 @@ netware-ssl-zlib:
|
||||
$(MAKE) -C lib -f Makefile.netware WITH_SSL=1 WITH_ZLIB=1
|
||||
$(MAKE) -C src -f Makefile.netware WITH_SSL=1 WITH_ZLIB=1
|
||||
|
||||
netware-ssh2-ssl-zlib:
|
||||
$(MAKE) -C lib -f Makefile.netware WITH_SSH2=1 WITH_SSL=1 WITH_ZLIB=1
|
||||
$(MAKE) -C src -f Makefile.netware WITH_SSH2=1 WITH_SSL=1 WITH_ZLIB=1
|
||||
|
||||
netware-zlib:
|
||||
$(MAKE) -C lib -f Makefile.netware WITH_ZLIB=1
|
||||
$(MAKE) -C src -f Makefile.netware WITH_ZLIB=1
|
||||
|
124
RELEASE-NOTES
124
RELEASE-NOTES
@@ -1,80 +1,86 @@
|
||||
Curl and libcurl 7.16.0
|
||||
Curl and libcurl 7.16.1
|
||||
|
||||
Public curl release number: 96
|
||||
Releases counted from the very beginning: 123
|
||||
Available command line options: 112
|
||||
Available curl_easy_setopt() options: 133
|
||||
Public curl release number: 97
|
||||
Releases counted from the very beginning: 124
|
||||
Available command line options: 115
|
||||
Available curl_easy_setopt() options: 137
|
||||
Number of public functions in libcurl: 54
|
||||
Amount of public web site mirrors: 37
|
||||
Amount of public web site mirrors: 39
|
||||
Number of known libcurl bindings: 35
|
||||
Number of contributors: 515
|
||||
Number of contributors: 539
|
||||
|
||||
This release includes the following changes:
|
||||
|
||||
o Added CURLE_SSL_CACERT_BADFILE
|
||||
o Added CURLMOPT_TIMERFUNCTION and CURLMOPT_TIMERDATA
|
||||
o (FTP) the CURLOPT_SOURCE_* options are removed and so are the --3p* command
|
||||
line options
|
||||
o curl_multi_socket() and family are suitable to start using
|
||||
o uses WSAPoll() on Windows Vista
|
||||
o (FTP) --ftp-ssl-control was added
|
||||
o CURLOPT_SSL_SESSIONID_CACHE and --no-sessionid added
|
||||
o CURLMOPT_PIPELINING added for enabling HTTP pipelined transfers
|
||||
o multi handles now have a shared connection cache
|
||||
o Added support for other MS-DOS compilers (besides djgpp)
|
||||
o CURLOPT_SOCKOPTFUNCTION and CURLOPT_SOCKOPTDATA were added
|
||||
o (FTP) libcurl avoids sending TYPE if the desired type was already set
|
||||
o (FTP) CURLOPT_PREQUOTE works even when CURLOPT_NOBODY is set true
|
||||
o Support for SCP and SFTP were added (powered by libssh2)
|
||||
o CURLOPT_CLOSEPOLICY is now deprecated
|
||||
o --ftp-ssl-ccc and CURLOPT_FTP_SSL_CCC were added
|
||||
o HTTP support for non-ASCII platforms
|
||||
o --libcurl was added
|
||||
|
||||
This release includes the following bugfixes:
|
||||
|
||||
o (HTTP) CURLOPT_FAILONERROR (curl -f) covers a few more reponse cases
|
||||
o curl_multi_socket() and the LOW_SPEED options
|
||||
o curl_multi_socket() expire timer during c-ares name resolves
|
||||
o curl_multi_add_handle on an already added handle now fails gracefully
|
||||
o multi interface crash if bad function call order was used for cleanup
|
||||
o put a new URL in saved cookie jar files
|
||||
o configure --with-gssapi-libs
|
||||
o SOCKS proxy connection fixes
|
||||
o (FTP) a failed upload does not invalidate the control connection
|
||||
o proxy URL with user name and empty password or no password at all now work
|
||||
o fixed a socket state problem with *multi_socket()
|
||||
o (HTTP) NTLM hostname fix
|
||||
o getsockname usage fixes
|
||||
o SOCKS5 proxy connects can now time-out
|
||||
o SOCKS5 connects that require auth no longer segfaults when auth not given
|
||||
o multi interface using asynch resolves could get stuck in wrong state
|
||||
o the 'running_handles' counter wasn't always updated properly when
|
||||
curl_multi_remove_handle() was used
|
||||
o (FTP) EPRT transfers with IPv6 didn't work properly
|
||||
o (FTP) SINGLECWD mode and using files in the root dir
|
||||
o (HTTP) Expect: header disabling work better
|
||||
o (HTTP) "Expect: 100-continue" disable on second POST on re-used connection
|
||||
o src/config.h.in is fixed
|
||||
o (HTTP) POST data logged to the debug callback function is now correctly
|
||||
tagged as data, not header
|
||||
o proxy close during CONNECT authentication is now dealt with nicely
|
||||
o the CURLOPT_DEBUGFUNCTION was sometimes called even when CURLOPT_VERBOSE
|
||||
was not enabled
|
||||
o multiple TFTP transfers on the same (easy or multi) handle could cause a
|
||||
crash
|
||||
o SIGSEGV when disconnecting on a transfer on a re-used handle when the
|
||||
host name didn't resolve
|
||||
o stack overwrite on 64bit Windows in the chunked decoding department
|
||||
o HTTP responses on persistent connections without Content-Length nor chunked
|
||||
encoding are now considered to be without response body
|
||||
o Content-Range: header parsing improved
|
||||
o CPU 100% load when HTTP upload connection broke
|
||||
o active FTP didn't work with multi interface
|
||||
o curl_getdate() could be off one hour for TZ time zones with DST, on windows
|
||||
o CURLOPT_FORBID_REUSE works again
|
||||
o CURLOPT_MAXCONNECTS set to zero caused libcurl to SIGSEGV
|
||||
o rate limiting works better
|
||||
o getting FTP response code errors when using the multi-interface caused
|
||||
libcurl to leak memory
|
||||
o no more SIGPIPE when GnuTLS is used
|
||||
o FTP downloading 2 zero byte files in a row
|
||||
o using proxy and URLs without protocol prefixes
|
||||
o first using a proxy and then accessing a site that 'no_proxy' matched,
|
||||
would still make libcurl use the proxy...
|
||||
o curl_easy_duphandle() now makes a handle that is valid for the multi
|
||||
interface since the magic number is set fine
|
||||
o libcurl.pc now uses Libs.private for "private" libs
|
||||
o --limit-rate (CURLOPT_MAX_SEND_SPEED_LARGE and CURLOPT_MAX_RECV_SPEED_LARGE)
|
||||
now work on windows again
|
||||
o improved download performance by avoiding the unconditional "double copying"
|
||||
o base64 encoding/decoding works on non-ASCII platforms
|
||||
o large file downloads
|
||||
o CURLOPT_COOKIELIST set to "ALL" crash
|
||||
o easy handle removal from multi handle before completion
|
||||
o TFTP upload memory leak
|
||||
o curl_easy_reset() now resets the CA bundle path correctly
|
||||
o two User-Agent headers in CONNECT requests with custom User-Agent
|
||||
|
||||
This release includes the following known bugs:
|
||||
|
||||
o see docs/KNOWN_BUGS (http://curl.haxx.se/docs/knownbugs.html)
|
||||
|
||||
Other curl-related news:
|
||||
|
||||
o a Smalltalk binding: http://curl.haxx.se/libcurl/smalltalk/
|
||||
o pycurl-7.15.5 was released: http://pycurl.sf.net
|
||||
o TclCurl 7.16.0 was released:
|
||||
http://personal1.iddeo.es/andresgarci/tclcurl/english/
|
||||
o Curb - Libcurl bindings for Ruby: http://curb.rubyforge.org/
|
||||
|
||||
New curl mirrors:
|
||||
|
||||
o http://curl.geosdreams.info/ is a new Polish mirror
|
||||
o http://curl.gfiles.org/ is a new Russian mirror
|
||||
o http://curl.online-mirror.de/ is a new German mirror
|
||||
o http://curl.blogvoid.com/ is a new Canadian mirror
|
||||
o http://curl.internet.bs/ is a new United Kingdom mirror
|
||||
o http://curl2.haxx.se/ is a new Swedish mirror
|
||||
o curl.miroir-francais.fr is a new French web mirror
|
||||
o curl.dsmirror.nl is a new Dutch web mirror
|
||||
|
||||
This release would not have looked like this without help, code, reports and
|
||||
advice from friends like these:
|
||||
|
||||
Domenico Andreoli, Armel Asselin, Gisle Vanem, Yang Tse, Andrew Biggs,
|
||||
Peter Sylvester, David McCreedy, Dmitriy Sergeyev, Dmitry Rechkin,
|
||||
Jari Sundell, Ravi Pratap, Michele Bini, Jeff Pohlmeyer, Michael Wallner,
|
||||
Mike Protts, Cory Nelson, Bernard Leak, Bogdan Nicula, Dan Fandrich,
|
||||
Nir Soffer
|
||||
James Housley, Olaf Stueben, Yang Tse, Gisle Vanem, Bradford Bruce,
|
||||
Ciprian Badescu, Dmitriy Sergeyev, Nir Soffer, Venkat Akella, Toon Verwaest,
|
||||
Matt Witherspoon, Alexey Simak, Martin Skinner, Sh Diao, Jared Lundell,
|
||||
Stefan Krause, Sebastien Willemijns, Alexey Simak, Brendan Jurd,
|
||||
Robson Braga Araujo, David McCreedy, Robert Foreman, Nathanael Nerode,
|
||||
Victor Snezhko, Linus Nielsen Feltzing, Toby Peterson, Dan Fandrich,
|
||||
Armel Asselin, Michael Wallner, Guenter Knauf
|
||||
|
||||
Thanks! (and sorry if I forgot to mention someone)
|
||||
|
@@ -1,6 +1,4 @@
|
||||
To get fixed in 7.16.0 (planned release: October 2006)
|
||||
To get fixed in 7.16.1 (planned release: January 2007)
|
||||
======================
|
||||
|
||||
67 - Jeff Pohlmeyer's crashing pipelining test case
|
||||
|
||||
69 -
|
||||
82 -
|
||||
|
42
acinclude.m4
42
acinclude.m4
@@ -1035,6 +1035,48 @@ AC_DEFUN([CURL_CHECK_STRUCT_TIMEVAL], [
|
||||
]) # AC_DEFUN
|
||||
|
||||
|
||||
dnl TYPE_SIG_ATOMIC_T
|
||||
dnl -------------------------------------------------
|
||||
dnl Check if the sig_atomic_t type is available, and
|
||||
dnl verify if it is already defined as volatile.
|
||||
|
||||
AC_DEFUN([TYPE_SIG_ATOMIC_T], [
|
||||
AC_CHECK_HEADERS(signal.h)
|
||||
AC_CHECK_TYPE([sig_atomic_t],[
|
||||
AC_DEFINE(HAVE_SIG_ATOMIC_T, 1,
|
||||
[Define to 1 if sig_atomic_t is an available typedef.])
|
||||
], ,[
|
||||
#ifdef HAVE_SIGNAL_H
|
||||
#include <signal.h>
|
||||
#endif
|
||||
])
|
||||
case "$ac_cv_type_sig_atomic_t" in
|
||||
yes)
|
||||
#
|
||||
AC_MSG_CHECKING([if sig_atomic_t is already defined as volatile])
|
||||
AC_TRY_LINK([
|
||||
#ifdef HAVE_SIGNAL_H
|
||||
#include <signal.h>
|
||||
#endif
|
||||
],[
|
||||
static volatile sig_atomic_t dummy = 0;
|
||||
],[
|
||||
AC_MSG_RESULT([no])
|
||||
ac_cv_sig_atomic_t_volatile="no"
|
||||
],[
|
||||
AC_MSG_RESULT([yes])
|
||||
ac_cv_sig_atomic_t_volatile="yes"
|
||||
])
|
||||
#
|
||||
if test "$ac_cv_sig_atomic_t_volatile" = "yes"; then
|
||||
AC_DEFINE(HAVE_SIG_ATOMIC_T_VOLATILE, 1,
|
||||
[Define to 1 if sig_atomic_t is already defined as volatile.])
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
]) # AC_DEFUN
|
||||
|
||||
|
||||
dnl CURL_CHECK_NONBLOCKING_SOCKET
|
||||
dnl -------------------------------------------------
|
||||
dnl Check for how to set a socket to non-blocking state. There seems to exist
|
||||
|
@@ -14,3 +14,9 @@ Henrik Stoerner
|
||||
Yang Tse
|
||||
Nick Mathewson
|
||||
Alexander Lazic
|
||||
Andreas Rieke
|
||||
Guilherme Balena Versiani
|
||||
Brad Spencer
|
||||
Ravi Pratap
|
||||
William Ahern
|
||||
Bram Matthys
|
||||
|
18
ares/CHANGES
18
ares/CHANGES
@@ -1,5 +1,23 @@
|
||||
Changelog for the c-ares project
|
||||
|
||||
* November 22
|
||||
|
||||
- Install ares_dns.h too
|
||||
|
||||
- Michael Wallner fixed this problem: When I set domains in the options
|
||||
struct, and there are domain/search entries in /etc/resolv.conf, the domains
|
||||
of the options struct will be overridden.
|
||||
|
||||
* November 6
|
||||
|
||||
- Yang Tse removed a couple of potential zero size memory allocations.
|
||||
|
||||
- Andreas Rieke fixed the line endings in the areslib.dsp file that I (Daniel)
|
||||
broke in the 1.3.2 release. We should switch to a system where that file is
|
||||
auto-generated. We could rip some code for that from curl...
|
||||
|
||||
Version 1.3.2 (November 3, 2006)
|
||||
|
||||
* October 12 2006
|
||||
|
||||
- Prevent ares_getsock() to overflow if more than 16 sockets are used.
|
||||
|
@@ -59,7 +59,7 @@ libcares_la_SOURCES = $(CSOURCES) $(HHEADERS)
|
||||
# where to install the c-ares headers
|
||||
libcares_ladir = $(includedir)
|
||||
# what headers to install on 'make install':
|
||||
libcares_la_HEADERS = ares.h ares_version.h
|
||||
libcares_la_HEADERS = ares.h ares_version.h ares_dns.h
|
||||
|
||||
# Make files named *.dist replace the file without .dist extension
|
||||
dist-hook:
|
||||
|
186
ares/Makefile.dj
186
ares/Makefile.dj
@@ -2,34 +2,50 @@
|
||||
# c-ares Makefile for djgpp/gcc/Watt-32.
|
||||
# By Gisle Vanem <giva@bgnett.no> 2004.
|
||||
#
|
||||
.SUFFIXES: .exe
|
||||
# $Id$
|
||||
|
||||
include ../packages/DOS/common.dj
|
||||
|
||||
include Makefile.inc
|
||||
|
||||
WATT32_ROOT = $(subst \,/,$(WATT_ROOT))
|
||||
|
||||
CC = gcc
|
||||
CFLAGS = -O2 -Wall -DWATT32 -Dselect=select_s -DHAVE_AF_INET6 \
|
||||
-DHAVE_PF_INET6 -DHAVE_IOCTLSOCKET -DHAVE_STRUCT_IN6_ADDR \
|
||||
-DHAVE_STRUCT_SOCKADDR_IN6 -DHAVE_STRUCT_ADDRINFO \
|
||||
-DHAVE_ARPA_NAMESER_H -DNS_INADDRSZ=4 \
|
||||
-DHAVE_SYS_TIME_H -DHAVE_TIME_H \
|
||||
-DTIME_WITH_SYS_TIME -DHAVE_STRUCT_TIMEVAL \
|
||||
-DHAVE_SOCKADDR_IN6_SIN6_SCOPE_ID -I$(WATT32_ROOT)/inc
|
||||
CFLAGS += -DWATT32 -DHAVE_AF_INET6 -DHAVE_PF_INET6 -DHAVE_FIONBIO \
|
||||
-DHAVE_STRUCT_IN6_ADDR -DHAVE_SOCKADDR_IN6_SIN6_SCOPE_ID \
|
||||
-DHAVE_SYS_TIME_H -DHAVE_STRUCT_SOCKADDR_IN6 -DHAVE_STRUCT_ADDRINFO \
|
||||
-DHAVE_SIGNAL_H -DHAVE_SIG_ATOMIC_T -DRETSIGTYPE='void' \
|
||||
-DHAVE_ARPA_NAMESER_H -DNS_INADDRSZ=4 -DHAVE_RECV -DHAVE_SEND \
|
||||
-DSEND_TYPE_ARG1='int' -DSEND_QUAL_ARG2='const' \
|
||||
-DSEND_TYPE_ARG2='void*' -DSEND_TYPE_ARG3='int' \
|
||||
-DSEND_TYPE_ARG4='int' -DSEND_TYPE_RETV='int' \
|
||||
-DRECV_TYPE_ARG1='int' -DRECV_TYPE_ARG2='void*' \
|
||||
-DRECV_TYPE_ARG3='int' -DRECV_TYPE_ARG4='int' \
|
||||
-DRECV_TYPE_RETV='int' -UHAVE_CONFIG_H -Dselect=select_s
|
||||
|
||||
LDFLAGS = -s
|
||||
EX_LIBS = $(WATT32_ROOT)/lib/libwatt.a
|
||||
|
||||
OBJ_DIR = djgpp
|
||||
ifeq ($(USE_DEBUG),1)
|
||||
EX_LIBS = ../lib/libcurl.a
|
||||
endif
|
||||
|
||||
ifeq ($(USE_SSL),1)
|
||||
EX_LIBS += $(OPENSSL_ROOT)/lib/libssl.a $(OPENSSL_ROOT)/lib/libcrypt.a
|
||||
endif
|
||||
|
||||
ifeq ($(USE_ZLIB),1)
|
||||
EX_LIBS += $(ZLIB_ROOT)/libz.a
|
||||
CFLAGS += -DUSE_MANUAL
|
||||
endif
|
||||
|
||||
ifeq ($(USE_IDNA),1)
|
||||
EX_LIBS += $(LIBIDN_ROOT)/lib/dj_obj/libidn.a -liconv
|
||||
endif
|
||||
|
||||
EX_LIBS += $(WATT32_ROOT)/lib/libwatt.a
|
||||
|
||||
OBJECTS = $(addprefix $(OBJ_DIR)/, $(CSOURCES:.c=.o))
|
||||
|
||||
all: $(OBJ_DIR) libcares.a ahost.exe adig.exe
|
||||
@echo Welcome to c-ares.
|
||||
|
||||
$(OBJ_DIR):
|
||||
- mkdir $(OBJ_DIR)
|
||||
|
||||
libcares.a: $(OBJECTS)
|
||||
ar rs $@ $?
|
||||
|
||||
@@ -46,12 +62,132 @@ vclean realclean: clean
|
||||
rm -f ahost.exe adig.exe depend.dj
|
||||
- rmdir $(OBJ_DIR)
|
||||
|
||||
$(OBJ_DIR)/%.o: %.c
|
||||
$(CC) $(CFLAGS) -o $@ -c $<
|
||||
@echo
|
||||
|
||||
depend:
|
||||
$(CC) -MM $(CFLAGS) $(CSOURCES) | \
|
||||
sed -e 's/^\([a-zA-Z0-9_-]*\.o:\)/$$(OBJ_DIR)\/\1/' > depend.dj
|
||||
|
||||
-include depend.dj
|
||||
# DO NOT DELETE THIS LINE
|
||||
$(OBJ_DIR)/ares_fds.o: ares_fds.c setup.h setup_once.h ares.h ares_private.h \
|
||||
ares_ipv6.h ../lib/memdebug.h ../lib/setup.h \
|
||||
../include/curl/stdcheaders.h ../include/curl/curl.h \
|
||||
../include/curl/curlver.h ../include/curl/easy.h \
|
||||
../include/curl/multi.h ../include/curl/curl.h
|
||||
$(OBJ_DIR)/ares_getsock.o: ares_getsock.c setup.h setup_once.h ares.h ares_private.h \
|
||||
ares_ipv6.h ../lib/memdebug.h ../lib/setup.h \
|
||||
../include/curl/stdcheaders.h ../include/curl/curl.h \
|
||||
../include/curl/curlver.h ../include/curl/easy.h \
|
||||
../include/curl/multi.h ../include/curl/curl.h
|
||||
$(OBJ_DIR)/ares_process.o: ares_process.c setup.h setup_once.h ares.h ares_dns.h \
|
||||
ares_private.h ares_ipv6.h ../lib/memdebug.h ../lib/setup.h \
|
||||
../include/curl/stdcheaders.h ../include/curl/curl.h \
|
||||
../include/curl/curlver.h ../include/curl/easy.h \
|
||||
../include/curl/multi.h ../include/curl/curl.h
|
||||
$(OBJ_DIR)/ares_free_hostent.o: ares_free_hostent.c setup.h setup_once.h ares.h \
|
||||
ares_private.h ares_ipv6.h ../lib/memdebug.h ../lib/setup.h \
|
||||
../include/curl/stdcheaders.h ../include/curl/curl.h \
|
||||
../include/curl/curlver.h ../include/curl/easy.h \
|
||||
../include/curl/multi.h ../include/curl/curl.h
|
||||
$(OBJ_DIR)/ares_query.o: ares_query.c setup.h setup_once.h ares.h ares_dns.h \
|
||||
ares_private.h ares_ipv6.h ../lib/memdebug.h ../lib/setup.h \
|
||||
../include/curl/stdcheaders.h ../include/curl/curl.h \
|
||||
../include/curl/curlver.h ../include/curl/easy.h \
|
||||
../include/curl/multi.h ../include/curl/curl.h
|
||||
$(OBJ_DIR)/ares__close_sockets.o: ares__close_sockets.c setup.h setup_once.h ares.h \
|
||||
ares_private.h ares_ipv6.h ../lib/memdebug.h ../lib/setup.h \
|
||||
../include/curl/stdcheaders.h ../include/curl/curl.h \
|
||||
../include/curl/curlver.h ../include/curl/easy.h \
|
||||
../include/curl/multi.h ../include/curl/curl.h
|
||||
$(OBJ_DIR)/ares_free_string.o: ares_free_string.c setup.h setup_once.h ares.h \
|
||||
ares_private.h ares_ipv6.h ../lib/memdebug.h ../lib/setup.h \
|
||||
../include/curl/stdcheaders.h ../include/curl/curl.h \
|
||||
../include/curl/curlver.h ../include/curl/easy.h \
|
||||
../include/curl/multi.h ../include/curl/curl.h
|
||||
$(OBJ_DIR)/ares_search.o: ares_search.c setup.h setup_once.h ares.h ares_private.h \
|
||||
ares_ipv6.h ../lib/memdebug.h ../lib/setup.h \
|
||||
../include/curl/stdcheaders.h ../include/curl/curl.h \
|
||||
../include/curl/curlver.h ../include/curl/easy.h \
|
||||
../include/curl/multi.h ../include/curl/curl.h
|
||||
$(OBJ_DIR)/ares__get_hostent.o: ares__get_hostent.c setup.h setup_once.h ares.h \
|
||||
ares_private.h ares_ipv6.h ../lib/memdebug.h ../lib/setup.h \
|
||||
../include/curl/stdcheaders.h ../include/curl/curl.h \
|
||||
../include/curl/curlver.h ../include/curl/easy.h \
|
||||
../include/curl/multi.h ../include/curl/curl.h inet_net_pton.h
|
||||
$(OBJ_DIR)/ares_gethostbyaddr.o: ares_gethostbyaddr.c setup.h setup_once.h ares.h \
|
||||
ares_private.h ares_ipv6.h ../lib/memdebug.h ../lib/setup.h \
|
||||
../include/curl/stdcheaders.h ../include/curl/curl.h \
|
||||
../include/curl/curlver.h ../include/curl/easy.h \
|
||||
../include/curl/multi.h ../include/curl/curl.h inet_net_pton.h
|
||||
$(OBJ_DIR)/ares_send.o: ares_send.c setup.h setup_once.h ares.h ares_dns.h \
|
||||
ares_private.h ares_ipv6.h ../lib/memdebug.h ../lib/setup.h \
|
||||
../include/curl/stdcheaders.h ../include/curl/curl.h \
|
||||
../include/curl/curlver.h ../include/curl/easy.h \
|
||||
../include/curl/multi.h ../include/curl/curl.h
|
||||
$(OBJ_DIR)/ares__read_line.o: ares__read_line.c setup.h setup_once.h ares.h \
|
||||
ares_private.h ares_ipv6.h ../lib/memdebug.h ../lib/setup.h \
|
||||
../include/curl/stdcheaders.h ../include/curl/curl.h \
|
||||
../include/curl/curlver.h ../include/curl/easy.h \
|
||||
../include/curl/multi.h ../include/curl/curl.h
|
||||
$(OBJ_DIR)/ares_gethostbyname.o: ares_gethostbyname.c setup.h setup_once.h ares.h \
|
||||
ares_private.h ares_ipv6.h ../lib/memdebug.h ../lib/setup.h \
|
||||
../include/curl/stdcheaders.h ../include/curl/curl.h \
|
||||
../include/curl/curlver.h ../include/curl/easy.h \
|
||||
../include/curl/multi.h ../include/curl/curl.h inet_net_pton.h \
|
||||
bitncmp.h
|
||||
$(OBJ_DIR)/ares_strerror.o: ares_strerror.c setup.h setup_once.h ares.h
|
||||
$(OBJ_DIR)/ares_cancel.o: ares_cancel.c setup.h setup_once.h ares.h ares_private.h \
|
||||
ares_ipv6.h ../lib/memdebug.h ../lib/setup.h \
|
||||
../include/curl/stdcheaders.h ../include/curl/curl.h \
|
||||
../include/curl/curlver.h ../include/curl/easy.h \
|
||||
../include/curl/multi.h ../include/curl/curl.h
|
||||
$(OBJ_DIR)/ares_init.o: ares_init.c setup.h setup_once.h ares.h ares_private.h \
|
||||
ares_ipv6.h ../lib/memdebug.h ../lib/setup.h \
|
||||
../include/curl/stdcheaders.h ../include/curl/curl.h \
|
||||
../include/curl/curlver.h ../include/curl/easy.h \
|
||||
../include/curl/multi.h ../include/curl/curl.h inet_net_pton.h
|
||||
$(OBJ_DIR)/ares_timeout.o: ares_timeout.c setup.h setup_once.h ares.h ares_private.h \
|
||||
ares_ipv6.h ../lib/memdebug.h ../lib/setup.h \
|
||||
../include/curl/stdcheaders.h ../include/curl/curl.h \
|
||||
../include/curl/curlver.h ../include/curl/easy.h \
|
||||
../include/curl/multi.h ../include/curl/curl.h
|
||||
$(OBJ_DIR)/ares_destroy.o: ares_destroy.c setup.h setup_once.h ares.h ares_private.h \
|
||||
ares_ipv6.h ../lib/memdebug.h ../lib/setup.h \
|
||||
../include/curl/stdcheaders.h ../include/curl/curl.h \
|
||||
../include/curl/curlver.h ../include/curl/easy.h \
|
||||
../include/curl/multi.h ../include/curl/curl.h
|
||||
$(OBJ_DIR)/ares_mkquery.o: ares_mkquery.c setup.h setup_once.h ares.h ares_dns.h \
|
||||
ares_private.h ares_ipv6.h ../lib/memdebug.h ../lib/setup.h \
|
||||
../include/curl/stdcheaders.h ../include/curl/curl.h \
|
||||
../include/curl/curlver.h ../include/curl/easy.h \
|
||||
../include/curl/multi.h ../include/curl/curl.h
|
||||
$(OBJ_DIR)/ares_version.o: ares_version.c setup.h setup_once.h ares_version.h
|
||||
$(OBJ_DIR)/ares_expand_name.o: ares_expand_name.c setup.h setup_once.h ares.h \
|
||||
ares_private.h ares_ipv6.h ../lib/memdebug.h ../lib/setup.h \
|
||||
../include/curl/stdcheaders.h ../include/curl/curl.h \
|
||||
../include/curl/curlver.h ../include/curl/easy.h \
|
||||
../include/curl/multi.h ../include/curl/curl.h
|
||||
$(OBJ_DIR)/ares_parse_a_reply.o: ares_parse_a_reply.c setup.h setup_once.h ares.h \
|
||||
ares_dns.h ares_private.h ares_ipv6.h ../lib/memdebug.h ../lib/setup.h \
|
||||
../include/curl/stdcheaders.h ../include/curl/curl.h \
|
||||
../include/curl/curlver.h ../include/curl/easy.h \
|
||||
../include/curl/multi.h ../include/curl/curl.h
|
||||
$(OBJ_DIR)/windows_port.o: windows_port.c setup.h setup_once.h
|
||||
$(OBJ_DIR)/ares_expand_string.o: ares_expand_string.c setup.h setup_once.h ares.h \
|
||||
ares_private.h ares_ipv6.h ../lib/memdebug.h ../lib/setup.h \
|
||||
../include/curl/stdcheaders.h ../include/curl/curl.h \
|
||||
../include/curl/curlver.h ../include/curl/easy.h \
|
||||
../include/curl/multi.h ../include/curl/curl.h
|
||||
$(OBJ_DIR)/ares_parse_ptr_reply.o: ares_parse_ptr_reply.c setup.h setup_once.h \
|
||||
ares.h ares_dns.h ares_private.h ares_ipv6.h ../lib/memdebug.h \
|
||||
../lib/setup.h ../include/curl/stdcheaders.h ../include/curl/curl.h \
|
||||
../include/curl/curlver.h ../include/curl/easy.h \
|
||||
../include/curl/multi.h ../include/curl/curl.h
|
||||
$(OBJ_DIR)/ares_parse_aaaa_reply.o: ares_parse_aaaa_reply.c setup.h setup_once.h \
|
||||
ares.h ares_dns.h inet_net_pton.h ares_private.h ares_ipv6.h \
|
||||
../lib/memdebug.h ../lib/setup.h ../include/curl/stdcheaders.h \
|
||||
../include/curl/curl.h ../include/curl/curlver.h ../include/curl/easy.h \
|
||||
../include/curl/multi.h ../include/curl/curl.h
|
||||
$(OBJ_DIR)/ares_getnameinfo.o: ares_getnameinfo.c setup.h setup_once.h ares.h \
|
||||
ares_private.h ares_ipv6.h ../lib/memdebug.h ../lib/setup.h \
|
||||
../include/curl/stdcheaders.h ../include/curl/curl.h \
|
||||
../include/curl/curlver.h ../include/curl/easy.h \
|
||||
../include/curl/multi.h ../include/curl/curl.h inet_ntop.h
|
||||
$(OBJ_DIR)/inet_net_pton.o: inet_net_pton.c setup.h setup_once.h ares_ipv6.h \
|
||||
inet_net_pton.h
|
||||
$(OBJ_DIR)/bitncmp.o: bitncmp.c bitncmp.h
|
||||
$(OBJ_DIR)/inet_ntop.o: inet_ntop.c setup.h setup_once.h ares_ipv6.h inet_ntop.h
|
||||
|
@@ -20,7 +20,7 @@ endif
|
||||
TARGETS = adig.nlm ahost.nlm
|
||||
LTARGET = libcares.lib
|
||||
VERSION = $(LIBCARES_VERSION)
|
||||
COPYR = Copyright (C) 1996 - 2006, Daniel Stenberg, <daniel@haxx.se>
|
||||
COPYR = Copyright (C) 1996 - 2007, Daniel Stenberg, <daniel@haxx.se>
|
||||
DESCR = cURL $(subst .def,,$(notdir $@)) $(LIBCARES_VERSION_STR) - http://curl.haxx.se
|
||||
MTSAFE = YES
|
||||
STACK = 64000
|
||||
@@ -281,6 +281,8 @@ config.h: Makefile.netware
|
||||
@echo $(DL)#define HAVE_SEND 1$(DL) >> $@
|
||||
@echo $(DL)#define HAVE_SETJMP_H 1$(DL) >> $@
|
||||
@echo $(DL)#define HAVE_SIGNAL 1$(DL) >> $@
|
||||
@echo $(DL)#define HAVE_SIGNAL_H 1$(DL) >> $@
|
||||
@echo $(DL)#define HAVE_SIG_ATOMIC_T 1$(DL) >> $@
|
||||
@echo $(DL)#define HAVE_SOCKET 1$(DL) >> $@
|
||||
@echo $(DL)#define HAVE_STDINT_H 1$(DL) >> $@
|
||||
@echo $(DL)#define HAVE_STDLIB_H 1$(DL) >> $@
|
||||
|
@@ -121,8 +121,8 @@ $(DEF_FILE): $(OBJECTS) Makefile.VC6
|
||||
@echo ares_gettimeofday >> $@
|
||||
@echo ares_parse_aaaa_reply >> $@
|
||||
|
||||
ahost.exe: $(OBJ_DIR) $(OBJ_DIR)\ahost.obj cares_imp.lib
|
||||
link $(LDFLAGS) -out:$@ $(OBJ_DIR)\ahost.obj cares_imp.lib $(EX_LIBS)
|
||||
ahost.exe: $(OBJ_DIR) $(OBJ_DIR)\ahost.obj $(OBJ_DIR)\getopt.obj cares_imp.lib
|
||||
link $(LDFLAGS) -out:$@ $(OBJ_DIR)\ahost.obj $(OBJ_DIR)\getopt.obj cares_imp.lib $(EX_LIBS)
|
||||
|
||||
adig.exe: $(OBJ_DIR) $(OBJ_DIR)\adig.obj $(OBJ_DIR)\getopt.obj cares_imp.lib
|
||||
link $(LDFLAGS) -out:$@ $(OBJ_DIR)\adig.obj $(OBJ_DIR)\getopt.obj cares_imp.lib $(EX_LIBS)
|
||||
|
@@ -1013,6 +1013,48 @@ AC_DEFUN([CURL_CHECK_STRUCT_TIMEVAL], [
|
||||
]) # AC_DEFUN
|
||||
|
||||
|
||||
dnl TYPE_SIG_ATOMIC_T
|
||||
dnl -------------------------------------------------
|
||||
dnl Check if the sig_atomic_t type is available, and
|
||||
dnl verify if it is already defined as volatile.
|
||||
|
||||
AC_DEFUN([TYPE_SIG_ATOMIC_T], [
|
||||
AC_CHECK_HEADERS(signal.h)
|
||||
AC_CHECK_TYPE([sig_atomic_t],[
|
||||
AC_DEFINE(HAVE_SIG_ATOMIC_T, 1,
|
||||
[Define to 1 if sig_atomic_t is an available typedef.])
|
||||
], ,[
|
||||
#ifdef HAVE_SIGNAL_H
|
||||
#include <signal.h>
|
||||
#endif
|
||||
])
|
||||
case "$ac_cv_type_sig_atomic_t" in
|
||||
yes)
|
||||
#
|
||||
AC_MSG_CHECKING([if sig_atomic_t is already defined as volatile])
|
||||
AC_TRY_LINK([
|
||||
#ifdef HAVE_SIGNAL_H
|
||||
#include <signal.h>
|
||||
#endif
|
||||
],[
|
||||
static volatile sig_atomic_t dummy = 0;
|
||||
],[
|
||||
AC_MSG_RESULT([no])
|
||||
ac_cv_sig_atomic_t_volatile="no"
|
||||
],[
|
||||
AC_MSG_RESULT([yes])
|
||||
ac_cv_sig_atomic_t_volatile="yes"
|
||||
])
|
||||
#
|
||||
if test "$ac_cv_sig_atomic_t_volatile" = "yes"; then
|
||||
AC_DEFINE(HAVE_SIG_ATOMIC_T_VOLATILE, 1,
|
||||
[Define to 1 if sig_atomic_t is already defined as volatile.])
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
]) # AC_DEFUN
|
||||
|
||||
|
||||
dnl CURL_CHECK_NONBLOCKING_SOCKET
|
||||
dnl -------------------------------------------------
|
||||
dnl Check for how to set a socket to non-blocking state. There seems to exist
|
||||
|
@@ -18,7 +18,7 @@
|
||||
#include "setup.h"
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifdef WIN32
|
||||
#if defined(WIN32) && !defined(WATT32)
|
||||
#include "nameser.h"
|
||||
#else
|
||||
#include <sys/time.h>
|
||||
|
@@ -18,8 +18,7 @@
|
||||
#include "setup.h"
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifdef WIN32
|
||||
#else
|
||||
#if !defined(WIN32) || defined(WATT32)
|
||||
#include <sys/time.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
|
@@ -39,7 +39,10 @@ void ares_cancel(ares_channel channel)
|
||||
channel->queries = NULL;
|
||||
if (!(channel->flags & ARES_FLAG_STAYOPEN))
|
||||
{
|
||||
for (i = 0; i < channel->nservers; i++)
|
||||
ares__close_sockets(channel, &channel->servers[i]);
|
||||
if (channel->servers)
|
||||
{
|
||||
for (i = 0; i < channel->nservers; i++)
|
||||
ares__close_sockets(channel, &channel->servers[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -25,23 +25,37 @@ void ares_destroy(ares_channel channel)
|
||||
int i;
|
||||
struct query *query;
|
||||
|
||||
for (i = 0; i < channel->nservers; i++)
|
||||
ares__close_sockets(channel, &channel->servers[i]);
|
||||
free(channel->servers);
|
||||
for (i = 0; i < channel->ndomains; i++)
|
||||
free(channel->domains[i]);
|
||||
free(channel->domains);
|
||||
if (!channel)
|
||||
return;
|
||||
|
||||
if (channel->servers) {
|
||||
for (i = 0; i < channel->nservers; i++)
|
||||
ares__close_sockets(channel, &channel->servers[i]);
|
||||
free(channel->servers);
|
||||
}
|
||||
|
||||
if (channel->domains) {
|
||||
for (i = 0; i < channel->ndomains; i++)
|
||||
free(channel->domains[i]);
|
||||
free(channel->domains);
|
||||
}
|
||||
|
||||
if(channel->sortlist)
|
||||
free(channel->sortlist);
|
||||
free(channel->lookups);
|
||||
while (channel->queries)
|
||||
{
|
||||
query = channel->queries;
|
||||
channel->queries = query->next;
|
||||
query->callback(query->arg, ARES_EDESTRUCTION, NULL, 0);
|
||||
|
||||
if (channel->lookups)
|
||||
free(channel->lookups);
|
||||
|
||||
while (channel->queries) {
|
||||
query = channel->queries;
|
||||
channel->queries = query->next;
|
||||
query->callback(query->arg, ARES_EDESTRUCTION, NULL, 0);
|
||||
if (query->tcpbuf)
|
||||
free(query->tcpbuf);
|
||||
if (query->skip_server)
|
||||
free(query->skip_server);
|
||||
free(query);
|
||||
}
|
||||
free(query);
|
||||
}
|
||||
|
||||
free(channel);
|
||||
}
|
||||
|
@@ -125,7 +125,9 @@ int ares_init_options(ares_channel *channelptr, struct ares_options *options,
|
||||
channel->queries = NULL;
|
||||
channel->domains = NULL;
|
||||
channel->sortlist = NULL;
|
||||
channel->servers = NULL;
|
||||
channel->sock_state_cb = NULL;
|
||||
channel->sock_state_cb_data = NULL;
|
||||
|
||||
/* Initialize configuration by each of the four sources, from highest
|
||||
* precedence to lowest.
|
||||
@@ -140,7 +142,7 @@ int ares_init_options(ares_channel *channelptr, struct ares_options *options,
|
||||
if (status != ARES_SUCCESS)
|
||||
{
|
||||
/* Something failed; clean up memory we may have allocated. */
|
||||
if (channel->nservers != -1)
|
||||
if (channel->servers)
|
||||
free(channel->servers);
|
||||
if (channel->domains)
|
||||
{
|
||||
@@ -214,12 +216,16 @@ static int init_by_options(ares_channel channel, struct ares_options *options,
|
||||
/* Copy the servers, if given. */
|
||||
if ((optmask & ARES_OPT_SERVERS) && channel->nservers == -1)
|
||||
{
|
||||
channel->servers =
|
||||
malloc(options->nservers * sizeof(struct server_state));
|
||||
if (!channel->servers && options->nservers != 0)
|
||||
return ARES_ENOMEM;
|
||||
for (i = 0; i < options->nservers; i++)
|
||||
channel->servers[i].addr = options->servers[i];
|
||||
/* Avoid zero size allocations at any cost */
|
||||
if (options->nservers > 0)
|
||||
{
|
||||
channel->servers =
|
||||
malloc(options->nservers * sizeof(struct server_state));
|
||||
if (!channel->servers)
|
||||
return ARES_ENOMEM;
|
||||
for (i = 0; i < options->nservers; i++)
|
||||
channel->servers[i].addr = options->servers[i];
|
||||
}
|
||||
channel->nservers = options->nservers;
|
||||
}
|
||||
|
||||
@@ -228,16 +234,20 @@ static int init_by_options(ares_channel channel, struct ares_options *options,
|
||||
*/
|
||||
if ((optmask & ARES_OPT_DOMAINS) && channel->ndomains == -1)
|
||||
{
|
||||
channel->domains = malloc(options->ndomains * sizeof(char *));
|
||||
if (!channel->domains && options->ndomains != 0)
|
||||
return ARES_ENOMEM;
|
||||
for (i = 0; i < options->ndomains; i++)
|
||||
{
|
||||
channel->ndomains = i;
|
||||
channel->domains[i] = strdup(options->domains[i]);
|
||||
if (!channel->domains[i])
|
||||
return ARES_ENOMEM;
|
||||
}
|
||||
/* Avoid zero size allocations at any cost */
|
||||
if (options->ndomains > 0)
|
||||
{
|
||||
channel->domains = malloc(options->ndomains * sizeof(char *));
|
||||
if (!channel->domains)
|
||||
return ARES_ENOMEM;
|
||||
for (i = 0; i < options->ndomains; i++)
|
||||
{
|
||||
channel->ndomains = i;
|
||||
channel->domains[i] = strdup(options->domains[i]);
|
||||
if (!channel->domains[i])
|
||||
return ARES_ENOMEM;
|
||||
}
|
||||
}
|
||||
channel->ndomains = options->ndomains;
|
||||
}
|
||||
|
||||
@@ -582,11 +592,11 @@ DhcpNameServer
|
||||
return (errno == ENOENT) ? ARES_SUCCESS : ARES_EFILE;
|
||||
while ((status = ares__read_line(fp, &line, &linesize)) == ARES_SUCCESS)
|
||||
{
|
||||
if ((p = try_config(line, "domain")))
|
||||
if ((p = try_config(line, "domain")) && channel->ndomains == -1)
|
||||
status = config_domain(channel, p);
|
||||
else if ((p = try_config(line, "lookup")) && !channel->lookups)
|
||||
status = config_lookup(channel, p, "bind", "file");
|
||||
else if ((p = try_config(line, "search")))
|
||||
else if ((p = try_config(line, "search")) && channel->ndomains == -1)
|
||||
status = set_search(channel, p);
|
||||
else if ((p = try_config(line, "nameserver")) && channel->nservers == -1)
|
||||
status = config_nameserver(&servers, &nservers, p);
|
||||
@@ -711,7 +721,6 @@ static int init_by_defaults(ares_channel channel)
|
||||
if (gethostname(hostname, sizeof(hostname)) == -1
|
||||
|| !strchr(hostname, '.'))
|
||||
{
|
||||
channel->domains = malloc(0);
|
||||
channel->ndomains = 0;
|
||||
}
|
||||
else
|
||||
@@ -940,6 +949,7 @@ static int set_search(ares_channel channel, const char *str)
|
||||
for(n=0; n < channel->ndomains; n++)
|
||||
free(channel->domains[n]);
|
||||
free(channel->domains);
|
||||
channel->domains = NULL;
|
||||
channel->ndomains = -1;
|
||||
}
|
||||
|
||||
@@ -955,8 +965,14 @@ static int set_search(ares_channel channel, const char *str)
|
||||
n++;
|
||||
}
|
||||
|
||||
if (!n)
|
||||
{
|
||||
channel->ndomains = 0;
|
||||
return ARES_SUCCESS;
|
||||
}
|
||||
|
||||
channel->domains = malloc(n * sizeof(char *));
|
||||
if (!channel->domains && n)
|
||||
if (!channel->domains)
|
||||
return ARES_ENOMEM;
|
||||
|
||||
/* Now copy the domains. */
|
||||
|
@@ -5,11 +5,11 @@
|
||||
|
||||
#define ARES_VERSION_MAJOR 1
|
||||
#define ARES_VERSION_MINOR 3
|
||||
#define ARES_VERSION_PATCH 1
|
||||
#define ARES_VERSION_PATCH 3
|
||||
#define ARES_VERSION ((ARES_VERSION_MAJOR<<16)|\
|
||||
(ARES_VERSION_MINOR<<8)|\
|
||||
(ARES_VERSION_PATCH))
|
||||
#define ARES_VERSION_STR "1.3.1"
|
||||
#define ARES_VERSION_STR "1.3.3-CVS"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@@ -3,7 +3,7 @@
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
/* Copyright (C) 2004 - 2005 by Daniel Stenberg et al
|
||||
/* Copyright (C) 2004 - 2006 by Daniel Stenberg et al
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software and its
|
||||
* documentation for any purpose and without fee is hereby granted, provided
|
||||
@@ -17,7 +17,7 @@
|
||||
*/
|
||||
|
||||
/* ================================================================ */
|
||||
/* ares/config-win32.h - Hand crafted config file for windows */
|
||||
/* ares/config-win32.h - Hand crafted config file for Windows */
|
||||
/* ================================================================ */
|
||||
|
||||
/* ---------------------------------------------------------------- */
|
||||
@@ -29,6 +29,9 @@
|
||||
#define HAVE_GETOPT_H 1
|
||||
#endif
|
||||
|
||||
/* Define if you have the <signal.h> header file. */
|
||||
#define HAVE_SIGNAL_H 1
|
||||
|
||||
/* Define if you have the <sys/time.h> header file */
|
||||
/* #define HAVE_SYS_TIME_H 1 */
|
||||
|
||||
@@ -57,6 +60,9 @@
|
||||
/* OTHER HEADER INFO */
|
||||
/* ---------------------------------------------------------------- */
|
||||
|
||||
/* Define if sig_atomic_t is an available typedef. */
|
||||
#define HAVE_SIG_ATOMIC_T 1
|
||||
|
||||
/* Define if you have the ANSI C header files. */
|
||||
#define STDC_HEADERS 1
|
||||
|
||||
@@ -70,24 +76,6 @@
|
||||
/* Define if you have the ioctlsocket function. */
|
||||
#define HAVE_IOCTLSOCKET 1
|
||||
|
||||
/* Define if you have the getnameinfo function. */
|
||||
#define HAVE_GETNAMEINFO 1
|
||||
|
||||
/* Define to the type qualifier of arg 1 for getnameinfo. */
|
||||
#define GETNAMEINFO_QUAL_ARG1 const
|
||||
|
||||
/* Define to the type of arg 1 for getnameinfo. */
|
||||
#define GETNAMEINFO_TYPE_ARG1 struct sockaddr *
|
||||
|
||||
/* Define to the type of arg 2 for getnameinfo. */
|
||||
#define GETNAMEINFO_TYPE_ARG2 socklen_t
|
||||
|
||||
/* Define to the type of args 4 and 6 for getnameinfo. */
|
||||
#define GETNAMEINFO_TYPE_ARG46 DWORD
|
||||
|
||||
/* Define to the type of arg 7 for getnameinfo. */
|
||||
#define GETNAMEINFO_TYPE_ARG7 int
|
||||
|
||||
/* Define if you have the recv function. */
|
||||
#define HAVE_RECV 1
|
||||
|
||||
@@ -127,6 +115,39 @@
|
||||
/* Define to the function return type for send. */
|
||||
#define SEND_TYPE_RETV int
|
||||
|
||||
/* Specifics for the Watt-32 tcp/ip stack */
|
||||
#ifdef WATT32
|
||||
#define SOCKET int
|
||||
#define NS_INADDRSZ 4
|
||||
#define HAVE_ARPA_NAMESER_H 1
|
||||
#undef HAVE_WINSOCK_H
|
||||
#undef HAVE_WINSOCK2_H
|
||||
#undef HAVE_WS2TCPIP_H
|
||||
#endif
|
||||
|
||||
/* ---------------------------------------------------------------- */
|
||||
/* TYPEDEF REPLACEMENTS */
|
||||
/* ---------------------------------------------------------------- */
|
||||
|
||||
/* Define this if in_addr_t is not an available 'typedefed' type */
|
||||
#define in_addr_t unsigned long
|
||||
|
||||
/* Define as the return type of signal handlers (int or void). */
|
||||
#define RETSIGTYPE void
|
||||
|
||||
/* Define ssize_t if it is not an available 'typedefed' type */
|
||||
#if (defined(__WATCOMC__) && (__WATCOMC__ >= 1240)) || defined(__POCC__)
|
||||
#elif defined(_WIN64)
|
||||
#define ssize_t __int64
|
||||
#else
|
||||
#define ssize_t int
|
||||
#endif
|
||||
|
||||
/* Define to 'int' if socklen_t is not an available 'typedefed' type */
|
||||
#ifndef HAVE_WS2TCPIP_H
|
||||
#define socklen_t int
|
||||
#endif
|
||||
|
||||
/* ---------------------------------------------------------------- */
|
||||
/* STRUCT RELATED */
|
||||
/* ---------------------------------------------------------------- */
|
||||
|
@@ -297,6 +297,10 @@ TYPE_IN_ADDR_T
|
||||
|
||||
TYPE_SOCKADDR_STORAGE
|
||||
|
||||
TYPE_SIG_ATOMIC_T
|
||||
|
||||
AC_TYPE_SIGNAL
|
||||
|
||||
CURL_CHECK_FUNC_RECV
|
||||
|
||||
CURL_CHECK_FUNC_SEND
|
||||
|
@@ -3,7 +3,7 @@
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
/* Copyright (C) 2004 - 2006 by Daniel Stenberg et al
|
||||
/* Copyright (C) 2004 - 2007 by Daniel Stenberg et al
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software and its
|
||||
* documentation for any purpose and without fee is hereby granted, provided
|
||||
@@ -29,7 +29,7 @@
|
||||
|
||||
/*
|
||||
* If we have the MSG_NOSIGNAL define, make sure we use
|
||||
* it as the fourth argument of send() and recv()
|
||||
* it as the fourth argument of function send()
|
||||
*/
|
||||
|
||||
#ifdef HAVE_MSG_NOSIGNAL
|
||||
@@ -74,7 +74,7 @@
|
||||
#define sread(x,y,z) (ssize_t)recv((RECV_TYPE_ARG1)(x), \
|
||||
(RECV_TYPE_ARG2)(y), \
|
||||
(RECV_TYPE_ARG3)(z), \
|
||||
(RECV_TYPE_ARG4)(SEND_4TH_ARG))
|
||||
(RECV_TYPE_ARG4)(0))
|
||||
#endif
|
||||
#else /* HAVE_RECV */
|
||||
#ifndef sread
|
||||
@@ -123,5 +123,24 @@
|
||||
#define ISPRINT(x) (isprint((int) ((unsigned char)x)))
|
||||
|
||||
|
||||
/*
|
||||
* Typedef to 'int' if sig_atomic_t is not an available 'typedefed' type.
|
||||
*/
|
||||
|
||||
#ifndef HAVE_SIG_ATOMIC_T
|
||||
typedef int sig_atomic_t;
|
||||
#define HAVE_SIG_ATOMIC_T
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Default return type for signal handlers.
|
||||
*/
|
||||
|
||||
#ifndef RETSIGTYPE
|
||||
#define RETSIGTYPE void
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* __SETUP_ONCE_H */
|
||||
|
||||
|
@@ -129,6 +129,10 @@ SOURCE=..\..\ares_gethostbyname.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\ares_getsock.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\ares_init.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
@@ -5,7 +5,6 @@ REM $Date$
|
||||
|
||||
REM create ca-bundle.h
|
||||
echo /* This file is generated automatically */ >lib\ca-bundle.h
|
||||
echo #define CURL_CA_BUNDLE getenv("CURL_CA_BUNDLE") >>lib\ca-bundle.h
|
||||
|
||||
REM create hugehelp.c
|
||||
copy src\hugehelp.c.cvs src\hugehelp.c
|
||||
|
76
configure.ac
76
configure.ac
@@ -78,6 +78,7 @@ AC_SUBST(PKGADD_VENDOR)
|
||||
dnl
|
||||
dnl initialize all the info variables
|
||||
curl_ssl_msg="no (--with-ssl / --with-gnutls)"
|
||||
curl_ssh_msg="no (--with-libssh2)"
|
||||
curl_zlib_msg="no (--with-zlib)"
|
||||
curl_krb4_msg="no (--with-krb4*)"
|
||||
curl_gss_msg="no (--with-gssapi)"
|
||||
@@ -1043,6 +1044,74 @@ if test X"$OPT_SSL" != Xno; then
|
||||
|
||||
fi
|
||||
|
||||
dnl **********************************************************************
|
||||
dnl Check for the presence of LIBSSH2 libraries and headers
|
||||
dnl **********************************************************************
|
||||
|
||||
dnl Default to compiler & linker defaults for LIBSSH2 files & libraries.
|
||||
OPT_LIBSSH2=off
|
||||
AC_ARG_WITH(libssh2,dnl
|
||||
AC_HELP_STRING([--with-libssh2=PATH],[Where to look for libssh2, PATH points to the LIBSSH2 installation (default: /usr/local/lib); when possible, set the PKG_CONFIG_PATH environment variable instead of using this option])
|
||||
AC_HELP_STRING([--without-libssh2], [disable LIBSSH2]),
|
||||
OPT_LIBSSH2=$withval)
|
||||
|
||||
if test X"$OPT_LIBSSH2" != Xno; then
|
||||
dnl backup the pre-libssh2 variables
|
||||
CLEANLDFLAGS="$LDFLAGS"
|
||||
CLEANCPPFLAGS="$CPPFLAGS"
|
||||
CLEANLIBS="$LIBS"
|
||||
|
||||
case "$OPT_LIBSSH2" in
|
||||
yes)
|
||||
dnl --with-libssh2 (without path) used
|
||||
PREFIX_LIBSSH2=/usr/local/lib
|
||||
LIB_LIBSSH2="$PREFIX_LIBSSH2/lib$libsuff"
|
||||
;;
|
||||
off)
|
||||
dnl no --with-libssh2 option given, just check default places
|
||||
PREFIX_LIBSSH2=
|
||||
;;
|
||||
*)
|
||||
dnl use the given --with-libssh2 spot
|
||||
PREFIX_LIBSSH2=$OPT_LIBSSH2
|
||||
LIB_LIBSSH2="$PREFIX_LIBSSH2/lib$libsuff"
|
||||
LDFLAGS="$LDFLAGS -L$LIB_LIBSSH2"
|
||||
CPPFLAGS="$CPPFLAGS -I$PREFIX_LIBSSH2/include"
|
||||
;;
|
||||
esac
|
||||
|
||||
if test X"$HAVECRYPTO" = X"yes"; then
|
||||
dnl This is only reasonable to do if crypto actually is there: check for
|
||||
dnl LIBSSH2 libs NOTE: it is important to do this AFTER the crypto lib
|
||||
|
||||
AC_CHECK_LIB(ssh2, libssh2_channel_open_ex)
|
||||
|
||||
AC_CHECK_HEADERS(libssh2.h,
|
||||
curl_ssh_msg="enabled (libSSH2)"
|
||||
LIBSSH2_ENABLED=1
|
||||
AC_DEFINE(USE_LIBSSH2, 1, [if libSSH2 is in use]))
|
||||
|
||||
if test X"$OPT_LIBSSH2" != Xoff &&
|
||||
test "$LIBSSH2_ENABLED" != "1"; then
|
||||
AC_MSG_ERROR([libSSH2 libs and/or directories were not found where specified!])
|
||||
fi
|
||||
else
|
||||
AC_MSG_WARN([without the use of OpenSSL libs, libssh2 cannot work])
|
||||
fi
|
||||
|
||||
if test "$LIBSSH2_ENABLED" = "1"; then
|
||||
if test -n "$LIB_LIBSSH2"; then
|
||||
dnl when the libssh2 shared libs were found in a path that the run-time
|
||||
dnl linker doesn't search through, we need to add it to LD_LIBRARY_PATH
|
||||
dnl to prevent further configure tests to fail due to this
|
||||
|
||||
LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$LIB_LIBSSH2"
|
||||
export LD_LIBRARY_PATH
|
||||
AC_MSG_NOTICE([Added $LIB_LIBSSH2 to LD_LIBRARY_PATH])
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
dnl **********************************************************************
|
||||
dnl Check for the random seed preferences
|
||||
dnl **********************************************************************
|
||||
@@ -1564,6 +1633,10 @@ TYPE_IN_ADDR_T
|
||||
|
||||
TYPE_SOCKADDR_STORAGE
|
||||
|
||||
TYPE_SIG_ATOMIC_T
|
||||
|
||||
AC_TYPE_SIGNAL
|
||||
|
||||
AC_FUNC_SELECT_ARGTYPES
|
||||
|
||||
CURL_CHECK_FUNC_RECV
|
||||
@@ -1574,7 +1647,7 @@ CURL_CHECK_MSG_NOSIGNAL
|
||||
|
||||
dnl Checks for library functions.
|
||||
dnl AC_PROG_GCC_TRADITIONAL
|
||||
AC_TYPE_SIGNAL
|
||||
|
||||
dnl AC_FUNC_VPRINTF
|
||||
case $host in
|
||||
*msdosdjgpp)
|
||||
@@ -2076,6 +2149,7 @@ AC_MSG_NOTICE([Configured to build curl/libcurl:
|
||||
Install prefix: ${prefix}
|
||||
Compiler: ${CC}
|
||||
SSL support: ${curl_ssl_msg}
|
||||
SSH support: ${curl_ssh_msg}
|
||||
zlib support: ${curl_zlib_msg}
|
||||
krb4 support: ${curl_krb4_msg}
|
||||
GSSAPI support: ${curl_gss_msg}
|
||||
|
@@ -142,8 +142,8 @@ Rexx
|
||||
|
||||
Ruby
|
||||
|
||||
Written by Hirotaka Matsuyuki
|
||||
http://www.d1.dion.ne.jp/~matuyuki/ruby.html
|
||||
Written by Ross Bamford
|
||||
http://curb.rubyforge.org/
|
||||
|
||||
Scheme
|
||||
|
||||
|
25
docs/INSTALL
25
docs/INSTALL
@@ -51,12 +51,12 @@ UNIX
|
||||
path for your compiler/linker, you don't need to do anything special. If
|
||||
you have OpenSSL installed in /usr/local/ssl, you can run configure like:
|
||||
|
||||
./configure --with-ssl
|
||||
./configure --with-ssl
|
||||
|
||||
If you have OpenSSL installed somewhere else (for example, /opt/OpenSSL,)
|
||||
you can run configure like this:
|
||||
|
||||
./configure --with-ssl=/opt/OpenSSL
|
||||
./configure --with-ssl=/opt/OpenSSL
|
||||
|
||||
If you insist on forcing a build without SSL support, even though you may
|
||||
have OpenSSL installed in your system, you can run configure like this:
|
||||
@@ -148,12 +148,21 @@ Win32
|
||||
-------
|
||||
|
||||
Run the 'mingw32.bat' file to get the proper environment variables set,
|
||||
then run 'make mingw32' in the root dir. Use 'make mingw32-ssl' to build
|
||||
then run 'make mingw32' in the root dir. Use 'make mingw32-ssl' to build
|
||||
curl SSL enabled.
|
||||
|
||||
If you have any problems linking libraries or finding header files, be sure
|
||||
to verify that the provided "Makefile.m32" files use the proper paths, and
|
||||
adjust as necessary.
|
||||
adjust as necessary. It is also possible to override these paths with
|
||||
environment variables, for example:
|
||||
|
||||
set ZLIB_PATH=c:\zlib-1.2.3
|
||||
set OPENSSL_PATH=c:\openssl-0.9.8d
|
||||
set LIBSSH2_PATH=c:\libssh2-0.15
|
||||
|
||||
ATTENTION: if you want to build with libssh2 support you have to use latest
|
||||
sources fetched from CVS - the current 0.14 release will NOT work!
|
||||
Use 'make mingw32-ssh2-ssl' to build curl with SSH2 and SSL enabled.
|
||||
|
||||
Cygwin
|
||||
------
|
||||
@@ -184,7 +193,7 @@ Win32
|
||||
documentation on how to compile zlib. Define the ZLIB_PATH environment
|
||||
variable to the location of zlib.h and zlib.lib, for example:
|
||||
|
||||
set ZLIB_PATH=c:\zlib-1.2.1
|
||||
set ZLIB_PATH=c:\zlib-1.2.3
|
||||
|
||||
Then run 'nmake vc-zlib' in curl's root directory.
|
||||
|
||||
@@ -198,7 +207,7 @@ Win32
|
||||
Before running nmake define the OPENSSL_PATH environment variable with
|
||||
the root/base directory of OpenSSL, for example:
|
||||
|
||||
set OPENSSL_PATH=c:\openssl-0.9.7d
|
||||
set OPENSSL_PATH=c:\openssl-0.9.8d
|
||||
|
||||
Then run 'nmake vc-ssl' or 'nmake vc-ssl-dll' in curl's root
|
||||
directory. 'nmake vc-ssl' will create a libcurl static and dynamic
|
||||
@@ -676,6 +685,7 @@ PORTS
|
||||
- PowerPC Linux
|
||||
- PowerPC Mac OS 9
|
||||
- PowerPC Mac OS X
|
||||
- SuperH4 Linux 2.6.X
|
||||
- SINIX-Z v5
|
||||
- Sparc Linux
|
||||
- Sparc Solaris 2.4, 2.5, 2.5.1, 2.6, 7, 8, 9, 10
|
||||
@@ -717,3 +727,6 @@ OpenSSL http://www.openssl.org
|
||||
MingW http://www.mingw.org
|
||||
OpenLDAP http://www.openldap.org
|
||||
Zlib http://www.gzip.org/zlib/
|
||||
libssh2 http://www.libssh2.org
|
||||
|
||||
|
||||
|
@@ -3,6 +3,25 @@ join in and help us correct one or more of these! Also be sure to check the
|
||||
changelog of the current development status, as one or more of these problems
|
||||
may have been fixed since this was written!
|
||||
|
||||
41. Jeff Pohlmeyer's curl_multi_socket crashing case. Recipe and instructions
|
||||
here: http://curl.haxx.se/mail/lib-2007-01/0022.html
|
||||
|
||||
40. HTTP Pipelining, NULL content
|
||||
http://curl.haxx.se/bug/view.cgi?id=1631566
|
||||
|
||||
39. Steffen Rumler's Race Condition in Curl_proxyCONNECT:
|
||||
http://curl.haxx.se/mail/lib-2007-01/0045.html
|
||||
|
||||
38. Kumar Swamy Bhatt's problem in ftp/ssl "LIST" operation:
|
||||
http://curl.haxx.se/mail/lib-2007-01/0103.html
|
||||
|
||||
37. Having more than one connection to the same host when doing NTLM
|
||||
authentication (with performs multiple "passes" and authenticates a
|
||||
connection rather than a HTTP request), and particularly when using the
|
||||
multi interface, there's a risk that libcurl will re-use a wrong connection
|
||||
when doing the different passes in the NTLM negotiation and thus fail to
|
||||
negotiate (in seemingly mysterious ways).
|
||||
|
||||
35. Both SOCKS5 and SOCKS4 proxy connections are done blocking, which is very
|
||||
bad when used with the multi interface.
|
||||
|
||||
@@ -44,11 +63,6 @@ may have been fixed since this was written!
|
||||
"system context" will make it use wrong(?) user name - at least when compared
|
||||
to what winhttp does. See http://curl.haxx.se/bug/view.cgi?id=1281867
|
||||
|
||||
25. When doing a CONNECT request with curl it doesn't properly handle if the
|
||||
proxy closes the connection within the authentication "negotiation phase".
|
||||
Like if you do HTTPS or similar over a proxy and you use perhaps
|
||||
--proxy-anyauth.
|
||||
|
||||
23. We don't support SOCKS for IPv6. We don't support FTPS over a SOCKS proxy.
|
||||
We don't have any test cases for SOCKS proxy. We probably have even more
|
||||
bugs and lack of features when a SOCKS proxy is used. And there seem to be a
|
||||
|
24
docs/THANKS
24
docs/THANKS
@@ -17,6 +17,7 @@ Alexander Kourakos
|
||||
Alexander Krasnostavsky
|
||||
Alexander Lazic
|
||||
Alexander Zhuravlev
|
||||
Alexey Simak
|
||||
Alexis Carvalho
|
||||
Amol Pattekar
|
||||
Andi Jahja
|
||||
@@ -26,6 +27,7 @@ Andreas Olsson
|
||||
Andreas Rieke
|
||||
Andres Garcia
|
||||
Andrew Benham
|
||||
Andrew Biggs
|
||||
Andrew Bushnell
|
||||
Andrew Francis
|
||||
Andrew Fuller
|
||||
@@ -36,6 +38,7 @@ Angus Mackay
|
||||
Antoine Calando
|
||||
Anton Kalmykov
|
||||
Arkadiusz Miskiewicz
|
||||
Armel Asselin
|
||||
Arve Knudsen
|
||||
Ates Goral
|
||||
Augustus Saunders
|
||||
@@ -43,12 +46,15 @@ Avery Fay
|
||||
Ben Greear
|
||||
Ben Madsen
|
||||
Benjamin Gerard
|
||||
Bernard Leak
|
||||
Bertrand Demiddelaer
|
||||
Bjorn Reese
|
||||
Bj<EFBFBD>rn Stenberg
|
||||
Bob Schader
|
||||
Bogdan Nicula
|
||||
Brad Burdick
|
||||
Bradford Bruce
|
||||
Brendan Jurd
|
||||
Brent Beardsley
|
||||
Brian Akins
|
||||
Brian Dessent
|
||||
@@ -68,6 +74,7 @@ Christian Robottom Reis
|
||||
Christophe Demory
|
||||
Christophe Legry
|
||||
Christopher R. Palmer
|
||||
Ciprian Badescu
|
||||
Clarence Gardner
|
||||
Clifford Wolf
|
||||
Cody Jones
|
||||
@@ -116,7 +123,9 @@ Dimitris Sarris
|
||||
Dinar
|
||||
Dirk Eddelbuettel
|
||||
Dirk Manske
|
||||
Dmitriy Sergeyev
|
||||
Dmitry Bartsevich
|
||||
Dmitry Rechkin
|
||||
Dolbneff A.V
|
||||
Domenico Andreoli
|
||||
Dominick Meglio
|
||||
@@ -206,11 +215,13 @@ James Clancy
|
||||
James Cone
|
||||
James Gallagher
|
||||
James Griffiths
|
||||
James Housley
|
||||
James MacMillan
|
||||
Jamie Lokier
|
||||
Jamie Newton
|
||||
Jamie Wilkinson
|
||||
Jan Kunder
|
||||
Jared Lundell
|
||||
Jari Sundell
|
||||
Jason S. Priebe
|
||||
Jaz Fresh
|
||||
@@ -313,12 +324,14 @@ Markus Oberhumer
|
||||
Martijn Koster
|
||||
Martin C. Martin
|
||||
Martin Hedenfalk
|
||||
Martin Skinner
|
||||
Marty Kuhrt
|
||||
Maruko
|
||||
Massimiliano Ziccardi
|
||||
Mathias Axelsson
|
||||
Mats Lidell
|
||||
Matt Veenstra
|
||||
Matt Witherspoon
|
||||
Matthew Blain
|
||||
Matthew Clarke
|
||||
Maurice Barnum
|
||||
@@ -337,12 +350,14 @@ Mihai Ionescu
|
||||
Mikael Sennerholm
|
||||
Mike Bytnar
|
||||
Mike Dobbs
|
||||
Mike Protts
|
||||
Miklos Nemeth
|
||||
Mitz Wark
|
||||
Mohamed Lrhazi
|
||||
Mohun Biswas
|
||||
Moonesamy
|
||||
Nathan O'Sullivan
|
||||
Nathanael Nerode
|
||||
Naveen Noel
|
||||
Neil Dunbar
|
||||
Neil Spring
|
||||
@@ -355,10 +370,12 @@ Nicolas Croiset
|
||||
Nicolas Fran<61>ois
|
||||
Niels van Tongeren
|
||||
Nikita Schmidt
|
||||
Nir Soffer
|
||||
Nis Jorgensen
|
||||
Nodak Sodak
|
||||
Norbert Novotny
|
||||
Ofer
|
||||
Olaf Stueben
|
||||
Olaf St<53>ben
|
||||
Oren Tirosh
|
||||
P R Schaffner
|
||||
@@ -398,6 +415,7 @@ Ralph Beckmann
|
||||
Ralph Mitchell
|
||||
Ramana Mokkapati
|
||||
Randy McMurchy
|
||||
Ravi Pratap
|
||||
Reinout van Schouwen
|
||||
Renaud Chaillat
|
||||
Renaud Duhaut
|
||||
@@ -416,6 +434,7 @@ Rick Jones
|
||||
Rick Richardson
|
||||
Rob Stanzel
|
||||
Robert D. Young
|
||||
Robert Foreman
|
||||
Robert Olson
|
||||
Robert Weaver
|
||||
Robin Kay
|
||||
@@ -442,6 +461,7 @@ Scott Davis
|
||||
Sebastien Willemijns
|
||||
Sergio Ballestrero
|
||||
Seshubabu Pasam
|
||||
Sh Diao
|
||||
Shard
|
||||
Shawn Poulson
|
||||
Shmulik Regev
|
||||
@@ -452,6 +472,7 @@ Simon Liu
|
||||
Spiridonoff A.V
|
||||
Stadler Stephan
|
||||
Stefan Esser
|
||||
Stefan Krause
|
||||
Stefan Ulrich
|
||||
Stephan Bergmann
|
||||
Stephen Kick
|
||||
@@ -489,6 +510,7 @@ Tomas Szepe
|
||||
Tomasz Lacki
|
||||
Tommy Tam
|
||||
Ton Voon
|
||||
Toon Verwaest
|
||||
Tor Arntsen
|
||||
Torsten Foertsch
|
||||
Toshiyuki Maezawa
|
||||
@@ -498,6 +520,8 @@ Troy Engel
|
||||
Tupone Alfredo
|
||||
Ulf H<>rnhammar
|
||||
Ulrich Zadow
|
||||
Venkat Akella
|
||||
Victor Snezhko
|
||||
Vilmos Nebehaj
|
||||
Vincent Bronner
|
||||
Vincent Penquerc'h
|
||||
|
16
docs/TODO
16
docs/TODO
@@ -43,10 +43,6 @@ TODO
|
||||
powered libcurl the default build (which of course would require that we'd
|
||||
bundle the c-ares source code in the libcurl source code releases).
|
||||
|
||||
* Support CONNECT 407 responses that kill the connection and expect the
|
||||
client to reconnect to complete the authentication. Currently libcurl
|
||||
assumes that a proxy connection will be kept alive.
|
||||
|
||||
* Make the curl/*.h headers include the proper system includes based on what
|
||||
was present at the time when configure was run. Currently, the sys/select.h
|
||||
header is for example included by curl/multi.h only on specific platforms
|
||||
@@ -188,8 +184,8 @@ TODO
|
||||
|
||||
* Fix the connection phase to be non-blocking when multi interface is used
|
||||
|
||||
* Add a way to check if the connection seems to be alive, to corrspond to the
|
||||
SSL_peak() way we use with OpenSSL.
|
||||
* Add a way to check if the connection seems to be alive, to correspond to
|
||||
the SSL_peak() way we use with OpenSSL.
|
||||
|
||||
LDAP
|
||||
|
||||
@@ -201,10 +197,6 @@ TODO
|
||||
|
||||
* RTSP - RFC2326 (protocol - very HTTP-like, also contains URL description)
|
||||
|
||||
* SFTP/SCP/SSH (no RFCs for protocol nor URI/URL format). An implementation
|
||||
should most probably use an existing ssh library, such as OpenSSH. or
|
||||
libssh2.org
|
||||
|
||||
* RSYNC (no RFCs for protocol nor URI/URL format). An implementation should
|
||||
most probably use an existing rsync library, such as librsync.
|
||||
|
||||
@@ -273,6 +265,10 @@ TODO
|
||||
|
||||
TEST SUITE
|
||||
|
||||
* Make our own version of stunnel for simple port forwarding to enable HTTPS
|
||||
and FTP-SSL tests without the stunnel dependency, and it could allow us to
|
||||
provide test tools built with either OpenSSL or GnuTLS
|
||||
|
||||
* Make the test servers able to serve multiple running test suites. Like if
|
||||
two users run 'make test' at once.
|
||||
|
||||
|
30
docs/curl.1
30
docs/curl.1
@@ -5,7 +5,7 @@
|
||||
.\" * | (__| |_| | _ <| |___
|
||||
.\" * \___|\___/|_| \_\_____|
|
||||
.\" *
|
||||
.\" * Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
.\" * Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
.\" *
|
||||
.\" * This software is licensed as described in the file COPYING, which
|
||||
.\" * you should have received as part of this distribution. The terms
|
||||
@@ -21,7 +21,7 @@
|
||||
.\" * $Id$
|
||||
.\" **************************************************************************
|
||||
.\"
|
||||
.TH curl 1 "23 Sep 2006" "Curl 7.16.0" "Curl Manual"
|
||||
.TH curl 1 "3 Nov 2006" "Curl 7.16.1" "Curl Manual"
|
||||
.SH NAME
|
||||
curl \- transfer a URL
|
||||
.SH SYNOPSIS
|
||||
@@ -30,8 +30,8 @@ curl \- transfer a URL
|
||||
.SH DESCRIPTION
|
||||
.B curl
|
||||
is a tool to transfer data from or to a server, using one of the supported
|
||||
protocols (HTTP, HTTPS, FTP, FTPS, TFTP, DICT, TELNET, LDAP or FILE).
|
||||
The command is designed to work without user interaction.
|
||||
protocols (HTTP, HTTPS, FTP, FTPS, SCP, SFTP, TFTP, DICT, TELNET, LDAP or
|
||||
FILE). The command is designed to work without user interaction.
|
||||
|
||||
curl offers a busload of useful tricks like proxy support, user
|
||||
authentication, ftp upload, HTTP post, SSL connections, cookies, file transfer
|
||||
@@ -320,7 +320,7 @@ is used to seed the random engine for SSL connections. See also the
|
||||
with HTTPS or FTPS. The certificate must be in PEM format. If the optional
|
||||
password isn't specified, it will be queried for on the terminal. Note that
|
||||
this option assumes a \&"certificate" file that is the private key and the
|
||||
private certificate concatenated! See \fI--cert\P and \fI--key\fP to specify
|
||||
private certificate concatenated! See \fI--cert\fP and \fI--key\fP to specify
|
||||
them independently.
|
||||
|
||||
If this option is used several times, the last one will be used.
|
||||
@@ -432,6 +432,14 @@ If this option is used twice, the second will again disable this.
|
||||
Terminates the connection if the server doesn't support SSL/TLS.
|
||||
(Added in 7.15.5)
|
||||
|
||||
If this option is used twice, the second will again disable this.
|
||||
.IP "--ftp-ssl-ccc"
|
||||
(FTP) Use CCC (Clear Command Channel)
|
||||
Shuts down the SSL/TLS layer after authenticating. The rest of the
|
||||
control channel communication will be unencrypted. This allows
|
||||
NAT routers to follow the FTP transaction.
|
||||
(Added in 7.16.1)
|
||||
|
||||
If this option is used twice, the second will again disable this.
|
||||
.IP "-F/--form <name=content>"
|
||||
(HTTP) This lets curl emulate a filled in form in which a user has pressed the
|
||||
@@ -591,7 +599,7 @@ line. So, it could look similar to this:
|
||||
|
||||
url = "http://curl.haxx.se/docs/"
|
||||
|
||||
This option can be used multiple times.
|
||||
This option can be used multiple times to load multiple config files.
|
||||
|
||||
When curl is invoked, it always (unless \fI-q\fP is used) checks for a default
|
||||
config file and uses it if found. The default config file is checked for in
|
||||
@@ -606,6 +614,12 @@ resort the '%USERPROFILE%\Application Data'.
|
||||
2) On windows, if there is no _curlrc file in the home dir, it checks for one
|
||||
in the same dir the executable curl is placed. On unix-like systems, it will
|
||||
simply try to load .curlrc from the determined home dir.
|
||||
.IP "--libcurl <file>"
|
||||
Append this option to any ordinary curl command line, and you will get a
|
||||
libcurl-using source code written to the file that does the equivalent
|
||||
operation of what your command line operation does!
|
||||
|
||||
If this option is used several times, the last given file name will be used.
|
||||
.IP "--limit-rate <speed>"
|
||||
Specify the maximum transfer rate you want curl to use. This feature is useful
|
||||
if you have a limited pipe and you'd like your transfer not use your entire
|
||||
@@ -615,6 +629,10 @@ The given speed is measured in bytes/second, unless a suffix is appended.
|
||||
Appending 'k' or 'K' will count the number as kilobytes, 'm' or M' makes it
|
||||
megabytes while 'g' or 'G' makes it gigabytes. Examples: 200K, 3m and 1G.
|
||||
|
||||
The given rate is the average speed, counted during the entire transfer. It
|
||||
means that curl might use higher transfer speeds in short bursts, but over
|
||||
time it uses no more than the given rate.
|
||||
|
||||
If you are also using the \fI-Y/--speed-limit\fP option, that option will take
|
||||
precedence and might cripple the rate-limiting slightly, to help keeping the
|
||||
speed-limit logic working.
|
||||
|
@@ -1,8 +1,8 @@
|
||||
/*****************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* $Id$
|
||||
@@ -41,9 +41,6 @@ int main(int argc, char **argv)
|
||||
/* no progress meter please */
|
||||
curl_easy_setopt(curl_handle, CURLOPT_NOPROGRESS, 1);
|
||||
|
||||
/* shut up completely */
|
||||
curl_easy_setopt(curl_handle, CURLOPT_MUTE, 1);
|
||||
|
||||
/* send all data to this function */
|
||||
curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, write_data);
|
||||
|
||||
|
@@ -9,6 +9,18 @@
|
||||
*
|
||||
* This example code only builds as-is on Windows.
|
||||
*
|
||||
* While Unix/Linux user, you do not need this software.
|
||||
* You can achieve the same result as synctime using curl, awk and date.
|
||||
* Set proxy as according to your network, but beware of proxy Cache-Control.
|
||||
*
|
||||
* To set your system clock, root access is required.
|
||||
* # date -s "`curl -sI http://nist.time.gov/timezone.cgi?UTC/s/0 \
|
||||
* | awk -F': ' '/Date: / {print $2}'`"
|
||||
*
|
||||
* To view remote webserver date and time.
|
||||
* $ curl -sI http://nist.time.gov/timezone.cgi?UTC/s/0 \
|
||||
* | awk -F': ' '/Date: / {print $2}'
|
||||
*
|
||||
* Synchronising your computer clock via Internet time server usually relies
|
||||
* on DAYTIME, TIME, or NTP protocols. These protocols provide good accurate
|
||||
* time synchronisation but it does not work very well through a
|
||||
@@ -300,10 +312,11 @@ int main(int argc, char *argv[])
|
||||
MthStr[LOCALTime.wMonth-1], LOCALTime.wYear,
|
||||
LOCALTime.wHour, LOCALTime.wMinute, LOCALTime.wSecond,
|
||||
LOCALTime.wMilliseconds);
|
||||
fprintf(stderr, "\nBefore HTTP. Date: %s%s\n\n", timeBuf, tzoneBuf);
|
||||
|
||||
fprintf(stderr, "Fetch: %s\n\n", conf->timeserver);
|
||||
fprintf(stderr, "Before HTTP. Date: %s%s\n\n", timeBuf, tzoneBuf);
|
||||
|
||||
/* HTTP HEAD command to the Webserver */
|
||||
fprintf(stderr, "Fetch: %s\n", conf->timeserver);
|
||||
SyncTime_CURL_Fetch(curl, conf->timeserver, "index.htm",
|
||||
HTTP_COMMAND_HEAD);
|
||||
|
||||
|
@@ -5,7 +5,7 @@
|
||||
.\" * | (__| |_| | _ <| |___
|
||||
.\" * \___|\___/|_| \_\_____|
|
||||
.\" *
|
||||
.\" * Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
.\" * Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
.\" *
|
||||
.\" * This software is licensed as described in the file COPYING, which
|
||||
.\" * you should have received as part of this distribution. The terms
|
||||
@@ -21,7 +21,7 @@
|
||||
.\" * $Id$
|
||||
.\" **************************************************************************
|
||||
.\"
|
||||
.TH curl_easy_setopt 3 "19 Apr 2006" "libcurl 7.15.4" "libcurl Manual"
|
||||
.TH curl_easy_setopt 3 "2 Nov 2006" "libcurl 7.16.1" "libcurl Manual"
|
||||
.SH NAME
|
||||
curl_easy_setopt \- set options for a curl easy handle
|
||||
.SH SYNOPSIS
|
||||
@@ -925,6 +925,12 @@ Try "AUTH SSL" first, and only if that fails try "AUTH TLS"
|
||||
.IP CURLFTPAUTH_TLS
|
||||
Try "AUTH TLS" first, and only if that fails try "AUTH SSL"
|
||||
.RE
|
||||
.IP CURLOPT_FTP_SSL_CCC
|
||||
Pass a long that is set to 0 to disable and 1 to enable. If enabled, this
|
||||
option makes libcurl use CCC (Clear Command Channel). It shuts down the
|
||||
SSL/TLS layer after authenticating. The rest of the control channel
|
||||
communication will be unencrypted. This allows NAT routers to follow the FTP
|
||||
transaction. (Added in 7.16.1)
|
||||
.IP CURLOPT_FTP_ACCOUNT
|
||||
Pass a pointer to a zero-terminated string (or NULL to disable). When an FTP
|
||||
server asks for "account data" after user name and password has been provided,
|
||||
@@ -1008,10 +1014,16 @@ to POST with \fICURLOPT_POST\fP etc.
|
||||
When uploading a file to a remote site, this option should be used to tell
|
||||
libcurl what the expected size of the infile is. This value should be passed
|
||||
as a long. See also \fICURLOPT_INFILESIZE_LARGE\fP.
|
||||
|
||||
Note that this option does not limit how much data libcurl will actually send,
|
||||
as that is controlled entirely by what the read callback returns.
|
||||
.IP CURLOPT_INFILESIZE_LARGE
|
||||
When uploading a file to a remote site, this option should be used to tell
|
||||
libcurl what the expected size of the infile is. This value should be passed
|
||||
as a curl_off_t. (Added in 7.11.0)
|
||||
|
||||
Note that this option does not limit how much data libcurl will actually send,
|
||||
as that is controlled entirely by what the read callback returns.
|
||||
.IP CURLOPT_UPLOAD
|
||||
A non-zero parameter tells the library to prepare for an upload. The
|
||||
\fICURLOPT_READDATA\fP and \fICURLOPT_INFILESIZE\fP or
|
||||
@@ -1092,23 +1104,14 @@ value unless you are perfectly aware of how this work and changes libcurl's
|
||||
behaviour. This concerns connection using any of the protocols that support
|
||||
persistent connections.
|
||||
|
||||
When reaching the maximum limit, curl uses the \fICURLOPT_CLOSEPOLICY\fP to
|
||||
figure out which of the existing connections to close to prevent the number of
|
||||
open connections to increase.
|
||||
When reaching the maximum limit, curl closes the oldest one in the cache to
|
||||
prevent the number of open connections to increase.
|
||||
|
||||
If you already have performed transfers with this curl handle, setting a
|
||||
smaller MAXCONNECTS than before may cause open connections to get closed
|
||||
unnecessarily.
|
||||
.IP CURLOPT_CLOSEPOLICY
|
||||
Pass a long. This option sets what policy libcurl should use when the
|
||||
connection cache is filled and one of the open connections has to be closed to
|
||||
make room for a new connection. This must be one of the CURLCLOSEPOLICY_*
|
||||
defines. Use \fICURLCLOSEPOLICY_LEAST_RECENTLY_USED\fP to make libcurl close
|
||||
the connection that was least recently used, that connection is also least
|
||||
likely to be capable of re-use. Use \fICURLCLOSEPOLICY_OLDEST\fP to make
|
||||
libcurl close the oldest connection, the one that was created first among the
|
||||
ones in the connection cache. The other close policies are not support
|
||||
yet.
|
||||
(Obsolete) This option does nothing.
|
||||
.IP CURLOPT_FRESH_CONNECT
|
||||
Pass a long. Set to non-zero to make the next transfer use a new (fresh)
|
||||
connection by force. If the connection cache is full before this connection,
|
||||
@@ -1246,14 +1249,14 @@ even indicate an accessible file.
|
||||
Note that option is by default set to the system path where libcurl's cacert
|
||||
bundle is assumed to be stored, as established at build time.
|
||||
.IP CURLOPT_CAPATH
|
||||
Pass a char * to a zero terminated string naming a directory holding
|
||||
multiple CA certificates to verify the peer with. The certificate
|
||||
directory must be prepared using the openssl c_rehash utility. This
|
||||
makes sense only when used in combination with the
|
||||
\fICURLOPT_SSL_VERIFYPEER\fP option. If \fICURLOPT_SSL_VERIFYPEER\fP
|
||||
is zero, \fICURLOPT_CAPATH\fP need not even indicate an accessible
|
||||
path. The \fICURLOPT_CAPATH\fP function apparently does not work in
|
||||
Windows due to some limitation in openssl. (Added in 7.9.8)
|
||||
Pass a char * to a zero terminated string naming a directory holding multiple
|
||||
CA certificates to verify the peer with. The certificate directory must be
|
||||
prepared using the openssl c_rehash utility. This makes sense only when used
|
||||
in combination with the \fICURLOPT_SSL_VERIFYPEER\fP option. If
|
||||
\fICURLOPT_SSL_VERIFYPEER\fP is zero, \fICURLOPT_CAPATH\fP need not even
|
||||
indicate an accessible path. The \fICURLOPT_CAPATH\fP function apparently
|
||||
does not work in Windows due to some limitation in openssl. This option is
|
||||
OpenSSL-specific and does nothing if libcurl is built to use GnuTLS.
|
||||
.IP CURLOPT_RANDOM_FILE
|
||||
Pass a char * to a zero terminated file name. The file will be used to read
|
||||
from to seed the random engine for SSL. The more random the specified file is,
|
||||
@@ -1312,6 +1315,17 @@ krb4 awareness. This is a string, 'clear', 'safe', 'confidential' or
|
||||
\&'private'. If the string is set but doesn't match one of these, 'private'
|
||||
will be used. Set the string to NULL to disable kerberos4. The kerberos
|
||||
support only works for FTP.
|
||||
.SH SSH OPTIONS
|
||||
.IP CURLOPT_SSH_AUTH_TYPES
|
||||
Pass a long set to a bitmask consisting of one or more of
|
||||
CURLSSH_AUTH_PUBLICKEY, CURLSSH_AUTH_PASSWORD, CURLSSH_AUTH_HOST,
|
||||
CURLSSH_AUTH_KEYBOARD. Set CURLSSH_AUTH_ANY to let libcurl pick one.
|
||||
.IP CURLOPT_SSH_PUBLIC_KEYFILE
|
||||
Pass a char * pointing to a file name for your public key. If not used,
|
||||
libcurl defaults to using \fB~/.ssh/id_dsa.pub\fP.
|
||||
.IP CURLOPT_SSH_PRIVATE_KEYFILE
|
||||
Pass a char * pointing to a file name for your private key. If not used,
|
||||
libcurl defaults to using \fB~/.ssh/id_dsa\fP.
|
||||
.SH OTHER OPTIONS
|
||||
.IP CURLOPT_PRIVATE
|
||||
Pass a char * as parameter, pointing to data that should be associated with
|
||||
|
@@ -26,7 +26,8 @@ again. It will instead return new messages at each new invoke until the queue
|
||||
is emptied.
|
||||
|
||||
The data the returned pointer points to will not survive calling
|
||||
\fIcurl_multi_cleanup(3)\fP or \fIcurl_multi_remove_handle(3)\fP.
|
||||
\fIcurl_multi_cleanup(3)\fP, \fIcurl_multi_remove_handle(3)\fP or
|
||||
\fIcurl_easy_cleanup(3)\fP.
|
||||
|
||||
The 'CURLMsg' struct is very simple and only contain very basic information.
|
||||
If more involved information is wanted, the particular "easy handle" in
|
||||
|
@@ -24,8 +24,9 @@ The list should be freed again (after usage) with
|
||||
A null pointer is returned if anything went wrong, otherwise the new list
|
||||
pointer is returned.
|
||||
.SH EXAMPLE
|
||||
.nf
|
||||
CURL handle;
|
||||
curl_slist *slist=NULL;
|
||||
struct curl_slist *slist=NULL;
|
||||
|
||||
slist = curl_slist_append(slist, "pragma:");
|
||||
curl_easy_setopt(handle, CURLOPT_HTTPHEADER, slist);
|
||||
@@ -33,5 +34,6 @@ pointer is returned.
|
||||
curl_easy_perform(handle);
|
||||
|
||||
curl_slist_free_all(slist); /* free the list again */
|
||||
.fi
|
||||
.SH "SEE ALSO"
|
||||
.BR curl_slist_free_all "(3), "
|
||||
|
@@ -21,7 +21,7 @@
|
||||
.\" * $Id$
|
||||
.\" **************************************************************************
|
||||
.\"
|
||||
.TH curl_version_info 3 "19 Apr 2006" "libcurl 7.15.4" "libcurl Manual"
|
||||
.TH curl_version_info 3 "2 Nov 2006" "libcurl 7.16.1" "libcurl Manual"
|
||||
.SH NAME
|
||||
curl_version_info - returns run-time libcurl version info
|
||||
.SH SYNOPSIS
|
||||
@@ -66,6 +66,11 @@ typedef struct {
|
||||
/* when 'age' is 2 or higher, the member below also exists: */
|
||||
const char *libidn; /* human readable string */
|
||||
|
||||
/* when 'age' is 3 or higher, the members below also exist: */
|
||||
int iconv_ver_num; /* '_libiconv_version' if iconv support enabled */
|
||||
|
||||
const char *libssh_version; /* human readable string */
|
||||
|
||||
} curl_version_info_data;
|
||||
.fi
|
||||
|
||||
|
@@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -392,6 +392,13 @@ typedef enum {
|
||||
CURLOPT_CONV_FROM_UTF8_FUNCTION */
|
||||
CURLE_SSL_CACERT_BADFILE, /* 77 - could not load CACERT file, missing
|
||||
or wrong format */
|
||||
CURLE_REMOTE_FILE_NOT_FOUND, /* 78 - remote file not found */
|
||||
CURLE_SSH, /* 79 - error from the SSH layer, somewhat
|
||||
generic so the error message will be of
|
||||
interest when this has happened */
|
||||
|
||||
CURLE_SSL_SHUTDOWN_FAILED, /* 80 - Failed to shut down the SSL
|
||||
connection */
|
||||
CURL_LAST /* never use! */
|
||||
} CURLcode;
|
||||
|
||||
@@ -427,6 +434,14 @@ typedef enum {
|
||||
#define CURLAUTH_ANY ~0 /* all types set */
|
||||
#define CURLAUTH_ANYSAFE (~CURLAUTH_BASIC)
|
||||
|
||||
#define CURLSSH_AUTH_ANY ~0 /* all types supported by the server */
|
||||
#define CURLSSH_AUTH_NONE 0 /* none allowed, silly but complete */
|
||||
#define CURLSSH_AUTH_PUBLICKEY (1<<0) /* public/private key files */
|
||||
#define CURLSSH_AUTH_PASSWORD (1<<1) /* password */
|
||||
#define CURLSSH_AUTH_HOST (1<<2) /* host key files */
|
||||
#define CURLSSH_AUTH_KEYBOARD (1<<3) /* keyboard interactive */
|
||||
#define CURLSSH_AUTH_DEFAULT CURLSSH_AUTH_ANY
|
||||
|
||||
#ifndef CURL_NO_OLDIES /* define this to test if your app builds with all
|
||||
the obsolete stuff removed! */
|
||||
/* this was the error code 50 in 7.7.3 and a few earlier versions, this
|
||||
@@ -1029,6 +1044,16 @@ typedef enum {
|
||||
enabled (== 1) */
|
||||
CINIT(SSL_SESSIONID_CACHE, LONG, 150),
|
||||
|
||||
/* allowed SSH authentication methods */
|
||||
CINIT(SSH_AUTH_TYPES, LONG, 151),
|
||||
|
||||
/* Used by scp/sftp to do public/private key authentication */
|
||||
CINIT(SSH_PUBLIC_KEYFILE, OBJECTPOINT, 152),
|
||||
CINIT(SSH_PRIVATE_KEYFILE, OBJECTPOINT, 153),
|
||||
|
||||
/* Send CCC (Clear Command Channel) after authentication */
|
||||
CINIT(FTP_SSL_CCC, LONG, 154),
|
||||
|
||||
CURLOPT_LASTENTRY /* the last unused */
|
||||
} CURLoption;
|
||||
|
||||
@@ -1506,6 +1531,7 @@ typedef enum {
|
||||
CURLVERSION_FIRST,
|
||||
CURLVERSION_SECOND,
|
||||
CURLVERSION_THIRD,
|
||||
CURLVERSION_FOURTH,
|
||||
CURLVERSION_LAST /* never actually use this */
|
||||
} CURLversion;
|
||||
|
||||
@@ -1514,7 +1540,7 @@ typedef enum {
|
||||
meant to be a built-in version number for what kind of struct the caller
|
||||
expects. If the struct ever changes, we redefine the NOW to another enum
|
||||
from above. */
|
||||
#define CURLVERSION_NOW CURLVERSION_THIRD
|
||||
#define CURLVERSION_NOW CURLVERSION_FOURTH
|
||||
|
||||
typedef struct {
|
||||
CURLversion age; /* age of the returned struct */
|
||||
@@ -1535,8 +1561,13 @@ typedef struct {
|
||||
/* This field was added in CURLVERSION_THIRD */
|
||||
const char *libidn;
|
||||
|
||||
/* These field were added in CURLVERSION_FOURTH */
|
||||
|
||||
/* Same as '_libiconv_version' if built with HAVE_ICONV */
|
||||
int iconv_ver_num;
|
||||
|
||||
const char *libssh_version; /* human readable string */
|
||||
|
||||
} curl_version_info_data;
|
||||
|
||||
#define CURL_VERSION_IPV6 (1<<0) /* IPv6-enabled */
|
||||
|
@@ -28,13 +28,13 @@
|
||||
|
||||
/* This is the version number of the libcurl package from which this header
|
||||
file origins: */
|
||||
#define LIBCURL_VERSION "7.16.0-CVS"
|
||||
#define LIBCURL_VERSION "7.16.1-CVS"
|
||||
|
||||
/* The numeric version number is also available "in parts" by using these
|
||||
defines: */
|
||||
#define LIBCURL_VERSION_MAJOR 7
|
||||
#define LIBCURL_VERSION_MINOR 16
|
||||
#define LIBCURL_VERSION_PATCH 0
|
||||
#define LIBCURL_VERSION_PATCH 1
|
||||
|
||||
/* This is the numeric version of the libcurl version number, meant for easier
|
||||
parsing and comparions by programs. The LIBCURL_VERSION_NUM define will
|
||||
@@ -51,6 +51,6 @@
|
||||
and it is always a greater number in a more recent release. It makes
|
||||
comparisons with greater than and less than work.
|
||||
*/
|
||||
#define LIBCURL_VERSION_NUM 0x071000
|
||||
#define LIBCURL_VERSION_NUM 0x071001
|
||||
|
||||
#endif /* __CURL_CURLVER_H */
|
||||
|
@@ -28,6 +28,10 @@
|
||||
|
||||
#include "curl.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
CURL_EXTERN int curl_mprintf(const char *format, ...);
|
||||
CURL_EXTERN int curl_mfprintf(FILE *fd, const char *format, ...);
|
||||
CURL_EXTERN int curl_msprintf(char *buffer, const char *format, ...);
|
||||
@@ -59,4 +63,8 @@ CURL_EXTERN char *curl_mvaprintf(const char *format, va_list args);
|
||||
# define vaprintf curl_mvaprintf
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __CURL_MPRINTF_H */
|
||||
|
@@ -8,7 +8,7 @@ CSOURCES = file.c timeval.c base64.c hostip.c progress.c formdata.c \
|
||||
content_encoding.c share.c http_digest.c md5.c http_negotiate.c \
|
||||
http_ntlm.c inet_pton.c strtoofft.c strerror.c hostares.c hostasyn.c \
|
||||
hostip4.c hostip6.c hostsyn.c hostthre.c inet_ntop.c parsedate.c \
|
||||
select.c gtls.c sslgen.c tftp.c splay.c strdup.c socks.c
|
||||
select.c gtls.c sslgen.c tftp.c splay.c strdup.c socks.c ssh.c
|
||||
|
||||
HHEADERS = arpa_telnet.h netrc.h file.h timeval.h base64.h hostip.h \
|
||||
progress.h formdata.h cookie.h http.h sendf.h ftp.h url.h dict.h \
|
||||
@@ -18,6 +18,6 @@ HHEADERS = arpa_telnet.h netrc.h file.h timeval.h base64.h hostip.h \
|
||||
share.h md5.h http_digest.h http_negotiate.h http_ntlm.h ca-bundle.h \
|
||||
inet_pton.h strtoofft.h strerror.h inet_ntop.h curlx.h memory.h \
|
||||
setup.h transfer.h select.h easyif.h multiif.h parsedate.h sslgen.h \
|
||||
gtls.h tftp.h sockaddr.h splay.h strdup.h setup_once.h socks.h
|
||||
gtls.h tftp.h sockaddr.h splay.h strdup.h setup_once.h socks.h ssh.h
|
||||
|
||||
|
||||
|
@@ -2,18 +2,21 @@
|
||||
# $Id$
|
||||
#
|
||||
## Makefile for building libcurl.a with MingW32 (GCC-3.2) and
|
||||
## optionally OpenSSL (0.9.7)
|
||||
## optionally OpenSSL (0.9.8)
|
||||
##
|
||||
## Use: make -f Makefile.m32
|
||||
## Use: make -f Makefile.m32 [SSL=1] [SSH2=1] [DYN=1]
|
||||
##
|
||||
## Comments to: Troy Engel <tengel@sonic.net> or
|
||||
## Joern Hartroth <hartroth@acm.org>
|
||||
|
||||
ifndef OPENSSL_PATH
|
||||
OPENSSL_PATH = ../../openssl-0.9.7d
|
||||
OPENSSL_PATH = ../../openssl-0.9.8d
|
||||
endif
|
||||
ifndef LIBSSH2_PATH
|
||||
LIBSSH2_PATH = ../../libssh2-0.14
|
||||
endif
|
||||
ifndef ZLIB_PATH
|
||||
ZLIB_PATH = ../../zlib-1.2.1
|
||||
ZLIB_PATH = ../../zlib-1.2.3
|
||||
endif
|
||||
|
||||
CC = gcc
|
||||
@@ -26,19 +29,27 @@ STRIP = strip -g
|
||||
## Nothing more to do below this line!
|
||||
|
||||
INCLUDES = -I. -I../include
|
||||
CFLAGS = -g -O2 -DMINGW32 -DBUILDING_LIBCURL -DHAVE_LONGLONG
|
||||
CFLAGS = -g -O2 -DBUILDING_LIBCURL -DHAVE_LONGLONG
|
||||
ifdef SSH2
|
||||
INCLUDES += -I"$(LIBSSH2_PATH)/include" -I"$(LIBSSH2_PATH)/win32"
|
||||
CFLAGS += -DUSE_LIBSSH2 -DHAVE_LIBSSH2_H
|
||||
DLL_LIBS += -L$(LIBSSH2_PATH)/win32 -lssh2
|
||||
endif
|
||||
ifdef SSL
|
||||
INCLUDES += -I"$(OPENSSL_PATH)/outinc" -I"$(OPENSSL_PATH)/outinc/openssl"
|
||||
CFLAGS += -DUSE_SSLEAY -DUSE_OPENSSL -DHAVE_OPENSSL_ENGINE_H -DHAVE_OPENSSL_PKCS12_H \
|
||||
-DHAVE_ENGINE_LOAD_BUILTIN_ENGINES -DOPENSSL_NO_KRB5 \
|
||||
-DCURL_CA_BUNDLE='getenv("CURL_CA_BUNDLE")'
|
||||
DLL_LIBS = -L$(OPENSSL_PATH)/out -leay32 -lssl32
|
||||
-DCURL_WANTS_CA_BUNDLE_ENV
|
||||
DLL_LIBS += -L$(OPENSSL_PATH)/out -leay32 -lssl32
|
||||
endif
|
||||
ifdef ZLIB
|
||||
INCLUDES += -I"$(ZLIB_PATH)"
|
||||
CFLAGS += -DHAVE_LIBZ -DHAVE_ZLIB_H
|
||||
DLL_LIBS += -L$(ZLIB_PATH) -lz
|
||||
endif
|
||||
ifdef SSPI
|
||||
CFLAGS += -DUSE_WINDOWS_SSPI
|
||||
endif
|
||||
COMPILE = $(CC) $(INCLUDES) $(CFLAGS)
|
||||
|
||||
# Makefile.inc provides the CSOURCES and HHEADERS defines
|
||||
|
@@ -19,7 +19,12 @@ endif
|
||||
|
||||
# Edit the path below to point to the base of your OpenSSL package.
|
||||
ifndef OPENSSL_PATH
|
||||
OPENSSL_PATH = ../../openssl-0.9.8c
|
||||
OPENSSL_PATH = ../../openssl-0.9.8d
|
||||
endif
|
||||
|
||||
# Edit the path below to point to the base of your LibSSH2 package.
|
||||
ifndef LIBSSH2_PATH
|
||||
LIBSSH2_PATH = ../../libssh2-0.14
|
||||
endif
|
||||
|
||||
ifndef INSTDIR
|
||||
@@ -29,7 +34,7 @@ endif
|
||||
# Edit the vars below to change NLM target settings.
|
||||
TARGET = libcurl
|
||||
VERSION = $(LIBCURL_VERSION)
|
||||
COPYR = Copyright (C) 1996 - 2006, Daniel Stenberg, <daniel@haxx.se>
|
||||
COPYR = Copyright (C) 1996 - 2007, Daniel Stenberg, <daniel@haxx.se>
|
||||
DESCR = cURL libcurl $(LIBCURL_VERSION_STR) - http://curl.haxx.se
|
||||
MTSAFE = YES
|
||||
STACK = 64000
|
||||
@@ -63,6 +68,7 @@ ifdef METROWERKS
|
||||
else
|
||||
CC = gcc
|
||||
endif
|
||||
AWK = awk
|
||||
YACC = bison -y
|
||||
CP = cp -afv
|
||||
# RM = rm -f
|
||||
@@ -121,6 +127,15 @@ ifdef WITH_SSL
|
||||
LDLIBS += $(OPENSSL_PATH)/out_nw_libc/crypto.lib $(OPENSSL_PATH)/out_nw_libc/ssl.lib
|
||||
IMPORTS += GetProcessSwitchCount RunningProcess
|
||||
endif
|
||||
ifdef WITH_SSH2
|
||||
INCLUDES += -I$(LIBSSH2_PATH)/include
|
||||
ifdef LINK_STATIC
|
||||
LDLIBS += $(LIBSSH2_PATH)/nw/libssh2.lib
|
||||
else
|
||||
IMPORTS += @$(LIBSSH2_PATH)/nw/libssh2.imp
|
||||
MODULES += libssh2.nlm
|
||||
endif
|
||||
endif
|
||||
ifdef WITH_ZLIB
|
||||
INCLUDES += -I$(ZLIB_PATH)
|
||||
ifdef LINK_STATIC
|
||||
@@ -184,7 +199,7 @@ $(OBJDIR)/%.o: %.c
|
||||
|
||||
$(OBJDIR)/version.inc: ../include/curl/curlver.h $(OBJDIR)
|
||||
@echo Creating $@
|
||||
@awk -f ../packages/NetWare/get_ver.awk $< > $@
|
||||
@$(AWK) -f ../packages/NetWare/get_ver.awk $< > $@
|
||||
|
||||
dist: all
|
||||
-$(RM) $(OBJDIR)/*.o $(OBJDIR)/$(TARGET).map $(OBJDIR)/$(TARGET).ncv
|
||||
@@ -205,6 +220,9 @@ clean:
|
||||
-$(RM) config.h ca-bundle.h
|
||||
-$(RM) -r $(OBJDIR)
|
||||
|
||||
distclean: clean
|
||||
-$(RM) -r $(TARGET).lib $(TARGET).nlm
|
||||
|
||||
$(INSTDIR):
|
||||
@mkdir $(INSTDIR)
|
||||
|
||||
@@ -324,6 +342,8 @@ config.h: Makefile.netware
|
||||
@echo $(DL)#define HAVE_SEND 1$(DL) >> $@
|
||||
@echo $(DL)#define HAVE_SETJMP_H 1$(DL) >> $@
|
||||
@echo $(DL)#define HAVE_SIGNAL 1$(DL) >> $@
|
||||
@echo $(DL)#define HAVE_SIGNAL_H 1$(DL) >> $@
|
||||
@echo $(DL)#define HAVE_SIG_ATOMIC_T 1$(DL) >> $@
|
||||
@echo $(DL)#define HAVE_SOCKET 1$(DL) >> $@
|
||||
@echo $(DL)#define HAVE_STDINT_H 1$(DL) >> $@
|
||||
@echo $(DL)#define HAVE_STDLIB_H 1$(DL) >> $@
|
||||
@@ -402,28 +422,44 @@ ifdef WITH_SSL
|
||||
@echo $(DL)#define HAVE_LIBCRYPTO 1$(DL) >> $@
|
||||
@echo $(DL)#define OPENSSL_NO_KRB5 1$(DL) >> $@
|
||||
endif
|
||||
ifdef WITH_SSH2
|
||||
@echo $(DL)#define USE_LIBSSH2 1$(DL) >> $@
|
||||
@echo $(DL)#define HAVE_LIBSSH2_H 1$(DL) >> $@
|
||||
endif
|
||||
ifdef OLD_NOVELLSDK
|
||||
@echo $(DL)#define socklen_t int$(DL) >> $@
|
||||
endif
|
||||
|
||||
ca-bundle.h: Makefile.netware
|
||||
FORCE: ;
|
||||
|
||||
ca-bundle.h: FORCE Makefile.netware
|
||||
@echo Creating $@
|
||||
@echo $(DL)/* Do not edit this file - it is created by make!$(DL) > $@
|
||||
@echo $(DL)** All your changes will be lost!!$(DL) >> $@
|
||||
@echo $(DL)*/$(DL) >> $@
|
||||
ifdef CABUNDLE
|
||||
@echo $(DL)#define CURL_CA_BUNDLE "$(CABUNDLE)"$(DL) >> $@
|
||||
else
|
||||
@echo $(DL)#define CURL_CA_BUNDLE getenv("CURL_CA_BUNDLE")$(DL) >> $@
|
||||
|
||||
url.c: ca-bundle.h
|
||||
endif
|
||||
|
||||
info: $(OBJDIR)/version.inc
|
||||
@echo Configured to build $(TARGET) with these options:
|
||||
@echo curl version: $(LIBCURL_VERSION_STR)
|
||||
@echo compiler/linker: $(CC) / $(LD)
|
||||
ifdef CABUNDLE
|
||||
@echo ca-bundle path: $(CABUNDLE)
|
||||
endif
|
||||
ifdef WITH_SSL
|
||||
@echo SSL support: enabled (OpenSSL)
|
||||
else
|
||||
@echo SSL support: no
|
||||
endif
|
||||
ifdef WITH_SSH2
|
||||
@echo SSH2 support: enabled (libssh2)
|
||||
else
|
||||
@echo SSH2 support: no
|
||||
endif
|
||||
ifdef WITH_ZLIB
|
||||
@echo zlib support: enabled
|
||||
else
|
||||
|
@@ -12,11 +12,11 @@ c-ares:
|
||||
http://daniel.haxx.se/projects/c-ares/
|
||||
|
||||
NOTE
|
||||
libcurl 7.11.1 builds with c-ares 1.1.0, but 7.11.2 and later require c-ares
|
||||
1.2.0 or alter.
|
||||
The latest libcurl version requires c-ares 1.3.2 or later to work
|
||||
flawlessly.
|
||||
|
||||
Once upon the time libcurl built fine with the "original" ares. That is no
|
||||
longer true. You need to use c-ares. c-ares is based on ares but improved.
|
||||
longer true. You need to use c-ares.
|
||||
|
||||
Build c-ares
|
||||
============
|
||||
|
96
lib/base64.c
96
lib/base64.c
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -40,28 +40,27 @@
|
||||
#define _MPRINTF_REPLACE /* use our functions only */
|
||||
#include <curl/mprintf.h>
|
||||
|
||||
#include "urldata.h" /* for the SessionHandle definition */
|
||||
#include "easyif.h" /* for Curl_convert_... prototypes */
|
||||
#include "base64.h"
|
||||
#include "memory.h"
|
||||
|
||||
/* include memdebug.h last */
|
||||
#include "memdebug.h"
|
||||
|
||||
/* ---- Base64 Encoding/Decoding Table --- */
|
||||
static const char table64[]=
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
|
||||
static void decodeQuantum(unsigned char *dest, const char *src)
|
||||
{
|
||||
unsigned int x = 0;
|
||||
int i;
|
||||
char *found;
|
||||
|
||||
for(i = 0; i < 4; i++) {
|
||||
if(src[i] >= 'A' && src[i] <= 'Z')
|
||||
x = (x << 6) + (unsigned int)(src[i] - 'A' + 0);
|
||||
else if(src[i] >= 'a' && src[i] <= 'z')
|
||||
x = (x << 6) + (unsigned int)(src[i] - 'a' + 26);
|
||||
else if(src[i] >= '0' && src[i] <= '9')
|
||||
x = (x << 6) + (unsigned int)(src[i] - '0' + 52);
|
||||
else if(src[i] == '+')
|
||||
x = (x << 6) + 62;
|
||||
else if(src[i] == '/')
|
||||
x = (x << 6) + 63;
|
||||
if((found = strchr(table64, src[i])))
|
||||
x = (x << 6) + (unsigned int)(found - table64);
|
||||
else if(src[i] == '=')
|
||||
x = (x << 6);
|
||||
}
|
||||
@@ -133,10 +132,6 @@ size_t Curl_base64_decode(const char *src, unsigned char **outptr)
|
||||
return rawlen;
|
||||
}
|
||||
|
||||
/* ---- Base64 Encoding --- */
|
||||
static const char table64[]=
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
|
||||
/*
|
||||
* Curl_base64_encode()
|
||||
*
|
||||
@@ -145,7 +140,8 @@ static const char table64[]=
|
||||
* went wrong, -1 is returned.
|
||||
*
|
||||
*/
|
||||
size_t Curl_base64_encode(const char *inp, size_t insize, char **outptr)
|
||||
size_t Curl_base64_encode(struct SessionHandle *data,
|
||||
const char *inp, size_t insize, char **outptr)
|
||||
{
|
||||
unsigned char ibuf[3];
|
||||
unsigned char obuf[4];
|
||||
@@ -153,6 +149,9 @@ size_t Curl_base64_encode(const char *inp, size_t insize, char **outptr)
|
||||
int inputparts;
|
||||
char *output;
|
||||
char *base64data;
|
||||
#ifdef CURL_DOES_CONVERSIONS
|
||||
char *convbuf;
|
||||
#endif
|
||||
|
||||
char *indata = (char *)inp;
|
||||
|
||||
@@ -165,6 +164,28 @@ size_t Curl_base64_encode(const char *inp, size_t insize, char **outptr)
|
||||
if(NULL == output)
|
||||
return 0;
|
||||
|
||||
#ifdef CURL_DOES_CONVERSIONS
|
||||
/*
|
||||
* The base64 data needs to be created using the network encoding
|
||||
* not the host encoding. And we can't change the actual input
|
||||
* so we copy it to a buffer, translate it, and use that instead.
|
||||
*/
|
||||
if(data) {
|
||||
convbuf = (char*)malloc(insize);
|
||||
if(!convbuf) {
|
||||
return 0;
|
||||
}
|
||||
memcpy(convbuf, indata, insize);
|
||||
if(CURLE_OK != Curl_convert_to_network(data, convbuf, insize)) {
|
||||
free(convbuf);
|
||||
return 0;
|
||||
}
|
||||
indata = convbuf; /* switch to the converted buffer */
|
||||
}
|
||||
#else
|
||||
(void)data;
|
||||
#endif
|
||||
|
||||
while(insize > 0) {
|
||||
for (i = inputparts = 0; i < 3; i++) {
|
||||
if(insize > 0) {
|
||||
@@ -209,6 +230,10 @@ size_t Curl_base64_encode(const char *inp, size_t insize, char **outptr)
|
||||
*output=0;
|
||||
*outptr = base64data; /* make it return the actual data memory */
|
||||
|
||||
#ifdef CURL_DOES_CONVERSIONS
|
||||
if(data)
|
||||
free(convbuf);
|
||||
#endif
|
||||
return strlen(base64data); /* return the length of the new data */
|
||||
}
|
||||
/* ---- End of Base64 Encoding ---- */
|
||||
@@ -231,14 +256,26 @@ int main(int argc, char **argv, char **envp)
|
||||
size_t base64Len;
|
||||
unsigned char *data;
|
||||
int dataLen;
|
||||
struct SessionHandle *handle = NULL;
|
||||
|
||||
#ifdef CURL_DOES_CONVERSIONS
|
||||
/* get a Curl handle so Curl_base64_encode can translate properly */
|
||||
handle = curl_easy_init();
|
||||
if(handle == NULL) {
|
||||
fprintf(stderr, "Error: curl_easy_init failed\n");
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
data = (unsigned char *)suck(&dataLen);
|
||||
base64Len = Curl_base64_encode(data, dataLen, &base64);
|
||||
base64Len = Curl_base64_encode(handle, data, dataLen, &base64);
|
||||
|
||||
fprintf(stderr, "%d\n", base64Len);
|
||||
fprintf(stdout, "%s", base64);
|
||||
fprintf(stdout, "%s\n", base64);
|
||||
|
||||
free(base64); free(data);
|
||||
#ifdef CURL_DOES_CONVERSIONS
|
||||
curl_easy_cleanup(handle);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
@@ -261,10 +298,17 @@ int main(int argc, char **argv, char **envp)
|
||||
unsigned char *data;
|
||||
int dataLen;
|
||||
int i, j;
|
||||
#ifdef CURL_DOES_CONVERSIONS
|
||||
/* get a Curl handle so main can translate properly */
|
||||
struct SessionHandle *handle = curl_easy_init();
|
||||
if(handle == NULL) {
|
||||
fprintf(stderr, "Error: curl_easy_init failed\n");
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
base64 = (char *)suck(&base64Len);
|
||||
data = (unsigned char *)malloc(base64Len * 3/4 + 8);
|
||||
dataLen = Curl_base64_decode(base64, data);
|
||||
dataLen = Curl_base64_decode(base64, &data);
|
||||
|
||||
fprintf(stderr, "%d\n", dataLen);
|
||||
|
||||
@@ -279,13 +323,21 @@ int main(int argc, char **argv, char **envp)
|
||||
printf(" | ");
|
||||
|
||||
for(j=0; j < 0x10; j++)
|
||||
if((j+i) < dataLen)
|
||||
if((j+i) < dataLen) {
|
||||
#ifdef CURL_DOES_CONVERSIONS
|
||||
if(CURLE_OK !=
|
||||
Curl_convert_from_network(handle, &data[i+j], (size_t)1))
|
||||
data[i+j] = '.';
|
||||
#endif /* CURL_DOES_CONVERSIONS */
|
||||
printf("%c", ISGRAPH(data[i+j])?data[i+j]:'.');
|
||||
else
|
||||
} else
|
||||
break;
|
||||
puts("");
|
||||
}
|
||||
|
||||
#ifdef CURL_DOES_CONVERSIONS
|
||||
curl_easy_cleanup(handle);
|
||||
#endif
|
||||
free(base64); free(data);
|
||||
return 0;
|
||||
}
|
||||
|
@@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2005, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -22,6 +22,7 @@
|
||||
*
|
||||
* $Id$
|
||||
***************************************************************************/
|
||||
size_t Curl_base64_encode(const char *input, size_t size, char **str);
|
||||
size_t Curl_base64_encode(struct SessionHandle *data,
|
||||
const char *input, size_t size, char **str);
|
||||
size_t Curl_base64_decode(const char *source, unsigned char **outptr);
|
||||
#endif
|
||||
|
@@ -31,6 +31,8 @@
|
||||
#define HAVE_SETJMP_H 1
|
||||
#define HAVE_SGTTY_H 1
|
||||
#define HAVE_SIGNAL 1
|
||||
#define HAVE_SIGNAL_H 1
|
||||
#define HAVE_SIG_ATOMIC_T 1
|
||||
#define HAVE_SOCKET 1
|
||||
#define HAVE_STRCASECMP 1
|
||||
#define HAVE_STRDUP 1
|
||||
|
@@ -32,6 +32,8 @@
|
||||
|
||||
//#define HAVE_STRICMP 1
|
||||
#define HAVE_SIGACTION 1
|
||||
#define HAVE_SIGNAL_H 1
|
||||
#define HAVE_SIG_ATOMIC_T 1
|
||||
|
||||
#ifdef MACOS_SSL_SUPPORT
|
||||
# define USE_SSLEAY 1
|
||||
@@ -45,6 +47,8 @@
|
||||
|
||||
#define HAVE_FIONBIO 1
|
||||
|
||||
#define RETSIGTYPE void
|
||||
|
||||
#define HAVE_GETNAMEINFO 1
|
||||
#define GETNAMEINFO_QUAL_ARG1 const
|
||||
#define GETNAMEINFO_TYPE_ARG1 struct sockaddr *
|
||||
|
@@ -245,6 +245,15 @@
|
||||
/* Define if you have the `signal' function. */
|
||||
#define HAVE_SIGNAL
|
||||
|
||||
/* Define if you have the <signal.h> header file. */
|
||||
#define HAVE_SIGNAL_H
|
||||
|
||||
/* Define if sig_atomic_t is an available typedef. */
|
||||
#define HAVE_SIG_ATOMIC_T
|
||||
|
||||
/* Define if sig_atomic_t is already defined as volatile. */
|
||||
#undef HAVE_SIG_ATOMIC_T_VOLATILE
|
||||
|
||||
/* Define if you have the `socket' function. */
|
||||
#define HAVE_SOCKET
|
||||
|
||||
|
@@ -413,6 +413,15 @@
|
||||
/* Define to 1 if you have the `signal' function. */
|
||||
#define HAVE_SIGNAL 1
|
||||
|
||||
/* Define to 1 if you have the <signal.h> header file. */
|
||||
#define HAVE_SIGNAL_H 1
|
||||
|
||||
/* Define to 1 if sig_atomic_t is an available typedef. */
|
||||
#define HAVE_SIG_ATOMIC_T 1
|
||||
|
||||
/* Define to 1 if sig_atomic_t is already defined as volatile. */
|
||||
/* #undef HAVE_SIG_ATOMIC_T_VOLATILE */
|
||||
|
||||
/* If you have sigsetjmp */
|
||||
/* #undef HAVE_SIGSETJMP */
|
||||
|
||||
|
@@ -57,6 +57,9 @@
|
||||
#define HAVE_PROCESS_H 1
|
||||
#endif
|
||||
|
||||
/* Define if you have the <signal.h> header file. */
|
||||
#define HAVE_SIGNAL_H 1
|
||||
|
||||
/* Define if you have the <sgtty.h> header file. */
|
||||
/* #define HAVE_SGTTY_H 1 */
|
||||
|
||||
@@ -125,6 +128,9 @@
|
||||
/* OTHER HEADER INFO */
|
||||
/* ---------------------------------------------------------------- */
|
||||
|
||||
/* Define if sig_atomic_t is an available typedef. */
|
||||
#define HAVE_SIG_ATOMIC_T 1
|
||||
|
||||
/* Define if you have the ANSI C header files. */
|
||||
#define STDC_HEADERS 1
|
||||
|
||||
@@ -288,13 +294,11 @@
|
||||
#define in_addr_t unsigned long
|
||||
|
||||
/* Define as the return type of signal handlers (int or void). */
|
||||
/* #define RETSIGTYPE void */
|
||||
#define RETSIGTYPE void
|
||||
|
||||
/* Define to `unsigned' if size_t is not an available 'typedefed' type */
|
||||
/* #define size_t unsigned */
|
||||
|
||||
/* Define to 'int' if ssize_t is not an available 'typedefed' type */
|
||||
#if (defined(__WATCOMC__) && (__WATCOMC__ >= 1240)) || defined(__POCC__)
|
||||
#elif defined(_WIN64)
|
||||
#define ssize_t __int64
|
||||
#else
|
||||
#define ssize_t int
|
||||
#endif
|
||||
@@ -348,6 +352,11 @@
|
||||
/* Undef keyword 'const' if it does not work. */
|
||||
/* #undef const */
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER > 1310)
|
||||
/* MSVC 2003 has gmtime_r */
|
||||
#define HAVE_GMTIME_R
|
||||
#endif
|
||||
|
||||
/* ---------------------------------------------------------------- */
|
||||
/* LDAP LIBRARY FILES */
|
||||
/* ---------------------------------------------------------------- */
|
||||
|
@@ -48,6 +48,9 @@
|
||||
/* Define if you have the <netinet/in.h> header file. */
|
||||
/* #define HAVE_NETINET_IN_H 1 */
|
||||
|
||||
/* Define if you have the <signal.h> header file. */
|
||||
#define HAVE_SIGNAL_H 1
|
||||
|
||||
/* Define if you have the <sgtty.h> header file. */
|
||||
/* #define HAVE_SGTTY_H 1 */
|
||||
|
||||
@@ -114,6 +117,9 @@
|
||||
/* OTHER HEADER INFO */
|
||||
/* ---------------------------------------------------------------- */
|
||||
|
||||
/* Define if sig_atomic_t is an available typedef. */
|
||||
#define HAVE_SIG_ATOMIC_T 1
|
||||
|
||||
/* Define if you have the ANSI C header files. */
|
||||
#define STDC_HEADERS 1
|
||||
|
||||
@@ -272,13 +278,15 @@
|
||||
#define in_addr_t unsigned long
|
||||
|
||||
/* Define as the return type of signal handlers (int or void). */
|
||||
/* #define RETSIGTYPE void */
|
||||
#define RETSIGTYPE void
|
||||
|
||||
/* Define to `unsigned' if size_t is not an available 'typedefed' type */
|
||||
/* #define size_t unsigned */
|
||||
|
||||
/* Define to 'int' if ssize_t is not an available 'typedefed' type */
|
||||
/* Define ssize_t if it is not an available 'typedefed' type */
|
||||
#if (defined(__WATCOMC__) && (__WATCOMC__ >= 1240)) || defined(__POCC__)
|
||||
#elif defined(_WIN64)
|
||||
#define ssize_t __int64
|
||||
#else
|
||||
#define ssize_t int
|
||||
#endif
|
||||
|
||||
/* Define to 'int' if socklen_t is not an available 'typedefed' type */
|
||||
#ifndef HAVE_WS2TCPIP_H
|
||||
|
@@ -51,6 +51,8 @@
|
||||
#define HAVE_SETLOCALE 1
|
||||
#define HAVE_SETVBUF 1
|
||||
#define HAVE_SIGNAL 1
|
||||
#define HAVE_SIGNAL_H 1
|
||||
#define HAVE_SIG_ATOMIC_T 1
|
||||
#define HAVE_SOCKET 1
|
||||
#define HAVE_SPNEGO 1
|
||||
#define HAVE_STRDUP 1
|
||||
|
@@ -384,11 +384,10 @@ static CURLcode bindlocal(struct connectdata *conn,
|
||||
if( bind(sockfd, sock, socksize) >= 0) {
|
||||
/* we succeeded to bind */
|
||||
struct Curl_sockaddr_storage add;
|
||||
size_t size;
|
||||
socklen_t size;
|
||||
|
||||
size = sizeof(add);
|
||||
if(getsockname(sockfd, (struct sockaddr *) &add,
|
||||
(socklen_t *)&size)<0) {
|
||||
if(getsockname(sockfd, (struct sockaddr *) &add, &size) < 0) {
|
||||
failf(data, "getsockname() failed");
|
||||
return CURLE_HTTP_PORT_FAILED;
|
||||
}
|
||||
|
10
lib/cookie.c
10
lib/cookie.c
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -806,9 +806,11 @@ struct Cookie *Curl_cookie_getlist(struct CookieInfo *c,
|
||||
****************************************************************************/
|
||||
void Curl_cookie_clearall(struct CookieInfo *cookies)
|
||||
{
|
||||
Curl_cookie_freelist(cookies->cookies);
|
||||
cookies->cookies = NULL;
|
||||
cookies->numcookies = 0;
|
||||
if(cookies) {
|
||||
Curl_cookie_freelist(cookies->cookies);
|
||||
cookies->cookies = NULL;
|
||||
cookies->numcookies = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
|
21
lib/easy.c
21
lib/easy.c
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -87,6 +87,7 @@
|
||||
#include "progress.h"
|
||||
#include "easyif.h"
|
||||
#include "sendf.h" /* for failf function prototype */
|
||||
#include <ca-bundle.h>
|
||||
|
||||
#define _MPRINTF_REPLACE /* use our functions only */
|
||||
#include <curl/mprintf.h>
|
||||
@@ -471,7 +472,7 @@ CURLcode curl_easy_perform(CURL *curl)
|
||||
|
||||
if(!data->state.connc) {
|
||||
/* oops, no connection cache, make one up */
|
||||
data->state.connc = Curl_mk_connc(CONNCACHE_PRIVATE);
|
||||
data->state.connc = Curl_mk_connc(CONNCACHE_PRIVATE, -1);
|
||||
if(!data->state.connc)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
@@ -561,7 +562,7 @@ CURL *curl_easy_duphandle(CURL *incurl)
|
||||
if(data->state.used_interface == Curl_if_multi)
|
||||
outcurl->state.connc = data->state.connc;
|
||||
else
|
||||
outcurl->state.connc = Curl_mk_connc(CONNCACHE_PRIVATE);
|
||||
outcurl->state.connc = Curl_mk_connc(CONNCACHE_PRIVATE, -1);
|
||||
|
||||
if(!outcurl->state.connc)
|
||||
break;
|
||||
@@ -593,12 +594,7 @@ CURL *curl_easy_duphandle(CURL *incurl)
|
||||
break;
|
||||
outcurl->change.url_alloc = TRUE;
|
||||
}
|
||||
if(data->change.proxy) {
|
||||
outcurl->change.proxy = strdup(data->change.proxy);
|
||||
if(!outcurl->change.proxy)
|
||||
break;
|
||||
outcurl->change.proxy_alloc = TRUE;
|
||||
}
|
||||
|
||||
if(data->change.referer) {
|
||||
outcurl->change.referer = strdup(data->change.referer);
|
||||
if(!outcurl->change.referer)
|
||||
@@ -623,6 +619,8 @@ CURL *curl_easy_duphandle(CURL *incurl)
|
||||
|
||||
Curl_easy_initHandleData(outcurl);
|
||||
|
||||
outcurl->magic = CURLEASY_MAGIC_NUMBER;
|
||||
|
||||
fail = FALSE; /* we reach this point and thus we are OK */
|
||||
|
||||
} while(0);
|
||||
@@ -633,8 +631,6 @@ CURL *curl_easy_duphandle(CURL *incurl)
|
||||
Curl_rm_connc(outcurl->state.connc);
|
||||
if(outcurl->state.headerbuff)
|
||||
free(outcurl->state.headerbuff);
|
||||
if(outcurl->change.proxy)
|
||||
free(outcurl->change.proxy);
|
||||
if(outcurl->change.url)
|
||||
free(outcurl->change.url);
|
||||
if(outcurl->change.referer)
|
||||
@@ -715,6 +711,9 @@ void curl_easy_reset(CURL *curl)
|
||||
/* This is our prefered CA cert bundle since install time */
|
||||
data->set.ssl.CAfile = (char *)CURL_CA_BUNDLE;
|
||||
#endif
|
||||
|
||||
data->set.ssh_auth_types = CURLSSH_AUTH_DEFAULT; /* defaults to any auth
|
||||
type */
|
||||
}
|
||||
|
||||
#ifdef CURL_DOES_CONVERSIONS
|
||||
|
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -165,7 +165,7 @@ CURLcode Curl_file_connect(struct connectdata *conn)
|
||||
file->fd = fd;
|
||||
if(!conn->data->set.upload && (fd == -1)) {
|
||||
failf(conn->data, "Couldn't open file %s", conn->data->reqdata.path);
|
||||
Curl_file_done(conn, CURLE_FILE_COULDNT_READ_FILE);
|
||||
Curl_file_done(conn, CURLE_FILE_COULDNT_READ_FILE, FALSE);
|
||||
return CURLE_FILE_COULDNT_READ_FILE;
|
||||
}
|
||||
|
||||
@@ -173,10 +173,11 @@ CURLcode Curl_file_connect(struct connectdata *conn)
|
||||
}
|
||||
|
||||
CURLcode Curl_file_done(struct connectdata *conn,
|
||||
CURLcode status)
|
||||
CURLcode status, bool premature)
|
||||
{
|
||||
struct FILEPROTO *file = conn->data->reqdata.proto.file;
|
||||
(void)status; /* not used */
|
||||
(void)premature; /* not used */
|
||||
Curl_safefree(file->freepath);
|
||||
|
||||
if(file->fd != -1)
|
||||
|
@@ -8,7 +8,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2005, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -25,7 +25,7 @@
|
||||
***************************************************************************/
|
||||
#ifndef CURL_DISABLE_FILE
|
||||
CURLcode Curl_file(struct connectdata *, bool *done);
|
||||
CURLcode Curl_file_done(struct connectdata *, CURLcode);
|
||||
CURLcode Curl_file_done(struct connectdata *, CURLcode, bool premature);
|
||||
CURLcode Curl_file_connect(struct connectdata *);
|
||||
#endif
|
||||
#endif
|
||||
|
108
lib/formdata.c
108
lib/formdata.c
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -24,7 +24,7 @@
|
||||
/*
|
||||
Debug the form generator stand-alone by compiling this source file with:
|
||||
|
||||
gcc -DHAVE_CONFIG_H -I../ -g -D_FORM_DEBUG -o formdata -I../include formdata.c strequal.c
|
||||
gcc -DHAVE_CONFIG_H -I../ -g -D_FORM_DEBUG -DCURLDEBUG -o formdata -I../include formdata.c strequal.c memdebug.c mprintf.c strerror.c
|
||||
|
||||
run the 'formdata' executable the output should end with:
|
||||
All Tests seem to have worked ...
|
||||
@@ -63,7 +63,7 @@ Content-Type: multipart/mixed, boundary=curlz1s0dkticx49MV1KGcYP5cvfSsz
|
||||
Content-Disposition: attachment; filename="inet_ntoa_r.h"
|
||||
Content-Type: text/plain
|
||||
...
|
||||
Content-Disposition: attachment; filename="Makefile.b32.resp"
|
||||
Content-Disposition: attachment; filename="Makefile.b32"
|
||||
Content-Type: text/plain
|
||||
...
|
||||
|
||||
@@ -73,7 +73,7 @@ Content-Type: multipart/mixed, boundary=curlirkYPmPwu6FrJ1vJ1u1BmtIufh1
|
||||
Content-Disposition: attachment; filename="inet_ntoa_r.h"
|
||||
Content-Type: text/plain
|
||||
...
|
||||
Content-Disposition: attachment; filename="Makefile.b32.resp"
|
||||
Content-Disposition: attachment; filename="Makefile.b32"
|
||||
Content-Type: text/plain
|
||||
...
|
||||
Content-Disposition: attachment; filename="inet_ntoa_r.h"
|
||||
@@ -87,7 +87,7 @@ Content-Type: multipart/mixed, boundary=curlirkYPmPwu6FrJ1vJ1u1BmtIufh1
|
||||
Content-Disposition: attachment; filename="inet_ntoa_r.h"
|
||||
Content-Type: text/plain
|
||||
...
|
||||
Content-Disposition: attachment; filename="Makefile.b32.resp"
|
||||
Content-Disposition: attachment; filename="Makefile.b32"
|
||||
Content-Type: text/plain
|
||||
...
|
||||
Content-Disposition: attachment; filename="inet_ntoa_r.h"
|
||||
@@ -118,6 +118,8 @@ Content-Disposition: form-data; name="FILECONTENT"
|
||||
#if defined(HAVE_LIBGEN_H) && defined(HAVE_BASENAME)
|
||||
#include <libgen.h>
|
||||
#endif
|
||||
#include "urldata.h" /* for struct SessionHandle */
|
||||
#include "easyif.h" /* for Curl_convert_... prototypes */
|
||||
#include "formdata.h"
|
||||
#include "strequal.h"
|
||||
#include "memory.h"
|
||||
@@ -452,7 +454,12 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost,
|
||||
* Set the Name property.
|
||||
*/
|
||||
case CURLFORM_PTRNAME:
|
||||
#ifdef CURL_DOES_CONVERSIONS
|
||||
/* treat CURLFORM_PTR like CURLFORM_COPYNAME so we'll
|
||||
have safe memory for the eventual conversion */
|
||||
#else
|
||||
current_form->flags |= HTTPPOST_PTRNAME; /* fall through */
|
||||
#endif
|
||||
case CURLFORM_COPYNAME:
|
||||
if (current_form->name)
|
||||
return_value = CURL_FORMADD_OPTION_TWICE;
|
||||
@@ -835,7 +842,7 @@ static CURLcode AddFormData(struct FormData **formp,
|
||||
*formp = newform;
|
||||
|
||||
if (size) {
|
||||
if(type == FORM_DATA)
|
||||
if((type == FORM_DATA) || (type == FORM_CONTENT))
|
||||
*size += length;
|
||||
else {
|
||||
/* Since this is a file to be uploaded here, add the size of the actual
|
||||
@@ -872,10 +879,11 @@ static CURLcode AddFormDataf(struct FormData **formp,
|
||||
* Curl_formclean() is used from http.c, this cleans a built FormData linked
|
||||
* list
|
||||
*/
|
||||
void Curl_formclean(struct FormData *form)
|
||||
void Curl_formclean(struct FormData **form_ptr)
|
||||
{
|
||||
struct FormData *next;
|
||||
struct FormData *next, *form;
|
||||
|
||||
form = *form_ptr;
|
||||
if(!form)
|
||||
return;
|
||||
|
||||
@@ -885,8 +893,40 @@ void Curl_formclean(struct FormData *form)
|
||||
free(form); /* free the struct */
|
||||
|
||||
} while ((form = next) != NULL); /* continue */
|
||||
|
||||
*form_ptr = NULL;
|
||||
}
|
||||
|
||||
#ifdef CURL_DOES_CONVERSIONS
|
||||
/*
|
||||
* Curl_formcovert() is used from http.c, this converts any
|
||||
form items that need to be sent in the network encoding.
|
||||
Returns CURLE_OK on success.
|
||||
*/
|
||||
CURLcode Curl_formconvert(struct SessionHandle *data, struct FormData *form)
|
||||
{
|
||||
struct FormData *next;
|
||||
CURLcode rc;
|
||||
|
||||
if(!form)
|
||||
return CURLE_OK;
|
||||
|
||||
if(!data)
|
||||
return CURLE_BAD_FUNCTION_ARGUMENT;
|
||||
|
||||
do {
|
||||
next=form->next; /* the following form line */
|
||||
if (form->type == FORM_DATA) {
|
||||
rc = Curl_convert_to_network(data, form->line, form->length);
|
||||
/* Curl_convert_to_network calls failf if unsuccessful */
|
||||
if (rc != CURLE_OK)
|
||||
return rc;
|
||||
}
|
||||
} while ((form = next) != NULL); /* continue */
|
||||
return CURLE_OK;
|
||||
}
|
||||
#endif /* CURL_DOES_CONVERSIONS */
|
||||
|
||||
/*
|
||||
* curl_formget()
|
||||
* Serialize a curl_httppost struct.
|
||||
@@ -917,18 +957,18 @@ int curl_formget(struct curl_httppost *form, void *arg,
|
||||
if (temp.fp) {
|
||||
fclose(temp.fp);
|
||||
}
|
||||
Curl_formclean(data);
|
||||
Curl_formclean(&data);
|
||||
return -1;
|
||||
}
|
||||
} while (read == sizeof(buffer));
|
||||
} else {
|
||||
if (ptr->length != append(arg, ptr->line, ptr->length)) {
|
||||
Curl_formclean(data);
|
||||
Curl_formclean(&data);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
Curl_formclean(data);
|
||||
Curl_formclean(&data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1179,7 +1219,7 @@ CURLcode Curl_getFormData(struct FormData **finalform,
|
||||
curList = curList->next;
|
||||
}
|
||||
if (result) {
|
||||
Curl_formclean(firstform);
|
||||
Curl_formclean(&firstform);
|
||||
free(boundary);
|
||||
return result;
|
||||
}
|
||||
@@ -1194,7 +1234,10 @@ CURLcode Curl_getFormData(struct FormData **finalform,
|
||||
if(file->contenttype &&
|
||||
!checkprefix("text/", file->contenttype)) {
|
||||
/* this is not a text content, mention our binary encoding */
|
||||
size += AddFormData(&form, "\r\nContent-Transfer-Encoding: binary", 0);
|
||||
result = AddFormDataf(&form, &size,
|
||||
"\r\nContent-Transfer-Encoding: binary");
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1232,21 +1275,26 @@ CURLcode Curl_getFormData(struct FormData **finalform,
|
||||
size_t nread;
|
||||
char buffer[512];
|
||||
while ((nread = fread(buffer, 1, sizeof(buffer), fileread)) != 0) {
|
||||
result = AddFormData(&form, FORM_DATA, buffer, nread, &size);
|
||||
result = AddFormData(&form, FORM_CONTENT, buffer, nread, &size);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (result) {
|
||||
Curl_formclean(firstform);
|
||||
Curl_formclean(&firstform);
|
||||
free(boundary);
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
Curl_formclean(firstform);
|
||||
#ifdef _FORM_DEBUG
|
||||
fprintf(stderr,
|
||||
"\n==> Curl_getFormData couldn't open/read \"%s\"\n",
|
||||
file->contents);
|
||||
#endif
|
||||
Curl_formclean(&firstform);
|
||||
free(boundary);
|
||||
*finalform = NULL;
|
||||
return CURLE_READ_ERROR;
|
||||
@@ -1255,7 +1303,7 @@ CURLcode Curl_getFormData(struct FormData **finalform,
|
||||
}
|
||||
else if (post->flags & HTTPPOST_BUFFER) {
|
||||
/* include contents of buffer */
|
||||
result = AddFormData(&form, FORM_DATA, post->buffer,
|
||||
result = AddFormData(&form, FORM_CONTENT, post->buffer,
|
||||
post->bufferlength, &size);
|
||||
if (result)
|
||||
break;
|
||||
@@ -1263,14 +1311,14 @@ CURLcode Curl_getFormData(struct FormData **finalform,
|
||||
|
||||
else {
|
||||
/* include the contents we got */
|
||||
result = AddFormData(&form, FORM_DATA, post->contents,
|
||||
result = AddFormData(&form, FORM_CONTENT, post->contents,
|
||||
post->contentslength, &size);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
} while ((file = file->more) != NULL); /* for each specified file for this field */
|
||||
if (result) {
|
||||
Curl_formclean(firstform);
|
||||
Curl_formclean(&firstform);
|
||||
free(boundary);
|
||||
return result;
|
||||
}
|
||||
@@ -1288,7 +1336,7 @@ CURLcode Curl_getFormData(struct FormData **finalform,
|
||||
|
||||
} while ((post = post->next) != NULL); /* for each field */
|
||||
if (result) {
|
||||
Curl_formclean(firstform);
|
||||
Curl_formclean(&firstform);
|
||||
free(boundary);
|
||||
return result;
|
||||
}
|
||||
@@ -1298,7 +1346,7 @@ CURLcode Curl_getFormData(struct FormData **finalform,
|
||||
"\r\n--%s--\r\n",
|
||||
boundary);
|
||||
if (result) {
|
||||
Curl_formclean(firstform);
|
||||
Curl_formclean(&firstform);
|
||||
free(boundary);
|
||||
return result;
|
||||
}
|
||||
@@ -1397,7 +1445,7 @@ size_t Curl_FormReader(char *buffer,
|
||||
|
||||
form->data = form->data->next; /* advance */
|
||||
|
||||
} while(form->data && (form->data->type == FORM_DATA));
|
||||
} while(form->data && (form->data->type != FORM_FILE));
|
||||
/* If we got an empty line and we have more data, we proceed to the next
|
||||
line immediately to avoid returning zero before we've reached the end.
|
||||
This is the bug reported November 22 1999 on curl 6.3. (Daniel) */
|
||||
@@ -1464,7 +1512,7 @@ int main()
|
||||
char value5[] = "value for PTRCONTENTS + CONTENTSLENGTH";
|
||||
char value6[] = "value for PTRCOTNENTS + CONTENTSLENGTH + CONTENTTYPE";
|
||||
char value7[] = "inet_ntoa_r.h";
|
||||
char value8[] = "Makefile.b32.resp";
|
||||
char value8[] = "Makefile.b32";
|
||||
char type2[] = "image/gif";
|
||||
char type6[] = "text/plain";
|
||||
char type7[] = "text/html";
|
||||
@@ -1473,7 +1521,8 @@ int main()
|
||||
int value5length = strlen(value4);
|
||||
int value6length = strlen(value5);
|
||||
int errors = 0;
|
||||
int size;
|
||||
CURLcode rc;
|
||||
size_t size;
|
||||
size_t nread;
|
||||
char buffer[4096];
|
||||
struct curl_httppost *httppost=NULL;
|
||||
@@ -1549,7 +1598,14 @@ int main()
|
||||
CURLFORM_END))
|
||||
++errors;
|
||||
|
||||
form=Curl_getFormData(httppost, &size);
|
||||
rc = Curl_getFormData(&form, httppost, NULL, &size);
|
||||
if(rc != CURLE_OK) {
|
||||
if(rc != CURLE_READ_ERROR) {
|
||||
const char *errortext = curl_easy_strerror(rc);
|
||||
fprintf(stdout, "\n==> Curl_getFormData error: %s\n", errortext);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
Curl_FormInit(&formread, form);
|
||||
|
||||
@@ -1557,7 +1613,7 @@ int main()
|
||||
nread = Curl_FormReader(buffer, 1, sizeof(buffer),
|
||||
(FILE *)&formread);
|
||||
|
||||
if(-1 == nread)
|
||||
if(nread < 1)
|
||||
break;
|
||||
fwrite(buffer, nread, 1, stdout);
|
||||
} while(1);
|
||||
|
@@ -8,7 +8,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -25,8 +25,10 @@
|
||||
***************************************************************************/
|
||||
|
||||
enum formtype {
|
||||
FORM_DATA, /* regular data */
|
||||
FORM_FILE /* 'line' points to a file name we should read from */
|
||||
FORM_DATA, /* form metadata (convert to network encoding if necessary) */
|
||||
FORM_CONTENT, /* form content (never convert) */
|
||||
FORM_FILE /* 'line' points to a file name we should read from
|
||||
to create the form data (never convert) */
|
||||
};
|
||||
|
||||
/* plain and simple linked list with lines to send */
|
||||
@@ -87,7 +89,9 @@ char *Curl_formpostheader(void *formp, size_t *len);
|
||||
|
||||
char *Curl_FormBoundary(void);
|
||||
|
||||
void Curl_formclean(struct FormData *);
|
||||
void Curl_formclean(struct FormData **);
|
||||
|
||||
CURLcode Curl_formconvert(struct SessionHandle *, struct FormData *);
|
||||
|
||||
#endif
|
||||
|
||||
|
104
lib/ftp.c
104
lib/ftp.c
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -265,7 +265,6 @@ static CURLcode ftp_readresp(curl_socket_t sockfd,
|
||||
ssize_t gotbytes;
|
||||
char *ptr;
|
||||
struct SessionHandle *data = conn->data;
|
||||
struct Curl_transfer_keeper *k = &data->reqdata.keep;
|
||||
char *buf = data->state.buffer;
|
||||
CURLcode result = CURLE_OK;
|
||||
struct ftp_conn *ftpc = &conn->proto.ftpc;
|
||||
@@ -329,7 +328,7 @@ static CURLcode ftp_readresp(curl_socket_t sockfd,
|
||||
* line */
|
||||
int i;
|
||||
|
||||
k->headerbytecount += gotbytes;
|
||||
conn->headerbytecount += gotbytes;
|
||||
|
||||
ftpc->nread_resp += gotbytes;
|
||||
for(i = 0; i < gotbytes; ptr++, i++) {
|
||||
@@ -448,7 +447,6 @@ CURLcode Curl_GetFTPResponse(ssize_t *nreadp, /* return number of bytes read */
|
||||
long timeout; /* timeout in seconds */
|
||||
int interval_ms;
|
||||
struct SessionHandle *data = conn->data;
|
||||
struct Curl_transfer_keeper *k = &data->reqdata.keep;
|
||||
char *line_start;
|
||||
int code=0; /* default ftp "error code" to return */
|
||||
char *buf = data->state.buffer;
|
||||
@@ -562,7 +560,7 @@ CURLcode Curl_GetFTPResponse(ssize_t *nreadp, /* return number of bytes read */
|
||||
* line */
|
||||
int i;
|
||||
|
||||
k->headerbytecount += gotbytes;
|
||||
conn->headerbytecount += gotbytes;
|
||||
|
||||
*nreadp += gotbytes;
|
||||
for(i = 0; i < gotbytes; ptr++, i++) {
|
||||
@@ -573,7 +571,7 @@ CURLcode Curl_GetFTPResponse(ssize_t *nreadp, /* return number of bytes read */
|
||||
|
||||
/* output debug output if that is requested */
|
||||
if(data->set.verbose)
|
||||
Curl_debug(data, CURLINFO_HEADER_IN,
|
||||
Curl_debug(data, CURLINFO_HEADER_IN,
|
||||
line_start, (size_t)perline, conn);
|
||||
|
||||
/*
|
||||
@@ -668,6 +666,7 @@ static void state(struct connectdata *conn,
|
||||
"ACCT",
|
||||
"PBSZ",
|
||||
"PROT",
|
||||
"CCC",
|
||||
"PWD",
|
||||
"QUOTE",
|
||||
"RETR_PREQUOTE",
|
||||
@@ -1168,6 +1167,15 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
|
||||
|
||||
#endif /* end of ipv4-specific code */
|
||||
|
||||
/* this tcpconnect assignment below is a hackish work-around to make the
|
||||
multi interface with active FTP work - as it will not wait for a
|
||||
(passive) connect in Curl_is_connected().
|
||||
|
||||
The *proper* fix is to make sure that the active connection from the
|
||||
server is done in a non-blocking way. Currently, it is still BLOCKING.
|
||||
*/
|
||||
conn->bits.tcpconnect = TRUE;
|
||||
|
||||
state(conn, FTP_PORT);
|
||||
return result;
|
||||
}
|
||||
@@ -1661,7 +1669,7 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
|
||||
return CURLE_FTP_WEIRD_PASV_REPLY;
|
||||
}
|
||||
|
||||
if(data->change.proxy && *data->change.proxy) {
|
||||
if(data->set.proxy && *data->set.proxy) {
|
||||
/*
|
||||
* This is a tunnel through a http proxy and we need to connect to the
|
||||
* proxy again here.
|
||||
@@ -2538,6 +2546,31 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
|
||||
/* we failed and bails out */
|
||||
return CURLE_FTP_SSL_FAILED;
|
||||
|
||||
if(data->set.ftp_use_ccc) {
|
||||
/* CCC - Clear Command Channel
|
||||
*/
|
||||
NBFTPSENDF(conn, "CCC", NULL);
|
||||
state(conn, FTP_CCC);
|
||||
}
|
||||
else {
|
||||
result = ftp_state_pwd(conn);
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
break;
|
||||
|
||||
case FTP_CCC:
|
||||
if (ftpcode < 500) {
|
||||
/* First shut down the SSL layer (note: this call will block) */
|
||||
result = Curl_ssl_shutdown(conn, FIRSTSOCKET);
|
||||
|
||||
if(result) {
|
||||
failf(conn->data, "Failed to clear the command channel (CCC)");
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/* Then continue as normal */
|
||||
result = ftp_state_pwd(conn);
|
||||
if(result)
|
||||
return result;
|
||||
@@ -2933,7 +2966,7 @@ CURLcode Curl_ftp_connect(struct connectdata *conn,
|
||||
*
|
||||
* Input argument is already checked for validity.
|
||||
*/
|
||||
CURLcode Curl_ftp_done(struct connectdata *conn, CURLcode status)
|
||||
CURLcode Curl_ftp_done(struct connectdata *conn, CURLcode status, bool premature)
|
||||
{
|
||||
struct SessionHandle *data = conn->data;
|
||||
struct FTP *ftp = data->reqdata.proto.ftp;
|
||||
@@ -2956,6 +2989,32 @@ CURLcode Curl_ftp_done(struct connectdata *conn, CURLcode status)
|
||||
*/
|
||||
return CURLE_OK;
|
||||
|
||||
switch(status) {
|
||||
case CURLE_BAD_DOWNLOAD_RESUME:
|
||||
case CURLE_FTP_WEIRD_PASV_REPLY:
|
||||
case CURLE_FTP_PORT_FAILED:
|
||||
case CURLE_FTP_COULDNT_SET_BINARY:
|
||||
case CURLE_FTP_COULDNT_RETR_FILE:
|
||||
case CURLE_FTP_COULDNT_STOR_FILE:
|
||||
case CURLE_FTP_ACCESS_DENIED:
|
||||
/* the connection stays alive fine even though this happened */
|
||||
/* fall-through */
|
||||
case CURLE_OK: /* doesn't affect the control connection's status */
|
||||
if (!premature) {
|
||||
ftpc->ctl_valid = was_ctl_valid;
|
||||
break;
|
||||
}
|
||||
/* until we cope better with prematurely ended requests, let them
|
||||
* fallback as if in complete failure */
|
||||
default: /* by default, an error means the control connection is
|
||||
wedged and should not be used anymore */
|
||||
ftpc->ctl_valid = FALSE;
|
||||
ftpc->cwdfail = TRUE; /* set this TRUE to prevent us to remember the
|
||||
current path, as this connection is going */
|
||||
conn->bits.close = TRUE; /* marked for closure */
|
||||
break;
|
||||
}
|
||||
|
||||
/* now store a copy of the directory we are in */
|
||||
if(ftpc->prevpath)
|
||||
free(ftpc->prevpath);
|
||||
@@ -2981,25 +3040,6 @@ CURLcode Curl_ftp_done(struct connectdata *conn, CURLcode status)
|
||||
/* free the dir tree and file parts */
|
||||
freedirs(conn);
|
||||
|
||||
switch(status) {
|
||||
case CURLE_BAD_DOWNLOAD_RESUME:
|
||||
case CURLE_FTP_WEIRD_PASV_REPLY:
|
||||
case CURLE_FTP_PORT_FAILED:
|
||||
case CURLE_FTP_COULDNT_SET_BINARY:
|
||||
case CURLE_FTP_COULDNT_RETR_FILE:
|
||||
case CURLE_FTP_COULDNT_STOR_FILE:
|
||||
case CURLE_FTP_ACCESS_DENIED:
|
||||
/* the connection stays alive fine even though this happened */
|
||||
/* fall-through */
|
||||
case CURLE_OK: /* doesn't affect the control connection's status */
|
||||
ftpc->ctl_valid = was_ctl_valid;
|
||||
break;
|
||||
default: /* by default, an error means the control connection is
|
||||
wedged and should not be used anymore */
|
||||
ftpc->ctl_valid = FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef HAVE_KRB4
|
||||
Curl_sec_fflush_fd(conn, conn->sock[SECONDARYSOCKET]);
|
||||
#endif
|
||||
@@ -3014,7 +3054,7 @@ CURLcode Curl_ftp_done(struct connectdata *conn, CURLcode status)
|
||||
|
||||
conn->sock[SECONDARYSOCKET] = CURL_SOCKET_BAD;
|
||||
|
||||
if(!ftp->no_transfer && !status) {
|
||||
if(!ftp->no_transfer && !status && !premature) {
|
||||
/*
|
||||
* Let's see what the server says about the transfer we just performed,
|
||||
* but lower the timeout as sometimes this connection has died while the
|
||||
@@ -3047,7 +3087,7 @@ CURLcode Curl_ftp_done(struct connectdata *conn, CURLcode status)
|
||||
}
|
||||
}
|
||||
|
||||
if(result)
|
||||
if(result || premature)
|
||||
/* the response code from the transfer showed an error already so no
|
||||
use checking further */
|
||||
;
|
||||
@@ -3089,7 +3129,7 @@ CURLcode Curl_ftp_done(struct connectdata *conn, CURLcode status)
|
||||
ftpc->dont_check = FALSE;
|
||||
|
||||
/* Send any post-transfer QUOTE strings? */
|
||||
if(!status && !result && data->set.postquote)
|
||||
if(!status && !result && !premature && data->set.postquote)
|
||||
result = ftp_sendquote(conn, data->set.postquote);
|
||||
|
||||
return result;
|
||||
@@ -3433,7 +3473,7 @@ CURLcode Curl_nbftpsendf(struct connectdata *conn,
|
||||
return res;
|
||||
|
||||
if(conn->data->set.verbose)
|
||||
Curl_debug(conn->data, CURLINFO_HEADER_OUT,
|
||||
Curl_debug(conn->data, CURLINFO_HEADER_OUT,
|
||||
sptr, (size_t)bytes_written, conn);
|
||||
|
||||
if(bytes_written != (ssize_t)write_len) {
|
||||
@@ -3491,7 +3531,7 @@ CURLcode Curl_ftpsendf(struct connectdata *conn,
|
||||
break;
|
||||
|
||||
if(conn->data->set.verbose)
|
||||
Curl_debug(conn->data, CURLINFO_HEADER_OUT,
|
||||
Curl_debug(conn->data, CURLINFO_HEADER_OUT,
|
||||
sptr, (size_t)bytes_written, conn);
|
||||
|
||||
if(bytes_written != (ssize_t)write_len) {
|
||||
|
@@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2005, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -25,7 +25,7 @@
|
||||
|
||||
#ifndef CURL_DISABLE_FTP
|
||||
CURLcode Curl_ftp(struct connectdata *conn, bool *done);
|
||||
CURLcode Curl_ftp_done(struct connectdata *conn, CURLcode);
|
||||
CURLcode Curl_ftp_done(struct connectdata *conn, CURLcode, bool premature);
|
||||
CURLcode Curl_ftp_connect(struct connectdata *conn, bool *done);
|
||||
CURLcode Curl_ftp_disconnect(struct connectdata *conn);
|
||||
CURLcode Curl_ftpsendf(struct connectdata *, const char *fmt, ...);
|
||||
|
@@ -77,6 +77,9 @@ CURLcode Curl_getinfo(struct SessionHandle *data, CURLINFO info, ...)
|
||||
struct curl_slist **param_slistp=NULL;
|
||||
char buf;
|
||||
|
||||
if(!data)
|
||||
return CURLE_BAD_FUNCTION_ARGUMENT;
|
||||
|
||||
va_start(arg, info);
|
||||
|
||||
switch(info&CURLINFO_TYPEMASK) {
|
||||
|
97
lib/gtls.c
97
lib/gtls.c
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -67,6 +67,23 @@ static void tls_log_func(int level, const char *str)
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Custom push and pull callback functions used by GNU TLS to read and write
|
||||
* to the socket. These functions are simple wrappers to send() and recv()
|
||||
* (although here using the sread/swrite macros as defined by setup_once.h).
|
||||
* We use custom functions rather than the GNU TLS defaults because it allows
|
||||
* us to get specific about the fourth "flags" argument, and to use arbitrary
|
||||
* private data with gnutls_transport_set_ptr if we wish.
|
||||
*/
|
||||
static ssize_t Curl_gtls_push(void *s, const void *buf, size_t len)
|
||||
{
|
||||
return swrite(s, buf, len);
|
||||
}
|
||||
|
||||
static ssize_t Curl_gtls_pull(void *s, void *buf, size_t len)
|
||||
{
|
||||
return sread(s, buf, len);
|
||||
}
|
||||
|
||||
/* Global GnuTLS init, called from Curl_ssl_init() */
|
||||
int Curl_gtls_init(void)
|
||||
@@ -285,6 +302,13 @@ Curl_gtls_connect(struct connectdata *conn,
|
||||
gnutls_transport_set_ptr(session,
|
||||
(gnutls_transport_ptr)conn->sock[sockindex]);
|
||||
|
||||
/* register callback functions to send and receive data. */
|
||||
gnutls_transport_set_push_function(session, Curl_gtls_push);
|
||||
gnutls_transport_set_pull_function(session, Curl_gtls_pull);
|
||||
|
||||
/* lowat must be set to zero when using custom push and pull functions. */
|
||||
gnutls_transport_set_lowat(session, 0);
|
||||
|
||||
/* This might be a reconnect, so we check for a session ID in the cache
|
||||
to speed up things */
|
||||
|
||||
@@ -452,13 +476,12 @@ Curl_gtls_connect(struct connectdata *conn,
|
||||
|
||||
|
||||
/* return number of sent (non-SSL) bytes */
|
||||
int Curl_gtls_send(struct connectdata *conn,
|
||||
ssize_t Curl_gtls_send(struct connectdata *conn,
|
||||
int sockindex,
|
||||
void *mem,
|
||||
size_t len)
|
||||
{
|
||||
int rc;
|
||||
rc = gnutls_record_send(conn->ssl[sockindex].session, mem, len);
|
||||
ssize_t rc = gnutls_record_send(conn->ssl[sockindex].session, mem, len);
|
||||
|
||||
if(rc < 0 ) {
|
||||
if(rc == GNUTLS_E_AGAIN)
|
||||
@@ -493,6 +516,72 @@ void Curl_gtls_close(struct connectdata *conn)
|
||||
close_one(conn, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is called to shut down the SSL layer but keep the
|
||||
* socket open (CCC - Clear Command Channel)
|
||||
*/
|
||||
int Curl_gtls_shutdown(struct connectdata *conn, int sockindex)
|
||||
{
|
||||
int result;
|
||||
int retval = 0;
|
||||
struct SessionHandle *data = conn->data;
|
||||
int done = 0;
|
||||
ssize_t nread;
|
||||
char buf[120];
|
||||
|
||||
/* This has only been tested on the proftpd server, and the mod_tls code
|
||||
sends a close notify alert without waiting for a close notify alert in
|
||||
response. Thus we wait for a close notify alert from the server, but
|
||||
we do not send one. Let's hope other servers do the same... */
|
||||
|
||||
if(conn->ssl[sockindex].session) {
|
||||
while(!done) {
|
||||
int what = Curl_select(conn->sock[sockindex],
|
||||
CURL_SOCKET_BAD, SSL_SHUTDOWN_TIMEOUT);
|
||||
if(what > 0) {
|
||||
/* Something to read, let's do it and hope that it is the close
|
||||
notify alert from the server */
|
||||
result = gnutls_record_recv(conn->ssl[sockindex].session,
|
||||
buf, sizeof(buf));
|
||||
switch(result) {
|
||||
case 0:
|
||||
/* This is the expected response. There was no data but only
|
||||
the close notify alert */
|
||||
done = 1;
|
||||
break;
|
||||
case GNUTLS_E_AGAIN:
|
||||
case GNUTLS_E_INTERRUPTED:
|
||||
infof(data, "GNUTLS_E_AGAIN || GNUTLS_E_INTERRUPTED\n");
|
||||
break;
|
||||
default:
|
||||
retval = -1;
|
||||
done = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if(0 == what) {
|
||||
/* timeout */
|
||||
failf(data, "SSL shutdown timeout");
|
||||
done = 1;
|
||||
break;
|
||||
}
|
||||
else {
|
||||
/* anything that gets here is fatally bad */
|
||||
failf(data, "select on SSL socket, errno: %d", Curl_sockerrno());
|
||||
retval = -1;
|
||||
done = 1;
|
||||
}
|
||||
}
|
||||
gnutls_deinit(conn->ssl[sockindex].session);
|
||||
}
|
||||
gnutls_certificate_free_credentials(conn->ssl[sockindex].cred);
|
||||
|
||||
conn->ssl[sockindex].session = NULL;
|
||||
conn->ssl[sockindex].use = FALSE;
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the read would block we return -1 and set 'wouldblock' to TRUE.
|
||||
* Otherwise we return the amount of data read. Other errors should return -1
|
||||
|
@@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2005, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -32,8 +32,8 @@ void Curl_gtls_close_all(struct SessionHandle *data);
|
||||
void Curl_gtls_close(struct connectdata *conn); /* close a SSL connection */
|
||||
|
||||
/* return number of sent (non-SSL) bytes */
|
||||
int Curl_gtls_send(struct connectdata *conn, int sockindex,
|
||||
void *mem, size_t len);
|
||||
ssize_t Curl_gtls_send(struct connectdata *conn, int sockindex,
|
||||
void *mem, size_t len);
|
||||
ssize_t Curl_gtls_recv(struct connectdata *conn, /* connection data */
|
||||
int num, /* socketindex */
|
||||
char *buf, /* store read data here */
|
||||
@@ -41,5 +41,6 @@ ssize_t Curl_gtls_recv(struct connectdata *conn, /* connection data */
|
||||
bool *wouldblock);
|
||||
void Curl_gtls_session_free(void *ptr);
|
||||
size_t Curl_gtls_version(char *buffer, size_t size);
|
||||
int Curl_gtls_shutdown(struct connectdata *conn, int sockindex);
|
||||
|
||||
#endif
|
||||
|
85
lib/http.c
85
lib/http.c
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -80,6 +80,7 @@
|
||||
#include <curl/curl.h>
|
||||
#include "transfer.h"
|
||||
#include "sendf.h"
|
||||
#include "easyif.h" /* for Curl_convert_... prototypes */
|
||||
#include "formdata.h"
|
||||
#include "progress.h"
|
||||
#include "base64.h"
|
||||
@@ -149,12 +150,12 @@ static CURLcode Curl_output_basic(struct connectdata *conn, bool proxy)
|
||||
}
|
||||
|
||||
snprintf(data->state.buffer, sizeof(data->state.buffer), "%s:%s", user, pwd);
|
||||
if(Curl_base64_encode(data->state.buffer,
|
||||
if(Curl_base64_encode(data, data->state.buffer,
|
||||
strlen(data->state.buffer),
|
||||
&authorization) > 0) {
|
||||
if(*userp)
|
||||
free(*userp);
|
||||
*userp = aprintf( "%sAuthorization: Basic %s\015\012",
|
||||
*userp = aprintf( "%sAuthorization: Basic %s\r\n",
|
||||
proxy?"Proxy-":"",
|
||||
authorization);
|
||||
free(authorization);
|
||||
@@ -873,6 +874,20 @@ CURLcode add_buffer_send(send_buffer *in,
|
||||
ptr = in->buffer;
|
||||
size = in->size_used;
|
||||
|
||||
#ifdef CURL_DOES_CONVERSIONS
|
||||
if(size - included_body_bytes > 0) {
|
||||
res = Curl_convert_to_network(conn->data, ptr, size - included_body_bytes);
|
||||
/* Curl_convert_to_network calls failf if unsuccessful */
|
||||
if(res != CURLE_OK) {
|
||||
/* conversion failed, free memory and return to the caller */
|
||||
if(in->buffer)
|
||||
free(in->buffer);
|
||||
free(in);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
#endif /* CURL_DOES_CONVERSIONS */
|
||||
|
||||
if(conn->protocol & PROT_HTTPS) {
|
||||
/* We never send more than CURL_MAX_WRITE_SIZE bytes in one single chunk
|
||||
when we speak HTTPS, as if only a fraction of it is sent now, this data
|
||||
@@ -903,8 +918,8 @@ CURLcode add_buffer_send(send_buffer *in,
|
||||
Curl_debug(conn->data, CURLINFO_HEADER_OUT, ptr,
|
||||
(size_t)(amount-included_body_bytes), conn);
|
||||
if (included_body_bytes)
|
||||
Curl_debug(conn->data, CURLINFO_DATA_OUT,
|
||||
ptr+amount-included_body_bytes,
|
||||
Curl_debug(conn->data, CURLINFO_DATA_OUT,
|
||||
ptr+amount-included_body_bytes,
|
||||
(size_t)included_body_bytes, conn);
|
||||
}
|
||||
|
||||
@@ -1086,6 +1101,8 @@ Curl_compareheader(char *headerline, /* line to check */
|
||||
* like any ordinary HTTP request, and not specially crafted like this. This
|
||||
* function only remains here like this for now since the rewrite is a bit too
|
||||
* much work to do at the moment.
|
||||
*
|
||||
* This function is BLOCKING which is nasty for all multi interface using apps.
|
||||
*/
|
||||
|
||||
CURLcode Curl_proxyCONNECT(struct connectdata *conn,
|
||||
@@ -1110,6 +1127,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
|
||||
curl_socket_t tunnelsocket = conn->sock[sockindex];
|
||||
send_buffer *req_buffer;
|
||||
curl_off_t cl=0;
|
||||
bool closeConnection = FALSE;
|
||||
|
||||
#define SELECT_OK 0
|
||||
#define SELECT_ERROR 1
|
||||
@@ -1117,6 +1135,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
|
||||
int error = SELECT_OK;
|
||||
|
||||
infof(data, "Establish HTTP proxy tunnel to %s:%d\n", hostname, remote_port);
|
||||
conn->bits.proxy_connect_closed = FALSE;
|
||||
|
||||
do {
|
||||
if(data->reqdata.newurl) {
|
||||
@@ -1143,15 +1162,18 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
|
||||
if(CURLE_OK == result) {
|
||||
char *host=(char *)"";
|
||||
const char *proxyconn="";
|
||||
const char *useragent="";
|
||||
|
||||
if(!checkheaders(data, "Host:")) {
|
||||
host = aprintf("Host: %s\r\n", host_port);
|
||||
if(!host)
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
if(!checkheaders(data, "Proxy-Connection:")) {
|
||||
if(!checkheaders(data, "Proxy-Connection:"))
|
||||
proxyconn = "Proxy-Connection: Keep-Alive\r\n";
|
||||
}
|
||||
|
||||
if(!checkheaders(data, "User-Agent:") && data->set.useragent)
|
||||
useragent = conn->allocptr.uagent;
|
||||
|
||||
if(CURLE_OK == result) {
|
||||
/* Send the connect request to the proxy */
|
||||
@@ -1167,7 +1189,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
|
||||
host,
|
||||
conn->allocptr.proxyuserpwd?
|
||||
conn->allocptr.proxyuserpwd:"",
|
||||
data->set.useragent?conn->allocptr.uagent:"",
|
||||
useragent,
|
||||
proxyconn);
|
||||
|
||||
if(CURLE_OK == result)
|
||||
@@ -1258,7 +1280,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
|
||||
|
||||
/* output debug if that is requested */
|
||||
if(data->set.verbose)
|
||||
Curl_debug(data, CURLINFO_HEADER_IN,
|
||||
Curl_debug(data, CURLINFO_HEADER_IN,
|
||||
line_start, (size_t)perline, conn);
|
||||
|
||||
/* send the header to the callback */
|
||||
@@ -1310,6 +1332,9 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
|
||||
cl = curlx_strtoofft(line_start + strlen("Content-Length:"),
|
||||
NULL, 10);
|
||||
}
|
||||
else if(Curl_compareheader(line_start,
|
||||
"Connection:", "close"))
|
||||
closeConnection = TRUE;
|
||||
else if(2 == sscanf(line_start, "HTTP/1.%d %d",
|
||||
&subversion,
|
||||
&k->httpcode)) {
|
||||
@@ -1336,11 +1361,21 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
|
||||
headers. 'newurl' is set to a new URL if we must loop. */
|
||||
Curl_http_auth_act(conn);
|
||||
|
||||
if (closeConnection && data->reqdata.newurl) {
|
||||
/* Connection closed by server. Don't use it anymore */
|
||||
sclose(conn->sock[sockindex]);
|
||||
conn->sock[sockindex] = CURL_SOCKET_BAD;
|
||||
break;
|
||||
}
|
||||
} while(data->reqdata.newurl);
|
||||
|
||||
if(200 != k->httpcode) {
|
||||
failf(data, "Received HTTP code %d from proxy after CONNECT",
|
||||
k->httpcode);
|
||||
|
||||
if (closeConnection && data->reqdata.newurl)
|
||||
conn->bits.proxy_connect_closed = TRUE;
|
||||
|
||||
return CURLE_RECV_ERROR;
|
||||
}
|
||||
|
||||
@@ -1390,6 +1425,8 @@ CURLcode Curl_http_connect(struct connectdata *conn, bool *done)
|
||||
free(data->state.first_host);
|
||||
|
||||
data->state.first_host = strdup(conn->host.name);
|
||||
if(!data->state.first_host)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
if(conn->protocol & PROT_HTTPS) {
|
||||
@@ -1473,11 +1510,12 @@ int Curl_https_getsock(struct connectdata *conn,
|
||||
*/
|
||||
|
||||
CURLcode Curl_http_done(struct connectdata *conn,
|
||||
CURLcode status)
|
||||
CURLcode status, bool premature)
|
||||
{
|
||||
struct SessionHandle *data = conn->data;
|
||||
struct HTTP *http =data->reqdata.proto.http;
|
||||
struct Curl_transfer_keeper *k = &data->reqdata.keep;
|
||||
(void)premature; /* not used */
|
||||
|
||||
/* set the proper values (possibly modified on POST) */
|
||||
conn->fread = data->set.fread; /* restore */
|
||||
@@ -1497,7 +1535,7 @@ CURLcode Curl_http_done(struct connectdata *conn,
|
||||
if(HTTPREQ_POST_FORM == data->set.httpreq) {
|
||||
k->bytecount = http->readbytecount + http->writebytecount;
|
||||
|
||||
Curl_formclean(http->sendit); /* Now free that whole lot */
|
||||
Curl_formclean(&http->sendit); /* Now free that whole lot */
|
||||
if(http->form.fp) {
|
||||
/* a file being uploaded was left opened, close it! */
|
||||
fclose(http->form.fp);
|
||||
@@ -1512,8 +1550,8 @@ CURLcode Curl_http_done(struct connectdata *conn,
|
||||
|
||||
if(!conn->bits.retry &&
|
||||
((http->readbytecount +
|
||||
k->headerbytecount -
|
||||
k->deductheadercount)) <= 0) {
|
||||
conn->headerbytecount -
|
||||
conn->deductheadercount)) <= 0) {
|
||||
/* If this connection isn't simply closed to be retried, AND nothing was
|
||||
read from the HTTP server (that counts), this can't be right so we
|
||||
return an error here */
|
||||
@@ -1599,7 +1637,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
|
||||
struct HTTP *http;
|
||||
char *ppath = data->reqdata.path;
|
||||
char *host = conn->host.name;
|
||||
const char *te = ""; /* tranfer-encoding */
|
||||
const char *te = ""; /* transfer-encoding */
|
||||
char *ptr;
|
||||
char *request;
|
||||
Curl_HttpReq httpreq = data->set.httpreq;
|
||||
@@ -1684,7 +1722,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
|
||||
|
||||
Curl_safefree(conn->allocptr.ref);
|
||||
if(data->change.referer && !checkheaders(data, "Referer:"))
|
||||
conn->allocptr.ref = aprintf("Referer: %s\015\012", data->change.referer);
|
||||
conn->allocptr.ref = aprintf("Referer: %s\r\n", data->change.referer);
|
||||
else
|
||||
conn->allocptr.ref = NULL;
|
||||
|
||||
@@ -1695,7 +1733,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
|
||||
data->set.encoding) {
|
||||
Curl_safefree(conn->allocptr.accept_encoding);
|
||||
conn->allocptr.accept_encoding =
|
||||
aprintf("Accept-Encoding: %s\015\012", data->set.encoding);
|
||||
aprintf("Accept-Encoding: %s\r\n", data->set.encoding);
|
||||
if(!conn->allocptr.accept_encoding)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
@@ -2179,10 +2217,19 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
|
||||
&http->readbytecount,
|
||||
FIRSTSOCKET,
|
||||
&http->writebytecount);
|
||||
|
||||
if(result) {
|
||||
Curl_formclean(http->sendit); /* free that whole lot */
|
||||
Curl_formclean(&http->sendit); /* free that whole lot */
|
||||
return result;
|
||||
}
|
||||
#ifdef CURL_DOES_CONVERSIONS
|
||||
/* time to convert the form data... */
|
||||
result = Curl_formconvert(data, http->sendit);
|
||||
if(result) {
|
||||
Curl_formclean(&http->sendit); /* free that whole lot */
|
||||
return result;
|
||||
}
|
||||
#endif /* CURL_DOES_CONVERSIONS */
|
||||
break;
|
||||
|
||||
case HTTPREQ_PUT: /* Let's PUT the data to the server! */
|
||||
@@ -2301,8 +2348,8 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
|
||||
(size_t)postsize);
|
||||
if(CURLE_OK == result)
|
||||
result = add_buffer(req_buffer,
|
||||
"\r\n0\r\n\r\n", 7); /* end of a chunked
|
||||
transfer stream */
|
||||
"\x0d\x0a\x30\x0d\x0a\x0d\x0a", 7);
|
||||
/* CR LF 0 CR LF CR LF */
|
||||
included_body = postsize + 7;
|
||||
}
|
||||
if(result)
|
||||
|
@@ -8,7 +8,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -35,7 +35,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
|
||||
|
||||
/* protocol-specific functions set up to be called by the main engine */
|
||||
CURLcode Curl_http(struct connectdata *conn, bool *done);
|
||||
CURLcode Curl_http_done(struct connectdata *, CURLcode);
|
||||
CURLcode Curl_http_done(struct connectdata *, CURLcode, bool premature);
|
||||
CURLcode Curl_http_connect(struct connectdata *conn, bool *done);
|
||||
CURLcode Curl_https_connecting(struct connectdata *conn, bool *done);
|
||||
int Curl_https_getsock(struct connectdata *conn,
|
||||
|
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -36,6 +36,7 @@
|
||||
#include "content_encoding.h"
|
||||
#include "http.h"
|
||||
#include "memory.h"
|
||||
#include "easyif.h" /* for Curl_convert_to_network prototype */
|
||||
|
||||
#define _MPRINTF_REPLACE /* use our functions only */
|
||||
#include <curl/mprintf.h>
|
||||
@@ -96,6 +97,9 @@ void Curl_httpchunk_init(struct connectdata *conn)
|
||||
* client (for byte-counting and whatever).
|
||||
*
|
||||
* The states and the state-machine is further explained in the header file.
|
||||
*
|
||||
* This function always uses ASCII hex values to accommodate non-ASCII hosts.
|
||||
* For example, 0x0d and 0x0a are used instead of '\r' and '\n'.
|
||||
*/
|
||||
CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
|
||||
char *datap,
|
||||
@@ -115,7 +119,11 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
|
||||
while(length) {
|
||||
switch(ch->state) {
|
||||
case CHUNK_HEX:
|
||||
if(ISXDIGIT(*datap)) {
|
||||
/* Check for an ASCII hex digit.
|
||||
We avoid the use of isxdigit to accommodate non-ASCII hosts. */
|
||||
if((*datap >= 0x30 && *datap <= 0x39) /* 0-9 */
|
||||
|| (*datap >= 0x41 && *datap <= 0x46) /* A-F */
|
||||
|| (*datap >= 0x61 && *datap <= 0x66)) { /* a-f */
|
||||
if(ch->hexindex < MAXNUM_SIZE) {
|
||||
ch->hexbuffer[ch->hexindex] = *datap;
|
||||
datap++;
|
||||
@@ -134,6 +142,17 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
|
||||
}
|
||||
/* length and datap are unmodified */
|
||||
ch->hexbuffer[ch->hexindex]=0;
|
||||
#ifdef CURL_DOES_CONVERSIONS
|
||||
/* convert to host encoding before calling strtoul */
|
||||
result = Curl_convert_from_network(conn->data,
|
||||
ch->hexbuffer,
|
||||
ch->hexindex);
|
||||
if(result != CURLE_OK) {
|
||||
/* Curl_convert_from_network calls failf if unsuccessful */
|
||||
/* Treat it as a bad hex character */
|
||||
return(CHUNKE_ILLEGAL_HEX);
|
||||
}
|
||||
#endif /* CURL_DOES_CONVERSIONS */
|
||||
ch->datasize=strtoul(ch->hexbuffer, NULL, 16);
|
||||
ch->state = CHUNK_POSTHEX;
|
||||
}
|
||||
@@ -143,7 +162,7 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
|
||||
/* In this state, we're waiting for CRLF to arrive. We support
|
||||
this to allow so called chunk-extensions to show up here
|
||||
before the CRLF comes. */
|
||||
if(*datap == '\r')
|
||||
if(*datap == 0x0d)
|
||||
ch->state = CHUNK_CR;
|
||||
length--;
|
||||
datap++;
|
||||
@@ -151,7 +170,7 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
|
||||
|
||||
case CHUNK_CR:
|
||||
/* waiting for the LF */
|
||||
if(*datap == '\n') {
|
||||
if(*datap == 0x0a) {
|
||||
/* we're now expecting data to come, unless size was zero! */
|
||||
if(0 == ch->datasize) {
|
||||
if (conn->bits.trailerHdrPresent!=TRUE) {
|
||||
@@ -235,7 +254,7 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
|
||||
break;
|
||||
|
||||
case CHUNK_POSTCR:
|
||||
if(*datap == '\r') {
|
||||
if(*datap == 0x0d) {
|
||||
ch->state = CHUNK_POSTLF;
|
||||
datap++;
|
||||
length--;
|
||||
@@ -245,7 +264,7 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
|
||||
break;
|
||||
|
||||
case CHUNK_POSTLF:
|
||||
if(*datap == '\n') {
|
||||
if(*datap == 0x0a) {
|
||||
/*
|
||||
* The last one before we go back to hex state and start all
|
||||
* over.
|
||||
@@ -277,7 +296,7 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
|
||||
}
|
||||
conn->trailer[conn->trlPos++]=*datap;
|
||||
|
||||
if(*datap == '\r')
|
||||
if(*datap == 0x0d)
|
||||
ch->state = CHUNK_TRAILER_CR;
|
||||
else {
|
||||
datap++;
|
||||
@@ -286,7 +305,7 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
|
||||
break;
|
||||
|
||||
case CHUNK_TRAILER_CR:
|
||||
if(*datap == '\r') {
|
||||
if(*datap == 0x0d) {
|
||||
ch->state = CHUNK_TRAILER_POSTCR;
|
||||
datap++;
|
||||
length--;
|
||||
@@ -296,14 +315,25 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
|
||||
break;
|
||||
|
||||
case CHUNK_TRAILER_POSTCR:
|
||||
if (*datap == '\n') {
|
||||
conn->trailer[conn->trlPos++]='\n';
|
||||
if (*datap == 0x0a) {
|
||||
conn->trailer[conn->trlPos++]=0x0a;
|
||||
conn->trailer[conn->trlPos]=0;
|
||||
if (conn->trlPos==2) {
|
||||
ch->state = CHUNK_STOP;
|
||||
return CHUNKE_STOP;
|
||||
}
|
||||
else {
|
||||
#ifdef CURL_DOES_CONVERSIONS
|
||||
/* Convert to host encoding before calling Curl_client_write */
|
||||
result = Curl_convert_from_network(conn->data,
|
||||
conn->trailer,
|
||||
conn->trlPos);
|
||||
if(result != CURLE_OK) {
|
||||
/* Curl_convert_from_network calls failf if unsuccessful */
|
||||
/* Treat it as a bad chunk */
|
||||
return(CHUNKE_BAD_CHUNK);
|
||||
}
|
||||
#endif /* CURL_DOES_CONVERSIONS */
|
||||
Curl_client_write(conn, CLIENTWRITE_HEADER,
|
||||
conn->trailer, conn->trlPos);
|
||||
}
|
||||
|
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -39,6 +39,7 @@
|
||||
#include "strtok.h"
|
||||
#include "url.h" /* for Curl_safefree() */
|
||||
#include "memory.h"
|
||||
#include "easyif.h" /* included for Curl_convert_... prototypes */
|
||||
|
||||
#define _MPRINTF_REPLACE /* use our functions only */
|
||||
#include <curl/mprintf.h>
|
||||
@@ -234,6 +235,21 @@ CURLcode Curl_output_digest(struct connectdata *conn,
|
||||
|
||||
struct SessionHandle *data = conn->data;
|
||||
struct digestdata *d;
|
||||
#ifdef CURL_DOES_CONVERSIONS
|
||||
CURLcode rc;
|
||||
/* The CURL_OUTPUT_DIGEST_CONV macro below is for non-ASCII machines.
|
||||
It converts digest text to ASCII so the MD5 will be correct for
|
||||
what ultimately goes over the network.
|
||||
*/
|
||||
#define CURL_OUTPUT_DIGEST_CONV(a, b) \
|
||||
rc = Curl_convert_to_network(a, (char *)b, strlen((const char*)b)); \
|
||||
if (rc != CURLE_OK) { \
|
||||
free(b); \
|
||||
return rc; \
|
||||
}
|
||||
#else
|
||||
#define CURL_OUTPUT_DIGEST_CONV(a, b)
|
||||
#endif /* CURL_DOES_CONVERSIONS */
|
||||
|
||||
if(proxy) {
|
||||
d = &data->state.proxydigest;
|
||||
@@ -270,7 +286,7 @@ CURLcode Curl_output_digest(struct connectdata *conn,
|
||||
/* Generate a cnonce */
|
||||
now = Curl_tvnow();
|
||||
snprintf(cnoncebuf, sizeof(cnoncebuf), "%06ld", now.tv_sec);
|
||||
if(Curl_base64_encode(cnoncebuf, strlen(cnoncebuf), &cnonce))
|
||||
if(Curl_base64_encode(data, cnoncebuf, strlen(cnoncebuf), &cnonce))
|
||||
d->cnonce = cnonce;
|
||||
else
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
@@ -291,6 +307,8 @@ CURLcode Curl_output_digest(struct connectdata *conn,
|
||||
aprintf("%s:%s:%s", userp, d->realm, passwdp);
|
||||
if(!md5this)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
CURL_OUTPUT_DIGEST_CONV(data, md5this); /* convert on non-ASCII machines */
|
||||
Curl_md5it(md5buf, md5this);
|
||||
free(md5this); /* free this again */
|
||||
|
||||
@@ -305,6 +323,7 @@ CURLcode Curl_output_digest(struct connectdata *conn,
|
||||
tmp = aprintf("%s:%s:%s", ha1, d->nonce, d->cnonce);
|
||||
if(!tmp)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
CURL_OUTPUT_DIGEST_CONV(data, tmp); /* convert on non-ASCII machines */
|
||||
Curl_md5it(md5buf, (unsigned char *)tmp);
|
||||
free(tmp); /* free this again */
|
||||
md5_to_ascii(md5buf, ha1);
|
||||
@@ -334,6 +353,7 @@ CURLcode Curl_output_digest(struct connectdata *conn,
|
||||
entity-body here */
|
||||
/* TODO: Append H(entity-body)*/
|
||||
}
|
||||
CURL_OUTPUT_DIGEST_CONV(data, md5this); /* convert on non-ASCII machines */
|
||||
Curl_md5it(md5buf, md5this);
|
||||
free(md5this); /* free this again */
|
||||
md5_to_ascii(md5buf, ha2);
|
||||
@@ -357,6 +377,7 @@ CURLcode Curl_output_digest(struct connectdata *conn,
|
||||
if(!md5this)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
CURL_OUTPUT_DIGEST_CONV(data, md5this); /* convert on non-ASCII machines */
|
||||
Curl_md5it(md5buf, md5this);
|
||||
free(md5this); /* free this again */
|
||||
md5_to_ascii(md5buf, request_digest);
|
||||
|
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -290,7 +290,8 @@ CURLcode Curl_output_negotiate(struct connectdata *conn)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
len = Curl_base64_encode(neg_ctx->output_token.value,
|
||||
len = Curl_base64_encode(conn->data,
|
||||
neg_ctx->output_token.value,
|
||||
neg_ctx->output_token.length,
|
||||
&encoded);
|
||||
|
||||
|
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -44,7 +44,12 @@
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "urldata.h"
|
||||
#include "easyif.h" /* for Curl_convert_... prototypes */
|
||||
#include "sendf.h"
|
||||
#include "strequal.h"
|
||||
#include "base64.h"
|
||||
@@ -56,6 +61,9 @@
|
||||
#define _MPRINTF_REPLACE /* use our functions only */
|
||||
#include <curl/mprintf.h>
|
||||
|
||||
/* "NTLMSSP" signature is always in ASCII regardless of the platform */
|
||||
#define NTLMSSP_SIGNATURE "\x4e\x54\x4c\x4d\x53\x53\x50"
|
||||
|
||||
#ifndef USE_WINDOWS_SSPI
|
||||
|
||||
#include <openssl/des.h>
|
||||
@@ -261,7 +269,7 @@ CURLntlm Curl_input_ntlm(struct connectdata *conn,
|
||||
ntlm->flags = 0;
|
||||
|
||||
if((size < 32) ||
|
||||
(memcmp(buffer, "NTLMSSP", 8) != 0) ||
|
||||
(memcmp(buffer, NTLMSSP_SIGNATURE, 8) != 0) ||
|
||||
(memcmp(buffer+8, type2_marker, sizeof(type2_marker)) != 0)) {
|
||||
/* This was not a good enough type-2 message */
|
||||
free(buffer);
|
||||
@@ -275,7 +283,7 @@ CURLntlm Curl_input_ntlm(struct connectdata *conn,
|
||||
fprintf(stderr, "**** TYPE2 header flags=0x%08.8lx ", ntlm->flags);
|
||||
print_flags(stderr, ntlm->flags);
|
||||
fprintf(stderr, "\n nonce=");
|
||||
print_hex(stderr, ntlm->nonce, 8);
|
||||
print_hex(stderr, (char *)ntlm->nonce, 8);
|
||||
fprintf(stderr, "\n****\n");
|
||||
fprintf(stderr, "**** Header %s\n ", header);
|
||||
});
|
||||
@@ -345,7 +353,9 @@ static void lm_resp(unsigned char *keys,
|
||||
/*
|
||||
* Set up lanmanager hashed password
|
||||
*/
|
||||
static void mk_lm_hash(char *password, unsigned char *lmbuffer /* 21 bytes */)
|
||||
static void mk_lm_hash(struct SessionHandle *data,
|
||||
char *password,
|
||||
unsigned char *lmbuffer /* 21 bytes */)
|
||||
{
|
||||
unsigned char pw[14];
|
||||
static const unsigned char magic[] = {
|
||||
@@ -363,6 +373,17 @@ static void mk_lm_hash(char *password, unsigned char *lmbuffer /* 21 bytes */)
|
||||
for (; i<14; i++)
|
||||
pw[i] = 0;
|
||||
|
||||
#ifdef CURL_DOES_CONVERSIONS
|
||||
/*
|
||||
* The LanManager hashed password needs to be created using the
|
||||
* password in the network encoding not the host encoding.
|
||||
*/
|
||||
if(data)
|
||||
Curl_convert_to_network(data, (char *)pw, 14);
|
||||
#else
|
||||
(void)data;
|
||||
#endif
|
||||
|
||||
{
|
||||
/* Create LanManager hashed password. */
|
||||
|
||||
@@ -394,13 +415,26 @@ static void utf8_to_unicode_le(unsigned char *dest, const char *src,
|
||||
/*
|
||||
* Set up nt hashed passwords
|
||||
*/
|
||||
static void mk_nt_hash(char *password, unsigned char *ntbuffer /* 21 bytes */)
|
||||
static void mk_nt_hash(struct SessionHandle *data,
|
||||
char *password,
|
||||
unsigned char *ntbuffer /* 21 bytes */)
|
||||
{
|
||||
size_t len = strlen(password);
|
||||
unsigned char *pw = malloc(len*2);
|
||||
|
||||
utf8_to_unicode_le(pw, password, len);
|
||||
|
||||
#ifdef CURL_DOES_CONVERSIONS
|
||||
/*
|
||||
* The NT hashed password needs to be created using the
|
||||
* password in the network encoding not the host encoding.
|
||||
*/
|
||||
if(data)
|
||||
Curl_convert_to_network(data, (char *)pw, len*2);
|
||||
#else
|
||||
(void)data;
|
||||
#endif
|
||||
|
||||
{
|
||||
/* Create NT hashed password. */
|
||||
MD4_CTX MD4;
|
||||
@@ -643,7 +677,7 @@ CURLcode Curl_output_ntlm(struct connectdata *conn,
|
||||
#else
|
||||
#define NTLM2FLAG 0
|
||||
#endif
|
||||
snprintf((char *)ntlmbuf, sizeof(ntlmbuf), "NTLMSSP%c"
|
||||
snprintf((char *)ntlmbuf, sizeof(ntlmbuf), NTLMSSP_SIGNATURE "%c"
|
||||
"\x01%c%c%c" /* 32-bit type = 1 */
|
||||
"%c%c%c%c" /* 32-bit NTLM flag field */
|
||||
"%c%c" /* domain length */
|
||||
@@ -702,7 +736,7 @@ CURLcode Curl_output_ntlm(struct connectdata *conn,
|
||||
});
|
||||
|
||||
/* now size is the size of the base64 encoded package size */
|
||||
size = Curl_base64_encode((char *)ntlmbuf, size, &base64);
|
||||
size = Curl_base64_encode(NULL, (char *)ntlmbuf, size, &base64);
|
||||
|
||||
if(size >0 ) {
|
||||
Curl_safefree(*allocuserpwd);
|
||||
@@ -837,7 +871,7 @@ CURLcode Curl_output_ntlm(struct connectdata *conn,
|
||||
MD5_Final(md5sum, &MD5);
|
||||
/* We shall only use the first 8 bytes of md5sum,
|
||||
but the des code in lm_resp only encrypt the first 8 bytes */
|
||||
mk_nt_hash(passwdp, ntbuffer);
|
||||
mk_nt_hash(conn->data, passwdp, ntbuffer);
|
||||
lm_resp(ntbuffer, md5sum, ntresp);
|
||||
|
||||
/* End of NTLM2 Session code */
|
||||
@@ -851,16 +885,18 @@ CURLcode Curl_output_ntlm(struct connectdata *conn,
|
||||
unsigned char lmbuffer[0x18];
|
||||
|
||||
#if USE_NTRESPONSES
|
||||
mk_nt_hash(passwdp, ntbuffer);
|
||||
mk_nt_hash(conn->data, passwdp, ntbuffer);
|
||||
lm_resp(ntbuffer, &ntlm->nonce[0], ntresp);
|
||||
#endif
|
||||
|
||||
mk_lm_hash(passwdp, lmbuffer);
|
||||
mk_lm_hash(conn->data, passwdp, lmbuffer);
|
||||
lm_resp(lmbuffer, &ntlm->nonce[0], lmresp);
|
||||
/* A safer but less compatible alternative is:
|
||||
* lm_resp(ntbuffer, &ntlm->nonce[0], lmresp);
|
||||
* See http://davenport.sourceforge.net/ntlm.html#ntlmVersion2 */
|
||||
#if USE_NTLM2SESSION
|
||||
}
|
||||
#endif
|
||||
|
||||
lmrespoff = 64; /* size of the message header */
|
||||
#if USE_NTRESPONSES
|
||||
@@ -874,7 +910,7 @@ CURLcode Curl_output_ntlm(struct connectdata *conn,
|
||||
|
||||
/* Create the big type-3 message binary blob */
|
||||
size = snprintf((char *)ntlmbuf, sizeof(ntlmbuf),
|
||||
"NTLMSSP%c"
|
||||
NTLMSSP_SIGNATURE "%c"
|
||||
"\x03%c%c%c" /* type-3, 32 bits */
|
||||
|
||||
"%c%c" /* LanManager length */
|
||||
@@ -966,7 +1002,7 @@ CURLcode Curl_output_ntlm(struct connectdata *conn,
|
||||
|
||||
DEBUG_OUT({
|
||||
fprintf(stderr, "**** TYPE3 header lmresp=");
|
||||
print_hex(stderr, &ntlmbuf[lmrespoff], 0x18);
|
||||
print_hex(stderr, (char *)&ntlmbuf[lmrespoff], 0x18);
|
||||
});
|
||||
|
||||
#if USE_NTRESPONSES
|
||||
@@ -978,7 +1014,7 @@ CURLcode Curl_output_ntlm(struct connectdata *conn,
|
||||
|
||||
DEBUG_OUT({
|
||||
fprintf(stderr, "\n ntresp=");
|
||||
print_hex(stderr, &ntlmbuf[ntrespoff], 0x18);
|
||||
print_hex(stderr, (char *)&ntlmbuf[ntrespoff], 0x18);
|
||||
});
|
||||
|
||||
#endif
|
||||
@@ -1010,10 +1046,19 @@ CURLcode Curl_output_ntlm(struct connectdata *conn,
|
||||
memcpy(&ntlmbuf[size], host, hostlen);
|
||||
size += hostlen;
|
||||
|
||||
#ifdef CURL_DOES_CONVERSIONS
|
||||
/* convert domain, user, and host to ASCII but leave the rest as-is */
|
||||
if(CURLE_OK != Curl_convert_to_network(conn->data,
|
||||
(char *)&ntlmbuf[domoff],
|
||||
size-domoff)) {
|
||||
return CURLE_CONV_FAILED;
|
||||
}
|
||||
#endif /* CURL_DOES_CONVERSIONS */
|
||||
|
||||
#endif
|
||||
|
||||
/* convert the binary blob into base64 */
|
||||
size = Curl_base64_encode((char *)ntlmbuf, size, &base64);
|
||||
size = Curl_base64_encode(NULL, (char *)ntlmbuf, size, &base64);
|
||||
|
||||
if(size >0 ) {
|
||||
Curl_safefree(*allocuserpwd);
|
||||
|
@@ -7,7 +7,7 @@
|
||||
*
|
||||
* Copyright (c) 1995, 1996, 1997, 1998, 1999 Kungliga Tekniska H<>gskolan
|
||||
* (Royal Institute of Technology, Stockholm, Sweden).
|
||||
* Copyright (c) 2004 - 2006 Daniel Stenberg
|
||||
* Copyright (c) 2004 - 2007 Daniel Stenberg
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -252,7 +252,7 @@ krb4_auth(void *app_data, struct connectdata *conn)
|
||||
}
|
||||
#endif
|
||||
|
||||
if(Curl_base64_encode((char *)adat.dat, adat.length, &p) < 1) {
|
||||
if(Curl_base64_encode(conn->data, (char *)adat.dat, adat.length, &p) < 1) {
|
||||
Curl_failf(data, "Out of memory base64-encoding");
|
||||
return AUTH_CONTINUE;
|
||||
}
|
||||
@@ -400,7 +400,8 @@ CURLcode Curl_krb_kauth(struct connectdata *conn)
|
||||
memset(key, 0, sizeof(key));
|
||||
memset(schedule, 0, sizeof(schedule));
|
||||
memset(passwd, 0, sizeof(passwd));
|
||||
if(Curl_base64_encode((char *)tktcopy.dat, tktcopy.length, &p) < 1) {
|
||||
if(Curl_base64_encode(conn->data, (char *)tktcopy.dat, tktcopy.length, &p)
|
||||
< 1) {
|
||||
failf(conn->data, "Out of memory base64-encoding.");
|
||||
Curl_set_command_prot(conn, save);
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
@@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2005, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -53,7 +53,8 @@ int Curl_sec_read_msg (struct connectdata *conn, char *, int);
|
||||
int Curl_sec_vfprintf(struct connectdata *, FILE *, const char *, va_list);
|
||||
int Curl_sec_fprintf2(struct connectdata *conn, FILE *f, const char *fmt, ...);
|
||||
int Curl_sec_vfprintf2(struct connectdata *conn, FILE *, const char *, va_list);
|
||||
int Curl_sec_write (struct connectdata *conn, int, char *, int);
|
||||
ssize_t Curl_sec_send(struct connectdata *conn, int, char *, int);
|
||||
int Curl_sec_write(struct connectdata *conn, int, char *, int);
|
||||
|
||||
void Curl_sec_end (struct connectdata *);
|
||||
int Curl_sec_login (struct connectdata *);
|
||||
|
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -402,7 +402,9 @@ CURLcode Curl_ldap(struct connectdata *conn, bool *done)
|
||||
(char *)attribute +
|
||||
(strlen((char *)attribute) - 7)) == 0)) {
|
||||
/* Binary attribute, encode to base64. */
|
||||
val_b64_sz = Curl_base64_encode(vals[i]->bv_val, vals[i]->bv_len,
|
||||
val_b64_sz = Curl_base64_encode(conn->data,
|
||||
vals[i]->bv_val,
|
||||
vals[i]->bv_len,
|
||||
&val_b64);
|
||||
if (val_b64_sz > 0) {
|
||||
Curl_client_write(conn, CLIENTWRITE_BODY, val_b64, val_b64_sz);
|
||||
|
@@ -120,11 +120,11 @@ $(LIB_DIR)/libcurl.framework: $(OBJECTS) $(LIB_DIR)/libcurl.plist
|
||||
mkdir -p $(LIB_DIR)/libcurl.framework/Versions/A/Headers
|
||||
cp $(LIB_DIR)/../include/curl/*.h $(LIB_DIR)/libcurl.framework/Versions/A/Headers
|
||||
cd $(LIB_DIR)/libcurl.framework; \
|
||||
ln -fs ./Versions/A/libcurl libcurl; \
|
||||
ln -fs ./Versions/A/Resources Resources; \
|
||||
ln -fs ./Versions/A/Headers Headers
|
||||
ln -fs Versions/A/libcurl libcurl; \
|
||||
ln -fs Versions/A/Resources Resources; \
|
||||
ln -fs Versions/A/Headers Headers
|
||||
cd $(LIB_DIR)/libcurl.framework/Versions; \
|
||||
ln -fs ./A Current
|
||||
ln -fs A Current
|
||||
|
||||
$(OBJECTS) : $(TMP_DIR)/%.o: $(LIB_DIR)/%.c
|
||||
$(CC) $(C_OPTIONS) -c $< -o $@
|
||||
|
@@ -1,3 +1,25 @@
|
||||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
* are also available at http://curl.haxx.se/docs/copyright.html.
|
||||
*
|
||||
* 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 COPYING file.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
* $Id$
|
||||
***************************************************************************/
|
||||
#include <winver.h>
|
||||
#include "../include/curl/curlver.h"
|
||||
|
||||
@@ -30,7 +52,7 @@ BEGIN
|
||||
VALUE "OriginalFilename", "libcurl.dll\0"
|
||||
VALUE "ProductName", "The cURL library\0"
|
||||
VALUE "ProductVersion", LIBCURL_VERSION "\0"
|
||||
VALUE "LegalCopyright", "Copyright 1996-2005 by Daniel Stenberg. http://curl.haxx.se/docs/copyright.html\0"
|
||||
VALUE "LegalCopyright", "Copyright 1996-2007 by Daniel Stenberg. http://curl.haxx.se/docs/copyright.html\0"
|
||||
END
|
||||
END
|
||||
|
||||
|
@@ -61,25 +61,29 @@ struct memdebug {
|
||||
*/
|
||||
|
||||
#define logfile curl_debuglogfile
|
||||
FILE *curl_debuglogfile;
|
||||
static bool memlimit; /* enable memory limit */
|
||||
static long memsize; /* set number of mallocs allowed */
|
||||
FILE *curl_debuglogfile = NULL;
|
||||
static bool memlimit = FALSE; /* enable memory limit */
|
||||
static long memsize = 0; /* set number of mallocs allowed */
|
||||
|
||||
/* this sets the log file name */
|
||||
void curl_memdebug(const char *logname)
|
||||
{
|
||||
if(logname)
|
||||
logfile = fopen(logname, "w");
|
||||
else
|
||||
logfile = stderr;
|
||||
if (!logfile) {
|
||||
if(logname)
|
||||
logfile = fopen(logname, "w");
|
||||
else
|
||||
logfile = stderr;
|
||||
}
|
||||
}
|
||||
|
||||
/* This function sets the number of malloc() calls that should return
|
||||
successfully! */
|
||||
void curl_memlimit(long limit)
|
||||
{
|
||||
memlimit = TRUE;
|
||||
memsize = limit;
|
||||
if (!memlimit) {
|
||||
memlimit = TRUE;
|
||||
memsize = limit;
|
||||
}
|
||||
}
|
||||
|
||||
/* returns TRUE if this isn't allowed! */
|
||||
|
24
lib/multi.c
24
lib/multi.c
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -347,7 +347,7 @@ CURLM *curl_multi_init(void)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
multi->connc = Curl_mk_connc(CONNCACHE_MULTI);
|
||||
multi->connc = Curl_mk_connc(CONNCACHE_MULTI, -1);
|
||||
if(!multi->connc) {
|
||||
Curl_hash_destroy(multi->hostcache);
|
||||
free(multi);
|
||||
@@ -512,9 +512,11 @@ CURLMcode curl_multi_remove_handle(CURLM *multi_handle,
|
||||
}
|
||||
|
||||
if(easy) {
|
||||
bool premature = (bool)(easy->state != CURLM_STATE_COMPLETED);
|
||||
|
||||
/* If the 'state' is not INIT or COMPLETED, we might need to do something
|
||||
nice to put the easy_handle in a good known state when this returns. */
|
||||
if(easy->state != CURLM_STATE_COMPLETED)
|
||||
if(premature)
|
||||
/* this handle is "alive" so we need to count down the total number of
|
||||
alive connections when this is removed */
|
||||
multi->num_alive--;
|
||||
@@ -547,7 +549,7 @@ CURLMcode curl_multi_remove_handle(CURLM *multi_handle,
|
||||
|
||||
/* Curl_done() clears the conn->data field to lose the association
|
||||
between the easy handle and the connection */
|
||||
Curl_done(&easy->easy_conn, easy->result);
|
||||
Curl_done(&easy->easy_conn, easy->result, premature);
|
||||
|
||||
if(easy->easy_conn)
|
||||
/* the connection is still alive, set back the association to enable
|
||||
@@ -802,7 +804,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
||||
char *gotourl;
|
||||
Curl_posttransfer(easy->easy_handle);
|
||||
|
||||
easy->result = Curl_done(&easy->easy_conn, CURLE_OK);
|
||||
easy->result = Curl_done(&easy->easy_conn, CURLE_OK, FALSE);
|
||||
/* We make sure that the pipe broken flag is reset
|
||||
because in this case, it isn't an actual break */
|
||||
easy->easy_handle->state.pipe_broke = FALSE;
|
||||
@@ -950,7 +952,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
||||
else if(easy->result) {
|
||||
/* failure detected */
|
||||
Curl_posttransfer(easy->easy_handle);
|
||||
Curl_done(&easy->easy_conn, easy->result);
|
||||
Curl_done(&easy->easy_conn, easy->result, FALSE);
|
||||
Curl_disconnect(easy->easy_conn); /* close the connection */
|
||||
easy->easy_conn = NULL; /* no more connection */
|
||||
}
|
||||
@@ -1017,7 +1019,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
||||
else {
|
||||
/* failure detected */
|
||||
Curl_posttransfer(easy->easy_handle);
|
||||
Curl_done(&easy->easy_conn, easy->result);
|
||||
Curl_done(&easy->easy_conn, easy->result, FALSE);
|
||||
Curl_disconnect(easy->easy_conn); /* close the connection */
|
||||
easy->easy_conn = NULL; /* no more connection */
|
||||
}
|
||||
@@ -1050,7 +1052,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
||||
else {
|
||||
/* failure detected */
|
||||
Curl_posttransfer(easy->easy_handle);
|
||||
Curl_done(&easy->easy_conn, easy->result);
|
||||
Curl_done(&easy->easy_conn, easy->result, FALSE);
|
||||
Curl_disconnect(easy->easy_conn); /* close the connection */
|
||||
easy->easy_conn = NULL; /* no more connection */
|
||||
}
|
||||
@@ -1169,7 +1171,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
||||
easy->easy_conn->sock[SECONDARYSOCKET] = CURL_SOCKET_BAD;
|
||||
}
|
||||
Curl_posttransfer(easy->easy_handle);
|
||||
Curl_done(&easy->easy_conn, easy->result);
|
||||
Curl_done(&easy->easy_conn, easy->result, FALSE);
|
||||
}
|
||||
else if(TRUE == done) {
|
||||
char *newurl;
|
||||
@@ -1188,7 +1190,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
||||
newurl = easy->easy_handle->reqdata.newurl;
|
||||
easy->easy_handle->reqdata.newurl = NULL;
|
||||
}
|
||||
easy->result = Curl_done(&easy->easy_conn, CURLE_OK);
|
||||
easy->result = Curl_done(&easy->easy_conn, CURLE_OK, FALSE);
|
||||
if(easy->result == CURLE_OK)
|
||||
easy->result = Curl_follow(easy->easy_handle, newurl, retry);
|
||||
if(CURLE_OK == easy->result) {
|
||||
@@ -1224,7 +1226,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
||||
|
||||
if (!easy->easy_handle->state.cancelled) {
|
||||
/* post-transfer command */
|
||||
easy->result = Curl_done(&easy->easy_conn, CURLE_OK);
|
||||
easy->result = Curl_done(&easy->easy_conn, CURLE_OK, FALSE);
|
||||
|
||||
/* after we have DONE what we're supposed to do, go COMPLETED, and
|
||||
it doesn't matter what the Curl_done() returned! */
|
||||
|
@@ -239,18 +239,6 @@ static time_t Curl_parsedate(const char *date)
|
||||
const char *indate = date; /* save the original pointer */
|
||||
int part = 0; /* max 6 parts */
|
||||
|
||||
#ifdef WIN32
|
||||
/*
|
||||
* On Windows, we need an odd work-around for the case when no TZ variable
|
||||
* is set. If it isn't set and "automatic DST adjustment" is enabled, the
|
||||
* time functions below will return values one hour off! As reported and
|
||||
* investigated in bug report #1230118.
|
||||
*/
|
||||
const char *env = getenv("TZ");
|
||||
if(!env)
|
||||
putenv("TZ=GMT");
|
||||
#endif
|
||||
|
||||
while(*date && (part < 6)) {
|
||||
bool found=FALSE;
|
||||
|
||||
@@ -400,13 +388,22 @@ static time_t Curl_parsedate(const char *date)
|
||||
/* thread-safe version */
|
||||
struct tm keeptime2;
|
||||
gmt = (struct tm *)gmtime_r(&t, &keeptime2);
|
||||
#else
|
||||
gmt = gmtime(&t); /* use gmtime_r() if available */
|
||||
#endif
|
||||
if(!gmt)
|
||||
return -1; /* illegal date/time */
|
||||
|
||||
t2 = mktime(gmt);
|
||||
#else
|
||||
/* It seems that at least the MSVC version of mktime() doesn't work
|
||||
properly if it gets the 'gmt' pointer passed in (which is a pointer
|
||||
returned from gmtime() pointing to static memory), so instead we copy
|
||||
the tm struct to a local struct and pass a pointer to that struct as
|
||||
input to mktime(). */
|
||||
struct tm gmt2;
|
||||
gmt = gmtime(&t); /* use gmtime_r() if available */
|
||||
if(!gmt)
|
||||
return -1; /* illegal date/time */
|
||||
gmt2 = *gmt;
|
||||
t2 = mktime(&gmt2);
|
||||
#endif
|
||||
|
||||
/* Add the time zone diff (between the given timezone and GMT) and the
|
||||
diff between the local time zone and GMT. */
|
||||
|
@@ -278,6 +278,13 @@ Curl_sec_write(struct connectdata *conn, int fd, char *buffer, int length)
|
||||
return tx;
|
||||
}
|
||||
|
||||
ssize_t
|
||||
Curl_sec_send(struct connectdata *conn, int num, char *buffer, int length)
|
||||
{
|
||||
curl_socket_t fd = conn->sock[num];
|
||||
return (ssize_t)Curl_sec_write(conn, fd, buffer, length);
|
||||
}
|
||||
|
||||
int
|
||||
Curl_sec_putc(struct connectdata *conn, int c, FILE *F)
|
||||
{
|
||||
|
25
lib/select.c
25
lib/select.c
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -44,6 +44,10 @@
|
||||
#include <socket.h>
|
||||
#endif
|
||||
|
||||
#ifdef __MSDOS__
|
||||
#include <dos.h> /* delay() */
|
||||
#endif
|
||||
|
||||
#include <curl/curl.h>
|
||||
|
||||
#include "urldata.h"
|
||||
@@ -111,7 +115,7 @@ int Curl_select(curl_socket_t readfd, curl_socket_t writefd, int timeout_ms)
|
||||
if (pfd[num].revents & (POLLIN|POLLHUP))
|
||||
ret |= CSELECT_IN;
|
||||
if (pfd[num].revents & POLLERR) {
|
||||
#ifdef __CYGWIN__
|
||||
#ifdef __CYGWIN__
|
||||
/* Cygwin 1.5.21 needs this hack to pass test 160 */
|
||||
if (errno == EINPROGRESS)
|
||||
ret |= CSELECT_IN;
|
||||
@@ -124,7 +128,7 @@ int Curl_select(curl_socket_t readfd, curl_socket_t writefd, int timeout_ms)
|
||||
if (writefd != CURL_SOCKET_BAD) {
|
||||
if (pfd[num].revents & POLLOUT)
|
||||
ret |= CSELECT_OUT;
|
||||
if (pfd[num].revents & POLLERR)
|
||||
if (pfd[num].revents & (POLLERR|POLLHUP))
|
||||
ret |= CSELECT_ERR;
|
||||
}
|
||||
|
||||
@@ -141,6 +145,21 @@ int Curl_select(curl_socket_t readfd, curl_socket_t writefd, int timeout_ms)
|
||||
timeout.tv_sec = timeout_ms / 1000;
|
||||
timeout.tv_usec = (timeout_ms % 1000) * 1000;
|
||||
|
||||
if((readfd == CURL_SOCKET_BAD) && (writefd == CURL_SOCKET_BAD)) {
|
||||
/* According to POSIX we should pass in NULL pointers if we don't want to
|
||||
wait for anything in particular but just use the timeout function.
|
||||
Windows however returns immediately if done so. I copied the MSDOS
|
||||
delay() use from src/main.c that already had this work-around. */
|
||||
#ifdef WIN32
|
||||
Sleep(timeout_ms);
|
||||
#elif defined(__MSDOS__)
|
||||
delay(timeout_ms);
|
||||
#else
|
||||
select(0, NULL, NULL, NULL, &timeout);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
FD_ZERO(&fds_err);
|
||||
maxfd = (curl_socket_t)-1;
|
||||
|
||||
|
200
lib/sendf.c
200
lib/sendf.c
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -45,6 +45,8 @@
|
||||
#include "sendf.h"
|
||||
#include "connect.h" /* for the Curl_sockerrno() proto */
|
||||
#include "sslgen.h"
|
||||
#include "ssh.h"
|
||||
#include "multiif.h"
|
||||
|
||||
#define _MPRINTF_REPLACE /* use the internal *printf() functions */
|
||||
#include <curl/mprintf.h>
|
||||
@@ -52,7 +54,7 @@
|
||||
#ifdef HAVE_KRB4
|
||||
#include "krb4.h"
|
||||
#else
|
||||
#define Curl_sec_write(a,b,c,d) -1
|
||||
#define Curl_sec_send(a,b,c,d) -1
|
||||
#define Curl_sec_read(a,b,c,d) -1
|
||||
#endif
|
||||
|
||||
@@ -312,9 +314,40 @@ CURLcode Curl_sendf(curl_socket_t sockfd, struct connectdata *conn,
|
||||
return res;
|
||||
}
|
||||
|
||||
static ssize_t Curl_plain_send(struct connectdata *conn,
|
||||
int num,
|
||||
void *mem,
|
||||
size_t len)
|
||||
{
|
||||
curl_socket_t sockfd = conn->sock[num];
|
||||
ssize_t bytes_written = swrite(sockfd, mem, len);
|
||||
|
||||
if(-1 == bytes_written) {
|
||||
int err = Curl_sockerrno();
|
||||
|
||||
if(
|
||||
#ifdef WSAEWOULDBLOCK
|
||||
/* This is how Windows does it */
|
||||
(WSAEWOULDBLOCK == err)
|
||||
#else
|
||||
/* errno may be EWOULDBLOCK or on some systems EAGAIN when it returned
|
||||
due to its inability to send off data without blocking. We therefor
|
||||
treat both error codes the same here */
|
||||
(EWOULDBLOCK == err) || (EAGAIN == err) || (EINTR == err)
|
||||
#endif
|
||||
)
|
||||
/* this is just a case of EWOULDBLOCK */
|
||||
bytes_written=0;
|
||||
else
|
||||
failf(conn->data, "Send failure: %s",
|
||||
Curl_strerror(conn, err));
|
||||
}
|
||||
return bytes_written;
|
||||
}
|
||||
|
||||
/*
|
||||
* Curl_write() is an internal write function that sends plain (binary) data
|
||||
* to the server. Works with plain sockets, SSL or kerberos.
|
||||
* Curl_write() is an internal write function that sends data to the
|
||||
* server. Works with plain sockets, SCP, SSL or kerberos.
|
||||
*/
|
||||
CURLcode Curl_write(struct connectdata *conn,
|
||||
curl_socket_t sockfd,
|
||||
@@ -329,35 +362,18 @@ CURLcode Curl_write(struct connectdata *conn,
|
||||
if (conn->ssl[num].use)
|
||||
/* only TRUE if SSL enabled */
|
||||
bytes_written = Curl_ssl_send(conn, num, mem, len);
|
||||
else {
|
||||
if(conn->sec_complete)
|
||||
/* only TRUE if krb4 enabled */
|
||||
bytes_written = Curl_sec_write(conn, sockfd, mem, len);
|
||||
else
|
||||
bytes_written = swrite(sockfd, mem, len);
|
||||
#ifdef USE_LIBSSH2
|
||||
else if (conn->protocol & PROT_SCP)
|
||||
bytes_written = Curl_scp_send(conn, num, mem, len);
|
||||
else if (conn->protocol & PROT_SFTP)
|
||||
bytes_written = Curl_sftp_send(conn, num, mem, len);
|
||||
#endif /* !USE_LIBSSH2 */
|
||||
else if(conn->sec_complete)
|
||||
/* only TRUE if krb4 enabled */
|
||||
bytes_written = Curl_sec_send(conn, num, mem, len);
|
||||
else
|
||||
bytes_written = Curl_plain_send(conn, num, mem, len);
|
||||
|
||||
if(-1 == bytes_written) {
|
||||
int err = Curl_sockerrno();
|
||||
|
||||
if(
|
||||
#ifdef WSAEWOULDBLOCK
|
||||
/* This is how Windows does it */
|
||||
(WSAEWOULDBLOCK == err)
|
||||
#else
|
||||
/* As pointed out by Christophe Demory on March 11 2003, errno
|
||||
may be EWOULDBLOCK or on some systems EAGAIN when it returned
|
||||
due to its inability to send off data without blocking. We
|
||||
therefor treat both error codes the same here */
|
||||
(EWOULDBLOCK == err) || (EAGAIN == err) || (EINTR == err)
|
||||
#endif
|
||||
)
|
||||
/* this is just a case of EWOULDBLOCK */
|
||||
bytes_written=0;
|
||||
else
|
||||
failf(conn->data, "Send failure: %s",
|
||||
Curl_strerror(conn, err));
|
||||
}
|
||||
}
|
||||
*written = bytes_written;
|
||||
retcode = (-1 != bytes_written)?CURLE_OK:CURLE_SEND_ERROR;
|
||||
|
||||
@@ -438,25 +454,9 @@ CURLcode Curl_client_write(struct connectdata *conn,
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
#define MIN(a,b) (a < b ? a : b)
|
||||
|
||||
void Curl_read_rewind(struct connectdata *conn,
|
||||
size_t extraBytesRead)
|
||||
{
|
||||
char buf[512 + 1];
|
||||
size_t bytesToShow;
|
||||
|
||||
conn->read_pos -= extraBytesRead;
|
||||
conn->bits.stream_was_rewound = TRUE;
|
||||
|
||||
bytesToShow = MIN(conn->buf_len - conn->read_pos, sizeof(buf)-1);
|
||||
memcpy(buf, conn->master_buffer + conn->read_pos, bytesToShow);
|
||||
buf[bytesToShow] = '\0';
|
||||
|
||||
DEBUGF(infof(conn->data,
|
||||
"Buffer after stream rewind (read_pos = %d): [%s]",
|
||||
conn->read_pos, buf));
|
||||
}
|
||||
#ifndef MIN
|
||||
#define MIN(a,b) ((a) < (b) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Internal read-from-socket function. This is meant to deal with plain
|
||||
@@ -472,8 +472,10 @@ int Curl_read(struct connectdata *conn, /* connection data */
|
||||
ssize_t *n) /* amount bytes read */
|
||||
{
|
||||
ssize_t nread;
|
||||
size_t bytestocopy = MIN(conn->buf_len - conn->read_pos, sizerequested);
|
||||
size_t bytesfromsocket = 0;
|
||||
char *buffertofill = NULL;
|
||||
bool pipelining = (bool)(conn->data->multi &&
|
||||
Curl_multi_canPipeline(conn->data->multi));
|
||||
|
||||
/* Set 'num' to 0 or 1, depending on which socket that has been sent here.
|
||||
If it is the second socket, we set num to 1. Otherwise to 0. This lets
|
||||
@@ -482,32 +484,53 @@ int Curl_read(struct connectdata *conn, /* connection data */
|
||||
|
||||
*n=0; /* reset amount to zero */
|
||||
|
||||
/* Copy from our master buffer first if we have some unread data there*/
|
||||
if (bytestocopy > 0) {
|
||||
memcpy(buf, conn->master_buffer + conn->read_pos, bytestocopy);
|
||||
conn->read_pos += bytestocopy;
|
||||
conn->bits.stream_was_rewound = FALSE;
|
||||
/* If session can pipeline, check connection buffer */
|
||||
if(pipelining) {
|
||||
size_t bytestocopy = MIN(conn->buf_len - conn->read_pos, sizerequested);
|
||||
|
||||
*n = (ssize_t)bytestocopy;
|
||||
return CURLE_OK;
|
||||
}
|
||||
/* Copy from our master buffer first if we have some unread data there*/
|
||||
if (bytestocopy > 0) {
|
||||
memcpy(buf, conn->master_buffer + conn->read_pos, bytestocopy);
|
||||
conn->read_pos += bytestocopy;
|
||||
conn->bits.stream_was_rewound = FALSE;
|
||||
|
||||
/* If we come here, it means that there is no data to read from the buffer,
|
||||
* so we read from the socket */
|
||||
bytesfromsocket = MIN(sizerequested, sizeof(conn->master_buffer));
|
||||
|
||||
if(conn->ssl[num].use) {
|
||||
nread = Curl_ssl_recv(conn, num, conn->master_buffer, bytesfromsocket);
|
||||
|
||||
if(nread == -1)
|
||||
return -1; /* -1 from Curl_ssl_recv() means EWOULDBLOCK */
|
||||
*n = (ssize_t)bytestocopy;
|
||||
return CURLE_OK;
|
||||
}
|
||||
/* If we come here, it means that there is no data to read from the buffer,
|
||||
* so we read from the socket */
|
||||
bytesfromsocket = MIN(sizerequested, sizeof(conn->master_buffer));
|
||||
buffertofill = conn->master_buffer;
|
||||
}
|
||||
else {
|
||||
bytesfromsocket = MIN((long)sizerequested, conn->data->set.buffer_size ?
|
||||
conn->data->set.buffer_size : BUFSIZE);
|
||||
buffertofill = buf;
|
||||
}
|
||||
|
||||
if(conn->ssl[num].use) {
|
||||
nread = Curl_ssl_recv(conn, num, buffertofill, bytesfromsocket);
|
||||
|
||||
if(nread == -1) {
|
||||
return -1; /* -1 from Curl_ssl_recv() means EWOULDBLOCK */
|
||||
}
|
||||
}
|
||||
#ifdef USE_LIBSSH2
|
||||
else if (conn->protocol & PROT_SCP) {
|
||||
nread = Curl_scp_recv(conn, num, buffertofill, bytesfromsocket);
|
||||
/* TODO: return CURLE_OK also for nread <= 0
|
||||
read failures and timeouts ? */
|
||||
}
|
||||
else if (conn->protocol & PROT_SFTP) {
|
||||
nread = Curl_sftp_recv(conn, num, buffertofill, bytesfromsocket);
|
||||
}
|
||||
#endif /* !USE_LIBSSH2 */
|
||||
else {
|
||||
if(conn->sec_complete)
|
||||
nread = Curl_sec_read(conn, sockfd, conn->master_buffer,
|
||||
nread = Curl_sec_read(conn, sockfd, buffertofill,
|
||||
bytesfromsocket);
|
||||
else
|
||||
nread = sread(sockfd, conn->master_buffer, bytesfromsocket);
|
||||
nread = sread(sockfd, buffertofill, bytesfromsocket);
|
||||
|
||||
if(-1 == nread) {
|
||||
int err = Curl_sockerrno();
|
||||
@@ -521,11 +544,13 @@ int Curl_read(struct connectdata *conn, /* connection data */
|
||||
}
|
||||
|
||||
if (nread >= 0) {
|
||||
memcpy(buf, conn->master_buffer, nread);
|
||||
if(pipelining) {
|
||||
memcpy(buf, conn->master_buffer, nread);
|
||||
conn->buf_len = nread;
|
||||
conn->read_pos = nread;
|
||||
}
|
||||
|
||||
conn->buf_len = nread;
|
||||
conn->read_pos = nread;
|
||||
*n = nread;
|
||||
*n += nread;
|
||||
}
|
||||
|
||||
return CURLE_OK;
|
||||
@@ -540,6 +565,7 @@ static int showit(struct SessionHandle *data, curl_infotype type,
|
||||
|
||||
#ifdef CURL_DOES_CONVERSIONS
|
||||
char buf[BUFSIZE+1];
|
||||
size_t conv_size = 0;
|
||||
|
||||
switch(type) {
|
||||
case CURLINFO_HEADER_OUT:
|
||||
@@ -549,8 +575,24 @@ static int showit(struct SessionHandle *data, curl_infotype type,
|
||||
size = BUFSIZE; /* truncate if necessary */
|
||||
buf[BUFSIZE] = '\0';
|
||||
}
|
||||
conv_size = size;
|
||||
memcpy(buf, ptr, size);
|
||||
Curl_convert_from_network(data, buf, size);
|
||||
/* Special processing is needed for this block if it
|
||||
* contains both headers and data (separated by CRLFCRLF).
|
||||
* We want to convert just the headers, leaving the data as-is.
|
||||
*/
|
||||
if(size > 4) {
|
||||
size_t i;
|
||||
for(i = 0; i < size-4; i++) {
|
||||
if(memcmp(&buf[i], "\x0d\x0a\x0d\x0a", 4) == 0) {
|
||||
/* convert everthing through this CRLFCRLF but no further */
|
||||
conv_size = i + 4;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Curl_convert_from_network(data, buf, conv_size);
|
||||
/* Curl_convert_from_network calls failf if unsuccessful */
|
||||
/* we might as well continue even if it fails... */
|
||||
ptr = buf; /* switch pointer to use my buffer instead */
|
||||
@@ -571,6 +613,12 @@ static int showit(struct SessionHandle *data, curl_infotype type,
|
||||
case CURLINFO_HEADER_IN:
|
||||
fwrite(s_infotype[type], 2, 1, data->set.err);
|
||||
fwrite(ptr, size, 1, data->set.err);
|
||||
#ifdef CURL_DOES_CONVERSIONS
|
||||
if(size != conv_size) {
|
||||
/* we had untranslated data so we need an explicit newline */
|
||||
fwrite("\n", 1, 1, data->set.err);
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
default: /* nada */
|
||||
break;
|
||||
|
@@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -364,6 +364,11 @@ int fileno( FILE *stream);
|
||||
#define DEBUGF(x)
|
||||
#endif
|
||||
|
||||
/* non-configure builds may define CURL_WANTS_CA_BUNDLE_ENV */
|
||||
#if defined(CURL_WANTS_CA_BUNDLE_ENV) && !defined(CURL_CA_BUNDLE)
|
||||
#define CURL_CA_BUNDLE getenv("CURL_CA_BUNDLE")
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Include macros and defines that should only be processed once.
|
||||
*/
|
||||
|
@@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -36,7 +36,7 @@
|
||||
|
||||
/*
|
||||
* If we have the MSG_NOSIGNAL define, make sure we use
|
||||
* it as the fourth argument of send() and recv()
|
||||
* it as the fourth argument of function send()
|
||||
*/
|
||||
|
||||
#ifdef HAVE_MSG_NOSIGNAL
|
||||
@@ -81,7 +81,7 @@
|
||||
#define sread(x,y,z) (ssize_t)recv((RECV_TYPE_ARG1)(x), \
|
||||
(RECV_TYPE_ARG2)(y), \
|
||||
(RECV_TYPE_ARG3)(z), \
|
||||
(RECV_TYPE_ARG4)(SEND_4TH_ARG))
|
||||
(RECV_TYPE_ARG4)(0))
|
||||
#endif
|
||||
#else /* HAVE_RECV */
|
||||
#ifndef sread
|
||||
@@ -130,5 +130,24 @@
|
||||
#define ISPRINT(x) (isprint((int) ((unsigned char)x)))
|
||||
|
||||
|
||||
/*
|
||||
* Typedef to 'int' if sig_atomic_t is not an available 'typedefed' type.
|
||||
*/
|
||||
|
||||
#ifndef HAVE_SIG_ATOMIC_T
|
||||
typedef int sig_atomic_t;
|
||||
#define HAVE_SIG_ATOMIC_T
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Default return type for signal handlers.
|
||||
*/
|
||||
|
||||
#ifndef RETSIGTYPE
|
||||
#define RETSIGTYPE void
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* __SETUP_ONCE_H */
|
||||
|
||||
|
979
lib/ssh.c
Normal file
979
lib/ssh.c
Normal file
@@ -0,0 +1,979 @@
|
||||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
* are also available at http://curl.haxx.se/docs/copyright.html.
|
||||
*
|
||||
* 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 COPYING file.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
* $Id$
|
||||
***************************************************************************/
|
||||
|
||||
/* #define CURL_LIBSSH2_DEBUG */
|
||||
|
||||
#include "setup.h"
|
||||
|
||||
#ifdef USE_LIBSSH2
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <ctype.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include <libssh2.h>
|
||||
#include <libssh2_sftp.h>
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_FCNTL_H
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_STAT_H
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_TIME_H
|
||||
#include <time.h>
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
#else /* probably some kind of unix */
|
||||
#ifdef HAVE_SYS_SOCKET_H
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
#include <sys/types.h>
|
||||
#ifdef HAVE_NETINET_IN_H
|
||||
#include <netinet/in.h>
|
||||
#endif
|
||||
#ifdef HAVE_ARPA_INET_H
|
||||
#include <arpa/inet.h>
|
||||
#endif
|
||||
#ifdef HAVE_UTSNAME_H
|
||||
#include <sys/utsname.h>
|
||||
#endif
|
||||
#ifdef HAVE_NETDB_H
|
||||
#include <netdb.h>
|
||||
#endif
|
||||
#ifdef VMS
|
||||
#include <in.h>
|
||||
#include <inet.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if (defined(NETWARE) && defined(__NOVELL_LIBC__))
|
||||
#undef in_addr_t
|
||||
#define in_addr_t unsigned long
|
||||
#endif
|
||||
|
||||
#include <curl/curl.h>
|
||||
#include "urldata.h"
|
||||
#include "sendf.h"
|
||||
#include "easyif.h" /* for Curl_convert_... prototypes */
|
||||
|
||||
#include "if2ip.h"
|
||||
#include "hostip.h"
|
||||
#include "progress.h"
|
||||
#include "transfer.h"
|
||||
#include "escape.h"
|
||||
#include "http.h" /* for HTTP proxy tunnel stuff */
|
||||
#include "ssh.h"
|
||||
#include "url.h"
|
||||
#include "speedcheck.h"
|
||||
#include "getinfo.h"
|
||||
|
||||
#include "strtoofft.h"
|
||||
#include "strequal.h"
|
||||
#include "sslgen.h"
|
||||
#include "connect.h"
|
||||
#include "strerror.h"
|
||||
#include "memory.h"
|
||||
#include "inet_ntop.h"
|
||||
#include "select.h"
|
||||
#include "parsedate.h" /* for the week day and month names */
|
||||
#include "sockaddr.h" /* required for Curl_sockaddr_storage */
|
||||
#include "multiif.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 */
|
||||
#include <curl/mprintf.h>
|
||||
|
||||
#if defined(WIN32) || defined(MSDOS) || defined(__EMX__)
|
||||
#define DIRSEP '\\'
|
||||
#else
|
||||
#define DIRSEP '/'
|
||||
#endif
|
||||
|
||||
#define _MPRINTF_REPLACE /* use our functions only */
|
||||
#include <curl/mprintf.h>
|
||||
|
||||
/* The last #include file should be: */
|
||||
#ifdef CURLDEBUG
|
||||
#include "memdebug.h"
|
||||
#endif
|
||||
|
||||
#ifndef LIBSSH2_SFTP_S_IRUSR
|
||||
/* Here's a work-around for those of you who happend to run a libssh2 version
|
||||
that is 0.14 or older. We should remove this kludge as soon as we can
|
||||
require a more recent libssh2 release. */
|
||||
#ifndef S_IRGRP
|
||||
#define S_IRGRP 0
|
||||
#endif
|
||||
|
||||
#ifndef S_IROTH
|
||||
#define S_IROTH 0
|
||||
#endif
|
||||
|
||||
#define LIBSSH2_SFTP_S_IRUSR S_IRUSR
|
||||
#define LIBSSH2_SFTP_S_IWUSR S_IWUSR
|
||||
#define LIBSSH2_SFTP_S_IRGRP S_IRGRP
|
||||
#define LIBSSH2_SFTP_S_IROTH S_IROTH
|
||||
#define LIBSSH2_SFTP_S_IRUSR S_IRUSR
|
||||
#define LIBSSH2_SFTP_S_IWUSR S_IWUSR
|
||||
#define LIBSSH2_SFTP_S_IRGRP S_IRGRP
|
||||
#define LIBSSH2_SFTP_S_IROTH S_IROTH
|
||||
#define LIBSSH2_SFTP_S_IFMT S_IFMT
|
||||
#define LIBSSH2_SFTP_S_IFDIR S_IFDIR
|
||||
#define LIBSSH2_SFTP_S_IFLNK S_IFLNK
|
||||
#define LIBSSH2_SFTP_S_IFSOCK S_IFSOCK
|
||||
#define LIBSSH2_SFTP_S_IFCHR S_IFCHR
|
||||
#define LIBSSH2_SFTP_S_IFBLK S_IFBLK
|
||||
#define LIBSSH2_SFTP_S_IXUSR S_IXUSR
|
||||
#define LIBSSH2_SFTP_S_IWGRP S_IWGRP
|
||||
#define LIBSSH2_SFTP_S_IXGRP S_IXGRP
|
||||
#define LIBSSH2_SFTP_S_IWOTH S_IWOTH
|
||||
#define LIBSSH2_SFTP_S_IXOTH S_IXOTH
|
||||
#endif
|
||||
|
||||
static LIBSSH2_ALLOC_FUNC(libssh2_malloc);
|
||||
static LIBSSH2_REALLOC_FUNC(libssh2_realloc);
|
||||
static LIBSSH2_FREE_FUNC(libssh2_free);
|
||||
|
||||
static void
|
||||
kbd_callback(const char *name, int name_len, const char *instruction,
|
||||
int instruction_len, int num_prompts,
|
||||
const LIBSSH2_USERAUTH_KBDINT_PROMPT *prompts,
|
||||
LIBSSH2_USERAUTH_KBDINT_RESPONSE *responses,
|
||||
void **abstract)
|
||||
{
|
||||
struct SSHPROTO *ssh = (struct SSHPROTO *)*abstract;
|
||||
|
||||
#ifdef CURL_LIBSSH2_DEBUG
|
||||
fprintf(stderr, "name=%s\n", name);
|
||||
fprintf(stderr, "name_len=%d\n", name_len);
|
||||
fprintf(stderr, "instruction=%s\n", instruction);
|
||||
fprintf(stderr, "instruction_len=%d\n", instruction_len);
|
||||
fprintf(stderr, "num_prompts=%d\n", num_prompts);
|
||||
#else
|
||||
(void)name;
|
||||
(void)name_len;
|
||||
(void)instruction;
|
||||
(void)instruction_len;
|
||||
#endif /* CURL_LIBSSH2_DEBUG */
|
||||
if (num_prompts == 1) {
|
||||
responses[0].text = strdup(ssh->passwd);
|
||||
responses[0].length = strlen(ssh->passwd);
|
||||
}
|
||||
(void)prompts;
|
||||
(void)abstract;
|
||||
} /* kbd_callback */
|
||||
|
||||
static CURLcode libssh2_error_to_CURLE(struct connectdata *conn)
|
||||
{
|
||||
int errorcode;
|
||||
struct SSHPROTO *scp = conn->data->reqdata.proto.ssh;
|
||||
|
||||
/* Get the libssh2 error code and string */
|
||||
errorcode = libssh2_session_last_error(scp->ssh_session, &scp->errorstr,
|
||||
NULL, 0);
|
||||
if (errorcode == LIBSSH2_FX_OK)
|
||||
return CURLE_OK;
|
||||
|
||||
infof(conn->data, "libssh2 error %d, '%s'\n", errorcode, scp->errorstr);
|
||||
|
||||
/* TODO: map some of the libssh2 errors to the more appropriate CURLcode
|
||||
error code, and possibly add a few new SSH-related one. We must however
|
||||
not return or even depend on libssh2 errors in the public libcurl API */
|
||||
|
||||
return CURLE_SSH;
|
||||
}
|
||||
|
||||
static LIBSSH2_ALLOC_FUNC(libssh2_malloc)
|
||||
{
|
||||
return malloc(count);
|
||||
(void)abstract;
|
||||
}
|
||||
|
||||
static LIBSSH2_REALLOC_FUNC(libssh2_realloc)
|
||||
{
|
||||
return realloc(ptr, count);
|
||||
(void)abstract;
|
||||
}
|
||||
|
||||
static LIBSSH2_FREE_FUNC(libssh2_free)
|
||||
{
|
||||
free(ptr);
|
||||
(void)abstract;
|
||||
}
|
||||
|
||||
static CURLcode ssh_init(struct connectdata *conn)
|
||||
{
|
||||
struct SessionHandle *data = conn->data;
|
||||
struct SSHPROTO *ssh;
|
||||
if (data->reqdata.proto.ssh)
|
||||
return CURLE_OK;
|
||||
|
||||
ssh = (struct SSHPROTO *)calloc(sizeof(struct SSHPROTO), 1);
|
||||
if (!ssh)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
data->reqdata.proto.ssh = ssh;
|
||||
|
||||
/* get some initial data into the ssh struct */
|
||||
ssh->bytecountp = &data->reqdata.keep.bytecount;
|
||||
|
||||
/* no need to duplicate them, this connectdata struct won't change */
|
||||
ssh->user = conn->user;
|
||||
ssh->passwd = conn->passwd;
|
||||
|
||||
ssh->errorstr = NULL;
|
||||
|
||||
ssh->ssh_session = NULL;
|
||||
ssh->ssh_channel = NULL;
|
||||
ssh->sftp_session = NULL;
|
||||
ssh->sftp_handle = NULL;
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Curl_ssh_connect() gets called from Curl_protocol_connect() to allow us to
|
||||
* do protocol-specific actions at connect-time.
|
||||
*/
|
||||
CURLcode Curl_ssh_connect(struct connectdata *conn, bool *done)
|
||||
{
|
||||
int i;
|
||||
struct SSHPROTO *ssh;
|
||||
const char *fingerprint;
|
||||
const char *authlist;
|
||||
char *home;
|
||||
char rsa_pub[PATH_MAX];
|
||||
char rsa[PATH_MAX];
|
||||
char tempHome[PATH_MAX];
|
||||
curl_socket_t sock;
|
||||
char *real_path;
|
||||
char *working_path;
|
||||
int working_path_len;
|
||||
bool authed = FALSE;
|
||||
CURLcode result;
|
||||
struct SessionHandle *data = conn->data;
|
||||
|
||||
rsa_pub[0] = rsa[0] = '\0';
|
||||
|
||||
result = ssh_init(conn);
|
||||
if (result)
|
||||
return result;
|
||||
|
||||
ssh = data->reqdata.proto.ssh;
|
||||
|
||||
working_path = curl_easy_unescape(data, data->reqdata.path, 0,
|
||||
&working_path_len);
|
||||
if (!working_path)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
#ifdef CURL_LIBSSH2_DEBUG
|
||||
if (ssh->user) {
|
||||
infof(data, "User: %s\n", ssh->user);
|
||||
}
|
||||
if (ssh->passwd) {
|
||||
infof(data, "Password: %s\n", ssh->passwd);
|
||||
}
|
||||
#endif /* CURL_LIBSSH2_DEBUG */
|
||||
sock = conn->sock[FIRSTSOCKET];
|
||||
ssh->ssh_session = libssh2_session_init_ex(libssh2_malloc, libssh2_free,
|
||||
libssh2_realloc, ssh);
|
||||
if (ssh->ssh_session == NULL) {
|
||||
failf(data, "Failure initialising ssh session\n");
|
||||
Curl_safefree(ssh->path);
|
||||
return CURLE_FAILED_INIT;
|
||||
}
|
||||
#ifdef CURL_LIBSSH2_DEBUG
|
||||
infof(data, "SSH socket: %d\n", sock);
|
||||
#endif /* CURL_LIBSSH2_DEBUG */
|
||||
|
||||
if (libssh2_session_startup(ssh->ssh_session, sock)) {
|
||||
failf(data, "Failure establishing ssh session\n");
|
||||
libssh2_session_free(ssh->ssh_session);
|
||||
ssh->ssh_session = NULL;
|
||||
Curl_safefree(ssh->path);
|
||||
return CURLE_FAILED_INIT;
|
||||
}
|
||||
|
||||
/*
|
||||
* Before we authenticate we should check the hostkey's fingerprint against
|
||||
* our known hosts. How that is handled (reading from file, whatever) is
|
||||
* up to us. As for know not much is implemented, besides showing how to
|
||||
* get the fingerprint.
|
||||
*/
|
||||
fingerprint = libssh2_hostkey_hash(ssh->ssh_session,
|
||||
LIBSSH2_HOSTKEY_HASH_MD5);
|
||||
|
||||
#ifdef CURL_LIBSSH2_DEBUG
|
||||
/* The fingerprint points to static storage (!), don't free() it. */
|
||||
infof(data, "Fingerprint: ");
|
||||
for (i = 0; i < 16; i++) {
|
||||
infof(data, "%02X ", (unsigned char) fingerprint[i]);
|
||||
}
|
||||
infof(data, "\n");
|
||||
#endif /* CURL_LIBSSH2_DEBUG */
|
||||
|
||||
/* TBD - methods to check the host keys need to be done */
|
||||
|
||||
/*
|
||||
* Figure out authentication methods
|
||||
* NB: As soon as we have provided a username to an openssh server we must
|
||||
* never change it later. Thus, always specify the correct username here,
|
||||
* even though the libssh2 docs kind of indicate that it should be possible
|
||||
* to get a 'generic' list (not user-specific) of authentication methods,
|
||||
* presumably with a blank username. That won't work in my experience.
|
||||
* So always specify it here.
|
||||
*/
|
||||
authlist = libssh2_userauth_list(ssh->ssh_session, ssh->user,
|
||||
strlen(ssh->user));
|
||||
|
||||
/*
|
||||
* Check the supported auth types in the order I feel is most secure with the
|
||||
* requested type of authentication
|
||||
*/
|
||||
if ((data->set.ssh_auth_types & CURLSSH_AUTH_PUBLICKEY) &&
|
||||
(strstr(authlist, "publickey") != NULL)) {
|
||||
/* To ponder about: should really the lib be messing about with the HOME
|
||||
environment variable etc? */
|
||||
home = curl_getenv("HOME");
|
||||
|
||||
if (data->set.ssh_public_key)
|
||||
snprintf(rsa_pub, sizeof(rsa_pub), "%s", data->set.ssh_public_key);
|
||||
else if (home)
|
||||
snprintf(rsa_pub, sizeof(rsa_pub), "%s/.ssh/id_dsa.pub", home);
|
||||
|
||||
if (data->set.ssh_private_key)
|
||||
snprintf(rsa, sizeof(rsa), "%s", data->set.ssh_private_key);
|
||||
else if (home)
|
||||
snprintf(rsa, sizeof(rsa), "%s/.ssh/id_dsa", home);
|
||||
|
||||
curl_free(home);
|
||||
|
||||
if (rsa_pub[0]) {
|
||||
/* The function below checks if the files exists, no need to stat() here.
|
||||
*/
|
||||
if (libssh2_userauth_publickey_fromfile(ssh->ssh_session, ssh->user,
|
||||
rsa_pub, rsa, "") == 0) {
|
||||
authed = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!authed &&
|
||||
(data->set.ssh_auth_types & CURLSSH_AUTH_PASSWORD) &&
|
||||
(strstr(authlist, "password") != NULL)) {
|
||||
if (!libssh2_userauth_password(ssh->ssh_session, ssh->user, ssh->passwd))
|
||||
authed = TRUE;
|
||||
}
|
||||
if (!authed && (data->set.ssh_auth_types & CURLSSH_AUTH_HOST) &&
|
||||
(strstr(authlist, "hostbased") != NULL)) {
|
||||
}
|
||||
if (!authed && (data->set.ssh_auth_types & CURLSSH_AUTH_KEYBOARD)
|
||||
&& (strstr(authlist, "keyboard-interactive") != NULL)) {
|
||||
/* Authentication failed. Continue with keyboard-interactive now. */
|
||||
if (libssh2_userauth_keyboard_interactive_ex(ssh->ssh_session, ssh->user,
|
||||
strlen(ssh->user),
|
||||
&kbd_callback) == 0) {
|
||||
authed = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (!authed) {
|
||||
failf(data, "Authentication failure\n");
|
||||
libssh2_session_free(ssh->ssh_session);
|
||||
ssh->ssh_session = NULL;
|
||||
Curl_safefree(ssh->path);
|
||||
return CURLE_FAILED_INIT;
|
||||
}
|
||||
|
||||
/*
|
||||
* At this point we have an authenticated ssh session.
|
||||
*/
|
||||
conn->sockfd = sock;
|
||||
conn->writesockfd = CURL_SOCKET_BAD;
|
||||
|
||||
if (conn->protocol == PROT_SFTP) {
|
||||
/*
|
||||
* Start the libssh2 sftp session
|
||||
*/
|
||||
ssh->sftp_session = libssh2_sftp_init(ssh->ssh_session);
|
||||
if (ssh->sftp_session == NULL) {
|
||||
failf(data, "Failure initialising sftp session\n");
|
||||
libssh2_sftp_shutdown(ssh->sftp_session);
|
||||
ssh->sftp_session = NULL;
|
||||
libssh2_session_free(ssh->ssh_session);
|
||||
ssh->ssh_session = NULL;
|
||||
return CURLE_FAILED_INIT;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the "home" directory
|
||||
*/
|
||||
i = libssh2_sftp_realpath(ssh->sftp_session, ".", tempHome, PATH_MAX-1);
|
||||
if (i > 0) {
|
||||
/* It seems that this string is not always NULL terminated */
|
||||
tempHome[i] = '\0';
|
||||
ssh->homedir = (char *)strdup(tempHome);
|
||||
if (!ssh->homedir) {
|
||||
libssh2_sftp_shutdown(ssh->sftp_session);
|
||||
ssh->sftp_session = NULL;
|
||||
libssh2_session_free(ssh->ssh_session);
|
||||
ssh->ssh_session = NULL;
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Return the error type */
|
||||
i = libssh2_sftp_last_error(ssh->sftp_session);
|
||||
DEBUGF(infof(data, "error = %d\n", i));
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for /~/ , indicating realative to the users home directory */
|
||||
if (conn->protocol == PROT_SCP) {
|
||||
real_path = (char *)malloc(working_path_len+1);
|
||||
if (real_path == NULL) {
|
||||
Curl_safefree(working_path);
|
||||
libssh2_session_free(ssh->ssh_session);
|
||||
ssh->ssh_session = NULL;
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
if (working_path[1] == '~')
|
||||
/* It is referenced to the home directory, so strip the leading '/' */
|
||||
memcpy(real_path, working_path+1, 1 + working_path_len-1);
|
||||
else
|
||||
memcpy(real_path, working_path, 1 + working_path_len);
|
||||
}
|
||||
else if (conn->protocol == PROT_SFTP) {
|
||||
if (working_path[1] == '~') {
|
||||
real_path = (char *)malloc(strlen(ssh->homedir) +
|
||||
working_path_len + 1);
|
||||
if (real_path == NULL) {
|
||||
libssh2_sftp_shutdown(ssh->sftp_session);
|
||||
ssh->sftp_session = NULL;
|
||||
libssh2_session_free(ssh->ssh_session);
|
||||
ssh->ssh_session = NULL;
|
||||
Curl_safefree(working_path);
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
/* It is referenced to the home directory, so strip the leading '/' */
|
||||
memcpy(real_path, ssh->homedir, strlen(ssh->homedir));
|
||||
real_path[strlen(ssh->homedir)] = '/';
|
||||
real_path[strlen(ssh->homedir)+1] = '\0';
|
||||
if (working_path_len > 3) {
|
||||
memcpy(real_path+strlen(ssh->homedir)+1, working_path + 3,
|
||||
1 + working_path_len -3);
|
||||
}
|
||||
}
|
||||
else {
|
||||
real_path = (char *)malloc(working_path_len+1);
|
||||
if (real_path == NULL) {
|
||||
libssh2_session_free(ssh->ssh_session);
|
||||
ssh->ssh_session = NULL;
|
||||
Curl_safefree(working_path);
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
memcpy(real_path, working_path, 1+working_path_len);
|
||||
}
|
||||
}
|
||||
else
|
||||
return CURLE_FAILED_INIT;
|
||||
|
||||
Curl_safefree(working_path);
|
||||
ssh->path = real_path;
|
||||
|
||||
*done = TRUE;
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
CURLcode Curl_scp_do(struct connectdata *conn, bool *done)
|
||||
{
|
||||
struct stat sb;
|
||||
struct SSHPROTO *scp = conn->data->reqdata.proto.ssh;
|
||||
CURLcode res = CURLE_OK;
|
||||
|
||||
*done = TRUE; /* unconditionally */
|
||||
|
||||
if (conn->data->set.upload) {
|
||||
/*
|
||||
* NOTE!!! libssh2 requires that the destination path is a full path
|
||||
* that includes the destination file and name OR ends in a "/" .
|
||||
* If this is not done the destination file will be named the
|
||||
* same name as the last directory in the path.
|
||||
*/
|
||||
scp->ssh_channel = libssh2_scp_send_ex(scp->ssh_session, scp->path,
|
||||
LIBSSH2_SFTP_S_IRUSR|
|
||||
LIBSSH2_SFTP_S_IWUSR|
|
||||
LIBSSH2_SFTP_S_IRGRP|
|
||||
LIBSSH2_SFTP_S_IROTH,
|
||||
conn->data->set.infilesize, 0, 0);
|
||||
if (!scp->ssh_channel)
|
||||
return CURLE_FAILED_INIT;
|
||||
|
||||
/* upload data */
|
||||
res = Curl_setup_transfer(conn, -1, -1, FALSE, NULL, FIRSTSOCKET, NULL);
|
||||
}
|
||||
else {
|
||||
/*
|
||||
* We must check the remote file, if it is a directory no vaules will
|
||||
* be set in sb
|
||||
*/
|
||||
curl_off_t bytecount;
|
||||
memset(&sb, 0, sizeof(struct stat));
|
||||
scp->ssh_channel = libssh2_scp_recv(scp->ssh_session, scp->path, &sb);
|
||||
if (!scp->ssh_channel) {
|
||||
if ((sb.st_mode == 0) && (sb.st_atime == 0) && (sb.st_mtime == 0) &&
|
||||
(sb.st_size == 0)) {
|
||||
/* Since sb is still empty, it is likely the file was not found */
|
||||
return CURLE_REMOTE_FILE_NOT_FOUND;
|
||||
}
|
||||
return libssh2_error_to_CURLE(conn);
|
||||
}
|
||||
/* download data */
|
||||
bytecount = (curl_off_t) sb.st_size;
|
||||
conn->data->reqdata.maxdownload = (curl_off_t) sb.st_size;
|
||||
res = Curl_setup_transfer(conn, FIRSTSOCKET,
|
||||
bytecount, FALSE, NULL, -1, NULL);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
CURLcode Curl_scp_done(struct connectdata *conn, CURLcode status,
|
||||
bool premature)
|
||||
{
|
||||
struct SSHPROTO *scp = conn->data->reqdata.proto.ssh;
|
||||
(void)premature; /* not used */
|
||||
|
||||
Curl_safefree(scp->path);
|
||||
scp->path = NULL;
|
||||
|
||||
if (scp->ssh_channel) {
|
||||
if (libssh2_channel_close(scp->ssh_channel) < 0) {
|
||||
infof(conn->data, "Failed to stop libssh2 channel subsystem\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (scp->ssh_session) {
|
||||
libssh2_session_disconnect(scp->ssh_session, "Shutdown");
|
||||
libssh2_session_free(scp->ssh_session);
|
||||
scp->ssh_session = NULL;
|
||||
}
|
||||
|
||||
free(conn->data->reqdata.proto.ssh);
|
||||
conn->data->reqdata.proto.ssh = NULL;
|
||||
Curl_pgrsDone(conn);
|
||||
|
||||
(void)status; /* unused */
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
/* return number of received (decrypted) bytes */
|
||||
ssize_t Curl_scp_send(struct connectdata *conn, int sockindex,
|
||||
void *mem, size_t len)
|
||||
{
|
||||
ssize_t nwrite;
|
||||
|
||||
/* libssh2_channel_write() returns int
|
||||
*
|
||||
* NOTE: we should not store nor rely on connection-related data to be
|
||||
* in the SessionHandle struct
|
||||
*/
|
||||
nwrite = (ssize_t)
|
||||
libssh2_channel_write(conn->data->reqdata.proto.ssh->ssh_channel,
|
||||
mem, len);
|
||||
(void)sockindex;
|
||||
return nwrite;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the read would block (EWOULDBLOCK) we return -1. Otherwise we return
|
||||
* a regular CURLcode value.
|
||||
*/
|
||||
ssize_t Curl_scp_recv(struct connectdata *conn, int sockindex,
|
||||
char *mem, size_t len)
|
||||
{
|
||||
ssize_t nread;
|
||||
|
||||
/* libssh2_channel_read() returns int
|
||||
*
|
||||
* NOTE: we should not store nor rely on connection-related data to be
|
||||
* in the SessionHandle struct
|
||||
*/
|
||||
|
||||
nread = (ssize_t)
|
||||
libssh2_channel_read(conn->data->reqdata.proto.ssh->ssh_channel,
|
||||
mem, len);
|
||||
(void)sockindex;
|
||||
return nread;
|
||||
}
|
||||
|
||||
/*
|
||||
* =============== SFTP ===============
|
||||
*/
|
||||
|
||||
CURLcode Curl_sftp_do(struct connectdata *conn, bool *done)
|
||||
{
|
||||
LIBSSH2_SFTP_ATTRIBUTES attrs;
|
||||
struct SSHPROTO *sftp = conn->data->reqdata.proto.ssh;
|
||||
CURLcode res = CURLE_OK;
|
||||
struct SessionHandle *data = conn->data;
|
||||
curl_off_t bytecount = 0;
|
||||
char *buf = data->state.buffer;
|
||||
|
||||
*done = TRUE; /* unconditionally */
|
||||
|
||||
if (data->set.upload) {
|
||||
/*
|
||||
* NOTE!!! libssh2 requires that the destination path is a full path
|
||||
* that includes the destination file and name OR ends in a "/" .
|
||||
* If this is not done the destination file will be named the
|
||||
* same name as the last directory in the path.
|
||||
*/
|
||||
sftp->sftp_handle =
|
||||
libssh2_sftp_open(sftp->sftp_session, sftp->path,
|
||||
LIBSSH2_FXF_WRITE|LIBSSH2_FXF_CREAT,
|
||||
LIBSSH2_SFTP_S_IRUSR|LIBSSH2_SFTP_S_IWUSR|
|
||||
LIBSSH2_SFTP_S_IRGRP|LIBSSH2_SFTP_S_IROTH);
|
||||
if (!sftp->sftp_handle)
|
||||
return CURLE_FAILED_INIT;
|
||||
|
||||
/* upload data */
|
||||
res = Curl_setup_transfer(conn, -1, -1, FALSE, NULL, FIRSTSOCKET, NULL);
|
||||
}
|
||||
else {
|
||||
if (sftp->path[strlen(sftp->path)-1] == '/') {
|
||||
/*
|
||||
* This is a directory that we are trying to get, so produce a
|
||||
* directory listing
|
||||
*
|
||||
* **BLOCKING behaviour** This should be made into a state machine and
|
||||
* get a separate function called from Curl_sftp_recv() when there is
|
||||
* data to read from the network, instead of "hanging" here.
|
||||
*/
|
||||
char filename[PATH_MAX+1];
|
||||
int len, totalLen, currLen;
|
||||
char *line;
|
||||
|
||||
sftp->sftp_handle =
|
||||
libssh2_sftp_opendir(sftp->sftp_session, sftp->path);
|
||||
if (!sftp->sftp_handle)
|
||||
return CURLE_SSH;
|
||||
|
||||
while ((len = libssh2_sftp_readdir(sftp->sftp_handle, filename,
|
||||
PATH_MAX, &attrs)) > 0) {
|
||||
filename[len] = '\0';
|
||||
|
||||
if (data->set.ftp_list_only) {
|
||||
if ((attrs.flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) &&
|
||||
((attrs.permissions & LIBSSH2_SFTP_S_IFMT) ==
|
||||
LIBSSH2_SFTP_S_IFDIR)) {
|
||||
infof(data, "%s\n", filename);
|
||||
}
|
||||
}
|
||||
else {
|
||||
totalLen = 80 + len;
|
||||
line = (char *)malloc(totalLen);
|
||||
if (!line)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
if (!(attrs.flags & LIBSSH2_SFTP_ATTR_UIDGID))
|
||||
attrs.uid = attrs.gid =0;
|
||||
|
||||
currLen = snprintf(line, totalLen, "---------- 1 %5d %5d",
|
||||
attrs.uid, attrs.gid);
|
||||
|
||||
if (attrs.flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) {
|
||||
if ((attrs.permissions & LIBSSH2_SFTP_S_IFMT) ==
|
||||
LIBSSH2_SFTP_S_IFDIR) {
|
||||
line[0] = 'd';
|
||||
}
|
||||
else if ((attrs.permissions & LIBSSH2_SFTP_S_IFMT) ==
|
||||
LIBSSH2_SFTP_S_IFLNK) {
|
||||
line[0] = 'l';
|
||||
}
|
||||
else if ((attrs.permissions & LIBSSH2_SFTP_S_IFMT) ==
|
||||
LIBSSH2_SFTP_S_IFSOCK) {
|
||||
line[0] = 's';
|
||||
}
|
||||
else if ((attrs.permissions & LIBSSH2_SFTP_S_IFMT) ==
|
||||
LIBSSH2_SFTP_S_IFCHR) {
|
||||
line[0] = 'c';
|
||||
}
|
||||
else if ((attrs.permissions & LIBSSH2_SFTP_S_IFMT) ==
|
||||
LIBSSH2_SFTP_S_IFBLK) {
|
||||
line[0] = 'b';
|
||||
}
|
||||
if (attrs.permissions & LIBSSH2_SFTP_S_IRUSR) {
|
||||
line[1] = 'r';
|
||||
}
|
||||
if (attrs.permissions & LIBSSH2_SFTP_S_IWUSR) {
|
||||
line[2] = 'w';
|
||||
}
|
||||
if (attrs.permissions & LIBSSH2_SFTP_S_IXUSR) {
|
||||
line[3] = 'x';
|
||||
}
|
||||
if (attrs.permissions & LIBSSH2_SFTP_S_IRGRP) {
|
||||
line[4] = 'r';
|
||||
}
|
||||
if (attrs.permissions & LIBSSH2_SFTP_S_IWGRP) {
|
||||
line[5] = 'w';
|
||||
}
|
||||
if (attrs.permissions & LIBSSH2_SFTP_S_IXGRP) {
|
||||
line[6] = 'x';
|
||||
}
|
||||
if (attrs.permissions & LIBSSH2_SFTP_S_IROTH) {
|
||||
line[7] = 'r';
|
||||
}
|
||||
if (attrs.permissions & LIBSSH2_SFTP_S_IWOTH) {
|
||||
line[8] = 'w';
|
||||
}
|
||||
if (attrs.permissions & LIBSSH2_SFTP_S_IXOTH) {
|
||||
line[9] = 'x';
|
||||
}
|
||||
}
|
||||
if (attrs.flags & LIBSSH2_SFTP_ATTR_SIZE) {
|
||||
currLen += snprintf(line+currLen, totalLen-currLen, "%11lld",
|
||||
attrs.filesize);
|
||||
}
|
||||
if (attrs.flags & LIBSSH2_SFTP_ATTR_ACMODTIME) {
|
||||
const char *months[12] = {
|
||||
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
|
||||
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
|
||||
struct tm *nowParts;
|
||||
time_t now, remoteTime;
|
||||
|
||||
now = time(NULL);
|
||||
remoteTime = (time_t)attrs.mtime;
|
||||
nowParts = localtime(&remoteTime);
|
||||
|
||||
if ((time_t)attrs.mtime > (now - (3600 * 24 * 180))) {
|
||||
currLen += snprintf(line+currLen, totalLen-currLen,
|
||||
" %s %2d %2d:%02d", months[nowParts->tm_mon],
|
||||
nowParts->tm_mday, nowParts->tm_hour,
|
||||
nowParts->tm_min);
|
||||
}
|
||||
else {
|
||||
currLen += snprintf(line+currLen, totalLen-currLen,
|
||||
" %s %2d %5d", months[nowParts->tm_mon],
|
||||
nowParts->tm_mday, 1900+nowParts->tm_year);
|
||||
}
|
||||
}
|
||||
currLen += snprintf(line+currLen, totalLen-currLen, " %s", filename);
|
||||
if ((attrs.flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) &&
|
||||
((attrs.permissions & LIBSSH2_SFTP_S_IFMT) ==
|
||||
LIBSSH2_SFTP_S_IFLNK)) {
|
||||
char linkPath[PATH_MAX + 1];
|
||||
|
||||
snprintf(linkPath, PATH_MAX, "%s%s", sftp->path, filename);
|
||||
len = libssh2_sftp_readlink(sftp->sftp_session, linkPath, filename,
|
||||
PATH_MAX);
|
||||
line = realloc(line, totalLen + 4 + len);
|
||||
if (!line)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
currLen += snprintf(line+currLen, totalLen-currLen, " -> %s",
|
||||
filename);
|
||||
}
|
||||
|
||||
currLen += snprintf(line+currLen, totalLen-currLen, "\n");
|
||||
res = Curl_client_write(conn, CLIENTWRITE_BODY, line, 0);
|
||||
free(line);
|
||||
}
|
||||
}
|
||||
libssh2_sftp_closedir(sftp->sftp_handle);
|
||||
sftp->sftp_handle = NULL;
|
||||
|
||||
/* no data to transfer */
|
||||
res = Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
|
||||
}
|
||||
else {
|
||||
/*
|
||||
* Work on getting the specified file
|
||||
*/
|
||||
sftp->sftp_handle =
|
||||
libssh2_sftp_open(sftp->sftp_session, sftp->path, LIBSSH2_FXF_READ,
|
||||
LIBSSH2_SFTP_S_IRUSR|LIBSSH2_SFTP_S_IWUSR|
|
||||
LIBSSH2_SFTP_S_IRGRP|LIBSSH2_SFTP_S_IROTH);
|
||||
if (!sftp->sftp_handle)
|
||||
return CURLE_SSH;
|
||||
|
||||
if (libssh2_sftp_stat(sftp->sftp_session, sftp->path, &attrs)) {
|
||||
/*
|
||||
* libssh2_sftp_open() didn't return an error, so maybe the server
|
||||
* just doesn't support stat()
|
||||
*/
|
||||
data->reqdata.size = -1;
|
||||
data->reqdata.maxdownload = -1;
|
||||
}
|
||||
else {
|
||||
data->reqdata.size = attrs.filesize;
|
||||
data->reqdata.maxdownload = attrs.filesize;
|
||||
Curl_pgrsSetDownloadSize(data, attrs.filesize);
|
||||
}
|
||||
|
||||
Curl_pgrsTime(data, TIMER_STARTTRANSFER);
|
||||
|
||||
/* Now download data. The libssh2 0.14 doesn't offer any way to do this
|
||||
without using this BLOCKING approach, so here's room for improvement
|
||||
once libssh2 can return EWOULDBLOCK to us. */
|
||||
#if 0
|
||||
/* code left here just because this is what this function will use the
|
||||
day libssh2 is improved */
|
||||
res = Curl_setup_transfer(conn, FIRSTSOCKET,
|
||||
bytecount, FALSE, NULL, -1, NULL);
|
||||
#endif
|
||||
while (res == CURLE_OK) {
|
||||
size_t nread;
|
||||
/* NOTE: most *read() functions return ssize_t but this returns size_t
|
||||
which normally is unsigned! */
|
||||
nread = libssh2_sftp_read(data->reqdata.proto.ssh->sftp_handle,
|
||||
buf, BUFSIZE-1);
|
||||
|
||||
if (nread > 0)
|
||||
buf[nread] = 0;
|
||||
|
||||
/* this check can be changed to a <= 0 when nread is changed to a
|
||||
signed variable type */
|
||||
if ((nread == 0) || (nread == (size_t)~0))
|
||||
break;
|
||||
|
||||
bytecount += nread;
|
||||
|
||||
res = Curl_client_write(conn, CLIENTWRITE_BODY, buf, nread);
|
||||
if(res)
|
||||
return res;
|
||||
|
||||
Curl_pgrsSetDownloadCounter(data, bytecount);
|
||||
|
||||
if(Curl_pgrsUpdate(conn))
|
||||
res = CURLE_ABORTED_BY_CALLBACK;
|
||||
else {
|
||||
struct timeval now = Curl_tvnow();
|
||||
res = Curl_speedcheck(data, now);
|
||||
}
|
||||
}
|
||||
if(Curl_pgrsUpdate(conn))
|
||||
res = CURLE_ABORTED_BY_CALLBACK;
|
||||
|
||||
/* no (more) data to transfer */
|
||||
res = Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
CURLcode Curl_sftp_done(struct connectdata *conn, CURLcode status,
|
||||
bool premature)
|
||||
{
|
||||
struct SSHPROTO *sftp = conn->data->reqdata.proto.ssh;
|
||||
(void)premature; /* not used */
|
||||
|
||||
Curl_safefree(sftp->path);
|
||||
sftp->path = NULL;
|
||||
|
||||
Curl_safefree(sftp->homedir);
|
||||
sftp->homedir = NULL;
|
||||
|
||||
if (sftp->sftp_handle) {
|
||||
if (libssh2_sftp_close(sftp->sftp_handle) < 0) {
|
||||
infof(conn->data, "Failed to close libssh2 file\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (sftp->sftp_session) {
|
||||
if (libssh2_sftp_shutdown(sftp->sftp_session) < 0) {
|
||||
infof(conn->data, "Failed to stop libssh2 sftp subsystem\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (sftp->ssh_channel) {
|
||||
if (libssh2_channel_close(sftp->ssh_channel) < 0) {
|
||||
infof(conn->data, "Failed to stop libssh2 channel subsystem\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (sftp->ssh_session) {
|
||||
libssh2_session_disconnect(sftp->ssh_session, "Shutdown");
|
||||
libssh2_session_free(sftp->ssh_session);
|
||||
sftp->ssh_session = NULL;
|
||||
}
|
||||
|
||||
free(conn->data->reqdata.proto.ssh);
|
||||
conn->data->reqdata.proto.ssh = NULL;
|
||||
Curl_pgrsDone(conn);
|
||||
|
||||
(void)status; /* unused */
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
/* return number of received (decrypted) bytes */
|
||||
ssize_t Curl_sftp_send(struct connectdata *conn, int sockindex,
|
||||
void *mem, size_t len)
|
||||
{
|
||||
ssize_t nwrite;
|
||||
|
||||
/* libssh2_sftp_write() returns size_t !*/
|
||||
|
||||
nwrite = (ssize_t)
|
||||
libssh2_sftp_write(conn->data->reqdata.proto.ssh->sftp_handle, mem, len);
|
||||
(void)sockindex;
|
||||
return nwrite;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the read would block (EWOULDBLOCK) we return -1. Otherwise we return
|
||||
* a regular CURLcode value.
|
||||
*/
|
||||
ssize_t Curl_sftp_recv(struct connectdata *conn, int sockindex,
|
||||
char *mem, size_t len)
|
||||
{
|
||||
ssize_t nread;
|
||||
|
||||
/* libssh2_sftp_read() returns size_t !*/
|
||||
|
||||
nread = (ssize_t)
|
||||
libssh2_sftp_read(conn->data->reqdata.proto.ssh->sftp_handle, mem, len);
|
||||
(void)sockindex;
|
||||
return nread;
|
||||
}
|
||||
|
||||
#endif /* USE_LIBSSH2 */
|
49
lib/ssh.h
Normal file
49
lib/ssh.h
Normal file
@@ -0,0 +1,49 @@
|
||||
#ifndef __SSH_H
|
||||
#define __SSH_H
|
||||
|
||||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
* are also available at http://curl.haxx.se/docs/copyright.html.
|
||||
*
|
||||
* 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 COPYING file.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
* $Id$
|
||||
***************************************************************************/
|
||||
|
||||
#ifdef USE_LIBSSH2
|
||||
|
||||
CURLcode Curl_ssh_connect(struct connectdata *conn, bool *done);
|
||||
|
||||
CURLcode Curl_scp_do(struct connectdata *conn, bool *done);
|
||||
CURLcode Curl_scp_done(struct connectdata *conn, CURLcode, bool premature);
|
||||
|
||||
ssize_t Curl_scp_send(struct connectdata *conn, int sockindex,
|
||||
void *mem, size_t len);
|
||||
ssize_t Curl_scp_recv(struct connectdata *conn, int sockindex,
|
||||
char *mem, size_t len);
|
||||
|
||||
CURLcode Curl_sftp_do(struct connectdata *conn, bool *done);
|
||||
CURLcode Curl_sftp_done(struct connectdata *conn, CURLcode, bool premature);
|
||||
|
||||
ssize_t Curl_sftp_send(struct connectdata *conn, int sockindex,
|
||||
void *mem, size_t len);
|
||||
ssize_t Curl_sftp_recv(struct connectdata *conn, int sockindex,
|
||||
char *mem, size_t len);
|
||||
|
||||
#endif /* USE_LIBSSH2 */
|
||||
|
||||
#endif /* __SSH_H */
|
55
lib/sslgen.c
55
lib/sslgen.c
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -23,7 +23,7 @@
|
||||
|
||||
/* This file is for "generic" SSL functions that all libcurl internals should
|
||||
use. It is responsible for calling the proper 'ossl' function in ssluse.c
|
||||
(OpenSSL based) or the 'gtsl' function in gtsl.c (GnuTLS based).
|
||||
(OpenSSL based) or the 'gtls' function in gtls.c (GnuTLS based).
|
||||
|
||||
SSL-functions in libcurl should call functions in this source file, and not
|
||||
to any specific SSL-layer.
|
||||
@@ -397,6 +397,25 @@ void Curl_ssl_close(struct connectdata *conn)
|
||||
}
|
||||
}
|
||||
|
||||
CURLcode Curl_ssl_shutdown(struct connectdata *conn, int sockindex)
|
||||
{
|
||||
if(conn->ssl[sockindex].use) {
|
||||
#ifdef USE_SSLEAY
|
||||
if(Curl_ossl_shutdown(conn, sockindex))
|
||||
return CURLE_SSL_SHUTDOWN_FAILED;
|
||||
#else
|
||||
#ifdef USE_GNUTLS
|
||||
if(Curl_gtls_shutdown(conn, sockindex))
|
||||
return CURLE_SSL_SHUTDOWN_FAILED;
|
||||
#else
|
||||
(void)conn;
|
||||
(void)sockindex;
|
||||
#endif /* USE_GNUTLS */
|
||||
#endif /* USE_SSLEAY */
|
||||
}
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
/* Selects an (Open)SSL crypto engine
|
||||
*/
|
||||
CURLcode Curl_ssl_set_engine(struct SessionHandle *data, const char *engine)
|
||||
@@ -455,10 +474,10 @@ struct curl_slist *Curl_ssl_engines_list(struct SessionHandle *data)
|
||||
}
|
||||
|
||||
/* return number of sent (non-SSL) bytes */
|
||||
int Curl_ssl_send(struct connectdata *conn,
|
||||
int sockindex,
|
||||
void *mem,
|
||||
size_t len)
|
||||
ssize_t Curl_ssl_send(struct connectdata *conn,
|
||||
int sockindex,
|
||||
void *mem,
|
||||
size_t len)
|
||||
{
|
||||
#ifdef USE_SSLEAY
|
||||
return Curl_ossl_send(conn, sockindex, mem, len);
|
||||
@@ -481,10 +500,10 @@ int Curl_ssl_send(struct connectdata *conn,
|
||||
* If the read would block (EWOULDBLOCK) we return -1. Otherwise we return
|
||||
* a regular CURLcode value.
|
||||
*/
|
||||
int Curl_ssl_recv(struct connectdata *conn, /* connection data */
|
||||
int sockindex, /* socketindex */
|
||||
char *mem, /* store read data here */
|
||||
size_t len) /* max amount to read */
|
||||
ssize_t Curl_ssl_recv(struct connectdata *conn, /* connection data */
|
||||
int sockindex, /* socketindex */
|
||||
char *mem, /* store read data here */
|
||||
size_t len) /* max amount to read */
|
||||
{
|
||||
#ifdef USE_SSL
|
||||
ssize_t nread;
|
||||
@@ -581,3 +600,19 @@ int Curl_ssl_check_cxn(struct connectdata *conn)
|
||||
return -1; /* connection status unknown */
|
||||
#endif /* USE_SSLEAY */
|
||||
}
|
||||
|
||||
bool Curl_ssl_data_pending(struct connectdata *conn,
|
||||
int connindex)
|
||||
{
|
||||
#ifdef USE_SSLEAY
|
||||
/* OpenSSL-specific */
|
||||
if(conn->ssl[connindex].handle)
|
||||
/* SSL is in use */
|
||||
return SSL_pending(conn->ssl[connindex].handle);
|
||||
#else
|
||||
(void)conn;
|
||||
(void)connindex;
|
||||
#endif
|
||||
return FALSE; /* nothing pending */
|
||||
|
||||
}
|
||||
|
27
lib/sslgen.h
27
lib/sslgen.h
@@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -32,7 +32,7 @@ void Curl_free_ssl_config(struct ssl_config_data* sslc);
|
||||
int Curl_ssl_init(void);
|
||||
void Curl_ssl_cleanup(void);
|
||||
CURLcode Curl_ssl_connect(struct connectdata *conn, int sockindex);
|
||||
CURLcode Curl_ssl_connect_nonblocking(struct connectdata *conn,
|
||||
CURLcode Curl_ssl_connect_nonblocking(struct connectdata *conn,
|
||||
int sockindex,
|
||||
bool *done);
|
||||
void Curl_ssl_close(struct connectdata *conn);
|
||||
@@ -42,14 +42,14 @@ void Curl_ssl_close_all(struct SessionHandle *data);
|
||||
CURLcode Curl_ssl_set_engine(struct SessionHandle *data, const char *engine);
|
||||
/* Sets engine as default for all SSL operations */
|
||||
CURLcode Curl_ssl_set_engine_default(struct SessionHandle *data);
|
||||
int Curl_ssl_send(struct connectdata *conn,
|
||||
int sockindex,
|
||||
void *mem,
|
||||
size_t len);
|
||||
int Curl_ssl_recv(struct connectdata *conn, /* connection data */
|
||||
int sockindex, /* socketindex */
|
||||
char *mem, /* store read data here */
|
||||
size_t len); /* max amount to read */
|
||||
ssize_t Curl_ssl_send(struct connectdata *conn,
|
||||
int sockindex,
|
||||
void *mem,
|
||||
size_t len);
|
||||
ssize_t Curl_ssl_recv(struct connectdata *conn, /* connection data */
|
||||
int sockindex, /* socketindex */
|
||||
char *mem, /* store read data here */
|
||||
size_t len); /* max amount to read */
|
||||
|
||||
/* init the SSL session ID cache */
|
||||
CURLcode Curl_ssl_initsessions(struct SessionHandle *, long);
|
||||
@@ -69,9 +69,16 @@ size_t Curl_ssl_version(char *buffer, size_t size);
|
||||
|
||||
int Curl_ssl_check_cxn(struct connectdata *conn);
|
||||
|
||||
CURLcode Curl_ssl_shutdown(struct connectdata *conn, int sockindex);
|
||||
|
||||
bool Curl_ssl_data_pending(struct connectdata *conn,
|
||||
int connindex);
|
||||
|
||||
#if !defined(USE_SSL) && !defined(SSLGEN_C)
|
||||
/* set up blank macros for none-SSL builds */
|
||||
#define Curl_ssl_close_all(x)
|
||||
#endif
|
||||
|
||||
#define SSL_SHUTDOWN_TIMEOUT 10000 /* ms */
|
||||
|
||||
#endif
|
||||
|
117
lib/ssluse.c
117
lib/ssluse.c
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -634,8 +634,8 @@ CURLcode Curl_ossl_set_engine(struct SessionHandle *data, const char *engine)
|
||||
if (data->state.engine) {
|
||||
ENGINE_finish(data->state.engine);
|
||||
ENGINE_free(data->state.engine);
|
||||
data->state.engine = NULL;
|
||||
}
|
||||
data->state.engine = NULL;
|
||||
if (!ENGINE_init(e)) {
|
||||
char buf[256];
|
||||
|
||||
@@ -661,10 +661,10 @@ CURLcode Curl_ossl_set_engine_default(struct SessionHandle *data)
|
||||
#ifdef HAVE_OPENSSL_ENGINE_H
|
||||
if (data->state.engine) {
|
||||
if (ENGINE_set_default(data->state.engine, ENGINE_METHOD_ALL) > 0) {
|
||||
infof(data,"set default crypto engine %s\n", data->state.engine);
|
||||
infof(data,"set default crypto engine '%s'\n", ENGINE_get_id(data->state.engine));
|
||||
}
|
||||
else {
|
||||
failf(data, "set default crypto engine %s failed", data->state.engine);
|
||||
failf(data, "set default crypto engine '%s' failed", ENGINE_get_id(data->state.engine));
|
||||
return CURLE_SSL_ENGINE_SETFAILED;
|
||||
}
|
||||
}
|
||||
@@ -728,6 +728,101 @@ void Curl_ossl_close(struct connectdata *conn)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is called to shut down the SSL layer but keep the
|
||||
* socket open (CCC - Clear Command Channel)
|
||||
*/
|
||||
int Curl_ossl_shutdown(struct connectdata *conn, int sockindex)
|
||||
{
|
||||
int retval = 0;
|
||||
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
|
||||
struct SessionHandle *data = conn->data;
|
||||
char buf[120]; /* We will use this for the OpenSSL error buffer, so it has
|
||||
to be at least 120 bytes long. */
|
||||
unsigned long sslerror;
|
||||
ssize_t nread;
|
||||
int err;
|
||||
int done = 0;
|
||||
|
||||
/* This has only been tested on the proftpd server, and the mod_tls code
|
||||
sends a close notify alert without waiting for a close notify alert in
|
||||
response. Thus we wait for a close notify alert from the server, but
|
||||
we do not send one. Let's hope other servers do the same... */
|
||||
|
||||
if(connssl->handle) {
|
||||
while(!done) {
|
||||
int what = Curl_select(conn->sock[sockindex],
|
||||
CURL_SOCKET_BAD, SSL_SHUTDOWN_TIMEOUT);
|
||||
if(what > 0) {
|
||||
/* Something to read, let's do it and hope that it is the close
|
||||
notify alert from the server */
|
||||
nread = (ssize_t)SSL_read(conn->ssl[sockindex].handle, buf,
|
||||
sizeof(buf));
|
||||
err = SSL_get_error(conn->ssl[sockindex].handle, (int)nread);
|
||||
|
||||
switch(err) {
|
||||
case SSL_ERROR_NONE: /* this is not an error */
|
||||
case SSL_ERROR_ZERO_RETURN: /* no more data */
|
||||
/* This is the expected response. There was no data but only
|
||||
the close notify alert */
|
||||
done = 1;
|
||||
break;
|
||||
case SSL_ERROR_WANT_READ:
|
||||
/* there's data pending, re-invoke SSL_read() */
|
||||
infof(data, "SSL_ERROR_WANT_READ\n");
|
||||
break;
|
||||
case SSL_ERROR_WANT_WRITE:
|
||||
/* SSL wants a write. Really odd. Let's bail out. */
|
||||
infof(data, "SSL_ERROR_WANT_WRITE\n");
|
||||
done = 1;
|
||||
break;
|
||||
default:
|
||||
/* openssl/ssl.h says "look at error stack/return value/errno" */
|
||||
sslerror = ERR_get_error();
|
||||
failf(conn->data, "SSL read: %s, errno %d",
|
||||
ERR_error_string(sslerror, buf),
|
||||
Curl_sockerrno() );
|
||||
done = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if(0 == what) {
|
||||
/* timeout */
|
||||
failf(data, "SSL shutdown timeout");
|
||||
done = 1;
|
||||
break;
|
||||
}
|
||||
else {
|
||||
/* anything that gets here is fatally bad */
|
||||
failf(data, "select on SSL socket, errno: %d", Curl_sockerrno());
|
||||
retval = -1;
|
||||
done = 1;
|
||||
}
|
||||
} /* while()-loop for the select() */
|
||||
|
||||
if(data->set.verbose) {
|
||||
switch(SSL_get_shutdown(connssl->handle)) {
|
||||
case SSL_SENT_SHUTDOWN:
|
||||
infof(data, "SSL_get_shutdown() returned SSL_SENT_SHUTDOWN\n");
|
||||
break;
|
||||
case SSL_RECEIVED_SHUTDOWN:
|
||||
infof(data, "SSL_get_shutdown() returned SSL_RECEIVED_SHUTDOWN\n");
|
||||
break;
|
||||
case SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN:
|
||||
infof(data, "SSL_get_shutdown() returned SSL_SENT_SHUTDOWN|"
|
||||
"SSL_RECEIVED__SHUTDOWN\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
connssl->use = FALSE; /* get back to ordinary socket usage */
|
||||
|
||||
SSL_free (connssl->handle);
|
||||
connssl->handle = NULL;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
void Curl_ossl_session_free(void *ptr)
|
||||
{
|
||||
/* free the ID */
|
||||
@@ -1207,7 +1302,7 @@ Curl_ossl_connect_step1(struct connectdata *conn,
|
||||
}
|
||||
|
||||
#ifdef SSL_CTRL_SET_MSG_CALLBACK
|
||||
if (data->set.fdebug) {
|
||||
if (data->set.fdebug && data->set.verbose) {
|
||||
/* the SSL trace callback is only used for verbose logging so we only
|
||||
inform about failures of setting it */
|
||||
if (!SSL_CTX_callback_ctrl(connssl->ctx, SSL_CTRL_SET_MSG_CALLBACK,
|
||||
@@ -1629,7 +1724,7 @@ Curl_ossl_connect_common(struct connectdata *conn,
|
||||
while(1) {
|
||||
int what = Curl_select(readfd, writefd, nonblocking?0:(int)timeout_ms);
|
||||
if(what > 0)
|
||||
/* reabable or writable, go loop in the outer loop */
|
||||
/* readable or writable, go loop in the outer loop */
|
||||
break;
|
||||
else if(0 == what) {
|
||||
if (nonblocking) {
|
||||
@@ -1702,10 +1797,10 @@ Curl_ossl_connect(struct connectdata *conn,
|
||||
}
|
||||
|
||||
/* return number of sent (non-SSL) bytes */
|
||||
int Curl_ossl_send(struct connectdata *conn,
|
||||
int sockindex,
|
||||
void *mem,
|
||||
size_t len)
|
||||
ssize_t Curl_ossl_send(struct connectdata *conn,
|
||||
int sockindex,
|
||||
void *mem,
|
||||
size_t len)
|
||||
{
|
||||
/* SSL_write() is said to return 'int' while write() and send() returns
|
||||
'size_t' */
|
||||
@@ -1741,7 +1836,7 @@ int Curl_ossl_send(struct connectdata *conn,
|
||||
failf(conn->data, "SSL_write() return error %d\n", err);
|
||||
return -1;
|
||||
}
|
||||
return rc; /* number of bytes */
|
||||
return (ssize_t)rc; /* number of bytes */
|
||||
}
|
||||
|
||||
/*
|
||||
|
16
lib/ssluse.h
16
lib/ssluse.h
@@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -29,8 +29,8 @@
|
||||
|
||||
#include "urldata.h"
|
||||
CURLcode Curl_ossl_connect(struct connectdata *conn, int sockindex);
|
||||
CURLcode Curl_ossl_connect_nonblocking(struct connectdata *conn,
|
||||
int sockindex,
|
||||
CURLcode Curl_ossl_connect_nonblocking(struct connectdata *conn,
|
||||
int sockindex,
|
||||
bool *done);
|
||||
void Curl_ossl_close(struct connectdata *conn); /* close a SSL connection */
|
||||
/* tell OpenSSL to close down all open information regarding connections (and
|
||||
@@ -52,10 +52,10 @@ struct curl_slist *Curl_ossl_engines_list(struct SessionHandle *data);
|
||||
int Curl_ossl_init(void);
|
||||
void Curl_ossl_cleanup(void);
|
||||
|
||||
int Curl_ossl_send(struct connectdata *conn,
|
||||
int sockindex,
|
||||
void *mem,
|
||||
size_t len);
|
||||
ssize_t Curl_ossl_send(struct connectdata *conn,
|
||||
int sockindex,
|
||||
void *mem,
|
||||
size_t len);
|
||||
ssize_t Curl_ossl_recv(struct connectdata *conn, /* connection data */
|
||||
int num, /* socketindex */
|
||||
char *buf, /* store read data here */
|
||||
@@ -66,4 +66,6 @@ size_t Curl_ossl_version(char *buffer, size_t size);
|
||||
int Curl_ossl_check_cxn(struct connectdata *cxn);
|
||||
int Curl_ossl_seed(struct SessionHandle *data);
|
||||
|
||||
int Curl_ossl_shutdown(struct connectdata *conn, int sockindex);
|
||||
|
||||
#endif
|
||||
|
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 2004 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 2004 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -244,6 +244,9 @@ curl_easy_strerror(CURLcode error)
|
||||
case CURLE_FTP_SSL_FAILED:
|
||||
return "Requested FTP SSL level failed";
|
||||
|
||||
case CURLE_SSL_SHUTDOWN_FAILED:
|
||||
return "Failed to shut down the SSL connection";
|
||||
|
||||
case CURLE_SEND_FAIL_REWIND:
|
||||
return "Send failed since rewinding of the data stream failed";
|
||||
|
||||
@@ -277,6 +280,12 @@ curl_easy_strerror(CURLcode error)
|
||||
case CURLE_CONV_REQD:
|
||||
return "caller must register CURLOPT_CONV_ callback options";
|
||||
|
||||
case CURLE_REMOTE_FILE_NOT_FOUND:
|
||||
return "Remote file not found";
|
||||
|
||||
case CURLE_SSH:
|
||||
return "Error in the SSH layer";
|
||||
|
||||
/* error codes not used by current libcurl */
|
||||
case CURLE_URL_MALFORMAT_USER:
|
||||
case CURLE_FTP_USER_PASSWORD_INCORRECT:
|
||||
|
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -1073,10 +1073,11 @@ void telrcv(struct connectdata *conn,
|
||||
}
|
||||
}
|
||||
|
||||
CURLcode Curl_telnet_done(struct connectdata *conn, CURLcode status)
|
||||
CURLcode Curl_telnet_done(struct connectdata *conn, CURLcode status, bool premature)
|
||||
{
|
||||
struct TELNET *tn = (struct TELNET *)conn->data->reqdata.proto.telnet;
|
||||
(void)status; /* unused */
|
||||
(void)premature; /* not used */
|
||||
|
||||
curl_slist_free_all(tn->telnet_vars);
|
||||
|
||||
|
@@ -8,7 +8,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2005, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -25,6 +25,6 @@
|
||||
***************************************************************************/
|
||||
#ifndef CURL_DISABLE_TELNET
|
||||
CURLcode Curl_telnet(struct connectdata *conn, bool *done);
|
||||
CURLcode Curl_telnet_done(struct connectdata *conn, CURLcode);
|
||||
CURLcode Curl_telnet_done(struct connectdata *conn, CURLcode, bool premature);
|
||||
#endif
|
||||
#endif
|
||||
|
82
lib/tftp.c
82
lib/tftp.c
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -77,6 +77,7 @@
|
||||
#include "connect.h"
|
||||
#include "strerror.h"
|
||||
#include "sockaddr.h" /* required for Curl_sockaddr_storage */
|
||||
#include "url.h"
|
||||
|
||||
#define _MPRINTF_REPLACE /* use our functions only */
|
||||
#include <curl/mprintf.h>
|
||||
@@ -255,10 +256,7 @@ static CURLcode tftp_send_first(tftp_state_data_t *state, tftp_event_t event)
|
||||
{
|
||||
int sbytes;
|
||||
const char *mode = "octet";
|
||||
|
||||
/* As RFC3617 describes the separator slash is not actually part of the file
|
||||
name so we skip the always-present first letter of the path string. */
|
||||
char *filename = &state->conn->data->reqdata.path[1];
|
||||
char *filename;
|
||||
struct SessionHandle *data = state->conn->data;
|
||||
CURLcode res = CURLE_OK;
|
||||
|
||||
@@ -281,7 +279,6 @@ static CURLcode tftp_send_first(tftp_state_data_t *state, tftp_event_t event)
|
||||
if(data->set.upload) {
|
||||
/* If we are uploading, send an WRQ */
|
||||
setpacketevent(&state->spacket, TFTP_EVENT_WRQ);
|
||||
filename = curl_easy_unescape(data, filename, 0, NULL);
|
||||
state->conn->data->reqdata.upload_fromhere = (char *)&state->spacket.data[4];
|
||||
if(data->set.infilesize != -1)
|
||||
Curl_pgrsSetUploadSize(data, data->set.infilesize);
|
||||
@@ -290,6 +287,10 @@ static CURLcode tftp_send_first(tftp_state_data_t *state, tftp_event_t event)
|
||||
/* If we are downloading, send an RRQ */
|
||||
setpacketevent(&state->spacket, TFTP_EVENT_RRQ);
|
||||
}
|
||||
/* As RFC3617 describes the separator slash is not actually part of the
|
||||
file name so we skip the always-present first letter of the path string. */
|
||||
filename = curl_easy_unescape(data, &state->conn->data->reqdata.path[1], 0,
|
||||
NULL);
|
||||
snprintf((char *)&state->spacket.data[2],
|
||||
TFTP_BLOCKSIZE,
|
||||
"%s%c%s%c", filename, '\0', mode, '\0');
|
||||
@@ -301,6 +302,7 @@ static CURLcode tftp_send_first(tftp_state_data_t *state, tftp_event_t event)
|
||||
if(sbytes < 0) {
|
||||
failf(data, "%s\n", Curl_strerror(state->conn, Curl_sockerrno()));
|
||||
}
|
||||
Curl_safefree(filename);
|
||||
break;
|
||||
|
||||
case TFTP_EVENT_ACK: /* Connected for transmit */
|
||||
@@ -569,10 +571,13 @@ CURLcode Curl_tftp_connect(struct connectdata *conn, bool *done)
|
||||
tftp_state_data_t *state;
|
||||
int rc;
|
||||
|
||||
state = conn->data->reqdata.proto.tftp = calloc(sizeof(tftp_state_data_t), 1);
|
||||
state = conn->data->reqdata.proto.tftp = calloc(sizeof(tftp_state_data_t),
|
||||
1);
|
||||
if(!state)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
conn->bits.close = FALSE; /* keep it open if possible */
|
||||
|
||||
state->conn = conn;
|
||||
state->sockfd = state->conn->sock[FIRSTSOCKET];
|
||||
state->state = TFTP_STATE_START;
|
||||
@@ -582,24 +587,27 @@ CURLcode Curl_tftp_connect(struct connectdata *conn, bool *done)
|
||||
|
||||
tftp_set_timeouts(state);
|
||||
|
||||
/* Bind to any interface, random UDP port.
|
||||
*
|
||||
* We once used the size of the local_addr struct as the third argument for
|
||||
* bind() to better work with IPv6 or whatever size the struct could have,
|
||||
* but we learned that at least Tru64, AIX and IRIX *requires* the size of
|
||||
* that argument to match the exact size of a 'sockaddr_in' struct when
|
||||
* running IPv4-only.
|
||||
*
|
||||
* Therefore we use the size from the address we connected to, which we
|
||||
* assume uses the same IP version and thus hopefully this works for both
|
||||
* IPv4 and IPv6...
|
||||
*/
|
||||
rc = bind(state->sockfd, (struct sockaddr *)&state->local_addr,
|
||||
conn->ip_addr->ai_addrlen);
|
||||
if(rc) {
|
||||
failf(conn->data, "bind() failed; %s\n",
|
||||
Curl_strerror(conn, Curl_sockerrno()));
|
||||
return CURLE_COULDNT_CONNECT;
|
||||
if(!conn->bits.reuse) {
|
||||
/* If not reused, bind to any interface, random UDP port. If it is reused,
|
||||
* this has already been done!
|
||||
*
|
||||
* We once used the size of the local_addr struct as the third argument for
|
||||
* bind() to better work with IPv6 or whatever size the struct could have,
|
||||
* but we learned that at least Tru64, AIX and IRIX *requires* the size of
|
||||
* that argument to match the exact size of a 'sockaddr_in' struct when
|
||||
* running IPv4-only.
|
||||
*
|
||||
* Therefore we use the size from the address we connected to, which we
|
||||
* assume uses the same IP version and thus hopefully this works for both
|
||||
* IPv4 and IPv6...
|
||||
*/
|
||||
rc = bind(state->sockfd, (struct sockaddr *)&state->local_addr,
|
||||
conn->ip_addr->ai_addrlen);
|
||||
if(rc) {
|
||||
failf(conn->data, "bind() failed; %s\n",
|
||||
Curl_strerror(conn, Curl_sockerrno()));
|
||||
return CURLE_COULDNT_CONNECT;
|
||||
}
|
||||
}
|
||||
|
||||
Curl_pgrsStartNow(conn->data);
|
||||
@@ -616,12 +624,16 @@ CURLcode Curl_tftp_connect(struct connectdata *conn, bool *done)
|
||||
* The done callback
|
||||
*
|
||||
**********************************************************/
|
||||
CURLcode Curl_tftp_done(struct connectdata *conn, CURLcode status)
|
||||
CURLcode Curl_tftp_done(struct connectdata *conn, CURLcode status,
|
||||
bool premature)
|
||||
{
|
||||
(void)status; /* unused */
|
||||
(void)premature; /* not used */
|
||||
|
||||
#if 0
|
||||
free(conn->data->reqdata.proto.tftp);
|
||||
conn->data->reqdata.proto.tftp = NULL;
|
||||
#endif
|
||||
Curl_pgrsDone(conn);
|
||||
|
||||
return CURLE_OK;
|
||||
@@ -641,7 +653,8 @@ CURLcode Curl_tftp_done(struct connectdata *conn, CURLcode status)
|
||||
CURLcode Curl_tftp(struct connectdata *conn, bool *done)
|
||||
{
|
||||
struct SessionHandle *data = conn->data;
|
||||
tftp_state_data_t *state = (tftp_state_data_t *)(conn->data->reqdata.proto.tftp);
|
||||
tftp_state_data_t *state =
|
||||
(tftp_state_data_t *) conn->data->reqdata.proto.tftp;
|
||||
tftp_event_t event;
|
||||
CURLcode code;
|
||||
int rc;
|
||||
@@ -649,7 +662,20 @@ CURLcode Curl_tftp(struct connectdata *conn, bool *done)
|
||||
socklen_t fromlen;
|
||||
int check_time = 0;
|
||||
|
||||
(void)done; /* prevent compiler warning */
|
||||
*done = TRUE;
|
||||
|
||||
/*
|
||||
Since connections can be re-used between SessionHandles, this might be a
|
||||
connection already existing but on a fresh SessionHandle struct so we must
|
||||
make sure we have a good 'struct TFTP' to play with. For new connections,
|
||||
the struct TFTP is allocated and setup in the Curl_tftp_connect() function.
|
||||
*/
|
||||
if(!state) {
|
||||
code = Curl_tftp_connect(conn, done);
|
||||
if(code)
|
||||
return code;
|
||||
state = (tftp_state_data_t *)conn->data->reqdata.proto.tftp;
|
||||
}
|
||||
|
||||
/* Run the TFTP State Machine */
|
||||
for(tftp_state_machine(state, TFTP_EVENT_INIT);
|
||||
|
@@ -8,7 +8,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2005, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -26,6 +26,6 @@
|
||||
#ifndef CURL_DISABLE_TFTP
|
||||
CURLcode Curl_tftp_connect(struct connectdata *conn, bool *done);
|
||||
CURLcode Curl_tftp(struct connectdata *conn, bool *done);
|
||||
CURLcode Curl_tftp_done(struct connectdata *conn, CURLcode);
|
||||
CURLcode Curl_tftp_done(struct connectdata *conn, CURLcode, bool premature);
|
||||
#endif
|
||||
#endif
|
||||
|
254
lib/transfer.c
254
lib/transfer.c
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -189,17 +189,39 @@ checkhttpprefix(struct SessionHandle *data,
|
||||
const char *s)
|
||||
{
|
||||
struct curl_slist *head = data->set.http200aliases;
|
||||
bool rc = FALSE;
|
||||
#ifdef CURL_DOES_CONVERSIONS
|
||||
/* convert from the network encoding using a scratch area */
|
||||
char *scratch = calloc(1, strlen(s)+1);
|
||||
if (NULL == scratch) {
|
||||
failf (data, "Failed to calloc memory for conversion!");
|
||||
return FALSE; /* can't return CURLE_OUT_OF_MEMORY so return FALSE */
|
||||
}
|
||||
strcpy(scratch, s);
|
||||
if (CURLE_OK != Curl_convert_from_network(data, scratch, strlen(s)+1)) {
|
||||
/* Curl_convert_from_network calls failf if unsuccessful */
|
||||
free(scratch);
|
||||
return FALSE; /* can't return CURLE_foobar so return FALSE */
|
||||
}
|
||||
s = scratch;
|
||||
#endif /* CURL_DOES_CONVERSIONS */
|
||||
|
||||
while (head) {
|
||||
if (checkprefix(head->data, s))
|
||||
return TRUE;
|
||||
if (checkprefix(head->data, s)) {
|
||||
rc = TRUE;
|
||||
break;
|
||||
}
|
||||
head = head->next;
|
||||
}
|
||||
|
||||
if(checkprefix("HTTP/", s))
|
||||
return TRUE;
|
||||
if ((rc != TRUE) && (checkprefix("HTTP/", s))) {
|
||||
rc = TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
#ifdef CURL_DOES_CONVERSIONS
|
||||
free(scratch);
|
||||
#endif /* CURL_DOES_CONVERSIONS */
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -251,21 +273,37 @@ CURLcode Curl_readrewind(struct connectdata *conn)
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
#ifdef USE_SSLEAY
|
||||
/* FIX: this is nasty OpenSSL-specific code that really shouldn't be here */
|
||||
static int data_pending(struct connectdata *conn)
|
||||
{
|
||||
if(conn->ssl[FIRSTSOCKET].handle)
|
||||
/* SSL is in use */
|
||||
return SSL_pending(conn->ssl[FIRSTSOCKET].handle);
|
||||
|
||||
return 0; /* nothing */
|
||||
return Curl_ssl_data_pending(conn, FIRSTSOCKET);
|
||||
}
|
||||
#else
|
||||
/* non-SSL never have pending data */
|
||||
#define data_pending(x) 0
|
||||
|
||||
#ifndef MIN
|
||||
#define MIN(a,b) (a < b ? a : b)
|
||||
#endif
|
||||
|
||||
static void read_rewind(struct connectdata *conn,
|
||||
size_t thismuch)
|
||||
{
|
||||
conn->read_pos -= thismuch;
|
||||
conn->bits.stream_was_rewound = TRUE;
|
||||
|
||||
#ifdef CURLDEBUG
|
||||
{
|
||||
char buf[512 + 1];
|
||||
size_t show;
|
||||
|
||||
show = MIN(conn->buf_len - conn->read_pos, sizeof(buf)-1);
|
||||
memcpy(buf, conn->master_buffer + conn->read_pos, show);
|
||||
buf[show] = '\0';
|
||||
|
||||
DEBUGF(infof(conn->data,
|
||||
"Buffer after stream rewind (read_pos = %d): [%s]",
|
||||
conn->read_pos, buf));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Curl_readwrite() is the low-level function to be called when data is to
|
||||
* be read and written to/from the connection.
|
||||
@@ -285,12 +323,15 @@ CURLcode Curl_readwrite(struct connectdata *conn,
|
||||
|
||||
curl_off_t contentlength;
|
||||
|
||||
if(k->keepon & KEEP_READ)
|
||||
/* only use the proper socket if the *_HOLD bit is not set simultaneously as
|
||||
then we are in rate limiting state in that transfer direction */
|
||||
|
||||
if((k->keepon & (KEEP_READ|KEEP_READ_HOLD)) == KEEP_READ)
|
||||
fd_read = conn->sockfd;
|
||||
else
|
||||
fd_read = CURL_SOCKET_BAD;
|
||||
|
||||
if(k->keepon & KEEP_WRITE)
|
||||
if((k->keepon & (KEEP_WRITE|KEEP_WRITE_HOLD)) == KEEP_WRITE)
|
||||
fd_write = conn->writesockfd;
|
||||
else
|
||||
fd_write = CURL_SOCKET_BAD;
|
||||
@@ -318,8 +359,14 @@ CURLcode Curl_readwrite(struct connectdata *conn,
|
||||
size_t bytestoread = buffersize;
|
||||
int readrc;
|
||||
|
||||
if (k->size != -1 && !k->header)
|
||||
bytestoread = (size_t)(k->size - k->bytecount);
|
||||
if (k->size != -1 && !k->header) {
|
||||
/* make sure we don't read "too much" if we can help it since we
|
||||
might be pipelining and then someone else might want to read what
|
||||
follows! */
|
||||
curl_off_t totalleft = k->size - k->bytecount;
|
||||
if(totalleft < (curl_off_t)bytestoread)
|
||||
bytestoread = (size_t)totalleft;
|
||||
}
|
||||
|
||||
/* receive data from the network! */
|
||||
readrc = Curl_read(conn, conn->sockfd, k->buf, bytestoread, &nread);
|
||||
@@ -377,7 +424,8 @@ CURLcode Curl_readwrite(struct connectdata *conn,
|
||||
/* str_start is start of line within buf */
|
||||
k->str_start = k->str;
|
||||
|
||||
k->end_ptr = memchr(k->str_start, '\n', nread);
|
||||
/* data is in network encoding so use 0x0a instead of '\n' */
|
||||
k->end_ptr = memchr(k->str_start, 0x0a, nread);
|
||||
|
||||
if (!k->end_ptr) {
|
||||
/* Not a complete header line within buffer, append the data to
|
||||
@@ -475,14 +523,27 @@ CURLcode Curl_readwrite(struct connectdata *conn,
|
||||
}
|
||||
}
|
||||
|
||||
if (('\n' == *k->p) || ('\r' == *k->p)) {
|
||||
/* headers are in network encoding so
|
||||
use 0x0a and 0x0d instead of '\n' and '\r' */
|
||||
if ((0x0a == *k->p) || (0x0d == *k->p)) {
|
||||
size_t headerlen;
|
||||
/* Zero-length header line means end of headers! */
|
||||
|
||||
#ifdef CURL_DOES_CONVERSIONS
|
||||
if (0x0d == *k->p) {
|
||||
*k->p = '\r'; /* replace with CR in host encoding */
|
||||
k->p++; /* pass the CR byte */
|
||||
}
|
||||
if (0x0a == *k->p) {
|
||||
*k->p = '\n'; /* replace with LF in host encoding */
|
||||
k->p++; /* pass the LF byte */
|
||||
}
|
||||
#else
|
||||
if ('\r' == *k->p)
|
||||
k->p++; /* pass the \r byte */
|
||||
if ('\n' == *k->p)
|
||||
k->p++; /* pass the \n byte */
|
||||
#endif /* CURL_DOES_CONVERSIONS */
|
||||
|
||||
if(100 == k->httpcode) {
|
||||
/*
|
||||
@@ -501,9 +562,19 @@ CURLcode Curl_readwrite(struct connectdata *conn,
|
||||
k->keepon |= KEEP_WRITE;
|
||||
}
|
||||
}
|
||||
else
|
||||
else {
|
||||
k->header = FALSE; /* no more header to parse! */
|
||||
|
||||
if((k->size == -1) && !conn->bits.chunk && !conn->bits.close)
|
||||
/* When connection is not to get closed, but no
|
||||
Content-Length nor Content-Encoding chunked have been
|
||||
received, there is no body in this response. We don't set
|
||||
stop_reading TRUE since that would also prevent necessary
|
||||
authentication actions to take place. */
|
||||
conn->bits.no_body = TRUE;
|
||||
|
||||
}
|
||||
|
||||
if (417 == k->httpcode) {
|
||||
/*
|
||||
* we got: "417 Expectation Failed" this means:
|
||||
@@ -542,10 +613,10 @@ CURLcode Curl_readwrite(struct connectdata *conn,
|
||||
return result;
|
||||
|
||||
data->info.header_size += (long)headerlen;
|
||||
k->headerbytecount += (long)headerlen;
|
||||
conn->headerbytecount += (long)headerlen;
|
||||
|
||||
k->deductheadercount =
|
||||
(100 == k->httpcode)?k->headerbytecount:0;
|
||||
conn->deductheadercount =
|
||||
(100 == k->httpcode)?conn->headerbytecount:0;
|
||||
|
||||
if (data->reqdata.resume_from &&
|
||||
(data->set.httpreq==HTTPREQ_GET) &&
|
||||
@@ -634,12 +705,37 @@ CURLcode Curl_readwrite(struct connectdata *conn,
|
||||
|
||||
if (!k->headerline++) {
|
||||
/* This is the first header, it MUST be the error code line
|
||||
or else we consiser this to be the body right away! */
|
||||
or else we consider this to be the body right away! */
|
||||
int httpversion_major;
|
||||
int nc=sscanf(k->p, " HTTP/%d.%d %3d",
|
||||
&httpversion_major,
|
||||
&k->httpversion,
|
||||
&k->httpcode);
|
||||
int nc;
|
||||
#ifdef CURL_DOES_CONVERSIONS
|
||||
#define HEADER1 scratch
|
||||
#define SCRATCHSIZE 21
|
||||
CURLcode res;
|
||||
char scratch[SCRATCHSIZE+1]; /* "HTTP/major.minor 123" */
|
||||
/* We can't really convert this yet because we
|
||||
don't know if it's the 1st header line or the body.
|
||||
So we do a partial conversion into a scratch area,
|
||||
leaving the data at k->p as-is.
|
||||
*/
|
||||
strncpy(&scratch[0], k->p, SCRATCHSIZE);
|
||||
scratch[SCRATCHSIZE] = 0; /* null terminate */
|
||||
res = Curl_convert_from_network(data,
|
||||
&scratch[0],
|
||||
SCRATCHSIZE);
|
||||
if (CURLE_OK != res) {
|
||||
/* Curl_convert_from_network calls failf if unsuccessful */
|
||||
return res;
|
||||
}
|
||||
#else
|
||||
#define HEADER1 k->p /* no conversion needed, just use k->p */
|
||||
#endif /* CURL_DOES_CONVERSIONS */
|
||||
|
||||
nc = sscanf(HEADER1,
|
||||
" HTTP/%d.%d %3d",
|
||||
&httpversion_major,
|
||||
&k->httpversion,
|
||||
&k->httpcode);
|
||||
if (nc==3) {
|
||||
k->httpversion += 10 * httpversion_major;
|
||||
}
|
||||
@@ -647,7 +743,7 @@ CURLcode Curl_readwrite(struct connectdata *conn,
|
||||
/* this is the real world, not a Nirvana
|
||||
NCSA 1.5.x returns this crap when asked for HTTP/1.1
|
||||
*/
|
||||
nc=sscanf(k->p, " HTTP %3d", &k->httpcode);
|
||||
nc=sscanf(HEADER1, " HTTP %3d", &k->httpcode);
|
||||
k->httpversion = 10;
|
||||
|
||||
/* If user has set option HTTP200ALIASES,
|
||||
@@ -730,6 +826,15 @@ CURLcode Curl_readwrite(struct connectdata *conn,
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CURL_DOES_CONVERSIONS
|
||||
/* convert from the network encoding */
|
||||
result = Curl_convert_from_network(data, k->p, strlen(k->p));
|
||||
if (CURLE_OK != result) {
|
||||
return(result);
|
||||
}
|
||||
/* Curl_convert_from_network calls failf if unsuccessful */
|
||||
#endif /* CURL_DOES_CONVERSIONS */
|
||||
|
||||
/* Check for Content-Length: header lines to get size. Ignore
|
||||
the header completely if we get a 416 response as then we're
|
||||
resuming a document that we don't get, and this header contains
|
||||
@@ -767,6 +872,8 @@ CURLcode Curl_readwrite(struct connectdata *conn,
|
||||
start++)
|
||||
; /* empty loop */
|
||||
|
||||
/* data is now in the host encoding so
|
||||
use '\r' and '\n' instead of 0x0d and 0x0a */
|
||||
end = strchr(start, '\r');
|
||||
if(!end)
|
||||
end = strchr(start, '\n');
|
||||
@@ -894,19 +1001,20 @@ CURLcode Curl_readwrite(struct connectdata *conn,
|
||||
|| checkprefix("x-compress", start))
|
||||
k->content_encoding = COMPRESS;
|
||||
}
|
||||
else if (Curl_compareheader(k->p, "Content-Range:", "bytes")) {
|
||||
else if (checkprefix("Content-Range:", k->p)) {
|
||||
/* Content-Range: bytes [num]-
|
||||
Content-Range: bytes: [num]-
|
||||
Content-Range: [num]-
|
||||
|
||||
The second format was added since Sun's webserver
|
||||
JavaWebServer/1.1.1 obviously sends the header this way!
|
||||
The third added since some servers use that!
|
||||
*/
|
||||
|
||||
char *ptr = Curl_strcasestr(k->p, "bytes");
|
||||
ptr+=5;
|
||||
char *ptr = k->p + 14;
|
||||
|
||||
if(*ptr == ':')
|
||||
/* stupid colon skip */
|
||||
/* Move forward until first digit */
|
||||
while(*ptr && !ISDIGIT(*ptr))
|
||||
ptr++;
|
||||
|
||||
k->offset = curlx_strtoofft(ptr, NULL, 10);
|
||||
@@ -1000,7 +1108,7 @@ CURLcode Curl_readwrite(struct connectdata *conn,
|
||||
return result;
|
||||
|
||||
data->info.header_size += (long)k->hbuflen;
|
||||
k->headerbytecount += (long)k->hbuflen;
|
||||
conn->headerbytecount += (long)k->hbuflen;
|
||||
|
||||
/* reset hbufp pointer && hbuflen */
|
||||
k->hbufp = data->state.headerbuff;
|
||||
@@ -1134,17 +1242,18 @@ CURLcode Curl_readwrite(struct connectdata *conn,
|
||||
|
||||
if((-1 != k->maxdownload) &&
|
||||
(k->bytecount + nread >= k->maxdownload)) {
|
||||
curl_off_t excess = k->bytecount +
|
||||
((curl_off_t) nread) - k->maxdownload;
|
||||
/* The 'excess' amount below can't be more than BUFSIZE which
|
||||
always will fit in a size_t */
|
||||
size_t excess = k->bytecount + nread - k->maxdownload;
|
||||
if (excess > 0 && !k->ignorebody) {
|
||||
infof(data,
|
||||
"Rewinding stream by : %" FORMAT_OFF_T
|
||||
"Rewinding stream by : %d"
|
||||
" bytes on url %s (size = %" FORMAT_OFF_T
|
||||
", maxdownload = %" FORMAT_OFF_T
|
||||
", bytecount = %" FORMAT_OFF_T ", nread = %d)\n",
|
||||
excess, conn->data->reqdata.path,
|
||||
k->size, k->maxdownload, k->bytecount, nread);
|
||||
Curl_read_rewind(conn, excess);
|
||||
read_rewind(conn, excess);
|
||||
}
|
||||
|
||||
nread = (ssize_t) (k->maxdownload - k->bytecount);
|
||||
@@ -1492,7 +1601,7 @@ CURLcode Curl_readwrite(struct connectdata *conn,
|
||||
}
|
||||
|
||||
/* Now update the "done" boolean we return */
|
||||
*done = (bool)(0 == k->keepon);
|
||||
*done = (bool)(0 == (k->keepon&(KEEP_READ|KEEP_WRITE)));
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
@@ -1523,7 +1632,6 @@ CURLcode Curl_readwrite_init(struct connectdata *conn)
|
||||
k->writebytecountp = data->reqdata.writebytecountp;
|
||||
|
||||
k->bytecount = 0;
|
||||
k->headerbytecount = 0;
|
||||
|
||||
k->buf = data->state.buffer;
|
||||
k->uploadbuf = data->state.uploadbuffer;
|
||||
@@ -1661,37 +1769,40 @@ Transfer(struct connectdata *conn)
|
||||
while (!done) {
|
||||
curl_socket_t fd_read;
|
||||
curl_socket_t fd_write;
|
||||
int interval_ms;
|
||||
|
||||
interval_ms = 1 * 1000;
|
||||
|
||||
/* limit-rate logic: if speed exceeds threshold, then do not include fd in
|
||||
select set */
|
||||
if ( (conn->data->set.max_send_speed > 0) &&
|
||||
(conn->data->progress.ulspeed > conn->data->set.max_send_speed) ) {
|
||||
select set. The current speed is recalculated in each Curl_readwrite()
|
||||
call */
|
||||
if ((k->keepon & KEEP_WRITE) &&
|
||||
(!data->set.max_send_speed ||
|
||||
(data->progress.ulspeed < data->set.max_send_speed) )) {
|
||||
fd_write = conn->writesockfd;
|
||||
k->keepon &= ~KEEP_WRITE_HOLD;
|
||||
}
|
||||
else {
|
||||
fd_write = CURL_SOCKET_BAD;
|
||||
Curl_pgrsUpdate(conn);
|
||||
}
|
||||
else {
|
||||
if(k->keepon & KEEP_WRITE)
|
||||
fd_write = conn->writesockfd;
|
||||
else
|
||||
fd_write = CURL_SOCKET_BAD;
|
||||
k->keepon |= KEEP_WRITE_HOLD; /* hold it */
|
||||
}
|
||||
|
||||
if ( (conn->data->set.max_recv_speed > 0) &&
|
||||
(conn->data->progress.dlspeed > conn->data->set.max_recv_speed) ) {
|
||||
fd_read = CURL_SOCKET_BAD;
|
||||
Curl_pgrsUpdate(conn);
|
||||
if ((k->keepon & KEEP_READ) &&
|
||||
(!data->set.max_recv_speed ||
|
||||
(data->progress.dlspeed < data->set.max_recv_speed)) ) {
|
||||
fd_read = conn->sockfd;
|
||||
k->keepon &= ~KEEP_READ_HOLD;
|
||||
}
|
||||
else {
|
||||
fd_read = CURL_SOCKET_BAD;
|
||||
if(k->keepon & KEEP_READ)
|
||||
fd_read = conn->sockfd;
|
||||
else
|
||||
fd_read = CURL_SOCKET_BAD;
|
||||
k->keepon |= KEEP_READ_HOLD; /* hold it */
|
||||
}
|
||||
|
||||
switch (Curl_select(fd_read, fd_write, interval_ms)) {
|
||||
/* The *_HOLD logic is necessary since even though there might be no
|
||||
traffic during the select interval, we still call Curl_readwrite() for
|
||||
the timeout case and if we limit transfer speed we must make sure that
|
||||
this function doesn't transfer anything while in HOLD status. */
|
||||
|
||||
switch (Curl_select(fd_read, fd_write, 1000)) {
|
||||
case -1: /* select() error, stop reading */
|
||||
#ifdef EINTR
|
||||
/* The EINTR is not serious, and it seems you might get this more
|
||||
@@ -2182,7 +2293,7 @@ Curl_connect_host(struct SessionHandle *data,
|
||||
to the new URL */
|
||||
urlchanged = data->change.url_changed;
|
||||
if ((CURLE_OK == res) && urlchanged) {
|
||||
res = Curl_done(conn, res);
|
||||
res = Curl_done(conn, res, FALSE);
|
||||
if(CURLE_OK == res) {
|
||||
char *gotourl = strdup(data->change.url);
|
||||
res = Curl_follow(data, gotourl, FALSE);
|
||||
@@ -2201,9 +2312,8 @@ bool Curl_retry_request(struct connectdata *conn,
|
||||
{
|
||||
bool retry = FALSE;
|
||||
struct SessionHandle *data = conn->data;
|
||||
struct Curl_transfer_keeper *k = &data->reqdata.keep;
|
||||
|
||||
if((data->reqdata.keep.bytecount+k->headerbytecount == 0) &&
|
||||
if((data->reqdata.keep.bytecount+conn->headerbytecount == 0) &&
|
||||
conn->bits.reuse &&
|
||||
!conn->bits.no_body) {
|
||||
/* We got no data, we attempted to re-use a connection and yet we want a
|
||||
@@ -2259,7 +2369,7 @@ CURLcode Curl_perform(struct SessionHandle *data)
|
||||
if(data->set.connect_only) {
|
||||
/* keep connection open for application to use the socket */
|
||||
conn->bits.close = FALSE;
|
||||
res = Curl_done(&conn, CURLE_OK);
|
||||
res = Curl_done(&conn, CURLE_OK, FALSE);
|
||||
break;
|
||||
}
|
||||
res = Curl_do(&conn, &do_done);
|
||||
@@ -2292,14 +2402,14 @@ CURLcode Curl_perform(struct SessionHandle *data)
|
||||
|
||||
/* Always run Curl_done(), even if some of the previous calls
|
||||
failed, but return the previous (original) error code */
|
||||
res2 = Curl_done(&conn, res);
|
||||
res2 = Curl_done(&conn, res, FALSE);
|
||||
|
||||
if(CURLE_OK == res)
|
||||
res = res2;
|
||||
}
|
||||
else
|
||||
/* Curl_do() failed, clean up left-overs in the done-call */
|
||||
res2 = Curl_done(&conn, res);
|
||||
res2 = Curl_done(&conn, res, FALSE);
|
||||
|
||||
/*
|
||||
* Important: 'conn' cannot be used here, since it may have been closed
|
||||
@@ -2344,8 +2454,8 @@ CURLcode Curl_perform(struct SessionHandle *data)
|
||||
}
|
||||
|
||||
/*
|
||||
* Curl_setup_transfer() is called to setup some basic properties for the upcoming
|
||||
* transfer.
|
||||
* Curl_setup_transfer() is called to setup some basic properties for the
|
||||
* upcoming transfer.
|
||||
*/
|
||||
CURLcode
|
||||
Curl_setup_transfer(
|
||||
|
270
lib/url.c
270
lib/url.c
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -128,6 +128,7 @@ void idn_free (void *ptr); /* prototype from idn-free.h, not provided by
|
||||
#include "http.h"
|
||||
#include "file.h"
|
||||
#include "ldap.h"
|
||||
#include "ssh.h"
|
||||
#include "url.h"
|
||||
#include "connect.h"
|
||||
#include "inet_ntop.h"
|
||||
@@ -165,7 +166,7 @@ static void signalPipeClose(struct curl_llist *pipe);
|
||||
|
||||
#define MAX_PIPELINE_LENGTH 5
|
||||
|
||||
/*
|
||||
/*
|
||||
* We use this ZERO_NULL to avoid picky compiler warnings,
|
||||
* when assigning a NULL pointer to a function pointer var.
|
||||
*/
|
||||
@@ -178,9 +179,6 @@ static void signalPipeClose(struct curl_llist *pipe);
|
||||
#ifndef WIN32
|
||||
/* not for WIN32 builds */
|
||||
|
||||
#ifndef RETSIGTYPE
|
||||
#define RETSIGTYPE void
|
||||
#endif
|
||||
#ifdef HAVE_SIGSETJMP
|
||||
extern sigjmp_buf curl_jmpenv;
|
||||
#endif
|
||||
@@ -312,9 +310,6 @@ CURLcode Curl_close(struct SessionHandle *data)
|
||||
Curl_safefree(data->state.first_host);
|
||||
Curl_safefree(data->state.scratch);
|
||||
|
||||
if(data->change.proxy_alloc)
|
||||
free(data->change.proxy);
|
||||
|
||||
if(data->change.referer_alloc)
|
||||
free(data->change.referer);
|
||||
|
||||
@@ -379,11 +374,13 @@ CURLcode Curl_close(struct SessionHandle *data)
|
||||
}
|
||||
|
||||
/* create a connection cache of a private or multi type */
|
||||
struct conncache *Curl_mk_connc(int type)
|
||||
struct conncache *Curl_mk_connc(int type,
|
||||
int amount) /* set -1 to use default */
|
||||
{
|
||||
/* It is subject for debate how many default connections to have for a multi
|
||||
connection cache... */
|
||||
int default_amount = (type == CONNCACHE_PRIVATE)?5:10;
|
||||
int default_amount = amount == -1?
|
||||
((type == CONNCACHE_PRIVATE)?5:10):amount;
|
||||
struct conncache *c;
|
||||
|
||||
c= calloc(sizeof(struct conncache), 1);
|
||||
@@ -409,6 +406,20 @@ CURLcode Curl_ch_connc(struct SessionHandle *data,
|
||||
long i;
|
||||
struct connectdata **newptr;
|
||||
|
||||
if(newamount < 1)
|
||||
newamount = 1; /* we better have at least one entry */
|
||||
|
||||
if(!c) {
|
||||
/* we get a NULL pointer passed in as connection cache, which means that
|
||||
there is no cache created for this SessionHandle just yet, we create a
|
||||
brand new with the requested size.
|
||||
*/
|
||||
data->state.connc = Curl_mk_connc(CONNCACHE_PRIVATE, newamount);
|
||||
if(!data->state.connc)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
if(newamount < c->num) {
|
||||
/* Since this number is *decreased* from the existing number, we must
|
||||
close the possibly open connections that live on the indexes that
|
||||
@@ -546,6 +557,9 @@ CURLcode Curl_open(struct SessionHandle **curl)
|
||||
the first call to curl_easy_perform() or when the handle is added to a
|
||||
multi stack. */
|
||||
|
||||
data->set.ssh_auth_types = CURLSSH_AUTH_DEFAULT; /* defaults to any auth
|
||||
type */
|
||||
|
||||
/* most recent connection is not yet defined */
|
||||
data->state.lastconnect = -1;
|
||||
|
||||
@@ -1088,15 +1102,7 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
|
||||
* Setting it to NULL, means no proxy but allows the environment variables
|
||||
* to decide for us.
|
||||
*/
|
||||
if(data->change.proxy_alloc) {
|
||||
/*
|
||||
* The already set string is allocated, free that first
|
||||
*/
|
||||
data->change.proxy_alloc = FALSE;
|
||||
free(data->change.proxy);
|
||||
}
|
||||
data->set.set_proxy = va_arg(param, char *);
|
||||
data->change.proxy = data->set.set_proxy;
|
||||
data->set.proxy = va_arg(param, char *);
|
||||
break;
|
||||
|
||||
case CURLOPT_WRITEHEADER:
|
||||
@@ -1134,6 +1140,10 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
|
||||
data->set.ftp_use_epsv = (bool)(0 != va_arg(param, long));
|
||||
break;
|
||||
|
||||
case CURLOPT_FTP_SSL_CCC:
|
||||
data->set.ftp_use_ccc = (bool)(0 != va_arg(param, long));
|
||||
break;
|
||||
|
||||
case CURLOPT_FTP_SKIP_PASV_IP:
|
||||
/*
|
||||
* Enable or disable FTP_SKIP_PASV_IP, which will disable/enable the
|
||||
@@ -1673,6 +1683,24 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
|
||||
data->set.ssl.sessionid = (bool)(0 != va_arg(param, long));
|
||||
break;
|
||||
|
||||
case CURLOPT_SSH_AUTH_TYPES:
|
||||
data->set.ssh_auth_types = va_arg(param, long);
|
||||
break;
|
||||
|
||||
case CURLOPT_SSH_PUBLIC_KEYFILE:
|
||||
/*
|
||||
* Use this file instead of the $HOME/.ssh/id_dsa.pub file
|
||||
*/
|
||||
data->set.ssh_public_key = va_arg(param, char *);
|
||||
break;
|
||||
|
||||
case CURLOPT_SSH_PRIVATE_KEYFILE:
|
||||
/*
|
||||
* Use this file instead of the $HOME/.ssh/id_dsa file
|
||||
*/
|
||||
data->set.ssh_private_key = va_arg(param, char *);
|
||||
break;
|
||||
|
||||
default:
|
||||
/* unknown tag and its companion, just ignore: */
|
||||
result = CURLE_FAILED_INIT; /* correct this */
|
||||
@@ -1782,7 +1810,10 @@ CURLcode Curl_disconnect(struct connectdata *conn)
|
||||
if(-1 != conn->connectindex) {
|
||||
/* unlink ourselves! */
|
||||
infof(data, "Closing connection #%ld\n", conn->connectindex);
|
||||
data->state.connc->connects[conn->connectindex] = NULL;
|
||||
if(data->state.connc)
|
||||
/* only clear the table entry if we still know in which cache we
|
||||
used to be in */
|
||||
data->state.connc->connects[conn->connectindex] = NULL;
|
||||
}
|
||||
|
||||
#ifdef USE_LIBIDN
|
||||
@@ -1877,7 +1908,7 @@ int Curl_removeHandleFromPipeline(struct SessionHandle *handle,
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
#if 0 /* this code is saved here as it is useful for debugging purposes */
|
||||
static void Curl_printPipeline(struct curl_llist *pipe)
|
||||
{
|
||||
struct curl_llist_element *curr;
|
||||
@@ -2016,6 +2047,10 @@ ConnectionExists(struct SessionHandle *data,
|
||||
ssl options as well */
|
||||
if(!Curl_ssl_config_matches(&needle->ssl_config,
|
||||
&check->ssl_config)) {
|
||||
infof(data,
|
||||
"Connection #%ld has different SSL parameters, "
|
||||
"can't reuse\n",
|
||||
check->connectindex );
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -2044,7 +2079,6 @@ ConnectionExists(struct SessionHandle *data,
|
||||
}
|
||||
|
||||
if(match) {
|
||||
#if 1
|
||||
if (!IsPipeliningEnabled(data)) {
|
||||
/* The check for a dead socket makes sense only in the
|
||||
non-pipelining case */
|
||||
@@ -2059,7 +2093,6 @@ ConnectionExists(struct SessionHandle *data,
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
check->inuse = TRUE; /* mark this as being in use so that no other
|
||||
handle in a multi stack may nick it */
|
||||
@@ -2105,26 +2138,8 @@ ConnectionKillOne(struct SessionHandle *data)
|
||||
if(!conn || conn->inuse)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* By using the set policy, we score each connection.
|
||||
*/
|
||||
switch(data->set.closepolicy) {
|
||||
case CURLCLOSEPOLICY_LEAST_RECENTLY_USED:
|
||||
default:
|
||||
/*
|
||||
* Set higher score for the age passed since the connection
|
||||
* was used.
|
||||
*/
|
||||
score = Curl_tvdiff(now, conn->now);
|
||||
break;
|
||||
case CURLCLOSEPOLICY_OLDEST:
|
||||
/*
|
||||
* Set higher score for the age passed since the connection
|
||||
* was created.
|
||||
*/
|
||||
score = Curl_tvdiff(now, conn->created);
|
||||
break;
|
||||
}
|
||||
/* Set higher score for the age passed since the connection was used */
|
||||
score = Curl_tvdiff(now, conn->now);
|
||||
|
||||
if(score > highscore) {
|
||||
highscore = score;
|
||||
@@ -2151,10 +2166,7 @@ static void
|
||||
ConnectionDone(struct connectdata *conn)
|
||||
{
|
||||
conn->inuse = FALSE;
|
||||
conn->data = NULL;
|
||||
|
||||
if (conn->send_pipe == 0 &&
|
||||
conn->recv_pipe == 0)
|
||||
if (!conn->send_pipe && !conn->recv_pipe)
|
||||
conn->is_in_pipeline = FALSE;
|
||||
}
|
||||
|
||||
@@ -2213,10 +2225,10 @@ static CURLcode ConnectPlease(struct SessionHandle *data,
|
||||
{
|
||||
CURLcode result;
|
||||
Curl_addrinfo *addr;
|
||||
char *hostname = data->change.proxy?conn->proxy.name:conn->host.name;
|
||||
char *hostname = conn->bits.httpproxy?conn->proxy.name:conn->host.name;
|
||||
|
||||
infof(data, "About to connect() to %s%s port %d (#%d)\n",
|
||||
data->change.proxy?"proxy ":"",
|
||||
conn->bits.httpproxy?"proxy ":"",
|
||||
hostname, conn->port, conn->connectindex);
|
||||
|
||||
/*************************************************************
|
||||
@@ -2372,7 +2384,8 @@ CURLcode Curl_protocol_connect(struct connectdata *conn,
|
||||
|
||||
/* it has started, possibly even completed but that knowledge isn't stored
|
||||
in this bit! */
|
||||
conn->bits.protoconnstart = TRUE;
|
||||
if (!result)
|
||||
conn->bits.protoconnstart = TRUE;
|
||||
}
|
||||
|
||||
return result; /* pass back status */
|
||||
@@ -2688,6 +2701,8 @@ static CURLcode CreateConnection(struct SessionHandle *data,
|
||||
char passwd[MAX_CURL_PASSWORD_LENGTH];
|
||||
int rc;
|
||||
bool reuse;
|
||||
char *proxy;
|
||||
bool proxy_alloc = FALSE;
|
||||
|
||||
#ifndef USE_ARES
|
||||
#ifdef SIGALRM
|
||||
@@ -2736,9 +2751,10 @@ static CURLcode CreateConnection(struct SessionHandle *data,
|
||||
conn->sock[SECONDARYSOCKET] = CURL_SOCKET_BAD; /* no file descriptor */
|
||||
conn->connectindex = -1; /* no index */
|
||||
|
||||
conn->bits.httpproxy = (bool)(data->change.proxy /* http proxy or not */
|
||||
&& *data->change.proxy
|
||||
&& (data->set.proxytype == CURLPROXY_HTTP));
|
||||
conn->bits.httpproxy = (bool)(data->set.proxy /* http proxy or not */
|
||||
&& *data->set.proxy
|
||||
&& (data->set.proxytype == CURLPROXY_HTTP));
|
||||
proxy = data->set.proxy; /* if global proxy is set, this is it */
|
||||
|
||||
/* Default protocol-independent behavior doesn't support persistent
|
||||
connections, so we set this to force-close. Protocols that support
|
||||
@@ -2838,7 +2854,7 @@ static CURLcode CreateConnection(struct SessionHandle *data,
|
||||
/*************************************************************
|
||||
* Detect what (if any) proxy to use
|
||||
*************************************************************/
|
||||
if(!data->change.proxy) {
|
||||
if(!conn->bits.httpproxy) {
|
||||
/* If proxy was not specified, we check for default proxy environment
|
||||
* variables, to enable i.e Lynx compliance:
|
||||
*
|
||||
@@ -2858,7 +2874,6 @@ static CURLcode CreateConnection(struct SessionHandle *data,
|
||||
*/
|
||||
char *no_proxy=NULL;
|
||||
char *no_proxy_tok_buf;
|
||||
char *proxy=NULL;
|
||||
char proxy_env[128];
|
||||
|
||||
no_proxy=curl_getenv("no_proxy");
|
||||
@@ -2933,13 +2948,12 @@ static CURLcode CreateConnection(struct SessionHandle *data,
|
||||
}
|
||||
|
||||
if(proxy && *proxy) {
|
||||
long bits = conn->protocol & (PROT_HTTPS|PROT_SSL);
|
||||
data->change.proxy = proxy;
|
||||
data->change.proxy_alloc=TRUE; /* this needs to be freed later */
|
||||
conn->bits.httpproxy = TRUE;
|
||||
|
||||
long bits = conn->protocol & (PROT_HTTPS|PROT_SSL|PROT_MISSING);
|
||||
/* force this to become HTTP */
|
||||
conn->protocol = PROT_HTTP | bits;
|
||||
|
||||
proxy_alloc=TRUE; /* this needs to be freed later */
|
||||
conn->bits.httpproxy = TRUE;
|
||||
}
|
||||
} /* if (!nope) - it wasn't specified non-proxy */
|
||||
} /* NO_PROXY wasn't specified or '*' */
|
||||
@@ -3023,7 +3037,7 @@ static CURLcode CreateConnection(struct SessionHandle *data,
|
||||
conn->curl_connecting = Curl_https_connecting;
|
||||
conn->curl_proto_getsock = Curl_https_getsock;
|
||||
|
||||
#else /* USE_SS */
|
||||
#else /* USE_SSL */
|
||||
failf(data, LIBCURL_NAME
|
||||
" was built with SSL disabled, https: not supported!");
|
||||
return CURLE_UNSUPPORTED_PROTOCOL;
|
||||
@@ -3050,11 +3064,9 @@ static CURLcode CreateConnection(struct SessionHandle *data,
|
||||
|
||||
conn->port = port;
|
||||
conn->remote_port = (unsigned short)port;
|
||||
conn->protocol |= PROT_FTP|PROT_CLOSEACTION;
|
||||
conn->protocol |= PROT_FTP;
|
||||
|
||||
if(data->change.proxy &&
|
||||
*data->change.proxy &&
|
||||
!data->set.tunnel_thru_httpproxy) {
|
||||
if(proxy && *proxy && !data->set.tunnel_thru_httpproxy) {
|
||||
/* Unless we have asked to tunnel ftp operations through the proxy, we
|
||||
switch and use HTTP operations only */
|
||||
#ifndef CURL_DISABLE_HTTP
|
||||
@@ -3215,14 +3227,44 @@ static CURLcode CreateConnection(struct SessionHandle *data,
|
||||
" was built with TFTP disabled!");
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
else if (strequal(conn->protostr, "SCP")) {
|
||||
#ifdef USE_LIBSSH2
|
||||
conn->port = PORT_SSH;
|
||||
conn->remote_port = PORT_SSH;
|
||||
conn->protocol = PROT_SCP;
|
||||
conn->curl_connect = Curl_ssh_connect; /* ssh_connect? */
|
||||
conn->curl_do = Curl_scp_do;
|
||||
conn->curl_done = Curl_scp_done;
|
||||
conn->curl_do_more = (Curl_do_more_func)ZERO_NULL;
|
||||
#else
|
||||
failf(data, LIBCURL_NAME
|
||||
" was built without LIBSSH2, scp: not supported!");
|
||||
return CURLE_UNSUPPORTED_PROTOCOL;
|
||||
#endif
|
||||
}
|
||||
else if (strequal(conn->protostr, "SFTP")) {
|
||||
#ifdef USE_LIBSSH2
|
||||
conn->port = PORT_SSH;
|
||||
conn->remote_port = PORT_SSH;
|
||||
conn->protocol = PROT_SFTP;
|
||||
conn->curl_connect = Curl_ssh_connect; /* ssh_connect? */
|
||||
conn->curl_do = Curl_sftp_do;
|
||||
conn->curl_done = Curl_sftp_done;
|
||||
conn->curl_do_more = (Curl_do_more_func)NULL;
|
||||
#else
|
||||
failf(data, LIBCURL_NAME
|
||||
" was built without LIBSSH2, scp: not supported!");
|
||||
return CURLE_UNSUPPORTED_PROTOCOL;
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
/* We fell through all checks and thus we don't support the specified
|
||||
protocol */
|
||||
failf(data, "Unsupported protocol: %s", conn->protostr);
|
||||
return CURLE_UNSUPPORTED_PROTOCOL;
|
||||
}
|
||||
|
||||
if(data->change.proxy && *data->change.proxy) {
|
||||
if(proxy && *proxy) {
|
||||
/* If this is supposed to use a proxy, we need to figure out the proxy
|
||||
host name name, so that we can re-use an existing connection
|
||||
that may exist registered to the same proxy host. */
|
||||
@@ -3231,8 +3273,9 @@ static CURLcode CreateConnection(struct SessionHandle *data,
|
||||
char *endofprot;
|
||||
|
||||
/* We need to make a duplicate of the proxy so that we can modify the
|
||||
string safely. */
|
||||
char *proxydup=strdup(data->change.proxy);
|
||||
string safely. If 'proxy_alloc' is TRUE, the string is already
|
||||
allocated and we can treat it as duplicated. */
|
||||
char *proxydup=proxy_alloc?proxy:strdup(proxy);
|
||||
|
||||
/* We use 'proxyptr' to point to the proxy name from now on... */
|
||||
char *proxyptr=proxydup;
|
||||
@@ -3341,12 +3384,13 @@ static CURLcode CreateConnection(struct SessionHandle *data,
|
||||
conn->proxy.name = conn->proxy.rawalloc;
|
||||
|
||||
free(proxydup); /* free the duplicate pointer and not the modified */
|
||||
proxy = NULL; /* this may have just been freed */
|
||||
if(!conn->proxy.rawalloc)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
/*************************************************************
|
||||
* If the protcol is using SSL and HTTP proxy is used, we set
|
||||
* If the protocol is using SSL and HTTP proxy is used, we set
|
||||
* the tunnel_proxy bit.
|
||||
*************************************************************/
|
||||
if((conn->protocol&PROT_SSL) && conn->bits.httpproxy)
|
||||
@@ -3381,9 +3425,9 @@ static CURLcode CreateConnection(struct SessionHandle *data,
|
||||
user[0] =0; /* to make everything well-defined */
|
||||
passwd[0]=0;
|
||||
|
||||
if (conn->protocol & (PROT_FTP|PROT_HTTP)) {
|
||||
/* This is a FTP or HTTP URL, we will now try to extract the possible
|
||||
* user+password pair in a string like:
|
||||
if (conn->protocol & (PROT_FTP|PROT_HTTP|PROT_SCP|PROT_SFTP)) {
|
||||
/* This is a FTP, HTTP, SCP or SFTP URL, we will now try to extract the
|
||||
* possible user+password pair in a string like:
|
||||
* ftp://user:password@ftp.my.site:8021/README */
|
||||
char *ptr=strchr(conn->host.name, '@');
|
||||
char *userpass = conn->host.name;
|
||||
@@ -3792,7 +3836,7 @@ static CURLcode CreateConnection(struct SessionHandle *data,
|
||||
/* set a pointer to the hostname we display */
|
||||
fix_hostname(data, conn, &conn->host);
|
||||
|
||||
if(!data->change.proxy || !*data->change.proxy) {
|
||||
if(!conn->proxy.name || !*conn->proxy.name) {
|
||||
/* If not connecting via a proxy, extract the port from the URL, if it is
|
||||
* there, thus overriding any defaults that might have been set above. */
|
||||
conn->port = conn->remote_port; /* it is the same port */
|
||||
@@ -3905,45 +3949,62 @@ static CURLcode SetupConnection(struct connectdata *conn,
|
||||
* Send user-agent to HTTP proxies even if the target protocol
|
||||
* isn't HTTP.
|
||||
*************************************************************/
|
||||
if((conn->protocol&PROT_HTTP) ||
|
||||
(data->change.proxy && *data->change.proxy)) {
|
||||
if((conn->protocol&PROT_HTTP) || conn->bits.httpproxy) {
|
||||
if(data->set.useragent) {
|
||||
Curl_safefree(conn->allocptr.uagent);
|
||||
conn->allocptr.uagent =
|
||||
aprintf("User-Agent: %s\015\012", data->set.useragent);
|
||||
aprintf("User-Agent: %s\r\n", data->set.useragent);
|
||||
if(!conn->allocptr.uagent)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
conn->headerbytecount = 0;
|
||||
|
||||
#ifdef CURL_DO_LINEEND_CONV
|
||||
data->state.crlf_conversions = 0; /* reset CRLF conversion counter */
|
||||
#endif /* CURL_DO_LINEEND_CONV */
|
||||
|
||||
if(CURL_SOCKET_BAD == conn->sock[FIRSTSOCKET]) {
|
||||
bool connected = FALSE;
|
||||
for(;;) {
|
||||
/* loop for CURL_SERVER_CLOSED_CONNECTION */
|
||||
|
||||
/* Connect only if not already connected! */
|
||||
result = ConnectPlease(data, conn, hostaddr, &connected);
|
||||
if(CURL_SOCKET_BAD == conn->sock[FIRSTSOCKET]) {
|
||||
bool connected = FALSE;
|
||||
|
||||
if(connected) {
|
||||
result = Curl_protocol_connect(conn, protocol_done);
|
||||
if(CURLE_OK == result)
|
||||
conn->bits.tcpconnect = TRUE;
|
||||
/* Connect only if not already connected! */
|
||||
result = ConnectPlease(data, conn, hostaddr, &connected);
|
||||
|
||||
if(connected) {
|
||||
result = Curl_protocol_connect(conn, protocol_done);
|
||||
if(CURLE_OK == result)
|
||||
conn->bits.tcpconnect = TRUE;
|
||||
}
|
||||
else
|
||||
conn->bits.tcpconnect = FALSE;
|
||||
|
||||
/* if the connection was closed by the server while exchanging
|
||||
authentication informations, retry with the new set
|
||||
authentication information */
|
||||
if(conn->bits.proxy_connect_closed) {
|
||||
/* reset the error buffer */
|
||||
if (data->set.errorbuffer)
|
||||
data->set.errorbuffer[0] = '\0';
|
||||
data->state.errorbuf = FALSE;
|
||||
continue;
|
||||
}
|
||||
|
||||
if(CURLE_OK != result)
|
||||
return result;
|
||||
}
|
||||
else
|
||||
conn->bits.tcpconnect = FALSE;
|
||||
|
||||
|
||||
if(CURLE_OK != result)
|
||||
return result;
|
||||
}
|
||||
else {
|
||||
Curl_pgrsTime(data, TIMER_CONNECT); /* we're connected already */
|
||||
conn->bits.tcpconnect = TRUE;
|
||||
*protocol_done = TRUE;
|
||||
if(data->set.verbose)
|
||||
verboseconnect(conn);
|
||||
else {
|
||||
Curl_pgrsTime(data, TIMER_CONNECT); /* we're connected already */
|
||||
conn->bits.tcpconnect = TRUE;
|
||||
*protocol_done = TRUE;
|
||||
if(data->set.verbose)
|
||||
verboseconnect(conn);
|
||||
}
|
||||
/* Stop the loop now */
|
||||
break;
|
||||
}
|
||||
|
||||
conn->now = Curl_tvnow(); /* time this *after* the connect is done, we
|
||||
@@ -4031,7 +4092,7 @@ CURLcode Curl_async_resolved(struct connectdata *conn,
|
||||
|
||||
|
||||
CURLcode Curl_done(struct connectdata **connp,
|
||||
CURLcode status) /* an error if this is called after an
|
||||
CURLcode status, bool premature) /* an error if this is called after an
|
||||
error was detected */
|
||||
{
|
||||
CURLcode result;
|
||||
@@ -4071,7 +4132,7 @@ CURLcode Curl_done(struct connectdata **connp,
|
||||
|
||||
/* this calls the protocol-specific function pointer previously set */
|
||||
if(conn->curl_done)
|
||||
result = conn->curl_done(conn, status);
|
||||
result = conn->curl_done(conn, status, premature);
|
||||
else
|
||||
result = CURLE_OK;
|
||||
|
||||
@@ -4081,8 +4142,6 @@ CURLcode Curl_done(struct connectdata **connp,
|
||||
cancelled before we proceed */
|
||||
ares_cancel(data->state.areschannel);
|
||||
|
||||
ConnectionDone(conn); /* the connection is no longer in use */
|
||||
|
||||
/* if data->set.reuse_forbid is TRUE, it means the libcurl client has
|
||||
forced us to close this no matter what we think.
|
||||
|
||||
@@ -4090,8 +4149,7 @@ CURLcode Curl_done(struct connectdata **connp,
|
||||
closed in spite of all our efforts to be nice, due to protocol
|
||||
restrictions in our or the server's end */
|
||||
if(data->set.reuse_forbid || conn->bits.close) {
|
||||
CURLcode res2;
|
||||
res2 = Curl_disconnect(conn); /* close the connection */
|
||||
CURLcode res2 = Curl_disconnect(conn); /* close the connection */
|
||||
|
||||
*connp = NULL; /* to make the caller of this function better detect that
|
||||
this was actually killed here */
|
||||
@@ -4102,6 +4160,8 @@ CURLcode Curl_done(struct connectdata **connp,
|
||||
result = res2;
|
||||
}
|
||||
else {
|
||||
ConnectionDone(conn); /* the connection is no longer in use */
|
||||
|
||||
/* remember the most recently used connection */
|
||||
data->state.lastconnect = conn->connectindex;
|
||||
|
||||
@@ -4138,7 +4198,7 @@ CURLcode Curl_do(struct connectdata **connp, bool *done)
|
||||
infof(data, "Re-used connection seems dead, get a new one\n");
|
||||
|
||||
conn->bits.close = TRUE; /* enforce close of this connection */
|
||||
result = Curl_done(&conn, result); /* we are so done with this */
|
||||
result = Curl_done(&conn, result, FALSE); /* we are so done with this */
|
||||
|
||||
/* conn may no longer be a good pointer */
|
||||
|
||||
|
@@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -39,7 +39,7 @@ CURLcode Curl_async_resolved(struct connectdata *conn,
|
||||
bool *protocol_connect);
|
||||
CURLcode Curl_do(struct connectdata **, bool *done);
|
||||
CURLcode Curl_do_more(struct connectdata *);
|
||||
CURLcode Curl_done(struct connectdata **, CURLcode);
|
||||
CURLcode Curl_done(struct connectdata **, CURLcode, bool premature);
|
||||
CURLcode Curl_disconnect(struct connectdata *);
|
||||
CURLcode Curl_protocol_connect(struct connectdata *conn, bool *done);
|
||||
CURLcode Curl_protocol_connecting(struct connectdata *conn, bool *done);
|
||||
@@ -47,7 +47,7 @@ CURLcode Curl_protocol_doing(struct connectdata *conn, bool *done);
|
||||
void Curl_safefree(void *ptr);
|
||||
|
||||
/* create a connection cache */
|
||||
struct conncache *Curl_mk_connc(int type);
|
||||
struct conncache *Curl_mk_connc(int type, int amount);
|
||||
/* free a connection cache */
|
||||
void Curl_rm_connc(struct conncache *c);
|
||||
/* Change number of entries of a connection cache */
|
||||
|
@@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -35,6 +35,7 @@
|
||||
#define PORT_DICT 2628
|
||||
#define PORT_LDAP 389
|
||||
#define PORT_TFTP 69
|
||||
#define PORT_SSH 22
|
||||
|
||||
#define DICT_MATCH "/MATCH:"
|
||||
#define DICT_MATCH2 "/M:"
|
||||
@@ -109,6 +110,11 @@
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIBSSH2_H
|
||||
#include <libssh2.h>
|
||||
#include <libssh2_sftp.h>
|
||||
#endif /* HAVE_LIBSSH2_H */
|
||||
|
||||
/* Download buffer size, keep it fairly big for speed reasons */
|
||||
#undef BUFSIZE
|
||||
#define BUFSIZE CURL_MAX_WRITE_SIZE
|
||||
@@ -296,7 +302,7 @@ struct HTTP {
|
||||
***************************************************************************/
|
||||
typedef enum {
|
||||
FTP_STOP, /* do nothing state, stops the state machine */
|
||||
FTP_WAIT220, /* waiting for the inintial 220 response immediately after
|
||||
FTP_WAIT220, /* waiting for the initial 220 response immediately after
|
||||
a connect */
|
||||
FTP_AUTH,
|
||||
FTP_USER,
|
||||
@@ -304,6 +310,7 @@ typedef enum {
|
||||
FTP_ACCT,
|
||||
FTP_PBSZ,
|
||||
FTP_PROT,
|
||||
FTP_CCC,
|
||||
FTP_PWD,
|
||||
FTP_QUOTE, /* waiting for a response to a command sent in a quote list */
|
||||
FTP_RETR_PREQUOTE,
|
||||
@@ -392,6 +399,22 @@ struct ftp_conn {
|
||||
ftpstate state; /* always use ftp.c:state() to change state! */
|
||||
};
|
||||
|
||||
struct SSHPROTO {
|
||||
curl_off_t *bytecountp;
|
||||
char *user;
|
||||
char *passwd;
|
||||
char *path; /* the path we operate on */
|
||||
char *homedir;
|
||||
char *errorstr;
|
||||
#ifdef USE_LIBSSH2
|
||||
LIBSSH2_SESSION *ssh_session; /* Secure Shell session */
|
||||
LIBSSH2_CHANNEL *ssh_channel; /* Secure Shell channel handle */
|
||||
LIBSSH2_SFTP *sftp_session; /* SFTP handle */
|
||||
LIBSSH2_SFTP_HANDLE *sftp_handle;
|
||||
#endif /* USE_LIBSSH2 */
|
||||
};
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
* FILE unique setup
|
||||
***************************************************************************/
|
||||
@@ -463,8 +486,12 @@ struct ConnectBits {
|
||||
when Curl_done() is called, to prevent Curl_done() to
|
||||
get invoked twice when the multi interface is
|
||||
used. */
|
||||
bool stream_was_rewound; /* Indicates that the stream was rewound after a request
|
||||
read past the end of its response byte boundary */
|
||||
bool stream_was_rewound; /* Indicates that the stream was rewound after a
|
||||
request read past the end of its response byte
|
||||
boundary */
|
||||
bool proxy_connect_closed; /* set true if a proxy disconnected the
|
||||
connection in a CONNECT request with auth, so
|
||||
that libcurl should reconnect and continue. */
|
||||
};
|
||||
|
||||
struct hostname {
|
||||
@@ -477,12 +504,14 @@ struct hostname {
|
||||
/*
|
||||
* Flags on the keepon member of the Curl_transfer_keeper
|
||||
*/
|
||||
enum {
|
||||
KEEP_NONE,
|
||||
KEEP_READ,
|
||||
KEEP_WRITE
|
||||
};
|
||||
|
||||
#define KEEP_NONE 0
|
||||
#define KEEP_READ 1 /* there is or may be data to read */
|
||||
#define KEEP_WRITE 2 /* there is or may be data to write */
|
||||
#define KEEP_READ_HOLD 4 /* when set, no reading should be done but there
|
||||
might still be data to read */
|
||||
#define KEEP_WRITE_HOLD 8 /* when set, no writing should be done but there
|
||||
might still be data to write */
|
||||
|
||||
/*
|
||||
* This struct is all the previously local variables from Curl_perform() moved
|
||||
@@ -506,13 +535,6 @@ struct Curl_transfer_keeper {
|
||||
curl_off_t bytecount; /* total number of bytes read */
|
||||
curl_off_t writebytecount; /* number of bytes written */
|
||||
|
||||
long headerbytecount; /* only count received headers */
|
||||
long deductheadercount; /* this amount of bytes doesn't count when we check
|
||||
if anything has been transfered at the end of
|
||||
a connection. We use this counter to make only
|
||||
a 100 reply (without a following second response
|
||||
code) result in a CURLE_GOT_NOTHING error code */
|
||||
|
||||
struct timeval start; /* transfer started at this time */
|
||||
struct timeval now; /* current time */
|
||||
bool header; /* incoming data has HTTP header */
|
||||
@@ -592,7 +614,7 @@ struct Curl_async {
|
||||
within the source when we need to cast between data pointers (such as NULL)
|
||||
and function pointers. */
|
||||
typedef CURLcode (*Curl_do_more_func)(struct connectdata *);
|
||||
typedef CURLcode (*Curl_done_func)(struct connectdata *, CURLcode);
|
||||
typedef CURLcode (*Curl_done_func)(struct connectdata *, CURLcode, bool);
|
||||
|
||||
|
||||
/*
|
||||
@@ -647,6 +669,7 @@ struct HandleData {
|
||||
struct FILEPROTO *file;
|
||||
void *telnet; /* private for telnet.c-eyes only */
|
||||
void *generic;
|
||||
struct SSHPROTO *ssh;
|
||||
} proto;
|
||||
};
|
||||
|
||||
@@ -670,7 +693,6 @@ struct connectdata {
|
||||
particular struct has */
|
||||
long protocol; /* PROT_* flags concerning the protocol set */
|
||||
#define PROT_MISSING (1<<0)
|
||||
#define PROT_CLOSEACTION (1<<1) /* needs action before socket close */
|
||||
#define PROT_HTTP (1<<2)
|
||||
#define PROT_HTTPS (1<<3)
|
||||
#define PROT_FTP (1<<4)
|
||||
@@ -681,6 +703,11 @@ struct connectdata {
|
||||
#define PROT_FTPS (1<<9)
|
||||
#define PROT_SSL (1<<10) /* protocol requires SSL */
|
||||
#define PROT_TFTP (1<<11)
|
||||
#define PROT_SCP (1<<12)
|
||||
#define PROT_SFTP (1<<13)
|
||||
|
||||
#define PROT_CLOSEACTION PROT_FTP /* these ones need action before socket
|
||||
close */
|
||||
|
||||
/* 'dns_entry' is the particular host we use. This points to an entry in the
|
||||
DNS cache and it will not get pruned while locked. It gets unlocked in
|
||||
@@ -709,6 +736,13 @@ struct connectdata {
|
||||
unsigned short remote_port; /* what remote port to connect to,
|
||||
not the proxy port! */
|
||||
|
||||
long headerbytecount; /* only count received headers */
|
||||
long deductheadercount; /* this amount of bytes doesn't count when we check
|
||||
if anything has been transfered at the end of
|
||||
a connection. We use this counter to make only
|
||||
a 100 reply (without a following second response
|
||||
code) result in a CURLE_GOT_NOTHING error code */
|
||||
|
||||
char *user; /* user name string, allocated */
|
||||
char *passwd; /* password string, allocated */
|
||||
|
||||
@@ -802,8 +836,10 @@ struct connectdata {
|
||||
struct sockaddr_in local_addr;
|
||||
#endif
|
||||
|
||||
bool readchannel_inuse; /* whether the read channel is in use by an easy handle */
|
||||
bool writechannel_inuse; /* whether the write channel is in use by an easy handle */
|
||||
bool readchannel_inuse; /* whether the read channel is in use by an easy
|
||||
handle */
|
||||
bool writechannel_inuse; /* whether the write channel is in use by an easy
|
||||
handle */
|
||||
bool is_in_pipeline; /* TRUE if this connection is in a pipeline */
|
||||
|
||||
struct curl_llist *send_pipe; /* List of handles waiting to
|
||||
@@ -1067,8 +1103,6 @@ struct DynamicStatic {
|
||||
changed after the connect phase, as we allow callback
|
||||
to change it and if so, we reconnect to use the new
|
||||
URL instead */
|
||||
char *proxy; /* work proxy, copied from UserDefined */
|
||||
bool proxy_alloc; /* http proxy string is malloc()'ed */
|
||||
char *referer; /* referer string */
|
||||
bool referer_alloc; /* referer sting is malloc()ed */
|
||||
struct curl_slist *cookielist; /* list of cookie files set by
|
||||
@@ -1097,7 +1131,7 @@ struct UserDefined {
|
||||
void *in; /* the uploaded file is read from here */
|
||||
void *writeheader; /* write the header to this if non-NULL */
|
||||
char *set_url; /* what original URL to work on */
|
||||
char *set_proxy; /* proxy to use */
|
||||
char *proxy; /* proxy to use */
|
||||
long use_port; /* which port to use (when not using default) */
|
||||
char *userpwd; /* <user:password>, if used */
|
||||
long httpauth; /* what kind of HTTP authentication to use (bitmask) */
|
||||
@@ -1173,7 +1207,6 @@ struct UserDefined {
|
||||
struct curl_slist *telnet_options; /* linked list of telnet options */
|
||||
curl_TimeCond timecondition; /* kind of time/date comparison */
|
||||
time_t timevalue; /* what time to compare with */
|
||||
curl_closepolicy closepolicy; /* connection cache close concept */
|
||||
Curl_HttpReq httpreq; /* what kind of HTTP request (if any) is this */
|
||||
char *customrequest; /* HTTP/FTP request to use */
|
||||
long httpversion; /* when non-zero, a specific HTTP version requested to
|
||||
@@ -1241,6 +1274,8 @@ struct UserDefined {
|
||||
bool reuse_fresh; /* do not re-use an existing connection */
|
||||
bool ftp_use_epsv; /* if EPSV is to be attempted or not */
|
||||
bool ftp_use_eprt; /* if EPRT is to be attempted or not */
|
||||
bool ftp_use_ccc; /* if CCC is to be attempted or not */
|
||||
|
||||
curl_ftpssl ftp_ssl; /* if AUTH TLS is to be attempted etc */
|
||||
curl_ftpauth ftpsslauth; /* what AUTH XXX to be attempted */
|
||||
bool no_signal; /* do not use any signal/alarm handler */
|
||||
@@ -1250,6 +1285,11 @@ struct UserDefined {
|
||||
bool ftp_skip_ip; /* skip the IP address the FTP server passes on to
|
||||
us */
|
||||
bool connect_only; /* make connection, let application use the socket */
|
||||
long ssh_auth_types; /* allowed SSH auth types */
|
||||
char *ssh_public_key; /* the path to the public key file for
|
||||
authentication */
|
||||
char *ssh_private_key; /* the path to the private key file for
|
||||
authentication */
|
||||
};
|
||||
|
||||
struct Names {
|
||||
|
@@ -45,6 +45,11 @@
|
||||
#include <iconv.h>
|
||||
#endif
|
||||
|
||||
#ifdef USE_LIBSSH2
|
||||
#include <libssh2.h>
|
||||
#endif
|
||||
|
||||
|
||||
char *curl_version(void)
|
||||
{
|
||||
static char version[200];
|
||||
@@ -88,6 +93,11 @@ char *curl_version(void)
|
||||
left -= len;
|
||||
ptr += len;
|
||||
#endif
|
||||
#ifdef USE_LIBSSH2
|
||||
len = snprintf(ptr, left, " libssh2/%s", LIBSSH2_VERSION);
|
||||
left -= len;
|
||||
ptr += len;
|
||||
#endif
|
||||
|
||||
return version;
|
||||
}
|
||||
@@ -125,6 +135,12 @@ static const char * const protocols[] = {
|
||||
"ftps",
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef USE_LIBSSH2
|
||||
"scp",
|
||||
"sftp",
|
||||
#endif
|
||||
|
||||
NULL
|
||||
};
|
||||
|
||||
@@ -179,10 +195,15 @@ static curl_version_info_data version_info = {
|
||||
0, /* c-ares version numerical */
|
||||
NULL, /* libidn version */
|
||||
0, /* iconv version */
|
||||
NULL, /* ssh lib version */
|
||||
};
|
||||
|
||||
curl_version_info_data *curl_version_info(CURLversion stamp)
|
||||
{
|
||||
#ifdef USE_LIBSSH2
|
||||
static char ssh_buffer[80];
|
||||
#endif
|
||||
|
||||
#ifdef USE_SSL
|
||||
static char ssl_buffer[80];
|
||||
Curl_ssl_version(ssl_buffer, sizeof(ssl_buffer));
|
||||
@@ -217,6 +238,11 @@ curl_version_info_data *curl_version_info(CURLversion stamp)
|
||||
#endif /* _LIBICONV_VERSION */
|
||||
#endif
|
||||
|
||||
#ifdef USE_LIBSSH2
|
||||
snprintf(ssh_buffer, sizeof(ssh_buffer), "libssh2/%s", LIBSSH2_VERSION);
|
||||
version_info.libssh_version = ssh_buffer;
|
||||
#endif
|
||||
|
||||
(void)stamp; /* avoid compiler warnings, we don't use this */
|
||||
|
||||
return &version_info;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user