Compare commits

..

254 Commits

Author SHA1 Message Date
Daniel Stenberg
c96f7f13da 7.11.2 coming today 2004-04-26 06:05:49 +00:00
Daniel Stenberg
1bdc4b2006 updated the warning text when SSL is explicitly disabled 2004-04-25 15:23:23 +00:00
Daniel Stenberg
3915fecf80 USE_MANUAL is now defined by default 2004-04-25 15:21:16 +00:00
Daniel Stenberg
f94f06825c moved older changes to the CHANGES.2003 file 2004-04-25 08:33:06 +00:00
Daniel Stenberg
2ddbf8975a disable-manual 2004-04-25 08:19:55 +00:00
Daniel Stenberg
68a3cbe384 make the generated hugehelp.c file use the USE_MANUAL define so that it
will be properly built with configure --disable-manual even if the source
file is already present
2004-04-25 08:13:07 +00:00
Daniel Stenberg
b9432d1296 test164 HTTP range with multiple ranges 2004-04-24 09:33:25 +00:00
Daniel Stenberg
e202a29a9a removed a memory leak when doing a windows threaded resolve and it failed 2004-04-23 14:10:29 +00:00
Daniel Stenberg
3755bffcc2 Gisle Vanem found and fixed a memory leak when doing (failing) Windows
threaded name resolves.
2004-04-23 14:04:30 +00:00
Daniel Stenberg
2a0a305300 only a minor comment/format change 2004-04-23 11:00:47 +00:00
Daniel Stenberg
70e2aadc18 Replaced Curl_FormReadOneLine with Curl_formpostheader as that is the only use
for it. It saves one extra copy of the header.

I also added comments for several functions in formdata.c
2004-04-23 10:37:52 +00:00
Daniel Stenberg
a1c8aaf666 o --proxy-ntlm now checks if libcurl supports NTLM before using it
o minor --fail with authentication bugfix
2004-04-23 08:50:28 +00:00
Daniel Stenberg
8ee470aaeb --proxy-ntlm fix and test case 163 2004-04-23 08:47:20 +00:00
Daniel Stenberg
37e4858cd0 Made --proxy-ntlm check if the underlying library actually supports NTLM 2004-04-23 08:44:27 +00:00
Daniel Stenberg
a27072bebb minor format fix 2004-04-23 08:40:20 +00:00
Daniel Stenberg
47059f45fe added test 163 - a simple test case that use -F field<file, to verify that
we can pass on "odd" characters (newline, CR, tab) like this.
2004-04-23 08:40:11 +00:00
Daniel Stenberg
daced8041d No longer uses the valgrind option '--logfile-fd', we use the --logfile
option instead (even though it appends the pid to the file name, making it
harder to figure out its name to parse it after a test has run).

Also made sure we only use valgrind for the actual test command command lines,
not when for example running curl to detect if there are any already running
servers are present etc.
2004-04-23 08:38:43 +00:00
Daniel Stenberg
b053ae6a65 define the obsolete options to different values to prevent "duplicate case"
situtations in bindings that still have switch() cases for them
2004-04-23 06:29:41 +00:00
Daniel Stenberg
42f60ecb36 require SSL as otherwise NTLM doesn't work! 2004-04-23 06:04:52 +00:00
Daniel Stenberg
550862f41a missing brace 2004-04-22 21:27:32 +00:00
Daniel Stenberg
6838f74fe0 allow newlines in the contents when doing -F "var=[contents]"
Robert Marlow reported.
2004-04-22 20:09:33 +00:00
Daniel Stenberg
2ff30d067c - David Byron found and fixed a small bug with the --fail and authentication
stuff added a few weeks ago.  Turns out that if you specify --proxy-ntlm and
  communicate with a proxy that requires basic authentication, the proxy
  properly returns a 407, but the failure detection code doesn't realize it
  should give up, so curl returns with exit code 0. Test case 162 verifies
  this.
2004-04-22 20:07:41 +00:00
Daniel Stenberg
84406b3e2c allow newlines in the contents when doing -F "var=[contents]" 2004-04-22 15:26:30 +00:00
Daniel Stenberg
c323969bdd removed Curl_ftp_quit() as it was turned into a static in ftp.c 2004-04-22 13:15:17 +00:00
Daniel Stenberg
43cbbdbea0 If a transfer is found out to be only partial, libcurl will now treat that
as a problem serious enough to skip the final QUIT command before closing
the control connection. To avoid the risk that it will "hang" waiting for
the QUIT response. Added test case 161 to verify this.
2004-04-22 13:10:43 +00:00
Daniel Stenberg
1d3f76df71 If only a partial file was transfered, we consider that a fatal problem so
we won't try to QUIT the control connection and risk "hanging" waiting for
a response. Test case 161 verifies this. The quit-sending function was
also made static.
2004-04-22 13:09:00 +00:00
Daniel Stenberg
33cb93ad0b Added comments 2004-04-22 12:35:45 +00:00
Daniel Stenberg
4dc9179f4b modified how valgrind is run to make sure that file handle 3 exists when
we tell valgrind to use that to send the logfile to
2004-04-22 10:33:55 +00:00
Daniel Stenberg
26a5ec9aa0 danish mirror 2004-04-22 08:54:34 +00:00
Daniel Stenberg
883ea3113c Gisle's items 2004-04-21 19:35:06 +00:00
Daniel Stenberg
62b7c08bb3 include unistd.h as well for the close() proto on some platforms (like Tru64) 2004-04-21 11:18:42 +00:00
Daniel Stenberg
a85fa66cc8 typecast the tolower() argument to an int to prevent compiler warning 2004-04-21 11:15:35 +00:00
Daniel Stenberg
9ba010c629 typecast tolower/toupper arguments to int to make picky compilers complain
less
2004-04-21 11:15:02 +00:00
Daniel Stenberg
3ef3f2b6f0 test case 160 "should work" now 2004-04-21 08:56:02 +00:00
Daniel Stenberg
1401d909e8 Fix the "lingering close" problem when re-using a connection, as test case
160 shows.

We got no data and we attempted to re-use a connection. This might happen if
the connection was left alive when we were done using it before, but that was
closed when we wanted to read from it again. Bad luck. Retry the same request
on a fresh connect!

Deleted the sockerror variable again, it serves no purpose anymore.
2004-04-21 08:49:14 +00:00
Daniel Stenberg
3233322622 increase the headerbytecount for incoming "headers" 2004-04-21 08:47:57 +00:00
Daniel Stenberg
e373f1fd73 log the WAIT command 2004-04-21 06:56:54 +00:00
Daniel Stenberg
dc25cd6f3a cleanup leftovers 2004-04-20 09:46:10 +00:00
Daniel Stenberg
0e31d41d4e test160 - for a more controlled testing of the case where libcurl starts
to re-use a connection that is closed when re-used and libcurl should then
make a new fresh connection and use instead
2004-04-20 08:35:37 +00:00
Daniel Stenberg
b7a7600465 Cleaned up hostname/name/gname and path/ppath confusion. Removed the fixed-
length limit of the hostname part of the URL.
2004-04-20 07:53:24 +00:00
Daniel Stenberg
111a2f3057 new mirror and one that changed domain 2004-04-20 07:52:16 +00:00
Daniel Stenberg
760cecac8d make the first response get a "connection: close" header as that is how
most 1.1 connections will be closed. The case where it gets closed anyway
is subject for a new separate test.
2004-04-20 07:36:09 +00:00
Daniel Stenberg
6f8b4395ec changed the logging to work when the logfile is removed during testing 2004-04-19 15:20:30 +00:00
Daniel Stenberg
5506f8767c Make the server include "Connection: close" in the headers of the replies
it actually will close. This is after all what HTTP 1.1 says a server should
do.
2004-04-19 08:41:36 +00:00
Daniel Stenberg
5887945828 Gisle Vanem corrected a mistake in a recent progress fix 2004-04-19 07:18:26 +00:00
Daniel Stenberg
25e98179be Gisle Vanem: patches to make sws.c compile under MingW/MSVC is
attached. And some cosmetic fixes.
2004-04-17 11:38:41 +00:00
Daniel Stenberg
78ebe3fa5a Gisle made a failed connect output the reason for it 2004-04-17 11:33:47 +00:00
Daniel Stenberg
a8e8e51b14 NDEBUG should not be defined when CURLDEBUG is 2004-04-17 11:33:14 +00:00
Daniel Stenberg
f97d194934 adding issue 36 to be fixed before release 2004-04-16 07:33:53 +00:00
Daniel Stenberg
4661cc7403 don't display the . and .. files when dumping the log/ contents 2004-04-16 07:02:17 +00:00
Daniel Stenberg
bc11929395 remade the logging function to better deal with removed logfiles during
the execution of the tests
2004-04-16 07:01:47 +00:00
Daniel Stenberg
caf37bc92e issue 31 - fix windows multi interface is now corrected 2004-04-15 15:05:48 +00:00
Daniel Stenberg
5de447b0cb clarified that select() timeouts should always remain rather short 2004-04-15 15:05:12 +00:00
Daniel Stenberg
5dbaced4a2 my test suite edits 2004-04-15 14:53:47 +00:00
Daniel Stenberg
43f8a1f5de change the log format to look similar to sws
added various logging info
2004-04-15 13:55:37 +00:00
Daniel Stenberg
f57efa1899 clean the log directory between each single test, so that we can better
display all logs and only logs with relevant data when a test fails and -p
is used.
2004-04-15 13:37:19 +00:00
Daniel Stenberg
592522ceaf ftp->dirs[] is no longer terminated with a zero entry but ftp->dirdepth
should be used
2004-04-15 10:43:40 +00:00
Daniel Stenberg
4f84e6d9e2 removed the fixed dir depth limit in the FTP code 2004-04-15 07:52:39 +00:00
Daniel Stenberg
6f08903f07 two ipresolve fixes 2004-04-14 12:13:32 +00:00
Daniel Stenberg
220cd010bd format fix 2004-04-14 12:13:21 +00:00
Daniel Stenberg
68e8a0f0d9 asking for CURL_IPRESOLVE_V6 when ipv6 addresses can't be resolved will
now cause the resolve function to return NULL immediately
2004-04-14 12:10:44 +00:00
Daniel Stenberg
b23dbf9f34 Gisle Vanem made the -4/-6 actually get set too 2004-04-14 12:00:53 +00:00
Daniel Stenberg
1d0b5b507a Curl_wait_for_resolv() could hang due to the bad timeout timer resolution and
some bad thinking on my part.
2004-04-14 11:43:26 +00:00
Daniel Stenberg
b83d8104cd several changes 2004-04-14 07:07:30 +00:00
Daniel Stenberg
bf6e1053cf display interesting log files on failure, if -p is used 2004-04-14 07:04:45 +00:00
Daniel Stenberg
c3dd928e29 enable verbose as well 2004-04-14 06:53:34 +00:00
Daniel Stenberg
aba6c2b89d Added test case 511 in an attempt to repeat bug report #934666 "storage leak
in ftp.c", but it shows no leaking.
2004-04-14 06:30:37 +00:00
Daniel Stenberg
9c0a386246 minor format fix 2004-04-13 14:34:12 +00:00
Daniel Stenberg
bba3bb7556 eh, these can't be used for poll()! ;-) 2004-04-13 14:31:49 +00:00
Daniel Stenberg
c1422864b5 additional info 2004-04-13 14:27:47 +00:00
Daniel Stenberg
31a693b99a Gisle Vanem's fix that makes the multi interface work on Windows again even
when not using ares.
2004-04-13 13:59:12 +00:00
Daniel Stenberg
804534fbc9 spell fixes 2004-04-13 11:03:02 +00:00
Daniel Stenberg
1bc6532c16 more news 2004-04-13 10:58:44 +00:00
Daniel Stenberg
b48bf7470d proper typecast to prevent compiler warning 2004-04-13 10:42:32 +00:00
Daniel Stenberg
1ca9ce5ef4 removed the BUGS section since it offers nothing good 2004-04-13 09:08:52 +00:00
Daniel Stenberg
789f2ecbe7 1.2.0 2004-04-13 07:44:26 +00:00
Daniel Stenberg
ee7d1d0701 remove an long time #defined struct member and use the actual "real" name
instead to make it easier to find/read
2004-04-13 07:37:28 +00:00
Daniel Stenberg
4e3aa250c4 Moved the 'tcp_nodelay' member to the proper 'UserDefined' struct within the
sessionhandle to make the duphandle() function work as supposed. Also tried
to start document functions the doxygen way (in the headers of the functions).
Can't make it work though...
2004-04-13 07:16:26 +00:00
Daniel Stenberg
3647a6ddcd move issue 35 (hostip.c cleanup) forward, I don't feel like doing that now 2004-04-13 06:13:41 +00:00
Daniel Stenberg
79aaa85a51 full-test passes -p to runtests as well to get more details in case of failure 2004-04-13 05:58:19 +00:00
Daniel Stenberg
392a543eff Initial support for dumping the contents of the files in log/ when failing
when -p is used. For easier bug-hunting of autobuild failures. This still
only shows what files that are present in log/, as I believe we need to
filter which files we show on a failure.
2004-04-13 05:57:50 +00:00
Daniel Stenberg
eb6345de60 somewhat safer typecasting in case sizeof(long) != sizeof(void *) (is there
even such platforms?)
2004-04-12 06:55:25 +00:00
Daniel Stenberg
0fd3b7a00a David Byron's patch for MSVC builds with zlib 2004-04-11 20:25:10 +00:00
Daniel Stenberg
bd51b80fa5 updated to not include the msvc-generated files 2004-04-11 06:33:02 +00:00
Daniel Stenberg
15c900839b when checked out from CVS, run this to generate the proper scripts 2004-04-11 06:32:41 +00:00
Daniel Stenberg
2fd463e979 Dirk Manske increased the resolution for what the CURLINFO_*_TIME return. 2004-04-09 09:36:31 +00:00
Daniel Stenberg
de8660a96a we're working on 1.2.0 now 2004-04-08 18:10:03 +00:00
Daniel Stenberg
1e9cb272f1 added test 159, use --ntlm together with -0 2004-04-07 15:01:11 +00:00
Daniel Stenberg
72b1144b8c getting only a 100 Continue response and nothing else, when talking HTTP,
is now treated as an error by libcurl
2004-04-07 14:27:54 +00:00
Daniel Stenberg
348fe0e210 --limit-rate using -d or -F does not work 2004-04-07 14:03:13 +00:00
Daniel Stenberg
cf1f46e1ca renamed the strtoofft() macro to curlx_strtoofft() to adjust to the curlx_*
concept, and added lib/README.curlx to explain details about it
2004-04-07 07:30:40 +00:00
Daniel Stenberg
f052cbee19 Use curl_off_t for the limit rate values to support REALLY huge values on
such platforms that support large files.
2004-04-07 07:23:52 +00:00
Daniel Stenberg
1f5e8670e1 mention getting windows builds to work after rearrangements 2004-04-06 15:30:57 +00:00
Daniel Stenberg
3b491d0f73 Moved long-standing issues over from TODO-RELEASE to the more long-term TODO
file.
2004-04-06 15:29:01 +00:00
Daniel Stenberg
26a2b8d26d the memory leak on windows have been addressed 2004-04-06 15:22:21 +00:00
Daniel Stenberg
a7fd6f9007 require ssl since ntlm needs it 2004-04-06 15:16:07 +00:00
Daniel Stenberg
8ed44e8dfb New authentication code added, particularly noticable when doing POST or PUT
with Digest or NTLM. libcurl will now use HEAD to negotiate the authentication
and when done perform the requested POST.
2004-04-06 15:14:10 +00:00
Daniel Stenberg
f617c1131a mention the man page updates from the other day 2004-04-06 15:12:50 +00:00
Daniel Stenberg
5ca47f19d7 the pack_hostent() proto isn't used/needed with ipv6 is enabled.
time to restructure this source file!
2004-04-06 15:09:43 +00:00
Daniel Stenberg
9044fcbb5f Gisle Vanem's fix for bug item #927979 reported by Nathan O'Sullivan.
Good enough?
2004-04-06 14:51:14 +00:00
Daniel Stenberg
7a82810b59 Added the curl source header and changed some comments 2004-04-06 14:07:04 +00:00
Daniel Stenberg
0ccdf3d0e6 improved --limit-rate functionality, partly by the new use of curlx_tvnow() 2004-04-06 12:06:05 +00:00
Daniel Stenberg
ca7f0852df Gisle Vanem caught me breaking the windows version of Curl_strerror() 2004-04-06 12:02:36 +00:00
Daniel Stenberg
780b962336 provide these functions as curlx_* ones as this enables the curl app to
re-use these sources and functions for subsecond resolution timing
2004-04-06 10:15:10 +00:00
Daniel Stenberg
bbeb840916 up-to-date with reality 2004-04-06 07:59:11 +00:00
Daniel Stenberg
f4ec465bfc added HAVE_GETTIMEOFDAY, we need it for better time resolution 2004-04-06 07:49:57 +00:00
Daniel Stenberg
57c86a953d typecasts to please picky compilers checking the printf() format string 2004-04-06 07:48:29 +00:00
Daniel Stenberg
0fff8656e9 one change, three bugs, one credit 2004-04-06 06:24:37 +00:00
Daniel Stenberg
7b929636ee the last couple of days 2004-04-06 06:24:06 +00:00
Daniel Stenberg
76835a2e00 two issues to fix before 7.11.2, one issue to fix befor 7.12.0 2004-04-06 06:18:48 +00:00
Daniel Stenberg
1b171b02ac remove the general use of sys_nerr 2004-04-06 06:06:10 +00:00
Daniel Stenberg
a8dc362572 generated files, no need to keep in CVS 2004-04-05 12:38:54 +00:00
Daniel Stenberg
7c72f8ee6c prepend the man3 dir to the file name to work better.
Robin Kay pointed this out.
2004-04-02 11:04:34 +00:00
Daniel Stenberg
c39a54609b edits, mainly to make the generated html output nicer 2004-04-02 09:56:01 +00:00
Daniel Stenberg
ce6b767b47 minor edits 2004-04-02 09:50:42 +00:00
Daniel Stenberg
7ba4d3464f Dirk Manske's feedback:
* bring back subsecond resolution to CURLINFO_TOTAL_TIME
* Fix the Curl_pgrsDone() so that the final progress update is shown properly
2004-04-02 07:32:03 +00:00
Daniel Stenberg
03def138fe Andrs Garca's updated mingw makefiles 2004-04-02 07:18:13 +00:00
Daniel Stenberg
9d99af5329 if select returns -1, bail out of the loop 2004-04-02 06:40:31 +00:00
Daniel Stenberg
c8d850dbad Only check that the c-ares lib is valid if we don't use the "embedded"
directory. The provided ares dir is probably up-to-date, but more importantly
it is often not built yet at the time when this configure script runs.
2004-04-01 10:26:59 +00:00
Daniel Stenberg
01ea357744 When ares is enabled, we now check for the ares_cancel function to verify
that we use a library that is recent enough to build with the latest libcurl.
2004-04-01 09:10:33 +00:00
Daniel Stenberg
ad9e83a90f Dirk Manske's fix that makes sure we cancel the ares resolve when we time out
from a name resolve. Without this, we leak memory!
2004-04-01 08:40:36 +00:00
Daniel Stenberg
6c9d96e811 Dirk Manske's ares_cancel() function was added. 2004-04-01 08:25:58 +00:00
Daniel Stenberg
f840e5192c edited slightly, point out our new mailinglist 2004-04-01 08:25:23 +00:00
Daniel Stenberg
ba9272dd05 remind us about cvs tagging when we've built a release archive 2004-04-01 08:23:26 +00:00
Daniel Stenberg
675db3a211 removed my previously attempted fix for ares timeouts, not needed 2004-04-01 07:04:58 +00:00
Daniel Stenberg
1fc7ff878e Applied Joe Halpin's bugfixes to the NI_WITHSCOPEID test program. 2004-04-01 06:53:11 +00:00
Daniel Stenberg
b643d148b1 Dominick Meglio man page fixes 2004-04-01 06:10:56 +00:00
Daniel Stenberg
5804c995e1 Use the new HAVE_NI_WITHSCOPEID define instead of merely checking for the
existance of NI_WITHSCOPEID since some platforms have that define but still
can't function with it set.
2004-03-31 21:33:52 +00:00
Daniel Stenberg
13a6f85320 issue 30, digest re-negotiate works now! 2004-03-31 21:04:26 +00:00
Daniel Stenberg
8b4582f111 recent changes 2004-03-31 21:03:55 +00:00
Daniel Stenberg
cd3bf7c56f updates and David Byron's spellfix 2004-03-31 21:01:20 +00:00
Daniel Stenberg
ee1595dcd5 Roy Shan fixed a case that prevented ares name resolve timeouts to occur. 2004-03-31 20:50:01 +00:00
Daniel Stenberg
310086deed we're working on 7.11.2-CVS right now 2004-03-31 20:22:28 +00:00
Daniel Stenberg
5d27f50f2f HAVE_NI_WITHSCOPEID spelled right! 2004-03-31 20:13:53 +00:00
Daniel Stenberg
9d0330d5bd Remove the elapsed time from the most recent select() only. 2004-03-31 13:19:41 +00:00
Daniel Stenberg
d5074f74bb The asynch name resolve methods now all use CURL_TIMEOUT_RESOLVE for
the specific time to wait for a resolve. The definition is at the top of
this source file.
2004-03-31 12:55:24 +00:00
Daniel Stenberg
ea0cf7c87b Dirk Manske found out the Curl_wait_for_resolv() timed out too early. 2004-03-31 12:45:26 +00:00
Daniel Stenberg
a56164c8e0 added swsbounce 2004-03-31 12:24:08 +00:00
Daniel Stenberg
cd95bb22ea added include to fix warning 2004-03-31 11:55:56 +00:00
Daniel Stenberg
1745ecd8ac * Fixed a memory leak when doing repeated re-negotiations.
* Made the incoming line parser more forgiving to allow "name=contents" pairs
where the contents isn't within double quotes.
* Made the digest code return CURLDIGEST_BADALGO if a requested algorithm
isn't supported by the code.
2004-03-31 11:55:07 +00:00
Daniel Stenberg
75d66b9c62 test 153 tests Digest authorization and stale=true stuff 2004-03-31 11:51:21 +00:00
Daniel Stenberg
2ff9f55001 Added "swsbounce" magic: if this keyword is present in a <data> section it
sets the "swsbounce" magic mode. If there follows a request for the SAME
test number and the SAME part number, this mode will make the server bump
the part number internally and thus return a different <dataNUM> section
than it otherwise would.

Test case 153 uses this in case you need an example. It is pretty involved
and hard-to-use, but then the situation is pretty special over all. Enjoy.
2004-03-31 11:50:44 +00:00
Daniel Stenberg
ce446dbdc2 Moved the NI_WITHSCOPEID magic #ifdef to the top of the file and made sure
we use the NIFLAGS properly on both places in the code that use getnameinfo().
2004-03-31 10:59:48 +00:00
Daniel Stenberg
dd2add82ee Fixed how the user name is extracted from http_proxy environment variable
when set.
2004-03-31 10:46:06 +00:00
Daniel Stenberg
40d9855df2 Andrs Garca fixed a warning in the ioctlsocket() usage. 2004-03-31 10:34:53 +00:00
Daniel Stenberg
ecf7adba15 modified the NI_WITHSCOPEID to use an AF_INET6 socket immediately and
added some more debug output to make it easier to detect failure reasons
in the autobuild logs
2004-03-31 10:31:08 +00:00
Daniel Stenberg
931c847e2b CURLDIGEST_BADALGO is a new return code from the digest code 2004-03-31 09:20:27 +00:00
Daniel Stenberg
8230d9bff8 Dominick Meglio fixed a missing comma 2004-03-31 06:10:40 +00:00
Daniel Stenberg
64cc14e9e6 one issue less 2004-03-30 15:35:09 +00:00
Daniel Stenberg
d5b8971ff3 typecast setsockopt()'s 4th argument to void * to make compilers complain
less
2004-03-30 13:05:45 +00:00
Daniel Stenberg
7ea837a18c adjusted to the new dns cache function to hide more hostip internals 2004-03-30 13:02:31 +00:00
Daniel Stenberg
b8b8473b6d Lots of comments added an clarified. Added timeout for the ares version
of Curl_is_resolved() to address Roy Shan's reported problem.
2004-03-30 13:02:07 +00:00
Daniel Stenberg
894dbae455 added stale boolean to the digest struct 2004-03-30 13:00:53 +00:00
Daniel Stenberg
2c11425868 first attempt to support stale=true 2004-03-30 13:00:32 +00:00
Daniel Stenberg
a2ea0abf7f Added CURL_CHECK_NI_WITHSCOPEID that checks if NI_WITHSCOPEID exists and
works. No code actually uses the HAVE_NI_WITHSCOPEID (that a positive test
results in), but this is still only for testing purposes.
2004-03-30 10:35:54 +00:00
Daniel Stenberg
be8f8e66a4 Dominick Meglio's new ares_expand_string() function 2004-03-30 09:06:42 +00:00
Daniel Stenberg
9fadfffb9d when checking the automake version, cut off trailing "-p[whatever]" from the
version string before doing the version number checks.
2004-03-30 08:28:39 +00:00
Daniel Stenberg
76f23acfa1 if 0'ed out a code section that uses __FUNCTION__ etc, used for debugging
the new "fail with auth" code
2004-03-30 08:21:09 +00:00
Daniel Stenberg
6950aeafcc init the dns pointer to NULL for clarity 2004-03-30 08:14:37 +00:00
Daniel Stenberg
cd160a66c9 added more comments for what the functions return 2004-03-30 08:11:54 +00:00
Daniel Stenberg
a7376968d2 mention the fact that you can append a new CA cert to the existing bundle too 2004-03-30 06:46:36 +00:00
Daniel Stenberg
fd96a2af34 David Byron's patch was appplied to make CURLOPT_FAILONERROR work nicely
even with authentcations such as NTLM or Digest enabled. Test cases 150, 151
and 152 were added to verify the functionality.
2004-03-30 06:42:12 +00:00
Daniel Stenberg
a90cd1a45c David Byron's new test cases for the --fail and auth stuff. 2004-03-30 06:41:33 +00:00
Daniel Stenberg
8e92600ddd David Byron made CURLOPT_FAILONERROR work with authentications such as NTLM
or Digest.
2004-03-30 06:40:01 +00:00
Daniel Stenberg
5e75c310ba 'authdone' was added to the sessionhandle and thus was removed from the
argument to the NTLM function(s)
2004-03-30 06:39:24 +00:00
Daniel Stenberg
20cab07c29 David Byron added 'authdone' to the SessionHandle. 2004-03-30 06:38:52 +00:00
Daniel Stenberg
f466d7a6f1 these are now in the packages/vms dir 2004-03-29 22:45:14 +00:00
Daniel Stenberg
dc46f535ae The select() timeout is better not static since some implementation actually
might change it. I don't *think* it does it when the timeout is 0,0 but it
is better to be sure...
2004-03-29 21:29:24 +00:00
Daniel Stenberg
27fd5d6d6a issue 24 is fixed by making sure the time fields use a static width 2004-03-29 13:46:58 +00:00
Daniel Stenberg
18a3c3302f several noticable recent changes 2004-03-29 13:46:16 +00:00
Daniel Stenberg
97959a00d7 changes changes changes 2004-03-29 13:45:53 +00:00
Daniel Stenberg
5e92b2906b All test targets now run 'make all' before they prcoeed with the actual
testing so that all test files are build first properly. David Byron reported.
2004-03-29 12:38:41 +00:00
Daniel Stenberg
126ed14313 Gisle Vanem's djgpp/MS-DOS updates 2004-03-29 12:29:25 +00:00
Daniel Stenberg
712d0374f7 fix to figure out the "real" windows path when built and run with mingw
Andrs Garca helped out!
2004-03-29 09:26:31 +00:00
Daniel Stenberg
4b49b2e3cf re-indented to use curl-standard source formatting 2004-03-29 07:25:59 +00:00
Daniel Stenberg
d85c21994f netinet/tcp.h may require netinet/in.h to be include before 2004-03-29 06:22:57 +00:00
Daniel Stenberg
6b33a5f954 use the correct struct 2004-03-28 21:41:10 +00:00
Daniel Stenberg
ed22afe5fb Tor fixed a left-over from the ip argument to setnodelay 2004-03-27 11:15:50 +00:00
Daniel Stenberg
843391c745 Gisle Vanem:
A patch to bypass MS' sillyness with regard to IPv6 and getaddrinfo().

The CURLDEBUG part is to avoid redefinition warning caused by memdebug.h. If
ENABLE_IPV6 isn't enabled, it doesn't matter since we never call
getaddrinfo(). Allthough we could to support weird protocols like SOCK_RDM
that Win-2K/XP has.
2004-03-26 13:47:46 +00:00
Daniel Stenberg
ad6699e0c4 some more password blurb 2004-03-26 13:20:28 +00:00
Daniel Stenberg
43137cf595 check for netinet/tcp.h precense before actually including it 2004-03-26 07:10:15 +00:00
Daniel Stenberg
db6dc49b0b removed the ip number from the notcpdelay function 2004-03-26 07:03:30 +00:00
Daniel Stenberg
593170d1de get the version number from the new curlver.h header file 2004-03-25 16:03:41 +00:00
Daniel Stenberg
0eace2fefe localtime and gmtime are not thread-safe on newer AIXes either so we force
a check for there *_r-versions too
2004-03-25 15:48:54 +00:00
Daniel Stenberg
abd65e21c6 force recent AIX versions to check for strerror_r 2004-03-25 15:10:01 +00:00
Daniel Stenberg
e21104a865 only output one line about the nodelay even if it fails 2004-03-25 14:01:01 +00:00
Daniel Stenberg
3ecf63fa66 win32 doesn't need and even doesn't build if we extern declare sys_nerr 2004-03-25 13:43:19 +00:00
Daniel Stenberg
762dcf0780 include the strerror.h file without curl_ prefix 2004-03-25 13:42:23 +00:00
Daniel Stenberg
75ee9b5333 strerror without prefix 2004-03-25 13:40:57 +00:00
Daniel Stenberg
e161bdc5be cut off 'curl_' from the strerror file names 2004-03-25 13:40:24 +00:00
Daniel Stenberg
bb3d6e8552 tcp-nodelay patch by Joe Halpin 2004-03-25 13:37:18 +00:00
Daniel Stenberg
189c2f4989 so there are at least two different strerror_r() versions and our brand
new configure script detects them and now this code acts according to what
API that was detected
2004-03-25 12:45:01 +00:00
Daniel Stenberg
f28389c87b Tor Arntsen fixed how this is invoked 2004-03-25 12:16:42 +00:00
Daniel Stenberg
7461592a16 strerror_r() detection changes:
1. Try with _THREAD_SAFE instead of _REENTRANT, as AIX seems to require it
   and if _REENTRANT is required we should already have it set since one of
   the previous tests.
2. Added API-detection for what kind of strerror_r() that is provided. The
   POSIX style or the glibc style.

Tor Arntsen provided the necessary feedback these changes are based upon.
2004-03-25 12:15:00 +00:00
Daniel Stenberg
50b0e72f7b detect daily snapshots using the new path for this test 2004-03-25 11:39:29 +00:00
Daniel Stenberg
76e73cfec8 make clean now removes *dist files too that might be leftovers from
'maketgz'
2004-03-25 11:34:35 +00:00
Daniel Stenberg
5d8ec172a6 invoke this script via env, as it is more likely to exist at a fixed path
while perl often is installed in /usr/local/bin or elsewhere
2004-03-25 08:22:03 +00:00
Daniel Stenberg
0953140b53 added curl_strerror to the build 2004-03-25 07:53:37 +00:00
Daniel Stenberg
6c2825997a extern declare the sys_nerr variable. Required on Solaris at least. 2004-03-25 07:52:11 +00:00
Daniel Stenberg
accc6eb91a Always include setup.h as the first header file.
Added a more verbose comment about what strerror_r() can set errno to in
case of failure.
This file still doesn't build on Solaris due to a missing 'sys_nerr' symbol.
2004-03-25 07:33:11 +00:00
Daniel Stenberg
eab8cdc640 Added protos for the upcoming curl_*_strerror() functions 2004-03-24 22:53:42 +00:00
Daniel Stenberg
dc9d0f256d missed the new header file 2004-03-24 22:46:02 +00:00
Daniel Stenberg
b60d6404d8 Gisle Vanem's fix to replace the bad use of strerror(). This introduces
Curl_strerror() that attempts to be thread-safe _and_ works on Windows too!
2004-03-24 22:45:37 +00:00
Daniel Stenberg
08fe4b3210 new header file - for Curl_strerror() 2004-03-24 22:43:09 +00:00
Daniel Stenberg
0e60a118d0 better comments, added some more variable types we use in the font-lock 2004-03-24 22:24:03 +00:00
Daniel Stenberg
4b78b4124e Tor Arntsen's major ispell patch 2004-03-24 21:40:45 +00:00
Daniel Stenberg
0d6d9af7ab Tor Arntsen's mkdir-fix to make this run with perl 5.0005 2004-03-24 21:28:31 +00:00
Daniel Stenberg
41cd36b830 Avoid doing chdir .., as it breaks the ability to use symlinks properly.
chdir to absolute directory names instead. (this flaw exists in the shell
version too)
2004-03-24 10:52:21 +00:00
Daniel Stenberg
242be55771 added check for strerror_r() 2004-03-24 08:45:58 +00:00
Daniel Stenberg
7cf47ea5b5 include curl/curlver.h instead since this only needs the version defines 2004-03-24 07:27:58 +00:00
Daniel Stenberg
6fb0012833 error messages and new test script 2004-03-23 16:12:55 +00:00
Daniel Stenberg
9d1ce9c0df we are progressing 2004-03-23 16:12:37 +00:00
Daniel Stenberg
5947e4e9fd distribute testcurl.pl too starting now 2004-03-23 16:11:01 +00:00
Daniel Stenberg
e992aa6a54 Greg Hewgill's version of testcurl.sh rewritten in perl for greater
portability. I put it in this directory instead of the root since I think
perhaps it makes more sense.
2004-03-23 16:07:02 +00:00
Daniel Stenberg
2cf218610e keep current_speed as an curl_off_t for better precision at higher speeds
if large file support is available
2004-03-23 16:01:31 +00:00
Daniel Stenberg
fe6f0aeb26 switch() on the right variable! 2004-03-23 15:48:27 +00:00
Daniel Stenberg
bd04c6fb67 curl_strequal() returns int, keep return variables in an int 2004-03-23 15:30:12 +00:00
Daniel Stenberg
c5637baa06 make the variables that hold the result of strlen() size_t 2004-03-23 15:28:31 +00:00
Daniel Stenberg
f8426a2c44 stricter variable type usage 2004-03-23 15:25:54 +00:00
Daniel Stenberg
0c791d1e76 variable type usage cleanup to please picky compilers 2004-03-23 15:20:57 +00:00
Daniel Stenberg
c4a89d29f6 get strlen() results in a size_t, delete 'register' 2004-03-23 15:14:57 +00:00
Daniel Stenberg
306ff5649a made time2str() use longs internally instead to prevent compiler warnings
when converting to ints
2004-03-23 15:06:14 +00:00
Daniel Stenberg
1c652dfc5d added explicit typecasts to prevent compiler warnings on variable conversions 2004-03-23 15:01:19 +00:00
Daniel Stenberg
1f61e7f8f4 If localbind fails, provide a more portable error message. 2004-03-23 14:43:42 +00:00
Daniel Stenberg
1a5f190e47 minor update by Kevin 2004-03-23 14:34:09 +00:00
Daniel Stenberg
570033448c src/version.h was not properly made! 2004-03-23 14:29:21 +00:00
Daniel Stenberg
f44b655513 progress meter fix, CURLINFO_CONTENT_LENGTH_DOWNLOAD fix, cygwin package fix 2004-03-23 11:52:08 +00:00
Daniel Stenberg
0aa720fa26 it actually fits to make a NNNd NNh display so this can be used up to
999 days
2004-03-23 11:46:31 +00:00
Daniel Stenberg
d44f3f84f8 Fixed the time fields no never get wider than 8 letters. They can now switch
to a "days + hours" or even "just days" display if the time value is very
large. I also switched several calculations over to fixed-point instead of the
previous doubles.
2004-03-23 11:43:34 +00:00
Daniel Stenberg
d426db3d27 int/size_t cleanup 2004-03-23 09:12:51 +00:00
Daniel Stenberg
0fd88d7c8f minor variable type cleanups 2004-03-23 08:50:28 +00:00
Daniel Stenberg
4e84ac4db8 minor edits to make picky compilers whine less 2004-03-23 08:46:08 +00:00
Daniel Stenberg
da5c8a121f changed the long to int typecasts to see if icc 8.0 complains less on this 2004-03-23 08:42:01 +00:00
Daniel Stenberg
76c36688d0 Makes CURLINFO_CONTENT_LENGTH_DOWNLOAD work even if CURLOPT_NOBODY is set
true.
2004-03-22 22:38:12 +00:00
Daniel Stenberg
651c8d3bc4 Kevin Roth's updates to handle a new requirement from the Cygwin folks to
package man and doc files in a slightly different location.
2004-03-22 22:24:23 +00:00
Daniel Stenberg
a8a946d71d crap files to get the dirs made when checked out from CVS 2004-03-22 21:46:08 +00:00
Daniel Stenberg
c5c005609e container to get this dir made 2004-03-22 21:42:07 +00:00
Daniel Stenberg
97886f9353 Make the axp/README ia64/README vax/README files get included as well.
They're 0-bytes files, but make the dirs get created!
2004-03-22 21:37:02 +00:00
Daniel Stenberg
a784bd0797 fixed the ntlm problem with longish passwords 2004-03-22 13:56:48 +00:00
Daniel Stenberg
4aacf65678 vms fixes committed 2004-03-22 13:56:30 +00:00
Daniel Stenberg
dd1ba7633e Enabled 'NT responses' in the NTLM type-3 message. 2004-03-22 13:50:30 +00:00
Daniel Stenberg
a4ea5a4054 fixed /I "." for the debug build too 2004-03-22 11:32:22 +00:00
Daniel Stenberg
69060b1382 add /I "." to include ca-bundle.h properly 2004-03-22 11:26:40 +00:00
Daniel Stenberg
a6562ea77d issue 27 fixed, moved libcurl version defines to its own header file 2004-03-22 10:22:01 +00:00
Daniel Stenberg
ad3563096a include the new curlver instead, since all this wants is the version info 2004-03-22 08:54:26 +00:00
Daniel Stenberg
c5f02c1986 Introducing curl/curlver.h for keeping the curl version info only. 2004-03-22 08:37:38 +00:00
Daniel Stenberg
7ef5d20cad files moved here from the $ROOT/src dir 2004-03-21 22:50:53 +00:00
Daniel Stenberg
98b619c3a7 removed deleted files 2004-03-21 22:49:36 +00:00
Daniel Stenberg
5b75919f95 Marty Kuhrt's adjustments for a cleaner VMS build 2004-03-21 22:44:52 +00:00
Daniel Stenberg
20b76e09e3 Marty Kuhrt's VMS updates 2004-03-21 22:38:01 +00:00
Daniel Stenberg
67fca4cb01 recognize and use ACLOCAL_FLAGS if set (Thomas Schwinge patch) 2004-03-21 15:45:58 +00:00
Daniel Stenberg
606715b2cd use tabs, not spaces! 2004-03-21 15:32:15 +00:00
Daniel Stenberg
ce04b35032 Added the Version 7.11.1 marker 2004-03-19 13:22:48 +00:00
Daniel Stenberg
ec7f244ee9 starting a new cycle 2004-03-19 08:41:49 +00:00
190 changed files with 7064 additions and 3122 deletions

1891
CHANGES

File diff suppressed because it is too large Load Diff

1572
CHANGES.2003 Normal file

File diff suppressed because it is too large Load Diff

17
README
View File

@@ -32,25 +32,30 @@ WEB SITE
Sweden -- http://curl.haxx.se/ Sweden -- http://curl.haxx.se/
Australia -- http://curl.planetmirror.com/ Australia -- http://curl.planetmirror.com/
Estonia -- http://curl.dope-brothers.com/ Denmark -- http://curl.cofman.dk/
Estonia -- http://curl.wildyou.net/
Germany -- http://curl.mirror.at.stealer.net/ Germany -- http://curl.mirror.at.stealer.net/
Germany -- http://curl.netmirror.org/
Russia -- http://curl.tsuren.net/ Russia -- http://curl.tsuren.net/
Thailand -- http://curl.siamu.ac.th/ Thailand -- http://curl.siamu.ac.th/
US (CA) -- http://curl.mirror.redwire.net/ US (CA) -- http://curl.mirror.redwire.net/
US -- http://curl.signal42.com/
DOWNLOAD DOWNLOAD
The official download mirror sites are: The official download mirror sites are:
Australia -- http://curl.planetmirror.com/download/ Australia -- http://curl.planetmirror.com/download.html
Estonia -- http://curl.dope-brothers.com/download/ Estonia -- http://curl.wildyou.net/download.html
Germany -- ftp://ftp.fu-berlin.de/pub/unix/network/curl/ Germany -- ftp://ftp.fu-berlin.de/pub/unix/network/curl/
Germany -- http://curl.mirror.at.stealer.net/download.html
Germany -- http://curl.netmirror.org/download.html
Hongkong -- http://www.execve.net/curl/ Hongkong -- http://www.execve.net/curl/
Russia -- http://curl.tsuren.net/download/ Russia -- http://curl.tsuren.net/download.html
Sweden -- ftp://ftp.sunet.se/pub/www/utilities/curl/ Sweden -- ftp://ftp.sunet.se/pub/www/utilities/curl/
Sweden -- http://cool.haxx.se/curl/ Sweden -- http://cool.haxx.se/curl/
Thailand -- http://curl.siamu.ac.th/download/ Thailand -- http://curl.siamu.ac.th/download.html
US (CA) -- http://curl.mirror.redwire.net/download/ US (CA) -- http://curl.mirror.redwire.net/download.html
CVS CVS

View File

@@ -1,89 +1,74 @@
Curl and libcurl 7.11.1. A bugfix release. Curl and libcurl 7.11.2. A bugfix release.
Public curl release number: 79 Public curl release number: 80
Releases counted from the very beginning: 106 Releases counted from the very beginning: 107
Available command line options: 94 Available command line options: 94
Available curl_easy_setopt() options: 112 Available curl_easy_setopt() options: 113
This release includes the following changes: This release includes the following changes:
o CURLOPT_POSTFIELDSIZE_LARGE added to offer POSTs larger than 2GB o removed maximum user+password+hostname size limit
o CURL_VERSION_LARGEFILE is a feature bit returned by libcurls that feature o removed maximum dir depth limit for FTP
large file support o the ares build now requires c-ares 1.2.0 or later
o libcurl only requires winsock 1.1 on windows now o --tcp-nodelay and CURLOPT_TCP_NODELAY were added
o when doing FTP, curl now sends QUIT before disconnecting o curl/curlver.h contains the libcurl version info now
o name resolves can now timeout on windows too
o $HOME is now recognized better when looking for .netrc files
o now re-uses the ares handle when re-using curl handles
o SO_BINDTODEVICE is used for network interface binding
o configure --disable-manual disables the built-in huge manual from the
command line tool
o the default Accept: header used in HTTP requests changed
o asynch dns lookups now require the c-ares library
o curl --socks can be used to set a SOCKS5 proxy to use
o response-headers received after a (proxy) CONNECT request are now passed
to the header callback just like other headers
This release includes the following bugfixes: This release includes the following bugfixes:
o builds and runs on Novell NetWare o configure --disable-manual works better
o Windows builds now report OS as "i386-pc-win32" o removed a memory leak when doing a windows threaded resolve and it failed
o received signals during SSL connect is handled better o --proxy-ntlm now checks if libcurl supports NTLM before using it
o improved PUT/POST with NTLM/Digest authentication o minor --fail with authentication bugfix
o following redirects and doing NTLM/Digest (where the first connection gets o CURLOPT_IPRESOLVE set to CURL_IPRESOLVE_V6 will now cause a returned error
closed) with the multi interface work better now if the host only can resolve ipv4 addresses
o file: progress meter and getinfo variables work now o curl -4/-6 now actually sets the requested option in libcurl
o CURLOPT_FRESH_CONNECT and CURLAUTH_NTLM now work when set together o multi interface on Windows without ares works again
o share interface usage without (un)lock functions segfaulted o improved resolution for the CURLINFO_*_TIME info variables
o --limit-rate no longer cripples the --speed-limit feature o getting only a 100 Continue response and nothing else, when talking HTTP,
o fixed verbose output problem with ipv6-enabled re-used connections is now treated as an error by libcurl
o fixed the socks5 code to check version in the socks response properly o fixed minor memory leak in libcurl for Windows when statically linked
o dns cache bug - fixed the 'inuse' counter o POST/PUT using Digest/NTLM/Negotiate (including anyauth) now work better
o large file fix for Content-Length o --limit-rate with high speed rates is a lot more accurate now, and supports
o better docs for the share interface limiting to speeds >2GB/sec on systems with Large File support.
o several configure fixes for mingw/msys o curl_strnqual.3 "refer-to" man page fix
o setting a Host: header is no longer affecting the Host: header used when o fixed a minor very old progress meter final update bug
libcurl follows a Location: o added checks for a working NI_WITHSCOPEID before that is used
o fixed numerous compiler warnings on several operating systems and compilers o fixed a flaw that prevented ares name resolve timeouts to occur
o PUTing from stdin couldn't disable chunked transfer-encoding o getting user name from http_proxy env variable works now
o corrected the mingw makefiles o fixed too early name resolve timeouts with ares
o improved the configure libz detection o HTTP Digest "re-negotiation" works now
o fixed EPRT/PORT use when doing FTP on ipv6-enabled AIX hosts o CURLOPT_FAILONERROR (-f/--fail) works with all kinds of authentication
o *nroff commands that only support -mandoc and not -man are now supported o better thread-safety thanks to the internal strerror() replacement
(for the built-in manual text in the command line tool) o better thread-safety on AIX thanks to better function detection
o fixed the unconditional #include of config.h in hugehelp.c o minor ipv6 build fix for windows
o builds fine on MPE/iX o the test suite runs fine with mingw-built curl
o upload using chunked transfer-encoding now sends the last chunk properly o the postit2.c example works now
teriminated with an extra CRLF o better error message when --interface fails on windows
o Fixed the progress meter display for files >2GB o the progress meter now displays very long times better
o persistant connections over a proxy messed up the proxy name/password o CURLINFO_CONTENT_LENGTH_DOWNLOAD with CURLOPT_NOBODY set TRUE now works
o the socks5 code segfaulted if no username/password was set o passwords longer than 14 letters work with NTLM
o the *_LARGE options now take curl_off_t types as parameters and this will o 'make netware' in the root dir works now
make it possible to handle large files on windows too o builds fine on VMS again and even nicer than before
o builds with large file support even on systems without strtoll()
Other curl-related news since the previous public release: Other curl-related news since the previous public release:
o Many platforms are being used to autobuild and autotest curl on a daily o PycURL 7.11.1 was released: http://pycurl.sf.net/
basis. Please join in and test curl on your systems: o CURLHandle 1.9 was released: http://curlhandle.sourceforge.net/
http://curl.haxx.se/auto/ o A curl module for the Q language was announced:
o the curl mailing lists moved, (re-)subscribe to the new ones from here: http://q-lang.sourceforge.net/
http://curl.haxx.se/mail/ o c-ares 1.2.0 was released: http://daniel.haxx.se/projects/c-ares/
o c-ares 1.1.0 was relased: http://daniel.haxx.se/projects/c-ares/ o New curl web mirrors:
o TclCurl 0.11.0 was released: Germany http://curl.netmirror.org/
http://personal1.iddeo.es/andresgarci/tclcurl/english/ USA http://curl.signal42.com/
o PycURL 7.11.0 was released: http://pycurl.sourceforge.net/ Denmark http://curl.cofman.dk/
o the libcurl D binding was released:
http://www.atari-soldiers.com/libcurl.html
o new Estonian web site mirror: http://curl.dope-brothers.com/
This release would not have looked like this without help, code, reports and This release would not have looked like this without help, code, reports and
advice from friends like these: advice from friends like these:
Gisle Vanem, Vincent Bronner, Richard Bramante, Dirk Manske, Dan Fandrich, Thomas Schwinge, Marty Kuhrt, G<>nter Knauf, Kevin Roth, Glen Nakamura, Gisle
Ken Hirsch, Stadler Stephan, Domenico Andreoli, Patrick Smith, Tor Arntsen, Vanem, Greg Hewgill, Joe Halpin, Tor Arntsen, Dirk Manske, Roy Shan, Mitz
Andr<64>s Garc<72>a, Tim Baker, Len Krause, Gilad, Ken Rastatter, P R Schaffner, Wark, Andr<64>s Garc<72>a, Robin Kay, Alan Pinstein, David Byron, Nathan
Greg Hewgill, Ben Greear, Jeff Lawson, Grigory Entin, Doug Porter, David O'Sullivan, Erwin Authried
Byron, Andy Serpa, Joe Halpin, Christopher R. Palmer, G<>nter Knauf
Thanks! (and sorry if I forgot to mention someone) Thanks! (and sorry if I forgot to mention someone)

View File

@@ -3,51 +3,35 @@ Issues not sorted in any particular order.
UNASSIGNED means that no person has publicly stated to work on the issue. UNASSIGNED means that no person has publicly stated to work on the issue.
DELETE means the issue is subject for dismissal DELETE means the issue is subject for dismissal
To get fixed in 7.11.1 (planned release in March 2004) To get fixed in 7.11.2 (planned release late April 2004)
====================== ======================
To get fixed in 7.11.2 (planned release May/June 2004)
======================
6. REST fix for servers not behaving well on >2GB requests. This should fail To get fixed in 7.12.0 (no date)
if the server doesn't set the pointer to the requested index. The tricky
part is to figure out if the server did the right thing or not.
UNASSIGNED
10. Anton Fedorov's "dumpcert" patch UNASSIGNED
http://curl.haxx.se/mail/lib-2004-03/0088.html
14. Evaluate/apply Gertjan van Wingerde's SSL patches, UNASSIGNED
http://curl.haxx.se/mail/lib-2004-03/0087.html
23. Peter Sylvester's "Most Significant Common Name" change. Feedback welcome.
At least the UTF8 conversion and comparison should be done. Patch?
UNASSIGNED
24. Make the progress meter use one digit more for the hour time fields.
Accomplish this by removing one of the times displayed.
27. Put the version defines in their own header file, so that lib/libcurl.rc
can include only that to reduce problems with MSVC.
28. Optimize the way libcurl uses CWD on each new request over a persistent
connection (on FTP) even if it doesn't have to.
29. Define USE_NTRESPONSES in the NTLM code to work properly with >14 letter
passwords against IIS servers. Requires test cases to be updated
accordingly. #915609
30. Digest re-negotiation is not supported, we wrongly assume a new 401
response to signify an authenticaion error. We need to detect the
difference between a 401 due to a bad Digest authorization header and a
401 because the server wants to re-negotiate.
Mitz Wark provided details and traces here:
http://curl.haxx.se/mail/lib-2004-03/0299.html
To get fixed in 7.12.0
====================== ======================
25. curl_easy_strerror() curl_multi_strerror() curl_share_strerror() 25. curl_easy_strerror() curl_multi_strerror() curl_share_strerror()
Code already in CVS. Messages need overview/improvements.
Medium prio.
26. i18n of error messages 26. i18n of error messages?
Low prio. Nobody has volunteered. Subject for removal.
33. Add a function to replace the malloc-calls within libcurl.
Low prio. Seshubabu Pasam works on this.
35. Rearrange lib/hostip.c to reduce the amount of #ifdefs and make it easier
to understand and edit. Daniel works on this. See
http://curl.haxx.se/beta/hostip-cleanup1.patch
Medium prio.
36. Add support for a threaded getaddrinfo() on Windows and IPv6 enabled
libcurl.
37. Configure option "--with-libidn" to support IDNA (Internationalising
Domain Names in Applications). Translate to/from ACE encoded domain
names as needed.
38. Make the ldap protocol work with Windows' built-in LDAP-client.
I.e. dynamically link to WLDAP32.DLL and add ldap URL parsing
(WLDAP32.DLL doesn't have an UTF-8 ldap_url_parse).

View File

@@ -64,7 +64,7 @@ dnl the code was bad, try a different program now, test 3
],[ ],[
/* ioctlsocket source code */ /* ioctlsocket source code */
int socket; int socket;
int flags = ioctlsocket(socket, FIONBIO, &flags); unsigned long flags = ioctlsocket(socket, FIONBIO, &flags);
],[ ],[
dnl ioctlsocket test was good dnl ioctlsocket test was good
nonblock="ioctlsocket" nonblock="ioctlsocket"
@@ -245,7 +245,8 @@ AC_DEFUN([CURL_CHECK_WORKING_GETADDRINFO],[
#include <sys/types.h> #include <sys/types.h>
#include <sys/socket.h> #include <sys/socket.h>
void main(void) { int main(void)
{
struct addrinfo hints, *ai; struct addrinfo hints, *ai;
int error; int error;
@@ -254,11 +255,9 @@ void main(void) {
hints.ai_socktype = SOCK_STREAM; hints.ai_socktype = SOCK_STREAM;
error = getaddrinfo("127.0.0.1", "8080", &hints, &ai); error = getaddrinfo("127.0.0.1", "8080", &hints, &ai);
if (error) { if (error) {
exit(1); return 1;
}
else {
exit(0);
} }
return 0;
} }
],[ ],[
ac_cv_working_getaddrinfo="yes" ac_cv_working_getaddrinfo="yes"
@@ -276,10 +275,72 @@ if test "$ac_cv_working_getaddrinfo" = "yes"; then
fi fi
]) ])
dnl ************************************************************
dnl check for working NI_WITHSCOPEID in getnameinfo()
dnl
AC_DEFUN([CURL_CHECK_NI_WITHSCOPEID],[
AC_CACHE_CHECK(for working NI_WITHSCOPEID, ac_cv_working_ni_withscopeid,[
AC_RUN_IFELSE([[
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
int main()
{
#ifdef NI_WITHSCOPEID
struct sockaddr_storage ss;
int sslen = sizeof(ss);
int rc;
char hbuf[NI_MAXHOST];
int fd = socket(AF_INET6, SOCK_STREAM, 0);
if(fd < 0) {
perror("socket()");
return 1; /* couldn't create socket of either kind */
}
rc = getsockname(fd, (struct sockaddr *)&ss, &sslen);
if(rc) {
perror("getsockname()");
return 2;
}
rc = getnameinfo((struct sockaddr *)&ss, sslen, hbuf, sizeof(hbuf),
NULL, 0,
NI_NUMERICHOST | NI_NUMERICSERV | NI_WITHSCOPEID);
if(rc) {
printf("rc = %s\n", gai_strerror(rc));
return 3;
}
return 0; /* everything works fine, use NI_WITHSCOPEID! */
#else
return 4; /* we don't seem to have the definition, don't use it */
#endif
}
]],
dnl program worked:
[ ac_cv_working_ni_withscopeid="yes" ],
dnl program failed:
[ ac_cv_working_ni_withscopeid="no" ],
dnl we cross-compile:
[ ac_cv_working_ni_withscopeid="yes" ]
) dnl end of AC_RUN_IFELSE
]) dnl end of AC_CACHE_CHECK
if test "$ac_cv_working_ni_withscopeid" = "yes"; then
AC_DEFINE(HAVE_NI_WITHSCOPEID, 1,
[Define if NI_WITHSCOPEID exists and works])
fi
]) dnl end of AC_DEFUN
AC_DEFUN([CURL_CHECK_LOCALTIME_R], AC_DEFUN([CURL_CHECK_LOCALTIME_R],
[ [
dnl check for a few thread-safe functions dnl check for localtime_r
AC_CHECK_FUNCS(localtime_r,[ AC_CHECK_FUNCS(localtime_r,[
AC_MSG_CHECKING(whether localtime_r is declared) AC_MSG_CHECKING(whether localtime_r is declared)
AC_EGREP_CPP(localtime_r,[ AC_EGREP_CPP(localtime_r,[
@@ -295,6 +356,92 @@ AC_DEFUN([CURL_CHECK_LOCALTIME_R],
AC_MSG_RESULT(no))])]) AC_MSG_RESULT(no))])])
]) ])
dnl
dnl This function checks for strerror_r(). If it isn't found at first, it
dnl retries with _THREAD_SAFE defined, as that is what AIX seems to require
dnl in order to find this function.
dnl
dnl If the function is found, it will then proceed to check how the function
dnl actually works: glibc-style or POSIX-style.
dnl
dnl glibc:
dnl char *strerror_r(int errnum, char *buf, size_t n);
dnl
dnl What this one does is to return the error string (no surprises there),
dnl but it doesn't usually copy anything into buf! The 'buf' and 'n'
dnl parameters are only meant as an optional working area, in case strerror_r
dnl needs it. A quick test on a few systems shows that it's generally not
dnl touched at all.
dnl
dnl POSIX:
dnl int strerror_r(int errnum, char *buf, size_t n);
dnl
AC_DEFUN([CURL_CHECK_STRERROR_R],
[
dnl determine of strerror_r is present
AC_CHECK_FUNCS(strerror_r,[
AC_MSG_CHECKING(whether strerror_r is declared)
AC_EGREP_CPP(strerror_r,[
#include <string.h>],[
strerror_r="yes"
AC_MSG_RESULT(yes)],[
AC_MSG_RESULT(no)
AC_MSG_CHECKING(whether strerror_r with -D_THREAD_SAFE is declared)
AC_EGREP_CPP(strerror_r,[
#define _THREAD_SAFE
#include <string.h>],[
strerror_r="yes"
CPPFLAGS="-D_THREAD_SAFE $CPPFLAGS"
AC_MSG_RESULT(yes)],
AC_MSG_RESULT(no))])])
if test "x$strerror_r" = "xyes"; then
dnl determine if this strerror_r() is glibc or POSIX
AC_MSG_CHECKING([for a glibc strerror_r API])
AC_TRY_RUN([
#include <string.h>
#include <errno.h>
int
main () {
char buffer[1024]; /* big enough to play with */
char *string =
strerror_r(EACCES, buffer, sizeof(buffer));
/* this should've returned a string */
if(!string || !string[0])
return 99;
return 0;
}
],
AC_DEFINE(HAVE_GLIBC_STRERROR_R, 1, [we have a glibc-style strerror_r()])
AC_MSG_RESULT([yes]),
AC_MSG_RESULT([no])
)
AC_MSG_CHECKING([for a POSIX strerror_r API])
AC_TRY_RUN([
#include <string.h>
#include <errno.h>
int
main () {
char buffer[1024]; /* big enough to play with */
int error =
strerror_r(EACCES, buffer, sizeof(buffer));
/* This should've returned zero, and written an error string in the
buffer.*/
if(!buffer[0] || error)
return 99;
return 0;
}
],
AC_DEFINE(HAVE_POSIX_STRERROR_R, 1, [we have a POSIX-style strerror_r()])
AC_MSG_RESULT([yes]),
AC_MSG_RESULT([no])
)
fi
])
AC_DEFUN([CURL_CHECK_INET_NTOA_R], AC_DEFUN([CURL_CHECK_INET_NTOA_R],
[ [
dnl determine if function definition for inet_ntoa_r exists. dnl determine if function definition for inet_ntoa_r exists.

View File

@@ -1,3 +1,27 @@
Changelog for the c-ares project
Version 1.2.0 (April 13, 2004)
* April 2, 2004
- Updated various man pages to look nicer when converted to HTML on the web
site.
* April 1, 2004
- Dirk Manske provided a new function that is now named ares_cancel(). It is
used to cancel/cleanup a resolve/request made using ares functions on the
given ares channel. It does not destroy/kill the ares channel itself.
- Dominick Meglio cleaned up the formatting in several man pages.
* March 30, 2004
- Dominick Meglio's new ares_expand_string. A helper function when decoding
incoming DNS packages.
- Daniel Stenberg modified the Makefile.in to use a for loop for the man page
installation to improve overview and make it easier to add man pages.
Version 1.1.0 (March 11, 2004)
* March 9, 2004 * March 9, 2004
- Gisle Vanem improved build on Windows. - Gisle Vanem improved build on Windows.
@@ -74,3 +98,5 @@ Version 1.0-pre1 (8 October 2003)
- Daniel Stenberg adjusted the windows port - Daniel Stenberg adjusted the windows port
- liren at vivisimo.com made the initial windows port - liren at vivisimo.com made the initial windows port
* Imported the sources from ares 1.1.1

View File

@@ -21,8 +21,6 @@ vc/adig/adig.dsp
vc/adig/adig.mak vc/adig/adig.mak
vc/adig/adig.plg vc/adig/adig.plg
vc/vc.dsw vc/vc.dsw
vc/vc.ncb
vc/vc.opt
vc/ahost/ahost.dep vc/ahost/ahost.dep
vc/ahost/ahost.dsp vc/ahost/ahost.dsp
vc/ahost/ahost.mak vc/ahost/ahost.mak

View File

@@ -25,7 +25,15 @@ OBJS= ares__close_sockets.o ares__get_hostent.o ares__read_line.o \
ares_free_hostent.o ares_free_string.o ares_gethostbyaddr.o \ ares_free_hostent.o ares_free_string.o ares_gethostbyaddr.o \
ares_gethostbyname.o ares_init.o ares_mkquery.o ares_parse_a_reply.o \ ares_gethostbyname.o ares_init.o ares_mkquery.o ares_parse_a_reply.o \
ares_parse_ptr_reply.o ares_process.o ares_query.o ares_search.o \ ares_parse_ptr_reply.o ares_process.o ares_query.o ares_search.o \
ares_send.o ares_strerror.o ares_timeout.o ares_version.o ares_send.o ares_strerror.o ares_timeout.o ares_version.o \
ares_expand_string.o ares_cancel.o
MANPAGES= ares_destroy.3 ares_expand_name.3 ares_expand_string.3 ares_fds.3 \
ares_free_hostent.3 ares_free_string.3 ares_gethostbyaddr.3 \
ares_gethostbyname.3 ares_init.3 ares_init_options.3 ares_mkquery.3 \
ares_parse_a_reply.3 ares_parse_ptr_reply.3 ares_process.3 \
ares_query.3 ares_search.3 ares_send.3 ares_strerror.3 ares_timeout.3 \
ares_version.3 ares_cancel.3
$(LIB): ${OBJS} $(LIB): ${OBJS}
ar cru $@ ${OBJS} ar cru $@ ${OBJS}
@@ -60,31 +68,9 @@ install:
chmod u-w ${DESTDIR}${libdir}/$(LIB) chmod u-w ${DESTDIR}${libdir}/$(LIB)
${INSTALL} -m 444 ${srcdir}/ares.h ${DESTDIR}${includedir} ${INSTALL} -m 444 ${srcdir}/ares.h ${DESTDIR}${includedir}
${INSTALL} -m 444 ${srcdir}/ares_version.h ${DESTDIR}${includedir} ${INSTALL} -m 444 ${srcdir}/ares_version.h ${DESTDIR}${includedir}
${INSTALL} -m 444 ${srcdir}/ares_destroy.3 ${DESTDIR}${mandir}/man3 (for man in $(MANPAGES); do \
${INSTALL} -m 444 ${srcdir}/ares_expand_name.3 ${DESTDIR}${mandir}/man3 ${INSTALL} -m 444 ${srcdir}/$${man} ${DESTDIR}${mandir}/man3; \
${INSTALL} -m 444 ${srcdir}/ares_fds.3 ${DESTDIR}${mandir}/man3 done)
${INSTALL} -m 444 ${srcdir}/ares_free_hostent.3 \
${DESTDIR}${mandir}/man3
${INSTALL} -m 444 ${srcdir}/ares_free_string.3 \
${DESTDIR}${mandir}/man3
${INSTALL} -m 444 ${srcdir}/ares_gethostbyaddr.3 \
${DESTDIR}${mandir}/man3
${INSTALL} -m 444 ${srcdir}/ares_gethostbyname.3 \
${DESTDIR}${mandir}/man3
${INSTALL} -m 444 ${srcdir}/ares_init.3 ${DESTDIR}${mandir}/man3
${INSTALL} -m 444 ${srcdir}/ares_init_options.3 \
${DESTDIR}${mandir}/man3
${INSTALL} -m 444 ${srcdir}/ares_mkquery.3 ${DESTDIR}${mandir}/man3
${INSTALL} -m 444 ${srcdir}/ares_parse_a_reply.3 \
${DESTDIR}${mandir}/man3
${INSTALL} -m 444 ${srcdir}/ares_parse_ptr_reply.3 \
${DESTDIR}${mandir}/man3
${INSTALL} -m 444 ${srcdir}/ares_process.3 ${DESTDIR}${mandir}/man3
${INSTALL} -m 444 ${srcdir}/ares_query.3 ${DESTDIR}${mandir}/man3
${INSTALL} -m 444 ${srcdir}/ares_search.3 ${DESTDIR}${mandir}/man3
${INSTALL} -m 444 ${srcdir}/ares_send.3 ${DESTDIR}${mandir}/man3
${INSTALL} -m 444 ${srcdir}/ares_strerror.3 ${DESTDIR}${mandir}/man3
${INSTALL} -m 444 ${srcdir}/ares_timeout.3 ${DESTDIR}${mandir}/man3
clean: clean:
rm -f ${OBJS} $(LIB) adig.o adig ahost.o ahost rm -f ${OBJS} $(LIB) adig.o adig ahost.o ahost

View File

@@ -1,19 +1,21 @@
c-ares
======
This package is based on ares 1.1.1 (written by Greg Hudson). I've decided to This package is based on ares 1.1.1 (written by Greg Hudson). I decided to
put together and release my own ares archives since the ares maintainer fork and release a separate project since the ares author didn't want the
doesn't want these improvements. improvements that were vital for our use of it.
The package is thus dubbed 'c-ares' since I (Daniel Stenberg) want this for This package is dubbed 'c-ares' since I (Daniel Stenberg) wanted this for use
use within the curl project (hence the letter C) and it makes a nice within the curl project (hence the letter C) and it makes a nice pun. Also,
pun. Also, c-ares will not remain API compatible with the original ares, so c-ares is not API compatible with ares: a new name makes that more obvious to
picking a new name makes it more obvious to the public. the public.
The full source code is available in the 'c-ares' release archives, and in the The full source code is available in the 'c-ares' release archives, and in the
'ares' subdir of the curl CVS source repostitory. 'ares' subdir of the curl CVS source repostitory.
If you find bugs, correct flaws, have questions or have comments in general in If you find bugs, correct flaws, have questions or have comments in general in
regard to c-ares (or by all means the original ares too), get in touch with us regard to c-ares (or by all means the original ares too), get in touch with us
on the curl-library mailing list. on the c-ares mailing list: http://cool.haxx.se/mailman/listinfo/c-ares
c-ares is of course distributed under the same MIT-style license as the c-ares is of course distributed under the same MIT-style license as the
original ares. original ares.

View File

@@ -55,6 +55,7 @@
#define ARES_EFILE 14 #define ARES_EFILE 14
#define ARES_ENOMEM 15 #define ARES_ENOMEM 15
#define ARES_EDESTRUCTION 16 #define ARES_EDESTRUCTION 16
#define ARES_EBADSTR 17
/* Flag values */ /* Flag values */
#define ARES_FLAG_USEVC (1 << 0) #define ARES_FLAG_USEVC (1 << 0)
@@ -104,7 +105,7 @@ int ares_init(ares_channel *channelptr);
int ares_init_options(ares_channel *channelptr, struct ares_options *options, int ares_init_options(ares_channel *channelptr, struct ares_options *options,
int optmask); int optmask);
void ares_destroy(ares_channel channel); void ares_destroy(ares_channel channel);
void ares_cancel(ares_channel channel);
void ares_send(ares_channel channel, const unsigned char *qbuf, int qlen, void ares_send(ares_channel channel, const unsigned char *qbuf, int qlen,
ares_callback callback, void *arg); ares_callback callback, void *arg);
void ares_query(ares_channel channel, const char *name, int dnsclass, void ares_query(ares_channel channel, const char *name, int dnsclass,
@@ -125,6 +126,8 @@ int ares_mkquery(const char *name, int dnsclass, int type, unsigned short id,
int rd, unsigned char **buf, int *buflen); int rd, unsigned char **buf, int *buflen);
int ares_expand_name(const unsigned char *encoded, const unsigned char *abuf, int ares_expand_name(const unsigned char *encoded, const unsigned char *abuf,
int alen, char **s, long *enclen); int alen, char **s, long *enclen);
int ares_expand_string(const unsigned char *encoded, const unsigned char *abuf,
int alen, unsigned char **s, long *enclen);
int ares_parse_a_reply(const unsigned char *abuf, int alen, int ares_parse_a_reply(const unsigned char *abuf, int alen,
struct hostent **host); struct hostent **host);
int ares_parse_ptr_reply(const unsigned char *abuf, int alen, const void *addr, int ares_parse_ptr_reply(const unsigned char *abuf, int alen, const void *addr,

37
ares/ares_cancel.3 Normal file
View File

@@ -0,0 +1,37 @@
.\" $Id$
.\"
.\" Copyright 1998 by the Massachusetts Institute of Technology.
.\"
.\" Permission to use, copy, modify, and distribute this
.\" software and its documentation for any purpose and without
.\" fee is hereby granted, provided that the above copyright
.\" notice appear in all copies and that both that copyright
.\" notice and this permission notice appear in supporting
.\" documentation, and that the name of M.I.T. not be used in
.\" advertising or publicity pertaining to distribution of the
.\" software without specific, written prior permission.
.\" M.I.T. makes no representations about the suitability of
.\" this software for any purpose. It is provided "as is"
.\" without express or implied warranty.
.\"
.TH ARES_CANCEL 3 "31 March 2004"
.SH NAME
ares_cancel \- Cancel a resolve
.SH SYNOPSIS
.nf
.B #include <ares.h>
.PP
.B int ares_cancel(ares_channel \fIchannel\fP)
.fi
.SH DESCRIPTION
The \fBares_cancel\fP function cancels all lookups/requests made on the the
name service channel identified by \fIchannel\fP. \fBares_cancel\fP invokes
the callbacks for each pending query on the channel, passing a status of
.BR ARES_ETIMEOUT .
These calls give the callbacks a chance to clean up any state which
might have been stored in their arguments.
.SH SEE ALSO
.BR ares_init (3)
.BR ares_destroy (3)
.SH AUTHOR
Dirk Manske

44
ares/ares_cancel.c Normal file
View File

@@ -0,0 +1,44 @@
/* Copyright 1998 by the Massachusetts Institute of Technology.
*
* Permission to use, copy, modify, and distribute this
* software and its documentation for any purpose and without
* fee is hereby granted, provided that the above copyright
* notice appear in all copies and that both that copyright
* notice and this permission notice appear in supporting
* documentation, and that the name of M.I.T. not be used in
* advertising or publicity pertaining to distribution of the
* software without specific, written prior permission.
* M.I.T. makes no representations about the suitability of
* this software for any purpose. It is provided "as is"
* without express or implied warranty.
*/
#include <stdlib.h>
#include "ares.h"
#include "ares_private.h"
/*
* ares_cancel() cancels a ongoing request/resolve that might be going on on
* the given channel. It does NOT kill the channel, use ares_destroy() for
* that.
*/
void ares_cancel(ares_channel channel)
{
struct query *query, *next;
int i;
for (query = channel->queries; query; query = next)
{
next = query->next;
query->callback(query->arg, ARES_ETIMEOUT, NULL, 0);
free(query->tcpbuf);
free(query->skip_server);
free(query);
}
channel->queries = NULL;
if (!(channel->flags & ARES_FLAG_STAYOPEN))
{
for (i = 0; i < channel->nservers; i++)
ares__close_sockets(&channel->servers[i]);
}
}

View File

@@ -36,7 +36,8 @@ status of
These calls give the callbacks a chance to clean up any state which These calls give the callbacks a chance to clean up any state which
might have been stored in their arguments. might have been stored in their arguments.
.SH SEE ALSO .SH SEE ALSO
.BR ares_init (3) .BR ares_init (3),
.BR ares_cancel (3)
.SH AUTHOR .SH AUTHOR
Greg Hudson, MIT Information Systems Greg Hudson, MIT Information Systems
.br .br

62
ares/ares_expand_string.3 Normal file
View File

@@ -0,0 +1,62 @@
.\" $Id$
.\"
.\" Copyright 1998 by the Massachusetts Institute of Technology.
.\"
.\" Permission to use, copy, modify, and distribute this
.\" software and its documentation for any purpose and without
.\" fee is hereby granted, provided that the above copyright
.\" notice appear in all copies and that both that copyright
.\" notice and this permission notice appear in supporting
.\" documentation, and that the name of M.I.T. not be used in
.\" advertising or publicity pertaining to distribution of the
.\" software without specific, written prior permission.
.\" M.I.T. makes no representations about the suitability of
.\" this software for any purpose. It is provided "as is"
.\" without express or implied warranty.
.\"
.TH ARES_EXPAND_NAME 3 "23 July 1998"
.SH NAME
ares_expand_string \- Expand a length encoded string
.SH SYNOPSIS
.nf
.B #include <ares.h>
.PP
.B int ares_expand_string(const unsigned char *\fIencoded\fP,
.B const unsigned char *\fIabuf\fP, int \fIalen\fP, unsigned char **\fIs\fP,
.B int *\fIenclen\fP)
.fi
.SH DESCRIPTION
The
.B ares_expand_string
function converts a length encoded string to a NULL terminated C
string. The argument
.I encoded
gives the beginning of the encoded string, and the arguments
.I abuf
and
.I alen
give the containing message buffer (necessary for the processing of
indirection pointers within the encoded domain name). The result is
placed in a NUL-terminated allocated buffer, a pointer to which is
stored in the variable pointed to by
.IR s .
The length of the encoded string is stored in the variable pointed to by
.I enclen
so that the caller can advance past the encoded string to read
further data in the message.
.SH RETURN VALUES
.B ares_expand_string
can return any of the following values:
.TP 15
.B ARES_SUCCESS
Expansion of the encoded string succeeded.
.TP 15
.B ARES_EBADSTR
The encoded string was malformed and could not be expanded.
.TP 15
.B ARES_ENOMEM
Memory was exhausted.
.SH SEE ALSO
.BR ares_free_string (3)
.SH AUTHOR
Dominick Meglio

65
ares/ares_expand_string.c Normal file
View File

@@ -0,0 +1,65 @@
/* Copyright 1998 by the Massachusetts Institute of Technology.
*
* Permission to use, copy, modify, and distribute this
* software and its documentation for any purpose and without
* fee is hereby granted, provided that the above copyright
* notice appear in all copies and that both that copyright
* notice and this permission notice appear in supporting
* documentation, and that the name of M.I.T. not be used in
* advertising or publicity pertaining to distribution of the
* software without specific, written prior permission.
* M.I.T. makes no representations about the suitability of
* this software for any purpose. It is provided "as is"
* without express or implied warranty.
*/
#include <sys/types.h>
#ifdef WIN32
#include "nameser.h"
#else
#include <netinet/in.h>
#include <arpa/nameser.h>
#endif
#include <string.h>
#include <stdlib.h>
#include "ares.h"
#include "ares_private.h" /* for the memdebug */
/* Simply decodes a length-encoded character string. The first byte of the
* input is the length of the string to be returned and the bytes thereafter
* are the characters of the string. The returned result will be NULL
* terminated.
*/
int ares_expand_string(const unsigned char *encoded,
const unsigned char *abuf,
int alen,
unsigned char **s,
long *enclen)
{
unsigned char *q;
long len;
if (encoded == abuf+alen)
return ARES_EBADSTR;
len = *encoded;
if (encoded+len+1 > abuf+alen)
return ARES_EBADSTR;
encoded++;
*s = malloc(len+1);
if (*s == NULL)
return ARES_ENOMEM;
q = *s;
strncpy((char *)q, (char *)encoded, len);
q[len] = '\0';
*s = q;
*enclen = len+1;
return ARES_SUCCESS;
}

View File

@@ -28,21 +28,16 @@ The
.I ares_free_hostent .I ares_free_hostent
function frees a function frees a
.B struct hostent .B struct hostent
allocated by one of the functions allocated by one of the functions \fIares_parse_a_reply(3)\fP or
.I ares_parse_a_reply \fIares_parse_ptr_reply(3)\fP.
or .SH NOTES
.IR ares_parse_ptr_reply . It is not necessary (and is not correct) to free the host structure passed to
the callback functions for \fIares_gethostbyname(3)\fP or
\fIares_gethostbyaddr(3)\fP. The ares library will automatically free such
host structures when the callback returns.
.SH SEE ALSO .SH SEE ALSO
.BR ares_parse_a_reply (3), .BR ares_parse_a_reply (3),
.BR ares_parse_ptr_reply (3) .BR ares_parse_ptr_reply (3)
.SH NOTES
It is not necessary (and is not correct) to free the host structure
passed to the callback functions for
.I ares_gethostbyname
or
.IR ares_gethostbyaddr .
The ares library will automatically free such host structures when the
callback returns.
.SH AUTHOR .SH AUTHOR
Greg Hudson, MIT Information Systems Greg Hudson, MIT Information Systems
.br .br

View File

@@ -26,11 +26,10 @@ ares_free_string \- Free strings allocated by ares functions
.SH DESCRIPTION .SH DESCRIPTION
The The
.I ares_free_string .I ares_free_string
function frees a string allocated by the function frees a string allocated by an ares function.
.I ares_mkquery
function.
.SH SEE ALSO .SH SEE ALSO
.BR ares_mkquery (3) .BR ares_mkquery (3)
.BR ares_expand_string (3)
.SH AUTHOR .SH AUTHOR
Greg Hudson, MIT Information Systems Greg Hudson, MIT Information Systems
.br .br

View File

@@ -40,14 +40,10 @@ and
.I addrlen .I addrlen
give the address as a series of bytes, and give the address as a series of bytes, and
.I family .I family
gives the type of address. When the query is complete or has failed, gives the type of address. When the query is complete or has failed, the ares
the ares library will invoke library will invoke \fIcallback\fP. Completion or failure of the query may
.IR callback . happen immediately, or may happen during a later call to
Completion or failure of the query may happen immediately, or may \fIares_process(3)\fP, \fIares_destroy(3)\fP or \fIares_cancel(3)\fP.
happen during a later call to
.BR ares_process (3)
or
.BR ares_destroy (3).
.PP .PP
The callback argument The callback argument
.I arg .I arg
@@ -93,7 +89,8 @@ did not complete successfully,
will be will be
.BR NULL . .BR NULL .
.SH SEE ALSO .SH SEE ALSO
.BR ares_process (3) .BR ares_process (3),
.BR ares_gethostbyname (3)
.SH AUTHOR .SH AUTHOR
Greg Hudson, MIT Information Systems Greg Hudson, MIT Information Systems
.br .br

View File

@@ -87,10 +87,10 @@ static void next_lookup(struct addr_query *aquery)
{ {
case 'b': case 'b':
addr = ntohl(aquery->addr.s_addr); addr = ntohl(aquery->addr.s_addr);
a1 = (int)(addr >> 24) & 0xff; a1 = (int)((addr >> 24) & 0xff);
a2 = (int)(addr >> 16) & 0xff; a2 = (int)((addr >> 16) & 0xff);
a3 = (int)(addr >> 8) & 0xff; a3 = (int)((addr >> 8) & 0xff);
a4 = (int)addr & 0xff; a4 = (int)(addr & 0xff);
sprintf(name, "%d.%d.%d.%d.in-addr.arpa", a4, a3, a2, a1); sprintf(name, "%d.%d.%d.%d.in-addr.arpa", a4, a3, a2, a1);
aquery->remaining_lookups = p + 1; aquery->remaining_lookups = p + 1;
ares_query(aquery->channel, name, C_IN, T_PTR, addr_callback, ares_query(aquery->channel, name, C_IN, T_PTR, addr_callback,

View File

@@ -37,14 +37,11 @@ The parameter
.I name .I name
gives the hostname as a NUL-terminated C string, and gives the hostname as a NUL-terminated C string, and
.I family .I family
gives the desired type of address for the resulting host entry. When gives the desired type of address for the resulting host entry. When the
the query is complete or has failed, the ares library will invoke query is complete or has failed, the ares library will invoke \fIcallback\fP.
.IR callback . Completion or failure of the query may happen immediately, or may happen
Completion or failure of the query may happen immediately, or may during a later call to \fIares_process(3)\fP, \fIares_destroy(3)\fP or
happen during a later call to \fIares_cancel(3)\fP.
.BR ares_process (3)
or
.BR ares_destroy (3).
.PP .PP
The callback argument The callback argument
.I arg .I arg
@@ -96,7 +93,8 @@ did not complete successfully,
will be will be
.BR NULL . .BR NULL .
.SH SEE ALSO .SH SEE ALSO
.BR ares_process (3) .BR ares_process (3),
.BR ares_gethostbyaddr (3)
.SH AUTHOR .SH AUTHOR
Greg Hudson, MIT Information Systems Greg Hudson, MIT Information Systems
.br .br

View File

@@ -21,11 +21,9 @@ ares_mkquery \- Compose a single-question DNS query buffer
.nf .nf
.B #include <ares.h> .B #include <ares.h>
.PP .PP
.B .B int ares_mkquery(const char *\fIname\fP, int \fIdnsclass\fP, int \fItype\fP,
int ares_mkquery(const char *\fIname\fP, int \fIdnsclass\fP, int \fItype\fP, .B unsigned short \fIid\fP, int \fIrd\fP, char **\fIbuf\fP,
.B .B int *\fIbuflen\fP)
unsigned short \fIid\fP, int \fIrd\fP, char **\fIbuf\fP,
int *\fIbuflen\fP)
.fi .fi
.SH DESCRIPTION .SH DESCRIPTION
The The
@@ -52,8 +50,7 @@ stored in the variable pointed to by
and the length of which will be stored in the variable pointed to by and the length of which will be stored in the variable pointed to by
.IR buflen . .IR buflen .
It is the caller's responsibility to free this buffer using It is the caller's responsibility to free this buffer using
.B ares_free_string \fIares_free_string(3)\fP when it is no longer needed.
when it is no longer needed.
.SH RETURN VALUES .SH RETURN VALUES
.B ares_mkquery .B ares_mkquery
can return any of the following values: can return any of the following values:

View File

@@ -21,9 +21,8 @@ ares_parse_a_reply \- Parse a reply to a DNS query of type A into a hostent
.nf .nf
.B #include <ares.h> .B #include <ares.h>
.PP .PP
.B .B int ares_parse_a_reply(const unsigned char *\fIabuf\fP, int \fIalen\fP,
int ares_parse_a_reply(const unsigned char *\fIabuf\fB, int \fIalen\fB, .B struct hostent **\fIhost\fP);
.B struct hostent **\fIhost\fB);
.fi .fi
.SH DESCRIPTION .SH DESCRIPTION
The The

View File

@@ -21,11 +21,9 @@ ares_parse_ptr_reply \- Parse a reply to a DNS query of type PTR into a hostent
.nf .nf
.B #include <ares.h> .B #include <ares.h>
.PP .PP
.B .B int ares_parse_ptr_reply(const unsigned char *\fIabuf\fP, int \fIalen\fP,
int ares_parse_ptr_reply(const unsigned char *\fIabuf\fB, int \fIalen\fB, .B const void *\fIaddr\fP, int \fIaddrlen\fP, int \fIfamily\fP,
.B .B struct hostent **\fIhost\fP);
const void *\fIaddr\fP, int \fIaddrlen\fP, int \fIfamily\fP,
.B struct hostent **\fIhost\fB);
.fi .fi
.SH DESCRIPTION .SH DESCRIPTION
The The

View File

@@ -35,13 +35,10 @@ The file descriptor sets pointed to by
and and
.I write_fds .I write_fds
should have file descriptors set in them according to whether the file should have file descriptors set in them according to whether the file
descriptors specified by descriptors specified by \fIares_fds(3)\fP are ready for reading and writing.
.BR ares_fds (3) (The easiest way to determine this information is to invoke
are ready for reading and writing. (The easiest way to determine this
information is to invoke
.B select .B select
with a timeout no greater than the timeout given by with a timeout no greater than the timeout given by \fIares_timeout(3)\fP ).
.BR ares_timeout (3)).
.PP .PP
The The
.B ares_process .B ares_process

View File

@@ -24,8 +24,7 @@ ares_send \- Initiate a DNS query
.B typedef void (*ares_callback)(void *\fIarg\fP, int \fIstatus\fP, .B typedef void (*ares_callback)(void *\fIarg\fP, int \fIstatus\fP,
.B unsigned char *\fIabuf\fP, int \fIalen\fP) .B unsigned char *\fIabuf\fP, int \fIalen\fP)
.PP .PP
.B .B void ares_send(ares_channel \fIchannel\fP, const unsigned char *\fIqbuf\fP,
void ares_send(ares_channel \fIchannel\fP, const unsigned char *\fIqbuf\fP,
.B int \fIqlen\fP, ares_callback \fIcallback\fP, void *\fIarg\fP) .B int \fIqlen\fP, ares_callback \fIcallback\fP, void *\fIarg\fP)
.fi .fi
.SH DESCRIPTION .SH DESCRIPTION

View File

@@ -35,7 +35,9 @@ const char *ares_strerror(int code)
"Timeout while contacting DNS servers", "Timeout while contacting DNS servers",
"End of file", "End of file",
"Error reading file", "Error reading file",
"Out of memory" "Out of memory",
"Channel is being destroyed",
"Misformatted string"
}; };
assert(code >= 0 && code < (int)(sizeof(errtext) / sizeof(*errtext))); assert(code >= 0 && code < (int)(sizeof(errtext) / sizeof(*errtext)));

View File

@@ -27,10 +27,8 @@ ares_fds \- Get file descriptors to select on for name service
.SH DESCRIPTION .SH DESCRIPTION
The The
.B ares_timeout .B ares_timeout
function determines the maximum time for which the caller should wait function determines the maximum time for which the caller should wait before
before invoking invoking \fIares_process(3)\fP to process timeouts. The parameter
.BR ares_process (3)
to process timeouts. The parameter
.I maxtv .I maxtv
specifies a existing maximum timeout, or specifies a existing maximum timeout, or
.B NULL .B NULL

View File

@@ -4,12 +4,12 @@
#define ARES__VERSION_H #define ARES__VERSION_H
#define ARES_VERSION_MAJOR 1 #define ARES_VERSION_MAJOR 1
#define ARES_VERSION_MINOR 0 #define ARES_VERSION_MINOR 2
#define ARES_VERSION_PATCH 0 #define ARES_VERSION_PATCH 0
#define ARES_VERSION ((ARES_VERSION_MAJOR<<16)|\ #define ARES_VERSION ((ARES_VERSION_MAJOR<<16)|\
(ARES_VERSION_MINOR<<8)|\ (ARES_VERSION_MINOR<<8)|\
(ARES_VERSION_PATCH)) (ARES_VERSION_PATCH))
#define ARES_VERSION_STR "1.0.0" #define ARES_VERSION_STR "1.2.0"
const char *ares_version(int *version); const char *ares_version(int *version);

4
ares/buildconf Executable file
View File

@@ -0,0 +1,4 @@
#!/bin/sh
aclocal
autoconf

View File

@@ -96,3 +96,5 @@ for(@entries) {
`gzip -9 $name-$version.tar`; `gzip -9 $name-$version.tar`;
# remove the dir # remove the dir
`rm -rf $name-$version`; `rm -rf $name-$version`;
print "NOTE: now cvs tag this release!\n";

Binary file not shown.

Binary file not shown.

View File

@@ -67,7 +67,7 @@ echo "buildconf: autoheader version $ah_version (ok)"
# automake 1.7 or newer # automake 1.7 or newer
# #
need_automake="1.7" need_automake="1.7"
am_version=`${AUTOMAKE:-automake} --version 2>/dev/null|head -1| sed -e 's/^.* \([0-9]\)/\1/' -e 's/[a-z]* *$//'` am_version=`${AUTOMAKE:-automake} --version 2>/dev/null|head -1| sed -e 's/^.* \([0-9]\)/\1/' -e 's/[a-z]* *$//' -e 's/\(.*\)\(-p.*\)/\1/'`
if test -z "$am_version"; then if test -z "$am_version"; then
echo "buildconf: automake not found." echo "buildconf: automake not found."
echo " You need automake version $need_automake or newer installed." echo " You need automake version $need_automake or newer installed."
@@ -159,7 +159,7 @@ fi
echo "buildconf: running libtoolize" echo "buildconf: running libtoolize"
${LIBTOOLIZE:-libtoolize} --copy --automake --force || die "The command '${LIBTOOLIZE:-libtoolize} --copy --automake --force' failed" ${LIBTOOLIZE:-libtoolize} --copy --automake --force || die "The command '${LIBTOOLIZE:-libtoolize} --copy --automake --force' failed"
echo "buildconf: running aclocal" echo "buildconf: running aclocal"
${ACLOCAL:-aclocal} || die "The command '${AUTOHEADER:-aclocal}' failed" ${ACLOCAL:-aclocal} $ACLOCAL_FLAGS || die "The command '${ACLOCAL:-aclocal}${ACLOCAL_FLAGS:+" $ACLOCAL_FLAGS"}' failed"
echo "buildconf: running aclocal hack to convert all mv to mv -f" echo "buildconf: running aclocal hack to convert all mv to mv -f"
perl -i.bak -pe 's/\bmv +([^-\s])/mv -f $1/g' aclocal.m4 perl -i.bak -pe 's/\bmv +([^-\s])/mv -f $1/g' aclocal.m4
echo "buildconf: running autoheader" echo "buildconf: running autoheader"
@@ -170,7 +170,7 @@ ${AUTOCONF:-autoconf} || die "The command '${AUTOCONF:-autoconf}' failed"
if test -d ares; then if test -d ares; then
cd ares cd ares
echo "buildconf: running aclocal in the ares directory" echo "buildconf: running aclocal in the ares directory"
${ACLOCAL:-aclocal} || die "The command '${ACLOCAL:-aclocal}' failed" ${ACLOCAL:-aclocal} $ACLOCAL_FLAGS || die "The command '${ACLOCAL:-aclocal}${ACLOCAL_FLAGS:+" $ACLOCAL_FLAGS"}' failed"
echo "buildconf: running autoconf in the ares directory" echo "buildconf: running autoconf in the ares directory"
${AUTOCONF:-autoconf} || die "The command '${AUTOCONF:-autoconf}' failed" ${AUTOCONF:-autoconf} || die "The command '${AUTOCONF:-autoconf}' failed"
cd .. cd ..

View File

@@ -24,14 +24,14 @@ AC_PATH_PROG( AR, ar, , $PATH:/usr/bin:/usr/local/bin:/usr/ccs/bin)
AC_SUBST(AR) AC_SUBST(AR)
dnl figure out the libcurl version dnl figure out the libcurl version
VERSION=`$SED -ne 's/^#define LIBCURL_VERSION "\(.*\)"/\1/p' ${srcdir}/include/curl/curl.h` VERSION=`$SED -ne 's/^#define LIBCURL_VERSION "\(.*\)"/\1/p' ${srcdir}/include/curl/curlver.h`
AM_INIT_AUTOMAKE(curl,$VERSION) AM_INIT_AUTOMAKE(curl,$VERSION)
AC_MSG_CHECKING([curl version]) AC_MSG_CHECKING([curl version])
AC_MSG_RESULT($VERSION) AC_MSG_RESULT($VERSION)
dnl dnl
dnl we extract the numerical version for curl-config only dnl we extract the numerical version for curl-config only
VERSIONNUM=`$SED -ne 's/^#define LIBCURL_VERSION_NUM 0x\(.*\)/\1/p' ${srcdir}/include/curl/curl.h` VERSIONNUM=`$SED -ne 's/^#define LIBCURL_VERSION_NUM 0x\(.*\)/\1/p' ${srcdir}/include/curl/curlver.h`
AC_SUBST(VERSIONNUM) AC_SUBST(VERSIONNUM)
dnl Solaris pkgadd support definitions dnl Solaris pkgadd support definitions
@@ -384,6 +384,8 @@ main()
if test "$ipv6" = "yes"; then if test "$ipv6" = "yes"; then
CURL_CHECK_WORKING_GETADDRINFO CURL_CHECK_WORKING_GETADDRINFO
CURL_CHECK_NI_WITHSCOPEID
fi fi
dnl ********************************************************************** dnl **********************************************************************
@@ -693,7 +695,7 @@ AC_HELP_STRING([--without-ssl], [disable SSL]),
if test X"$OPT_SSL" = Xno if test X"$OPT_SSL" = Xno
then then
AC_MSG_WARN(SSL/https support disabled) AC_MSG_WARN([SSL disabled, you will not be able to use HTTPS, FTPS, NTLM and more])
else else
dnl Check for and handle argument to --with-ssl. dnl Check for and handle argument to --with-ssl.
@@ -915,6 +917,7 @@ printf("just fine");
#endif #endif
], ],
[ AC_MSG_RESULT([yes]) [ AC_MSG_RESULT([yes])
RECENTAIX=yes
OPT_THREAD=off ], OPT_THREAD=off ],
[ AC_MSG_RESULT([no]) ] [ AC_MSG_RESULT([no]) ]
) )
@@ -952,10 +955,31 @@ else
dnl is there a localtime_r() dnl is there a localtime_r()
CURL_CHECK_LOCALTIME_R() CURL_CHECK_LOCALTIME_R()
AC_CHECK_FUNCS( gmtime_r ) dnl is there a strerror_r()
CURL_CHECK_STRERROR_R()
AC_CHECK_FUNCS( gmtime_r )
fi fi
dnl for recent AIX versions, we skip all the thread-safe checks above since
dnl they claim a thread-safe libc using the standard API. But there are
dnl some functions still not thread-safe. Check for these!
dnl Let's hope this split URL remains working:
dnl http://publibn.boulder.ibm.com/doc_link/en_US/a_doc_lib/aixprggd/ \
dnl genprogc/thread_quick_ref.htm
if test "x$RECENTAIX" = "xyes"; then
dnl is there a localtime_r()
CURL_CHECK_LOCALTIME_R()
dnl is there a strerror_r()
CURL_CHECK_STRERROR_R()
AC_CHECK_FUNCS( gmtime_r )
fi
dnl ********************************************************************** dnl **********************************************************************
dnl Back to "normal" configuring dnl Back to "normal" configuring
dnl ********************************************************************** dnl **********************************************************************
@@ -979,6 +1003,7 @@ AC_CHECK_HEADERS(
arpa/inet.h \ arpa/inet.h \
net/if.h \ net/if.h \
netinet/in.h \ netinet/in.h \
netinet/tcp.h \
netdb.h \ netdb.h \
sys/sockio.h \ sys/sockio.h \
sys/stat.h \ sys/stat.h \
@@ -1015,6 +1040,9 @@ dnl default includes
#ifdef HAVE_SYS_SOCKET_H #ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h> #include <sys/socket.h>
#endif #endif
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
] ]
) )
@@ -1226,6 +1254,7 @@ AC_HELP_STRING([--disable-ares],[Disable ares for name lookups]),
dnl ares so it should not be a problem. dnl ares so it should not be a problem.
if test "x$enableval" = "xyes" ; then if test "x$enableval" = "xyes" ; then
if test -d "$srcdir/ares"; then if test -d "$srcdir/ares"; then
aresembedded="yes"
AC_CONFIG_SUBDIRS(ares) AC_CONFIG_SUBDIRS(ares)
aresinc=`cd $srcdir/ares && pwd` aresinc=`cd $srcdir/ares && pwd`
CPPFLAGS="$CPPFLAGS -I$aresinc" CPPFLAGS="$CPPFLAGS -I$aresinc"
@@ -1240,6 +1269,31 @@ AC_HELP_STRING([--disable-ares],[Disable ares for name lookups]),
CPPFLAGS="$CPPFLAGS -I$enableval/include" CPPFLAGS="$CPPFLAGS -I$enableval/include"
LDFLAGS="$LDFLAGS -L$enableval/lib" LDFLAGS="$LDFLAGS -L$enableval/lib"
fi fi
if test -z "$aresembedded"; then
dnl verify that a sufficient c-ares is here if we have pointed one
dnl out and don't use the "embedded" ares dir (in which case we don't
dnl check it because it might not have been built yet)
AC_MSG_CHECKING([that c-ares is good and recent enough])
AC_LINK_IFELSE( [
#include <ares.h>
/* provide a set of dummy functions in case c-ares was built with debug */
void curl_dofree() { }
void curl_sclose() { }
void curl_domalloc() { }
int main(void)
{
ares_channel channel;
ares_cancel(channel);
return 0;
}
],
AC_MSG_RESULT(yes),
AC_MSG_RESULT(no)
AC_MSG_ERROR([c-ares library defective or too old])
)
fi
;; ;;
esac ], esac ],
AC_MSG_RESULT(no) AC_MSG_RESULT(no)

View File

@@ -2,17 +2,8 @@
;;;; $Id$ ;;;; $Id$
;;; The curl hacker's C conventions. ;;; The curl hacker's C conventions.
;;; See the sample.emacs file on how this file can be made to take
;;; After loading this file and added the mode-hook you can in C ;;; effect automatically when editing curl source files.
;;; files, put something like this to use the curl style
;;; automatically:
;;
;; /* -----------------------------------------------------------------
;; * local variables:
;; * eval: (set c-file-style "curl")
;; * end:
;; */
;;
(defconst curl-c-style (defconst curl-c-style
'((c-basic-offset . 2) '((c-basic-offset . 2)
@@ -37,7 +28,7 @@
(setq tab-width 8 (setq tab-width 8
indent-tabs-mode nil ; Use spaces. Not tabs. indent-tabs-mode nil ; Use spaces. Not tabs.
comment-column 40 comment-column 40
c-font-lock-extra-types (append '("bool" "CURL" "CURLcode" "ssize_t" "size_t" "socklen_t" "fd_set" "time_t" "curl_off_t" "curl_socket_t")) c-font-lock-extra-types (append '("bool" "CURL" "CURLcode" "ssize_t" "size_t" "socklen_t" "fd_set" "time_t" "curl_off_t" "curl_socket_t" "in_addr_t" "CURLSHcode" "CURLMcode"))
) )
;; keybindings for C, C++, and Objective-C. We can put these in ;; keybindings for C, C++, and Objective-C. We can put these in
;; c-mode-base-map because of inheritance ... ;; c-mode-base-map because of inheritance ...

View File

@@ -3,8 +3,9 @@ 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 changelog of the current development status, as one or more of these problems
may have been fixed since this was written! may have been fixed since this was written!
* NTLM authentication with passwords longer than 14 letters fail. There is * --limit-rate using -d or -F does not work. This is because the limit logic
a known fix for this, planned to come in curl 7.11.2 is provided by the curl app in its read/write callbacks, and when doing
-d/-F the callbacks aren't used!
* Doing resumed upload over HTTP does not work with '-C -', because curl * Doing resumed upload over HTTP does not work with '-C -', because curl
doesn't do a HEAD first to get the initial size. This needs to be done doesn't do a HEAD first to get the initial size. This needs to be done
@@ -22,13 +23,6 @@ may have been fixed since this was written!
indicate that the user wants to reach the root dir (this exception SHALL indicate that the user wants to reach the root dir (this exception SHALL
remain even when this bug is fixed). remain even when this bug is fixed).
* 1) libcurl does a POST
2) receives a 100-continue
3) sends away the POST
Now, if nothing else is returned from the server, libcurl MUST return
CURLE_GOT_NOTHING, but it seems it returns CURLE_OK as it seems to count
the 100-continue reply as a good enough reply.
* libcurl doesn't treat the content-length of compressed data properly, as * libcurl doesn't treat the content-length of compressed data properly, as
it seems HTTP servers send the *uncompressed* length in that header and it seems HTTP servers send the *uncompressed* length in that header and
libcurl thinks of it as the *compressed* lenght. Some explanations are here: libcurl thinks of it as the *compressed* lenght. Some explanations are here:
@@ -38,9 +32,6 @@ may have been fixed since this was written!
locally, which is because libcurl doesn't call the write callback with zero locally, which is because libcurl doesn't call the write callback with zero
bytes. Explained here: http://curl.haxx.se/mail/archive-2003-04/0143.html bytes. Explained here: http://curl.haxx.se/mail/archive-2003-04/0143.html
* Using CURLOPT_FAILONERROR (-f/--fail) will make authentication to stop
working if you use anything but plain Basic auth.
* IPv6 support on AIX 4.3.3 doesn't work due to a missing sockaddr_storage * IPv6 support on AIX 4.3.3 doesn't work due to a missing sockaddr_storage
struct. It has been reported to work on AIX 5.1 though. struct. It has been reported to work on AIX 5.1 though.

View File

@@ -63,6 +63,11 @@ USING PASSWORDS
curl -u name:passwd ftp://machine.domain:port/full/path/to/file curl -u name:passwd ftp://machine.domain:port/full/path/to/file
FTPS
It is just like for FTP, but you may also want to specify and use
SSL-specific options for certificates etc.
HTTP HTTP
The HTTP URL doesn't support user and password in the URL string. Curl The HTTP URL doesn't support user and password in the URL string. Curl
@@ -75,6 +80,12 @@ USING PASSWORDS
curl -u name:passwd http://machine.domain/full/path/to/file curl -u name:passwd http://machine.domain/full/path/to/file
HTTP offers many different methods of authentication and curl supports
several: Basic, Digest, NTLM and Negotiate. Without telling which method to
use, curl defaults to Basic. You can also ask curl to pick the most secure
ones out of the ones that the server accepts for the given URL, by using
--anyauth.
NOTE! Since HTTP URLs don't support user and password, you can't use that NOTE! Since HTTP URLs don't support user and password, you can't use that
style when using Curl via a proxy. You _must_ use the -u style fetch style when using Curl via a proxy. You _must_ use the -u style fetch
during such circumstances. during such circumstances.

View File

@@ -28,6 +28,12 @@ server, do one of the following:
With the curl command tool: --cacert [file] With the curl command tool: --cacert [file]
3. Add the CA cert for your server to the existing default CA cert bundle.
The default path of the CA bundle installed with the curl package is:
/usr/local/share/curl/curl-ca-bundle.crt, which can be changed by running
configure with the --with-ca-bundle option pointing out the path of your
choice.
Neglecting to use one of the above menthods when dealing with a server using a Neglecting to use one of the above menthods when dealing with a server using a
certficate that isn't signed by one of the certficates in the installed CA certficate that isn't signed by one of the certficates in the installed CA
cert bundle, will cause SSL to report an error ("certificate verify failed") cert bundle, will cause SSL to report an error ("certificate verify failed")
@@ -40,7 +46,3 @@ connections that previously weren't really secure. It turned out many people
were using previous versions of curl/libcurl without realizing the need for were using previous versions of curl/libcurl without realizing the need for
the CA cert options to get truly secure SSL connections. the CA cert options to get truly secure SSL connections.
The default path of the CA bundle installed with the curl package is:
/usr/local/share/curl/curl-ca-bundle.crt, which can be changed by running
configure with the --with-ca-bundle option pointing out the path of your
choice.

View File

@@ -57,6 +57,13 @@ TODO
FTP FTP
* Optimize the way libcurl uses CWD on each new request over a persistent
connection (on FTP) even if it doesn't have to.
* REST fix for servers not behaving well on >2GB requests. This should fail
if the server doesn't set the pointer to the requested index. The tricky
part is to figure out if the server did the right thing or not.
* Support the most common FTP proxies, Philip Newton provided a list * Support the most common FTP proxies, Philip Newton provided a list
allegedly from ncftp: allegedly from ncftp:
http://curl.haxx.se/mail/archive-2003-04/0126.html http://curl.haxx.se/mail/archive-2003-04/0126.html
@@ -91,6 +98,15 @@ TODO
SSL SSL
* Anton Fedorov's "dumpcert" patch:
http://curl.haxx.se/mail/lib-2004-03/0088.html
* Evaluate/apply Gertjan van Wingerde's SSL patches:
http://curl.haxx.se/mail/lib-2004-03/0087.html
* Peter Sylvester's "Most Significant Common Name" change. Feedback welcome.
At least the UTF8 conversion and comparison should be done. Patch?
* If you really want to improve the SSL situation, you should probably have a * If you really want to improve the SSL situation, you should probably have a
look at SSL cafile loading as well - quick traces look to me like these are look at SSL cafile loading as well - quick traces look to me like these are
done on every request as well, when they should only be necessary once per done on every request as well, when they should only be necessary once per

View File

@@ -2,7 +2,7 @@
.\" nroff -man curl.1 .\" nroff -man curl.1
.\" Written by Daniel Stenberg .\" Written by Daniel Stenberg
.\" .\"
.TH curl 1 "5 Mar 2004" "Curl 7.11.1" "Curl Manual" .TH curl 1 "25 Mar 2004" "Curl 7.11.2" "Curl Manual"
.SH NAME .SH NAME
curl \- transfer a URL curl \- transfer a URL
.SH SYNOPSIS .SH SYNOPSIS
@@ -707,6 +707,11 @@ is a plain '-', it is instead written to stdout. This option has no point when
you're using a shell with decent redirecting capabilities. you're using a shell with decent redirecting capabilities.
If this option is used several times, the last one will be used. If this option is used several times, the last one will be used.
.IP "--tcp-nodelay"
Turn on the TCP_NODELAY option. See the \fIcurl_easy_setopt(3)\fP man page for
details about this option. (Added in 7.11.2)
If this option is used several times, each occurance toggles this on/off.
.IP "-t/--telnet-option <OPT=val>" .IP "-t/--telnet-option <OPT=val>"
Pass options to the telnet protocol. Supported options are: Pass options to the telnet protocol. Supported options are:

View File

@@ -70,6 +70,8 @@ int main(int argc, char **argv)
switch(rc) { switch(rc) {
case -1: case -1:
/* select error */ /* select error */
still_running = 0;
printf("select() returns error, this is badness\n");
break; break;
case 0: case 0:
default: default:

View File

@@ -33,8 +33,8 @@ int main(int argc, char *argv[])
CURL *curl; CURL *curl;
CURLcode res; CURLcode res;
struct HttpPost *formpost=NULL; struct curl_httppost *formpost=NULL;
struct HttpPost *lastptr=NULL; struct curl_httppost *lastptr=NULL;
struct curl_slist *headerlist=NULL; struct curl_slist *headerlist=NULL;
char buf[] = "Expect:"; char buf[] = "Expect:";

View File

@@ -31,5 +31,4 @@ If this function returns NULL, something went wrong and no valid handle was
returned. returned.
.SH "SEE ALSO" .SH "SEE ALSO"
.BR curl_easy_init "(3)," curl_easy_cleanup "(3)," curl_global_init "(3) .BR curl_easy_init "(3)," curl_easy_cleanup "(3)," curl_global_init "(3)
.SH BUGS
Surely there are some, you tell me!

View File

@@ -20,7 +20,7 @@ filled in accordingly and can be relied upon only if the function returns
CURLE_OK. This function is intended to get used *AFTER* a performed transfer, CURLE_OK. This function is intended to get used *AFTER* a performed transfer,
all results from this function are undefined until the transfer is completed. all results from this function are undefined until the transfer is completed.
.SH AVAILABLE INFORMATION .SH AVAILABLE INFORMATION
These are informations that can be extracted: The following information can be extracted:
.IP CURLINFO_EFFECTIVE_URL .IP CURLINFO_EFFECTIVE_URL
Pass a pointer to a 'char *' to receive the last used effective URL. Pass a pointer to a 'char *' to receive the last used effective URL.
.IP CURLINFO_RESPONSE_CODE .IP CURLINFO_RESPONSE_CODE
@@ -51,7 +51,7 @@ pre-transfer commands and negotiations that are specific to the particular
protocol(s) involved. protocol(s) involved.
.IP CURLINFO_STARTTRANSFER_TIME .IP CURLINFO_STARTTRANSFER_TIME
Pass a pointer to a double to receive the time, in seconds, it took from the Pass a pointer to a double to receive the time, in seconds, it took from the
start until the first byte is just about to be transfered. This includes start until the first byte is just about to be transferred. This includes
CURLINFO_PRETRANSFER_TIME and also the time the server needs to calculate CURLINFO_PRETRANSFER_TIME and also the time the server needs to calculate
the result. the result.
.IP CURLINFO_REDIRECT_TIME .IP CURLINFO_REDIRECT_TIME
@@ -106,7 +106,7 @@ method(s) available. The meaning of the bits is explained in the
CURLOPT_HTTPAUTH option for \fIcurl_easy_setopt(3)\fP. (Added in 7.10.8) CURLOPT_HTTPAUTH option for \fIcurl_easy_setopt(3)\fP. (Added in 7.10.8)
.IP CURLINFO_PROXYAUTH_AVAIL .IP CURLINFO_PROXYAUTH_AVAIL
Pass a pointer to a long to receive a bitmask indicating the authentication Pass a pointer to a long to receive a bitmask indicating the authentication
method(s) available for your proxy athentication. (Added in 7.10.8) method(s) available for your proxy authentication. (Added in 7.10.8)
.SH RETURN VALUE .SH RETURN VALUE
If the operation was successful, CURLE_OK is returned. Otherwise an If the operation was successful, CURLE_OK is returned. Otherwise an
appropriate error code will be returned. appropriate error code will be returned.

View File

@@ -13,7 +13,7 @@ curl_easy_init - Start a libcurl easy session
.SH DESCRIPTION .SH DESCRIPTION
This function must be the first function to call, and it returns a CURL easy This function must be the first function to call, and it returns a CURL easy
handle that you must use as input to other easy-functions. curl_easy_init handle that you must use as input to other easy-functions. curl_easy_init
intializes curl and this call \fBMUST\fP have a corresponding call to initializes curl and this call \fBMUST\fP have a corresponding call to
\fIcurl_easy_cleanup(3)\fP when the operation is complete. \fIcurl_easy_cleanup(3)\fP when the operation is complete.
.SH RETURN VALUE .SH RETURN VALUE
@@ -21,5 +21,3 @@ If this function returns NULL, something went wrong and you cannot use the
other curl functions. other curl functions.
.SH "SEE ALSO" .SH "SEE ALSO"
.BR curl_easy_cleanup "(3), " curl_global_init "(3) .BR curl_easy_cleanup "(3), " curl_global_init "(3)
.SH BUGS
Surely there are some, you tell me!

View File

@@ -85,7 +85,7 @@ lookups. It enables nice timeouts for name resolves without signals.
.IP CURLOPT_WRITEFUNCTION .IP CURLOPT_WRITEFUNCTION
Function pointer that should match the following prototype: \fBsize_t Function pointer that should match the following prototype: \fBsize_t
function( void *ptr, size_t size, size_t nmemb, void *stream);\fP This function( void *ptr, size_t size, size_t nmemb, void *stream);\fP This
function gets called by libcurl as soon as there is data reveiced that needs function gets called by libcurl as soon as there is data received that needs
to be saved. The size of the data pointed to by \fIptr\fP is \fIsize\fP to be saved. The size of the data pointed to by \fIptr\fP is \fIsize\fP
multiplied with \fInmemb\fP, it will not be zero terminated. Return the number multiplied with \fInmemb\fP, it will not be zero terminated. Return the number
of bytes actually taken care of. If that amount differs from the amount passed of bytes actually taken care of. If that amount differs from the amount passed
@@ -165,7 +165,7 @@ Function pointer that should match the following prototype: \fIint
curl_debug_callback (CURL *, curl_infotype, char *, size_t, void *);\fP curl_debug_callback (CURL *, curl_infotype, char *, size_t, void *);\fP
\fICURLOPT_DEBUGFUNCTION\fP replaces the standard debug function used when \fICURLOPT_DEBUGFUNCTION\fP replaces the standard debug function used when
\fICURLOPT_VERBOSE \fP is in effect. This callback receives debug information, \fICURLOPT_VERBOSE \fP is in effect. This callback receives debug information,
as specified with the \fBcurl_infotype\fP argument. This funtion must return as specified with the \fBcurl_infotype\fP argument. This function must return
0. The data pointed to by the char * passed to this function WILL NOT be zero 0. The data pointed to by the char * passed to this function WILL NOT be zero
terminated, but will be exactly of the size as told by the size_t argument. terminated, but will be exactly of the size as told by the size_t argument.
@@ -191,7 +191,7 @@ Function pointer that should match the following prototype: \fBCURLcode
sslctxfun(CURL *curl, void *sslctx, void *parm);\fP This function gets called sslctxfun(CURL *curl, void *sslctx, void *parm);\fP This function gets called
by libcurl just before the initialization of an SSL connection after having by libcurl just before the initialization of an SSL connection after having
processed all other SSL related options to give a last chance to an processed all other SSL related options to give a last chance to an
application to modify the behaviour of openssl's ssl initilaization. The application to modify the behaviour of openssl's ssl initialization. The
\fIsslctx\fP parameter is actually a pointer to an openssl \fISSL_CTX\fP. If \fIsslctx\fP parameter is actually a pointer to an openssl \fISSL_CTX\fP. If
an error is returned no attempt to establish a connection is made and the an error is returned no attempt to establish a connection is made and the
perform operation will return the error code from this callback function. Set perform operation will return the error code from this callback function. Set
@@ -249,8 +249,8 @@ be prefixed with [protocol]:// since any such prefix will be ignored. The
proxy's port number may optionally be specified with the separate option proxy's port number may optionally be specified with the separate option
\fICURLOPT_PROXYPORT\fP. \fICURLOPT_PROXYPORT\fP.
\fBNOTE:\fP when you tell the library to use a HTTP proxy, libcurl will \fBNOTE:\fP when you tell the library to use an HTTP proxy, libcurl will
transparently convert operations to HTTP even if you specify a FTP URL transparently convert operations to HTTP even if you specify an FTP URL
etc. This may have an impact on what other features of the library you can etc. This may have an impact on what other features of the library you can
use, such as \fICURLOPT_QUOTE\fP and similar FTP specifics that don't work use, such as \fICURLOPT_QUOTE\fP and similar FTP specifics that don't work
unless you tunnel through the HTTP proxy. Such tunneling is activated with unless you tunnel through the HTTP proxy. Such tunneling is activated with
@@ -282,19 +282,35 @@ libcurl caches this info for 60 seconds.
.IP CURLOPT_DNS_USE_GLOBAL_CACHE .IP CURLOPT_DNS_USE_GLOBAL_CACHE
Pass a long. If the value is non-zero, it tells curl to use a global DNS cache Pass a long. If the value is non-zero, it tells curl to use a global DNS cache
that will survive between easy handle creations and deletions. This is not that will survive between easy handle creations and deletions. This is not
thread-safe and this will use a global varible. thread-safe and this will use a global variable.
\fBWARNING:\fP this option is considered obsolete. Stop using it. Switch over \fBWARNING:\fP this option is considered obsolete. Stop using it. Switch over
to using the share interface instead! See \fICURLOPT_SHARE\fP and to using the share interface instead! See \fICURLOPT_SHARE\fP and
\fIcurl_share_init(3)\fP. \fIcurl_share_init(3)\fP.
.IP CURLOPT_BUFFERSIZE .IP CURLOPT_BUFFERSIZE
Pass a long specifying your prefered size for the receive buffer in libcurl. Pass a long specifying your preferred size for the receive buffer in libcurl.
The main point of this would be that the write callback gets called more often The main point of this would be that the write callback gets called more often
and with smaller chunks. This is just treated as a request, not an order. You and with smaller chunks. This is just treated as a request, not an order. You
cannot be guaranteed to actually get the given size. (Added in 7.10) cannot be guaranteed to actually get the given size. (Added in 7.10)
.IP CURLOPT_PORT .IP CURLOPT_PORT
Pass a long specifying what remote port number to connect to, instead of the Pass a long specifying what remote port number to connect to, instead of the
one specified in the URL or the default port for the used protocol. one specified in the URL or the default port for the used protocol.
.IP CURLOPT_TCP_NODELAY
Pass a long specifying whether the TCP_NODELAY option should be set or
cleared (1 = set, 0 = clear). The option is cleared by default. This
will have no effect after the connection has been established.
Setting this option will disable TCP's Nagle algorithm. The purpose of
this algorithm is to try to minimize the number of small packets on
the network (where "small packets" means TCP segments less than the
Maximum Segment Size (MSS) for the network).
Maximizing the amount of data sent per TCP segment is good because it
amortizes the overhead of the send. However, in some cases (most
notably telnet or rlogin) small segments may need to be sent
without delay. This is less efficient than sending larger amounts of
data at a time, and can contribute to congestion on the network if
overdone.
.SH NAMES and PASSWORDS OPTIONS (Authentication) .SH NAMES and PASSWORDS OPTIONS (Authentication)
.IP CURLOPT_NETRC .IP CURLOPT_NETRC
This parameter controls the preference of libcurl between using user names and This parameter controls the preference of libcurl between using user names and
@@ -370,7 +386,7 @@ regular old-fashioned Basic method.
.IP CURLAUTH_GSSNEGOTIATE .IP CURLAUTH_GSSNEGOTIATE
HTTP GSS-Negotiate authentication. The GSS-Negotiate (also known as plain HTTP GSS-Negotiate authentication. The GSS-Negotiate (also known as plain
"Negotiate") method was designed by Microsoft and is used in their web "Negotiate") method was designed by Microsoft and is used in their web
aplications. It is primarily meant as a support for Kerberos5 authentication applications. It is primarily meant as a support for Kerberos5 authentication
but may be also used along with another authentication methods. For more but may be also used along with another authentication methods. For more
information see IETF draft draft-brezak-spnego-http-04.txt. information see IETF draft draft-brezak-spnego-http-04.txt.
@@ -379,17 +395,17 @@ this to work.
.IP CURLAUTH_NTLM .IP CURLAUTH_NTLM
HTTP NTLM authentication. A proprietary protocol invented and used by HTTP NTLM authentication. A proprietary protocol invented and used by
Microsoft. It uses a challenge-response and hash concept similar to Digest, to Microsoft. It uses a challenge-response and hash concept similar to Digest, to
prevent the password from being evesdropped. prevent the password from being eavesdropped.
\fBNOTE\fP that you need to build libcurl with SSL support for this option to \fBNOTE\fP that you need to build libcurl with SSL support for this option to
work. work.
.IP CURLAUTH_ANY .IP CURLAUTH_ANY
This is a convenience macro that sets all bits and thus makes libcurl pick any This is a convenience macro that sets all bits and thus makes libcurl pick any
it finds suitable. libcurl will automaticly select the one it finds most it finds suitable. libcurl will automatically select the one it finds most
secure. secure.
.IP CURLAUTH_ANYSAFE .IP CURLAUTH_ANYSAFE
This is a convenience macro that sets all bits except Basic and thus makes This is a convenience macro that sets all bits except Basic and thus makes
libcurl pick any it finds suitable. libcurl will automaticly select the one it libcurl pick any it finds suitable. libcurl will automatically select the one it
finds most secure. finds most secure.
.RE .RE
.IP CURLOPT_PROXYAUTH .IP CURLOPT_PROXYAUTH
@@ -405,7 +421,7 @@ this writing, only Basic and NTLM work. (Added in 7.10.7)
.SH HTTP OPTIONS .SH HTTP OPTIONS
.IP CURLOPT_AUTOREFERER .IP CURLOPT_AUTOREFERER
Pass a non-zero parameter to enable this. When enabled, libcurl will Pass a non-zero parameter to enable this. When enabled, libcurl will
automaticly set the Referer: field in requests where it follows a Location: automatically set the Referer: field in requests where it follows a Location:
redirect. redirect.
.IP CURLOPT_ENCODING .IP CURLOPT_ENCODING
Sets the contents of the Accept-Encoding: header sent in an HTTP Sets the contents of the Accept-Encoding: header sent in an HTTP
@@ -422,7 +438,7 @@ encoding done by the server is ignored. See the special file
lib/README.encoding for details. lib/README.encoding for details.
.IP CURLOPT_FOLLOWLOCATION .IP CURLOPT_FOLLOWLOCATION
A non-zero parameter tells the library to follow any Location: header that the A non-zero parameter tells the library to follow any Location: header that the
server sends as part of a HTTP header. server sends as part of an HTTP header.
\fBNOTE:\fP this means that the library will re-send the same request on the \fBNOTE:\fP this means that the library will re-send the same request on the
new location and follow new Location: headers all the way until no more such new location and follow new Location: headers all the way until no more such
@@ -447,7 +463,7 @@ one by HTML forms. See the \fICURLOPT_POSTFIELDS\fP option for how to specify
the data to post and \fICURLOPT_POSTFIELDSIZE\fP in how to set the data the data to post and \fICURLOPT_POSTFIELDSIZE\fP in how to set the data
size. Using the \fICURLOPT_POSTFIELDS\fP option implies this option. size. Using the \fICURLOPT_POSTFIELDS\fP option implies this option.
.IP CURLOPT_POSTFIELDS .IP CURLOPT_POSTFIELDS
Pass a char * as parameter, which should be the full data to post in a HTTP Pass a char * as parameter, which should be the full data to post in an HTTP
post operation. You need to make sure that the data is formatted the way you post operation. You need to make sure that the data is formatted the way you
want the server to receive it. libcurl will not convert or encode it for want the server to receive it. libcurl will not convert or encode it for
you. Most web servers will assume this data to be url-encoded. Take note. you. Most web servers will assume this data to be url-encoded. Take note.
@@ -529,9 +545,10 @@ set a cookie in the http request. The format of the string should be
NAME=CONTENTS, where NAME is the cookie name and CONTENTS is what the cookie NAME=CONTENTS, where NAME is the cookie name and CONTENTS is what the cookie
should contain. should contain.
If you need to set mulitple cookies, you need to set them all using a single If you need to set multiple cookies, you need to set them all using a single
option and thus you need to concat them all in one single string. Set multiple option and thus you need to concatenate them all in one single string. Set
cookies in one string like this: "name1=content1; name2=content2;" etc. multiple cookies in one string like this: "name1=content1; name2=content2;"
etc.
Using this option multiple times will only make the latest string override the Using this option multiple times will only make the latest string override the
previously ones. previously ones.
@@ -622,7 +639,7 @@ only files in their response to NLST; they might not include subdirectories
and symbolic links. and symbolic links.
.IP CURLOPT_FTPAPPEND .IP CURLOPT_FTPAPPEND
A non-zero parameter tells the library to append to the remote file instead of A non-zero parameter tells the library to append to the remote file instead of
overwrite it. This is only useful when uploading to a ftp site. overwrite it. This is only useful when uploading to an ftp site.
.IP CURLOPT_FTP_USE_EPRT .IP CURLOPT_FTP_USE_EPRT
Pass a long. If the value is non-zero, it tells curl to use the EPRT (and Pass a long. If the value is non-zero, it tells curl to use the EPRT (and
LPRT) command when doing active FTP downloads (which is enabled by LPRT) command when doing active FTP downloads (which is enabled by
@@ -684,7 +701,7 @@ Pass an curl_off_t as parameter. It contains the offset in number of bytes
that you want the transfer to start from. (Added in 7.11.0) that you want the transfer to start from. (Added in 7.11.0)
.IP CURLOPT_CUSTOMREQUEST .IP CURLOPT_CUSTOMREQUEST
Pass a pointer to a zero terminated string as parameter. It will be user Pass a pointer to a zero terminated string as parameter. It will be user
instead of GET or HEAD when doing a HTTP request, or instead of LIST or NLST instead of GET or HEAD when doing an HTTP request, or instead of LIST or NLST
when doing an ftp directory listing. This is useful for doing DELETE or other when doing an ftp directory listing. This is useful for doing DELETE or other
more or less obscure HTTP requests. Don't do this at will, make sure your more or less obscure HTTP requests. Don't do this at will, make sure your
server supports the command first. server supports the command first.
@@ -863,7 +880,7 @@ key.
\fBNOTE:\fPIf the crypto device cannot be loaded, \fBNOTE:\fPIf the crypto device cannot be loaded,
\fICURLE_SSL_ENGINE_NOTFOUND\fP is returned. \fICURLE_SSL_ENGINE_NOTFOUND\fP is returned.
.IP CURLOPT_SSLENGINE_DEFAULT .IP CURLOPT_SSLENGINE_DEFAULT
Sets the actual crypto engine as the default for (asymetric) crypto Sets the actual crypto engine as the default for (asymmetric) crypto
operations. operations.
\fBNOTE:\fPIf the crypto device cannot be set, \fBNOTE:\fPIf the crypto device cannot be set,
@@ -904,8 +921,8 @@ in the SSL handshake, set 1 to check existence, 2 to ensure that it matches
the provided hostname. This is by default set to 2. (default changed in 7.10) the provided hostname. This is by default set to 2. (default changed in 7.10)
.IP CURLOPT_SSL_CIPHER_LIST .IP CURLOPT_SSL_CIPHER_LIST
Pass a char *, pointing to a zero terminated string holding the list of Pass a char *, pointing to a zero terminated string holding the list of
ciphers to use for the SSL connection. The list must be syntactly correct, it ciphers to use for the SSL connection. The list must be syntactically correct,
consists of one or more cipher strings separated by colons. Commas or spaces it consists of one or more cipher strings separated by colons. Commas or spaces
are also acceptable separators but colons are normally used, \!, \- and \+ can are also acceptable separators but colons are normally used, \!, \- and \+ can
be used as operators. Valid examples of cipher lists include 'RC4-SHA', be used as operators. Valid examples of cipher lists include 'RC4-SHA',
\'SHA1+DES\', 'TLSv1' and 'DEFAULT'. The default list is normally set when you \'SHA1+DES\', 'TLSv1' and 'DEFAULT'. The default list is normally set when you

View File

@@ -13,7 +13,7 @@ curl_formadd - add a section to a multipart/formdata HTTP POST
.ad .ad
.SH DESCRIPTION .SH DESCRIPTION
curl_formadd() is used to append sections when building a multipart/formdata curl_formadd() is used to append sections when building a multipart/formdata
HTTP POST (sometimes refered to as rfc1867-style posts). Append one section at HTTP POST (sometimes referred to as rfc1867-style posts). Append one section at
a time until you've added all the sections you want included and then you pass a time until you've added all the sections you want included and then you pass
the \fIfirstitem\fP pointer as parameter to \fBCURLOPT_HTTPPOST\fP. the \fIfirstitem\fP pointer as parameter to \fBCURLOPT_HTTPPOST\fP.
\fIlastitem\fP is set after each call and on repeated invokes it should be \fIlastitem\fP is set after each call and on repeated invokes it should be
@@ -81,7 +81,7 @@ internally chosen one.
.B CURLFORM_FILENAME .B CURLFORM_FILENAME
followed by a pointer to a string to a name, will make libcurl use the given followed by a pointer to a string to a name, will make libcurl use the given
name in the file upload part, intead of the actual file name given to name in the file upload part, instead of the actual file name given to
\fICURLFORM_FILE\fP. \fICURLFORM_FILE\fP.
.B BCURLFORM_BUFFER .B BCURLFORM_BUFFER

View File

@@ -36,7 +36,7 @@ This string specifies the time on a given day. Syntax supported includes:
.TP .TP
.B time zone items .B time zone items
Specifies international time zone. There are a few acronyms supported, but in Specifies international time zone. There are a few acronyms supported, but in
general you should instead use the specific realtive time compared to general you should instead use the specific relative time compared to
UTC. Supported formats include: -1200, MST, +0100. UTC. Supported formats include: -1200, MST, +0100.
.TP .TP
.B day of the week items .B day of the week items

View File

@@ -42,7 +42,7 @@ See this table for notable exceptions.
Normal printf() clone. Normal printf() clone.
.TP .TP
.B curl_mfprintf() .B curl_mfprintf()
Normal fprinf() clone. Normal fprintf() clone.
.TP .TP
.B curl_msprintf() .B curl_msprintf()
Normal sprintf() clone. Normal sprintf() clone.

View File

@@ -14,6 +14,17 @@ this \fImulti_handle\fP control the specified \fIeasy_handle\fP.
When an easy handle has been added to a multi stack, you can not and you must When an easy handle has been added to a multi stack, you can not and you must
not use \fIcurl_easy_perform(3)\fP on that handle! not use \fIcurl_easy_perform(3)\fP on that handle!
The easy handle will remain added until you remove it again with
\fIcurl_multi_remove_handle(3)\fP. You should remove the easy handle from the
multi stack before you terminate first the easy handle and then the multi
handle:
1 - \fIcurl_multi_remove_handle(3)\fP
2 - \fIcurl_easy_cleanup(3)\fP
3 - \fIcurl_multi_cleanup(3)\fP
.SH RETURN VALUE .SH RETURN VALUE
CURLMcode type, general libcurl multi interface error code. CURLMcode type, general libcurl multi interface error code.
.SH "SEE ALSO" .SH "SEE ALSO"

View File

@@ -11,7 +11,16 @@ curl_multi_cleanup - close down a multi session
.SH DESCRIPTION .SH DESCRIPTION
Cleans up and removes a whole multi stack. It does not free or touch any Cleans up and removes a whole multi stack. It does not free or touch any
individual easy handles in any way - they still need to be closed individual easy handles in any way - they still need to be closed
individually, using the usual \fIcurl_easy_cleanup(3)\fP way. individually, using the usual \fIcurl_easy_cleanup(3)\fP way. The order of
cleaning up should be:
1 - \fIcurl_multi_remove_handle(3)\fP before any easy handles are cleaned up
2 - \fIcurl_easy_cleanup(3)\fP can now be called independently since the easy
handle is no longer connected to the multi handle
3 - \fIcurl_multi_cleanup(3)\fP should be called when all easy handles are
removed
.SH RETURN VALUE .SH RETURN VALUE
CURLMcode type, general libcurl multi interface error code. CURLMcode type, general libcurl multi interface error code.
.SH "SEE ALSO" .SH "SEE ALSO"

View File

@@ -1,9 +1,10 @@
.\" $Id$ .\" $Id$
.\" .\"
.TH curl_multi_fdset 3 "3 May 2002" "libcurl 7.9.5" "libcurl Manual" .TH curl_multi_fdset 3 "15 Apr 2004" "libcurl 7.9.5" "libcurl Manual"
.SH NAME .SH NAME
curl_multi_fdset - extracts file descriptor information from a multi handle curl_multi_fdset - extracts file descriptor information from a multi handle
.SH SYNOPSIS .SH SYNOPSIS
.nf
#include <curl/curl.h> #include <curl/curl.h>
CURLMcode curl_multi_fdset(CURLM *multi_handle, CURLMcode curl_multi_fdset(CURLM *multi_handle,
@@ -14,15 +15,21 @@ CURLMcode curl_multi_fdset(CURLM *multi_handle,
.ad .ad
.SH DESCRIPTION .SH DESCRIPTION
This function extracts file descriptor information from a given multi_handle. This function extracts file descriptor information from a given multi_handle.
libcurl returns its fd_set sets. The application can use these to select() or libcurl returns its fd_set sets. The application can use these to select()
poll() on. The curl_multi_perform() function should be called as soon as one on. The \fIcurl_multi_perform(3)\fI function should be called as soon as one
of them are ready to be read from or written to. of them are ready to be read from or written to.
NOTE that once this call is made, you must not remove the sets you point to, NOTE that once this call is made, you must not remove the sets you point to,
as libcurl will need to be able to read them. It needs them after select() as libcurl will need to be able to read them. It needs them after select()
calls, to know if certain sockets are readable or writable. calls, to know if certain sockets are readable or writable.
You should also be aware that when doing select(), you should consider using a
rather small (single-digit number of seconds) timeout and call
\fIcurl_multi_perform\fP regularly - even if no activity has been seen on the
fd_sets - as otherwise libcurl-internal retries and timeouts may not work as
you'd think.
.SH RETURN VALUE .SH RETURN VALUE
CURLMcode type, general libcurl multi interface error code. See CURLMcode type, general libcurl multi interface error code. See
\fIlibcurl-errors.3\fP \fIlibcurl-errors(3)\fP
.SH "SEE ALSO" .SH "SEE ALSO"
.BR curl_multi_cleanup "(3)," curl_multi_init "(3)" .BR curl_multi_cleanup "(3)," curl_multi_init "(3)"

View File

@@ -23,7 +23,7 @@ remaining messages after this function was called.
The data the returned pointer points to will not survive calling The data the returned pointer points to will not survive calling
\fIcurl_multi_cleanup(3)\fP. \fIcurl_multi_cleanup(3)\fP.
The 'CURLMsg' struct is very simple and only contain very basic informations. The 'CURLMsg' struct is very simple and only contain very basic information.
If more involved information is wanted, the particular "easy handle" in If more involved information is wanted, the particular "easy handle" in
present in that struct and can thus be used in subsequent regular present in that struct and can thus be used in subsequent regular
\fIcurl_easy_getinfo(3)\fP calls (or similar): \fIcurl_easy_getinfo(3)\fP calls (or similar):

View File

@@ -10,7 +10,7 @@ curl_multi_init - create a multi handle
.ad .ad
.SH DESCRIPTION .SH DESCRIPTION
This function returns a CURLM handle to be used as input to all the other This function returns a CURLM handle to be used as input to all the other
multi-functions, sometimes refered to as a multi handle on some places in the multi-functions, sometimes referred to as a multi handle on some places in the
documentation. This init call MUST have a corresponding call to documentation. This init call MUST have a corresponding call to
\fIcurl_multi_cleanup(3)\fP when the operation is complete. \fIcurl_multi_cleanup(3)\fP when the operation is complete.
.SH RETURN VALUE .SH RETURN VALUE

View File

@@ -19,14 +19,14 @@ integer-pointer.
.SH "RETURN VALUE" .SH "RETURN VALUE"
CURLMcode type, general libcurl multi interface error code. CURLMcode type, general libcurl multi interface error code.
If you receive \fICURLM_CALL_MULTI_PERFORM\fP, this basicly means that you If you receive \fICURLM_CALL_MULTI_PERFORM\fP, this basically means that you
should call \fIcurl_multi_perform\fP again, before you select() on more should call \fIcurl_multi_perform\fP again, before you select() on more
actions. You don't have to do it immediately, but the return code means that actions. You don't have to do it immediately, but the return code means that
libcurl may have more data available to return or that there may be more data libcurl may have more data available to return or that there may be more data
to send off before it is "satisfied". to send off before it is "satisfied".
NOTE that this only returns errors etc regarding the whole multi stack. There NOTE that this only returns errors etc regarding the whole multi stack. There
might still have occurred problems on invidual transfers even when this might still have occurred problems on individual transfers even when this
function returns OK. function returns OK.
.SH "TYPICAL USAGE" .SH "TYPICAL USAGE"
Most application will use \fIcurl_multi_fdset(3)\fP to get the multi_handle's Most application will use \fIcurl_multi_fdset(3)\fP to get the multi_handle's

View File

@@ -10,7 +10,7 @@ curl_share_init - Create a shared object
.ad .ad
.SH DESCRIPTION .SH DESCRIPTION
This function returns a CURLSH handle to be used as input to all the other This function returns a CURLSH handle to be used as input to all the other
share-functions, sometimes refered to as a share handle on some places in the share-functions, sometimes referred to as a share handle on some places in the
documentation. This init call MUST have a corresponding call to documentation. This init call MUST have a corresponding call to
\fIcurl_share_cleanup\fP when all operations using the share are complete. \fIcurl_share_cleanup\fP when all operations using the share are complete.

View File

@@ -1 +1 @@
.so curl_strequal.3 .so man3/curl_strequal.3

View File

@@ -23,7 +23,7 @@ return until it is done (successfully or not).
After the transfer has been made, you can set new options and make another After the transfer has been made, you can set new options and make another
transfer, or if you're done, cleanup the session by calling transfer, or if you're done, cleanup the session by calling
\fIcurl_easy_cleanup(3)\fP. If you want persistant connections, you don't \fIcurl_easy_cleanup(3)\fP. If you want persistent connections, you don't
cleanup immediately, but instead run ahead and perform other transfers using cleanup immediately, but instead run ahead and perform other transfers using
the same easy handle. the same easy handle.

View File

@@ -36,7 +36,7 @@ Couldn't resolve host. The given remote host was not resolved.
.IP "CURLE_COULDNT_CONNECT (7)" .IP "CURLE_COULDNT_CONNECT (7)"
Failed to connect() to host or proxy. Failed to connect() to host or proxy.
.IP "CURLE_FTP_WEIRD_SERVER_REPLY (8)" .IP "CURLE_FTP_WEIRD_SERVER_REPLY (8)"
After connecting to a FTP server, libcurl expects to get a certain reply back. After connecting to an FTP server, libcurl expects to get a certain reply back.
This error code implies that it god a strange or bad reply. The given remote This error code implies that it god a strange or bad reply. The given remote
server is probably not an OK FTP server. server is probably not an OK FTP server.
.IP "CURLE_FTP_ACCESS_DENIED (9)" .IP "CURLE_FTP_ACCESS_DENIED (9)"
@@ -93,7 +93,7 @@ There was a problem reading a local file or an error returned by the read
callback. callback.
.IP "CURLE_OUT_OF_MEMORY (27)" .IP "CURLE_OUT_OF_MEMORY (27)"
Out of memory. A memory allocation request failed. This is serious badness and Out of memory. A memory allocation request failed. This is serious badness and
things are severly screwed up if this ever occur. things are severely screwed up if this ever occur.
.IP "CURLE_OPERATION_TIMEOUTED (28)" .IP "CURLE_OPERATION_TIMEOUTED (28)"
Operation timeout. The specified time-out period was reached according to the Operation timeout. The specified time-out period was reached according to the
conditions. conditions.
@@ -106,14 +106,14 @@ specified a good enough address for libcurl to use. See \fICURLOPT_FTPPORT\fP.
The FTP REST command returned error. This should never happen if the server is The FTP REST command returned error. This should never happen if the server is
sane. sane.
.IP "CURLE_FTP_COULDNT_GET_SIZE (32)" .IP "CURLE_FTP_COULDNT_GET_SIZE (32)"
The FTP SIZE command returned errror. SIZE is not a kosher FTP command, it is The FTP SIZE command returned error. SIZE is not a kosher FTP command, it is
an extension and not all servers support it. This is not a surprising error. an extension and not all servers support it. This is not a surprising error.
.IP "CURLE_HTTP_RANGE_ERROR (33)" .IP "CURLE_HTTP_RANGE_ERROR (33)"
The HTTP server does not support or accept range requests. The HTTP server does not support or accept range requests.
.IP "CURLE_HTTP_POST_ERROR (34)" .IP "CURLE_HTTP_POST_ERROR (34)"
This is an odd error that mainly occurs due to internal confusion. This is an odd error that mainly occurs due to internal confusion.
.IP "CURLE_SSL_CONNECT_ERROR (35)" .IP "CURLE_SSL_CONNECT_ERROR (35)"
A problem occured somewhere in the SSL/TLS handshake. You really want the A problem occurred somewhere in the SSL/TLS handshake. You really want the
error buffer and read the message there as it pinpoints the problem slightly error buffer and read the message there as it pinpoints the problem slightly
more. Could be certificates (file formats, paths, permissions), passwords, and more. Could be certificates (file formats, paths, permissions), passwords, and
others. others.
@@ -187,8 +187,19 @@ Requested FTP SSL level failed
.SH "CURLMcode" .SH "CURLMcode"
This is the generic return code used by functions in the libcurl multi This is the generic return code used by functions in the libcurl multi
interface. interface.
.IP "CURLM_CALL_MULTI_PERFORM (-1)"
This is left to be documented. This is not really an error. It means you should call
\fIcurl_multi_perform(3)\fP again without doing select() or similar in between.
.IP "CURLM_OK (0)"
Things are fine.
.IP "CURLM_BAD_HANDLE (1)"
The passed-in handle is not a valid CURLM handle.
.IP "CURLM_BAD_EASY_HANDLE (2)"
An easy handle was not good/valid.
.IP "CURLM_OUT_OF_MEMORY (3)"
You are doomed.
.IP "CURLM_INTERNAL_ERROR (4)"
This can only be returned if libcurl bugs. Please report it to us!
.SH "CURLSHcode" .SH "CURLSHcode"
The "share" interface will return a CURLSHcode to indicate when an The "share" interface will return a CURLSHcode to indicate when an
error has occurred. error has occurred.

View File

@@ -71,7 +71,7 @@ timeout every now and then, should you want that.
A little note here about the return codes from the multi functions, and A little note here about the return codes from the multi functions, and
especially the \fIcurl_multi_perform(3)\fP: if you receive especially the \fIcurl_multi_perform(3)\fP: if you receive
\fICURLM_CALL_MULTI_PERFORM\fP, this basicly means that you should call \fICURLM_CALL_MULTI_PERFORM\fP, this basically means that you should call
\fIcurl_multi_perform(3)\fP again, before you select() on more actions. You \fIcurl_multi_perform(3)\fP again, before you select() on more actions. You
don't have to do it immediately, but the return code means that libcurl may don't have to do it immediately, but the return code means that libcurl may
have more data available to return or that there may be more data to send off have more data available to return or that there may be more data to send off
@@ -97,4 +97,4 @@ to clean them up properly.
If you want to re-use an easy handle that was added to the multi handle for If you want to re-use an easy handle that was added to the multi handle for
transfer, you must first remove it from the multi stack and then re-add it transfer, you must first remove it from the multi stack and then re-add it
again (possbily after having altered some options at your own choice). again (possibly after having altered some options at your own choice).

View File

@@ -21,8 +21,8 @@ libcurl is complete, it \fBmust\fP call \fIcurl_global_cleanup(3)\fP. In
between those two calls, you can use libcurl as described below. between those two calls, you can use libcurl as described below.
To transfer files, you always set up an "easy handle" using To transfer files, you always set up an "easy handle" using
\fIcurl_easy_init(3)\fP, but when you want the file(s) transfered you have the \fIcurl_easy_init(3)\fP, but when you want the file(s) transferred you have
option of using the "easy" interface, or the "multi" interface. the option of using the "easy" interface, or the "multi" interface.
The easy interface is a synchronous interface with which you call The easy interface is a synchronous interface with which you call
\fIcurl_easy_perform(3)\fP and let it perform the transfer. When it is \fIcurl_easy_perform(3)\fP and let it perform the transfer. When it is
@@ -30,7 +30,7 @@ completed, the function return and you can continue. More details are found in
the \fIlibcurl-easy(3)\fP man page. the \fIlibcurl-easy(3)\fP man page.
The multi interface on the other hand is an asynchronous interface, that you The multi interface on the other hand is an asynchronous interface, that you
call and that performs only a little piece of the tranfer on each invoke. It call and that performs only a little piece of the transfer on each invoke. It
is perfect if you want to do things while the transfer is in progress, or is perfect if you want to do things while the transfer is in progress, or
similar. The multi interface allows you to select() on libcurl action, and similar. The multi interface allows you to select() on libcurl action, and
even to easily download multiple files simultaneously using a single thread. even to easily download multiple files simultaneously using a single thread.
@@ -56,7 +56,7 @@ portable environment variable reader
get information about a performed transfer get information about a performed transfer
.TP .TP
.B curl_formadd() .B curl_formadd()
helps building a HTTP form POST helps building an HTTP form POST
.TP .TP
.B curl_formfree() .B curl_formfree()
free a list built with \fIcurl_formadd(3)\fP free a list built with \fIcurl_formadd(3)\fP

View File

@@ -1,8 +1,5 @@
pkginclude_HEADERS = \ pkginclude_HEADERS = \
curl.h \ curl.h curlver.h easy.h mprintf.h stdcheaders.h types.h multi.h
easy.h \
mprintf.h \
stdcheaders.h \
types.h \
multi.h
pkgincludedir= $(includedir)/curl pkgincludedir= $(includedir)/curl
CLEANFILES = *dist

View File

@@ -27,31 +27,7 @@
http://curl.haxx.se/libcurl/ http://curl.haxx.se/libcurl/
*/ */
/* This is the version number of the libcurl package from which this header #include "curlver.h" /* the libcurl version defines */
file origins: */
#define LIBCURL_VERSION "7.11.0-CVS"
/* This is the numeric version of the libcurl version number, meant for easier
parsing and comparions by programs. The LIBCURL_VERSION_NUM define will
always follow this syntax:
0xXXYYZZ
Where XX, YY and ZZ are the main version, release and patch numbers in
hexadecimal. All three numbers are always represented using two digits. 1.2
would appear as "0x010200" while version 9.11.7 appears as "0x090b07".
This 6-digit hexadecimal number does not show pre-release number, 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 0x070b00
/* The numeric version number is also available "in parts" by using these
defines: */
#define LIBCURL_VERSION_MAJOR 7
#define LIBCURL_VERSION_MINOR 11
#define LIBCURL_VERSION_PATCH 0
#include <stdio.h> #include <stdio.h>
#include <limits.h> #include <limits.h>
@@ -786,6 +762,9 @@ typedef enum {
/* The _LARGE version of the standard POSTFIELDSIZE option */ /* The _LARGE version of the standard POSTFIELDSIZE option */
CINIT(POSTFIELDSIZE_LARGE, OFF_T, 120), CINIT(POSTFIELDSIZE_LARGE, OFF_T, 120),
/* Enable/disable the TCP Nagle algorithm */
CINIT(TCP_NODELAY, LONG, 121),
CURLOPT_LASTENTRY /* the last unused */ CURLOPT_LASTENTRY /* the last unused */
} CURLoption; } CURLoption;
@@ -804,12 +783,12 @@ typedef enum {
#ifndef CURL_NO_OLDIES /* define this to test if your app builds with all #ifndef CURL_NO_OLDIES /* define this to test if your app builds with all
the obsolete stuff removed! */ the obsolete stuff removed! */
#define CURLOPT_HTTPREQUEST 0 #define CURLOPT_HTTPREQUEST -1
#define CURLOPT_FTPASCII CURLOPT_TRANSFERTEXT #define CURLOPT_FTPASCII CURLOPT_TRANSFERTEXT
#define CURLOPT_MUTE 0 #define CURLOPT_MUTE -2
#define CURLOPT_PASSWDFUNCTION 0 #define CURLOPT_PASSWDFUNCTION -3
#define CURLOPT_PASSWDDATA 0 #define CURLOPT_PASSWDDATA -4
#define CURLOPT_CLOSEFUNCTION 0 #define CURLOPT_CLOSEFUNCTION -5
#else #else
/* This is set if CURL_NO_OLDIES is defined at compile-time */ /* This is set if CURL_NO_OLDIES is defined at compile-time */
@@ -1090,7 +1069,6 @@ void curl_slist_free_all(struct curl_slist *);
*/ */
time_t curl_getdate(const char *p, const time_t *now); time_t curl_getdate(const char *p, const time_t *now);
#define CURLINFO_STRING 0x100000 #define CURLINFO_STRING 0x100000
#define CURLINFO_LONG 0x200000 #define CURLINFO_LONG 0x200000
#define CURLINFO_DOUBLE 0x300000 #define CURLINFO_DOUBLE 0x300000
@@ -1266,6 +1244,28 @@ typedef struct {
*/ */
curl_version_info_data *curl_version_info(CURLversion); curl_version_info_data *curl_version_info(CURLversion);
/*
* NAME curl_easy_strerror()
*
* DESCRIPTION
*
* The curl_easy_strerror function may be used to turn a CURLcode value
* into the equivalent human readable error string. This is useful
* for printing meaningful error messages.
*/
const char *curl_easy_strerror(CURLcode);
/*
* NAME curl_share_strerror()
*
* DESCRIPTION
*
* The curl_share_strerror function may be used to turn a CURLSHcode value
* into the equivalent human readable error string. This is useful
* for printing meaningful error messages.
*/
const char *curl_share_strerror(CURLSHcode);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

55
include/curl/curlver.h Normal file
View File

@@ -0,0 +1,55 @@
#ifndef __CURL_CURLVER_H
#define __CURL_CURLVER_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, 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$
***************************************************************************/
/* This header file contains nothing but libcurl version info, generated by
a script at release-time. This was made its own header file in 7.11.2 */
/* This is the version number of the libcurl package from which this header
file origins: */
#define LIBCURL_VERSION "7.11.2-CVS"
/* This is the numeric version of the libcurl version number, meant for easier
parsing and comparions by programs. The LIBCURL_VERSION_NUM define will
always follow this syntax:
0xXXYYZZ
Where XX, YY and ZZ are the main version, release and patch numbers in
hexadecimal. All three numbers are always represented using two digits. 1.2
would appear as "0x010200" while version 9.11.7 appears as "0x090b07".
This 6-digit hexadecimal number does not show pre-release number, 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 0x070b02
/* The numeric version number is also available "in parts" by using these
defines: */
#define LIBCURL_VERSION_MAJOR 7
#define LIBCURL_VERSION_MINOR 11
#define LIBCURL_VERSION_PATCH 2
#endif /* __CURL_CURLVER_H */

View File

@@ -203,6 +203,17 @@ CURLMcode curl_multi_cleanup(CURLM *multi_handle);
CURLMsg *curl_multi_info_read(CURLM *multi_handle, CURLMsg *curl_multi_info_read(CURLM *multi_handle,
int *msgs_in_queue); int *msgs_in_queue);
/*
* NAME curl_multi_strerror()
*
* DESCRIPTION
*
* The curl_multi_strerror function may be used to turn a CURLMcode value
* into the equivalent human readable error string. This is useful
* for printing meaningful error messages.
*/
const char *curl_multi_strerror(CURLMcode);
#ifdef __cplusplus #ifdef __cplusplus
} /* end of extern "C" */ } /* end of extern "C" */
#endif #endif

View File

@@ -1,15 +1,32 @@
#***************************************************************************
# _ _ ____ _
# Project ___| | | | _ \| |
# / __| | | | |_) | |
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
# Copyright (C) 1998 - 2004, 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$ # $Id$
# ###########################################################################
AUTOMAKE_OPTIONS = foreign nostdinc AUTOMAKE_OPTIONS = foreign nostdinc
EXTRA_DIST = getdate.y Makefile.b32 Makefile.b32.resp Makefile.m32 \ EXTRA_DIST = getdate.y Makefile.b32 Makefile.b32.resp Makefile.m32 \
Makefile.vc6 Makefile.riscos libcurl.def curllib.dsp \ Makefile.vc6 Makefile.riscos libcurl.def curllib.dsp curllib.dsw \
curllib.dsw config-vms.h config-win32.h config-riscos.h config-mac.h \ config-vms.h config-win32.h config-riscos.h config-mac.h config.h.in \
config.h.in ca-bundle.crt README.encoding README.memoryleak \ ca-bundle.crt README.encoding README.memoryleak README.ares README.curlx \
README.ares makefile.dj config.dj \ makefile.dj config.dj libcurl.framework.make libcurl.plist libcurl.rc \
libcurl.framework.make libcurl.plist libcurl.rc \
config-amigaos.h amigaos.c amigaos.h makefile.amiga config-netware.h \ config-amigaos.h amigaos.c amigaos.h makefile.amiga config-netware.h \
Makefile.netware nwlib.c libcurl.imp Makefile.netware nwlib.c libcurl.imp
@@ -38,16 +55,16 @@ VERSION=-version-info 2:2:0
# that the current interface number gets larger faster. # that the current interface number gets larger faster.
# #
# 3.If the library source code has changed at all since the last update, then # 3.If the library source code has changed at all since the last update, then
# increment revision (c:r:a becomes c:r+1:a). # increment revision (c:r+1:a)
# #
# 4.If any interfaces have been added, removed, or changed since the last # 4.If any interfaces have been added, removed, or changed since the last
# update, increment current, and set revision to 0. # update, increment current, and set revision to 0. (c+1:r=0:a)
# #
# 5.If any interfaces have been added since the last public release, then # 5.If any interfaces have been added since the last public release, then
# increment age. # increment age. (c:r:a+1)
# #
# 6.If any interfaces have been removed since the last public release, then # 6.If any interfaces have been removed since the last public release, then
# set age to 0. # set age to 0. (c:r:a=0)
# #
if NO_UNDEFINED if NO_UNDEFINED
@@ -63,20 +80,20 @@ endif
libcurl_la_LDFLAGS = $(UNDEF) $(VERSION) $(MIMPURE) libcurl_la_LDFLAGS = $(UNDEF) $(VERSION) $(MIMPURE)
libcurl_la_SOURCES = arpa_telnet.h file.c netrc.h timeval.c \ libcurl_la_SOURCES = arpa_telnet.h file.c netrc.h timeval.c base64.c \
base64.c file.h hostip.c progress.c timeval.h base64.h formdata.c \ file.h hostip.c progress.c timeval.h base64.h formdata.c hostip.h \
hostip.h progress.h cookie.c formdata.h http.c sendf.c cookie.h ftp.c \ progress.h cookie.c formdata.h http.c sendf.c cookie.h ftp.c http.h \
http.h sendf.h url.c dict.c ftp.h if2ip.c speedcheck.c url.h dict.h \ sendf.h url.c dict.c ftp.h if2ip.c speedcheck.c url.h dict.h \
getdate.c if2ip.h speedcheck.h urldata.h getdate.h ldap.c ssluse.c \ getdate.c if2ip.h speedcheck.h urldata.h getdate.h ldap.c ssluse.c \
version.c getenv.c ldap.h ssluse.h escape.c mprintf.c telnet.c escape.h \ version.c getenv.c ldap.h ssluse.h escape.c mprintf.c telnet.c \
netrc.c telnet.h getinfo.c getinfo.h transfer.c strequal.c \ escape.h netrc.c telnet.h getinfo.c getinfo.h transfer.c strequal.c \
strequal.h easy.c security.h security.c krb4.c krb4.h memdebug.c \ strequal.h easy.c security.h security.c krb4.c krb4.h memdebug.c \
memdebug.h inet_ntoa_r.h http_chunks.c http_chunks.h strtok.c strtok.h \ memdebug.h inet_ntoa_r.h http_chunks.c http_chunks.h strtok.c \
connect.c connect.h llist.c llist.h hash.c hash.h multi.c \ strtok.h connect.c connect.h llist.c llist.h hash.c hash.h multi.c \
content_encoding.c content_encoding.h share.c share.h http_digest.c \ content_encoding.c content_encoding.h share.c share.h http_digest.c \
md5.c md5.h http_digest.h http_negotiate.c http_negotiate.h \ md5.c md5.h http_digest.h http_negotiate.c http_negotiate.h \
http_ntlm.c http_ntlm.h ca-bundle.h inet_pton.c inet_pton.h \ http_ntlm.c http_ntlm.h ca-bundle.h inet_pton.c inet_pton.h \
strtoofft.c strtoofft.h strtoofft.c strtoofft.h strerror.c strerror.h
noinst_HEADERS = setup.h transfer.h noinst_HEADERS = setup.h transfer.h

View File

@@ -12,7 +12,7 @@ AR = ar
RM = rm -f RM = rm -f
RANLIB = ranlib RANLIB = ranlib
STRIP = strip -g STRIP = strip -g
OPENSSL_PATH = ../../openssl-0.9.7c OPENSSL_PATH = ../../openssl-0.9.7d
ZLIB_PATH = ../../zlib-1.2.1 ZLIB_PATH = ../../zlib-1.2.1
######################################################## ########################################################

View File

@@ -19,6 +19,7 @@
# files in the "cfg" directory, but then the make file # files in the "cfg" directory, but then the make file
# in \src would need to be changed. # in \src would need to be changed.
# #
# $Id: Makefile.vc6,v 1.17 2004/01/13 08:57:01 bagder Exp $
############################################################## ##############################################################
# CHANGE LOG # CHANGE LOG
# ------------------------------------------------------------ # ------------------------------------------------------------
@@ -37,12 +38,17 @@ LIB_NAME_DEBUG = libcurld
OPENSSL_PATH = ../../openssl-0.9.7a OPENSSL_PATH = ../../openssl-0.9.7a
!ENDIF !ENDIF
!IFNDEF ZLIB_PATH
ZLIB_PATH = ../../zlib-1.1.4
!ENDIF
############################################################# #############################################################
## Nothing more to do below this line! ## Nothing more to do below this line!
CCNODBG = cl.exe /MD /O2 /D "NDEBUG" CCNODBG = cl.exe /MD /O2 /D "NDEBUG"
CCDEBUG = cl.exe /MDd /Od /Gm /Zi /D "_DEBUG" /GZ CCDEBUG = cl.exe /MDd /Od /Gm /Zi /D "_DEBUG" /GZ
CFLAGSSSL = /D "USE_SSLEAY" /I "$(OPENSSL_PATH)/inc32" /I "$(OPENSSL_PATH)/inc32/openssl" CFLAGSSSL = /D "USE_SSLEAY" /I "$(OPENSSL_PATH)/inc32" /I "$(OPENSSL_PATH)/inc32/openssl"
CFLAGSZLIB = /D "HAVE_ZLIB_H" /D "HAVE_ZLIB" /D "HAVE_LIBZ" /I "$(ZLIB_PATH)"
CFLAGS = /I "." /I "../include" /nologo /W3 /GX /D "WIN32" /D "VC6" /D "_MBCS" /D "_LIB" /YX /FD /c /D "MSDOS" CFLAGS = /I "." /I "../include" /nologo /W3 /GX /D "WIN32" /D "VC6" /D "_MBCS" /D "_LIB" /YX /FD /c /D "MSDOS"
LNKDLL = link.exe /DLL /def:libcurl.def LNKDLL = link.exe /DLL /def:libcurl.def
@@ -100,6 +106,19 @@ CFGSET = TRUE
RESOURCE = $(DIROBJ)\libcurl.res RESOURCE = $(DIROBJ)\libcurl.res
!ENDIF !ENDIF
######################
# release-ssl-zlib
!IF "$(CFG)" == "release-ssl-zlib"
TARGET =$(LIB_NAME).lib
DIROBJ =.\$(CFG)
LFLAGSSSL = "/LIBPATH:$(OPENSSL_PATH)/out32"
LFLAGSZLIB = "/LIBPATH:$(ZLIB_PATH)"
LNK = $(LNKLIB) $(LFLAGSSSL) $(LFLAGSZLIB) /out:$(TARGET)
CC = $(CCNODBG) $(CFLAGSSSL) $(CFLAGSZLIB)
CFGSET = TRUE
!ENDIF
###################### ######################
# release-libcurl-ssl-dll # release-libcurl-ssl-dll
!IF "$(CFG)" == "release-libcurl-ssl-dll" !IF "$(CFG)" == "release-libcurl-ssl-dll"
@@ -169,6 +188,7 @@ RESOURCE = $(DIROBJ)\libcurl.res
!MESSAGE release - release static library !MESSAGE release - release static library
!MESSAGE release-dll - release dll !MESSAGE release-dll - release dll
!MESSAGE release-ssl - release static library with ssl !MESSAGE release-ssl - release static library with ssl
!MESSAGE release-ssl-zlib - release static library with ssl and zlib
!MESSAGE release-ssl-dll - release dll library with ssl !MESSAGE release-ssl-dll - release dll library with ssl
!MESSAGE release-libcurl-ssl-dll - static libcurl with shared ssl !MESSAGE release-libcurl-ssl-dll - static libcurl with shared ssl
!MESSAGE debug - debug static library !MESSAGE debug - debug static library
@@ -222,6 +242,8 @@ X_OBJS= \
$(DIROBJ)\http_negotiate.obj \ $(DIROBJ)\http_negotiate.obj \
$(DIROBJ)\http_ntlm.obj \ $(DIROBJ)\http_ntlm.obj \
$(DIROBJ)\md5.obj \ $(DIROBJ)\md5.obj \
$(DIROBJ)\strerror.obj \
$(DIROBJ)\content_encoding.obj \
$(RESOURCE) $(RESOURCE)
all : $(TARGET) all : $(TARGET)

View File

@@ -5,56 +5,53 @@ $Id$
| (__| |_| | _ <| |___ | (__| |_| | _ <| |___
\___|\___/|_| \_\_____| \___|\___/|_| \_\_____|
How To Build libcurl to Use ares For Asynch Name Resolves How To Build libcurl to Use c-ares For Asynch Name Resolves
========================================================= ===========================================================
ares: c-ares:
ftp://athena-dist.mit.edu/pub/ATHENA/ares/ares-1.1.1.tar.gz http://daniel.haxx.se/projects/c-ares/
http://curl.haxx.se/dev/ares-1.1.1.tar.gz
http://curl.sourceforge.net/dev/ares-1.1.1.tar.gz
http://curl.planetmirror.com/dev/ares-1.1.1.tar.gz
http://curl.tsuren.net/dev/ares-1.1.1.tar.gz
c-ares: (a patched and improved version of ares)
http://curl.haxx.se/beta/arescurl-1.0-pre1.tar.gz
NOTE NOTE
libcurl works with ares 1.1.1, but several patches and improvements have libcurl 7.11.1 builds with c-ares 1.1.0, but 7.11.2 and later require c-ares
been put into the c-ares package which has made it more portable and better 1.2.0 or alter.
working on several platforms.
Build ares 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.
1. unpack the ares archive Build c-ares
2. cd ares-dir ============
1. unpack the c-ares archive
2. cd c-ares-dir
3. ./configure 3. ./configure
4. make 4. make
Build libcurl to use ares in the curl source tree Build libcurl to use c-ares in the curl source tree
================================================= ===================================================
1. name the ares source directory 'ares' in the curl source directory 1. name the c-ares source directory 'ares' in the curl source directory
(if you have checked out the curl sources from CVS, you will already have
c-ares in a directory named ares).
2. ./configure --enable-ares 2. ./configure --enable-ares
3. make 3. make
Build libcurl to use an installed ares Build libcurl to use an installed c-ares
====================================== ========================================
1. ./configure --enable-ares=/path/to/ares/install 1. ./configure --enable-ares=/path/to/ares/install
2. make 2. make
Ares and ipv6 c-ares and ipv6
============= ===============
If the configure script enables IPv6 support you need to explicitly disable If the configure script enables IPv6 support you need to explicitly disable
that (--disable-ipv6) since ares isn't IPv6 compatible (yet). that (--disable-ipv6) since c-ares isn't IPv6 compatible (yet).
Ares on win32 c-ares on win32
============= ===============
(description brought by Dominick Meglio) (description brought by Dominick Meglio)
First I compiled curl-ares. I changed the default C runtime library to be the First I compiled c-ares. I changed the default C runtime library to be the
single-threaded rather than the multi-threaded (this seems to be required to single-threaded rather than the multi-threaded (this seems to be required to
prevent linking errors later on). Then I simply build the areslib project (the prevent linking errors later on). Then I simply build the areslib project (the
other projects adig/ahost seem to fail under MSVC). other projects adig/ahost seem to fail under MSVC).

43
lib/README.curlx Normal file
View File

@@ -0,0 +1,43 @@
$Id$
_ _ ____ _
___| | | | _ \| |
/ __| | | | |_) | |
| (__| |_| | _ <| |___
\___|\___/|_| \_\_____|
Source Code Functions Apps Might Use
====================================
The libcurl source code offers a few functions by source only. They are not
part of the official libcurl API, but the source files might be useful for
others so apps can optionally compile/build with these sources to gain
additional functions.
strtoofft.[ch]
==============
curlx_strtoofft()
A macro that converts a string containing a number to a curl_off_t number.
This might use the curlx_strtoll() function which is provided as source
code in strtoofft.c. Note that the function is only provided if no
strtoll() (or equivalent) function exist on your platform. If curl_off_t
is only a 32 bit number on your platform, this macro uses strtol().
timeval.[ch]
============
Provides a 'struct timeval' for platforms that don't have one already, and
includes the proper include files for those that have one. Using this will
make the output require the 'winmm' lib on Windows (unless WITHOUT_MM_LIB
is defined at compile-time).
curlx_tvnow()
returns a struct timeval for the current time.
curlx_tvdiff()
returns the difference between two timeval structs, in number of
milliseconds.

View File

@@ -25,10 +25,12 @@
#define HAVE_IO_H 1 #define HAVE_IO_H 1
#define HAVE_IOCTLSOCKET 1 #define HAVE_IOCTLSOCKET 1
#define HAVE_INET_PTON 1 #define HAVE_INET_PTON 1
#define HAVE_LONGLONG 1
#define HAVE_MALLOC_H 1 #define HAVE_MALLOC_H 1
#define HAVE_MEMORY_H 1 #define HAVE_MEMORY_H 1
#define HAVE_NETDB_H 1 #define HAVE_NETDB_H 1
#define HAVE_NETINET_IN_H 1 #define HAVE_NETINET_IN_H 1
#define HAVE_NETINET_TCP_H 1
#define HAVE_NET_IF_H 1 #define HAVE_NET_IF_H 1
#define HAVE_PERROR 1 #define HAVE_PERROR 1
#define HAVE_SELECT 1 #define HAVE_SELECT 1
@@ -38,12 +40,14 @@
#define HAVE_SIGACTION 1 #define HAVE_SIGACTION 1
#define HAVE_SIGSETJMP 1 #define HAVE_SIGSETJMP 1
#define HAVE_SOCKET 1 #define HAVE_SOCKET 1
#define HAVE_SPNEGO 1
#define HAVE_STRCASECMP 1 #define HAVE_STRCASECMP 1
#define HAVE_STRDUP 1 #define HAVE_STRDUP 1
#define HAVE_STRFTIME 1 #define HAVE_STRFTIME 1
#define HAVE_STRICMP 1 #define HAVE_STRICMP 1
#define HAVE_STRSTR 1 #define HAVE_STRSTR 1
#define HAVE_STRTOLL 1 #define HAVE_STRTOLL 1
#define HAVE_SYS_IOCTL_H 1
#define HAVE_SYS_SOCKET_H 1 #define HAVE_SYS_SOCKET_H 1
#define HAVE_SYS_STAT_H 1 #define HAVE_SYS_STAT_H 1
#define HAVE_SYS_TYPES_H 1 #define HAVE_SYS_TYPES_H 1
@@ -53,9 +57,13 @@
#define HAVE_UNISTD_H 1 #define HAVE_UNISTD_H 1
#define HAVE_VPRINTF 1 #define HAVE_VPRINTF 1
#if (DJGPP_MINOR >= 4)
#define HAVE_STRLCAT 1
#endif
#define RETSIGTYPE void #define RETSIGTYPE void
#define SIZEOF_LONG_DOUBLE 16 #define SIZEOF_LONG_DOUBLE 16
#define SIZEOF_LONG_LONG 8 #define SIZEOF_CURL_OFF_T 4 /* no huge file support */
#define STDC_HEADERS 1 #define STDC_HEADERS 1
#define TIME_WITH_SYS_TIME 1 #define TIME_WITH_SYS_TIME 1

View File

@@ -32,7 +32,15 @@
#ifdef HAVE_SYS_SOCKET_H #ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h> #include <sys/socket.h>
#endif #endif
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h> /* <netinet/tcp.h> may need it */
#endif
#ifdef HAVE_NETINET_TCP_H
#include <netinet/tcp.h> /* for TCP_NODELAY */
#endif
#ifdef HAVE_SYS_IOCTL_H
#include <sys/ioctl.h> #include <sys/ioctl.h>
#endif
#ifdef HAVE_UNISTD_H #ifdef HAVE_UNISTD_H
#include <unistd.h> #include <unistd.h>
#endif #endif
@@ -86,6 +94,7 @@
#include "urldata.h" #include "urldata.h"
#include "sendf.h" #include "sendf.h"
#include "if2ip.h" #include "if2ip.h"
#include "strerror.h"
#include "connect.h" #include "connect.h"
/* The last #include file should be: */ /* The last #include file should be: */
@@ -138,7 +147,7 @@ int Curl_nonblock(curl_socket_t sockfd, /* operate on this */
#ifdef HAVE_IOCTLSOCKET #ifdef HAVE_IOCTLSOCKET
/* Windows? */ /* Windows? */
int flags; unsigned long flags;
flags = nonblock; flags = nonblock;
return ioctlsocket(sockfd, FIONBIO, &flags); return ioctlsocket(sockfd, FIONBIO, &flags);
#define SETBLOCK 3 #define SETBLOCK 3
@@ -295,10 +304,10 @@ static CURLcode bindlocal(struct connectdata *conn,
if (setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE, if (setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE,
data->set.device, strlen(data->set.device)+1) != 0) { data->set.device, strlen(data->set.device)+1) != 0) {
/* printf("Failed to BINDTODEVICE, socket: %d device: %s error: %s\n", /* printf("Failed to BINDTODEVICE, socket: %d device: %s error: %s\n",
sockfd, data->set.device, strerror(errno)); */ sockfd, data->set.device, Curl_strerror(Curl_ourerrno())); */
infof(data, "SO_BINDTODEVICE %s failed\n", infof(data, "SO_BINDTODEVICE %s failed\n",
data->set.device); data->set.device);
/* This is typiclally "errno 1, error: Operation not permitted" if /* This is typically "errno 1, error: Operation not permitted" if
you're not running as root or another suitable privileged user */ you're not running as root or another suitable privileged user */
} }
} }
@@ -353,37 +362,9 @@ static CURLcode bindlocal(struct connectdata *conn,
} }
#endif #endif
if(!bindworked) { if(!bindworked) {
switch(errno) { failf(data, "%s", Curl_strerror(conn, Curl_ourerrno()));
case EBADF:
failf(data, "Invalid descriptor: %d", errno);
break;
case EINVAL:
failf(data, "Invalid request: %d", errno);
break;
case EACCES:
failf(data, "Address is protected, user not superuser: %d", errno);
break;
case ENOTSOCK:
failf(data,
"Argument is a descriptor for a file, not a socket: %d",
errno);
break;
case EFAULT:
failf(data, "Inaccessable memory error: %d", errno);
break;
case ENAMETOOLONG:
failf(data, "Address too long: %d", errno);
break;
case ENOMEM:
failf(data, "Insufficient kernel memory was available: %d", errno);
break;
default:
failf(data, "errno %d", errno);
break;
} /* end of switch(errno) */
return CURLE_HTTP_PORT_FAILED; return CURLE_HTTP_PORT_FAILED;
} /* end of else */ }
} /* end of if h */ } /* end of if h */
else { else {
@@ -488,8 +469,8 @@ CURLcode Curl_is_connected(struct connectdata *conn,
} }
else if(1 != rc) { else if(1 != rc) {
int error = Curl_ourerrno(); int error = Curl_ourerrno();
failf(data, "Failed connect to %s:%d, errno: %d", failf(data, "Failed connect to %s:%d; %s",
conn->hostname, conn->port, error); conn->hostname, conn->port, Curl_strerror(conn,error));
return CURLE_COULDNT_CONNECT; return CURLE_COULDNT_CONNECT;
} }
/* /*
@@ -503,6 +484,23 @@ CURLcode Curl_is_connected(struct connectdata *conn,
return CURLE_OK; return CURLE_OK;
} }
static void Curl_setNoDelay(struct connectdata *conn,
curl_socket_t sockfd)
{
#ifdef TCP_NODELAY
struct SessionHandle *data= conn->data;
socklen_t onoff = (socklen_t) data->set.tcp_nodelay;
if(setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, (void *)&onoff,
sizeof(onoff)) < 0)
infof(data, "Could not set TCP_NODELAY: %s\n",
Curl_strerror(conn, Curl_ourerrno()));
else
infof(data,"TCP_NODELAY set\n");
#else
(void)conn;
(void)sockfd;
#endif
}
/* /*
* TCP connect to the given host with timeout, proxy or remote doesn't matter. * TCP connect to the given host with timeout, proxy or remote doesn't matter.
@@ -581,6 +579,9 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */
sockfd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); sockfd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
if (sockfd == CURL_SOCKET_BAD) if (sockfd == CURL_SOCKET_BAD)
continue; continue;
else if(data->set.tcp_nodelay)
Curl_setNoDelay(conn, sockfd);
#else #else
/* /*
* Connecting with old style IPv4-only support * Connecting with old style IPv4-only support
@@ -600,6 +601,9 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */
return CURLE_COULDNT_CONNECT; /* big time error */ return CURLE_COULDNT_CONNECT; /* big time error */
} }
else if(data->set.tcp_nodelay)
Curl_setNoDelay(conn, sockfd);
/* nasty address work before connect can be made */ /* nasty address work before connect can be made */
memset((char *) &serv_addr, '\0', sizeof(serv_addr)); memset((char *) &serv_addr, '\0', sizeof(serv_addr));
memcpy((char *)&(serv_addr.sin_addr), memcpy((char *)&(serv_addr.sin_addr),
@@ -651,8 +655,8 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */
break; break;
default: default:
/* unknown error, fallthrough and try another address! */ /* unknown error, fallthrough and try another address! */
failf(data, "Failed to connect to %s IP number %d: %d", failf(data, "Failed to connect to %s IP number %d: %s",
hostname, aliasindex+1, error); hostname, aliasindex+1, Curl_strerror(conn,error));
break; break;
} }
} }
@@ -692,7 +696,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */
if (sockfd == CURL_SOCKET_BAD) { if (sockfd == CURL_SOCKET_BAD) {
/* no good connect was made */ /* no good connect was made */
*sockconn = -1; *sockconn = -1;
failf(data, "Connect failed"); failf(data, "Connect failed; %s", Curl_strerror(conn,Curl_ourerrno()));
return CURLE_COULDNT_CONNECT; return CURLE_COULDNT_CONNECT;
} }

View File

@@ -43,7 +43,7 @@ RSC=rc.exe
# PROP Ignore_Export_Lib 0 # PROP Ignore_Export_Lib 0
# PROP Target_Dir "" # PROP Target_Dir ""
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CURLLIB_EXPORTS" /YX /FD /c # ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CURLLIB_EXPORTS" /YX /FD /c
# ADD CPP /nologo /MT /W3 /GX /Zi /O2 /I "..\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CURLLIB_EXPORTS" /D "_WINDLL" /FR /FD /c # ADD CPP /nologo /MT /W3 /GX /Zi /O2 /I "." /I "..\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CURLLIB_EXPORTS" /D "_WINDLL" /FR /FD /c
# SUBTRACT CPP /YX # SUBTRACT CPP /YX
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
@@ -70,7 +70,7 @@ LINK32=link.exe
# PROP Ignore_Export_Lib 0 # PROP Ignore_Export_Lib 0
# PROP Target_Dir "" # PROP Target_Dir ""
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CURLLIB_EXPORTS" /YX /FD /GZ /c # ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CURLLIB_EXPORTS" /YX /FD /GZ /c
# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "..\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CURLLIB_EXPORTS" /FR /FD /GZ /c # ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "." /I "..\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CURLLIB_EXPORTS" /FR /FD /GZ /c
# SUBTRACT CPP /WX /YX # SUBTRACT CPP /WX /YX
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32

View File

@@ -271,7 +271,7 @@ CURLcode curl_easy_perform(CURL *curl)
} }
if (!data->hostcache) { if (!data->hostcache) {
data->hostcache = Curl_hash_alloc(7, Curl_freednsinfo); data->hostcache = Curl_mk_dnscache();
if(!data->hostcache) if(!data->hostcache)
/* While we possibly could survive and do good without a host cache, /* While we possibly could survive and do good without a host cache,

View File

@@ -196,7 +196,7 @@ CURLcode Curl_file(struct connectdata *conn)
/* If we have selected NOBODY and HEADER, it means that we only want file /* If we have selected NOBODY and HEADER, it means that we only want file
information. Which for FILE can't be much more than the file size and information. Which for FILE can't be much more than the file size and
date. */ date. */
if(data->set.no_body && data->set.include_header && fstated) { if(conn->bits.no_body && data->set.include_header && fstated) {
CURLcode result; CURLcode result;
sprintf(buf, "Content-Length: %" FORMAT_OFF_T "\r\n", expected_size); sprintf(buf, "Content-Length: %" FORMAT_OFF_T "\r\n", expected_size);
result = Curl_client_write(data, CLIENTWRITE_BOTH, buf, 0); result = Curl_client_write(data, CLIENTWRITE_BOTH, buf, 0);

View File

@@ -176,7 +176,7 @@ int FormParse(char *input,
struct curl_httppost **httppost, struct curl_httppost **httppost,
struct curl_httppost **last_post) struct curl_httppost **last_post)
{ {
/* nextarg MUST be a string in the format 'name=contents' and we'll /* 'input' MUST be a string in the format 'name=contents' and we'll
build a linked list with the info */ build a linked list with the info */
char name[256]; char name[256];
char *contents; char *contents;
@@ -975,6 +975,10 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost,
return return_value; return return_value;
} }
/*
* curl_formadd() is a public API to add a section to the multipart formpost.
*/
CURLFORMcode curl_formadd(struct curl_httppost **httppost, CURLFORMcode curl_formadd(struct curl_httppost **httppost,
struct curl_httppost **last_post, struct curl_httppost **last_post,
...) ...)
@@ -987,6 +991,9 @@ CURLFORMcode curl_formadd(struct curl_httppost **httppost,
return result; return result;
} }
/*
* AddFormData() adds a chunk of data to the FormData linked list.
*/
static size_t AddFormData(struct FormData **formp, static size_t AddFormData(struct FormData **formp,
const void *line, const void *line,
size_t length) size_t length)
@@ -1014,6 +1021,9 @@ static size_t AddFormData(struct FormData **formp,
return length; return length;
} }
/*
* AddFormDataf() adds printf()-style formatted data to the formdata chain.
*/
static size_t AddFormDataf(struct FormData **formp, static size_t AddFormDataf(struct FormData **formp,
const char *fmt, ...) const char *fmt, ...)
@@ -1027,7 +1037,10 @@ static size_t AddFormDataf(struct FormData **formp,
return AddFormData(formp, s, 0); return AddFormData(formp, s, 0);
} }
/*
* Curl_FormBoundary() creates a suitable boundary string and returns an
* allocated one.
*/
char *Curl_FormBoundary(void) char *Curl_FormBoundary(void)
{ {
char *retstring; char *retstring;
@@ -1056,7 +1069,10 @@ char *Curl_FormBoundary(void)
return retstring; return retstring;
} }
/* Used from http.c, this cleans a built FormData linked list */ /*
* 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)
{ {
struct FormData *next; struct FormData *next;
@@ -1069,7 +1085,10 @@ void Curl_formclean(struct FormData *form)
} while((form=next)); /* continue */ } while((form=next)); /* continue */
} }
/* external function to free up a whole form post chain */ /*
* curl_formfree() is an external function to free up a whole form post
* chain
*/
void curl_formfree(struct curl_httppost *form) void curl_formfree(struct curl_httppost *form)
{ {
struct curl_httppost *next; struct curl_httppost *next;
@@ -1098,6 +1117,13 @@ void curl_formfree(struct curl_httppost *form)
} while((form=next)); /* continue */ } while((form=next)); /* continue */
} }
/*
* Curl_getFormData() converts a linked list of "meta data" into a complete
* (possibly huge) multipart formdata. The input list is in 'post', while the
* output resulting linked lists gets stored in '*finalform'. *sizep will get
* the total size of the whole POST.
*/
CURLcode Curl_getFormData(struct FormData **finalform, CURLcode Curl_getFormData(struct FormData **finalform,
struct curl_httppost *post, struct curl_httppost *post,
curl_off_t *sizep) curl_off_t *sizep)
@@ -1218,11 +1244,14 @@ CURLcode Curl_getFormData(struct FormData **finalform,
char buffer[1024]; char buffer[1024];
size_t nread; size_t nread;
fileread = strequal("-", file->contents)?stdin: fileread = strequal("-", file->contents)?
/* binary read for win32 crap */ stdin:fopen(file->contents, "rb"); /* binary read for win32 */
/*VMS??*/ fopen(file->contents, "rb"); /* ONLY ALLOWS FOR STREAM FILES ON VMS */ /*
/*VMS?? Stream files are OK, as are FIXED & VAR files WITHOUT implied CC */ * VMS: This only allows for stream files on VMS. Stream files are
/*VMS?? For implied CC, every record needs to have a \n appended & 1 added to SIZE */ * OK, as are FIXED & VAR files WITHOUT implied CC For implied CC,
* every record needs to have a \n appended & 1 added to SIZE
*/
if(fileread) { if(fileread) {
while((nread = fread(buffer, 1, 1024, fileread))) while((nread = fread(buffer, 1, 1024, fileread)))
size += AddFormData(&form, buffer, nread); size += AddFormData(&form, buffer, nread);
@@ -1231,10 +1260,6 @@ CURLcode Curl_getFormData(struct FormData **finalform,
fclose(fileread); fclose(fileread);
} }
else { else {
#if 0
/* File wasn't found, add a nothing field! */
size += AddFormData(&form, "", 0);
#endif
Curl_formclean(firstform); Curl_formclean(firstform);
free(boundary); free(boundary);
*finalform = NULL; *finalform = NULL;
@@ -1278,6 +1303,10 @@ CURLcode Curl_getFormData(struct FormData **finalform,
return result; return result;
} }
/*
* Curl_FormInit() inits the struct 'form' points to with the 'formdata'
* and resets the 'sent' counter.
*/
int Curl_FormInit(struct Form *form, struct FormData *formdata ) int Curl_FormInit(struct Form *form, struct FormData *formdata )
{ {
if(!formdata) if(!formdata)
@@ -1289,7 +1318,10 @@ int Curl_FormInit(struct Form *form, struct FormData *formdata )
return 0; return 0;
} }
/* fread() emulation */ /*
* Curl_FormReader() is the fread() emulation function that will be used to
* deliver the formdata to the transfer loop and then sent away to the peer.
*/
size_t Curl_FormReader(char *buffer, size_t Curl_FormReader(char *buffer,
size_t size, size_t size,
size_t nitems, size_t nitems,
@@ -1335,48 +1367,25 @@ size_t Curl_FormReader(char *buffer,
return gotsize; return gotsize;
} }
/* possible (old) fread() emulation that copies at most one line */ /*
size_t Curl_FormReadOneLine(char *buffer, * Curl_formpostheader() returns the first line of the formpost, the
size_t size, * request-header part (which is not part of the request-body like the rest of
size_t nitems, * the post).
FILE *mydata) */
char *Curl_formpostheader(void *formp, size_t *len)
{ {
struct Form *form; char *header;
size_t wantedsize; struct Form *form=(struct Form *)formp;
size_t gotsize;
form=(struct Form *)mydata;
wantedsize = size * nitems;
if(!form->data) if(!form->data)
return 0; /* nothing, error, empty */ return 0; /* nothing, ERROR! */
do { header = form->data->line;
*len = form->data->length;
if( (form->data->length - form->sent ) > wantedsize ) {
memcpy(buffer, form->data->line + form->sent, wantedsize);
form->sent += wantedsize;
return wantedsize;
}
memcpy(buffer,
form->data->line + form->sent,
gotsize = (form->data->length - form->sent) );
form->sent = 0;
form->data = form->data->next; /* advance */ form->data = form->data->next; /* advance */
} while(!gotsize && form->data); return header;
/* 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) */
return gotsize;
} }

View File

@@ -65,11 +65,12 @@ size_t Curl_FormReader(char *buffer,
size_t nitems, size_t nitems,
FILE *mydata); FILE *mydata);
/* possible (old) fread() emulation that copies at most one line */ /*
size_t Curl_FormReadOneLine(char *buffer, * Curl_formpostheader() returns the first line of the formpost, the
size_t size, * request-header part (which is not part of the request-body like the rest of
size_t nitems, * the post).
FILE *mydata); */
char *Curl_formpostheader(void *formp, size_t *len);
char *Curl_FormBoundary(void); char *Curl_FormBoundary(void);

134
lib/ftp.c
View File

@@ -91,6 +91,7 @@
#include "strequal.h" #include "strequal.h"
#include "ssluse.h" #include "ssluse.h"
#include "connect.h" #include "connect.h"
#include "strerror.h"
#if defined(HAVE_INET_NTOA_R) && !defined(HAVE_INET_NTOA_R_DECL) #if defined(HAVE_INET_NTOA_R) && !defined(HAVE_INET_NTOA_R_DECL)
#include "inet_ntoa_r.h" #include "inet_ntoa_r.h"
@@ -104,12 +105,19 @@
#include "memdebug.h" #include "memdebug.h"
#endif #endif
#ifdef HAVE_NI_WITHSCOPEID
#define NIFLAGS NI_NUMERICHOST | NI_NUMERICSERV | NI_WITHSCOPEID
#else
#define NIFLAGS NI_NUMERICHOST | NI_NUMERICSERV
#endif
/* Local API functions */ /* Local API functions */
static CURLcode ftp_sendquote(struct connectdata *conn, static CURLcode ftp_sendquote(struct connectdata *conn,
struct curl_slist *quote); struct curl_slist *quote);
static CURLcode ftp_cwd(struct connectdata *conn, char *path); static CURLcode ftp_cwd(struct connectdata *conn, char *path);
static CURLcode ftp_mkd(struct connectdata *conn, char *path); static CURLcode ftp_mkd(struct connectdata *conn, char *path);
static CURLcode ftp_cwd_and_mkd(struct connectdata *conn, char *path); static CURLcode ftp_cwd_and_mkd(struct connectdata *conn, char *path);
static CURLcode ftp_quit(struct connectdata *conn);
/* easy-to-use macro: */ /* easy-to-use macro: */
#define FTPSENDF(x,y,z) if((result = Curl_ftpsendf(x,y,z))) return result #define FTPSENDF(x,y,z) if((result = Curl_ftpsendf(x,y,z))) return result
@@ -117,11 +125,21 @@ static CURLcode ftp_cwd_and_mkd(struct connectdata *conn, char *path);
static void freedirs(struct FTP *ftp) static void freedirs(struct FTP *ftp)
{ {
int i; int i;
for (i=0; ftp->dirs[i]; i++){ if(ftp->dirs) {
for (i=0; i < ftp->dirdepth; i++){
if(ftp->dirs[i]) {
free(ftp->dirs[i]); free(ftp->dirs[i]);
ftp->dirs[i]=NULL; ftp->dirs[i]=NULL;
} }
} }
free(ftp->dirs);
ftp->dirs = NULL;
}
if(ftp->file) {
free(ftp->file);
ftp->file = NULL;
}
}
/*********************************************************************** /***********************************************************************
* *
@@ -339,6 +357,8 @@ CURLcode Curl_GetFTPResponse(ssize_t *nreadp, /* return number of bytes read */
* line */ * line */
int i; int i;
conn->headerbytecount += gotbytes;
*nreadp += gotbytes; *nreadp += gotbytes;
for(i = 0; i < gotbytes; ptr++, i++) { for(i = 0; i < gotbytes; ptr++, i++) {
perline++; perline++;
@@ -585,13 +605,13 @@ CURLcode Curl_ftp_connect(struct connectdata *conn)
infof(data, "We have successfully logged in\n"); infof(data, "We have successfully logged in\n");
if (conn->ssl[FIRSTSOCKET].use) { if (conn->ssl[FIRSTSOCKET].use) {
#ifdef HAVE_KRB4 #ifdef HAVE_KRB4
/* we are logged in (with Kerberos) /* We are logged in with Kerberos, now set the requested protection
* now set the requested protection level * level
*/ */
if(conn->sec_complete) if(conn->sec_complete)
Curl_sec_set_protection_level(conn); Curl_sec_set_protection_level(conn);
/* we may need to issue a KAUTH here to have access to the files /* We may need to issue a KAUTH here to have access to the files
* do it if user supplied a password * do it if user supplied a password
*/ */
if(conn->passwd && *conn->passwd) { if(conn->passwd && *conn->passwd) {
@@ -724,14 +744,12 @@ CURLcode Curl_ftp_done(struct connectdata *conn)
ssize_t nread; ssize_t nread;
int ftpcode; int ftpcode;
CURLcode result=CURLE_OK; CURLcode result=CURLE_OK;
bool was_ctl_valid = ftp->ctl_valid;
/* free the dir tree parts */ /* free the dir tree and file parts */
freedirs(ftp); freedirs(ftp);
if(ftp->file) { ftp->ctl_valid = FALSE;
free(ftp->file);
ftp->file = NULL;
}
if(data->set.upload) { if(data->set.upload) {
if((-1 != data->set.infilesize) && if((-1 != data->set.infilesize) &&
@@ -766,6 +784,8 @@ CURLcode Curl_ftp_done(struct connectdata *conn)
} }
} }
ftp->ctl_valid = was_ctl_valid;
#ifdef HAVE_KRB4 #ifdef HAVE_KRB4
Curl_sec_fflush_fd(conn, conn->sock[SECONDARYSOCKET]); Curl_sec_fflush_fd(conn, conn->sock[SECONDARYSOCKET]);
#endif #endif
@@ -954,7 +974,7 @@ CURLcode ftp_getsize(struct connectdata *conn, char *file,
if(ftpcode == 213) { if(ftpcode == 213) {
/* get the size from the ascii string: */ /* get the size from the ascii string: */
*size = strtoofft(buf+4, NULL, 0); *size = curlx_strtoofft(buf+4, NULL, 0);
} }
else else
return CURLE_FTP_COULDNT_GET_SIZE; return CURLE_FTP_COULDNT_GET_SIZE;
@@ -1073,14 +1093,9 @@ ftp_pasv_verbose(struct connectdata *conn,
char hbuf[NI_MAXHOST]; /* ~1KB */ char hbuf[NI_MAXHOST]; /* ~1KB */
char nbuf[NI_MAXHOST]; /* ~1KB */ char nbuf[NI_MAXHOST]; /* ~1KB */
char sbuf[NI_MAXSERV]; /* around 32 */ char sbuf[NI_MAXSERV]; /* around 32 */
#ifdef NI_WITHSCOPEID
const int niflags = NI_NUMERICHOST | NI_NUMERICSERV | NI_WITHSCOPEID;
#else
const int niflags = NI_NUMERICHOST | NI_NUMERICSERV;
#endif
(void)port; /* prevent compiler warning */ (void)port; /* prevent compiler warning */
if (getnameinfo(addr->ai_addr, addr->ai_addrlen, if (getnameinfo(addr->ai_addr, addr->ai_addrlen,
nbuf, sizeof(nbuf), sbuf, sizeof(sbuf), niflags)) { nbuf, sizeof(nbuf), sbuf, sizeof(sbuf), NIFLAGS)) {
snprintf(nbuf, sizeof(nbuf), "?"); snprintf(nbuf, sizeof(nbuf), "?");
snprintf(sbuf, sizeof(sbuf), "?"); snprintf(sbuf, sizeof(sbuf), "?");
} }
@@ -1126,11 +1141,6 @@ CURLcode ftp_use_port(struct connectdata *conn)
char hbuf[NI_MAXHOST]; char hbuf[NI_MAXHOST];
struct sockaddr *sa=(struct sockaddr *)&ss; struct sockaddr *sa=(struct sockaddr *)&ss;
#ifdef NI_WITHSCOPEID
#define NIFLAGS NI_NUMERICHOST | NI_NUMERICSERV | NI_WITHSCOPEID
#else
#define NIFLAGS NI_NUMERICHOST | NI_NUMERICSERV
#endif
unsigned char *ap; unsigned char *ap;
unsigned char *pp; unsigned char *pp;
char portmsgbuf[4096], tmp[4096]; char portmsgbuf[4096], tmp[4096];
@@ -1138,6 +1148,7 @@ CURLcode ftp_use_port(struct connectdata *conn)
const char *mode[] = { "EPRT", "LPRT", "PORT", NULL }; const char *mode[] = { "EPRT", "LPRT", "PORT", NULL };
char **modep; char **modep;
int rc; int rc;
int error;
/* /*
* we should use Curl_if2ip? given pickiness of recent ftpd, * we should use Curl_if2ip? given pickiness of recent ftpd,
@@ -1172,6 +1183,7 @@ CURLcode ftp_use_port(struct connectdata *conn)
} }
portsock = CURL_SOCKET_BAD; portsock = CURL_SOCKET_BAD;
error = 0;
for (ai = res; ai; ai = ai->ai_next) { for (ai = res; ai; ai = ai->ai_next) {
/* /*
* Workaround for AIX5 getaddrinfo() problem (it doesn't set ai_socktype): * Workaround for AIX5 getaddrinfo() problem (it doesn't set ai_socktype):
@@ -1180,16 +1192,20 @@ CURLcode ftp_use_port(struct connectdata *conn)
ai->ai_socktype = hints.ai_socktype; ai->ai_socktype = hints.ai_socktype;
portsock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); portsock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
if (portsock == CURL_SOCKET_BAD) if (portsock == CURL_SOCKET_BAD) {
error = Curl_ourerrno();
continue; continue;
}
if (bind(portsock, ai->ai_addr, ai->ai_addrlen) < 0) { if (bind(portsock, ai->ai_addr, ai->ai_addrlen) < 0) {
error = Curl_ourerrno();
sclose(portsock); sclose(portsock);
portsock = CURL_SOCKET_BAD; portsock = CURL_SOCKET_BAD;
continue; continue;
} }
if (listen(portsock, 1) < 0) { if (listen(portsock, 1) < 0) {
error = Curl_ourerrno();
sclose(portsock); sclose(portsock);
portsock = CURL_SOCKET_BAD; portsock = CURL_SOCKET_BAD;
continue; continue;
@@ -1199,13 +1215,13 @@ CURLcode ftp_use_port(struct connectdata *conn)
} }
freeaddrinfo(res); freeaddrinfo(res);
if (portsock == CURL_SOCKET_BAD) { if (portsock == CURL_SOCKET_BAD) {
failf(data, "%s", strerror(errno)); failf(data, "%s", Curl_strerror(conn,error));
return CURLE_FTP_PORT_FAILED; return CURLE_FTP_PORT_FAILED;
} }
sslen = sizeof(ss); sslen = sizeof(ss);
if (getsockname(portsock, sa, &sslen) < 0) { if (getsockname(portsock, sa, &sslen) < 0) {
failf(data, "%s", strerror(errno)); failf(data, "%s", Curl_strerror(conn,Curl_ourerrno()));
return CURLE_FTP_PORT_FAILED; return CURLE_FTP_PORT_FAILED;
} }
@@ -1256,7 +1272,8 @@ CURLcode ftp_use_port(struct connectdata *conn)
portmsgbuf, tmp); portmsgbuf, tmp);
if(result) if(result)
return result; return result;
} else if (strcmp(*modep, "LPRT") == 0 || }
else if (strcmp(*modep, "LPRT") == 0 ||
strcmp(*modep, "PORT") == 0) { strcmp(*modep, "PORT") == 0) {
int i; int i;
@@ -1602,7 +1619,7 @@ CURLcode ftp_use_pasv(struct connectdata *conn,
newport = num; newport = num;
/* we should use the same host we already are connected to */ /* we should use the same host we already are connected to */
newhostp = conn->name; newhostp = conn->hostname;
} }
} }
else else
@@ -1834,7 +1851,7 @@ CURLcode Curl_ftp_nextconnect(struct connectdata *conn)
return result; return result;
} }
else if(!data->set.no_body) { else if(!conn->bits.no_body) {
/* Retrieve file or directory */ /* Retrieve file or directory */
bool dirlist=FALSE; bool dirlist=FALSE;
curl_off_t downloadsize=-1; curl_off_t downloadsize=-1;
@@ -1845,10 +1862,10 @@ CURLcode Curl_ftp_nextconnect(struct connectdata *conn)
char *ptr; char *ptr;
char *ptr2; char *ptr2;
from=strtoofft(conn->range, &ptr, 0); from=curlx_strtoofft(conn->range, &ptr, 0);
while(ptr && *ptr && (isspace((int)*ptr) || (*ptr=='-'))) while(ptr && *ptr && (isspace((int)*ptr) || (*ptr=='-')))
ptr++; ptr++;
to=strtoofft(ptr, &ptr2, 0); to=curlx_strtoofft(ptr, &ptr2, 0);
if(ptr == ptr2) { if(ptr == ptr2) {
/* we didn't get any digit */ /* we didn't get any digit */
to=-1; to=-1;
@@ -2067,7 +2084,7 @@ CURLcode Curl_ftp_nextconnect(struct connectdata *conn)
/* only if we have nothing but digits: */ /* only if we have nothing but digits: */
if(bytes++) { if(bytes++) {
/* get the number! */ /* get the number! */
size = strtoofft(bytes, NULL, 0); size = curlx_strtoofft(bytes, NULL, 0);
} }
} }
@@ -2156,7 +2173,7 @@ CURLcode ftp_perform(struct connectdata *conn,
{ {
int i; /* counter for loop */ int i; /* counter for loop */
for (i=0; ftp->dirs[i]; i++) { for (i=0; i < ftp->dirdepth; i++) {
/* RFC 1738 says empty components should be respected too, but /* RFC 1738 says empty components should be respected too, but
that is plain stupid since CWD can't be used with an empty argument */ that is plain stupid since CWD can't be used with an empty argument */
if ((result = ftp_cwd_and_mkd(conn, ftp->dirs[i])) != CURLE_OK) if ((result = ftp_cwd_and_mkd(conn, ftp->dirs[i])) != CURLE_OK)
@@ -2205,7 +2222,7 @@ CURLcode ftp_perform(struct connectdata *conn,
/* If we have selected NOBODY and HEADER, it means that we only want file /* If we have selected NOBODY and HEADER, it means that we only want file
information. Which in FTP can't be much more than the file size and information. Which in FTP can't be much more than the file size and
date. */ date. */
if(data->set.no_body && data->set.include_header && ftp->file) { if(conn->bits.no_body && data->set.include_header && ftp->file) {
/* The SIZE command is _not_ RFC 959 specified, and therefor many servers /* The SIZE command is _not_ RFC 959 specified, and therefor many servers
may not support it! It is however the only way we have to get a file's may not support it! It is however the only way we have to get a file's
size! */ size! */
@@ -2268,7 +2285,7 @@ CURLcode ftp_perform(struct connectdata *conn,
return CURLE_OK; return CURLE_OK;
} }
if(data->set.no_body) if(conn->bits.no_body)
/* doesn't really transfer any data */ /* doesn't really transfer any data */
ftp->no_transfer = TRUE; ftp->no_transfer = TRUE;
/* Get us a second connection up and connected */ /* Get us a second connection up and connected */
@@ -2301,7 +2318,7 @@ CURLcode ftp_perform(struct connectdata *conn,
* The input argument is already checked for validity. * The input argument is already checked for validity.
* *
* ftp->ctl_valid starts out as FALSE, and gets set to TRUE if we reach the * ftp->ctl_valid starts out as FALSE, and gets set to TRUE if we reach the
* end of the function. * Curl_ftp_done() function without finding any major problem.
*/ */
CURLcode Curl_ftp(struct connectdata *conn) CURLcode Curl_ftp(struct connectdata *conn)
{ {
@@ -2311,9 +2328,8 @@ CURLcode Curl_ftp(struct connectdata *conn)
struct FTP *ftp; struct FTP *ftp;
char *slash_pos; /* position of the first '/' char in curpos */ char *slash_pos; /* position of the first '/' char in curpos */
char *cur_pos=conn->ppath; /* current position in ppath. point at the begin char *cur_pos=conn->path; /* current position in ppath. point at the begin
of next path component */ of next path component */
int path_part=0;/* current path component */
/* the ftp struct is already inited in ftp_connect() */ /* the ftp struct is already inited in ftp_connect() */
ftp = conn->proto.ftp; ftp = conn->proto.ftp;
@@ -2325,23 +2341,28 @@ CURLcode Curl_ftp(struct connectdata *conn)
Curl_pgrsSetUploadSize(data, 0); Curl_pgrsSetUploadSize(data, 0);
Curl_pgrsSetDownloadSize(data, 0); Curl_pgrsSetDownloadSize(data, 0);
/* fixed : initialize ftp->dirs[xxx] to NULL ! ftp->dirdepth = 0;
is done in Curl_ftp_connect() */ ftp->diralloc = 5; /* default dir depth to allocate */
ftp->dirs = (char **)malloc(ftp->diralloc * sizeof(ftp->dirs[0]));
if(!ftp->dirs)
return CURLE_OUT_OF_MEMORY;
ftp->dirs[0] = NULL; /* to start with */
/* parse the URL path into separate path components */ /* parse the URL path into separate path components */
while((slash_pos=strchr(cur_pos, '/'))) { while((slash_pos=strchr(cur_pos, '/'))) {
/* 1 or 0 to indicate absolute directory */ /* 1 or 0 to indicate absolute directory */
bool absolute_dir = (cur_pos - conn->ppath > 0) && (path_part == 0); bool absolute_dir = (cur_pos - conn->path > 0) && (ftp->dirdepth == 0);
/* seek out the next path component */ /* seek out the next path component */
if (slash_pos-cur_pos) { if (slash_pos-cur_pos) {
/* we skip empty path components, like "x//y" since the FTP command CWD /* we skip empty path components, like "x//y" since the FTP command CWD
requires a parameter and a non-existant parameter a) doesn't work on requires a parameter and a non-existant parameter a) doesn't work on
many servers and b) has no effect on the others. */ many servers and b) has no effect on the others. */
ftp->dirs[path_part] = curl_unescape(cur_pos - absolute_dir, ftp->dirs[ftp->dirdepth] = curl_unescape(cur_pos - absolute_dir,
slash_pos - cur_pos + absolute_dir); slash_pos - cur_pos +
absolute_dir);
if (!ftp->dirs[path_part]) { /* run out of memory ... */ if (!ftp->dirs[ftp->dirdepth]) { /* run out of memory ... */
failf(data, "no memory"); failf(data, "no memory");
freedirs(ftp); freedirs(ftp);
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
@@ -2354,12 +2375,16 @@ CURLcode Curl_ftp(struct connectdata *conn)
if(!retcode) { if(!retcode) {
cur_pos = slash_pos + 1; /* jump to the rest of the string */ cur_pos = slash_pos + 1; /* jump to the rest of the string */
if(++path_part >= (CURL_MAX_FTP_DIRDEPTH-1)) { if(++ftp->dirdepth >= ftp->diralloc) {
/* too deep, we need the last entry to be kept NULL at all /* enlarge array */
times to signal end of list */ char *bigger;
failf(data, "too deep dir hierarchy"); ftp->diralloc *= 2; /* double the size each time */
bigger = realloc(ftp->dirs, ftp->diralloc * sizeof(ftp->dirs[0]));
if(!bigger) {
freedirs(ftp); freedirs(ftp);
return CURLE_URL_MALFORMAT; return CURLE_OUT_OF_MEMORY;
}
ftp->dirs = (char **)bigger;
} }
} }
} }
@@ -2400,7 +2425,8 @@ CURLcode Curl_ftp(struct connectdata *conn)
else else
freedirs(ftp); freedirs(ftp);
ftp->ctl_valid = TRUE; ftp->ctl_valid = TRUE; /* seems good */
return retcode; return retcode;
} }
@@ -2455,7 +2481,7 @@ CURLcode Curl_ftpsendf(struct connectdata *conn,
/*********************************************************************** /***********************************************************************
* *
* Curl_ftp_quit() * ftp_quit()
* *
* This should be called before calling sclose() on an ftp control connection * This should be called before calling sclose() on an ftp control connection
* (not data connections). We should then wait for the response from the * (not data connections). We should then wait for the response from the
@@ -2463,7 +2489,7 @@ CURLcode Curl_ftpsendf(struct connectdata *conn,
* connection. * connection.
* *
*/ */
CURLcode Curl_ftp_quit(struct connectdata *conn) static CURLcode ftp_quit(struct connectdata *conn)
{ {
ssize_t nread; ssize_t nread;
int ftpcode; int ftpcode;
@@ -2493,13 +2519,13 @@ CURLcode Curl_ftp_disconnect(struct connectdata *conn)
bad in any way, sending quit and waiting around here will make the bad in any way, sending quit and waiting around here will make the
disconnect wait in vain and cause more problems than we need to. disconnect wait in vain and cause more problems than we need to.
Curl_ftp_quit() will check the state of ftp->ctl_valid. If it's ok it ftp_quit() will check the state of ftp->ctl_valid. If it's ok it
will try to send the QUIT command, otherwise it will just return. will try to send the QUIT command, otherwise it will just return.
*/ */
/* The FTP session may or may not have been allocated/setup at this point! */ /* The FTP session may or may not have been allocated/setup at this point! */
if(ftp) { if(ftp) {
(void)Curl_ftp_quit(conn); /* ignore errors on the QUIT */ (void)ftp_quit(conn); /* ignore errors on the QUIT */
if(ftp->entrypath) if(ftp->entrypath)
free(ftp->entrypath); free(ftp->entrypath);
@@ -2507,10 +2533,6 @@ CURLcode Curl_ftp_disconnect(struct connectdata *conn)
free(ftp->cache); free(ftp->cache);
ftp->cache = NULL; ftp->cache = NULL;
} }
if(ftp->file) {
free(ftp->file);
ftp->file = NULL; /* zero */
}
freedirs(ftp); freedirs(ftp);
} }
return CURLE_OK; return CURLE_OK;

View File

@@ -32,7 +32,6 @@ CURLcode Curl_ftpsendf(struct connectdata *, const char *fmt, ...);
CURLcode Curl_GetFTPResponse(ssize_t *nread, struct connectdata *conn, CURLcode Curl_GetFTPResponse(ssize_t *nread, struct connectdata *conn,
int *ftpcode); int *ftpcode);
CURLcode Curl_ftp_nextconnect(struct connectdata *conn); CURLcode Curl_ftp_nextconnect(struct connectdata *conn);
CURLcode Curl_ftp_quit(struct connectdata *conn);
#endif #endif
#endif #endif

View File

@@ -742,16 +742,16 @@ ToYear (int Year)
static int static int
LookupWord (YYSTYPE *yylval, char *buff) LookupWord (YYSTYPE *yylval, char *buff)
{ {
register char *p; char *p;
register char *q; char *q;
register const TABLE *tp; const TABLE *tp;
int i; size_t i;
int abbrev; int abbrev;
/* Make it lowercase. */ /* Make it lowercase. */
for (p = buff; *p; p++) for (p = buff; *p; p++)
if (ISUPPER ((unsigned char) *p)) if (ISUPPER ((unsigned char) *p))
*p = tolower (*p); *p = tolower ((int)*p);
if (strcmp (buff, "am") == 0 || strcmp (buff, "a.m.") == 0) if (strcmp (buff, "am") == 0 || strcmp (buff, "a.m.") == 0)
{ {

View File

@@ -49,6 +49,9 @@
#ifdef HAVE_STDLIB_H #ifdef HAVE_STDLIB_H
#include <stdlib.h> /* required for free() prototypes */ #include <stdlib.h> /* required for free() prototypes */
#endif #endif
#ifdef HAVE_UNISTD_H
#include <unistd.h> /* for the close() proto */
#endif
#ifdef VMS #ifdef VMS
#include <in.h> #include <in.h>
#include <inet.h> #include <inet.h>
@@ -60,6 +63,10 @@
#include <setjmp.h> #include <setjmp.h>
#endif #endif
#ifdef WIN32
#include <process.h>
#endif
#if (defined(NETWARE) && defined(__NOVELL_LIBC__)) #if (defined(NETWARE) && defined(__NOVELL_LIBC__))
#undef in_addr_t #undef in_addr_t
#define in_addr_t unsigned long #define in_addr_t unsigned long
@@ -70,6 +77,7 @@
#include "hostip.h" #include "hostip.h"
#include "hash.h" #include "hash.h"
#include "share.h" #include "share.h"
#include "strerror.h"
#include "url.h" #include "url.h"
#define _MPRINTF_REPLACE /* use our functions only */ #define _MPRINTF_REPLACE /* use our functions only */
@@ -88,19 +96,32 @@
#define ARES_SUCCESS CURLE_OK #define ARES_SUCCESS CURLE_OK
#endif #endif
#define CURL_TIMEOUT_RESOLVE 300 /* when using asynch methods, we allow this
many seconds for a name resolve */
/* These two symbols are for the global DNS cache */
static curl_hash hostname_cache; static curl_hash hostname_cache;
static int host_cache_initialized; static int host_cache_initialized;
static void freednsentry(void *freethis);
/*
* my_getaddrinfo() is the generic low-level name resolve API within this
* source file. There exist three versions of this function - for different
* name resolve layers (selected at build-time). They all take this same set
* of arguments
*/
static Curl_addrinfo *my_getaddrinfo(struct connectdata *conn, static Curl_addrinfo *my_getaddrinfo(struct connectdata *conn,
char *hostname, char *hostname,
int port, int port,
int *waitp); int *waitp);
#ifndef ENABLE_IPV6
#if !defined(HAVE_GETHOSTBYNAME_R) || defined(USE_ARES) || \ #if (!defined(HAVE_GETHOSTBYNAME_R) || defined(USE_ARES) || \
defined(USE_THREADING_GETHOSTBYNAME) defined(USE_THREADING_GETHOSTBYNAME)) && \
!defined(ENABLE_IPV6)
static struct hostent* pack_hostent(char** buf, struct hostent* orig); static struct hostent* pack_hostent(char** buf, struct hostent* orig);
#endif #endif
#endif
#ifdef USE_THREADING_GETHOSTBYNAME #ifdef USE_THREADING_GETHOSTBYNAME
#ifdef DEBUG_THREADING_GETHOSTBYNAME #ifdef DEBUG_THREADING_GETHOSTBYNAME
@@ -113,29 +134,40 @@ static void trace_it (const char *fmt, ...);
#define TRACE(x) #define TRACE(x)
#endif #endif
static struct hostent* pack_hostent (char** buf, struct hostent* orig);
static bool init_gethostbyname_thread (struct connectdata *conn, static bool init_gethostbyname_thread (struct connectdata *conn,
const char *hostname, int port); const char *hostname, int port);
struct thread_data { struct thread_data {
HANDLE thread_hnd; HANDLE thread_hnd;
DWORD thread_id; unsigned thread_id;
DWORD thread_status; DWORD thread_status;
curl_socket_t dummy_sock; /* dummy for Curl_multi_ares_fdset() */
}; };
#endif #endif
/*
* Curl_global_host_cache_init() initializes and sets up a global DNS cache.
* Global DNS cache is general badness. Do not use. This will be removed in
* a future version. Use the share interface instead!
*/
void Curl_global_host_cache_init(void) void Curl_global_host_cache_init(void)
{ {
if (!host_cache_initialized) { if (!host_cache_initialized) {
Curl_hash_init(&hostname_cache, 7, Curl_freednsinfo); Curl_hash_init(&hostname_cache, 7, freednsentry);
host_cache_initialized = 1; host_cache_initialized = 1;
} }
} }
/*
* Return a pointer to the global cache
*/
curl_hash *Curl_global_host_cache_get(void) curl_hash *Curl_global_host_cache_get(void)
{ {
return &hostname_cache; return &hostname_cache;
} }
/*
* Destroy and cleanup the global DNS cache
*/
void Curl_global_host_cache_dtor(void) void Curl_global_host_cache_dtor(void)
{ {
if (host_cache_initialized) { if (host_cache_initialized) {
@@ -144,7 +176,10 @@ void Curl_global_host_cache_dtor(void)
} }
} }
/* count the number of characters that an integer takes up */ /*
* Minor utility-function:
* Count the number of characters that an integer takes up.
*/
static int _num_chars(int i) static int _num_chars(int i)
{ {
int chars = 0; int chars = 0;
@@ -165,7 +200,10 @@ static int _num_chars(int i)
return chars; return chars;
} }
/* Create a hostcache id */ /*
* Minor utility-function:
* Create a hostcache id string for the DNS caching.
*/
static char * static char *
create_hostcache_id(char *server, int port, size_t *entry_len) create_hostcache_id(char *server, int port, size_t *entry_len)
{ {
@@ -192,6 +230,13 @@ struct hostcache_prune_data {
time_t now; time_t now;
}; };
/*
* This function is set as a callback to be called for every entry in the DNS
* cache when we want to prune old unused entries.
*
* Returning non-zero means remove the entry, return 0 to keep it in the
* cache.
*/
static int static int
hostcache_timestamp_remove(void *datap, void *hc) hostcache_timestamp_remove(void *datap, void *hc)
{ {
@@ -209,6 +254,9 @@ hostcache_timestamp_remove(void *datap, void *hc)
return 1; return 1;
} }
/*
* Prune the DNS cache. This assumes that a lock has already been taken.
*/
static void static void
hostcache_prune(curl_hash *hostcache, int cache_timeout, time_t now) hostcache_prune(curl_hash *hostcache, int cache_timeout, time_t now)
{ {
@@ -222,6 +270,10 @@ hostcache_prune(curl_hash *hostcache, int cache_timeout, time_t now)
hostcache_timestamp_remove); hostcache_timestamp_remove);
} }
/*
* Library-wide function for pruning the DNS cache. This function takes and
* returns the appropriate locks.
*/
void Curl_hostcache_prune(struct SessionHandle *data) void Curl_hostcache_prune(struct SessionHandle *data)
{ {
time_t now; time_t now;
@@ -245,15 +297,22 @@ void Curl_hostcache_prune(struct SessionHandle *data)
} }
#ifdef HAVE_SIGSETJMP #ifdef HAVE_SIGSETJMP
/* Beware this is a global and unique instance */ /* Beware this is a global and unique instance. This is used to store the
return address that we can jump back to from inside a signal handler. This
is not thread-safe stuff. */
sigjmp_buf curl_jmpenv; sigjmp_buf curl_jmpenv;
#endif #endif
/* When calling Curl_resolv() has resulted in a response with a returned /*
address, we call this function to store the information in the dns * cache_resolv_response() stores a 'Curl_addrinfo' struct in the DNS cache.
cache etc */ *
* When calling Curl_resolv() has resulted in a response with a returned
* address, we call this function to store the information in the dns
* cache etc
*
* Returns the Curl_dns_entry entry pointer or NULL if the storage failed.
*/
static struct Curl_dns_entry * static struct Curl_dns_entry *
cache_resolv_response(struct SessionHandle *data, cache_resolv_response(struct SessionHandle *data,
Curl_addrinfo *addr, Curl_addrinfo *addr,
@@ -303,14 +362,21 @@ cache_resolv_response(struct SessionHandle *data,
return dns; return dns;
} }
/* Resolve a name and return a pointer in the 'entry' argument if one /*
is available. * Curl_resolv() is the main name resolve function within libcurl. It resolves
* a name and returns a pointer to the entry in the 'entry' argument (if one
Return codes: * is provided). This function might return immediately if we're using asynch
* resolves. See the return codes.
-1 = error, no pointer *
0 = OK, pointer provided * The cache entry we return will get its 'inuse' counter increased when this
1 = waiting for response, no pointer * function is used. You MUST call Curl_resolv_unlock() later (when you're
* done using this struct) to decrease the counter again.
*
* Return codes:
*
* -1 = error, no pointer
* 0 = OK, pointer provided
* 1 = waiting for response, no pointer
*/ */
int Curl_resolv(struct connectdata *conn, int Curl_resolv(struct connectdata *conn,
char *hostname, char *hostname,
@@ -405,6 +471,11 @@ int Curl_resolv(struct connectdata *conn,
return rc; return rc;
} }
/*
* Curl_resolv_unlock() unlocks the given cached DNS entry. When this has been
* made, the struct may be destroyed due to pruning. It is important that only
* one unlock is made for each Curl_resolv() call.
*/
void Curl_resolv_unlock(struct SessionHandle *data, struct Curl_dns_entry *dns) void Curl_resolv_unlock(struct SessionHandle *data, struct Curl_dns_entry *dns)
{ {
if(data->share) if(data->share)
@@ -438,9 +509,9 @@ void Curl_freeaddrinfo(Curl_addrinfo *p)
} }
/* /*
* Free a cache dns entry. * File-internal: free a cache dns entry.
*/ */
void Curl_freednsinfo(void *freethis) static void freednsentry(void *freethis)
{ {
struct Curl_dns_entry *p = (struct Curl_dns_entry *) freethis; struct Curl_dns_entry *p = (struct Curl_dns_entry *) freethis;
@@ -449,6 +520,14 @@ void Curl_freednsinfo(void *freethis)
free(p); free(p);
} }
/*
* Curl_mk_dnscache() creates a new DNS cache and returns the handle for it.
*/
curl_hash *Curl_mk_dnscache(void)
{
return Curl_hash_alloc(7, freednsentry);
}
/* --- resolve name or IP-number --- */ /* --- resolve name or IP-number --- */
/* Allocate enough memory to hold the full name information structs and /* Allocate enough memory to hold the full name information structs and
@@ -460,6 +539,15 @@ void Curl_freednsinfo(void *freethis)
#ifdef USE_ARES #ifdef USE_ARES
/*
* Curl_multi_ares_fdset() is called when someone from the outside world
* (using curl_multi_fdset()) wants to get our fd_set setup and we're talking
* with ares. The caller must make sure that this function is only called when
* we have a working ares channel.
*
* Returns: CURLE_OK always!
*/
CURLcode Curl_multi_ares_fdset(struct connectdata *conn, CURLcode Curl_multi_ares_fdset(struct connectdata *conn,
fd_set *read_fd_set, fd_set *read_fd_set,
fd_set *write_fd_set, fd_set *write_fd_set,
@@ -473,24 +561,32 @@ CURLcode Curl_multi_ares_fdset(struct connectdata *conn,
return CURLE_OK; return CURLE_OK;
} }
/* called to check if the name is resolved now */ /*
* Curl_is_resolved() is called repeatedly to check if a previous name resolve
* request has completed. It should also make sure to time-out if the
* operation seems to take too long.
*
* Returns normal CURLcode errors.
*/
CURLcode Curl_is_resolved(struct connectdata *conn, CURLcode Curl_is_resolved(struct connectdata *conn,
struct Curl_dns_entry **dns) struct Curl_dns_entry **dns)
{ {
fd_set read_fds, write_fds; fd_set read_fds, write_fds;
static const struct timeval tv={0,0}; struct timeval tv={0,0};
int count; int count;
struct SessionHandle *data = conn->data; struct SessionHandle *data = conn->data;
int nfds; int nfds;
FD_ZERO(&read_fds); FD_ZERO(&read_fds);
FD_ZERO(&write_fds); FD_ZERO(&write_fds);
nfds = ares_fds(data->state.areschannel, &read_fds, &write_fds); nfds = ares_fds(data->state.areschannel, &read_fds, &write_fds);
count = select(nfds, &read_fds, &write_fds, NULL, count = select(nfds, &read_fds, &write_fds, NULL,
(struct timeval *)&tv); (struct timeval *)&tv);
if(count) /* Call ares_process() unconditonally here, even if we simply timed out
above, as otherwise the ares name resolve won't timeout! */
ares_process(data->state.areschannel, &read_fds, &write_fds); ares_process(data->state.areschannel, &read_fds, &write_fds);
*dns = NULL; *dns = NULL;
@@ -505,23 +601,21 @@ CURLcode Curl_is_resolved(struct connectdata *conn,
return CURLE_OK; return CURLE_OK;
} }
/* This is a function that locks and waits until the name resolve operation /*
has completed. * Curl_wait_for_resolv() waits for a resolve to finish. This function should
* be avoided since using this risk getting the multi interface to "hang".
If 'entry' is non-NULL, make it point to the resolved dns entry *
* If 'entry' is non-NULL, make it point to the resolved dns entry
Return CURLE_COULDNT_RESOLVE_HOST if the host was not resolved, and *
CURLE_OPERATION_TIMEDOUT if a time-out occurred. * Returns CURLE_COULDNT_RESOLVE_HOST if the host was not resolved, and
* CURLE_OPERATION_TIMEDOUT if a time-out occurred.
*/ */
CURLcode Curl_wait_for_resolv(struct connectdata *conn, CURLcode Curl_wait_for_resolv(struct connectdata *conn,
struct Curl_dns_entry **entry) struct Curl_dns_entry **entry)
{ {
CURLcode rc=CURLE_OK; CURLcode rc=CURLE_OK;
struct SessionHandle *data = conn->data; struct SessionHandle *data = conn->data;
struct timeval now = Curl_tvnow(); long timeout = CURL_TIMEOUT_RESOLVE; /* default name resolve timeout */
bool timedout = FALSE;
long timeout = 300; /* default name resolve timeout in seconds */
long elapsed = 0; /* time taken so far */
/* now, see if there's a connect timeout or a regular timeout to /* now, see if there's a connect timeout or a regular timeout to
use instead of the default one */ use instead of the default one */
@@ -530,34 +624,46 @@ CURLcode Curl_wait_for_resolv(struct connectdata *conn,
else if(conn->data->set.timeout) else if(conn->data->set.timeout)
timeout = conn->data->set.timeout; timeout = conn->data->set.timeout;
/* We convert the number of seconds into number of milliseconds here: */
if(timeout < 2147483)
/* maximum amount of seconds that can be multiplied with 1000 and
still fit within 31 bits */
timeout *= 1000;
else
timeout = 0x7fffffff; /* ridiculous amount of time anyway */
/* Wait for the name resolve query to complete. */ /* Wait for the name resolve query to complete. */
while (1) { while (1) {
int nfds=0; int nfds=0;
fd_set read_fds, write_fds; fd_set read_fds, write_fds;
struct timeval *tvp, tv, store; struct timeval *tvp, tv, store;
int count; int count;
struct timeval now = Curl_tvnow();
long timediff;
store.tv_sec = (int)(timeout - elapsed); store.tv_sec = (int)timeout/1000;
store.tv_usec = 0; store.tv_usec = (timeout%1000)*1000;
FD_ZERO(&read_fds); FD_ZERO(&read_fds);
FD_ZERO(&write_fds); FD_ZERO(&write_fds);
nfds = ares_fds(data->state.areschannel, &read_fds, &write_fds); nfds = ares_fds(data->state.areschannel, &read_fds, &write_fds);
if (nfds == 0) if (nfds == 0)
/* no file descriptors means we're done waiting */
break; break;
tvp = ares_timeout(data->state.areschannel, tvp = ares_timeout(data->state.areschannel, &store, &tv);
&store, &tv);
count = select(nfds, &read_fds, &write_fds, NULL, tvp); count = select(nfds, &read_fds, &write_fds, NULL, tvp);
if (count < 0 && errno != EINVAL) if (count < 0 && errno != EINVAL)
break; break;
else if(!count) {
/* timeout */
timedout = TRUE;
break;
}
ares_process(data->state.areschannel, &read_fds, &write_fds); ares_process(data->state.areschannel, &read_fds, &write_fds);
elapsed = Curl_tvdiff(Curl_tvnow(), now)/1000; /* spent time */ timediff = Curl_tvdiff(Curl_tvnow(), now); /* spent time */
timeout -= timediff?timediff:1; /* always deduct at least 1 */
if (timeout < 0) {
/* our timeout, so we cancel the ares operation */
ares_cancel(data->state.areschannel);
break;
}
} }
/* Operation complete, if the lookup was successful we now have the entry /* Operation complete, if the lookup was successful we now have the entry
@@ -568,12 +674,12 @@ CURLcode Curl_wait_for_resolv(struct connectdata *conn,
if(!conn->async.dns) { if(!conn->async.dns) {
/* a name was not resolved */ /* a name was not resolved */
if(timedout || (conn->async.status == ARES_ETIMEOUT)) { if((timeout < 0) || (conn->async.status == ARES_ETIMEOUT)) {
failf(data, "Resolving host timed out: %s", conn->name); failf(data, "Resolving host timed out: %s", conn->hostname);
rc = CURLE_OPERATION_TIMEDOUT; rc = CURLE_OPERATION_TIMEDOUT;
} }
else if(conn->async.done) { else if(conn->async.done) {
failf(data, "Could not resolve host: %s (%s)", conn->name, failf(data, "Could not resolve host: %s (%s)", conn->hostname,
ares_strerror(conn->async.status)); ares_strerror(conn->async.status));
rc = CURLE_COULDNT_RESOLVE_HOST; rc = CURLE_COULDNT_RESOLVE_HOST;
} }
@@ -591,8 +697,16 @@ CURLcode Curl_wait_for_resolv(struct connectdata *conn,
#if defined(USE_ARES) || defined(USE_THREADING_GETHOSTBYNAME) #if defined(USE_ARES) || defined(USE_THREADING_GETHOSTBYNAME)
/* this function gets called by ares/gethostbyname_thread() when we got /*
the name resolved or not */ * host_callback() gets called by ares/gethostbyname_thread() when we got the
* name resolved (or not!).
*
* If the status argument is ARES_SUCCESS, we must copy the hostent field
* since ares will free it when this function returns. This operation stores
* the resolved data in the DNS cache.
*
* The storage operation locks and unlocks the DNS cache.
*/
static void host_callback(void *arg, /* "struct connectdata *" */ static void host_callback(void *arg, /* "struct connectdata *" */
int status, int status,
struct hostent *hostent) struct hostent *hostent)
@@ -633,9 +747,11 @@ static void host_callback(void *arg, /* "struct connectdata *" */
#ifdef USE_ARES #ifdef USE_ARES
/* /*
* Return name information about the given hostname and port number. If * my_getaddrinfo() when using ares for name resolves.
*
* Returns name information about the given hostname and port number. If
* successful, the 'hostent' is returned and the forth argument will point to * successful, the 'hostent' is returned and the forth argument will point to
* memory we need to free after use. That meory *MUST* be freed with * memory we need to free after use. That memory *MUST* be freed with
* Curl_freeaddrinfo(), nothing else. * Curl_freeaddrinfo(), nothing else.
*/ */
static Curl_addrinfo *my_getaddrinfo(struct connectdata *conn, static Curl_addrinfo *my_getaddrinfo(struct connectdata *conn,
@@ -648,6 +764,10 @@ static Curl_addrinfo *my_getaddrinfo(struct connectdata *conn,
*waitp = FALSE; *waitp = FALSE;
if(data->set.ip_version == CURL_IPRESOLVE_V6)
/* an ipv6 address was requested and we can't get/use one */
return NULL;
bufp = strdup(hostname); bufp = strdup(hostname);
if(bufp) { if(bufp) {
@@ -670,9 +790,14 @@ static Curl_addrinfo *my_getaddrinfo(struct connectdata *conn,
#if !defined(USE_ARES) && !defined(USE_THREADING_GETHOSTBYNAME) #if !defined(USE_ARES) && !defined(USE_THREADING_GETHOSTBYNAME)
/* For builds without ARES and threaded gethostbyname, Curl_resolv() can never /*
return wait==TRUE, so this function will never be called. If it still gets * Curl_wait_for_resolv() for builds without ARES and threaded gethostbyname,
called, we return failure at once. */ * Curl_resolv() can never return wait==TRUE, so this function will never be
* called. If it still gets called, we return failure at once.
*
* We provide this function only to allow multi.c to remain unaware if we are
* doing asynch resolves or not.
*/
CURLcode Curl_wait_for_resolv(struct connectdata *conn, CURLcode Curl_wait_for_resolv(struct connectdata *conn,
struct Curl_dns_entry **entry) struct Curl_dns_entry **entry)
{ {
@@ -681,6 +806,13 @@ CURLcode Curl_wait_for_resolv(struct connectdata *conn,
return CURLE_COULDNT_RESOLVE_HOST; return CURLE_COULDNT_RESOLVE_HOST;
} }
/*
* This function will never be called when built with ares or threaded
* resolves. If it still gets called, we return failure at once.
*
* We provide this function only to allow multi.c to remain unaware if we are
* doing asynch resolves or not.
*/
CURLcode Curl_is_resolved(struct connectdata *conn, CURLcode Curl_is_resolved(struct connectdata *conn,
struct Curl_dns_entry **dns) struct Curl_dns_entry **dns)
{ {
@@ -692,18 +824,32 @@ CURLcode Curl_is_resolved(struct connectdata *conn,
#endif #endif
#if !defined(USE_ARES) #if !defined(USE_ARES)
/*
* Non-ares build. If we are using threading gethostbyname, then this must
* set the fd_set for the threaded resolve socket. If not, we just return OK.
*/
CURLcode Curl_multi_ares_fdset(struct connectdata *conn, CURLcode Curl_multi_ares_fdset(struct connectdata *conn,
fd_set *read_fd_set, fd_set *read_fd_set,
fd_set *write_fd_set, fd_set *write_fd_set,
int *max_fdp) int *max_fdp)
{ {
#ifdef USE_THREADING_GETHOSTBYNAME
const struct thread_data *td =
(const struct thread_data *) conn->async.os_specific;
if (td && td->dummy_sock != CURL_SOCKET_BAD) {
FD_SET(td->dummy_sock,write_fd_set);
*max_fdp = td->dummy_sock;
}
#else /* if not USE_THREADING_GETHOSTBYNAME */
(void)conn; (void)conn;
(void)read_fd_set; (void)read_fd_set;
(void)write_fd_set; (void)write_fd_set;
(void)max_fdp; (void)max_fdp;
#endif
return CURLE_OK; return CURLE_OK;
} }
#endif #endif /* !USE_ARES */
#if defined(ENABLE_IPV6) && !defined(USE_ARES) #if defined(ENABLE_IPV6) && !defined(USE_ARES)
@@ -745,9 +891,11 @@ void curl_freeaddrinfo(struct addrinfo *freethis,
#endif #endif
/* /*
* Return name information about the given hostname and port number. If * my_getaddrinfo() when built ipv6-enabled.
*
* Returns name information about the given hostname and port number. If
* successful, the 'addrinfo' is returned and the forth argument will point to * successful, the 'addrinfo' is returned and the forth argument will point to
* memory we need to free after use. That meory *MUST* be freed with * memory we need to free after use. That memory *MUST* be freed with
* Curl_freeaddrinfo(), nothing else. * Curl_freeaddrinfo(), nothing else.
*/ */
static Curl_addrinfo *my_getaddrinfo(struct connectdata *conn, static Curl_addrinfo *my_getaddrinfo(struct connectdata *conn,
@@ -765,11 +913,17 @@ static Curl_addrinfo *my_getaddrinfo(struct connectdata *conn,
/* see if we have an IPv6 stack */ /* see if we have an IPv6 stack */
s = socket(PF_INET6, SOCK_DGRAM, 0); s = socket(PF_INET6, SOCK_DGRAM, 0);
if (s < 0) if (s < 0) {
/* Some non-IPv6 stacks have been found to make very slow name resolves /* Some non-IPv6 stacks have been found to make very slow name resolves
* when PF_UNSPEC is used, so thus we switch to a mere PF_INET lookup if * when PF_UNSPEC is used, so thus we switch to a mere PF_INET lookup if
* the stack seems to be a non-ipv6 one. */ * the stack seems to be a non-ipv6 one. */
if(data->set.ip_version == CURL_IPRESOLVE_V6)
/* an ipv6 address was requested and we can't get/use one */
return NULL;
pf = PF_INET; pf = PF_INET;
}
else { else {
/* This seems to be an IPv6-capable stack, use PF_UNSPEC for the widest /* This seems to be an IPv6-capable stack, use PF_UNSPEC for the widest
* possible checks. And close the socket again. * possible checks. And close the socket again.
@@ -807,11 +961,14 @@ static Curl_addrinfo *my_getaddrinfo(struct connectdata *conn,
} }
#else /* following code is IPv4-only */ #else /* following code is IPv4-only */
#if !defined(HAVE_GETHOSTBYNAME_R) || defined(USE_ARES) || defined(USE_THREADING_GETHOSTBYNAME) #if !defined(HAVE_GETHOSTBYNAME_R) || defined(USE_ARES) || \
defined(USE_THREADING_GETHOSTBYNAME)
static void hostcache_fixoffset(struct hostent *h, long offset); static void hostcache_fixoffset(struct hostent *h, long offset);
/* /*
* Performs a "deep" copy of a hostent into a buffer (returns a pointer to the * pack_hostent() is a file-local function that performs a "deep" copy of a
* copy). Make absolutely sure the destination buffer is big enough! * hostent into a buffer (returns a pointer to the copy). Make absolutely sure
* the destination buffer is big enough!
*/ */
static struct hostent* pack_hostent(char** buf, struct hostent* orig) static struct hostent* pack_hostent(char** buf, struct hostent* orig)
{ {
@@ -887,11 +1044,11 @@ static struct hostent* pack_hostent(char** buf, struct hostent* orig)
/* now, shrink the allocated buffer to the size we actually need, which /* now, shrink the allocated buffer to the size we actually need, which
most often is only a fraction of the original alloc */ most often is only a fraction of the original alloc */
newbuf=(char *)realloc(*buf, (long)bufptr-(long)(*buf)); newbuf=(char *)realloc(*buf, (long)(bufptr-*buf));
/* if the alloc moved, we need to adjust things again */ /* if the alloc moved, we need to adjust things again */
if(newbuf != *buf) if(newbuf != *buf)
hostcache_fixoffset((struct hostent*)newbuf, (long)newbuf-(long)*buf); hostcache_fixoffset((struct hostent*)newbuf, (long)(newbuf-*buf));
/* setup the return */ /* setup the return */
*buf = newbuf; *buf = newbuf;
@@ -901,6 +1058,12 @@ static struct hostent* pack_hostent(char** buf, struct hostent* orig)
} }
#endif #endif
/*
* hostcache_fixoffset() is a utility-function that corrects all pointers in
* the given hostent struct according to the offset. This is typically used
* when a hostent has been reallocated and needs to be setup properly on the
* new address.
*/
static void hostcache_fixoffset(struct hostent *h, long offset) static void hostcache_fixoffset(struct hostent *h, long offset)
{ {
int i=0; int i=0;
@@ -925,6 +1088,11 @@ static void hostcache_fixoffset(struct hostent *h, long offset)
#ifndef USE_ARES #ifndef USE_ARES
/*
* MakeIP() converts the input binary ipv4-address to an ascii string in the
* dotted numerical format. 'addr' is a pointer to a buffer that is 'addr_len'
* bytes big. 'num' is the 32 bit IP number.
*/
static char *MakeIP(unsigned long num, char *addr, int addr_len) static char *MakeIP(unsigned long num, char *addr, int addr_len)
{ {
#if defined(HAVE_INET_NTOA) || defined(HAVE_INET_NTOA_R) #if defined(HAVE_INET_NTOA) || defined(HAVE_INET_NTOA_R)
@@ -946,9 +1114,13 @@ static char *MakeIP(unsigned long num, char *addr, int addr_len)
return (addr); return (addr);
} }
/* The original code to this function was once stolen from the Dancer source /*
code, written by Bjorn Reese, it has since been patched and modified * my_getaddrinfo() - the ipv4 "traditional" version.
considerably. */ *
* The original code to this function was once stolen from the Dancer source
* code, written by Bjorn Reese, it has since been patched and modified
* considerably.
*/
static Curl_addrinfo *my_getaddrinfo(struct connectdata *conn, static Curl_addrinfo *my_getaddrinfo(struct connectdata *conn,
char *hostname, char *hostname,
int port, int port,
@@ -961,6 +1133,10 @@ static Curl_addrinfo *my_getaddrinfo(struct connectdata *conn,
*waitp = 0; /* don't wait, we act synchronously */ *waitp = 0; /* don't wait, we act synchronously */
if(data->set.ip_version == CURL_IPRESOLVE_V6)
/* an ipv6 address was requested and we can't get/use one */
return NULL;
in=inet_addr(hostname); in=inet_addr(hostname);
if (in != CURL_INADDR_NONE) { if (in != CURL_INADDR_NONE) {
struct in_addr *addrentry; struct in_addr *addrentry;
@@ -1148,6 +1324,7 @@ static Curl_addrinfo *my_getaddrinfo(struct connectdata *conn,
else { else {
#ifdef USE_THREADING_GETHOSTBYNAME #ifdef USE_THREADING_GETHOSTBYNAME
/* fire up a new resolver thread! */
if (init_gethostbyname_thread(conn,hostname,port)) { if (init_gethostbyname_thread(conn,hostname,port)) {
*waitp = TRUE; /* please wait for the response */ *waitp = TRUE; /* please wait for the response */
return NULL; return NULL;
@@ -1183,20 +1360,26 @@ static void trace_it (const char *fmt, ...)
static int do_trace = -1; static int do_trace = -1;
va_list args; va_list args;
if (do_trace == -1) if (do_trace == -1) {
do_trace = getenv("CURL_TRACE") ? 1 : 0; const char *env = getenv("CURL_TRACE");
do_trace = (env && atoi(env) > 0);
}
if (!do_trace) if (!do_trace)
return; return;
va_start (args, fmt); va_start (args, fmt);
vfprintf (stderr, fmt, args); vfprintf (stderr, fmt, args);
fflush (stderr); /*fflush (stderr); */ /* seems a bad idea in a multi-threaded app */
va_end (args); va_end (args);
} }
#endif #endif
/* For builds without ARES/USE_IPV6, create a resolver thread and wait on it. /*
* gethostbyname_thread() resolves a name, calls the host_callback and then
* exits.
*
* For builds without ARES/USE_IPV6, create a resolver thread and wait on it.
*/ */
static DWORD WINAPI gethostbyname_thread (void *arg) static unsigned __stdcall gethostbyname_thread (void *arg)
{ {
struct connectdata *conn = (struct connectdata*) arg; struct connectdata *conn = (struct connectdata*) arg;
struct hostent *he; struct hostent *he;
@@ -1215,32 +1398,43 @@ static DWORD WINAPI gethostbyname_thread (void *arg)
TRACE(("Winsock-error %d, addr %s\n", conn->async.status, TRACE(("Winsock-error %d, addr %s\n", conn->async.status,
he ? inet_ntoa(*(struct in_addr*)he->h_addr) : "unknown")); he ? inet_ntoa(*(struct in_addr*)he->h_addr) : "unknown"));
return (rc); return (rc);
/* An implicit ExitThread() here */ /* An implicit _endthreadex() here */
} }
/* complementary of ares_destroy /*
* destroy_thread_data() cleans up async resolver data.
* Complementary of ares_destroy.
*/ */
static void destroy_thread_data (struct connectdata *conn) static void destroy_thread_data (struct Curl_async *async)
{ {
if (conn->async.hostname) if (async->hostname)
free(conn->async.hostname); free(async->hostname);
if (conn->async.os_specific)
free(conn->async.os_specific); if (async->os_specific) {
conn->async.hostname = NULL; curl_socket_t sock = ((const struct thread_data*)async->os_specific)->dummy_sock;
conn->async.os_specific = NULL;
if (sock != CURL_SOCKET_BAD)
sclose(sock);
free(async->os_specific);
}
async->hostname = NULL;
async->os_specific = NULL;
} }
/*
* init_gethostbyname_thread() starts a new thread that performs
* the actual resolve. This function returns before the resolve is done.
*/
static bool init_gethostbyname_thread (struct connectdata *conn, static bool init_gethostbyname_thread (struct connectdata *conn,
const char *hostname, int port) const char *hostname, int port)
{ {
struct thread_data *td = malloc(sizeof(*td)); struct thread_data *td = calloc(sizeof(*td), 1);
if (!td) { if (!td) {
SetLastError(ENOMEM); SetLastError(ENOMEM);
return (0); return (0);
} }
memset (td, 0, sizeof(*td));
Curl_safefree(conn->async.hostname); Curl_safefree(conn->async.hostname);
conn->async.hostname = strdup(hostname); conn->async.hostname = strdup(hostname);
if (!conn->async.hostname) { if (!conn->async.hostname) {
@@ -1255,17 +1449,31 @@ static bool init_gethostbyname_thread (struct connectdata *conn,
conn->async.dns = NULL; conn->async.dns = NULL;
conn->async.os_specific = (void*) td; conn->async.os_specific = (void*) td;
td->thread_hnd = CreateThread(NULL, 0, gethostbyname_thread, td->dummy_sock = CURL_SOCKET_BAD;
td->thread_hnd = (HANDLE) _beginthreadex(NULL, 0, gethostbyname_thread,
conn, 0, &td->thread_id); conn, 0, &td->thread_id);
if (!td->thread_hnd) { if (!td->thread_hnd) {
TRACE(("CreateThread() failed; %lu\n", GetLastError())); SetLastError(errno);
destroy_thread_data(conn); TRACE(("_beginthreadex() failed; %s\n", Curl_strerror(conn,errno)));
destroy_thread_data(&conn->async);
return (0); return (0);
} }
/* This socket is only to keep Curl_multi_ares_fdset() and select() happy;
* should never become signalled for read/write since it's unbound but
* Windows needs atleast 1 socket in select().
*/
td->dummy_sock = socket(AF_INET, SOCK_DGRAM, 0);
return (1); return (1);
} }
/* called to check if the name is resolved now */ /*
* Curl_wait_for_resolv() waits for a resolve to finish. This function should
* be avoided since using this risk getting the multi interface to "hang".
*
* If 'entry' is non-NULL, make it point to the resolved dns entry
*
* This is the version for resolves-in-a-thread.
*/
CURLcode Curl_wait_for_resolv(struct connectdata *conn, CURLcode Curl_wait_for_resolv(struct connectdata *conn,
struct Curl_dns_entry **entry) struct Curl_dns_entry **entry)
{ {
@@ -1279,26 +1487,31 @@ CURLcode Curl_wait_for_resolv(struct connectdata *conn,
/* now, see if there's a connect timeout or a regular timeout to /* now, see if there's a connect timeout or a regular timeout to
use instead of the default one */ use instead of the default one */
timeout = conn->data->set.connecttimeout ? conn->data->set.connecttimeout : timeout =
conn->data->set.connecttimeout ? conn->data->set.connecttimeout :
conn->data->set.timeout ? conn->data->set.timeout : conn->data->set.timeout ? conn->data->set.timeout :
300; /* default name resolve timeout in seconds */ CURL_TIMEOUT_RESOLVE; /* default name resolve timeout */
ticks = GetTickCount(); ticks = GetTickCount();
status = WaitForSingleObject(td->thread_hnd, 1000UL*timeout); status = WaitForSingleObject(td->thread_hnd, 1000UL*timeout);
if (status == WAIT_OBJECT_0 || status == WAIT_ABANDONED) { if (status == WAIT_OBJECT_0 || status == WAIT_ABANDONED) {
/* Thread finished before timeout; propagate Winsock error to this thread */ /* Thread finished before timeout; propagate Winsock error to this thread.
* 'conn->async.done = TRUE' is set in host_callback().
*/
WSASetLastError(conn->async.status); WSASetLastError(conn->async.status);
GetExitCodeThread(td->thread_hnd, &td->thread_status); GetExitCodeThread(td->thread_hnd, &td->thread_status);
TRACE(("status %lu, thread-status %08lX\n", status, td->thread_status)); TRACE(("gethostbyname_thread() status %lu, thread retval %lu, ",
status, td->thread_status));
} }
else { else {
conn->async.done = TRUE; conn->async.done = TRUE;
TerminateThread(td->thread_hnd, (DWORD)-1);
td->thread_status = (DWORD)-1; td->thread_status = (DWORD)-1;
TRACE(("gethostbyname_thread() timeout, "));
} }
TRACE(("gethostbyname_thread() retval %08lX, elapsed %lu ms\n", TRACE(("elapsed %lu ms\n", GetTickCount()-ticks));
td->thread_status, GetTickCount()-ticks));
CloseHandle(td->thread_hnd);
if(entry) if(entry)
*entry = conn->async.dns; *entry = conn->async.dns;
@@ -1308,24 +1521,33 @@ CURLcode Curl_wait_for_resolv(struct connectdata *conn,
if (!conn->async.dns) { if (!conn->async.dns) {
/* a name was not resolved */ /* a name was not resolved */
if (td->thread_status == (DWORD)-1 || conn->async.status == NO_DATA) { if (td->thread_status == (DWORD)-1 || conn->async.status == NO_DATA) {
failf(data, "Resolving host timed out: %s", conn->name); failf(data, "Resolving host timed out: %s", conn->hostname);
rc = CURLE_OPERATION_TIMEDOUT; rc = CURLE_OPERATION_TIMEDOUT;
} }
else if(conn->async.done) { else if(conn->async.done) {
failf(data, "Could not resolve host: %s (code %lu)", conn->name, conn->async.status); failf(data, "Could not resolve host: %s; %s",
conn->hostname, Curl_strerror(conn,conn->async.status));
rc = CURLE_COULDNT_RESOLVE_HOST; rc = CURLE_COULDNT_RESOLVE_HOST;
} }
else else
rc = CURLE_OPERATION_TIMEDOUT; rc = CURLE_OPERATION_TIMEDOUT;
}
destroy_thread_data(conn); destroy_thread_data(&conn->async);
if (CURLE_OK != rc)
/* close the connection, since we can't return failure here without /* close the connection, since we can't return failure here without
cleaning up this connection properly */ cleaning up this connection properly */
Curl_disconnect(conn); Curl_disconnect(conn);
}
return (rc); return (rc);
} }
/*
* Curl_is_resolved() is called repeatedly to check if a previous name resolve
* request has completed. It should also make sure to time-out if the
* operation seems to take too long.
*/
CURLcode Curl_is_resolved(struct connectdata *conn, CURLcode Curl_is_resolved(struct connectdata *conn,
struct Curl_dns_entry **entry) struct Curl_dns_entry **entry)
{ {
@@ -1333,7 +1555,7 @@ CURLcode Curl_is_resolved(struct connectdata *conn,
if (conn->async.done) { if (conn->async.done) {
/* we're done */ /* we're done */
destroy_thread_data(conn); destroy_thread_data(&conn->async);
if (!conn->async.dns) { if (!conn->async.dns) {
TRACE(("Curl_is_resolved(): CURLE_COULDNT_RESOLVE_HOST\n")); TRACE(("Curl_is_resolved(): CURLE_COULDNT_RESOLVE_HOST\n"));
return CURLE_COULDNT_RESOLVE_HOST; return CURLE_COULDNT_RESOLVE_HOST;

View File

@@ -74,8 +74,8 @@ void Curl_scan_cache_used(void *user, void *ptr);
/* free name info */ /* free name info */
void Curl_freeaddrinfo(Curl_addrinfo *freeaddr); void Curl_freeaddrinfo(Curl_addrinfo *freeaddr);
/* free cached name info */ /* make a new dns cache and return the handle */
void Curl_freednsinfo(void *freethis); curl_hash *Curl_mk_dnscache(void);
/* prune old entries from the DNS cache */ /* prune old entries from the DNS cache */
void Curl_hostcache_prune(struct SessionHandle *data); void Curl_hostcache_prune(struct SessionHandle *data);

View File

@@ -105,8 +105,10 @@
static CURLcode Curl_output_basic_proxy(struct connectdata *conn); static CURLcode Curl_output_basic_proxy(struct connectdata *conn);
/* /*
* This function checks the linked list of custom HTTP headers for a particular * checkheaders() checks the linked list of custom HTTP headers for a
* header (prefix). * particular header (prefix).
*
* Returns a pointer to the first matching header or NULL if none matched.
*/ */
static char *checkheaders(struct SessionHandle *data, const char *thisheader) static char *checkheaders(struct SessionHandle *data, const char *thisheader)
{ {
@@ -120,6 +122,12 @@ static char *checkheaders(struct SessionHandle *data, const char *thisheader)
return NULL; return NULL;
} }
/*
* Curl_output_basic() sets up an Authorization: header for HTTP Basic
* authentication. It uses the conn->user, conn->passwd fields for it.
*
* Returns CURLcode.
*/
static CURLcode Curl_output_basic(struct connectdata *conn) static CURLcode Curl_output_basic(struct connectdata *conn)
{ {
char *authorization; char *authorization;
@@ -139,6 +147,13 @@ static CURLcode Curl_output_basic(struct connectdata *conn)
return CURLE_OK; return CURLE_OK;
} }
/*
* Curl_output_basic_proxy() sets up a proxy-Authorization: header for HTTP
* Basic proxy authentication. It uses the conn->proxyuser and
* conn->proxypasswd fields for it.
*
* Returns CURLcode.
*/
static CURLcode Curl_output_basic_proxy(struct connectdata *conn) static CURLcode Curl_output_basic_proxy(struct connectdata *conn)
{ {
char *authorization; char *authorization;
@@ -186,33 +201,49 @@ void Curl_http_auth_act(struct connectdata *conn)
conn->newurl = strdup(data->change.url); /* clone URL */ conn->newurl = strdup(data->change.url); /* clone URL */
data->state.authavail = CURLAUTH_NONE; /* clear it here */ data->state.authavail = CURLAUTH_NONE; /* clear it here */
} }
else if(!data->state.authdone && (data->info.httpcode < 400)) {
/* no (known) authentication available,
authentication is not "done" yet and
no authentication seems to be required and
we didn't try HEAD or GET */
if((data->set.httpreq != HTTPREQ_GET) &&
(data->set.httpreq != HTTPREQ_HEAD)) {
conn->newurl = strdup(data->change.url); /* clone URL */
data->state.authdone = TRUE;
}
}
} }
/* /**
* Setup the authentication headers for the host/proxy and the correct * http_auth_headers() setups the authentication headers for the host/proxy
* authentication method. * and the correct authentication method. conn->data->state.authdone is set to
* TRUE when authentication is done.
*
* @param conn all information about the current connection
*
* Returns CURLcode
*/ */
static CURLcode http_auth_headers(struct connectdata *conn, static CURLcode http_auth_headers(struct connectdata *conn,
char *request, char *request,
char *path, char *path)
bool *ready) /* set TRUE when the auth phase
is done and ready to do the *actual*
request */
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data; struct SessionHandle *data = conn->data;
char *auth=NULL; char *auth=NULL;
*ready = FALSE; /* default is no */ curlassert(data);
if(!data->state.authstage) { if(!data->state.authstage) {
if(conn->bits.httpproxy && conn->bits.proxy_user_passwd) if(conn->bits.httpproxy && conn->bits.proxy_user_passwd) {
data->state.authdone = FALSE;
Curl_http_auth_stage(data, 407); Curl_http_auth_stage(data, 407);
else if(conn->bits.user_passwd) }
else if(conn->bits.user_passwd) {
data->state.authdone = FALSE;
Curl_http_auth_stage(data, 401); Curl_http_auth_stage(data, 401);
}
else { else {
*ready = TRUE; data->state.authdone = TRUE;
return CURLE_OK; /* no authentication with no user or password */ return CURLE_OK; /* no authentication with no user or password */
} }
} }
@@ -229,7 +260,7 @@ static CURLcode http_auth_headers(struct connectdata *conn,
#ifdef USE_SSLEAY #ifdef USE_SSLEAY
if(data->state.authwant == CURLAUTH_NTLM) { if(data->state.authwant == CURLAUTH_NTLM) {
auth=(char *)"NTLM"; auth=(char *)"NTLM";
result = Curl_output_ntlm(conn, TRUE, ready); result = Curl_output_ntlm(conn, TRUE);
if(result) if(result)
return result; return result;
} }
@@ -244,7 +275,7 @@ static CURLcode http_auth_headers(struct connectdata *conn,
if(result) if(result)
return result; return result;
} }
*ready = TRUE; data->state.authdone = TRUE;
/* Switch to web authentication after proxy authentication is done */ /* Switch to web authentication after proxy authentication is done */
Curl_http_auth_stage(data, 401); Curl_http_auth_stage(data, 401);
} }
@@ -262,14 +293,14 @@ static CURLcode http_auth_headers(struct connectdata *conn,
result = Curl_output_negotiate(conn); result = Curl_output_negotiate(conn);
if (result) if (result)
return result; return result;
*ready = TRUE; data->state.authdone = TRUE;
} }
else else
#endif #endif
#ifdef USE_SSLEAY #ifdef USE_SSLEAY
if(data->state.authwant == CURLAUTH_NTLM) { if(data->state.authwant == CURLAUTH_NTLM) {
auth=(char *)"NTLM"; auth=(char *)"NTLM";
result = Curl_output_ntlm(conn, FALSE, ready); result = Curl_output_ntlm(conn, FALSE);
if(result) if(result)
return result; return result;
} }
@@ -284,7 +315,7 @@ static CURLcode http_auth_headers(struct connectdata *conn,
(unsigned char *)path); (unsigned char *)path);
if(result) if(result)
return result; return result;
*ready = TRUE; data->state.authdone = TRUE;
} }
else if(data->state.authwant == CURLAUTH_BASIC) {/* Basic */ else if(data->state.authwant == CURLAUTH_BASIC) {/* Basic */
if(conn->bits.user_passwd && if(conn->bits.user_passwd &&
@@ -295,7 +326,7 @@ static CURLcode http_auth_headers(struct connectdata *conn,
return result; return result;
} }
/* basic is always ready */ /* basic is always ready */
*ready = TRUE; data->state.authdone = TRUE;
} }
} }
if(auth) if(auth)
@@ -304,7 +335,7 @@ static CURLcode http_auth_headers(struct connectdata *conn,
} }
} }
else else
*ready = TRUE; data->state.authdone = TRUE;
return result; return result;
} }
@@ -365,8 +396,14 @@ CURLcode Curl_http_auth(struct connectdata *conn,
if(data->state.authwant == CURLAUTH_GSSNEGOTIATE) { if(data->state.authwant == CURLAUTH_GSSNEGOTIATE) {
/* if exactly this is wanted, go */ /* if exactly this is wanted, go */
int neg = Curl_input_negotiate(conn, start); int neg = Curl_input_negotiate(conn, start);
if (neg == 0) if (neg == 0) {
conn->newurl = strdup(data->change.url); conn->newurl = strdup(data->change.url);
data->state.authproblem = (conn->newurl == NULL);
}
else {
infof(data, "Authentication problem. Ignoring this.\n");
data->state.authproblem = TRUE;
}
} }
else else
if(data->state.authwant & CURLAUTH_GSSNEGOTIATE) if(data->state.authwant & CURLAUTH_GSSNEGOTIATE)
@@ -383,10 +420,14 @@ CURLcode Curl_http_auth(struct connectdata *conn,
CURLntlm ntlm = CURLntlm ntlm =
Curl_input_ntlm(conn, (bool)(httpcode == 407), start); Curl_input_ntlm(conn, (bool)(httpcode == 407), start);
if(CURLNTLM_BAD != ntlm) if(CURLNTLM_BAD != ntlm) {
conn->newurl = strdup(data->change.url); /* clone string */ conn->newurl = strdup(data->change.url); /* clone string */
else data->state.authproblem = (conn->newurl == NULL);
}
else {
infof(data, "Authentication problem. Ignoring this.\n"); infof(data, "Authentication problem. Ignoring this.\n");
data->state.authproblem = TRUE;
}
} }
else else
if(data->state.authwant & CURLAUTH_NTLM) if(data->state.authwant & CURLAUTH_NTLM)
@@ -398,17 +439,18 @@ CURLcode Curl_http_auth(struct connectdata *conn,
*availp |= CURLAUTH_DIGEST; *availp |= CURLAUTH_DIGEST;
if(data->state.authwant == CURLAUTH_DIGEST) { if(data->state.authwant == CURLAUTH_DIGEST) {
/* Digest authentication is activated */ /* Digest authentication is activated */
CURLdigest dig = CURLDIGEST_BAD; CURLdigest dig = Curl_input_digest(conn, start);
if(data->state.digest.nonce) if(CURLDIGEST_FINE == dig) {
infof(data, "Authentication problem. Ignoring this.\n");
else
dig = Curl_input_digest(conn, start);
if(CURLDIGEST_FINE == dig)
/* We act on it. Store our new url, which happens to be /* We act on it. Store our new url, which happens to be
the same one we already use! */ the same one we already use! */
conn->newurl = strdup(data->change.url); /* clone string */ conn->newurl = strdup(data->change.url); /* clone string */
data->state.authproblem = (conn->newurl == NULL);
}
else {
infof(data, "Authentication problem. Ignoring this.\n");
data->state.authproblem = TRUE;
}
} }
else else
if(data->state.authwant & CURLAUTH_DIGEST) { if(data->state.authwant & CURLAUTH_DIGEST) {
@@ -430,16 +472,114 @@ CURLcode Curl_http_auth(struct connectdata *conn,
valid. */ valid. */
data->state.authavail = CURLAUTH_NONE; data->state.authavail = CURLAUTH_NONE;
infof(data, "Authentication problem. Ignoring this.\n"); infof(data, "Authentication problem. Ignoring this.\n");
data->state.authproblem = TRUE;
} }
else if(data->state.authwant & CURLAUTH_BASIC) { else if(data->state.authwant & CURLAUTH_BASIC) {
data->state.authavail |= CURLAUTH_BASIC; data->state.authavail |= CURLAUTH_BASIC;
} else {
/*
** We asked for something besides basic but got
** Basic anyway. This is no good.
*/
infof(data, "Server expects Basic auth, but we're doing something else.\n");
data->state.authproblem = TRUE;
} }
} }
return CURLE_OK; return CURLE_OK;
} }
/**
* Curl_http_should_fail() determines whether an HTTP response has gotten us
* into an error state or not.
*
* @param conn all information about the current connection
*
* @retval 0 communications should continue
*
* @retval 1 communications should not continue
*/
int Curl_http_should_fail(struct connectdata *conn)
{
struct SessionHandle *data;
struct Curl_transfer_keeper *k;
/* fread() emulation to provide POST and/or request data */ curlassert(conn);
data = conn->data;
curlassert(data);
/*
** For readability
*/
k = &conn->keep;
/*
** If we haven't been asked to fail on error,
** don't fail.
*/
if (!data->set.http_fail_on_error)
return 0;
/*
** Any code < 400 is never terminal.
*/
if (k->httpcode < 400)
return 0;
/*
** Any code >= 400 that's not 401 or 407 is always
** a terminal error
*/
if ((k->httpcode != 401) &&
(k->httpcode != 407))
return 1;
/*
** All we have left to deal with is 401 and 407
*/
curlassert((k->httpcode == 401) || (k->httpcode == 407));
/*
** Examine the current authentication state to see if this
** is an error. The idea is for this function to get
** called after processing all the headers in a response
** message. So, if we've been to asked to authenticate a
** particular stage, and we've done it, we're OK. But, if
** we're already completely authenticated, it's not OK to
** get another 401 or 407.
**
** It is possible for authentication to go stale such that
** the client needs to reauthenticate. Once that info is
** available, use it here.
*/
#if 0 /* set to 1 when debugging this functionality */
infof(data,"%s: authstage = %d\n",__FUNCTION__,data->state.authstage);
infof(data,"%s: authwant = 0x%08x\n",__FUNCTION__,data->state.authwant);
infof(data,"%s: authavail = 0x%08x\n",__FUNCTION__,data->state.authavail);
infof(data,"%s: httpcode = %d\n",__FUNCTION__,k->httpcode);
infof(data,"%s: authdone = %d\n",__FUNCTION__,data->state.authdone);
infof(data,"%s: newurl = %s\n",__FUNCTION__,conn->newurl ? conn->newurl : "(null)");
infof(data,"%s: authproblem = %d\n",__FUNCTION__,data->state.authproblem);
#endif
if (data->state.authstage &&
(data->state.authstage == k->httpcode))
return (data->state.authdone || data->state.authproblem);
/*
** Either we're not authenticating, or we're supposed to
** be authenticating something else. This is an error.
*/
return 1;
}
/*
* readmoredata() is a "fread() emulation" to provide POST and/or request
* data. It is used when a huge POST is to be made and the entire chunk wasn't
* sent in the first send(). This function will then be called from the
* transfer.c loop when more data is to be sent to the peer.
*
* Returns the amount of bytes it filled the buffer with.
*/
static size_t readmoredata(char *buffer, static size_t readmoredata(char *buffer,
size_t size, size_t size,
size_t nitems, size_t nitems,
@@ -502,7 +642,7 @@ static CURLcode
add_buffer(send_buffer *in, const void *inptr, size_t size); add_buffer(send_buffer *in, const void *inptr, size_t size);
/* /*
* add_buffer_init() returns a fine buffer struct * add_buffer_init() sets up and returns a fine buffer struct
*/ */
static static
send_buffer *add_buffer_init(void) send_buffer *add_buffer_init(void)
@@ -518,6 +658,8 @@ send_buffer *add_buffer_init(void)
/* /*
* add_buffer_send() sends a buffer and frees all associated memory. * add_buffer_send() sends a buffer and frees all associated memory.
*
* Returns CURLcode
*/ */
static static
CURLcode add_buffer_send(send_buffer *in, CURLcode add_buffer_send(send_buffer *in,
@@ -608,7 +750,7 @@ CURLcode add_buffer_send(send_buffer *in,
/* /*
* add_bufferf() builds a buffer from the formatted input * add_bufferf() add the formatted input to the buffer.
*/ */
static static
CURLcode add_bufferf(send_buffer *in, const char *fmt, ...) CURLcode add_bufferf(send_buffer *in, const char *fmt, ...)
@@ -633,7 +775,7 @@ CURLcode add_bufferf(send_buffer *in, const char *fmt, ...)
} }
/* /*
* add_buffer() appends a memory chunk to the existing one * add_buffer() appends a memory chunk to the existing buffer
*/ */
static static
CURLcode add_buffer(send_buffer *in, const void *inptr, size_t size) CURLcode add_buffer(send_buffer *in, const void *inptr, size_t size)
@@ -760,9 +902,6 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn,
infof(data, "Establish HTTP proxy tunnel to %s:%d\n", hostname, remote_port); infof(data, "Establish HTTP proxy tunnel to %s:%d\n", hostname, remote_port);
do { do {
bool auth; /* we don't really have to know when the auth phase is done,
but this variable will be set to true then */
if(conn->newurl) { if(conn->newurl) {
/* This only happens if we've looped here due to authentication reasons, /* This only happens if we've looped here due to authentication reasons,
and we don't really use the newly cloned URL here then. Just free() and we don't really use the newly cloned URL here then. Just free()
@@ -776,7 +915,7 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn,
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
/* Setup the proxy-authorization header, if any */ /* Setup the proxy-authorization header, if any */
result = http_auth_headers(conn, (char *)"CONNECT", host_port, &auth); result = http_auth_headers(conn, (char *)"CONNECT", host_port);
if(CURLE_OK == result) { if(CURLE_OK == result) {
/* OK, now send the connect request to the proxy */ /* OK, now send the connect request to the proxy */
@@ -877,7 +1016,7 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn,
/* send the header to the callback */ /* send the header to the callback */
writetype = CLIENTWRITE_HEADER; writetype = CLIENTWRITE_HEADER;
if(data->set.http_include_header) if(data->set.include_header)
writetype |= CLIENTWRITE_BODY; writetype |= CLIENTWRITE_BODY;
result = Curl_client_write(data, writetype, line_start, perline); result = Curl_client_write(data, writetype, line_start, perline);
@@ -951,7 +1090,8 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn,
} }
/* /*
* HTTP stuff to do at connect-time. * Curl_http_connect() performs HTTP stuff to do at connect-time, called from
* the generic Curl_connect().
*/ */
CURLcode Curl_http_connect(struct connectdata *conn) CURLcode Curl_http_connect(struct connectdata *conn)
{ {
@@ -997,6 +1137,11 @@ CURLcode Curl_http_connect(struct connectdata *conn)
return CURLE_OK; return CURLE_OK;
} }
/*
* Curl_http_done() gets called from Curl_done() after a single HTTP request
* has been performed.
*/
CURLcode Curl_http_done(struct connectdata *conn) CURLcode Curl_http_done(struct connectdata *conn)
{ {
struct SessionHandle *data; struct SessionHandle *data;
@@ -1029,10 +1174,12 @@ CURLcode Curl_http_done(struct connectdata *conn)
conn->bytecount = http->readbytecount + http->writebytecount; conn->bytecount = http->readbytecount + http->writebytecount;
if(!conn->bits.retry && if(!conn->bits.retry &&
!(http->readbytecount + conn->headerbytecount)) { ((http->readbytecount +
conn->headerbytecount -
conn->deductheadercount)) <= 0) {
/* If this connection isn't simply closed to be retried, AND nothing was /* If this connection isn't simply closed to be retried, AND nothing was
read from the HTTP server, this can't be right so we return an error read from the HTTP server (that counts), this can't be right so we
here */ return an error here */
failf(data, "Empty reply from server"); failf(data, "Empty reply from server");
return CURLE_GOT_NOTHING; return CURLE_GOT_NOTHING;
} }
@@ -1040,6 +1187,10 @@ CURLcode Curl_http_done(struct connectdata *conn)
return CURLE_OK; return CURLE_OK;
} }
/*
* Curl_http_auth_stage() sets the "authentication stage" - which is 407 for
* proxy authentication or 401 for host authentication.
*/
void Curl_http_auth_stage(struct SessionHandle *data, void Curl_http_auth_stage(struct SessionHandle *data,
int stage) int stage)
{ {
@@ -1054,6 +1205,11 @@ void Curl_http_auth_stage(struct SessionHandle *data,
data->state.authavail = CURLAUTH_NONE; /* no type available yet */ data->state.authavail = CURLAUTH_NONE; /* no type available yet */
} }
/*
* Curl_http() gets called from the generic Curl_do() function when a HTTP
* request is to be performed. This creates and sends a propperly constructed
* HTTP request.
*/
CURLcode Curl_http(struct connectdata *conn) CURLcode Curl_http(struct connectdata *conn)
{ {
struct SessionHandle *data=conn->data; struct SessionHandle *data=conn->data;
@@ -1061,12 +1217,12 @@ CURLcode Curl_http(struct connectdata *conn)
CURLcode result=CURLE_OK; CURLcode result=CURLE_OK;
struct HTTP *http; struct HTTP *http;
struct Cookie *co=NULL; /* no cookies from start */ struct Cookie *co=NULL; /* no cookies from start */
char *ppath = conn->ppath; /* three previous function arguments */ char *ppath = conn->path;
char *host = conn->name; char *host = conn->hostname;
const char *te = ""; /* tranfer-encoding */ const char *te = ""; /* tranfer-encoding */
char *ptr; char *ptr;
char *request; char *request;
bool authdone=TRUE; /* if the authentication phase is done */ Curl_HttpReq httpreq = data->set.httpreq;
if(!conn->proto.http) { if(!conn->proto.http) {
/* Only allocate this struct if we don't already have it! */ /* Only allocate this struct if we don't already have it! */
@@ -1085,19 +1241,40 @@ CURLcode Curl_http(struct connectdata *conn)
if ( (conn->protocol&(PROT_HTTP|PROT_FTP)) && if ( (conn->protocol&(PROT_HTTP|PROT_FTP)) &&
data->set.upload) { data->set.upload) {
data->set.httpreq = HTTPREQ_PUT; httpreq = HTTPREQ_PUT;
} }
request = data->set.customrequest? /* Now set the 'request' pointer to the proper request string */
data->set.customrequest: if(data->set.customrequest)
(data->set.no_body?(char *)"HEAD": request = data->set.customrequest;
((HTTPREQ_POST == data->set.httpreq) || else {
(HTTPREQ_POST_FORM == data->set.httpreq))?(char *)"POST": if(conn->bits.no_body)
(HTTPREQ_PUT == data->set.httpreq)?(char *)"PUT":(char *)"GET"); request = (char *)"HEAD";
else {
curlassert((httpreq > HTTPREQ_NONE) && (httpreq < HTTPREQ_LAST));
switch(httpreq) {
case HTTPREQ_POST:
case HTTPREQ_POST_FORM:
request = (char *)"POST";
break;
case HTTPREQ_PUT:
request = (char *)"PUT";
break;
case HTTPREQ_GET:
request = (char *)"GET";
break;
case HTTPREQ_HEAD:
request = (char *)"HEAD";
break;
default: /* this should never happen */
break;
}
}
}
/* The User-Agent string has been built in url.c already, because it might /* The User-Agent string might have been allocated in url.c already, because
have been used in the proxy connect, but if we have got a header with it might have been used in the proxy connect, but if we have got a header
the user-agent string specified, we erase the previously made string with the user-agent string specified, we erase the previously made string
here. */ here. */
if(checkheaders(data, "User-Agent:") && conn->allocptr.uagent) { if(checkheaders(data, "User-Agent:") && conn->allocptr.uagent) {
free(conn->allocptr.uagent); free(conn->allocptr.uagent);
@@ -1105,10 +1282,20 @@ CURLcode Curl_http(struct connectdata *conn)
} }
/* setup the authentication headers */ /* setup the authentication headers */
result = http_auth_headers(conn, request, ppath, &authdone); result = http_auth_headers(conn, request, ppath);
if(result) if(result)
return result; return result;
if(!data->state.authdone && (httpreq != HTTPREQ_GET)) {
/* Until we are authenticated, we switch over to HEAD. Unless its a GET
we want to do. The explanation for this is rather long and boring, but
the point is that it can't be done otherwise without risking having to
send the POST or PUT data multiple times. */
httpreq = HTTPREQ_HEAD;
request = (char *)"HEAD";
conn->bits.no_body = TRUE;
}
Curl_safefree(conn->allocptr.ref); Curl_safefree(conn->allocptr.ref);
if(data->change.referer && !checkheaders(data, "Referer:")) if(data->change.referer && !checkheaders(data, "Referer:"))
conn->allocptr.ref = aprintf("Referer: %s\015\012", data->change.referer); conn->allocptr.ref = aprintf("Referer: %s\015\012", data->change.referer);
@@ -1121,7 +1308,7 @@ CURLcode Curl_http(struct connectdata *conn)
else else
conn->allocptr.cookie = NULL; conn->allocptr.cookie = NULL;
if(!conn->bits.upload_chunky && (data->set.httpreq != HTTPREQ_GET)) { if(!conn->bits.upload_chunky && (httpreq != HTTPREQ_GET)) {
/* not a chunky transfer yet, but data is to be sent */ /* not a chunky transfer yet, but data is to be sent */
ptr = checkheaders(data, "Transfer-Encoding:"); ptr = checkheaders(data, "Transfer-Encoding:");
if(ptr) { if(ptr) {
@@ -1212,7 +1399,7 @@ CURLcode Curl_http(struct connectdata *conn)
/* The path sent to the proxy is in fact the entire URL */ /* The path sent to the proxy is in fact the entire URL */
ppath = data->change.url; ppath = data->change.url;
} }
if(HTTPREQ_POST_FORM == data->set.httpreq) { if(HTTPREQ_POST_FORM == httpreq) {
/* we must build the whole darned post sequence first, so that we have /* we must build the whole darned post sequence first, so that we have
a size of the whole shebang before we start to send it */ a size of the whole shebang before we start to send it */
result = Curl_getFormData(&http->sendit, data->set.httppost, result = Curl_getFormData(&http->sendit, data->set.httppost,
@@ -1231,9 +1418,9 @@ CURLcode Curl_http(struct connectdata *conn)
if(!checkheaders(data, "Accept:")) if(!checkheaders(data, "Accept:"))
http->p_accept = "Accept: */*\r\n"; http->p_accept = "Accept: */*\r\n";
if(( (HTTPREQ_POST == data->set.httpreq) || if(( (HTTPREQ_POST == httpreq) ||
(HTTPREQ_POST_FORM == data->set.httpreq) || (HTTPREQ_POST_FORM == httpreq) ||
(HTTPREQ_PUT == data->set.httpreq) ) && (HTTPREQ_PUT == httpreq) ) &&
conn->resume_from) { conn->resume_from) {
/********************************************************************** /**********************************************************************
* Resuming upload in HTTP means that we PUT or POST and that we have * Resuming upload in HTTP means that we PUT or POST and that we have
@@ -1296,14 +1483,14 @@ CURLcode Curl_http(struct connectdata *conn)
* or uploading and we always let customized headers override our internal * or uploading and we always let customized headers override our internal
* ones if any such are specified. * ones if any such are specified.
*/ */
if((data->set.httpreq == HTTPREQ_GET) && if((httpreq == HTTPREQ_GET) &&
!checkheaders(data, "Range:")) { !checkheaders(data, "Range:")) {
/* if a line like this was already allocated, free the previous one */ /* if a line like this was already allocated, free the previous one */
if(conn->allocptr.rangeline) if(conn->allocptr.rangeline)
free(conn->allocptr.rangeline); free(conn->allocptr.rangeline);
conn->allocptr.rangeline = aprintf("Range: bytes=%s\r\n", conn->range); conn->allocptr.rangeline = aprintf("Range: bytes=%s\r\n", conn->range);
} }
else if((data->set.httpreq != HTTPREQ_GET) && else if((httpreq != HTTPREQ_GET) &&
!checkheaders(data, "Content-Range:")) { !checkheaders(data, "Content-Range:")) {
if(conn->resume_from) { if(conn->resume_from) {
@@ -1466,11 +1653,11 @@ CURLcode Curl_http(struct connectdata *conn)
http->postdata = NULL; /* nothing to post at this point */ http->postdata = NULL; /* nothing to post at this point */
Curl_pgrsSetUploadSize(data, 0); /* upload size is 0 atm */ Curl_pgrsSetUploadSize(data, 0); /* upload size is 0 atm */
/* If 'authdone' is still FALSE, we must not set the write socket index to /* If 'authdone' is FALSE, we must not set the write socket index to the
the Curl_transfer() call below, as we're not ready to actually upload Curl_transfer() call below, as we're not ready to actually upload any
any data yet. */ data yet. */
switch(data->set.httpreq) { switch(httpreq) {
case HTTPREQ_POST_FORM: case HTTPREQ_POST_FORM:
if(Curl_FormInit(&http->form, http->sendit)) { if(Curl_FormInit(&http->form, http->sendit)) {
@@ -1499,7 +1686,7 @@ CURLcode Curl_http(struct connectdata *conn)
} }
if(!checkheaders(data, "Content-Type:")) { if(!checkheaders(data, "Content-Type:")) {
/* Get Content-Type: line from Curl_FormReadOneLine, which happens /* Get Content-Type: line from Curl_formpostheader, which happens
to always be the first line. We can know this for sure since to always be the first line. We can know this for sure since
we always build the formpost linked list the same way! we always build the formpost linked list the same way!
@@ -1507,13 +1694,11 @@ CURLcode Curl_http(struct connectdata *conn)
string etc why disabling this header is likely to not make things string etc why disabling this header is likely to not make things
work, but we support it anyway. work, but we support it anyway.
*/ */
char contentType[256]; char *contentType;
size_t linelength=0; size_t linelength=0;
linelength = Curl_FormReadOneLine(contentType, contentType = Curl_formpostheader((void *)&http->form,
sizeof(contentType), &linelength);
1, if(!contentType) {
(FILE *)&http->form);
if(!linelength) {
failf(data, "Could not get Content-Type header line!"); failf(data, "Could not get Content-Type header line!");
return CURLE_HTTP_POST_ERROR; return CURLE_HTTP_POST_ERROR;
} }
@@ -1535,8 +1720,8 @@ CURLcode Curl_http(struct connectdata *conn)
/* setup variables for the upcoming transfer */ /* setup variables for the upcoming transfer */
result = Curl_Transfer(conn, FIRSTSOCKET, -1, TRUE, result = Curl_Transfer(conn, FIRSTSOCKET, -1, TRUE,
&http->readbytecount, &http->readbytecount,
authdone?FIRSTSOCKET:-1, data->state.authdone?FIRSTSOCKET:-1,
authdone?&http->writebytecount:NULL); data->state.authdone?&http->writebytecount:NULL);
if(result) { if(result) {
Curl_formclean(http->sendit); /* free that whole lot */ Curl_formclean(http->sendit); /* free that whole lot */
return result; return result;
@@ -1574,8 +1759,8 @@ CURLcode Curl_http(struct connectdata *conn)
/* prepare for transfer */ /* prepare for transfer */
result = Curl_Transfer(conn, FIRSTSOCKET, -1, TRUE, result = Curl_Transfer(conn, FIRSTSOCKET, -1, TRUE,
&http->readbytecount, &http->readbytecount,
authdone?FIRSTSOCKET:-1, data->state.authdone?FIRSTSOCKET:-1,
authdone?&http->writebytecount:NULL); data->state.authdone?&http->writebytecount:NULL);
if(result) if(result)
return result; return result;
break; break;
@@ -1606,7 +1791,7 @@ CURLcode Curl_http(struct connectdata *conn)
if(data->set.postfields) { if(data->set.postfields) {
if(authdone && (postsize < (100*1024))) { if(data->state.authdone && (postsize < (100*1024))) {
/* If we're not done with the authentication phase, we don't expect /* If we're not done with the authentication phase, we don't expect
to actually send off any data yet. Hence, we delay the sending of to actually send off any data yet. Hence, we delay the sending of
the body until we receive that friendly 100-continue response */ the body until we receive that friendly 100-continue response */
@@ -1642,7 +1827,7 @@ CURLcode Curl_http(struct connectdata *conn)
/* set the upload size to the progress meter */ /* set the upload size to the progress meter */
Curl_pgrsSetUploadSize(data, http->postsize); Curl_pgrsSetUploadSize(data, http->postsize);
if(!authdone && !checkheaders(data, "Expect:")) { if(!data->state.authdone && !checkheaders(data, "Expect:")) {
/* if not disabled explicitly we add a Expect: 100-continue to the /* if not disabled explicitly we add a Expect: 100-continue to the
headers which actually speeds up post operations (as there is headers which actually speeds up post operations (as there is
one packet coming back from the web server) */ one packet coming back from the web server) */

View File

@@ -42,9 +42,13 @@ CURLcode Curl_http_connect(struct connectdata *conn);
void Curl_httpchunk_init(struct connectdata *conn); void Curl_httpchunk_init(struct connectdata *conn);
CHUNKcode Curl_httpchunk_read(struct connectdata *conn, char *datap, CHUNKcode Curl_httpchunk_read(struct connectdata *conn, char *datap,
ssize_t length, ssize_t *wrote); ssize_t length, ssize_t *wrote);
/* These functions are in http.c */
void Curl_http_auth_stage(struct SessionHandle *data, int stage); void Curl_http_auth_stage(struct SessionHandle *data, int stage);
CURLcode Curl_http_auth(struct connectdata *conn, CURLcode Curl_http_auth(struct connectdata *conn,
int httpcode, char *header); int httpcode, char *header);
void Curl_http_auth_act(struct connectdata *conn); void Curl_http_auth_act(struct connectdata *conn);
int Curl_http_should_fail(struct connectdata *conn);
#endif #endif
#endif #endif

View File

@@ -36,6 +36,7 @@
#include "md5.h" #include "md5.h"
#include "http_digest.h" #include "http_digest.h"
#include "url.h" /* for Curl_safefree() */
#define _MPRINTF_REPLACE /* use our functions only */ #define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h> #include <curl/mprintf.h>
@@ -57,6 +58,8 @@ CURLdigest Curl_input_digest(struct connectdata *conn,
{ {
bool more = TRUE; bool more = TRUE;
struct SessionHandle *data=conn->data; struct SessionHandle *data=conn->data;
bool before = FALSE; /* got a nonce before */
struct digestdata *d = &data->state.digest;
/* skip initial whitespaces */ /* skip initial whitespaces */
while(*header && isspace((int)*header)) while(*header && isspace((int)*header))
@@ -65,6 +68,10 @@ CURLdigest Curl_input_digest(struct connectdata *conn,
if(checkprefix("Digest", header)) { if(checkprefix("Digest", header)) {
header += strlen("Digest"); header += strlen("Digest");
/* If we already have received a nonce, keep that in mind */
if(d->nonce)
before = TRUE;
/* clear off any former leftovers and init to defaults */ /* clear off any former leftovers and init to defaults */
Curl_digest_cleanup(data); Curl_digest_cleanup(data);
@@ -77,21 +84,32 @@ CURLdigest Curl_input_digest(struct connectdata *conn,
header++; header++;
/* how big can these strings be? */ /* how big can these strings be? */
if(2 == sscanf(header, "%31[^=]=\"%127[^\"]\"", if((2 == sscanf(header, "%31[^=]=\"%127[^\"]\"",
value, content)) { value, content)) ||
/* try the same scan but without quotes around the content but don't
include the possibly trailing comma */
(2 == sscanf(header, "%31[^=]=%127[^,]",
value, content)) ) {
if(strequal(value, "nonce")) { if(strequal(value, "nonce")) {
data->state.digest.nonce = strdup(content); d->nonce = strdup(content);
}
else if(strequal(value, "stale")) {
if(strequal(content, "true"))
d->stale = TRUE;
} }
else if(strequal(value, "cnonce")) { else if(strequal(value, "cnonce")) {
data->state.digest.cnonce = strdup(content); d->cnonce = strdup(content);
} }
else if(strequal(value, "realm")) { else if(strequal(value, "realm")) {
data->state.digest.realm = strdup(content); d->realm = strdup(content);
} }
else if(strequal(value, "algorithm")) { else if(strequal(value, "algorithm")) {
if(strequal(content, "MD5-sess")) if(strequal(content, "MD5-sess"))
data->state.digest.algo = CURLDIGESTALGO_MD5SESS; d->algo = CURLDIGESTALGO_MD5SESS;
/* else, remain using the default md5 */ else if(strequal(content, "MD5"))
d->algo = CURLDIGESTALGO_MD5;
else
return CURLDIGEST_BADALGO;
} }
else { else {
/* unknown specifier, ignore it! */ /* unknown specifier, ignore it! */
@@ -106,8 +124,15 @@ CURLdigest Curl_input_digest(struct connectdata *conn,
/* allow the list to be comma-separated */ /* allow the list to be comma-separated */
header++; header++;
} }
/* We had a nonce since before, and we got another one now without
'stale=true'. This means we provided bad credentials in the previous
request */
if(!data->state.digest.nonce) if(before && !d->stale)
return CURLDIGEST_BAD;
/* We got this header without a nonce, that's a bad Digest line! */
if(!d->nonce)
return CURLDIGEST_BAD; return CURLDIGEST_BAD;
} }
else else
@@ -140,6 +165,7 @@ CURLcode Curl_output_digest(struct connectdata *conn,
unsigned char *md5this; unsigned char *md5this;
struct SessionHandle *data = conn->data; struct SessionHandle *data = conn->data;
struct digestdata *d = &data->state.digest;
/* /*
if the algorithm is "MD5" or unspecified (which then defaults to MD5): if the algorithm is "MD5" or unspecified (which then defaults to MD5):
@@ -151,20 +177,20 @@ CURLcode Curl_output_digest(struct connectdata *conn,
A1 = H( unq(username-value) ":" unq(realm-value) ":" passwd ) A1 = H( unq(username-value) ":" unq(realm-value) ":" passwd )
":" unq(nonce-value) ":" unq(cnonce-value) ":" unq(nonce-value) ":" unq(cnonce-value)
*/ */
if(data->state.digest.algo == CURLDIGESTALGO_MD5SESS) { if(d->algo == CURLDIGESTALGO_MD5SESS) {
md5this = (unsigned char *) md5this = (unsigned char *)
aprintf("%s:%s:%s:%s:%s", aprintf("%s:%s:%s:%s:%s",
conn->user, conn->user,
data->state.digest.realm, d->realm,
conn->passwd, conn->passwd,
data->state.digest.nonce, d->nonce,
data->state.digest.cnonce); d->cnonce);
} }
else { else {
md5this = (unsigned char *) md5this = (unsigned char *)
aprintf("%s:%s:%s", aprintf("%s:%s:%s",
conn->user, conn->user,
data->state.digest.realm, d->realm,
conn->passwd); conn->passwd);
} }
Curl_md5it(md5buf, md5this); Curl_md5it(md5buf, md5this);
@@ -183,7 +209,7 @@ CURLcode Curl_output_digest(struct connectdata *conn,
free(md5this); /* free this again */ free(md5this); /* free this again */
md5_to_ascii(md5buf, ha2); md5_to_ascii(md5buf, ha2);
md5this = (unsigned char *)aprintf("%s:%s:%s", ha1, data->state.digest.nonce, md5this = (unsigned char *)aprintf("%s:%s:%s", ha1, d->nonce,
ha2); ha2);
Curl_md5it(md5buf, md5this); Curl_md5it(md5buf, md5this);
free(md5this); /* free this again */ free(md5this); /* free this again */
@@ -195,6 +221,7 @@ CURLcode Curl_output_digest(struct connectdata *conn,
nonce="1053604145", uri="/64", response="c55f7f30d83d774a3d2dcacf725abaca" nonce="1053604145", uri="/64", response="c55f7f30d83d774a3d2dcacf725abaca"
*/ */
Curl_safefree(conn->allocptr.userpwd);
conn->allocptr.userpwd = conn->allocptr.userpwd =
aprintf( "Authorization: Digest " aprintf( "Authorization: Digest "
"username=\"%s\", " "username=\"%s\", "
@@ -203,8 +230,8 @@ CURLcode Curl_output_digest(struct connectdata *conn,
"uri=\"%s\", " "uri=\"%s\", "
"response=\"%s\"\r\n", "response=\"%s\"\r\n",
conn->user, conn->user,
data->state.digest.realm, d->realm,
data->state.digest.nonce, d->nonce,
uripath, /* this is the PATH part of the URL */ uripath, /* this is the PATH part of the URL */
request_digest ); request_digest );
@@ -213,19 +240,23 @@ CURLcode Curl_output_digest(struct connectdata *conn,
void Curl_digest_cleanup(struct SessionHandle *data) void Curl_digest_cleanup(struct SessionHandle *data)
{ {
if(data->state.digest.nonce) struct digestdata *d = &data->state.digest;
free(data->state.digest.nonce);
data->state.digest.nonce = NULL;
if(data->state.digest.cnonce) if(d->nonce)
free(data->state.digest.cnonce); free(d->nonce);
data->state.digest.cnonce = NULL; d->nonce = NULL;
if(data->state.digest.realm) if(d->cnonce)
free(data->state.digest.realm); free(d->cnonce);
data->state.digest.realm = NULL; d->cnonce = NULL;
data->state.digest.algo = CURLDIGESTALGO_MD5; /* default algorithm */ if(d->realm)
free(d->realm);
d->realm = NULL;
d->algo = CURLDIGESTALGO_MD5; /* default algorithm */
d->stale = FALSE; /* default means normal, not stale */
} }
#endif #endif

View File

@@ -26,6 +26,7 @@
typedef enum { typedef enum {
CURLDIGEST_NONE, /* not a digest */ CURLDIGEST_NONE, /* not a digest */
CURLDIGEST_BAD, /* a digest, but one we don't like */ CURLDIGEST_BAD, /* a digest, but one we don't like */
CURLDIGEST_BADALGO, /* unsupported algorithm requested */
CURLDIGEST_FINE, /* a digest we act on */ CURLDIGEST_FINE, /* a digest we act on */
CURLDIGEST_LAST /* last entry in this enum, don't use */ CURLDIGEST_LAST /* last entry in this enum, don't use */

View File

@@ -77,7 +77,7 @@
#endif #endif
/* Define this to make the type-3 message include the NT response message */ /* Define this to make the type-3 message include the NT response message */
#undef USE_NTRESPONSES #define USE_NTRESPONSES 1
/* /*
(*) = A "security buffer" is a triplet consisting of two shorts and one (*) = A "security buffer" is a triplet consisting of two shorts and one
@@ -277,8 +277,7 @@ static void mkhash(char *password,
/* this is for creating ntlm header output */ /* this is for creating ntlm header output */
CURLcode Curl_output_ntlm(struct connectdata *conn, CURLcode Curl_output_ntlm(struct connectdata *conn,
bool proxy, bool proxy)
bool *ready)
{ {
const char *domain=""; /* empty */ const char *domain=""; /* empty */
const char *host=""; /* empty */ const char *host=""; /* empty */
@@ -300,7 +299,9 @@ CURLcode Curl_output_ntlm(struct connectdata *conn,
/* point to the correct struct with this */ /* point to the correct struct with this */
struct ntlmdata *ntlm; struct ntlmdata *ntlm;
*ready = FALSE; curlassert(conn);
curlassert(conn->data);
conn->data->state.authdone = FALSE;
if(proxy) { if(proxy) {
allocuserpwd = &conn->allocptr.proxyuserpwd; allocuserpwd = &conn->allocptr.proxyuserpwd;
@@ -562,7 +563,7 @@ CURLcode Curl_output_ntlm(struct connectdata *conn,
return CURLE_OUT_OF_MEMORY; /* FIX TODO */ return CURLE_OUT_OF_MEMORY; /* FIX TODO */
ntlm->state = NTLMSTATE_TYPE3; /* we sent a type-3 */ ntlm->state = NTLMSTATE_TYPE3; /* we sent a type-3 */
*ready = TRUE; conn->data->state.authdone = TRUE;
/* Switch to web authentication after proxy authentication is done */ /* Switch to web authentication after proxy authentication is done */
if (proxy) if (proxy)
@@ -577,7 +578,7 @@ CURLcode Curl_output_ntlm(struct connectdata *conn,
free(*allocuserpwd); free(*allocuserpwd);
*allocuserpwd=NULL; *allocuserpwd=NULL;
} }
*ready = TRUE; conn->data->state.authdone = TRUE;
break; break;
} }

View File

@@ -36,7 +36,7 @@ typedef enum {
CURLntlm Curl_input_ntlm(struct connectdata *conn, bool proxy, char *header); CURLntlm Curl_input_ntlm(struct connectdata *conn, bool proxy, char *header);
/* this is for creating ntlm header output */ /* this is for creating ntlm header output */
CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy, bool *ready); CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy);
void Curl_ntlm_cleanup(struct SessionHandle *data); void Curl_ntlm_cleanup(struct SessionHandle *data);

View File

@@ -1,5 +1,5 @@
#include <winver.h> #include <winver.h>
#include "../include/curl/curl.h" #include "../include/curl/curlver.h"
LANGUAGE 0x09,0x01 LANGUAGE 0x09,0x01

View File

@@ -14,13 +14,14 @@ endif
SOURCES = base64.c connect.c content_.c cookie.c dict.c \ SOURCES = base64.c connect.c content_.c cookie.c dict.c \
easy.c escape.c file.c formdata.c ftp.c \ easy.c escape.c file.c formdata.c ftp.c \
getdate.c getenv.c getinfo.c hash.c hostip.c \ getdate.c getenv.c getinfo.c hash.c hostip.c \
http.c http_chu.c http_dig.c http_neg.c http_ntl.c \
if2ip.c krb4.c md5.c ldap.c llist.c \ if2ip.c krb4.c md5.c ldap.c llist.c \
memdebug.c mprintf.c multi.c netrc.c progress.c \ memdebug.c mprintf.c multi.c netrc.c progress.c \
security.c sendf.c share.c speedche.c ssluse.c \ security.c sendf.c share.c speedche.c ssluse.c \
strequal.c strtok.c telnet.c timeval.c transfer.c \ strequal.c strtok.c telnet.c timeval.c transfer.c \
url.c version.c strerror.c strtoofft.c url.c version.c http.c \
http_chunks.c http_digest.c http_negotiate.c http_ntlm.c
SOURCES := $(strip $(SOURCES))
OBJECTS = $(SOURCES:.c=.o) OBJECTS = $(SOURCES:.c=.o)
CURL_LIB = libcurl.a CURL_LIB = libcurl.a
@@ -46,130 +47,155 @@ realclean vclean: clean
base64.o: base64.c setup.h config.h config.dj ../include/curl/mprintf.h \ base64.o: base64.c setup.h config.h config.dj ../include/curl/mprintf.h \
base64.h base64.h
connect.o: connect.c setup.h config.h config.dj urldata.h cookie.h \ connect.o: connect.c setup.h config.h config.dj urldata.h cookie.h \
../include/curl/curl.h ../include/curl/types.h ../include/curl/easy.h \ ../include/curl/curl.h ../include/curl/curlver.h \
../include/curl/multi.h formdata.h timeval.h http_chunks.h hostip.h \ ../include/curl/types.h ../include/curl/easy.h ../include/curl/multi.h \
hash.h llist.h sendf.h if2ip.h formdata.h timeval.h http_chunks.h hostip.h hash.h llist.h sendf.h \
if2ip.h strerror.h connect.h
content_.o: content_.c setup.h config.h config.dj content_.o: content_.c setup.h config.h config.dj
cookie.o: cookie.c setup.h config.h config.dj urldata.h cookie.h \ cookie.o: cookie.c setup.h config.h config.dj urldata.h cookie.h \
../include/curl/curl.h ../include/curl/types.h ../include/curl/easy.h \ ../include/curl/curl.h ../include/curl/curlver.h \
../include/curl/multi.h formdata.h timeval.h http_chunks.h hostip.h \ ../include/curl/types.h ../include/curl/easy.h ../include/curl/multi.h \
hash.h llist.h getdate.h strequal.h strtok.h sendf.h formdata.h timeval.h http_chunks.h hostip.h hash.h llist.h getdate.h \
strequal.h strtok.h sendf.h
dict.o: dict.c setup.h config.h config.dj urldata.h cookie.h \ dict.o: dict.c setup.h config.h config.dj urldata.h cookie.h \
../include/curl/curl.h ../include/curl/types.h ../include/curl/easy.h \ ../include/curl/curl.h ../include/curl/curlver.h \
../include/curl/multi.h formdata.h timeval.h http_chunks.h hostip.h \ ../include/curl/types.h ../include/curl/easy.h ../include/curl/multi.h \
hash.h llist.h transfer.h sendf.h progress.h strequal.h \ formdata.h timeval.h http_chunks.h hostip.h hash.h llist.h transfer.h \
../include/curl/mprintf.h sendf.h progress.h strequal.h dict.h ../include/curl/mprintf.h
easy.o: easy.c setup.h config.h config.dj strequal.h urldata.h cookie.h \ easy.o: easy.c setup.h config.h config.dj strequal.h urldata.h cookie.h \
../include/curl/curl.h ../include/curl/types.h ../include/curl/easy.h \ ../include/curl/curl.h ../include/curl/curlver.h \
../include/curl/multi.h formdata.h timeval.h http_chunks.h hostip.h \ ../include/curl/types.h ../include/curl/easy.h ../include/curl/multi.h \
hash.h llist.h transfer.h ssluse.h url.h getinfo.h share.h \ formdata.h timeval.h http_chunks.h hostip.h hash.h llist.h transfer.h \
../include/curl/mprintf.h ssluse.h url.h getinfo.h share.h ../include/curl/mprintf.h
escape.o: escape.c setup.h config.h config.dj ../include/curl/curl.h \ escape.o: escape.c setup.h config.h config.dj ../include/curl/curl.h \
../include/curl/types.h ../include/curl/easy.h ../include/curl/multi.h ../include/curl/curlver.h ../include/curl/types.h \
../include/curl/easy.h ../include/curl/multi.h
file.o: file.c setup.h config.h config.dj urldata.h cookie.h \ file.o: file.c setup.h config.h config.dj urldata.h cookie.h \
../include/curl/curl.h ../include/curl/types.h ../include/curl/easy.h \ ../include/curl/curl.h ../include/curl/curlver.h \
../include/curl/multi.h formdata.h timeval.h http_chunks.h hostip.h \ ../include/curl/types.h ../include/curl/easy.h ../include/curl/multi.h \
hash.h llist.h progress.h sendf.h escape.h ../include/curl/mprintf.h formdata.h timeval.h http_chunks.h hostip.h hash.h llist.h progress.h \
sendf.h escape.h file.h speedcheck.h getinfo.h transfer.h \
../include/curl/mprintf.h
formdata.o: formdata.c setup.h config.h config.dj ../include/curl/curl.h \ formdata.o: formdata.c setup.h config.h config.dj ../include/curl/curl.h \
../include/curl/types.h ../include/curl/easy.h ../include/curl/multi.h \ ../include/curl/curlver.h ../include/curl/types.h \
formdata.h strequal.h ../include/curl/easy.h ../include/curl/multi.h formdata.h strequal.h
ftp.o: ftp.c setup.h config.h config.dj ../include/curl/curl.h \ ftp.o: ftp.c setup.h config.h config.dj ../include/curl/curl.h \
../include/curl/types.h ../include/curl/easy.h ../include/curl/multi.h \ ../include/curl/curlver.h ../include/curl/types.h \
urldata.h cookie.h formdata.h timeval.h http_chunks.h hostip.h hash.h \ ../include/curl/easy.h ../include/curl/multi.h urldata.h cookie.h \
llist.h sendf.h if2ip.h progress.h transfer.h escape.h http.h ftp.h \ formdata.h timeval.h http_chunks.h hostip.h hash.h llist.h sendf.h \
strequal.h ssluse.h connect.h ../include/curl/mprintf.h if2ip.h progress.h transfer.h escape.h http.h ftp.h strtoofft.h \
strequal.h ssluse.h connect.h strerror.h ../include/curl/mprintf.h
getdate.o: getdate.c setup.h config.h config.dj getdate.h getdate.o: getdate.c setup.h config.h config.dj getdate.h
getenv.o: getenv.c setup.h config.h config.dj getenv.o: getenv.c setup.h config.h config.dj ../include/curl/curl.h \
../include/curl/curlver.h ../include/curl/types.h \
../include/curl/easy.h ../include/curl/multi.h
getinfo.o: getinfo.c setup.h config.h config.dj ../include/curl/curl.h \ getinfo.o: getinfo.c setup.h config.h config.dj ../include/curl/curl.h \
../include/curl/types.h ../include/curl/easy.h ../include/curl/multi.h \ ../include/curl/curlver.h ../include/curl/types.h \
urldata.h cookie.h formdata.h timeval.h http_chunks.h hostip.h hash.h \ ../include/curl/easy.h ../include/curl/multi.h urldata.h cookie.h \
llist.h formdata.h timeval.h http_chunks.h hostip.h hash.h llist.h getinfo.h
hash.o: hash.c setup.h config.h config.dj hash.h llist.h hash.o: hash.c setup.h config.h config.dj hash.h llist.h
hostip.o: hostip.c setup.h config.h config.dj urldata.h cookie.h \ hostip.o: hostip.c setup.h config.h config.dj urldata.h cookie.h \
../include/curl/curl.h ../include/curl/types.h ../include/curl/easy.h \ ../include/curl/curl.h ../include/curl/curlver.h \
../include/curl/multi.h formdata.h timeval.h http_chunks.h hostip.h \ ../include/curl/types.h ../include/curl/easy.h ../include/curl/multi.h \
hash.h llist.h sendf.h share.h url.h ../include/curl/mprintf.h formdata.h timeval.h http_chunks.h hostip.h hash.h llist.h sendf.h \
http.o: http.c setup.h config.h config.dj urldata.h cookie.h \ share.h url.h ../include/curl/mprintf.h
../include/curl/curl.h ../include/curl/types.h ../include/curl/easy.h \ if2ip.o: if2ip.c setup.h config.h config.dj if2ip.h
../include/curl/multi.h formdata.h timeval.h http_chunks.h hostip.h \
hash.h llist.h transfer.h sendf.h progress.h base64.h strequal.h \
ssluse.h http_digest.h http_ntlm.h http_negotiate.h url.h share.h \
http.h ../include/curl/mprintf.h
http_chu.o: http_chu.c setup.h config.h config.dj urldata.h cookie.h \
../include/curl/curl.h ../include/curl/types.h ../include/curl/easy.h \
../include/curl/multi.h formdata.h timeval.h http_chunks.h hostip.h \
hash.h llist.h sendf.h content_encoding.h ../include/curl/mprintf.h
http_dig.o: http_dig.c setup.h config.h config.dj urldata.h cookie.h \
../include/curl/curl.h ../include/curl/types.h ../include/curl/easy.h \
../include/curl/multi.h formdata.h timeval.h http_chunks.h hostip.h \
hash.h llist.h sendf.h strequal.h md5.h http_digest.h \
../include/curl/mprintf.h
http_neg.o: http_neg.c setup.h config.h config.dj
http_ntl.o: http_ntl.c setup.h config.h config.dj
if2ip.o: if2ip.c setup.h config.h config.dj
krb4.o: krb4.c setup.h config.h config.dj krb4.o: krb4.c setup.h config.h config.dj
md5.o: md5.c setup.h config.h config.dj md5.o: md5.c setup.h config.h config.dj md5.h
ldap.o: ldap.c setup.h config.h config.dj urldata.h cookie.h \ ldap.o: ldap.c setup.h config.h config.dj urldata.h cookie.h \
../include/curl/curl.h ../include/curl/types.h ../include/curl/easy.h \ ../include/curl/curl.h ../include/curl/curlver.h \
../include/curl/multi.h formdata.h timeval.h http_chunks.h hostip.h \ ../include/curl/types.h ../include/curl/easy.h ../include/curl/multi.h \
hash.h llist.h sendf.h escape.h transfer.h ../include/curl/mprintf.h formdata.h timeval.h http_chunks.h hostip.h hash.h llist.h sendf.h \
escape.h transfer.h ldap.h ../include/curl/mprintf.h
llist.o: llist.c setup.h config.h config.dj llist.h llist.o: llist.c setup.h config.h config.dj llist.h
memdebug.o: memdebug.c setup.h config.h config.dj ../include/curl/curl.h \ memdebug.o: memdebug.c
../include/curl/types.h ../include/curl/easy.h ../include/curl/multi.h \ mprintf.o: mprintf.c setup.h config.h config.dj ../include/curl/mprintf.h
../include/curl/mprintf.h urldata.h cookie.h formdata.h timeval.h \
http_chunks.h hostip.h hash.h llist.h
mprintf.o: mprintf.c setup.h config.h config.dj
multi.o: multi.c setup.h config.h config.dj ../include/curl/curl.h \ multi.o: multi.c setup.h config.h config.dj ../include/curl/curl.h \
../include/curl/types.h ../include/curl/easy.h ../include/curl/multi.h \ ../include/curl/curlver.h ../include/curl/types.h \
urldata.h cookie.h formdata.h timeval.h http_chunks.h hostip.h hash.h \ ../include/curl/easy.h ../include/curl/multi.h urldata.h cookie.h \
llist.h transfer.h url.h connect.h progress.h formdata.h timeval.h http_chunks.h hostip.h hash.h llist.h transfer.h \
url.h connect.h progress.h
netrc.o: netrc.c setup.h config.h config.dj ../include/curl/curl.h \ netrc.o: netrc.c setup.h config.h config.dj ../include/curl/curl.h \
../include/curl/types.h ../include/curl/easy.h ../include/curl/multi.h \ ../include/curl/curlver.h ../include/curl/types.h \
strequal.h strtok.h ../include/curl/mprintf.h ../include/curl/easy.h ../include/curl/multi.h netrc.h strequal.h \
strtok.h ../include/curl/mprintf.h
progress.o: progress.c setup.h config.h config.dj ../include/curl/curl.h \ progress.o: progress.c setup.h config.h config.dj ../include/curl/curl.h \
../include/curl/types.h ../include/curl/easy.h ../include/curl/multi.h \ ../include/curl/curlver.h ../include/curl/types.h \
urldata.h cookie.h formdata.h timeval.h http_chunks.h hostip.h hash.h \ ../include/curl/easy.h ../include/curl/multi.h urldata.h cookie.h \
llist.h sendf.h progress.h ../include/curl/mprintf.h formdata.h timeval.h http_chunks.h hostip.h hash.h llist.h sendf.h \
progress.h ../include/curl/mprintf.h
security.o: security.c setup.h config.h config.dj security.o: security.c setup.h config.h config.dj
sendf.o: sendf.c setup.h config.h config.dj ../include/curl/curl.h \ sendf.o: sendf.c setup.h config.h config.dj ../include/curl/curl.h \
../include/curl/types.h ../include/curl/easy.h ../include/curl/multi.h \ ../include/curl/curlver.h ../include/curl/types.h \
urldata.h cookie.h formdata.h timeval.h http_chunks.h hostip.h hash.h \ ../include/curl/easy.h ../include/curl/multi.h urldata.h cookie.h \
llist.h sendf.h connect.h ../include/curl/mprintf.h formdata.h timeval.h http_chunks.h hostip.h hash.h llist.h sendf.h \
connect.h ../include/curl/mprintf.h
share.o: share.c setup.h config.h config.dj ../include/curl/curl.h \ share.o: share.c setup.h config.h config.dj ../include/curl/curl.h \
../include/curl/types.h ../include/curl/easy.h ../include/curl/multi.h \ ../include/curl/curlver.h ../include/curl/types.h \
urldata.h cookie.h formdata.h timeval.h http_chunks.h hostip.h hash.h \ ../include/curl/easy.h ../include/curl/multi.h urldata.h cookie.h \
llist.h share.h formdata.h timeval.h http_chunks.h hostip.h hash.h llist.h share.h
speedche.o: speedche.c setup.h config.h config.dj ../include/curl/curl.h \ speedche.o: speedche.c setup.h config.h config.dj ../include/curl/curl.h \
../include/curl/types.h ../include/curl/easy.h ../include/curl/multi.h \ ../include/curl/curlver.h ../include/curl/types.h \
urldata.h cookie.h formdata.h timeval.h http_chunks.h hostip.h hash.h \ ../include/curl/easy.h ../include/curl/multi.h urldata.h cookie.h \
llist.h sendf.h speedcheck.h formdata.h timeval.h http_chunks.h hostip.h hash.h llist.h sendf.h \
speedcheck.h
ssluse.o: ssluse.c setup.h config.h config.dj urldata.h cookie.h \ ssluse.o: ssluse.c setup.h config.h config.dj urldata.h cookie.h \
../include/curl/curl.h ../include/curl/types.h ../include/curl/easy.h \ ../include/curl/curl.h ../include/curl/curlver.h \
../include/curl/multi.h formdata.h timeval.h http_chunks.h hostip.h \
hash.h llist.h sendf.h url.h inet_pton.h
strequal.o: strequal.c setup.h config.h config.dj
strtok.o: strtok.c setup.h config.h config.dj
telnet.o: telnet.c setup.h config.h config.dj urldata.h cookie.h \
../include/curl/curl.h ../include/curl/types.h ../include/curl/easy.h \
../include/curl/multi.h formdata.h timeval.h http_chunks.h hostip.h \
hash.h llist.h transfer.h sendf.h ../include/curl/mprintf.h \
arpa_telnet.h
timeval.o: timeval.c timeval.h setup.h config.h config.dj
transfer.o: transfer.c setup.h config.h config.dj strequal.h urldata.h \
cookie.h ../include/curl/curl.h ../include/curl/types.h \
../include/curl/easy.h ../include/curl/multi.h formdata.h timeval.h \
http_chunks.h hostip.h hash.h llist.h netrc.h content_encoding.h \
transfer.h sendf.h speedcheck.h progress.h getdate.h http.h url.h \
getinfo.h ssluse.h http_digest.h http_ntlm.h http_negotiate.h share.h \
../include/curl/mprintf.h
url.o: url.c setup.h config.h config.dj urldata.h cookie.h \
../include/curl/curl.h ../include/curl/types.h ../include/curl/easy.h \
../include/curl/multi.h formdata.h timeval.h http_chunks.h hostip.h \
hash.h llist.h netrc.h base64.h ssluse.h if2ip.h transfer.h sendf.h \
progress.h strequal.h escape.h strtok.h share.h content_encoding.h \
http_digest.h http_negotiate.h ftp.h dict.h telnet.h http.h file.h \
ldap.h url.h connect.h ca-bundle.h ../include/curl/mprintf.h
version.o: version.c setup.h config.h config.dj ../include/curl/curl.h \
../include/curl/types.h ../include/curl/easy.h ../include/curl/multi.h \ ../include/curl/types.h ../include/curl/easy.h ../include/curl/multi.h \
urldata.h cookie.h formdata.h timeval.h http_chunks.h hostip.h hash.h \ formdata.h timeval.h http_chunks.h hostip.h hash.h llist.h sendf.h \
llist.h url.h inet_pton.h ssluse.h connect.h
strequal.o: strequal.c setup.h config.h config.dj strequal.h
strtok.o: strtok.c setup.h config.h config.dj strtok.h
telnet.o: telnet.c setup.h config.h config.dj urldata.h cookie.h \
../include/curl/curl.h ../include/curl/curlver.h \
../include/curl/types.h ../include/curl/easy.h ../include/curl/multi.h \
formdata.h timeval.h http_chunks.h hostip.h hash.h llist.h transfer.h \
sendf.h telnet.h ../include/curl/mprintf.h arpa_telnet.h
timeval.o: timeval.c timeval.h setup.h config.h config.dj
transfer.o: transfer.c setup.h config.h config.dj strtoofft.h \
../include/curl/curl.h ../include/curl/curlver.h \
../include/curl/types.h ../include/curl/easy.h ../include/curl/multi.h \
strequal.h urldata.h cookie.h formdata.h timeval.h http_chunks.h \
hostip.h hash.h llist.h netrc.h content_encoding.h transfer.h sendf.h \
speedcheck.h progress.h getdate.h http.h url.h getinfo.h ssluse.h \
http_digest.h http_ntlm.h http_negotiate.h share.h \
../include/curl/mprintf.h
strerror.o: strerror.c setup.h config.h config.dj ../include/curl/curl.h \
../include/curl/curlver.h ../include/curl/types.h \
../include/curl/easy.h ../include/curl/multi.h strerror.h urldata.h \
cookie.h formdata.h timeval.h http_chunks.h hostip.h hash.h llist.h \
../include/curl/mprintf.h
strtoofft.o: strtoofft.c setup.h config.h config.dj strtoofft.h \
../include/curl/curl.h ../include/curl/curlver.h \
../include/curl/types.h ../include/curl/easy.h ../include/curl/multi.h
url.o: url.c setup.h config.h config.dj urldata.h cookie.h \
../include/curl/curl.h ../include/curl/curlver.h \
../include/curl/types.h ../include/curl/easy.h ../include/curl/multi.h \
formdata.h timeval.h http_chunks.h hostip.h hash.h llist.h netrc.h \
base64.h ssluse.h if2ip.h transfer.h sendf.h progress.h strequal.h \
escape.h strtok.h share.h content_encoding.h http_digest.h \
http_negotiate.h ftp.h dict.h telnet.h http.h file.h ldap.h url.h \
connect.h ca-bundle.h ../include/curl/mprintf.h
version.o: version.c setup.h config.h config.dj ../include/curl/curl.h \
../include/curl/curlver.h ../include/curl/types.h \
../include/curl/easy.h ../include/curl/multi.h urldata.h cookie.h \
formdata.h timeval.h http_chunks.h hostip.h hash.h llist.h
http.o: http.c setup.h config.h config.dj urldata.h cookie.h \
../include/curl/curl.h ../include/curl/curlver.h \
../include/curl/types.h ../include/curl/easy.h ../include/curl/multi.h \
formdata.h timeval.h http_chunks.h hostip.h hash.h llist.h transfer.h \
sendf.h progress.h base64.h strequal.h ssluse.h http_digest.h \
http_ntlm.h http_negotiate.h url.h share.h http.h \
../include/curl/mprintf.h
http_chunks.o: http_chunks.c setup.h config.h config.dj urldata.h \
cookie.h ../include/curl/curl.h ../include/curl/curlver.h \
../include/curl/types.h ../include/curl/easy.h ../include/curl/multi.h \
formdata.h timeval.h http_chunks.h hostip.h hash.h llist.h sendf.h \
content_encoding.h http.h ../include/curl/mprintf.h
http_digest.o: http_digest.c setup.h config.h config.dj urldata.h \
cookie.h ../include/curl/curl.h ../include/curl/curlver.h \
../include/curl/types.h ../include/curl/easy.h ../include/curl/multi.h \
formdata.h timeval.h http_chunks.h hostip.h hash.h llist.h sendf.h \
strequal.h md5.h http_digest.h ../include/curl/mprintf.h
http_negotiate.o: http_negotiate.c setup.h config.h config.dj
http_ntlm.o: http_ntlm.c setup.h config.h config.dj

View File

@@ -122,8 +122,8 @@ enum {
typedef struct { typedef struct {
FormatType type; FormatType type;
int flags; int flags;
int width; /* width OR width parameter number */ long width; /* width OR width parameter number */
int precision; /* precision OR precision parameter number */ long precision; /* precision OR precision parameter number */
union { union {
char *str; char *str;
void *ptr; void *ptr;
@@ -281,7 +281,8 @@ int dprintf_Pass1Report(va_stack_t *vto, int max)
* *
******************************************************************/ ******************************************************************/
static int dprintf_Pass1(char *format, va_stack_t *vto, char **endpos, va_list arglist) static long dprintf_Pass1(char *format, va_stack_t *vto, char **endpos,
va_list arglist)
{ {
char *fmt = format; char *fmt = format;
int param_num = 0; int param_num = 0;
@@ -681,7 +682,7 @@ static int dprintf_formatf(
else else
prec = -1; prec = -1;
alt = p->flags & FLAGS_ALT; alt = (p->flags & FLAGS_ALT)?TRUE:FALSE;
switch (p->type) { switch (p->type) {
case FORMAT_INT: case FORMAT_INT:
@@ -1042,7 +1043,7 @@ static int alloc_addbyter(int output, FILE *data)
infop->alloc *= 2; infop->alloc *= 2;
} }
infop->buffer[ infop->len ] = output; infop->buffer[ infop->len ] = (char)output;
infop->len++; infop->len++;

View File

@@ -122,7 +122,7 @@ CURLM *curl_multi_init(void)
multi->type = CURL_MULTI_HANDLE; multi->type = CURL_MULTI_HANDLE;
} }
multi->hostcache = Curl_hash_alloc(7, Curl_freednsinfo); multi->hostcache = Curl_mk_dnscache();
if(!multi->hostcache) { if(!multi->hostcache) {
/* failure, free mem and bail out */ /* failure, free mem and bail out */
free(multi); free(multi);
@@ -380,7 +380,7 @@ CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
case CURLM_STATE_WAITRESOLVE: case CURLM_STATE_WAITRESOLVE:
/* awaiting an asynch name resolve to complete */ /* awaiting an asynch name resolve to complete */
{ {
struct Curl_dns_entry *dns; struct Curl_dns_entry *dns = NULL;
/* check if we have the name resolved by now */ /* check if we have the name resolved by now */
easy->result = Curl_is_resolved(easy->easy_conn, &dns); easy->result = Curl_is_resolved(easy->easy_conn, &dns);

View File

@@ -91,7 +91,7 @@ int Curl_parsenetrc(char *host,
char state_login=0; /* Found a login keyword */ char state_login=0; /* Found a login keyword */
char state_password=0; /* Found a password keyword */ char state_password=0; /* Found a password keyword */
char state_our_login=0; /* With specific_login, found *our* login name */ int state_our_login=FALSE; /* With specific_login, found *our* login name */
#define NETRC DOT_CHAR "netrc" #define NETRC DOT_CHAR "netrc"
@@ -210,7 +210,7 @@ int Curl_parsenetrc(char *host,
else if(strequal("machine", tok)) { else if(strequal("machine", tok)) {
/* ok, there's machine here go => */ /* ok, there's machine here go => */
state = HOSTFOUND; state = HOSTFOUND;
state_our_login = 0; state_our_login = FALSE;
} }
break; break;
} /* switch (state) */ } /* switch (state) */

View File

@@ -26,9 +26,6 @@
#include <string.h> #include <string.h>
#include <time.h> #include <time.h>
/* 20000318 mgs
* later we use _scrsize to determine the screen width, this emx library
* function needs stdlib.h to be included */
#if defined(__EMX__) #if defined(__EMX__)
#include <stdlib.h> #include <stdlib.h>
#endif #endif
@@ -36,19 +33,34 @@
#include <curl/curl.h> #include <curl/curl.h>
#include "urldata.h" #include "urldata.h"
#include "sendf.h" #include "sendf.h"
#include "progress.h" #include "progress.h"
#define _MPRINTF_REPLACE /* use our functions only */ #define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h> #include <curl/mprintf.h>
/* Provide a string that is 2 + 1 + 2 + 1 + 2 = 8 letters long (plus the zero
static void time2str(char *r, int t) byte) */
static void time2str(char *r, long t)
{ {
int h = (t/3600); long h;
int m = (t-(h*3600))/60; if(!t) {
int s = (t-(h*3600)-(m*60)); strcpy(r, "--:--:--");
sprintf(r,"%2d:%02d:%02d",h,m,s); return;
}
h = (t/3600);
if(h <= 99) {
long m = (t-(h*3600))/60;
long s = (t-(h*3600)-(m*60));
sprintf(r, "%2ld:%02ld:%02ld",h,m,s);
}
else {
/* this equals to more than 99 hours, switch to a more suitable output
format to fit within the limits. */
if(h/24 <= 999)
sprintf(r, "%3ldd %02ldh", h/24, h-(h/24)*24);
else
sprintf(r, "%7ldd", h/24);
}
} }
/* The point of this function would be to return a string of the input data, /* The point of this function would be to return a string of the input data,
@@ -105,14 +117,13 @@ static char *max5data(curl_off_t bytes, char *max5)
void Curl_pgrsDone(struct connectdata *conn) void Curl_pgrsDone(struct connectdata *conn)
{ {
struct SessionHandle *data = conn->data; struct SessionHandle *data = conn->data;
if(!(data->progress.flags & PGRS_HIDE)) {
data->progress.lastshow=0; data->progress.lastshow=0;
Curl_pgrsUpdate(conn); /* the final (forced) update */ Curl_pgrsUpdate(conn); /* the final (forced) update */
if(!data->progress.callback) if(!(data->progress.flags & PGRS_HIDE) &&
/* only output if we don't use progress callback */ !data->progress.callback)
/* only output if we don't use a progress callback and we're not hidden */
fprintf(data->set.err, "\n"); fprintf(data->set.err, "\n");
} }
}
/* reset all times except redirect */ /* reset all times except redirect */
void Curl_pgrsResetTimes(struct SessionHandle *data) void Curl_pgrsResetTimes(struct SessionHandle *data)
@@ -137,26 +148,26 @@ void Curl_pgrsTime(struct SessionHandle *data, timerid timer)
case TIMER_NAMELOOKUP: case TIMER_NAMELOOKUP:
data->progress.t_nslookup = data->progress.t_nslookup =
(double)Curl_tvdiff(Curl_tvnow(), data->progress.t_startsingle)/1000.0; Curl_tvdiff_secs(Curl_tvnow(), data->progress.t_startsingle);
break; break;
case TIMER_CONNECT: case TIMER_CONNECT:
data->progress.t_connect = data->progress.t_connect =
(double)Curl_tvdiff(Curl_tvnow(), data->progress.t_startsingle)/1000.0; Curl_tvdiff_secs(Curl_tvnow(), data->progress.t_startsingle);
break; break;
case TIMER_PRETRANSFER: case TIMER_PRETRANSFER:
data->progress.t_pretransfer = data->progress.t_pretransfer =
(double)Curl_tvdiff(Curl_tvnow(), data->progress.t_startsingle)/1000.0; Curl_tvdiff_secs(Curl_tvnow(), data->progress.t_startsingle);
break; break;
case TIMER_STARTTRANSFER: case TIMER_STARTTRANSFER:
data->progress.t_starttransfer = data->progress.t_starttransfer =
(double)Curl_tvdiff(Curl_tvnow(), data->progress.t_startsingle)/1000.0; Curl_tvdiff_secs(Curl_tvnow(), data->progress.t_startsingle);
break; break;
case TIMER_POSTRANSFER: case TIMER_POSTRANSFER:
/* this is the normal end-of-transfer thing */ /* this is the normal end-of-transfer thing */
break; break;
case TIMER_REDIRECT: case TIMER_REDIRECT:
data->progress.t_redirect = data->progress.t_redirect =
(double)Curl_tvdiff(Curl_tvnow(), data->progress.start)/1000.0; Curl_tvdiff_secs(Curl_tvnow(), data->progress.start);
break; break;
} }
} }
@@ -195,44 +206,27 @@ void Curl_pgrsSetUploadSize(struct SessionHandle *data, curl_off_t size)
data->progress.flags &= ~PGRS_UL_SIZE_KNOWN; data->progress.flags &= ~PGRS_UL_SIZE_KNOWN;
} }
/* EXAMPLE OUTPUT to follow:
% Total % Received % Xferd Average Speed Time Curr.
Dload Upload Total Current Left Speed
100 12345 100 12345 100 12345 12345 12345 12:12:12 12:12:12 12:12:12 12345
*/
int Curl_pgrsUpdate(struct connectdata *conn) int Curl_pgrsUpdate(struct connectdata *conn)
{ {
struct timeval now; struct timeval now;
int result; int result;
char max5[6][10]; char max5[6][10];
double dlpercen=0; int dlpercen=0;
double ulpercen=0; int ulpercen=0;
double total_percen=0; int total_percen=0;
curl_off_t total_transfer; curl_off_t total_transfer;
curl_off_t total_expected_transfer; curl_off_t total_expected_transfer;
double timespent; long timespent;
struct SessionHandle *data = conn->data; struct SessionHandle *data = conn->data;
int nowindex = data->progress.speeder_c% CURR_TIME; int nowindex = data->progress.speeder_c% CURR_TIME;
int checkindex; int checkindex;
int countindex; /* amount of seconds stored in the speeder array */ int countindex; /* amount of seconds stored in the speeder array */
char time_left[10]; char time_left[10];
char time_total[10]; char time_total[10];
char time_current[10]; char time_spent[10];
long ulestimate=0;
double ulestimate=0; long dlestimate=0;
double dlestimate=0; long total_estimate;
double total_estimate;
if(data->progress.flags & PGRS_HIDE) if(data->progress.flags & PGRS_HIDE)
; /* We do enter this function even if we don't wanna see anything, since ; /* We do enter this function even if we don't wanna see anything, since
@@ -246,26 +240,25 @@ int Curl_pgrsUpdate(struct connectdata *conn)
"\n", "\n",
conn->resume_from); conn->resume_from);
fprintf(data->set.err, fprintf(data->set.err,
" %% Total %% Received %% Xferd Average Speed Time Curr.\n" " %% Total %% Received %% Xferd Average Speed Time Time Time Current\n"
" Dload Upload Total Current Left Speed\n"); " Dload Upload Total Spent Left Speed\n");
} }
data->progress.flags |= PGRS_HEADERS_OUT; /* headers are shown */ data->progress.flags |= PGRS_HEADERS_OUT; /* headers are shown */
} }
now = Curl_tvnow(); /* what time is it */ now = Curl_tvnow(); /* what time is it */
/* The exact time spent so far (from the start) */ /* The time spent so far (from the start) */
timespent = (double)Curl_tvdiff (now, data->progress.start)/1000; data->progress.timespent = Curl_tvdiff_secs(now, data->progress.start);
timespent = (long)data->progress.timespent;
data->progress.timespent = timespent;
/* The average download speed this far */ /* The average download speed this far */
data->progress.dlspeed = data->progress.dlspeed =
data->progress.downloaded/(timespent>0.01?timespent:1); data->progress.downloaded/(timespent?timespent:1);
/* The average upload speed this far */ /* The average upload speed this far */
data->progress.ulspeed = data->progress.ulspeed =
data->progress.uploaded/(timespent>0.01?timespent:1); data->progress.uploaded/(timespent?timespent:1);
if(data->progress.lastshow == Curl_tvlong(now)) if(data->progress.lastshow == Curl_tvlong(now))
return 0; /* never update this more than once a second if the end isn't return 0; /* never update this more than once a second if the end isn't
@@ -309,7 +302,7 @@ int Curl_pgrsUpdate(struct connectdata *conn)
span_ms=1; /* at least one millisecond MUST have passed */ span_ms=1; /* at least one millisecond MUST have passed */
/* Calculate the average speed the last 'countindex' seconds */ /* Calculate the average speed the last 'countindex' seconds */
data->progress.current_speed = data->progress.current_speed = (curl_off_t)
(data->progress.speeder[nowindex]- (data->progress.speeder[nowindex]-
data->progress.speeder[checkindex])/((double)span_ms/1000); data->progress.speeder[checkindex])/((double)span_ms/1000);
} }
@@ -338,35 +331,25 @@ int Curl_pgrsUpdate(struct connectdata *conn)
/* Figure out the estimated time of arrival for the upload */ /* Figure out the estimated time of arrival for the upload */
if((data->progress.flags & PGRS_UL_SIZE_KNOWN) && if((data->progress.flags & PGRS_UL_SIZE_KNOWN) &&
(data->progress.ulspeed > 0)) { (data->progress.ulspeed > 0)) {
ulestimate = (double)data->progress.size_ul / data->progress.ulspeed; ulestimate = (long)(data->progress.size_ul / data->progress.ulspeed);
ulpercen = ((double)data->progress.uploaded / data->progress.size_ul)*100; ulpercen = (long)(data->progress.uploaded / data->progress.size_ul)*100;
} }
/* ... and the download */ /* ... and the download */
if((data->progress.flags & PGRS_DL_SIZE_KNOWN) && if((data->progress.flags & PGRS_DL_SIZE_KNOWN) &&
(data->progress.dlspeed > 0)) { (data->progress.dlspeed > 0)) {
dlestimate = (double)data->progress.size_dl / data->progress.dlspeed; dlestimate = (long)(data->progress.size_dl / data->progress.dlspeed);
dlpercen = ((double)data->progress.downloaded / data->progress.size_dl)*100; dlpercen = (long)(data->progress.downloaded / data->progress.size_dl)*100;
} }
/* Now figure out which of them that is slower and use for the for /* Now figure out which of them that is slower and use for the for
total estimate! */ total estimate! */
total_estimate = ulestimate>dlestimate?ulestimate:dlestimate; total_estimate = ulestimate>dlestimate?ulestimate:dlestimate;
/* create the three time strings */
/* If we have a total estimate, we can display that and the expected time2str(time_left, total_estimate > 0?(total_estimate - timespent):0);
time left */ time2str(time_total, total_estimate);
if(total_estimate > 0) { time2str(time_spent, timespent);
time2str(time_left, (int)(total_estimate - data->progress.timespent));
time2str(time_total, (int)total_estimate);
}
else {
/* otherwise we blank those times */
strcpy(time_left, "--:--:--");
strcpy(time_total, "--:--:--");
}
/* The time spent so far is always known */
time2str(time_current, (int)data->progress.timespent);
/* Get the total amount of data expected to get transfered */ /* Get the total amount of data expected to get transfered */
total_expected_transfer = total_expected_transfer =
@@ -380,22 +363,21 @@ int Curl_pgrsUpdate(struct connectdata *conn)
/* Get the percentage of data transfered so far */ /* Get the percentage of data transfered so far */
if(total_expected_transfer > 0) if(total_expected_transfer > 0)
total_percen=((double)total_transfer/total_expected_transfer)*100; total_percen=(int)(total_transfer/total_expected_transfer)*100;
fprintf(data->set.err, fprintf(data->set.err,
"\r%3d %s %3d %s %3d %s %s %s %s %s %s %s", "\r%3d %s %3d %s %3d %s %s %s %s %s %s %s",
(int)total_percen, /* total % */ total_percen, /* 3 letters */ /* total % */
max5data(total_expected_transfer, max5[2]), /* total size */ max5data(total_expected_transfer, max5[2]), /* total size */
(int)dlpercen, /* rcvd % */ dlpercen, /* 3 letters */ /* rcvd % */
max5data(data->progress.downloaded, max5[0]), /* rcvd size */ max5data(data->progress.downloaded, max5[0]), /* rcvd size */
(int)ulpercen, /* xfer % */ ulpercen, /* 3 letters */ /* xfer % */
max5data(data->progress.uploaded, max5[1]), /* xfer size */ max5data(data->progress.uploaded, max5[1]), /* xfer size */
max5data(data->progress.dlspeed, max5[3]), /* avrg dl speed */ max5data(data->progress.dlspeed, max5[3]), /* avrg dl speed */
max5data(data->progress.ulspeed, max5[4]), /* avrg ul speed */ max5data(data->progress.ulspeed, max5[4]), /* avrg ul speed */
time_total, /* total time */ time_total, /* 8 letters */ /* total time */
time_current, /* current time */ time_spent, /* 8 letters */ /* time spent */
time_left, /* time left */ time_left, /* 8 letters */ /* time left */
max5data(data->progress.current_speed, max5[5]) /* current speed */ max5data(data->progress.current_speed, max5[5]) /* current speed */
); );

View File

@@ -417,7 +417,6 @@ int Curl_read(struct connectdata *conn, /* connection data */
if(-1 == nread) { if(-1 == nread) {
int err = Curl_ourerrno(); int err = Curl_ourerrno();
conn->sockerror = err;
#ifdef WIN32 #ifdef WIN32
if(WSAEWOULDBLOCK == err) if(WSAEWOULDBLOCK == err)
#else #else
@@ -425,8 +424,6 @@ int Curl_read(struct connectdata *conn, /* connection data */
#endif #endif
return -1; return -1;
} }
else
conn->sockerror = 0; /* no error */
#ifdef USE_SSLEAY #ifdef USE_SSLEAY
} }

View File

@@ -46,10 +46,6 @@
#endif #endif
#endif #endif
#ifdef VMS
/* hand-modified VMS config.h! */
#include "config-vms.h"
#endif
#ifdef NETWARE #ifdef NETWARE
/* hand-modified NetWare config.h! */ /* hand-modified NetWare config.h! */
#include "config-netware.h" #include "config-netware.h"
@@ -134,15 +130,10 @@ defined(HAVE_LIBSSL) && defined(HAVE_LIBCRYPTO)
#endif #endif
#ifndef STDC_HEADERS /* no standard C headers! */ #ifndef STDC_HEADERS /* no standard C headers! */
#ifdef VMS
#include "../include/curl/stdcheaders.h"
#else
#include <curl/stdcheaders.h> #include <curl/stdcheaders.h>
#endif #endif
#endif
#if defined(CURLDEBUG) && defined(HAVE_ASSERT_H) #if defined(CURLDEBUG) && defined(HAVE_ASSERT_H)
#define NDEBUG
#define curlassert(x) assert(x) #define curlassert(x) assert(x)
#else #else
/* does nothing without CURLDEBUG defined */ /* does nothing without CURLDEBUG defined */
@@ -174,6 +165,17 @@ defined(HAVE_LIBSSL) && defined(HAVE_LIBCRYPTO)
#define WIN32_LEAN_AND_MEAN /* Prevent including <winsock*.h> in <windows.h> */ #define WIN32_LEAN_AND_MEAN /* Prevent including <winsock*.h> in <windows.h> */
#endif #endif
#if (defined(ENABLE_IPV6) || defined(CURLDEBUG)) && defined(_MSC_VER) && \
(!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0500)
/*
* Needed to pull in the real getaddrinfo() and not the inline version
* in <wspiAPI.H> which doesn't support IPv6 (IPv4 only). <wspiAPI.H> is
* included from <ws2tcpip.h> for <= 0x0500 SDKs.
*/
#undef _WIN32_WINNT
#define _WIN32_WINNT 0x0501
#endif
#include <winsock2.h> /* required by telnet.c */ #include <winsock2.h> /* required by telnet.c */
#if defined(ENABLE_IPV6) || defined(USE_SSLEAY) #if defined(ENABLE_IPV6) || defined(USE_SSLEAY)
@@ -276,10 +278,6 @@ typedef struct hostent Curl_addrinfo;
typedef struct in_addr Curl_ipconnect; typedef struct in_addr Curl_ipconnect;
#endif #endif
#ifdef VMS
#define IOCTL_3_ARGS
#endif
#ifdef mpeix #ifdef mpeix
#define IOCTL_3_ARGS #define IOCTL_3_ARGS
#endif #endif

View File

@@ -73,7 +73,7 @@ curl_share_setopt(CURLSH *sh, CURLSHoption option, ...)
{ {
case CURL_LOCK_DATA_DNS: case CURL_LOCK_DATA_DNS:
if (!share->hostcache) { if (!share->hostcache) {
share->hostcache = Curl_hash_alloc(7, Curl_freednsinfo); share->hostcache = Curl_mk_dnscache();
} }
break; break;

View File

@@ -94,7 +94,7 @@ static int passwd_callback(char *buf, int num, int verify
else { else {
if(num > (int)strlen((char *)global_passwd)) { if(num > (int)strlen((char *)global_passwd)) {
strcpy(buf, global_passwd); strcpy(buf, global_passwd);
return strlen(buf); return (int)strlen(buf);
} }
} }
return 0; return 0;
@@ -185,7 +185,7 @@ int random_the_seed(struct SessionHandle *data)
if(!area) if(!area)
return 3; /* out of memory */ return 3; /* out of memory */
len = strlen(area); len = (int)strlen(area);
RAND_add(area, len, (len >> 1)); RAND_add(area, len, (len >> 1));
free(area); /* now remove the random junk */ free(area); /* now remove the random junk */
@@ -544,7 +544,7 @@ static int Get_SSL_Session(struct connectdata *conn,
if(!check->sessionid) if(!check->sessionid)
/* not session ID means blank entry */ /* not session ID means blank entry */
continue; continue;
if(curl_strequal(conn->name, check->name) && if(curl_strequal(conn->hostname, check->name) &&
(conn->remote_port == check->remote_port) && (conn->remote_port == check->remote_port) &&
Curl_ssl_config_matches(&conn->ssl_config, &check->ssl_config)) { Curl_ssl_config_matches(&conn->ssl_config, &check->ssl_config)) {
/* yes, we have a session ID! */ /* yes, we have a session ID! */
@@ -662,7 +662,7 @@ static int Store_SSL_Session(struct connectdata *conn,
/* now init the session struct wisely */ /* now init the session struct wisely */
store->sessionid = ssl_sessionid; store->sessionid = ssl_sessionid;
store->age = data->state.sessionage; /* set current age */ store->age = data->state.sessionage; /* set current age */
store->name = strdup(conn->name); /* clone host name */ store->name = strdup(conn->hostname); /* clone host name */
store->remote_port = conn->remote_port; /* port number */ store->remote_port = conn->remote_port; /* port number */
Curl_clone_ssl_config(&conn->ssl_config, &store->ssl_config); Curl_clone_ssl_config(&conn->ssl_config, &store->ssl_config);
@@ -818,10 +818,10 @@ static CURLcode verifyhost(struct connectdata *conn,
int i; int i;
if(GEN_DNS == target) { if(GEN_DNS == target) {
hostlen = strlen(conn->hostname); hostlen = (int)strlen(conn->hostname);
domain = strchr(conn->hostname, '.'); domain = strchr(conn->hostname, '.');
if(domain) if(domain)
domainlen = strlen(domain); domainlen = (int)strlen(domain);
} }
/* get amount of alternatives, RFC2459 claims there MUST be at least /* get amount of alternatives, RFC2459 claims there MUST be at least
@@ -1070,7 +1070,7 @@ Curl_SSLConnect(struct connectdata *conn,
and then how much time that has elapsed to know how much time we and then how much time that has elapsed to know how much time we
allow for the connect call */ allow for the connect call */
if(data->set.timeout || data->set.connecttimeout) { if(data->set.timeout || data->set.connecttimeout) {
double has_passed; long has_passed;
/* Evaluate in milliseconds how much time that has passed */ /* Evaluate in milliseconds how much time that has passed */
has_passed = Curl_tvdiff(Curl_tvnow(), data->progress.start); has_passed = Curl_tvdiff(Curl_tvnow(), data->progress.start);
@@ -1087,7 +1087,7 @@ Curl_SSLConnect(struct connectdata *conn,
timeout_ms = data->set.connecttimeout*1000; timeout_ms = data->set.connecttimeout*1000;
/* subtract the passed time */ /* subtract the passed time */
timeout_ms -= (long)has_passed; timeout_ms -= has_passed;
if(timeout_ms < 0) { if(timeout_ms < 0) {
/* a precaution, no need to continue if time already is up */ /* a precaution, no need to continue if time already is up */
@@ -1117,14 +1117,15 @@ Curl_SSLConnect(struct connectdata *conn,
FD_SET(sockfd, &writefd); FD_SET(sockfd, &writefd);
else { else {
/* untreated error */ /* untreated error */
unsigned long errdetail;
char error_buffer[120]; /* OpenSSL documents that this must be at least char error_buffer[120]; /* OpenSSL documents that this must be at least
120 bytes long. */ 120 bytes long. */
detail = ERR_get_error(); /* Gets the earliest error code from the errdetail = ERR_get_error(); /* Gets the earliest error code from the
thread's error queue and removes the thread's error queue and removes the
entry. */ entry. */
switch(detail) { switch(errdetail) {
case 0x1407E086: case 0x1407E086:
/* 1407E086: /* 1407E086:
SSL routines: SSL routines:
@@ -1140,7 +1141,7 @@ Curl_SSLConnect(struct connectdata *conn,
return CURLE_SSL_CACERT; return CURLE_SSL_CACERT;
default: default:
/* detail is already set to the SSL error above */ /* detail is already set to the SSL error above */
failf(data, "SSL: %s", ERR_error_string(detail, error_buffer)); failf(data, "SSL: %s", ERR_error_string(errdetail, error_buffer));
/* OpenSSL 0.9.6 and later has a function named /* OpenSSL 0.9.6 and later has a function named
ERRO_error_string_n() that takes the size of the buffer as a third ERRO_error_string_n() that takes the size of the buffer as a third
argument, and we should possibly switch to using that one in the argument, and we should possibly switch to using that one in the

View File

@@ -20,7 +20,17 @@
* *
***************************************************************************/ ***************************************************************************/
#include "setup.h"
#include <curl/curl.h> #include <curl/curl.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "strerror.h"
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
const char * const char *
curl_easy_strerror(CURLcode error) curl_easy_strerror(CURLcode error)
@@ -244,8 +254,7 @@ curl_easy_strerror(CURLcode error)
const char * const char *
curl_multi_strerror(CURLMcode error) curl_multi_strerror(CURLMcode error)
{ {
switch (error) switch (error) {
{
case CURLM_CALL_MULTI_PERFORM: case CURLM_CALL_MULTI_PERFORM:
return "please call curl_multi_perform() soon"; return "please call curl_multi_perform() soon";
@@ -274,8 +283,7 @@ curl_multi_strerror(CURLMcode error)
const char * const char *
curl_share_strerror(CURLSHcode error) curl_share_strerror(CURLSHcode error)
{ {
switch (error) switch (error) {
{
case CURLSHE_OK: case CURLSHE_OK:
return "no error"; return "no error";
@@ -294,3 +302,252 @@ curl_share_strerror(CURLSHcode error)
return "CURLSH unknown"; return "CURLSH unknown";
} }
#if defined(WIN32) && !defined(__CYGWIN__)
/* This function handles most / all (?) Winsock errors cURL is able to produce.
*/
static const char *
get_winsock_error (int err, char *buf, size_t len)
{
char *p;
switch (err) {
case WSAEINTR:
p = "Call interrupted.";
break;
case WSAEBADF:
p = "Bad file";
break;
case WSAEACCES:
p = "Bad access";
break;
case WSAEFAULT:
p = "Bad argument";
break;
case WSAEINVAL:
p = "Invalid arguments";
break;
case WSAEMFILE:
p = "Out of file descriptors";
break;
case WSAEWOULDBLOCK:
p = "Call would block";
break;
case WSAEINPROGRESS:
case WSAEALREADY:
p = "Blocking call in progress";
break;
case WSAENOTSOCK:
p = "Descriptor is not a socket.";
break;
case WSAEDESTADDRREQ:
p = "Need destination address";
break;
case WSAEMSGSIZE:
p = "Bad message size";
break;
case WSAEPROTOTYPE:
p = "Bad protocol";
break;
case WSAENOPROTOOPT:
p = "Protocol option is unsupported";
break;
case WSAEPROTONOSUPPORT:
p = "Protocol is unsupported";
break;
case WSAESOCKTNOSUPPORT:
p = "Socket is unsupported";
break;
case WSAEOPNOTSUPP:
p = "Operation not supported";
break;
case WSAEAFNOSUPPORT:
p = "Address family not supported";
break;
case WSAEPFNOSUPPORT:
p = "Protocol family not supported";
break;
case WSAEADDRINUSE:
p = "Address already in use";
break;
case WSAEADDRNOTAVAIL:
p = "Address not available";
break;
case WSAENETDOWN:
p = "Network down";
break;
case WSAENETUNREACH:
p = "Network unreachable";
break;
case WSAENETRESET:
p = "Network has been reset";
break;
case WSAECONNABORTED:
p = "Connection was aborted";
break;
case WSAECONNRESET:
p = "Connection was reset";
break;
case WSAENOBUFS:
p = "No buffer space";
break;
case WSAEISCONN:
p = "Socket is already connected";
break;
case WSAENOTCONN:
p = "Socket is not connected";
break;
case WSAESHUTDOWN:
p = "Socket has been shut down";
break;
case WSAETOOMANYREFS:
p = "Too many references";
break;
case WSAETIMEDOUT:
p = "Timed out";
break;
case WSAECONNREFUSED:
p = "Connection refused";
break;
case WSAELOOP:
p = "Loop??";
break;
case WSAENAMETOOLONG:
p = "Name too long";
break;
case WSAEHOSTDOWN:
p = "Host down";
break;
case WSAEHOSTUNREACH:
p = "Host unreachable";
break;
case WSAENOTEMPTY:
p = "Not empty";
break;
case WSAEPROCLIM:
p = "Process limit reached";
break;
case WSAEUSERS:
p = "Too many users";
break;
case WSAEDQUOT:
p = "Bad quota";
break;
case WSAESTALE:
p = "Something is stale";
break;
case WSAEREMOTE:
p = "Remote error";
break;
case WSAEDISCON:
p = "Disconnected";
break;
/* Extended Winsock errors */
case WSASYSNOTREADY:
p = "Winsock library is not ready";
break;
case WSANOTINITIALISED:
p = "Winsock library not initalised";
break;
case WSAVERNOTSUPPORTED:
p = "Winsock version not supported.";
break;
/* getXbyY() errors (already handled in herrmsg):
* Authoritative Answer: Host not found */
case WSAHOST_NOT_FOUND:
p = "Host not found";
break;
/* Non-Authoritative: Host not found, or SERVERFAIL */
case WSATRY_AGAIN:
p = "Host not found, try again";
break;
/* Non recoverable errors, FORMERR, REFUSED, NOTIMP */
case WSANO_RECOVERY:
p = "Unrecoverable error in call to nameserver";
break;
/* Valid name, no data record of requested type */
case WSANO_DATA:
p = "No data record of requested type";
break;
default:
return NULL;
}
strncpy (buf, p, len);
buf [len-1] = '\0';
return buf;
}
#endif /* WIN32 && !__CYGWIN__ */
/*
* Our thread-safe and smart strerror() replacement.
*
* The 'err' argument passed in to this function MUST be a true errno number
* as reported on this system. We do no range checking on the number before
* we pass it to the "number-to-message" convertion function and there might
* be systems that don't do proper range checking in there themselves.
*
* We don't do range checking (on systems other than Windows) since there is
* no good reliable and portable way to do it.
*/
const char *Curl_strerror(struct connectdata *conn, int err)
{
char *buf, *p;
size_t max;
curlassert(conn);
curlassert(err >= 0);
buf = conn->syserr_buf;
max = sizeof(conn->syserr_buf)-1;
*buf = '\0';
#if defined(WIN32) && !defined(__CYGWIN__)
/* 'sys_nerr' is the maximum errno number, it is not widely portable */
if (err >= 0 && err < sys_nerr)
strncpy(buf, strerror(err), max);
else {
if (!get_winsock_error (err, buf, max) &&
!FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM, NULL, err,
LANG_NEUTRAL, buf, max, NULL))
snprintf(buf, max, "Unknown error %d (%#x)", err, err);
}
#else /* not native Windows coming up */
/* These should be atomic and hopefully thread-safe */
#ifdef HAVE_STRERROR_R
/* There are two different APIs for strerror_r(). The POSIX and the GLIBC
versions. */
#ifdef HAVE_POSIX_STRERROR_R
strerror_r(err, buf, max);
/* this may set errno to ERANGE if insufficient storage was supplied via
'strerrbuf' and 'buflen' to contain the generated message string, or
EINVAL if the value of 'errnum' is not a valid error number.*/
#else
{
/* HAVE_GLIBC_STRERROR_R */
char buffer[256];
char *msg = strerror_r(err, buffer, sizeof(buffer));
strncpy(buf, msg, max);
}
#endif /* end of HAVE_GLIBC_STRERROR_R */
#else /* HAVE_STRERROR_R */
strncpy(buf, strerror(err), max);
#endif /* end of HAVE_STRERROR_R */
#endif /* end of ! Windows */
buf[max] = '\0'; /* make sure the string is zero terminated */
/* strip trailing '\r\n' or '\n'. */
if ((p = strrchr(buf,'\n')) != NULL && (p - buf) >= 2)
*p = '\0';
if ((p = strrchr(buf,'\r')) != NULL && (p - buf) >= 1)
*p = '\0';
return buf;
}

Some files were not shown because too many files have changed in this diff Show More