Compare commits

..

139 Commits

Author SHA1 Message Date
Daniel Stenberg
7e16ec8724 7.9.3 2002-01-23 18:10:00 +00:00
Daniel Stenberg
8c459156f8 7.9.3 public 2002-01-23 18:01:16 +00:00
Daniel Stenberg
2db894807b Andrs Garca found out that we didn't properly stop reading from a connection
after the headers on a HEAD request. This bug has been added in 7.9.3 and was
mnot present earlier.
2002-01-23 07:15:32 +00:00
Daniel Stenberg
95ceeb6e0b more about passwords and started about proxies 2002-01-22 13:41:00 +00:00
Daniel Stenberg
c9c00d2a23 verify big files 2002-01-22 13:10:16 +00:00
Daniel Stenberg
1afe49864d minor edit 2002-01-22 08:22:04 +00:00
Daniel Stenberg
6924bee3a0 added --cc description and an example 2002-01-21 14:57:07 +00:00
Daniel Stenberg
39d4552dab pre4 2002-01-21 12:11:45 +00:00
Daniel Stenberg
a23c63738f HTTP POST explained 2002-01-21 10:54:56 +00:00
Daniel Stenberg
e911945c55 #505514, as correctly pointed out by Antonio (anton@concord.ru), trying to
post a non-existing file should include nothing, not an error text!
2002-01-19 11:08:05 +00:00
Daniel Stenberg
6d58d13710 mingw fix, mac os x fix, long long check removed from configure,
--enable-debug uses even stricter options now
2002-01-18 15:16:08 +00:00
Daniel Stenberg
0b177cb165 newly generated 2002-01-18 15:14:35 +00:00
Daniel Stenberg
3e31b619de added more text in the 'passwords' section 2002-01-18 15:08:32 +00:00
Daniel Stenberg
f925979b2f satisfy gcc -Wundef 2002-01-18 13:10:41 +00:00
Daniel Stenberg
49f7fa82b9 #if [undefined] => #ifdef [undefined] 2002-01-18 13:04:48 +00:00
Daniel Stenberg
e4cd4cf3f3 playing with more strict gcc warnings with --enable-debug 2002-01-18 13:00:13 +00:00
Daniel Stenberg
e74b20926d prevents gcc -Wcast-align from complaining 2002-01-18 12:59:33 +00:00
Daniel Stenberg
a312127c91 made gcc -Wcast-align happy 2002-01-18 12:56:10 +00:00
Daniel Stenberg
1dc5bf4f73 #ifndef and #define magic to prevent compiler warnings when doing #if BLA
where BLA is undefined
2002-01-18 12:53:05 +00:00
Daniel Stenberg
01cfe670c5 updated to 2002 status ;-) 2002-01-18 12:48:36 +00:00
Daniel Stenberg
fd307bfe29 cut off a big piece of comment and added a pointer to the Trio web page
should anyone ever want a good printf() clone
2002-01-18 10:45:03 +00:00
Daniel Stenberg
a00de093a7 commented out the 'long long' and 'long double' checks, as we don't really
use them anyway and they cause warnings in lib/mprint.c
2002-01-18 10:43:55 +00:00
Daniel Stenberg
7bfe853af3 I wish I could type. Anyway, this proved it is a good habit to put the NULL
on the left side of comparisons...
2002-01-18 10:36:25 +00:00
Daniel Stenberg
cbaecca8e9 added typecast for a malloc() return, and added check for NULL 2002-01-18 10:30:51 +00:00
Daniel Stenberg
8edfb370a8 Added #include <errno.h> 2002-01-18 09:25:58 +00:00
Daniel Stenberg
4c08c8f7db Andrs Garca patched. It now checks for EWOULDBLOCK properly on windows
boxes.
2002-01-18 08:03:54 +00:00
Daniel Stenberg
c174680a03 patched by Andrs Garca 2002-01-18 08:03:12 +00:00
Daniel Stenberg
cb5f6e18e6 7.9.3-pre3 2002-01-17 14:34:26 +00:00
Daniel Stenberg
b798e7a5ae correct ssl version, fixed ssl writes, solved time-out disconnect without
text, fixed dns cache problem, made it compile with openssl before 0.9.5
again and extended libcurl-the-guide a bit more
2002-01-17 14:25:49 +00:00
Daniel Stenberg
5deab7ad27 more text added 2002-01-17 14:24:25 +00:00
Daniel Stenberg
12cdfd282d added a comment about this example only works with 7.9.3 and newer libs 2002-01-17 13:45:19 +00:00
Daniel Stenberg
eba8035e12 Richard Archer made it compile and build with OpenSSL versions prior to
0.9.5
2002-01-17 10:40:13 +00:00
Daniel Stenberg
edcbf4350b include our own sprintf() prototype to make it return sensible data on
all platforms, I also edited a few data types slightly to prevent my
compiler from warning on comparisions between signed and unsigned values
2002-01-17 08:03:48 +00:00
Sterling Hughes
9289ea471f Get this working, still need to check for leaks and such, but should be
fine..
2002-01-17 07:38:25 +00:00
Sterling Hughes
7d06185aa6 Make the keys for hostcache entries be in the format::
host:port, so accessing curl.haxx.se on port 80 would yield a key value
of ::
curl.haxx.se:80
2002-01-17 06:55:37 +00:00
Daniel Stenberg
01ecb1d7e7 filled-in text in the "Building" chapter and added a "libcurl with C++"
chapter
2002-01-17 00:27:56 +00:00
Daniel Stenberg
e177f14595 SSL writes passed back a silly length... 2002-01-16 23:28:58 +00:00
Daniel Stenberg
5c6eddcadd fixed time-out returned without error text set 2002-01-16 22:26:01 +00:00
Daniel Stenberg
b3b4786990 Kevin Roth's SSLeay() patch, slight edited by me. Works with OpenSSL 0.9.5
now.
2002-01-16 17:45:08 +00:00
Daniel Stenberg
fbe2907599 7.9.3-pre2 2002-01-16 15:12:12 +00:00
Daniel Stenberg
343da8d4b3 --cc and working non-blocking sockets uploads 2002-01-16 15:04:37 +00:00
Daniel Stenberg
8d97792dbc - shrunk the BUFSIZE define from 50K to 20K
- made a separate buffer for uploads (due to the non-blocking stuff)
- added two connectdata struct fields for non-blocking uploads
2002-01-16 14:53:19 +00:00
Daniel Stenberg
8d07c87be7 modified to deal with the new non-blocking versions of Curl_read() and
Curl_write().
2002-01-16 14:50:53 +00:00
Daniel Stenberg
ed21701df3 Curl_write's 5th argument now is signed 2002-01-16 14:49:51 +00:00
Daniel Stenberg
df01507582 Curl_read() and Curl_write() are both now adjusted to return properly in
cases where EWOULDBLOCK or equivalent is returned. We must not block.
2002-01-16 14:49:08 +00:00
Daniel Stenberg
f2bda5fd5b Curl_write() now takes a different 5th argument 2002-01-16 14:47:50 +00:00
Daniel Stenberg
cba9838e8f Somewhat ugly fix to deal with non-blocking sockets. We just loop and try
again. THIS IS NOT A NICE FIX.
2002-01-16 14:47:00 +00:00
Daniel Stenberg
b6dba9f5dd Somewhat ugly fix to deal with non-blocking sockets. We just loop and try
again. THIS IS NOT A NICE FIX. We should/must make a select() then and only
retry when we can write to the socket again.
2002-01-16 14:46:00 +00:00
Daniel Stenberg
6e9d1617c6 added support for --cc to output the compiler name. This makes it possible
to compile libcurl stuff without any prior knowledge:

cc=`curl-config --cc`
cflags=`curl-config --cflags`
libs=`curl-config --libs`

$cc $flags $libs -o example example.c

Or if you prefer, the oh-so-cool single-line version:

`curl-config --cc --cflags --libs` -o example example.c
2002-01-16 14:20:06 +00:00
Daniel Stenberg
ea811fee52 added a somewhat cool single-line command that builds most example sources
on unix-like systems
2002-01-16 14:13:54 +00:00
Daniel Stenberg
7391fd8f6a initial attempt to write a tutorial-like libcurl guide 2002-01-15 08:22:00 +00:00
Daniel Stenberg
6c00c58f2a fixed non-blocking reads, fixed ssl sessions, in_addr_t and more non-blocking 2002-01-14 23:32:57 +00:00
Daniel Stenberg
4931fbce49 Curl_read() now returns a negative return code if EWOULDBLOCK or similar 2002-01-14 23:14:59 +00:00
Daniel Stenberg
fefc7ea600 a memory leak when name lookup failed is now removed 2002-01-14 23:14:24 +00:00
Daniel Stenberg
d220389647 Stoned Elipot's patch for the in_addr_t test 2002-01-14 07:53:09 +00:00
Sterling Hughes
a1f910c159 Remove erreaneous include, setup.h is included one line above 2002-01-14 05:36:28 +00:00
Daniel Stenberg
e4866563de Gtz Babin-Ebell updated with some new 7.9.3 features 2002-01-13 11:32:36 +00:00
Daniel Stenberg
47f45aa229 Gtz Babin-Ebell provided some documantation for the ENGINE stuff 2002-01-13 11:32:05 +00:00
Daniel Stenberg
affe334675 added http-post.c 2002-01-10 09:00:02 +00:00
Daniel Stenberg
ee7e184e26 slightly extended to mention that -v and -i are good options to use when
reporting bugs
2002-01-10 07:38:53 +00:00
Daniel Stenberg
bec0ebacf1 bad comment begone 2002-01-09 13:23:01 +00:00
Daniel Stenberg
5bd6d631c6 cut off argc and argv as well 2002-01-09 13:22:31 +00:00
Daniel Stenberg
fd1799f3bb Cleaned up this example to make it even simpler. 2002-01-09 13:22:03 +00:00
Daniel Stenberg
d84a0c51e0 Cris Bailiff found out that when the SSL session cache was filled, libcurl
would crash. This corrects the problem.
2002-01-09 09:38:37 +00:00
Daniel Stenberg
d9a7c7de51 David Bentham's updated QNX notification 2002-01-08 23:27:42 +00:00
Daniel Stenberg
d57e09889a added a missing failf() before returning an error code 2002-01-08 23:23:24 +00:00
Daniel Stenberg
eecb86bfb0 this seems to correct the SSL reading problem introduced when switching
over to non-blocking sockets, but this loops very nastily. We should return
back to the select() and wait there until more data arrives, not just blindly
attempt again and again...
2002-01-08 23:19:32 +00:00
Daniel Stenberg
0b1197936c I made the write callback create the file the first time it gets called so
that it won't create an empty file if the remote file doesn't exist
2002-01-08 13:05:44 +00:00
Daniel Stenberg
b545ac6391 test case 38 added a few new requirements 2002-01-08 09:32:41 +00:00
Daniel Stenberg
a922132e4a updated 2002-01-08 09:32:21 +00:00
Daniel Stenberg
9474e8d6d2 added some tracability 2002-01-08 09:32:10 +00:00
Daniel Stenberg
6328428568 test case 38, try a HTTP download resume without the server supporting
ranges
2002-01-08 09:31:40 +00:00
Daniel Stenberg
ea9a88a9b8 another example source added 2002-01-08 08:26:22 +00:00
Daniel Stenberg
aec7358ca4 7.9.3 pre-release commit 2002-01-08 08:25:44 +00:00
Daniel Stenberg
3c334b2bb6 non-blocking sockets, DNS caching updated, cookies corrected, bool is now
unsigned everywhere
2002-01-08 07:22:33 +00:00
Daniel Stenberg
75bba0da92 added two typecasts to prevent compiler (gcc3) warnings 2002-01-08 07:06:07 +00:00
Sterling Hughes
c0bfe7be15 1) the dns_cache_timeout should be an integer, not a bool
2) in the curl_dns_cache_entry structure, timestamp should be
a time_t instead of an integer (although I doubt it matters).
2002-01-08 04:30:59 +00:00
Sterling Hughes
22ac08e06d Add support for DNS cache timeouts via the CURLOPT_DNS_CACHE_TIMEOUT option.
The default cache timeout for this is 60 seconds, which is arbitrary and
completely subject to change :)
2002-01-08 04:26:47 +00:00
Daniel Stenberg
87037136ef As identified in bug report #495290, the last "name=value" pair in a
Set-Cookie: line was ignored if they didn't end with a trailing
semicolon. This is indeed wrong syntax, but there are high-profile web sites
out there sending cookies like that so we must make a best-effort to parse
them.
2002-01-07 23:05:36 +00:00
Daniel Stenberg
2182e37433 the bool typedef is now made unsigned, to make sure it stays that on all
platforms, unrelated to what they might prefer by default
2002-01-07 22:47:21 +00:00
Daniel Stenberg
1de82b220d removed silly check for >=0 of a supposedly unsigned value! 2002-01-07 22:46:38 +00:00
Sterling Hughes
bd878756fc Probably not necessary, but good practice. 2002-01-07 20:55:35 +00:00
Sterling Hughes
8d7f402efb Make cach'ing work with threads now, there are now three cases:
- Use a global dns cache (via setting the tentatively named,
    CURLOPT_DNS_USE_GLOBAL_CACHE option to true)
    - Use a per-handle dns cache, by default
    - Use a pooled dns cache when in the "multi" interface
2002-01-07 20:52:32 +00:00
Daniel Stenberg
d3299beec7 Modified to use non-blocking sockets all the time. 2002-01-07 18:38:01 +00:00
Daniel Stenberg
f9192db358 VC++ makefile, HTTP 204, cookie fix, non-blocking socket for better SSL
connection timeout
2002-01-07 16:03:36 +00:00
Daniel Stenberg
c69c0c0446 added proper breaks in the switch() 2002-01-07 15:24:52 +00:00
Daniel Stenberg
deb2911c0e Added David Bentham's notes about QNX and FD_SETSIZE 2002-01-07 15:14:01 +00:00
Daniel Stenberg
e31a306a38 HTTP response 204 should be treated similar to 304, that is we must not
expect (nor read) any response-body
2002-01-07 14:57:18 +00:00
Daniel Stenberg
d9a7773011 added precautions to not go insane when two matching cookies end up in the
cookie list, even though they're not supposed to do that...
2002-01-07 14:56:15 +00:00
sm
2b14916813 Add hash and llist to VC dsp file 2002-01-04 23:48:28 +00:00
sm
1d1530e14c Add hash and llist to VC makefile 2002-01-04 23:47:07 +00:00
Daniel Stenberg
b4fdc025a8 -l lists all tests 2002-01-04 13:20:17 +00:00
Daniel Stenberg
f1c14fe0b4 The former -c is "-C -" these days 2002-01-04 13:15:07 +00:00
Daniel Stenberg
38306cda54 dns cache, ftp response read, 64bit fixes, printf replaces, inet_ntoa_r
corrections
2002-01-04 09:57:57 +00:00
Daniel Stenberg
5a0f0023cf replaced printf() => Curl_sendf() 2002-01-04 09:53:39 +00:00
Daniel Stenberg
6dcdb8b821 removed a commented line 2002-01-04 09:53:10 +00:00
Daniel Stenberg
781f52a287 fixed an inet_ntoa() occurance to use inet_ntoa_r() if it is available.
I also replaced all printf() calls with calls to Curl_failf()
2002-01-04 09:52:44 +00:00
Daniel Stenberg
f75ff58b4b an unconditional occurance of inet_ntoa() now uses inet_ntoa_r() on all
platforms that have such a function.
This affects multi-thread running libcurls on IPv4 systems that have VERBOSE
switched on. The previous version was risking that another thread overwrote
the data before it was read out in this thread. There could possibly also
be a slight risk that the data isn't zero terminated for a short while and
thus could cause the thread to crash...
2002-01-04 09:38:52 +00:00
Daniel Stenberg
ae9bf16dee #include the local "inet_ntoa_r.h" file if no proto was found in the global
header directory but the function *is* present!
2002-01-04 09:35:23 +00:00
Daniel Stenberg
17a8bf212f The buffer in ftp_pasv_verbose(), used for gethostbyaddr_r(), is now defined
to become properly 8-byte aligned on 64-bit archs. Philip Gladstone reported.
2002-01-04 09:17:52 +00:00
Daniel Stenberg
4fc76afef4 The FTP response lines are now passed to the function callback registered for
headers.
2002-01-04 09:03:11 +00:00
Daniel Stenberg
a31155a72a multi stuff from the multi-dev branch 2002-01-03 15:03:57 +00:00
Daniel Stenberg
75601f7924 multi interface example/test sources from the multi-dev branch 2002-01-03 15:03:14 +00:00
Daniel Stenberg
8b6314ccfb merged the multi-dev branch back into MAIN again 2002-01-03 15:01:22 +00:00
Daniel Stenberg
6de7dc5879 Sterling Hughes' provided initial DNS cache source code. 2002-01-03 10:22:59 +00:00
Daniel Stenberg
6aaee5f23b minor changes 2002-01-03 09:43:17 +00:00
Daniel Stenberg
dd06dcebe1 added required software and Guido Neitzer's Mac OS X build instructions 2002-01-03 09:12:41 +00:00
Daniel Stenberg
b35c26b751 added a little percentage for "ok coverage" 2002-01-03 08:22:05 +00:00
Daniel Stenberg
128f341635 Changed how -I/--head works when --include is also used... Test case 104
stopped working after the dec-20 fixes that now supports FTP operations to
skip the transfer phase.
2002-01-03 08:07:29 +00:00
Daniel Stenberg
e48bc1be48 Philip Gladstone's fixes 2002-01-03 07:23:21 +00:00
Daniel Stenberg
0077b9c0a2 pass an 'int' as the third argument to bind() 2002-01-03 00:51:33 +00:00
Daniel Stenberg
fe37fb5921 Philip Gladstone's 64-bit sparc native compiler compatibility issues fixed. 2002-01-02 10:06:47 +00:00
Daniel Stenberg
221ecd0a30 the changes from 1999 is now in CHANGES.1999 2001-12-21 09:55:13 +00:00
Daniel Stenberg
560492707d moved the changes from 1999 into its own file 2001-12-21 09:54:45 +00:00
Daniel Stenberg
dfdf4916fa rewrote 3.9 to be more generic with more languages:
"3.9 How do I use curl in my favourite programming language?"
2001-12-21 09:20:04 +00:00
Daniel Stenberg
97a8c98886 spell 2001-12-21 08:10:34 +00:00
Daniel Stenberg
62fb70e9d1 recent fixes 2001-12-21 08:02:35 +00:00
Daniel Stenberg
8a9098a36c *cool* fix by Bjrn Stenberg, makes proxy transfers work better...! :-) 2001-12-20 15:58:22 +00:00
Daniel Stenberg
28027c2aa2 If nobody is set we won't download any FTP file. If include_header is set,
we return a set of headers not more. This enables FTP operations that don't
transfer any data, only perform FTP commands.
2001-12-20 11:22:01 +00:00
Daniel Stenberg
d60029d66e Added 4.5.6 "301 Moved Permanently", as a reply to bug report #495215 2001-12-19 23:25:04 +00:00
Daniel Stenberg
226fe8bdf9 Gtz Babin-Ebell's contributed "simplessl.c" example source code 2001-12-18 10:13:41 +00:00
Daniel Stenberg
33237b4502 run automake last 2001-12-18 01:00:24 +00:00
Daniel Stenberg
af6c394785 Gtz Babin-Ebell's OpenSSL ENGINE patch 2001-12-17 23:01:39 +00:00
Daniel Stenberg
558d12d7f6 strip trailing CRs 2001-12-17 10:32:10 +00:00
Daniel Stenberg
bfa8a6da26 cut off the description to prevent people from using this! 2001-12-17 09:33:54 +00:00
Daniel Stenberg
aa6b3d22a2 Marcus Webster's added CURLFORM_CONTENTHEADER docs 2001-12-16 12:54:42 +00:00
Daniel Stenberg
2eb355733f Marcus Webster's newly added CURLFORM_CONTENTHEADER 2001-12-14 12:59:16 +00:00
Daniel Stenberg
e66cdacb93 minor changes 2001-12-13 07:16:27 +00:00
Daniel Stenberg
c67f2da283 solaris 2.5.1 needs the sys/types.h file before the sys/socket.h 2001-12-11 15:08:27 +00:00
Daniel Stenberg
e192261788 failf() calls should not have newlines in the message string! 2001-12-11 13:13:01 +00:00
Daniel Stenberg
c63ca99c1c when the file name given to -T is used to build an upload path, the local
directory part is now stripped off and only the actual file name part will be
used
2001-12-11 00:48:55 +00:00
Daniel Stenberg
1c99c4ad11 HTTP_PROXY => http_proxy as Bjrn pointed out 2001-12-10 11:59:05 +00:00
Daniel Stenberg
bbcfc10677 corrected the READFUNCTION docs slightly 2001-12-10 07:46:43 +00:00
Daniel Stenberg
47e67eab26 corrected the comment above gmtime_r 2001-12-07 15:56:57 +00:00
Daniel Stenberg
650b95045d added gmtime_r check 2001-12-07 15:51:59 +00:00
Cris Bailiff
5603134e58 Updated location information for Curl_easy 2001-12-07 09:24:42 +00:00
Daniel Stenberg
d12fd897cb Jason Mancini's -Oalways suggestion 2001-12-06 14:40:16 +00:00
Daniel Stenberg
5e95203a5d let us know if curl compiles on more platforms 2001-12-06 12:48:41 +00:00
Daniel Stenberg
cad4a571ce curl compiles on HURD 2001-12-06 07:11:33 +00:00
81 changed files with 5369 additions and 2282 deletions

230
CHANGES
View File

@@ -6,6 +6,236 @@
History of Changes History of Changes
Version 7.9.3
Daniel (23 January 2002)
- Andr<64>s Garc<72>a found a persistancy problem when doing HTTP HEAD, that made
curl "hang" until the connection was closed by the server. This problem has
been introduced in 7.9.3 due to internal rewrites, this was not present in
7.9.2.
Version 7.9.3-pre4
Daniel (19 January 2002)
- Antonio filed bug report #505514 and provided a fix! When doing multipart
formposts, libcurl would include an error text in the actual post if a
specified file wasn't found. This is not libcurl's job. Instead we add an
empty part.
Daniel (18 January 2002)
- Played around with stricter compiler warnings for gcc (when ./configure
--enable-debug is used) and changed some minor things to stop the warnings.
- Commented out the 'long long' and 'long double' checks in configure.in, as
we don't currently use them anyway and the code in lib/mprintf.c that use
them causes warnings.
- Saul Good and jonatan pointed out Mac OS X build problems with pre3 and how
to correct them. Two compiler warnings were removed as well.
- Andr<64>s Garc<72>a fixed two minor mingw32 building problems.
Version 7.9.3-pre3
Daniel (17 January 2002)
- docs/libcurl-the-guide is a new tutorial for our libcurl programming
friends.
- Richard Archer brought back the ability to compile and build with OpenSSL
versions before 0.9.5.
[http://sourceforge.net/tracker/?func=detail&atid=100976&aid=504163&group_id=976]
- The DNS cache code didn't take the port number into account, which made it
work rather bad on IPv6-enabled hosts (especially when doing passive
FTP). Sterling fixed it.
Daniel (16 January 2002)
- Georg Horn could make a transfer time-out without error text. I found it and
corrected it.
- SSL writes didn't work, they return an uninitialized value that caused
havoc all over. Georg Horn experienced this.
- Kevin Roth patched the curl_version() function to use the proper OpenSSL
function for version information. This way, curl will report the version of
the SSL library actually running right now, not the one that had its headers
installed when libcurl was built. Mainly intersting when running with shared
OpenSSL libraries.
Version 7.9.3-pre2
Daniel (16 January 2002)
- Mofied the main transfer loop and related stuff to deal with non-blocking
sockets in the upload section. While doing this, I've now separated the
connection oriented buffers to have one for downloads and one for uploads
(as two can happen simultaneously). I also shrunk the buffers to 20K
each. As we have a scratch buffer twice the size of the upload buffer, we
arrived at 80K for buffers compared with the previous 150K.
- Added the --cc option to curl-config command as it enables so very cool
one-liners. Have a go a this one, building the simple.c example:
$ `curl-config --cc --cflags --libs` -o example simple.c
Daniel (14 January 2002)
- I made all socket reads (recv) handle EWOULDBLOCK. I hope nicely. Now we
only need to address all writes (send) too and then I'm ready for another
pre-release...
- Stoned Elipot patched the in_addr_t configure test to make it work better on
more platforms.
Daniel (9 January 2002)
- Cris Bailiff found out that filling up curl's SSL session cache caused a
crash!
- Posted the curl questionnaire on the web site. If you haven't posted your
opinions there yet, go there and do it now while it is still there:
http://curl.haxx.se/q/
- Georg Horn quickly found out that the SSL reading no longer worked as
supposed since the switch to non-blocking sockets. I've made a quick patch
(for reading only) but we should improve it even further.
Version 7.9.3-pre1
Daniel (7 January 2002)
- I made the 'bool' typedef use an "unsigned char". It makes it the same on
all platforms, no matter what the platform thinks the default format for
char is. This was noticed since we made a silly comparison involving such a
bool variable, and only one compiler/platform combination (on Debian Linux)
complained about it (that happened to have its char unsigned by default).
- Bug report #495290 identified a cookie parsing problem that was corrected.
When a Set-Cookie: line is received without a trailing semicolon, libcurl
didn't read the last "name=value" pair of the line, leading to confusions...
- Sterling committed his updated DNS cache code.
- I worked with Georg Horn and comments from G<>tz Babin-Ebell and switched
curl's socket operations completely over to non-blocking for the entire
operation (previously we used non-blocking only for the connection phase).
We had to do this to make the SSL connection phase timeout properly without
the use of signals. A little extra code to deal with this was added.
- T. Bharath pointed out a slightly obscure cookie engine flaw.
- Pete Su pointed out that libcurl didn't treat HTTP code 204 as it should.
204-replies never provides a response-body. This resulted in bad persistant
behavior when 204 was received.
Daniel (5 January 2002)
- SM updated the VC++ library Makefiles for the new source files.
Daniel (4 January 2002)
- I discovered that we wrongly used inet_ntoa() (instead of inet_ntoa_r() in
two places in the source code). One happened with VERBOSE set on connects,
and the other when VERBOSE was on and krb4 over nat was used... I honestly
don't think anyone has suffered from these mistakes.
- I replaced a lot of silly occurances of printf() to instead use the more
appropriate Curl_infof() or Curl_failf(). The krb4 and telnet code were
affected.
- Philip Gladstone found a few more problems with 64-bit archs (the 64-bit
sparc on solaris 8).
- After discussions on the libcurl list with Raoul Cridlig, I just made FTP
response lines get passed to the header callback if such a one is
registered. It'll make it possible for any application to get all the
responses an FTP server sends to libcurl.
Daniel (3 January 2002)
- Sterling Hughes brought a few buckets of code. Now, libcurl will
automatically cache DNS lookups and re-use the previous results first if any
such is available. It greatly improves speed when doing many repeated
operations to the same host.
- As the test case uses --include and then --head, I had to modify src/main.c
to deal with this situation slightly better than previously. When done, we
have 100% good tests again in the main branch.
Daniel (2 January 2002)
- Made test case 25 run again in the multi-dev branch. But it seems that the
changes done on dec-20 made test case 104 cease to work (in both branches).
- Philip Gladstone pointed out a few portability problems in the source code
that didn't compile on 64-bit sparcs using Sun's native compiler...
Daniel (20 December 2001)
- Bj<42>rn Stenberg caught an unpleasent (but hard-to-find) bug that could cause
libcurl to hang on transfers over proxy, when the proxy was specified with
an environment variable!
- Added code to make ftp operations treat the NO_BODY and HEADERS options
better:
NO_BODY set TRUE and HEADERS set TRUE:
Return a set of headers with file info
NO_BODY set FALSE
Transfer data as usual, HEADERS is ignored
NO_BODY set TRUE and HEADERS set FALSE
Don't transfer any data, don't return any headers. Just perform the set
of FTP commands.
Daniel (17 December 2001)
- G<>tz Babin-Ebell dove into the dark dungeons of the OpenSSL ENGINE stuff and
made libcurl support it! This allows libcurl to do SSL connections with the
private key stored in external hardware.
To make this good, he had to add a bunch of new library options that'll be
useful to others as well:
CURLOPT_SSLCERTTYPE set SSL cert type (PEM/DER)
CURLOPT_SSLKEY set SSL private key (file)
CURLOPT_SSLKEYTYPE: set SSL key type (PEM/DER/ENG)
CURLOPT_SSLKEYPASSWD: set the passphrase for your private key
(CURLOPT_SSLCERTPASSWD is an alias)
CURLOPT_SSLENGINE: set the name of the crypto engine
(returns CURLE_SSL_ENGINE_NOTFOUND on error)
CURLOPT_SSLENGINE_DEFAULT: set the default engine
There are two new failure codes:
CURLE_SSL_ENGINE_NOTFOUND
CURLE_SSL_ENGINE_SETFAILED
Daniel (14 December 2001)
- We have "branched" the source-tree at a few places. Checkout the CVS sources
with the 'multi-dev' label to get the latest multi interface development
tree. The idea is to only branch affected files and to restrict the branch
to the v8 multi interface development only.
*NOTE* that if we get bug reports and patches etc, we might need to apply
them in both branches!
The multi-dev branch is what we are gonna use as main branch in the future
if it turns out successful. Thus, we must maintain both now in case we need
them. The current main branch will be used if we want to release a 7.9.3 or
perhaps a 7.10 release before version 8. Which is very likely.
- Marcus Webster provided code for the new CURLFORM_CONTENTHEADER option for
curl_formadd(), that lets an application add a set of headers for that
particular part in a multipart/form-post. He also provided a section to the
man page that describes the new option.
Daniel (11 December 2001)
- Ben Greear made me aware of the fact that the Curl_failf() usage internally
was a bit sloppy with adding newlines or not to the error messages. Let's
once and for all say that they do not belong there!
- When uploading files with -T to give a local file name, and you end the URL
with a slash to have the local file name used remote too, we now no longer
use the local directory as well. Only the file part of the -T file name
will be appended to the right of the slash in the URL.
Daniel (7 December 2001)
- Michal Bonino pointed out that Digital Unix doesn't have gmtime_r so the
link failed. Added a configure check and corrected source code.
Version 7.9.2 Version 7.9.2
Daniel (5 December 2001) Daniel (5 December 2001)

835
CHANGES.0
View File

@@ -1,838 +1,3 @@
Daniel (28 December 1999):
- Tim Verhoeven correctly identified that curl
doesn't support URL formatted file names when getting ftp. Now, there's a
problem with getting very weird file names off FTP servers. RFC 959 defines
that the file name syntax to use should be the same as in the native OS of
the server. Since we don't know the peer server system we currently just
translate the URL syntax into plain letters. It is still better and with
the solaris 2.6-supplied ftp server it works with spaces in the file names.
Daniel (27 December 1999):
- When curl parsed cookies straight off a remote site, it corrupted the input
data, which, if the downloaded headers were stored made very odd characters
in the saved data. Correctly identified and reported by Paul Harrington.
Daniel (13 December 1999):
- General cleanups in the library interface. There had been some bad kludges
added during times of stress and I did my best to clean them off. It was
both regarding the lib API as well as include file confusions.
Daniel (3 December 1999):
- A small --stderr bug was reported by Eetu Ojanen...
- who also brought the suggestion of extending the -X flag to ftp list as
well. So, now it is and the long option is now --request instead. It is
only for ftp list for now (and the former http stuff too of course).
Lars J. Aas (24 November 1999):
- Patched curl to compile and build under BeOS. Doesn't work yet though!
- Corrected the Makefile.am files to allow putting object files in
different directories than the sources.
Version 6.3.1
Daniel (23 November 1999):
- I've had this major disk crash. My good old trust-worthy source disk died
along with the machine that hosted it. Thank goodness most of all the
things I've done are either backed up elsewhere or stored in this CVS
server!
- Michael S. Steuer pointed out a bug in the -F handling
that made curl hang if you posted an empty variable such as '-F name='. It
was one of those old bugs that never have worked properly...
- Jason Baietto pointed out a general flaw in the HTTP
download. Curl didn't complain if it was prematurely aborted before the
entire download was completed. It does now.
Daniel (19 November 1999):
- Chris Maltby very accurately criticized the lack of
return code checks on the fwrite() calls. I did a thorough check for all
occurrences and corrected this.
Daniel (17 November 1999):
- Paul Harrington pointed out that the -m/--max-time option
doesn't work for the slow system calls like gethostbyname()... I don't have
any good fix yet, just a slightly less bad one that makes curl exit hard
when the timeout is reached.
- Bjorn Reese helped me point out a possible problem that might be the reason
why Thomas Hurst experience problems in his Amiga version.
Daniel (12 November 1999):
- I found a crash in the new cookie file parser. It crashed when you gave
a plain http header file as input...
Version 6.3
Daniel (10 November 1999):
- I kind of found out that the HTTP time-conditional GETs (-z) aren't always
respected by the web server and the document is therefore sent in whole
again, even though it doesn't match the requested condition. After reading
section 13.3.4 of RFC 2616, I think I'm doing the right thing now when I do
my own check as well. If curl thinks the condition isn't met, the transfer
is aborted prematurely (after all the headers have been received).
- After comments from Robert Linden I also rewrote some parts of the man page
to better describe how the -F works.
- Michael Anti put up a new curl download mirror in
China: http://www.pshowing.com/curl/
- I added the list of download mirrors to the README file
- I did add more explanations to the man page
Daniel (8 November 1999):
- I made the -b/--cookie option capable of reading netscape formatted cookie
files as well as normal http-header files. It should be able to
transparently figure out what kind of file it got as input.
Daniel (29 October 1999):
- Another one of Sebastiaan van Erk's ideas (that has been requested before
but I seem to have forgotten who it was), is to add support for ranges in
FTP downloads. As usual, one request is just a request, when they're two
it is a demand. I've added simple support for X-Y style fetches. X has to
be the lower number, though you may omit one of the numbers. Use the -r/
--range switch (previously HTTP-only).
- Sebastiaan van Erk suggested that curl should be
able to show the file size of a specified file. I think this is a splendid
idea and the -I flag is now working for FTP. It displays the file size in
this manner:
Content-Length: XXXX
As it resembles normal headers, and leaves us the opportunity to add more
info in that display if we can come up with more in the future! It also
makes sense since if you access ftp through a HTTP proxy, you'd get the
file size the same way.
I changed the order of the QUOTE command executions. They're now executed
just after the login and before any other command. I made this to enable
quote commands to run before the -I stuff is done too.
- I found out that -D/--dump-header and -V/--version weren't documented in
the man page.
- Many HTTP/1.1 servers do not support ranges. Don't ask me why. I did add
some text about this in the man page for the range option. The thread in
the mailing list that started this was initiated by Michael Anti.
- I get reports about nroff crashes on solaris 2.6+ when displaying the curl
man page. Switch to gnroff instead, it is reported to work(!). Adam Barclay
reported and brought the suggestion.
- In a dialogue with Johannes G. Kristinsson we came
up with the idea to let -H/--header specified headers replace the
internally generated headers, if you happened to select to add a header
that curl normally uses by itself. The advantage with this is not entirely
obvious, but in Johannes' case it means that he can use another Host: than
the one curl would set.
Daniel (27 October 1999):
- Jongki Suwandi brought a nice patch for (yet another) crash when following
a location:. This time you had to follow a https:// server's redirect to
get the core.
Version 6.2
Daniel (21 October 1999):
- I think I managed to remove the suspicious (nil) that has been seen just
before the "Host:" in HTTP requests when -v was used.
- I found out that if you followed a location: when using a proxy, without
having specified http:// in the URL, the protocol part was added once again
when moving to the next URL! (The protocol part has to be added to the
URL when going through a proxy since it has no protocol-guessing system
such as curl has.)
- Benjamin Ritcey reported a core dump under solaris 2.6
with OpenSSL 0.9.4. It turned out this was due to a bad free() in main.c
that occurred after the download was done and completed.
- Benjamin found ftp downloads to show the first line of the download meter
to get written twice, and I removed that problem. It was introduced with
the multiple URL support.
- Dan Zitter correctly pointed out that curl 6.1 and earlier versions didn't
honor RFC 2616 chapter 4 section 2, "Message Headers": "...Field names are
case-insensitive..." HTTP header parsing assumed a certain casing. Dan
also provided me with a patch that corrected this, which I took the liberty
of editing slightly.
- Dan Zitter also provided a nice patch for config.guess to better recognize
the Mac OS X
- Dan also corrected a minor problem in the lib/Makefile that caused linking
to fail on OS X.
Daniel (19 October 1999):
- Len Marinaccio came up with some problems with curl. Since Windows has a
crippled shell, it can't redirect stderr and that causes trouble. I added
--stderr today which allows the user to redirect the stderr stream to a
file or stdout.
Daniel (18 October 1999):
- The configure script now understands the '--without-ssl' flag, which now
totally disable SSL/https support. Previously it wasn't possible to force
the configure script to leave SSL alone. The previous functionality has
been retained. Troy Engel helped test this new one.
Version 6.1
Daniel (17 October 1999):
- I ifdef'ed or commented all the zlib stuff in the sources and configure
script. It turned out we needed to mock more with zlib than I initially
thought, to make it capable of downloading compressed HTTP documents and
uncompress them on the fly. I didn't mean the zlib parts of curl to become
more than minor so this means I halt the zlib expedition for now and wait
until someone either writes the code or zlib gets updated and better
adjusted for this kind of usage. I won't get into details here, but a
short a summary is suitable:
- zlib can't automatically detect whether to use zlib or gzip
decompression methods.
- zlib is very neat for reading gzipped files from a file descriptor,
although not as nice for reading buffer-based data such as we would
want it.
- there are still some problems with the win32 version when reading from
a file descriptor if that is a socket
Daniel (14 October 1999):
- Moved the (external) include files for libcurl into a subdirectory named
curl and adjusted all #include lines to use <curl/XXXX> to maintain a
better name space and control of the headers. This has been requested.
Daniel (12 October 1999):
- I modified the 'maketgz' script to perform a 'make' too before a release
archive is put together in an attempt to make the time stamps better and
hopefully avoid the double configure-running that use to occur.
Daniel (11 October 1999):
- Applied J<>rn's patches that fixes zlib for mingw32 compiles as well as
some other missing zlib #ifdef and more text on the multiple URL docs in
the man page.
Version 6.1beta
Daniel (6 October 1999):
- Douglas E. Wegscheid sent me a patch that made the exact same thing as I
just made: the -d switch is now capable of reading post data from a named
file or stdin. Use it similarly to the -F. To read the post data from a
given file:
curl -d @path/to/filename www.postsite.com
or let curl read it out from stdin:
curl -d @- www.postit.com
J<>rn Hartroth (3 October 1999):
- Brought some more patches for multiple URL functionality. The MIME
separation ideas are almost scrapped now, and a custom separator is being
used instead. This is still compile-time "flagged".
Daniel
- Updated curl.1 with multiple URL info.
Daniel (30 September 1999):
- Felix von Leitner brought openssl-check fixes for configure.in to work
out-of-the-box when the openssl files are installed in the system default
dirs.
Daniel (28 September 1999)
- Added libz functionality. This should enable decompressing gzip, compress
or deflate encoding HTTP documents. It also makes curl send an accept that
it accepts that kind of encoding. Compressed contents usually shortens
download time. I *need* someone to tell me a site that uses compressed HTTP
documents so that I can test this out properly.
- As a result of the adding of zlib awareness, I changed the version string
a little. I plan to add openldap version reporting in there too.
Daniel (17 September 1999)
- Made the -F option allow stdin when specifying files. By using '-' instead
of file name, the data will be read from stdin.
Version 6.0
Daniel (13 September 1999)
- Added -X/--http-request <request> to enable any HTTP command to be sent.
Do not that your server has to support the exact string you enter. This
should possibly a string like DELETE or TRACE.
- Applied Douglas' mingw32-fixes for the makefiles.
Daniel (10 September 1999)
- Douglas E. Wegscheid pointed out a problem. Curl didn't check the FTP
servers return code properly after the --quote commands were issued. It
took anything non 200 as an error, when all 2XX codes should be accepted as
OK.
- Sending cookies to the same site in multiple lines like curl used to do
turned out to be bad and breaking the cookie specs. Curl now sends all
cookies on a single Cookie: line. Curl is not yet RFC 2109 compliant, but I
doubt that many servers do use that syntax (yet).
Daniel (8 September 1999)
- J<>rn helped me make sure it still compiles nicely with mingw32 under win32.
Daniel (7 September 1999)
- FTP upload through proxy is now turned into a HTTP PUT. Requested by
Stefan Kanthak.
- Added the ldap files to the .m32 makefile.
Daniel (3 September 1999)
- Made cookie matching work while using HTTP proxy.
Bjorn Reese (31 August 1999)
- Passed his ldap:// patch. Note that this requires the openldap shared
library to be installed and that LD_LIBRARY_PATH points to the
directory where the lib will be found when curl is run with a
ldap:// URL.
J<>rn Hartroth (31 August 1999)
- Made the Mingw32 makefiles into single files.
- Made file:// work for Win32. The same code is now used for unix as well for
performance reasons.
Douglas E. Wegscheid (30 August 1999)
- Patched the Mingw32 makefiles for SSL builds.
Matthew Clarke (30 August 1999)
- Made a cool patch for configure.in to allow --with-ssl to specify the
root dir of the openssl installation, as in
./configure --with-ssl=/usr/ssl_here
- Corrected the 'reconf' script to work better with some shells.
J<>rn Hartroth (26 August 1999)
- Fixed the Mingw32 makefiles in lib/ and corrected the file.c for win32
compiles.
Version 5.11
Daniel (25 August 1999)
- John Weismiller pointed out a bug in the header-line
realloc() system in download.c.
- I added lib/file.[ch] to offer a first, simple, file:// support. It
probably won't do much good on win32 system at this point, but I see it
as a start.
- Made the release archives get a Makefile in the root dir, which can be
used to start the compiling/building process easier. I haven't really
changed any INSTALL text yet, I wanted to get some feed-back on this
first.
Daniel (17 August 1999)
- Another Location: bug. Curl didn't do proper relative locations if the
original URL had cgi-parameters that contained a slash. Nusu's page
again.
- Corrected the NO_PROXY usage. It is a list of substrings that if one of
them matches the tail of the host name it should connect to, curl should
not use a proxy to connect there. Pointed out to me by Douglas
E. Wegscheid. I also changed the README text a little regarding this.
Daniel (16 August 1999)
- Fixed a memory bug with http-servers that sent Location: to a Location:
page. Nusu's page showed this too.
- Made cookies work a lot better. Setting the same cookie name several times
used to add more cookies instead of replacing the former one which it
should've. Nusu <nus at intergorj.ro> brought me an URL that made this
painfully visible...
Troy (15 August 1999)
- Brought new .spec files as well as a patch for configure.in that lets the
configure script find the openssl files better, even when the include
files are in /usr/include/openssl
Version 5.10
Daniel (13 August 1999)
- SSL_CTX_set_default_passwd_cb() has been modified in the 0.9.4 version of
OpenSSL. Now why couldn't they simply add a *new* function instead of
modifying the parameters of an already existing function? This way, we get
a compiler warning if compiling with 0.9.4 but not with earlier. So, I had
to come up with a #if construction that deals with this...
- Made curl output the SSL version number get displayed properly with 0.9.4.
Troy (12 August 1999)
- Added MingW32 (GCC-2.95) support under Win32. The INSTALL file was also
a bit rearranged.
Daniel (12 August 1999)
- I had to copy a good <arpa/telnet.h> include file into the curl source
tree to enable the silly win32 systems to compile. The distribution rights
allows us to do that as long as the file remains unmodified.
- I corrected a few minor things that made the compiler complain when
-Wall -pedantic was used.
- I'm moving the official curl web page to http://curl.haxx.nu. I think it
will make it easier to remember as it is a lot shorter and less cryptic.
The old one still works and shows the same info.
Daniel (11 August 1999)
- Albert Chin-A-Young mailed me another correction for NROFF in the
configure.in that is supposed to be better for IRIX users.
Daniel (10 August 1999)
- Albert Chin-A-Young helped me with some stupid Makefile things, as well as
some fiddling with the getdate.c stuff that he had problems with under
HP-UX v10. getdate.y will now be compiled into getdate.c if the appropriate
yacc or bison is found by the configure script. Since this is slightly new,
we need to test the output getdate.c with win32 systems to make sure it
still compiles there.
Daniel (5 August 1999)
- I've just setup a new mailing list with the intention to keep discussions
around libcurl development in it. I mainly expect it to be for thoughts and
brainstorming around a "next generation" library, rather than nitpicking
about the current implementation or details in the current libcurl.
To join our happy bunch of future-looking geeks, enter 'subscribe
<address>' in the body of a mail and send it to
libcurl-request@listserv.fts.frontec.se. Curl bug reports, the usual curl
talk and everything else should still be kept in this mailing list. I've
started to archive this mailing list and have put the libcurl web page at
www.fts.frontec.se/~dast/libcurl/.
- Stefan Kanthak contacted me regarding a few problems in the configure
script which he discovered when trying to make curl compile and build under
Siemens SINIX-Z V5.42B2004!
- Marcus Klein very accurately informed me that src/version.h was not present
in the CVS repository. Oh, how silly...
- Linus Nielsen rewrote the telnet:// part and now curl offers limited telnet
support. If you run curl like 'curl telnet://host' you'll get all output on
the screen and curl will read input from stdin. You'll be able to login and
run commands etc, but since the output is buffered, expect to get a little
weird output.
This is still in its infancy and it might get changed. We need your
feed-back and input in how this is best done.
WIN32 NOTE: I bet we'll get problems when trying to compile the current
lib/telnet.c on win32, but I think we can sort them out in time.
- David Sanderson reported that FORCE_ALLOCA_H or HAVE_ALLOCA_H must be
defined for getdate.c to compile properly on HP-UX 11.0. I updated the
configure script to check for alloca.h which should make it.
Daniel (4 August 1999)
- I finally got to understand Marcus Klein's ftp download resume problem,
which turns out to be due to different outputs from different ftp
servers. It makes ftp download resuming a little trickier, but I've made
some modifications I really believe will work for most ftp servers and I do
hope you report if you have problems with this!
- Added text about file transfer resuming to README.curl.
Daniel (2 August 1999)
- Applied a progress-bar patch from Lars J. Aas. It offers
a new styled progress bar enabled with -#/--progress-bar.
T. Yamada <tai at imasy.or.jp> (30 July 1999)
- It breaks with segfault when 1) curl is using .netrc to obtain
username/password (option '-n'), and 2) is automatically redirected to
another location (option '-L').
There is a small bug in lib/url.c (block starting from line 641), which
tries to take out username/password from user- supplied command-line
argument ('-u' option). This block is never executed on first attempt since
CONF_USERPWD bit isn't set at first, but curl later turns it on when it
checks for CONF_NETRC bit. So when curl tries to redo everything due to
redirection, it segfaults trying to access *data->userpwd.
Version 5.9.1
Daniel (30 July 1999)
- Steve Walch pointed out that there is a memory leak in the formdata
functions. I added a FormFree() function that is now used and supposed to
correct this flaw.
- Mark Wotton reported:
'curl -L https://www.cwa.com.au/' core dumps. I managed to cure this by
correcting the cleanup procedure. The bug seems to be gone with my OpenSSL
0.9.2b, although still occurs when I run the ~100 years old SSLeay 0.8.0. I
don't know whether it is curl or SSLeay that is to blame for that.
- Marcus Klein:
Reported an FTP upload resume bug that I really can't repeat nor understand.
I leave it here so that it won't be forgotten.
Daniel (29 July 1999)
- Costya Shulyupin suggested support for longer URLs when following Location:
and I could only agree and fix it!
- Leigh Purdie found a problem in the upload/POST department. It turned out
that http.c accidentaly cleared the pointer instead of the byte counter
when supposed to.
- Costya Shulyupin pointed out a problem with port numbers and Location:. If
you had a server at a non-standard port that redirected to an URL using a
standard port number, curl still used that first port number.
- Ralph Beckmann pointed out a problem when using both CONF_FOLLOWLOCATION
and CONF_FAILONERROR simultaneously. Since the CONF_FAILONERROR exits on
the 302-code that the follow location header outputs it will never show any
html on location: pages. I have now made it look for >=400 codes if
CONF_FOLLOWLOCATION is set.
- 'struct slist' is now renamed to 'struct curl_slist' (as suggested by Ralph
Beckmann).
- Joshua Swink and Rick Welykochy were the first to point out to me that the
latest OpenSSL package now have moved the standard include path. It is now
in /usr/local/ssl/include/openssl and I have now modified the --enable-ssl
option for the configure script to use that as the primary path, and I
leave the former path too to work with older packages of OpenSSL too.
Daniel (9 June 1999)
- I finally understood the IRIX problem and now it seem to compile on it!
I am gonna remove those #define strcasecmp() things once and for all now.
Daniel (4 June 1999)
- I adjusted the FTP reply 227 parser to make the PASV command work better
with more ftp servers. Appearantly the Roxen Challanger server replied
something curl 5.9 could deal with! :-( Reported by Ashley Reid-Montanaro
and Mark Butler brought a solution for it.
Daniel (26 May 1999)
- Rearranged. README is new, the old one is now README.curl and I added a
README.libcurl with text I got from Ralph Beckmann.
- I also updated the INSTALL text.
Daniel (25 May 1999)
- David Jonathan Lowsky correctly pointed out that curl didn't properly deal
with form posting where the variable shouldn't have any content, as in curl
-F "form=" www.site.com. It was now fixed.
Version 5.9
Daniel (22 May 1999)
- I've got a bug report from Aaron Scarisbrick in which he states he has some
problems with -L under FreeBSD 3.0. I have previously got another bug
report from Stefan Grether which points at an error with similar sympthoms
when using win32. I made the allocation of the new url string a bit faster
and different, don't know if it actually improves anything though...
Daniel (20 May 1999)
- Made the cookie parser deal with CRLF newlines too.
Daniel (19 May 1999)
- Download() didn't properly deal with failing return codes from the sread()
function. Adam Coyne found the problem in the win32 version, and Troy Engel
helped me out isolating it.
Daniel (16 May 1999)
- Richard Adams pointed out a bug I introduced in 5.8. --dump-header doesn't
work anymore! :-/ I fixed it now.
- After a suggestion by Joshua Swink I added -S / --show-error to force curl
to display the error message in case of an error, even if -s/--silent was
used.
Daniel (10 May 1999)
- I moved the stuff concerning HTTP, DICT and TELNET it their own source
files now. It is a beginning on my clean-up of the sources to make them
layer all those protocols better to enable more to be added easier in the
future!
- Leon Breedt sent me some files I've not put into the main curl
archive. They're for creating the Debian package thingie. He also sent me a
debian package that I've made available for download at the web page
Daniel (9 May 1999)
- Made it compile on cygwin too.
Troy Engel (7 May 1999)
- Brought a series of patches to allow curl to compile smoothly on MSVC++ 6
again!
Daniel (6 May 1999)
- I changed the #ifdef HAVE_STRFTIME placement for the -z code so that it
will be easier to discover systems that don't have that function and thus
can't use -z successfully. Made the strftime() get used if WIN32 is defined
too.
Version 5.8
Daniel (5 May 1999)
- I've had it with this autoconf/automake mess. It seems to work allright
for most people who don't have automake installed, but for those who have
there are problems all over.
I've got like five different bug reports on this only the last
week... Claudio Neves and Federico Bianchi and root <duggerj001 at
hawaii.rr.com> are some of them reporting this.
Currently, I have no really good fix since I want to use automake myself to
generate the Makefile.in files. I've found out that the @SHELL@-problems
can often be fixed by manually invoking 'automake' in the archive root
before you run ./configure... I've hacked my maketgz script now to fiddle
a bit with this and my tests seem to work better than before at least!
Daniel (4 May 1999)
- mkhelp.pl has been doing badly lately. I corrected a case problem in
the regexes.
- I've now remade the -o option to not touch the file unless it needs to.
I had to do this to make -z option really fine, since now you can make a
curl fetch and use a local copy's time when downloading to that file, as
in:
curl -z dump -o dump remote.site.com/file.html
This will only get the file if the remote one is newer than the local.
I'm aware that this alters previous behaviour a little. Some scripts out
there may depend on that the file is always touched...
- Corrected a bug in the SSLv2/v3 selection.
- Felix von Leitner requested that curl should be able to send
"If-Modified-Since" headers, which indeed is a fair idea. I implemented it
right away! Try -z <expression> where expression is a full GNU date
expression or a file name to get the date from!
Stephan Lagerholm (30 Apr 1999)
- Pointed out a problem with the src/Makefile for FreeBSD. The RM variable
isn't set and causes the make to fail.
Daniel (26 April 1999)
- Am I silly or what? Irving Wolfe pointed out to me that the curl version
number was not set properly. Hasn't been since 5.6. This was due to a bug
in my maketgz script!
David Eriksson (25 Apr 1999)
- Found a bug in cookies.c that made it crash at times.
Version 5.7.1
Doug Kaufman (23 Apr 1999)
- Brought two sunos 4 fixes. One of them being the hostip.c fix mentioned
below and the other one a correction in include/stdcheaders.h
- Added a paragraph about compiling with the US-version of openssl to the
INSTALL file.
Daniel
- New mailing list address. Info updated on the web page as well as in the
README file
Greg Onufer (20 Apr 1999)
- hostip.c didn't compile properly on SunOS 5.5.1.
It needs an #include <sys/types.h>
Version 5.7
Daniel (Apr 20 1999)
- Decided to upload a non-beta version right now!
- Made curl support any-length HTTP headers. The destination buffer is now
simply enlarged every time it turns out to be too small!
- Added the FAQ file to the archive. Still a bit smallish, but it is a
start.
Eric Thelin (15 Apr 1999)
- Made -D accept '-' instead of filename to write to stdout.
Version 5.6.3beta
Daniel (Apr 12 1999)
- Changed two #ifdef WIN32 to better #ifdef <errorcode> when connect()ing
in url.c and ftp.c. Makes cygwin32 deal with them better too. We should
try to get some decent win32-replacement there. Anyone?
- The old -3/--crlf option is now ONLY --crlf!
- I changed the "SSL fix" to a more lame one, but that doesn't remove as
much functionality. Now I've enabled the lib to select what SSL version it
should try first. Appearantly some older SSL-servers don't like when you
talk v3 with them so you need to be able to force curl to talk v2 from the
start. The fix dated April 6 and posted on the mailing list forced curl to
use v2 at all times using a modern OpenSSL version, but we don't really
want such a crippled solution.
- Marc Boucher sent me a patch that corrected a math error for the
"Curr.Speed" progress meter.
- Eric Thelin sent me a patch that enables '-K -' to read a config file from
stdin.
- I found out we didn't close the file properly before so I added it!
Daniel (Apr 9 1999)
- Yu Xin pointed out a problem with ftp download resume. It didn't work at
all! ;-O
Daniel (Apr 6 1999)
- Corrected the version string part generated for the SSL version.
- I found a way to make some other SSL page work with openssl 0.9.1+ that
previously didn't (ssleay 0.8.0 works with it though!). Trying to get
some real info from the OpenSSL guys to see how I should do to behave the
best way. SSLeay 0.8.0 shouldn't be that much in use anyway these days!
Version 5.6.2beta
Daniel (Apr 4 1999)
- Finally have curl more cookie "aware". Now read carefully. This is how
it works.
To make curl read cookies from an already existing file, in plain header-
format (like from the headers of a previous fetch) invoke curl with the
-b flag like:
curl -b file http://site/foo.html
Curl will then use all cookies it finds matching. The old style that sets
a single cookie with -b is still supported and is used if the string
following -b includes a '=' letter, as in "-b name=daniel".
To make curl read the cookies sent in combination with a location: (which
sites often do) point curl to read a non-existing file at first (i.e
to start with no existing cookies), like:
curl -b nowhere http://site/setcookieandrelocate.html
- Added a paragraph in the TODO file about the SSL problems recently
reported. Evidently, some kind of SSL-problem curl may need to address.
- Better "Location:" following.
Douglas E. Wegscheid (Tue, 30 Mar 1999)
- A subsecond display patch.
Daniel (Mar 14 1999)
- I've separated the version number of libcurl and curl now. To make
things a little easier, I decided to start the curl numbering from
5.6 and the former version number known as "curl" is now the one
set for libcurl.
- Removed the 'enable-no-pass' from configure, I doubt anyone wanted
that.
- Made lots of tiny adjustments to compile smoothly with cygwin under
win32. It's a killer for porting this to win32, bye bye VC++! ;-)
Compiles and builds out-of-the-box now. See the new wordings in
INSTALL for details.
- Beginning experiments with downloading multiple document from a http
server while remaining connected.
Version 5.6beta
Daniel (Mar 13 1999)
- Since I've changed so much, I thought I'd just go ahead and implement the
suggestion from Douglas E. Wegscheid. -D or --dump-header is now storing
HTTP headers separately in the specified file.
- Added new text to INSTALL on what to do to build this on win32 now.
- Aaargh. I had to take a step back and prefix the shared #include files
in the sources with "../include/" to please VC++...
Daniel (Mar 12 1999)
- Split the url.c source into many tiny sources for better readability
and smaller size.
Daniel (Mar 11 1999)
- Started to change stuff for a move to make libcurl and a more separate
curl application that uses the libcurl. Made the libcurl sources into
the new lib directory while the curl application will remain in src as
before. New makefiles, adjusted configure script and so.
libcurl.a built quickly and easily. I better make a better interface to
the lib functions though.
The new root dir include/ is supposed to contain the public information
about the new libcurl. It is a little ugly so far :-)
Daniel (Mar 1 1999)
- Todd Kaufmann sent me a good link to Netscape's cookie spec as well as the
info that RFC 2109 specifies how to use them. The link is now in the
README and the RFC in the RESOURCES.
Daniel (Feb 23 1999)
- Finally made configure accept --with-ssl to look for SSL libs and includes
in the "standard" place /usr/local/ssl...
Daniel (Feb 22 1999)
- Verified that curl linked fine with OpenSSL 0.9.1c which seems to be
the most recent.
Henri Gomez (Fri Feb 5 1999)
- Sent in an updated curl-ssl.spec. I still miss the script that builds an
RPM automatically...
Version 5.5.1
Mark Butler (27 Jan 1999)
- Corrected problems in Download().
Danitel Stenberg (25 Jan 1999)
- Jeremie Petit pointed out a few flaws in the source that prevented it from
compile warning free with the native compiler under Digital Unix v4.0d.
Version 5.5
Daniel Stenberg (15 Jan 1999)
- Added Bjorns small text to the README about the DICT protocol.
Daniel Stenberg (11 Jan 1999)
- <jswink at softcom.net> reported about the win32-versioin: "Doesn't use
ALL_PROXY environment variable". Turned out to be because of the static-
buffer nature of the win32 environment variable calls!
Bjorn Reese (10 Jan 1999)
- I have attached a simple addition for the DICT protocol (RFC 2229).
It performs dictionary lookups. The output still needs to be better
formatted.
To test it try (the exact format, and more examples are described in
the RFC)
dict://dict.org/m:hello
dict://dict.org/m:hello::soundex
Vicente Garcia (10 Jan 1999)
- Corrected the progress meter for files larger than 20MB.
Daniel Stenberg (7 Jan 1999)
- Corrected the -t and -T help texts. They claimed to be FTP only.
Version 5.4
Daniel Stenberg
(7 Jan 1999)
- Irving Wolfe reported that curl -s didn't always supress the progress
reporting. It was the form post that autoamtically always switched it on
again. This is now corrected!
(4 Jan 1999)
- Andreas Kostyrka suggested I'd add PUT and he helped me out to test it. If
you use -t or -T now on a http or https server, PUT will be used for file
upload.
I removed the former use of -T with HTTP. I doubt anyone ever really used
that.
(4 Jan 1999)
- Erik Jacobsen found a width bug in the mprintf() function. I corrected it
now.
(4 Jan 1999)
- As John V. Chow pointed out to me, curl accepted very limited URL sizes. It
should now accept path parts that are up to at least 4096 bytes.
- Somehow I screwed up when applying the AIX fix from Gilbert Ramirez, so
I redid that now.
Version 5.3a (win32 only) Version 5.3a (win32 only)
Troy Engel Troy Engel

835
CHANGES.1999 Normal file
View File

@@ -0,0 +1,835 @@
Daniel (28 December 1999):
- Tim Verhoeven correctly identified that curl
doesn't support URL formatted file names when getting ftp. Now, there's a
problem with getting very weird file names off FTP servers. RFC 959 defines
that the file name syntax to use should be the same as in the native OS of
the server. Since we don't know the peer server system we currently just
translate the URL syntax into plain letters. It is still better and with
the solaris 2.6-supplied ftp server it works with spaces in the file names.
Daniel (27 December 1999):
- When curl parsed cookies straight off a remote site, it corrupted the input
data, which, if the downloaded headers were stored made very odd characters
in the saved data. Correctly identified and reported by Paul Harrington.
Daniel (13 December 1999):
- General cleanups in the library interface. There had been some bad kludges
added during times of stress and I did my best to clean them off. It was
both regarding the lib API as well as include file confusions.
Daniel (3 December 1999):
- A small --stderr bug was reported by Eetu Ojanen...
- who also brought the suggestion of extending the -X flag to ftp list as
well. So, now it is and the long option is now --request instead. It is
only for ftp list for now (and the former http stuff too of course).
Lars J. Aas (24 November 1999):
- Patched curl to compile and build under BeOS. Doesn't work yet though!
- Corrected the Makefile.am files to allow putting object files in
different directories than the sources.
Version 6.3.1
Daniel (23 November 1999):
- I've had this major disk crash. My good old trust-worthy source disk died
along with the machine that hosted it. Thank goodness most of all the
things I've done are either backed up elsewhere or stored in this CVS
server!
- Michael S. Steuer pointed out a bug in the -F handling
that made curl hang if you posted an empty variable such as '-F name='. It
was one of those old bugs that never have worked properly...
- Jason Baietto pointed out a general flaw in the HTTP
download. Curl didn't complain if it was prematurely aborted before the
entire download was completed. It does now.
Daniel (19 November 1999):
- Chris Maltby very accurately criticized the lack of
return code checks on the fwrite() calls. I did a thorough check for all
occurrences and corrected this.
Daniel (17 November 1999):
- Paul Harrington pointed out that the -m/--max-time option
doesn't work for the slow system calls like gethostbyname()... I don't have
any good fix yet, just a slightly less bad one that makes curl exit hard
when the timeout is reached.
- Bjorn Reese helped me point out a possible problem that might be the reason
why Thomas Hurst experience problems in his Amiga version.
Daniel (12 November 1999):
- I found a crash in the new cookie file parser. It crashed when you gave
a plain http header file as input...
Version 6.3
Daniel (10 November 1999):
- I kind of found out that the HTTP time-conditional GETs (-z) aren't always
respected by the web server and the document is therefore sent in whole
again, even though it doesn't match the requested condition. After reading
section 13.3.4 of RFC 2616, I think I'm doing the right thing now when I do
my own check as well. If curl thinks the condition isn't met, the transfer
is aborted prematurely (after all the headers have been received).
- After comments from Robert Linden I also rewrote some parts of the man page
to better describe how the -F works.
- Michael Anti put up a new curl download mirror in
China: http://www.pshowing.com/curl/
- I added the list of download mirrors to the README file
- I did add more explanations to the man page
Daniel (8 November 1999):
- I made the -b/--cookie option capable of reading netscape formatted cookie
files as well as normal http-header files. It should be able to
transparently figure out what kind of file it got as input.
Daniel (29 October 1999):
- Another one of Sebastiaan van Erk's ideas (that has been requested before
but I seem to have forgotten who it was), is to add support for ranges in
FTP downloads. As usual, one request is just a request, when they're two
it is a demand. I've added simple support for X-Y style fetches. X has to
be the lower number, though you may omit one of the numbers. Use the -r/
--range switch (previously HTTP-only).
- Sebastiaan van Erk suggested that curl should be
able to show the file size of a specified file. I think this is a splendid
idea and the -I flag is now working for FTP. It displays the file size in
this manner:
Content-Length: XXXX
As it resembles normal headers, and leaves us the opportunity to add more
info in that display if we can come up with more in the future! It also
makes sense since if you access ftp through a HTTP proxy, you'd get the
file size the same way.
I changed the order of the QUOTE command executions. They're now executed
just after the login and before any other command. I made this to enable
quote commands to run before the -I stuff is done too.
- I found out that -D/--dump-header and -V/--version weren't documented in
the man page.
- Many HTTP/1.1 servers do not support ranges. Don't ask me why. I did add
some text about this in the man page for the range option. The thread in
the mailing list that started this was initiated by Michael Anti.
- I get reports about nroff crashes on solaris 2.6+ when displaying the curl
man page. Switch to gnroff instead, it is reported to work(!). Adam Barclay
reported and brought the suggestion.
- In a dialogue with Johannes G. Kristinsson we came
up with the idea to let -H/--header specified headers replace the
internally generated headers, if you happened to select to add a header
that curl normally uses by itself. The advantage with this is not entirely
obvious, but in Johannes' case it means that he can use another Host: than
the one curl would set.
Daniel (27 October 1999):
- Jongki Suwandi brought a nice patch for (yet another) crash when following
a location:. This time you had to follow a https:// server's redirect to
get the core.
Version 6.2
Daniel (21 October 1999):
- I think I managed to remove the suspicious (nil) that has been seen just
before the "Host:" in HTTP requests when -v was used.
- I found out that if you followed a location: when using a proxy, without
having specified http:// in the URL, the protocol part was added once again
when moving to the next URL! (The protocol part has to be added to the
URL when going through a proxy since it has no protocol-guessing system
such as curl has.)
- Benjamin Ritcey reported a core dump under solaris 2.6
with OpenSSL 0.9.4. It turned out this was due to a bad free() in main.c
that occurred after the download was done and completed.
- Benjamin found ftp downloads to show the first line of the download meter
to get written twice, and I removed that problem. It was introduced with
the multiple URL support.
- Dan Zitter correctly pointed out that curl 6.1 and earlier versions didn't
honor RFC 2616 chapter 4 section 2, "Message Headers": "...Field names are
case-insensitive..." HTTP header parsing assumed a certain casing. Dan
also provided me with a patch that corrected this, which I took the liberty
of editing slightly.
- Dan Zitter also provided a nice patch for config.guess to better recognize
the Mac OS X
- Dan also corrected a minor problem in the lib/Makefile that caused linking
to fail on OS X.
Daniel (19 October 1999):
- Len Marinaccio came up with some problems with curl. Since Windows has a
crippled shell, it can't redirect stderr and that causes trouble. I added
--stderr today which allows the user to redirect the stderr stream to a
file or stdout.
Daniel (18 October 1999):
- The configure script now understands the '--without-ssl' flag, which now
totally disable SSL/https support. Previously it wasn't possible to force
the configure script to leave SSL alone. The previous functionality has
been retained. Troy Engel helped test this new one.
Version 6.1
Daniel (17 October 1999):
- I ifdef'ed or commented all the zlib stuff in the sources and configure
script. It turned out we needed to mock more with zlib than I initially
thought, to make it capable of downloading compressed HTTP documents and
uncompress them on the fly. I didn't mean the zlib parts of curl to become
more than minor so this means I halt the zlib expedition for now and wait
until someone either writes the code or zlib gets updated and better
adjusted for this kind of usage. I won't get into details here, but a
short a summary is suitable:
- zlib can't automatically detect whether to use zlib or gzip
decompression methods.
- zlib is very neat for reading gzipped files from a file descriptor,
although not as nice for reading buffer-based data such as we would
want it.
- there are still some problems with the win32 version when reading from
a file descriptor if that is a socket
Daniel (14 October 1999):
- Moved the (external) include files for libcurl into a subdirectory named
curl and adjusted all #include lines to use <curl/XXXX> to maintain a
better name space and control of the headers. This has been requested.
Daniel (12 October 1999):
- I modified the 'maketgz' script to perform a 'make' too before a release
archive is put together in an attempt to make the time stamps better and
hopefully avoid the double configure-running that use to occur.
Daniel (11 October 1999):
- Applied J<>rn's patches that fixes zlib for mingw32 compiles as well as
some other missing zlib #ifdef and more text on the multiple URL docs in
the man page.
Version 6.1beta
Daniel (6 October 1999):
- Douglas E. Wegscheid sent me a patch that made the exact same thing as I
just made: the -d switch is now capable of reading post data from a named
file or stdin. Use it similarly to the -F. To read the post data from a
given file:
curl -d @path/to/filename www.postsite.com
or let curl read it out from stdin:
curl -d @- www.postit.com
J<>rn Hartroth (3 October 1999):
- Brought some more patches for multiple URL functionality. The MIME
separation ideas are almost scrapped now, and a custom separator is being
used instead. This is still compile-time "flagged".
Daniel
- Updated curl.1 with multiple URL info.
Daniel (30 September 1999):
- Felix von Leitner brought openssl-check fixes for configure.in to work
out-of-the-box when the openssl files are installed in the system default
dirs.
Daniel (28 September 1999)
- Added libz functionality. This should enable decompressing gzip, compress
or deflate encoding HTTP documents. It also makes curl send an accept that
it accepts that kind of encoding. Compressed contents usually shortens
download time. I *need* someone to tell me a site that uses compressed HTTP
documents so that I can test this out properly.
- As a result of the adding of zlib awareness, I changed the version string
a little. I plan to add openldap version reporting in there too.
Daniel (17 September 1999)
- Made the -F option allow stdin when specifying files. By using '-' instead
of file name, the data will be read from stdin.
Version 6.0
Daniel (13 September 1999)
- Added -X/--http-request <request> to enable any HTTP command to be sent.
Do not that your server has to support the exact string you enter. This
should possibly a string like DELETE or TRACE.
- Applied Douglas' mingw32-fixes for the makefiles.
Daniel (10 September 1999)
- Douglas E. Wegscheid pointed out a problem. Curl didn't check the FTP
servers return code properly after the --quote commands were issued. It
took anything non 200 as an error, when all 2XX codes should be accepted as
OK.
- Sending cookies to the same site in multiple lines like curl used to do
turned out to be bad and breaking the cookie specs. Curl now sends all
cookies on a single Cookie: line. Curl is not yet RFC 2109 compliant, but I
doubt that many servers do use that syntax (yet).
Daniel (8 September 1999)
- J<>rn helped me make sure it still compiles nicely with mingw32 under win32.
Daniel (7 September 1999)
- FTP upload through proxy is now turned into a HTTP PUT. Requested by
Stefan Kanthak.
- Added the ldap files to the .m32 makefile.
Daniel (3 September 1999)
- Made cookie matching work while using HTTP proxy.
Bjorn Reese (31 August 1999)
- Passed his ldap:// patch. Note that this requires the openldap shared
library to be installed and that LD_LIBRARY_PATH points to the
directory where the lib will be found when curl is run with a
ldap:// URL.
J<>rn Hartroth (31 August 1999)
- Made the Mingw32 makefiles into single files.
- Made file:// work for Win32. The same code is now used for unix as well for
performance reasons.
Douglas E. Wegscheid (30 August 1999)
- Patched the Mingw32 makefiles for SSL builds.
Matthew Clarke (30 August 1999)
- Made a cool patch for configure.in to allow --with-ssl to specify the
root dir of the openssl installation, as in
./configure --with-ssl=/usr/ssl_here
- Corrected the 'reconf' script to work better with some shells.
J<>rn Hartroth (26 August 1999)
- Fixed the Mingw32 makefiles in lib/ and corrected the file.c for win32
compiles.
Version 5.11
Daniel (25 August 1999)
- John Weismiller pointed out a bug in the header-line
realloc() system in download.c.
- I added lib/file.[ch] to offer a first, simple, file:// support. It
probably won't do much good on win32 system at this point, but I see it
as a start.
- Made the release archives get a Makefile in the root dir, which can be
used to start the compiling/building process easier. I haven't really
changed any INSTALL text yet, I wanted to get some feed-back on this
first.
Daniel (17 August 1999)
- Another Location: bug. Curl didn't do proper relative locations if the
original URL had cgi-parameters that contained a slash. Nusu's page
again.
- Corrected the NO_PROXY usage. It is a list of substrings that if one of
them matches the tail of the host name it should connect to, curl should
not use a proxy to connect there. Pointed out to me by Douglas
E. Wegscheid. I also changed the README text a little regarding this.
Daniel (16 August 1999)
- Fixed a memory bug with http-servers that sent Location: to a Location:
page. Nusu's page showed this too.
- Made cookies work a lot better. Setting the same cookie name several times
used to add more cookies instead of replacing the former one which it
should've. Nusu <nus at intergorj.ro> brought me an URL that made this
painfully visible...
Troy (15 August 1999)
- Brought new .spec files as well as a patch for configure.in that lets the
configure script find the openssl files better, even when the include
files are in /usr/include/openssl
Version 5.10
Daniel (13 August 1999)
- SSL_CTX_set_default_passwd_cb() has been modified in the 0.9.4 version of
OpenSSL. Now why couldn't they simply add a *new* function instead of
modifying the parameters of an already existing function? This way, we get
a compiler warning if compiling with 0.9.4 but not with earlier. So, I had
to come up with a #if construction that deals with this...
- Made curl output the SSL version number get displayed properly with 0.9.4.
Troy (12 August 1999)
- Added MingW32 (GCC-2.95) support under Win32. The INSTALL file was also
a bit rearranged.
Daniel (12 August 1999)
- I had to copy a good <arpa/telnet.h> include file into the curl source
tree to enable the silly win32 systems to compile. The distribution rights
allows us to do that as long as the file remains unmodified.
- I corrected a few minor things that made the compiler complain when
-Wall -pedantic was used.
- I'm moving the official curl web page to http://curl.haxx.nu. I think it
will make it easier to remember as it is a lot shorter and less cryptic.
The old one still works and shows the same info.
Daniel (11 August 1999)
- Albert Chin-A-Young mailed me another correction for NROFF in the
configure.in that is supposed to be better for IRIX users.
Daniel (10 August 1999)
- Albert Chin-A-Young helped me with some stupid Makefile things, as well as
some fiddling with the getdate.c stuff that he had problems with under
HP-UX v10. getdate.y will now be compiled into getdate.c if the appropriate
yacc or bison is found by the configure script. Since this is slightly new,
we need to test the output getdate.c with win32 systems to make sure it
still compiles there.
Daniel (5 August 1999)
- I've just setup a new mailing list with the intention to keep discussions
around libcurl development in it. I mainly expect it to be for thoughts and
brainstorming around a "next generation" library, rather than nitpicking
about the current implementation or details in the current libcurl.
To join our happy bunch of future-looking geeks, enter 'subscribe
<address>' in the body of a mail and send it to
libcurl-request@listserv.fts.frontec.se. Curl bug reports, the usual curl
talk and everything else should still be kept in this mailing list. I've
started to archive this mailing list and have put the libcurl web page at
www.fts.frontec.se/~dast/libcurl/.
- Stefan Kanthak contacted me regarding a few problems in the configure
script which he discovered when trying to make curl compile and build under
Siemens SINIX-Z V5.42B2004!
- Marcus Klein very accurately informed me that src/version.h was not present
in the CVS repository. Oh, how silly...
- Linus Nielsen rewrote the telnet:// part and now curl offers limited telnet
support. If you run curl like 'curl telnet://host' you'll get all output on
the screen and curl will read input from stdin. You'll be able to login and
run commands etc, but since the output is buffered, expect to get a little
weird output.
This is still in its infancy and it might get changed. We need your
feed-back and input in how this is best done.
WIN32 NOTE: I bet we'll get problems when trying to compile the current
lib/telnet.c on win32, but I think we can sort them out in time.
- David Sanderson reported that FORCE_ALLOCA_H or HAVE_ALLOCA_H must be
defined for getdate.c to compile properly on HP-UX 11.0. I updated the
configure script to check for alloca.h which should make it.
Daniel (4 August 1999)
- I finally got to understand Marcus Klein's ftp download resume problem,
which turns out to be due to different outputs from different ftp
servers. It makes ftp download resuming a little trickier, but I've made
some modifications I really believe will work for most ftp servers and I do
hope you report if you have problems with this!
- Added text about file transfer resuming to README.curl.
Daniel (2 August 1999)
- Applied a progress-bar patch from Lars J. Aas. It offers
a new styled progress bar enabled with -#/--progress-bar.
T. Yamada <tai at imasy.or.jp> (30 July 1999)
- It breaks with segfault when 1) curl is using .netrc to obtain
username/password (option '-n'), and 2) is automatically redirected to
another location (option '-L').
There is a small bug in lib/url.c (block starting from line 641), which
tries to take out username/password from user- supplied command-line
argument ('-u' option). This block is never executed on first attempt since
CONF_USERPWD bit isn't set at first, but curl later turns it on when it
checks for CONF_NETRC bit. So when curl tries to redo everything due to
redirection, it segfaults trying to access *data->userpwd.
Version 5.9.1
Daniel (30 July 1999)
- Steve Walch pointed out that there is a memory leak in the formdata
functions. I added a FormFree() function that is now used and supposed to
correct this flaw.
- Mark Wotton reported:
'curl -L https://www.cwa.com.au/' core dumps. I managed to cure this by
correcting the cleanup procedure. The bug seems to be gone with my OpenSSL
0.9.2b, although still occurs when I run the ~100 years old SSLeay 0.8.0. I
don't know whether it is curl or SSLeay that is to blame for that.
- Marcus Klein:
Reported an FTP upload resume bug that I really can't repeat nor understand.
I leave it here so that it won't be forgotten.
Daniel (29 July 1999)
- Costya Shulyupin suggested support for longer URLs when following Location:
and I could only agree and fix it!
- Leigh Purdie found a problem in the upload/POST department. It turned out
that http.c accidentaly cleared the pointer instead of the byte counter
when supposed to.
- Costya Shulyupin pointed out a problem with port numbers and Location:. If
you had a server at a non-standard port that redirected to an URL using a
standard port number, curl still used that first port number.
- Ralph Beckmann pointed out a problem when using both CONF_FOLLOWLOCATION
and CONF_FAILONERROR simultaneously. Since the CONF_FAILONERROR exits on
the 302-code that the follow location header outputs it will never show any
html on location: pages. I have now made it look for >=400 codes if
CONF_FOLLOWLOCATION is set.
- 'struct slist' is now renamed to 'struct curl_slist' (as suggested by Ralph
Beckmann).
- Joshua Swink and Rick Welykochy were the first to point out to me that the
latest OpenSSL package now have moved the standard include path. It is now
in /usr/local/ssl/include/openssl and I have now modified the --enable-ssl
option for the configure script to use that as the primary path, and I
leave the former path too to work with older packages of OpenSSL too.
Daniel (9 June 1999)
- I finally understood the IRIX problem and now it seem to compile on it!
I am gonna remove those #define strcasecmp() things once and for all now.
Daniel (4 June 1999)
- I adjusted the FTP reply 227 parser to make the PASV command work better
with more ftp servers. Appearantly the Roxen Challanger server replied
something curl 5.9 could deal with! :-( Reported by Ashley Reid-Montanaro
and Mark Butler brought a solution for it.
Daniel (26 May 1999)
- Rearranged. README is new, the old one is now README.curl and I added a
README.libcurl with text I got from Ralph Beckmann.
- I also updated the INSTALL text.
Daniel (25 May 1999)
- David Jonathan Lowsky correctly pointed out that curl didn't properly deal
with form posting where the variable shouldn't have any content, as in curl
-F "form=" www.site.com. It was now fixed.
Version 5.9
Daniel (22 May 1999)
- I've got a bug report from Aaron Scarisbrick in which he states he has some
problems with -L under FreeBSD 3.0. I have previously got another bug
report from Stefan Grether which points at an error with similar sympthoms
when using win32. I made the allocation of the new url string a bit faster
and different, don't know if it actually improves anything though...
Daniel (20 May 1999)
- Made the cookie parser deal with CRLF newlines too.
Daniel (19 May 1999)
- Download() didn't properly deal with failing return codes from the sread()
function. Adam Coyne found the problem in the win32 version, and Troy Engel
helped me out isolating it.
Daniel (16 May 1999)
- Richard Adams pointed out a bug I introduced in 5.8. --dump-header doesn't
work anymore! :-/ I fixed it now.
- After a suggestion by Joshua Swink I added -S / --show-error to force curl
to display the error message in case of an error, even if -s/--silent was
used.
Daniel (10 May 1999)
- I moved the stuff concerning HTTP, DICT and TELNET it their own source
files now. It is a beginning on my clean-up of the sources to make them
layer all those protocols better to enable more to be added easier in the
future!
- Leon Breedt sent me some files I've not put into the main curl
archive. They're for creating the Debian package thingie. He also sent me a
debian package that I've made available for download at the web page
Daniel (9 May 1999)
- Made it compile on cygwin too.
Troy Engel (7 May 1999)
- Brought a series of patches to allow curl to compile smoothly on MSVC++ 6
again!
Daniel (6 May 1999)
- I changed the #ifdef HAVE_STRFTIME placement for the -z code so that it
will be easier to discover systems that don't have that function and thus
can't use -z successfully. Made the strftime() get used if WIN32 is defined
too.
Version 5.8
Daniel (5 May 1999)
- I've had it with this autoconf/automake mess. It seems to work allright
for most people who don't have automake installed, but for those who have
there are problems all over.
I've got like five different bug reports on this only the last
week... Claudio Neves and Federico Bianchi and root <duggerj001 at
hawaii.rr.com> are some of them reporting this.
Currently, I have no really good fix since I want to use automake myself to
generate the Makefile.in files. I've found out that the @SHELL@-problems
can often be fixed by manually invoking 'automake' in the archive root
before you run ./configure... I've hacked my maketgz script now to fiddle
a bit with this and my tests seem to work better than before at least!
Daniel (4 May 1999)
- mkhelp.pl has been doing badly lately. I corrected a case problem in
the regexes.
- I've now remade the -o option to not touch the file unless it needs to.
I had to do this to make -z option really fine, since now you can make a
curl fetch and use a local copy's time when downloading to that file, as
in:
curl -z dump -o dump remote.site.com/file.html
This will only get the file if the remote one is newer than the local.
I'm aware that this alters previous behaviour a little. Some scripts out
there may depend on that the file is always touched...
- Corrected a bug in the SSLv2/v3 selection.
- Felix von Leitner requested that curl should be able to send
"If-Modified-Since" headers, which indeed is a fair idea. I implemented it
right away! Try -z <expression> where expression is a full GNU date
expression or a file name to get the date from!
Stephan Lagerholm (30 Apr 1999)
- Pointed out a problem with the src/Makefile for FreeBSD. The RM variable
isn't set and causes the make to fail.
Daniel (26 April 1999)
- Am I silly or what? Irving Wolfe pointed out to me that the curl version
number was not set properly. Hasn't been since 5.6. This was due to a bug
in my maketgz script!
David Eriksson (25 Apr 1999)
- Found a bug in cookies.c that made it crash at times.
Version 5.7.1
Doug Kaufman (23 Apr 1999)
- Brought two sunos 4 fixes. One of them being the hostip.c fix mentioned
below and the other one a correction in include/stdcheaders.h
- Added a paragraph about compiling with the US-version of openssl to the
INSTALL file.
Daniel
- New mailing list address. Info updated on the web page as well as in the
README file
Greg Onufer (20 Apr 1999)
- hostip.c didn't compile properly on SunOS 5.5.1.
It needs an #include <sys/types.h>
Version 5.7
Daniel (Apr 20 1999)
- Decided to upload a non-beta version right now!
- Made curl support any-length HTTP headers. The destination buffer is now
simply enlarged every time it turns out to be too small!
- Added the FAQ file to the archive. Still a bit smallish, but it is a
start.
Eric Thelin (15 Apr 1999)
- Made -D accept '-' instead of filename to write to stdout.
Version 5.6.3beta
Daniel (Apr 12 1999)
- Changed two #ifdef WIN32 to better #ifdef <errorcode> when connect()ing
in url.c and ftp.c. Makes cygwin32 deal with them better too. We should
try to get some decent win32-replacement there. Anyone?
- The old -3/--crlf option is now ONLY --crlf!
- I changed the "SSL fix" to a more lame one, but that doesn't remove as
much functionality. Now I've enabled the lib to select what SSL version it
should try first. Appearantly some older SSL-servers don't like when you
talk v3 with them so you need to be able to force curl to talk v2 from the
start. The fix dated April 6 and posted on the mailing list forced curl to
use v2 at all times using a modern OpenSSL version, but we don't really
want such a crippled solution.
- Marc Boucher sent me a patch that corrected a math error for the
"Curr.Speed" progress meter.
- Eric Thelin sent me a patch that enables '-K -' to read a config file from
stdin.
- I found out we didn't close the file properly before so I added it!
Daniel (Apr 9 1999)
- Yu Xin pointed out a problem with ftp download resume. It didn't work at
all! ;-O
Daniel (Apr 6 1999)
- Corrected the version string part generated for the SSL version.
- I found a way to make some other SSL page work with openssl 0.9.1+ that
previously didn't (ssleay 0.8.0 works with it though!). Trying to get
some real info from the OpenSSL guys to see how I should do to behave the
best way. SSLeay 0.8.0 shouldn't be that much in use anyway these days!
Version 5.6.2beta
Daniel (Apr 4 1999)
- Finally have curl more cookie "aware". Now read carefully. This is how
it works.
To make curl read cookies from an already existing file, in plain header-
format (like from the headers of a previous fetch) invoke curl with the
-b flag like:
curl -b file http://site/foo.html
Curl will then use all cookies it finds matching. The old style that sets
a single cookie with -b is still supported and is used if the string
following -b includes a '=' letter, as in "-b name=daniel".
To make curl read the cookies sent in combination with a location: (which
sites often do) point curl to read a non-existing file at first (i.e
to start with no existing cookies), like:
curl -b nowhere http://site/setcookieandrelocate.html
- Added a paragraph in the TODO file about the SSL problems recently
reported. Evidently, some kind of SSL-problem curl may need to address.
- Better "Location:" following.
Douglas E. Wegscheid (Tue, 30 Mar 1999)
- A subsecond display patch.
Daniel (Mar 14 1999)
- I've separated the version number of libcurl and curl now. To make
things a little easier, I decided to start the curl numbering from
5.6 and the former version number known as "curl" is now the one
set for libcurl.
- Removed the 'enable-no-pass' from configure, I doubt anyone wanted
that.
- Made lots of tiny adjustments to compile smoothly with cygwin under
win32. It's a killer for porting this to win32, bye bye VC++! ;-)
Compiles and builds out-of-the-box now. See the new wordings in
INSTALL for details.
- Beginning experiments with downloading multiple document from a http
server while remaining connected.
Version 5.6beta
Daniel (Mar 13 1999)
- Since I've changed so much, I thought I'd just go ahead and implement the
suggestion from Douglas E. Wegscheid. -D or --dump-header is now storing
HTTP headers separately in the specified file.
- Added new text to INSTALL on what to do to build this on win32 now.
- Aaargh. I had to take a step back and prefix the shared #include files
in the sources with "../include/" to please VC++...
Daniel (Mar 12 1999)
- Split the url.c source into many tiny sources for better readability
and smaller size.
Daniel (Mar 11 1999)
- Started to change stuff for a move to make libcurl and a more separate
curl application that uses the libcurl. Made the libcurl sources into
the new lib directory while the curl application will remain in src as
before. New makefiles, adjusted configure script and so.
libcurl.a built quickly and easily. I better make a better interface to
the lib functions though.
The new root dir include/ is supposed to contain the public information
about the new libcurl. It is a little ugly so far :-)
Daniel (Mar 1 1999)
- Todd Kaufmann sent me a good link to Netscape's cookie spec as well as the
info that RFC 2109 specifies how to use them. The link is now in the
README and the RFC in the RESOURCES.
Daniel (Feb 23 1999)
- Finally made configure accept --with-ssl to look for SSL libs and includes
in the "standard" place /usr/local/ssl...
Daniel (Feb 22 1999)
- Verified that curl linked fine with OpenSSL 0.9.1c which seems to be
the most recent.
Henri Gomez (Fri Feb 5 1999)
- Sent in an updated curl-ssl.spec. I still miss the script that builds an
RPM automatically...
Version 5.5.1
Mark Butler (27 Jan 1999)
- Corrected problems in Download().
Danitel Stenberg (25 Jan 1999)
- Jeremie Petit pointed out a few flaws in the source that prevented it from
compile warning free with the native compiler under Digital Unix v4.0d.
Version 5.5
Daniel Stenberg (15 Jan 1999)
- Added Bjorns small text to the README about the DICT protocol.
Daniel Stenberg (11 Jan 1999)
- <jswink at softcom.net> reported about the win32-versioin: "Doesn't use
ALL_PROXY environment variable". Turned out to be because of the static-
buffer nature of the win32 environment variable calls!
Bjorn Reese (10 Jan 1999)
- I have attached a simple addition for the DICT protocol (RFC 2229).
It performs dictionary lookups. The output still needs to be better
formatted.
To test it try (the exact format, and more examples are described in
the RFC)
dict://dict.org/m:hello
dict://dict.org/m:hello::soundex
Vicente Garcia (10 Jan 1999)
- Corrected the progress meter for files larger than 20MB.
Daniel Stenberg (7 Jan 1999)
- Corrected the -t and -T help texts. They claimed to be FTP only.
Version 5.4
Daniel Stenberg
(7 Jan 1999)
- Irving Wolfe reported that curl -s didn't always supress the progress
reporting. It was the form post that autoamtically always switched it on
again. This is now corrected!
(4 Jan 1999)
- Andreas Kostyrka suggested I'd add PUT and he helped me out to test it. If
you use -t or -T now on a http or https server, PUT will be used for file
upload.
I removed the former use of -T with HTTP. I doubt anyone ever really used
that.
(4 Jan 1999)
- Erik Jacobsen found a width bug in the mprintf() function. I corrected it
now.
(4 Jan 1999)
- As John V. Chow pointed out to me, curl accepted very limited URL sizes. It
should now accept path parts that are up to at least 4096 bytes.
- Somehow I screwed up when applying the AIX fix from Gilbert Ramirez, so
I redid that now.

View File

@@ -10,14 +10,10 @@ This file is only present in the CVS - never in release archives. It contains
information about other files and things that the CVS repository keeps in its information about other files and things that the CVS repository keeps in its
inner sanctum. inner sanctum.
Use autoconf 2.50 and no earlier. Also, try having automake 1.5 and libtool Compile and build instructions follow below.
1.4.1 at least.
You will need perl to generate the src/hugehelp.c file. The file
src/hugehelp.c.cvs is a one-shot file that you can rename to src/hugehelp.c if
you really can't generate the true file yourself!
CHANGES.0 contains ancient changes. CHANGES.0 contains ancient changes.
CHANGES.$year contains changes for the particular year.
memanalyze.pl is for analyzing the output generated by curl if -DMALLOCDEBUG memanalyze.pl is for analyzing the output generated by curl if -DMALLOCDEBUG
is used when compiling is used when compiling
@@ -26,12 +22,38 @@ you really can't generate the true file yourself!
Makefile.dist is included as the root Makefile in distribution archives Makefile.dist is included as the root Makefile in distribution archives
perl/contrib/ is a subdirectory with various perl scripts perl/ is a subdirectory with various perl scripts
java/ is a subdirectory with the Java interface to libcurl
To build after having extracted everything from CVS, do this: To build after having extracted everything from CVS, do this:
./buildconf ./buildconf
./configure ./configure
make make
REQUIREMENTS
You need the following software installed:
o autoconf 2.50 (or later)
o automake 1.5 (or later)
o libtool 1.4 (or later)
o GNU m4 (required by autoconf)
o nroff + perl (if you don't have nroff and perl and you for some reason
don't want to install them, you can rename the source file
src/hugehelp.c.cvs to src/hugehelp.c and avoid having to generate this
file. This will of course give you an older version of the file that isn't
up-to-date. That file was checked in once and won't be updated very
regularly.)
MAC OS X
For Mac OS X users, Guido Neitzer write down the following step-by-step guide:
1. Install fink (http://fink.sourceforge.net)
2. Update fink to the newest version (with the installed fink)
3. Install the latest version of autoconf, automake and m4 with fink
4. Install version 1.4.1 of libtool - you find it in the "unstable" section
(read the manual to see how to get unstable versions)
5. Get cURL from the cvs
6. Build cURL with "./buildconf", "./configure", "make", "sudo make install"

View File

@@ -11,7 +11,7 @@ EXTRA_DIST = \
bin_SCRIPTS = curl-config bin_SCRIPTS = curl-config
SUBDIRS = docs lib src include tests packages SUBDIRS = docs lib src include tests packages multi
# create a root makefile in the distribution: # create a root makefile in the distribution:
dist-hook: dist-hook:

View File

@@ -176,7 +176,7 @@ AC_DEFUN([TYPE_IN_ADDR_T],
AC_DEFINE_UNQUOTED(in_addr_t, $curl_cv_in_addr_t_equiv, AC_DEFINE_UNQUOTED(in_addr_t, $curl_cv_in_addr_t_equiv,
[type to use in place of in_addr_t if not defined])], [type to use in place of in_addr_t if not defined])],
[#include <sys/types.h> [#include <sys/types.h>
#include <sys/socket.h>, #include <sys/socket.h>
#include <arpa/inet.h>]) #include <arpa/inet.h>])
]) ])

View File

@@ -5,7 +5,7 @@ die(){
exit exit
} }
automake || die "The command 'automake $MAKEFILES' failed"
aclocal || die "The command 'aclocal' failed" aclocal || die "The command 'aclocal' failed"
autoheader || die "The command 'autoheader' failed" autoheader || die "The command 'autoheader' failed"
autoconf || die "The command 'autoconf' failed" autoconf || die "The command 'autoconf' failed"
automake || die "The command 'automake $MAKEFILES' failed"

View File

@@ -69,7 +69,7 @@ AC_ARG_ENABLE(debug,
*) AC_MSG_RESULT(yes) *) AC_MSG_RESULT(yes)
CPPFLAGS="$CPPFLAGS -DMALLOCDEBUG" CPPFLAGS="$CPPFLAGS -DMALLOCDEBUG"
CFLAGS="-W -Wall -Wwrite-strings -pedantic -g" CFLAGS="-W -Wall -Wwrite-strings -pedantic -Wundef -Wpointer-arith -Wcast-align -Wnested-externs -g"
;; ;;
esac ], esac ],
AC_MSG_RESULT(no) AC_MSG_RESULT(no)
@@ -392,6 +392,10 @@ else
OPENSSL_ENABLED=1) OPENSSL_ENABLED=1)
fi fi
dnl Check for the OpenSSL engine header, it is kind of "separated"
dnl from the main SSL check
AC_CHECK_HEADERS(openssl/engine.h)
AC_SUBST(OPENSSL_ENABLED) AC_SUBST(OPENSSL_ENABLED)
fi fi
@@ -469,6 +473,8 @@ else
dnl is there a localtime_r() dnl is there a localtime_r()
CURL_CHECK_LOCALTIME_R() CURL_CHECK_LOCALTIME_R()
AC_CHECK_FUNCS( gmtime_r )
fi fi
dnl ********************************************************************** dnl **********************************************************************
@@ -518,9 +524,9 @@ AC_HEADER_TIME
# mprintf() checks: # mprintf() checks:
# check for 'long double' # check for 'long double'
AC_CHECK_SIZEOF(long double, 8) # AC_CHECK_SIZEOF(long double, 8)
# check for 'long long' # check for 'long long'
AC_CHECK_SIZEOF(long long, 4) # AC_CHECK_SIZEOF(long long, 4)
# check for ssize_t # check for ssize_t
AC_CHECK_TYPE(ssize_t, int) AC_CHECK_TYPE(ssize_t, int)
@@ -591,6 +597,7 @@ AC_CONFIG_FILES([Makefile \
include/Makefile \ include/Makefile \
include/curl/Makefile \ include/curl/Makefile \
src/Makefile \ src/Makefile \
multi/Makefile \
lib/Makefile \ lib/Makefile \
tests/Makefile \ tests/Makefile \
tests/data/Makefile \ tests/data/Makefile \

View File

@@ -16,6 +16,7 @@ Usage: curl-config [OPTION]
Available values for OPTION include: Available values for OPTION include:
--cc compiler
--cflags pre-processor and compiler flags --cflags pre-processor and compiler flags
--feature newline separated list of enabled features --feature newline separated list of enabled features
--help display this help and exit --help display this help and exit
@@ -42,6 +43,10 @@ while test $# -gt 0; do
esac esac
case "$1" in case "$1" in
--cc)
echo @CC@
;;
--prefix) --prefix)
echo $prefix echo $prefix
;; ;;

View File

@@ -23,11 +23,16 @@ BUGS
When reporting a bug, you should include information that will help us When reporting a bug, you should include information that will help us
understand what's wrong, what you expected to happen and how to repeat the understand what's wrong, what you expected to happen and how to repeat the
bad behaviour. You therefore need to supply your operating system's name and bad behavior. You therefore need to supply your operating system's name and
version number (uname -a under a unix is fine), what version of curl you're version number (uname -a under a unix is fine), what version of curl you're
using (curl -V is fine), what URL you were working with and anything else using (curl -V is fine), what URL you were working with and anything else
you think matters. you think matters.
Since curl deals with networks, it often helps us a lot if you include a
protocol debug dump with your bug report. The output you get by using the -v
flag. Usually, you also get more info by using -i so that is likely to be
useful when reporting bugs as well.
If curl crashed, causing a core dump (in unix), there is hardly any use to If curl crashed, causing a core dump (in unix), there is hardly any use to
send that huge file to anyone of us. Unless we have an exact same system send that huge file to anyone of us. Unless we have an exact same system
setup as you, we can't do much with it. What we instead ask of you is to get setup as you, we can't do much with it. What we instead ask of you is to get
@@ -36,8 +41,7 @@ BUGS
The address and how to subscribe to the mailing list is detailed in the The address and how to subscribe to the mailing list is detailed in the
MANUAL file. MANUAL file.
How To Get A Stack Trace HOW TO GET A STACK TRACE
========================
First, you must make sure that you compile all sources with -g and that you First, you must make sure that you compile all sources with -g and that you
don't 'strip' the final executable. Try to avoid optimizing the code as don't 'strip' the final executable. Try to avoid optimizing the code as

View File

@@ -1,4 +1,4 @@
Updated: November 27, 2001 (http://curl.haxx.se/docs/faq.shtml) Updated: January 22, 2002 (http://curl.haxx.se/docs/faq.shtml)
_ _ ____ _ _ _ ____ _
___| | | | _ \| | ___| | | | _ \| |
/ __| | | | |_) | | / __| | | | |_) | |
@@ -33,7 +33,7 @@ FAQ
3.6 Does curl support javascript, ASP, XML, XHTML or HTML version Y? 3.6 Does curl support javascript, ASP, XML, XHTML or HTML version Y?
3.7 Can I use curl to delete/rename a file through FTP? 3.7 Can I use curl to delete/rename a file through FTP?
3.8 How do I tell curl to follow HTTP redirects? 3.8 How do I tell curl to follow HTTP redirects?
3.9 How do I use curl in PHP, Perl, Tcl, Ruby or Java? 3.9 How do I use curl in my favourite programming language?
3.10 What about SOAP, WebDAV, XML-RPC or similar protocols over HTTP? 3.10 What about SOAP, WebDAV, XML-RPC or similar protocols over HTTP?
3.11 How do I POST with a different Content-Type? 3.11 How do I POST with a different Content-Type?
3.12 Why do FTP specific features over HTTP proxy fail? 3.12 Why do FTP specific features over HTTP proxy fail?
@@ -49,6 +49,7 @@ FAQ
4.5.3 "403 Forbidden" 4.5.3 "403 Forbidden"
4.5.4 "404 Not Found" 4.5.4 "404 Not Found"
4.5.5 "405 Method Not Allowed" 4.5.5 "405 Method Not Allowed"
4.5.6 "301 Moved Permanently"
4.6 Can you tell me what error code 142 means? 4.6 Can you tell me what error code 142 means?
4.7 How do I keep user names and passwords secret in Curl command lines? 4.7 How do I keep user names and passwords secret in Curl command lines?
4.8 I found a bug! 4.8 I found a bug!
@@ -162,9 +163,8 @@ FAQ
1.6 What do you get for making cURL? 1.6 What do you get for making cURL?
Project cURL is entirely free and open, without any commercial interests or Project cURL is entirely free and open. No person gets paid in any way for
money involved. No person gets paid in any way for developing curl. We all developing curl. We all do this voluntarily on our spare time.
do this voluntarily on our spare time.
We get some help from companies. Contactor Data hosts the curl web site and We get some help from companies. Contactor Data hosts the curl web site and
the main mailing list, Haxx owns the curl web site's domain and the main mailing list, Haxx owns the curl web site's domain and
@@ -334,11 +334,12 @@ FAQ
curl -L http://redirector.com curl -L http://redirector.com
3.9 How do I use curl in PHP, Perl, Tcl, Ruby or Java? 3.9 How do I use curl in my favourite programming language?
There exist many language-interfaces for curl that integrates it better with There exist many language interfaces/bindings for curl that integrates it
various languages. If you are fluid in a script language, you may very well better with various languages. If you are fluid in a script language, you
opt to use such an interface instead of using the command line tool. may very well opt to use such an interface instead of using the command line
tool.
At the time of writing, there are bindings for the five language mentioned At the time of writing, there are bindings for the five language mentioned
above, but chances are there are even more by the time you read this. Or you above, but chances are there are even more by the time you read this. Or you
@@ -348,17 +349,10 @@ FAQ
install and use them, in the libcurl section of the curl web site: install and use them, in the libcurl section of the curl web site:
http://curl.haxx.se/libcurl/ http://curl.haxx.se/libcurl/
PHP4 has the ability to use libcurl as an internal module if built with that
option enabled. You then get a set of extra functions that can be used
within your PHP programs. You find all details about those functions in the
curl section in the PHP manual, see the online version at:
http://www.php.net/manual/ref.curl.php In December 2001, there are interfaces available for the following
languages: C/C++, Cocoa, Dylan, Java, Perl, PHP, Python, Rexx, Ruby, Scheme
PHP also offers the option to run a command line, and then you can of course and Tcl. By the time you read this, additional ones may have appeared!
invoke the curl tool using a command line. This is the way to use curl if
you're using PHP3 or PHP4 built without curl module support.
3.10 What about SOAP, WebDAV, XML-RPC or similar protocols over HTTP? 3.10 What about SOAP, WebDAV, XML-RPC or similar protocols over HTTP?
@@ -386,7 +380,7 @@ FAQ
There is one exception to this rule, and that is if you can "tunnel through" There is one exception to this rule, and that is if you can "tunnel through"
the given HTTP proxy. Proxy tunneling is enabled with a special option (-p) the given HTTP proxy. Proxy tunneling is enabled with a special option (-p)
and is generally not available as proxy admins usuable disable tunneling to and is generally not available as proxy admins usually disable tunneling to
other ports than 443 (which is used for HTTPS access through proxies). other ports than 443 (which is used for HTTPS access through proxies).
4. Running Problems 4. Running Problems
@@ -478,6 +472,17 @@ FAQ
identified by the Request-URI. The response MUST include an Allow header identified by the Request-URI. The response MUST include an Allow header
containing a list of valid methods for the requested resource. containing a list of valid methods for the requested resource.
4.5.6 "301 Moved Permanently"
If you get this return code and an HTML outpt similar to this:
<H1>Moved Permanently</H1> The document has moved <A
HREF="http://same_url_now_with_a_trailing_slash/">here</A>.
it might be because you request a directory URL but without the trailing
slash. Try the same operation again _with_ the trailing URL, or use the
-L/--location option to follow the redirection.
4.6. Can you tell me what error code 142 means? 4.6. Can you tell me what error code 142 means?
All error codes that are larger than the highest documented error code means All error codes that are larger than the highest documented error code means

View File

@@ -178,9 +178,9 @@ Win32
For VC++ 6, there's an included Makefile.vc6 that should be possible For VC++ 6, there's an included Makefile.vc6 that should be possible
to use out-of-the-box. to use out-of-the-box.
Microsoft note: add /Zm200 to the compiler options to increase the Microsoft note: add /Zm200 to the compiler options to increase the
compiler's memory allocation limit, as the hugehelp.c won't compile compiler's memory allocation limit, as the hugehelp.c won't compile
due to "too long puts string". due to "too long puts string".
With SSL: With SSL:
@@ -322,6 +322,20 @@ VMS
13-jul-2001 13-jul-2001
N. Baggus N. Baggus
QNX
===
(This section was graciously brought to us by David Bentham)
As QNX is targetted for resource constrained environments, the QNX headers
set conservative limits. This includes the FD_SETSIZE macro, set by default
to 32. Socket descriptors returned within the CURL library may exceed this,
resulting in memory faults/SIGSEGV crashes when passed into select(..)
calls using fd_set macros.
A good all-round solution to this is to override the default when building
libcurl, by overriding CFLAGS during configure, example
# configure CFLAGS='-DFD_SETSIZE=64 -g -O2'
CROSS COMPILE CROSS COMPILE
============= =============
@@ -364,7 +378,8 @@ CROSS COMPILE
PORTS PORTS
===== =====
This is a probably incomplete list of known hardware and operating systems This is a probably incomplete list of known hardware and operating systems
that curl has been compiled for: that curl has been compiled for. If you know one system curl compiles and
runs on, that isn't listed, please let us know!
- Alpha DEC OSF 4 - Alpha DEC OSF 4
- Alpha Digital UNIX v3.2 - Alpha Digital UNIX v3.2
@@ -391,6 +406,7 @@ PORTS
- Ultrix 4.3a - Ultrix 4.3a
- i386 BeOS - i386 BeOS
- i386 FreeBSD - i386 FreeBSD
- i386 HURD
- i386 Linux 1.3, 2.0, 2.2, 2.3, 2.4 - i386 Linux 1.3, 2.0, 2.2, 2.3, 2.4
- i386 NetBSD - i386 NetBSD
- i386 OS/2 - i386 OS/2

View File

@@ -601,15 +601,15 @@ RESUMING FILE TRANSFERS
Continue downloading a document: Continue downloading a document:
curl -c -o file ftp://ftp.server.com/path/file curl -C - -o file ftp://ftp.server.com/path/file
Continue uploading a document(*1): Continue uploading a document(*1):
curl -c -T file ftp://ftp.server.com/path/file curl -C - -T file ftp://ftp.server.com/path/file
Continue downloading a document from a web server(*2): Continue downloading a document from a web server(*2):
curl -c -o file http://www.server.com/ curl -C - -o file http://www.server.com/
(*1) = This requires that the ftp server supports the non-standard command (*1) = This requires that the ftp server supports the non-standard command
SIZE. If it doesn't, curl will say so. SIZE. If it doesn't, curl will say so.

View File

@@ -76,3 +76,6 @@ that have contributed with non-trivial parts:
- Tomasz Lacki <Tomasz.Lacki@primark.pl> - Tomasz Lacki <Tomasz.Lacki@primark.pl>
- Georg Huettenegger <georg@ist.org> - Georg Huettenegger <georg@ist.org>
- John Lask <johnlask@hotmail.com> - John Lask <johnlask@hotmail.com>
- Eric Lavigne <erlavigne@wanadoo.fr>
- Marcus Webster <marcus.webster@phocis.com>
- G<>tz Babin-Ebell <babin<69>ebell@trustcenter.de>

View File

@@ -19,10 +19,7 @@ TODO
* The new 'multi' interface is being designed. Work out the details, start * The new 'multi' interface is being designed. Work out the details, start
implementing and write test applications! implementing and write test applications!
[http://curl.haxx.se/dev/multi.h] [http://curl.haxx.se/lxr/source/lib/multi.h]
* Add a name resolve cache to libcurl to make repeated fetches to the same
host name (when persitancy isn't available) faster.
* Introduce another callback interface for upload/download that makes one * Introduce another callback interface for upload/download that makes one
less copy of data and thus a faster operation. less copy of data and thus a faster operation.
@@ -33,11 +30,36 @@ TODO
telnet, ldap, dict or file. telnet, ldap, dict or file.
* Add asynchronous name resolving. http://curl.haxx.se/dev/async-resolver.txt * Add asynchronous name resolving. http://curl.haxx.se/dev/async-resolver.txt
This should be made to work on most of the supported platforms, or
otherwise it isn't really interesting.
* Data sharing. Tell which easy handles within a multi handle that should
share cookies, connection cache, dns cache, ssl session cache.
* Mutexes. By adding mutex callback support, the 'data sharing' mentioned
above can be made between several easy handles running in different threads
too. The actual mutex implementations will be left for the application to
implement, libcurl will merely call 'getmutex' and 'leavemutex' callbacks.
* No-faster-then-this transfers. Many people have limited bandwidth and they
want the ability to make sure their transfers never use more bandwith than
they think is good.
* Set the SO_KEEPALIVE socket option to make libcurl notice and disconnect
very long time idle connections.
* Make sure we don't ever loop because of non-blocking sockets return
EWOULDBLOCK or similar. This concerns the HTTP request sending, the FTP
command sending etc.
* Go through the code and verify that libcurl deals with big files >2GB and
>4GB all over. Bug reports indicate that it doesn't currently work
properly.
DOCUMENTATION DOCUMENTATION
* Document all CURLcode error codes, why they happen and what most likely * Document all CURLcode error codes, why they happen and what most likely
will make them not happen again. will make them not happen again. In a libcurl point of view.
FTP FTP
@@ -52,11 +74,7 @@ TODO
already working http dito works. It of course requires that 'MDTM' works, already working http dito works. It of course requires that 'MDTM' works,
and it isn't a standard FTP command. and it isn't a standard FTP command.
* Suggested on the mailing list: CURLOPT_FTP_MKDIR...! * Add FTPS support with SSL for the data connection too.
* Always use the FTP SIZE command before downloading, as that makes it more
likely that we know the size when downloading. Some sites support SIZE but
don't show the size in the RETR response!
HTTP HTTP
@@ -81,34 +99,53 @@ TODO
http://www.innovation.ch/java/ntlm.html that contains detailed reverse- http://www.innovation.ch/java/ntlm.html that contains detailed reverse-
engineered info. engineered info.
* RFC2617 compliance, "Digest Access Authentication" * RFC2617 compliance, "Digest Access Authentication" A valid test page seem
A valid test page seem to exist at: to exist at: http://hopf.math.nwu.edu/testpage/digest/ And some friendly
http://hopf.math.nwu.edu/testpage/digest/ person's server source code is available at
And some friendly person's server source code is available at http://hopf.math.nwu.edu/digestauth/index.html Then there's the Apache
http://hopf.math.nwu.edu/digestauth/index.html mod_digest source code too of course. It seems as if Netscape doesn't
Then there's the Apache mod_digest source code too of course. It seems as support this, and not many servers do. Although this is a lot better
if Netscape doesn't support this, and not many servers do. Although this is authentication method than the more common "Basic". Basic sends the
a lot better authentication method than the more common "Basic". Basic password in cleartext over the network, this "Digest" method uses a
sends the password in cleartext over the network, this "Digest" method uses challange-response protocol which increases security quite a lot.
a challange-response protocol which increases security quite a lot.
* Pipelining. Sending multiple requests before the previous one(s) are done.
This could possibly be implemented using the multi interface to queue
requests and the response data.
TELNET TELNET
* Make TELNET work on windows98! * Make TELNET work on windows98!
* Reading input (to send to the remote server) on stdin is a crappy solution
for library purposes. We need to invent a good way for the application to
be able to provide the data to send.
* Move the telnet support's network select() loop go away and merge the code
into the main transfer loop. Until this is done, the multi interface won't
work for telnet.
SSL SSL
* Add an interface to libcurl that enables "session IDs" to get * Add an interface to libcurl that enables "session IDs" to get
exported/imported. Cris Bailiff said: "OpenSSL has functions which can exported/imported. Cris Bailiff said: "OpenSSL has functions which can
serialise the current SSL state to a buffer of your choice, and serialise the current SSL state to a buffer of your choice, and
recover/reset the state from such a buffer at a later date - this is used recover/reset the state from such a buffer at a later date - this is used
by mod_ssl for apache to implement and SSL session ID cache" by mod_ssl for apache to implement and SSL session ID cache". This whole
idea might become moot if we enable the 'data sharing' as mentioned in the
LIBCURL label above.
* Make curl's SSL layer option capable of using other free SSL libraries. * Make curl's SSL layer option capable of using other free SSL libraries.
Such as the Mozilla Security Services Such as the Mozilla Security Services
(http://www.mozilla.org/projects/security/pki/nss/) and GNUTLS (http://www.mozilla.org/projects/security/pki/nss/) and GNUTLS
(http://gnutls.hellug.gr/) (http://gnutls.hellug.gr/)
LDAP
* Look over the implementation. The looping will have to "go away" from the
lib/ldap.c source file and get moved to the main network code so that the
multi interface and friends will work for LDAP as well.
CLIENT CLIENT
* "curl ftp://site.com/*.txt" * "curl ftp://site.com/*.txt"
@@ -117,6 +154,11 @@ TODO
the same syntax to specify several files to get uploaded (using the same the same syntax to specify several files to get uploaded (using the same
persistant connection), using -T. persistant connection), using -T.
* When the multi interface has been implemented and proved to work, the
client could be told to use maximum N simultaneous transfers and then just
make sure that happens. It should of course not make more than one
connection to the same remote host.
TEST SUITE TEST SUITE
* Extend the test suite to include more protocols. The telnet could just do * Extend the test suite to include more protocols. The telnet could just do

View File

@@ -2,7 +2,7 @@
.\" nroff -man curl-config.1 .\" nroff -man curl-config.1
.\" Written by Daniel Stenberg .\" Written by Daniel Stenberg
.\" .\"
.TH curl-config 1 "16 August 2001" "Curl 7.8.1" "curl-config manual" .TH curl-config 1 "21 January 2002" "Curl 7.9.3" "curl-config manual"
.SH NAME .SH NAME
curl-config \- Get information about a libcurl installation curl-config \- Get information about a libcurl installation
.SH SYNOPSIS .SH SYNOPSIS
@@ -11,6 +11,8 @@ curl-config \- Get information about a libcurl installation
.B curl-config .B curl-config
displays information about a previous curl and libcurl installation. displays information about a previous curl and libcurl installation.
.SH OPTIONS .SH OPTIONS
.IP "--cc"
Displays the compiler used to build libcurl.
.IP "--cflags" .IP "--cflags"
Set of compiler options (CFLAGS) to use when compiling files that use Set of compiler options (CFLAGS) to use when compiling files that use
libcurl. Currently that is only thw include path to the curl include files. libcurl. Currently that is only thw include path to the curl include files.
@@ -38,18 +40,23 @@ major, minor, patch. So that libcurl 7.7.4 would appear as 070704 and libcurl
.SH "EXAMPLES" .SH "EXAMPLES"
What linker options do I need when I link with libcurl? What linker options do I need when I link with libcurl?
curl-config --libs $ curl-config --libs
What compiler options do I need when I compile using libcurl functions? What compiler options do I need when I compile using libcurl functions?
curl-config --cflags $ curl-config --cflags
How do I know if libcurl was built with SSL support? How do I know if libcurl was built with SSL support?
curl-config --feature | grep SSL $ curl-config --feature | grep SSL
What's the installed libcurl version? What's the installed libcurl version?
curl-config --version $ curl-config --version
How do I build a single file with a one-line command?
$ `curl-config --cc --cflags --libs` -o example example.c
.SH "SEE ALSO" .SH "SEE ALSO"
.BR curl (1) .BR curl (1)

View File

@@ -4,8 +4,7 @@
.\" .\"
.TH curl 1 "30 Nov 2001" "Curl 7.9.2" "Curl Manual" .TH curl 1 "30 Nov 2001" "Curl 7.9.2" "Curl Manual"
.SH NAME .SH NAME
curl \- get a URL with FTP, TELNET, LDAP, GOPHER, DICT, FILE, HTTP or curl \- transfer a URL
HTTPS syntax.
.SH SYNOPSIS .SH SYNOPSIS
.B curl [options] .B curl [options]
.I [URL...] .I [URL...]
@@ -677,7 +676,7 @@ If this option is used several times, the last one will be used.
Default config file. Default config file.
.SH ENVIRONMENT .SH ENVIRONMENT
.IP "HTTP_PROXY [protocol://]<host>[:port]" .IP "http_proxy [protocol://]<host>[:port]"
Sets proxy server to use for HTTP. Sets proxy server to use for HTTP.
.IP "HTTPS_PROXY [protocol://]<host>[:port]" .IP "HTTPS_PROXY [protocol://]<host>[:port]"
Sets proxy server to use for HTTPS. Sets proxy server to use for HTTPS.
@@ -688,11 +687,8 @@ Sets proxy server to use for GOPHER.
.IP "ALL_PROXY [protocol://]<host>[:port]" .IP "ALL_PROXY [protocol://]<host>[:port]"
Sets proxy server to use if no protocol-specific proxy is set. Sets proxy server to use if no protocol-specific proxy is set.
.IP "NO_PROXY <comma-separated list of hosts>" .IP "NO_PROXY <comma-separated list of hosts>"
list of host names that shouldn't go through any proxy. If set to a list of host names that shouldn't go through any proxy. If set to a asterisk
asterisk '*' only, it matches all hosts. '*' only, it matches all hosts.
.IP "COLUMNS <integer>"
The width of the terminal. This variable only affects curl when the
--progress-bar option is used.
.SH EXIT CODES .SH EXIT CODES
There exists a bunch of different error codes and their corresponding error There exists a bunch of different error codes and their corresponding error
messages that may appear during bad conditions. At the time of this writing, messages that may appear during bad conditions. At the time of this writing,

View File

@@ -2,7 +2,7 @@
.\" nroff -man [file] .\" nroff -man [file]
.\" $Id$ .\" $Id$
.\" .\"
.TH curl_easy_setopt 3 "30 Nov 2001" "libcurl 7.9.2" "libcurl Manual" .TH curl_easy_setopt 3 "10 Dec 2001" "libcurl 7.9.2" "libcurl Manual"
.SH NAME .SH NAME
curl_easy_setopt - Set curl easy-session options curl_easy_setopt - Set curl easy-session options
.SH SYNOPSIS .SH SYNOPSIS
@@ -77,9 +77,8 @@ function gets called by libcurl as soon as it needs to read data in order to
send it to the peer. The data area pointed at by the pointer \fIptr\fP may be send it to the peer. The data area pointed at by the pointer \fIptr\fP may be
filled with at most \fIsize\fP multiplied with \fInmemb\fP number of filled with at most \fIsize\fP multiplied with \fInmemb\fP number of
bytes. Your function must return the actual number of bytes that you stored in bytes. Your function must return the actual number of bytes that you stored in
that memory area. Returning -1 will signal an error to the library and cause that memory area. Returning 0 will signal end-of-file to the library and cause
it to abort the current transfer immediately (with a \fICURLE_READ_ERROR\fP it to stop the current transfer.
return code).
.TP .TP
.B CURLOPT_INFILESIZE .B CURLOPT_INFILESIZE
When uploading a file to a remote site, this option should be used to tell When uploading a file to a remote site, this option should be used to tell
@@ -320,13 +319,54 @@ with \fIcurl_easy_cleanup(3)\fP.
.TP .TP
.B CURLOPT_SSLCERT .B CURLOPT_SSLCERT
Pass a pointer to a zero terminated string as parameter. The string should be Pass a pointer to a zero terminated string as parameter. The string should be
the file name of your certificate in PEM format. the file name of your certificate. The default format is "PEM" and can be
changed with \fICURLOPT_SSLCERTTYPE\fP.
.TP
.B CURLOPT_SSLCERTTYPE
Pass a pointer to a zero terminated string as parameter. The string should be
the format of your certificate. Supported formats are "PEM" and "DER".
.TP .TP
.B CURLOPT_SSLCERTPASSWD .B CURLOPT_SSLCERTPASSWD
Pass a pointer to a zero terminated string as parameter. It will be used as Pass a pointer to a zero terminated string as parameter. It will be used as
the password required to use the CURLOPT_SSLCERT certificate. If the password the password required to use the CURLOPT_SSLCERT certificate. If the password
is not supplied, you will be prompted for it. \fICURLOPT_PASSWDFUNCTION\fP can is not supplied, you will be prompted for it. \fICURLOPT_PASSWDFUNCTION\fP can
be used to set your own prompt function. be used to set your own prompt function.
\fBNOTE:\fPThis option is replaced by \fICURLOPT_SSLKEYPASSWD\fP and only
cept for backward compatibility. You never needed a pass phrase to load
a certificate but you need one to load your private key.
.TP
.B CURLOPT_SSLKEY
Pass a pointer to a zero terminated string as parameter. The string should be
the file name of your private key. The default format is "PEM" and can be
changed with \fICURLOPT_SSLKEYTYPE\fP.
.TP
.B CURLOPT_SSLKEYTYPE
Pass a pointer to a zero terminated string as parameter. The string should be
the format of your private key. Supported formats are "PEM", "DER" and "ENG".
\fBNOTE:\fPThe format "ENG" enables you to load the private key from a crypto
engine. in this case \fICURLOPT_SSLKEY\fP is used as an identifier passed to
the engine. You have to set the crypto engine with \fICURLOPT_SSL_ENGINE\fP.
.TP
.B CURLOPT_SSLKEYASSWD
Pass a pointer to a zero terminated string as parameter. It will be used as
the password required to use the \fICURLOPT_SSLKEY\fP private key. If the password
is not supplied, you will be prompted for it. \fICURLOPT_PASSWDFUNCTION\fP can
be used to set your own prompt function.
.TP
.B CURLOPT_SSL_ENGINE
Pass a pointer to a zero terminated string as parameter. It will be used as
the identifier for the crypto engine you want to use for your private key.
\fBNOTE:\fPIf the crypto device cannot be loaded, \fICURLE_SSL_ENGINE_NOTFOUND\fP
is returned.
.TP
.B CURLOPT_SSL_ENGINEDEFAULT
Sets the actual crypto engine as the default for (asymetric) crypto operations.
\fBNOTE:\fPIf the crypto device cannot be set, \fICURLE_SSL_ENGINE_SETFAILED\fP
is returned.
.TP .TP
.B CURLOPT_CRLF .B CURLOPT_CRLF
Convert Unix newlines to CRLF newlines on FTP uploads. Convert Unix newlines to CRLF newlines on FTP uploads.

View File

@@ -58,6 +58,13 @@ are allowed. The effect of this parameter is the same as giving multiple
\fBCURLFORM_FILE\fP options possibly with \fBCURLFORM_CONTENTTYPE\fP after or \fBCURLFORM_FILE\fP options possibly with \fBCURLFORM_CONTENTTYPE\fP after or
before each \fBCURLFORM_FILE\fP option. before each \fBCURLFORM_FILE\fP option.
Should you need to specify extra headers for the form POST section, use
\fBCURLFORM_CONTENTHEADER\fP. This takes a curl_slist prepared in the usual way
using \fBcurl_slist_append\fP and appends the list of headers to those Curl
automatically generates for \fBCURLFORM_CONTENTTYPE\fP and the content
disposition. The list must exist while the POST occurs, if you free it before
the post completes you may experience problems.
The last argument in such an array must always be \fBCURLFORM_END\fP. The last argument in such an array must always be \fBCURLFORM_END\fP.
The pointers \fI*firstitem\fP and \fI*lastitem\fP should both be pointing to The pointers \fI*firstitem\fP and \fI*lastitem\fP should both be pointing to

View File

@@ -2,7 +2,7 @@
.\" nroff -man [file] .\" nroff -man [file]
.\" $Id$ .\" $Id$
.\" .\"
.TH curl_formparse 3 "21 May 2001" "libcurl 7.7.4" "libcurl Manual" .TH curl_formparse 3 "17 Dec 2001" "libcurl 7.9.2" "libcurl Manual"
.SH NAME .SH NAME
curl_formparse - add a section to a multipart/formdata HTTP POST: curl_formparse - add a section to a multipart/formdata HTTP POST:
deprecated (use curl_formadd instead) deprecated (use curl_formadd instead)
@@ -13,75 +13,6 @@ deprecated (use curl_formadd instead)
.BI "struct HttpPost ** " lastitem ");" .BI "struct HttpPost ** " lastitem ");"
.ad .ad
.SH DESCRIPTION .SH DESCRIPTION
curl_formparse() is used to append sections when building a multipart/formdata This has been removed deliberately. The \fBcurl_formadd\fP has been introduced
HTTP POST (sometimes refered to as rfc1867-style posts). Append one section at to replace this function. Do not use this. Convert to the new function
a time until you've added all the sections you want included and then you pass now. curl_formparse() will be removed from a future version of libcurl.
the \fIfirstitem\fP pointer as parameter to \fBCURLOPT_HTTPPOST\fP.
\fIlastitem\fP is set after each call and on repeated invokes it should be
left as set to allow repeated invokes to find the end of the list in a faster
way. \fIstring\fP must be a zero terminated string abiding to the syntax
described in a section below
The pointers \fI*firstitem\fP and \fI*lastitem\fP should both be pointing to
NULL in the first call to this function. All list-data will be allocated by
the function itself. You must call \fIcurl_formfree\fP after the form post has
been done to free the resources again.
This function will copy all input data and keep its own version of it
allocated until you call \fIcurl_formfree\fP. When you've passed the pointer
to \fIcurl_easy_setopt\fP, you must not free the list until after you've
called \fIcurl_easy_cleanup\fP for the curl handle.
See example below.
.SH "FORM PARSE STRINGS"
The
.I string
parameter must be using one of the following patterns. Note that the []
letters should not be included in the real-life string.
.TP 0.8i
.B [name]=[contents]
Add a form field named 'name' with the contents 'contents'. This is the
typcial contents of the HTML tag <input type=text>.
.TP
.B [name]=@[filename]
Add a form field named 'name' with the contents as read from the local file
named 'filename'. This is the typcial contents of the HTML tag <input
type=file>.
.TP
.B [name]=@[filename1,filename2,...]
Add a form field named 'name' with the contents as read from the local files
named 'filename1' and 'filename2'. This is identical to the upper, except that
you get the contents of several files in one section.
.TP
.B [name]=@[filename];[type=<content-type>]
Whenever you specify a file to read from, you can optionally specify the
content-type as well. The content-type is passed to the server together with
the contents of the file. curl_formparse() will guess content-type for a
number of well-known extensions and otherwise it will set it to binary. You
can override the internal decision by using this option.
.TP
.B [name]=@[filename1,filename2,...];[type=<content-type>]
When you specify several files to read the contents from, you can set the
content-type for all of them in the same way as with a single file.
.PP
.SH RETURN VALUE
Returns non-zero if an error occurs.
.SH EXAMPLE
HttpPost* post = NULL;
HttpPost* last = NULL;
/* Add an image section */
curl_formparse("picture=@my-face.jpg", &post, &last);
/* Add a normal text section */
curl_formparse("name=FooBar", &post, &last);
/* Set the form info */
curl_easy_setopt(curl, CURLOPT_HTTPPOST, post);
.SH "SEE ALSO"
.BR curl_easy_setopt "(3), "
.BR curl_formadd "(3), "
.BR curl_formfree "(3)
.SH BUGS
Surely there are some, you tell me!

View File

@@ -6,7 +6,8 @@ AUTOMAKE_OPTIONS = foreign no-dependencies
EXTRA_DIST = README curlgtk.c sepheaders.c simple.c postit.c postit2.c \ EXTRA_DIST = README curlgtk.c sepheaders.c simple.c postit.c postit2.c \
win32sockets.c persistant.c ftpget.c Makefile.example \ win32sockets.c persistant.c ftpget.c Makefile.example \
multithread.c getinmemory.c ftpupload.c httpput.c multithread.c getinmemory.c ftpupload.c httpput.c \
simplessl.c ftpgetresp.c http-post.c
all: all:
@echo "done" @echo "done"

View File

@@ -10,6 +10,10 @@ them for submission in future packages and on the web site.
The Makefile.example is an example makefile that could be used to build these The Makefile.example is an example makefile that could be used to build these
examples. Just edit the file according to your system and requirements first. examples. Just edit the file according to your system and requirements first.
Most examples should build fine using a command line like this:
$ gcc `curl-config --cflags` `curl-config --libs` -o example example.c
Try the php/examples/ directory for PHP programming snippets! Try the php/examples/ directory for PHP programming snippets!
*PLEASE* do not use the curl.haxx.se site as a test target for your libcurl *PLEASE* do not use the curl.haxx.se site as a test target for your libcurl

View File

@@ -14,31 +14,70 @@
#include <curl/types.h> #include <curl/types.h>
#include <curl/easy.h> #include <curl/easy.h>
/* to make this work under windows, use the win32-functions from the /*
win32socket.c file as well */ * This is an example showing how to get a single file from an FTP server.
* It delays the actual destination file creation until the first write
* callback so that it won't create an empty file in case the remote file
* doesn't exist or something else fails.
*/
int main(int argc, char **argv) struct FtpFile {
char *filename;
FILE *stream;
};
int my_fwrite(void *buffer, size_t size, size_t nmemb, void *stream)
{
struct FtpFile *out=(struct FtpFile *)stream;
if(out && !out->stream) {
/* open file for writing */
out->stream=fopen(out->filename, "wb");
if(!out->stream)
return -1; /* failure, can't open file to write */
}
return fwrite(buffer, size, nmemb, out->stream);
}
int main(void)
{ {
CURL *curl; CURL *curl;
CURLcode res; CURLcode res;
FILE *ftpfile; struct FtpFile ftpfile={
"curl.tar.gz", /* name to store the file as if succesful */
/* local file name to store the file as */ NULL
ftpfile = fopen("curl.tar.gz", "wb"); /* b is binary for win */ };
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init(); curl = curl_easy_init();
if(curl) { if(curl) {
/* Get curl 7.7 from sunet.se's FTP site: */ /* Get curl 7.9.2 from sunet.se's FTP site: */
curl_easy_setopt(curl, CURLOPT_URL, curl_easy_setopt(curl, CURLOPT_URL,
"ftp://ftp.sunet.se/pub/www/utilities/curl/curl-7.7.tar.gz"); "ftp://ftp.sunet.se/pub/www/utilities/curl/curl-7.9.2.tar.gz");
curl_easy_setopt(curl, CURLOPT_FILE, ftpfile); /* Define our callback to get called when there's data to be written */
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, my_fwrite);
/* Set a pointer to our struct to pass to the callback */
curl_easy_setopt(curl, CURLOPT_FILE, &ftpfile);
/* Switch on full protocol/debug output */
curl_easy_setopt(curl, CURLOPT_VERBOSE, TRUE);
res = curl_easy_perform(curl); res = curl_easy_perform(curl);
/* always cleanup */ /* always cleanup */
curl_easy_cleanup(curl); curl_easy_cleanup(curl);
if(CURLE_OK != res) {
/* we failed */
fprintf(stderr, "curl told us %d\n", res);
}
} }
fclose(ftpfile); /* close the local file */ if(ftpfile.stream)
fclose(ftpfile.stream); /* close the local file */
curl_global_cleanup();
return 0; return 0;
} }

View File

@@ -0,0 +1,61 @@
/*****************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* $Id$
*/
#include <stdio.h>
#include <curl/curl.h>
#include <curl/types.h>
#include <curl/easy.h>
/*
* Similar to ftpget.c but this also stores the received response-lines
* in a separate file using our own callback!
*
* This functionality was introduced in libcurl 7.9.3.
*/
size_t
write_response(void *ptr, size_t size, size_t nmemb, void *data)
{
FILE *writehere = (FILE *)data;
return fwrite(ptr, size, nmemb, writehere);
}
int main(int argc, char **argv)
{
CURL *curl;
CURLcode res;
FILE *ftpfile;
FILE *respfile;
/* local file name to store the file as */
ftpfile = fopen("ftp-list", "wb"); /* b is binary, needed on win32 */
/* local file name to store the FTP server's response lines in */
respfile = fopen("ftp-responses", "wb"); /* b is binary, needed on win32 */
curl = curl_easy_init();
if(curl) {
/* Get a file listing from sunet */
curl_easy_setopt(curl, CURLOPT_URL, "ftp://ftp.sunet.se/");
curl_easy_setopt(curl, CURLOPT_FILE, ftpfile);
curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, write_response);
curl_easy_setopt(curl, CURLOPT_WRITEHEADER, respfile);
res = curl_easy_perform(curl);
/* always cleanup */
curl_easy_cleanup(curl);
}
fclose(ftpfile); /* close the local file */
fclose(respfile); /* close the response file */
return 0;
}

35
docs/examples/http-post.c Normal file
View File

@@ -0,0 +1,35 @@
/*****************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* $Id$
*/
#include <stdio.h>
#include <curl/curl.h>
int main(void)
{
CURL *curl;
CURLcode res;
curl = curl_easy_init();
if(curl) {
/* First set the URL that is about to receive our POST. This URL can
just as well be a https:// URL if that is what should receive the
data. */
curl_easy_setopt(curl, CURLOPT_URL, "http://postit.example.com/moo.cgi");
/* Now specify the POST data */
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "name=daniel&project=curl");
/* Perform the request, res will get the return code */
res = curl_easy_perform(curl);
/* always cleanup */
curl_easy_cleanup(curl);
}
return 0;
}

View File

@@ -9,27 +9,16 @@
*/ */
#include <stdio.h> #include <stdio.h>
#include <curl/curl.h> #include <curl/curl.h>
#include <curl/types.h>
#include <curl/easy.h>
/* to make this work under windows, use the win32-functions from the int main(void)
win32socket.c file as well */
int main(int argc, char **argv)
{ {
CURL *curl; CURL *curl;
CURLcode res; CURLcode res;
FILE *headerfile;
headerfile = fopen("dumpit", "w");
curl = curl_easy_init(); curl = curl_easy_init();
if(curl) { if(curl) {
/* what call to write: */
curl_easy_setopt(curl, CURLOPT_URL, "curl.haxx.se"); curl_easy_setopt(curl, CURLOPT_URL, "curl.haxx.se");
curl_easy_setopt(curl, CURLOPT_WRITEHEADER, headerfile);
res = curl_easy_perform(curl); res = curl_easy_perform(curl);
/* always cleanup */ /* always cleanup */

118
docs/examples/simplessl.c Normal file
View File

@@ -0,0 +1,118 @@
/*****************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* $Id$
*/
#include <stdio.h>
#include <curl/curl.h>
#include <curl/types.h>
#include <curl/easy.h>
/* some requirements for this to work:
1. set pCertFile to the file with the client certificate
2. if the key is passphrase protected, set pPassphrase to the
passphrase you use
3. if you are using a crypto engine:
3.1. set a #define USE_ENGINE
3.2. set pEngine to the name of the crypto engine you use
3.3. set pKeyName to the key identifier you want to use
4. if you don't use a crypto engine:
4.1. set pKeyName to the file name of your client key
4.2. if the format of the key file is DER, set pKeyType to "DER"
!! verify of the server certificate is not implemented here !!
**** This example only works with libcurl 7.9.3 and later! ****
*/
int main(int argc, char **argv)
{
CURL *curl;
CURLcode res;
FILE *headerfile;
const char *pCertFile = "testcert.pem";
const char *pCACertFile="cacert.pem"
const char *pKeyName;
const char *pKeyType;
const char *pEngine;
#if USE_ENGINE
pKeyName = "rsa_test";
pKeyType = "ENG";
pEngine = "chil"; /* for nChiper HSM... */
#else
pKeyName = "testkey.pem";
pKeyType = "PEM";
pEngine = NULL;
#endif
const char *pPassphrase = NULL;
headerfile = fopen("dumpit", "w");
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if(curl) {
/* what call to write: */
curl_easy_setopt(curl, CURLOPT_URL, "HTTPS://curl.haxx.se");
curl_easy_setopt(curl, CURLOPT_WRITEHEADER, headerfile);
while(1) /* do some ugly short cut... */
{
if (pEngine) /* use crypto engine */
{
if (curl_easy_setopt(curl, CURLOPT_SSLENGINE,pEngine) != CURLE_OK)
{ /* load the crypto engine */
fprintf(stderr,"can't set crypto engine\n");
break;
}
if (curl_easy_setopt(curl, CURLOPT_SSLENGINE_DEFAULT,1) != CURLE_OK)
{ /* set the crypto engine as default */
/* only needed for the first time you load
a engine in a curl object... */
fprintf(stderr,"can't set crypto engine as default\n");
break;
}
}
/* cert is stored PEM coded in file... */
/* since PEM is default, we needn't set it for PEM */
curl_easy_setopt(curl,CURLOPT_SSLCERTTYPE,"PEM");
/* set the cert for client authentication */
curl_easy_setopt(curl,CURLOPT_SSLCERT,pCertFile);
/* sorry, for engine we must set the passphrase
(if the key has one...) */
if (pPassphrase)
curl_easy_setopt(curl,CURLOPT_SSLKEYPASSWD,pPassphrase);
/* if we use a key stored in a crypto engine,
we must set the key type to "ENG" */
curl_easy_setopt(curl,CURLOPT_SSLKEYTYPE,pKeyType);
/* set the private key (file or ID in engine) */
curl_easy_setopt(curl,CURLOPT_SSLKEY,pKeyName);
/* set the file with the certs vaildating the server */
curl_easy_setopt(curl,CURLOPT_CAINFO,pCACertFile);
/* disconnect if we can't validate server's cert */
curl_easy_setopt(curl,CURLOPT_SSL_VERIFYPEER,1);
res = curl_easy_perform(curl);
break; /* we are done... */
}
/* always cleanup */
curl_easy_cleanup(curl);
}
curl_global_cleanup();
return 0;
}

529
docs/libcurl-the-guide Normal file
View File

@@ -0,0 +1,529 @@
$Id$
_ _ ____ _
___| | | | _ \| |
/ __| | | | |_) | |
| (__| |_| | _ <| |___
\___|\___/|_| \_\_____|
PROGRAMMING WITH LIBCURL
About this Document
This document will attempt to describe the general principle and some basic
approaches to consider when programming with libcurl. The text will focus
mainly on the C/C++ interface but might apply fairly well on other interfaces
as well as they usually follow the C one pretty closely.
This document will refer to 'the user' as the person writing the source code
that uses libcurl. That would probably be you or someone in your position.
What will be generally refered to as 'the program' will be the collected
source code that you write that is using libcurl for transfers. The program
is outside libcurl and libcurl is outside of the program.
To get the more details on all options and functions described herein, please
refer to their respective man pages.
Building
There are many different ways to build C programs. This chapter will assume a
unix-style build process. If you use a different build system, you can still
read this to get general information that may apply to your environment as
well.
Compiling the Program
Your compiler needs to know where the libcurl headers are
located. Therefore you must set your compiler's include path to point to
the directory where you installed them. The 'curl-config'[3] tool can be
used to get this information:
$ curl-config --cflags
Linking the Program with libcurl
When having compiled the program, you need to link your object files to
create a single executable. For that to succeed, you need to link with
libcurl and possibly also with other libraries that libcurl itself depends
on. Like OpenSSL librararies, but even some standard OS libraries may be
needed on the command line. To figure out which flags to use, once again
the 'curl-config' tool comes to the rescue:
$ curl-config --libs
SSL or Not
libcurl can be built and customized in many ways. One of the things that
varies from different libraries and builds is the support for SSL-based
transfers, like HTTPS and FTPS. If OpenSSL was detected properly at
build-time, libcurl will be built with SSL support. To figure out if an
installed libcurl has been built with SSL support enabled, use
'curl-config' like this:
$ curl-config --feature
And if SSL is supported, the keyword 'SSL' will be written to stdout,
possibly together with a few other features that can be on and off on
different libcurls.
Portable Code in a Portable World
The people behind libcurl have put a considerable effort to make libcurl work
on a large amount of different operating systems and environments.
You program libcurl the same way on all platforms that libcurl runs on. There
are only very few minor considerations that differs. If you just make sure to
write your code portable enough, you may very well create yourself a very
portable program. libcurl shouldn't stop you from that.
Global Preparation
The program must initialize some of the libcurl functionality globally. That
means it should be done exactly once, no matter how many times you intend to
use the library. Once for your program's entire life time. This is done using
curl_global_init()
and it takes one parameter which is a bit pattern that tells libcurl what to
intialize. Using CURL_GLOBAL_ALL will make it initialize all known internal
sub modules, and might be a good default option. The current two bits that
are specified are:
CURL_GLOBAL_WIN32 which only does anything on Windows machines. When used on
a Windows machine, it'll make libcurl intialize the win32 socket
stuff. Without having that initialized properly, your program cannot use
sockets properly. You should only do this once for each application, so if
your program already does this or of another library in use does it, you
should not tell libcurl to do this as well.
CURL_GLOBAL_SSL which only does anything on libcurls compiled and built
SSL-enabled. On these systems, this will make libcurl init OpenSSL properly
for this application. This is only needed to do once for each application so
if your program or another library already does this, this bit should not be
needed.
libcurl has a default protection mechanism that detects if curl_global_init()
hasn't been called by the time curl_easy_perform() is called and if that is
the case, libcurl runs the function itself with a guessed bit pattern. Please
note that depending solely on this is not considered nice nor very good.
When the program no longer uses libcurl, it should call
curl_global_cleanup(), which is the opposite of the init call. It will then
do the reversed operations to cleanup the resources the curl_global_init()
call initialized.
Repeated calls to curl_global_init() and curl_global_cleanup() should be
avoided. They should be called once each.
Handle the Easy libcurl
libcurl version 7 is oriented around the so called easy interface. All
operations in the easy interface are prefixed with 'curl_easy'.
Future libcurls will also offer the multi interface. More about that
interface, what it is targeted for and how to use it is still only debated on
the libcurl mailing list and developer web pages. Join up to discuss and
figure out!
To use the easy interface, you must first create yourself an easy handle. You
need one handle for each easy session you want to perform. Basicly, you
should use one handle for every thread you plan to use for transferring. You
must never share the same handle in multiple threads.
Get an easy handle with
easyhandle = curl_easy_init();
It returns an easy handle. Using that you proceed to the next step: setting
up your preferred actions. A handle is just a logic entity for the upcoming
transfer or series of transfers. One of the most basic properties to set in
the handle is the URL. You set your preferred URL to transfer with
CURLOPT_URL in a manner similar to:
curl_easy_setopt(easyhandle, CURLOPT_URL, "http://curl.haxx.se/");
Let's assume for a while that you want to receive data as the URL indentifies
a remote resource you want to get here. Since you write a sort of application
that needs this transfer, I assume that you would like to get the data passed
to you directly instead of simply getting it passed to stdout. So, you write
your own function that matches this prototype:
size_t write_data(void *buffer, size_t size, size_t nmemb, void *userp);
You tell libcurl to pass all data to this function by issuing a function
similar to this:
curl_easy_setopt(easyhandle, CURLOPT_WRITEFUNCTION, write_data);
You can control what data your function get in the forth argument by setting
another property:
curl_easy_setopt(easyhandle, CURLOPT_FILE, &internal_struct);
Using that property, you can easily pass local data between your application
and the function that gets invoked by libcurl. libcurl itself won't touch the
data you pass with CURLOPT_FILE.
libcurl offers its own default internal callback that'll take care of the
data if you don't set the callback with CURLOPT_WRITEFUNCTION. It will then
simply output the received data to stdout. You can have the default callback
write the data to a different file handle by passing a 'FILE *' to a file
opened for writing with the CURLOPT_FILE option.
Now, we need to take a step back and have a deep breath. Here's one of those
rare platform-dependent nitpicks. Did you spot it? On some platforms[2],
libcurl won't be able to operate on files opened by the program. Thus, if you
use the default callback and pass in a an open file with CURLOPT_FILE, it
will crash. You should therefore avoid this to make your program run fine
virtually everywhere.
There are of course many more options you can set, and we'll get back to a
few of them later. Let's instead continue to the actual transfer:
success = curl_easy_perform(easyhandle);
The curl_easy_perform() will connect to the remote site, do the necessary
commands and receive the transfer. Whenever it receives data, it calls the
callback function we previously set. The function may get one byte at a time,
or it may get many kilobytes at once. libcurl delivers as much as possible as
often as possible. Your callback function should return the number of bytes
it "took care of". If that is not the exact same amount of bytes that was
passed to it, libcurl will abort the operation and return with an error code.
When the transfer is complete, the function returns a return code that
informs you if it succeeded in its mission or not. If a return code isn't
enough for you, you can use the CURLOPT_ERRORBUFFER to point libcurl to a
buffer of yours where it'll store a human readable error message as well.
If you then want to transfer another file, the handle is ready to be used
again. Mind you, it is even preferred that you re-use an existing handle if
you intend to make another transfer. libcurl will then attempt to re-use the
previous
When It Doesn't Work
There will always be times when the transfer fails for some reason. You might
have set the wrong libcurl option or misunderstood what the libcurl option
actually does, or the remote server might return non-standard replies that
confuse the library which then confuses your program.
There's one golden rule when these things occur: set the CURLOPT_VERBOSE
option to TRUE. It'll cause the library to spew out the entire protocol
details it sends, some internal info and some received protcol data as well
(especially when using FTP). If you're using HTTP, adding the headers in the
received output to study is also a clever way to get a better understanding
wht the server behaves the way it does. Include headers in the normal body
output with CURLOPT_HEADER set TRUE.
Of course there are bugs left. We need to get to know about them to be able
to fix them, so we're quite dependent on your bug reports! When you do report
suspected bugs in libcurl, please include as much details you possibly can: a
protocol dump that CURLOPT_VERBOSE produces, library version, as much as
possible of your code that uses libcurl, operating system name and version,
compiler name and version etc.
Getting some in-depth knowledge about the protocols involved is never wrong,
and if you're trying to funny things, you might very well understand libcurl
and how to use it better if you study the appropriate RFC documents at least
briefly.
Upload Data to a Remote Site
libcurl tries to keep a protocol independent approach to most transfers, thus
uploading to a remote FTP site is very similar to uploading data to a HTTP
server with a PUT request.
Of course, first you either create an easy handle or you re-use one existing
one. Then you set the URL to operate on just like before. This is the remote
URL, that we now will upload.
Since we write an application, we most likely want libcurl to get the upload
data by asking us for it. To make it do that, we set the read callback and
the custom pointer libcurl will pass to our read callback. The read callback
should have a prototype similar to:
size_t function(char *bufptr, size_t size, size_t nitems, void *userp);
Where bufptr is the pointer to a buffer we fill in with data to upload and
size*nitems is the size of the buffer and therefore also the maximum amount
of data we can return to libcurl in this call. The 'userp' pointer is the
custom pointer we set to point to a struct of ours to pass private data
between the application and the callback.
curl_easy_setopt(easyhandle, CURLOPT_READFUNCTION, read_function);
curl_easy_setopt(easyhandle, CURLOPT_INFILE, &filedata);
Tell libcurl that we want to upload:
curl_easy_setopt(easyhandle, CURLOPT_UPLOAD, TRUE);
A few protocols won't behave properly when uploads are done without any prior
knowledge of the expected file size. HTTP PUT is one example [1]. So, set the
upload file size using the CURLOPT_INFILESIZE like this:
curl_easy_setopt(easyhandle, CURLOPT_INFILESIZE, file_size);
When you call curl_easy_perform() this time, it'll perform all the necessary
operations and when it has invoked the upload it'll call your supplied
callback to get the data to upload. The program should return as much data as
possible in every invoke, as that is likely to make the upload perform as
fast as possible. The callback should return the number of bytes it wrote in
the buffer. Returning 0 will signal the end of the upload.
Passwords
Many protocols use or even require that user name and password are provided
to be able to download or upload the data of your choice. libcurl offers
several ways to specify them.
Most protocols support that you specify the name and password in the URL
itself. libcurl will detect this and use them accordingly. This is written
like this:
protocol://user:password@example.com/path/
If you need any odd letters in your user name or password, you should enter
them URL encoded, as %XX where XX is a two-digit hexadecimal number.
libcurl also provides options to set various passwords. The user name and
password as shown embedded in the URL can instead get set with the
CURLOPT_USERPWD option. The argument passed to libcurl should be a char * to
a string in the format "user:password:". In a manner like this:
curl_easy_setopt(easyhandle, CURLOPT_USERPWD, "myname:thesecret");
Another case where name and password might be needed at times, is for those
users who need to athenticate themselves to a proxy they use. libcurl offers
another option for this, the CURLOPT_PROXYUSERPWD. It is used quite similar
to the CURLOPT_USERPWD option like this:
curl_easy_setopt(easyhandle, CURLOPT_PROXYUSERPWD, "myname:thesecret");
There's a long time unix "standard" way of storing ftp user names and
passwords, namely in the $HOME/.netrc file. The file should be made private
so that only the user may read it (see also the "Security Considerations"
chapter), as it might contain the password in plain text. libcurl has the
ability to use this file to figure out what set of user name and password to
use for a particular host. As an extension to the normal functionality,
libcurl also supports this file for non-FTP protocols such as HTTP. To make
curl use this file, use the CURLOPT_NETRC option:
curl_easy_setopt(easyhandle, CURLOPT_NETRC, TRUE);
And a very basic example of how such a .netrc file may look like:
machine myhost.mydomain.com
login userlogin
password secretword
All these examples have been cases where the password has been optional, or
at least you could leave it out and have libcurl attempt to do its job
without it. There are times when the password isn't optional, like when
you're using an SSL private key for secure transfers.
You can in this situation either pass a password to libcurl to use to unlock
the private key, or you can let libcurl prompt the user for it. If you prefer
to ask the user, then you can provide your own callback function that will be
called when libcurl wants the password. That way, you can control how the
question will appear to the user.
To pass the known private key password to libcurl:
curl_easy_setopt(easyhandle, CURLOPT_SSLKEYPASSWD, "keypassword");
To make a password callback:
int enter_passwd(void *ourp, const char *prompt, char *buffer, int len);
curl_easy_setopt(easyhandle, CURLOPT_PASSWDFUNCTION, enter_passwd);
HTTP POSTing
We get many questions regarding how to issue HTTP POSTs with libcurl the
proper way. This chapter will thus include examples using both different
versions of HTTP POST that libcurl supports.
The first version is the simple POST, the most common version, that most HTML
pages using the <form> tag uses. We provide a pointer to the data and tell
libcurl to post it all to the remote site:
char *data="name=daniel&project=curl";
curl_easy_setopt(easyhandle, CURLOPT_POSTFIELDS, data);
curl_easy_setopt(easyhandle, CURLOPT_URL, "http://posthere.com/");
curl_easy_perform(easyhandle); /* post away! */
Simple enough, huh? Ok, so what if you want to post binary data that also
requires you to set the Content-Type: header of the post? Well, binary posts
prevents libcurl from being able to do strlen() on the data to figure out the
size, so therefore we must tell libcurl the size of the post data. Setting
headers in libcurl requests are done in a generic way, by building a list of
our own headers and then passing that list to libcurl.
struct curl_slist *headers=NULL;
headers = curl_slist_append(headers, "Content-Type: text/xml");
/* post binary data */
curl_easy_setopt(easyhandle, CURLOPT_POSTFIELD, binaryptr);
/* set the size of the postfields data */
curl_easy_setopt(easyhandle, CURLOPT_POSTFIELDSIZE, 23);
/* pass our list of custom made headers */
curl_easy_setopt(easyhandle, CURLOPT_HTTPHEADER, headers);
curl_easy_perform(easyhandle); /* post away! */
curl_slist_free_all(headers); /* free the header list */
While the simple examples above cover the majority of all cases where HTTP
POST operations are required, they don't do multipart formposts. Multipart
formposts were introduced as a better way to post (possibly large) binary
data and was first documented in the RFC1867. They're called multipart
because they're built by a chain of parts, each being a single unit. Each
part has its own name and contents. You can in fact create and post a
multipart formpost with the regular libcurl POST support described above, but
that would require that you build a formpost yourself and provide to
libcurl. To make that easier, libcurl provides curl_formadd(). Using this
function, you add parts to the form. When you're done adding parts, you post
the whole form.
The following example sets two simple text parts with plain textual contents,
and then a file with binary contents and upload the whole thing.
struct HttpPost *post=NULL;
struct HttpPost *last=NULL;
curl_formadd(&post, &last,
CURLFORM_COPYNAME, "name",
CURLFORM_COPYCONTENTS, "daniel", CURLFORM_END);
curl_formadd(&post, &last,
CURLFORM_COPYNAME, "project",
CURLFORM_COPYCONTENTS, "curl", CURLFORM_END);
curl_formadd(&post, &last,
CURLFORM_COPYNAME, "logotype-image",
CURLFORM_FILECONTENT, "curl.png", CURLFORM_END);
/* Set the form info */
curl_easy_setopt(easyhandle, CURLOPT_HTTPPOST, post);
curl_easy_perform(easyhandle); /* post away! */
/* free the post data again */
curl_formfree(post);
The multipart formposts are a chain of parts using MIME-style separators and
headers. That means that each of these separate parts get a few headers set
that describes its individual content-type, size etc. Now, to enable your
application to handicraft this formpost even more, libcurl allows you to
supply your own custom headers to an individual form part. You can of course
supply headers to as many parts you like, but this little example will show
how you have set headers to one specific part when you add that to post
handle:
struct curl_slist *headers=NULL;
headers = curl_slist_append(headers, "Content-Type: text/xml");
curl_formadd(&post, &last,
CURLFORM_COPYNAME, "logotype-image",
CURLFORM_FILECONTENT, "curl.xml",
CURLFORM_CONTENTHEADER, headers,
CURLFORM_END);
curl_easy_perform(easyhandle); /* post away! */
curl_formfree(post); /* free post */
curl_slist_free_all(post); /* free custom header list */
Showing Progress
libcurl with C++
There's basicly only one thing to keep in mind when using C++ instead of C
when interfacing libcurl:
"The Callbacks Must Be Plain C"
So if you want a write callback set in libcurl, you should put it within
'extern'. Similar to this:
extern "C" {
size_t write_data(void *ptr, size_t size, size_t nmemb,
void *ourpointer)
{
/* do what you want with the data */
}
}
This will of course effectively turn the callback code into C. There won't be
any "this" pointer available etc.
Proxies
What "proxy" means according to Merriam-Webster: "a person authorized to act
for another" but also "the agency, function, or office of a deputy who acts
as a substitute for another".
Proxies are exceedingly common these days. Companies often only offer
internet access to employees through their HTTP proxies. Network clients or
user-agents ask the proxy for docuements, the proxy does the actual request
and then it returns them.
libcurl has full support for HTTP proxies, so when a given URL is wanted,
libcurl will ask the proxy for it instead of trying to connect to the actual
host identified in the URL.
The fact that the proxy is a HTTP proxy puts certain restrictions on what can
actually happen. A requested URL that might not be a HTTP URL will be still
be passed to the HTTP proxy to deliver back to libcurl. This happens
transparantly, and an application may not need to know. I say "may", because
at times it is very important to understand that all operations over a HTTP
proxy is using the HTTP protocol. For example, you can't invoke your own
custom FTP commands or even proper FTP directory listings.
To tell libcurl to use a proxy at a given port number:
curl_easy_setopt(easyhandle, CURLOPT_PROXY, "proxy-host.com:8080");
Some proxies require user authentication before allowing a request, and you
pass that information similar to this:
curl_easy_setopt(easyhandle, CURLOPT_PROXYUSERPWD, "user:password");
[ environment variables, SSL, tunneling, automatic proxy config (.pac) ]
Security Considerations
[ ps output, netrc plain text, plain text protocols / base64 ]
Certificates and Other SSL Tricks
Future
-----
Footnotes:
[1] = HTTP PUT without knowing the size prior to transfer is indeed possible,
but libcurl does not support the chunked transfers on uploading that is
necessary for this feature to work. We'd gratefully appreciate patches
that bring this functionality...
[2] = This happens on Windows machines when libcurl is built and used as a
DLL. However, you can still do this on Windows if you link with a static
library.
[3] = The curl-config tool is generated at build-time (on unix-like systems)
and should be installed with the 'make install' or similar instruction
that installs the library, header files, man pages etc.

View File

@@ -30,11 +30,11 @@
# include <time.h> # include <time.h>
#else #else
# include <sys/types.h> # include <sys/types.h>
# if TIME_WITH_SYS_TIME # ifdef TIME_WITH_SYS_TIME
# include <sys/time.h> # include <sys/time.h>
# include <time.h> # include <time.h>
# else # else
# if HAVE_SYS_TIME_H # ifdef HAVE_SYS_TIME_H
# include <sys/time.h> # include <sys/time.h>
# else # else
# include <time.h> # include <time.h>
@@ -62,6 +62,7 @@ struct HttpPost {
char *contents; /* pointer to allocated data contents */ char *contents; /* pointer to allocated data contents */
long contentslength; /* length of contents field */ long contentslength; /* length of contents field */
char *contenttype; /* Content-Type */ char *contenttype; /* Content-Type */
struct curl_slist* contentheader; /* list of extra headers for this form */
struct HttpPost *more; /* if one field name has more than one file, this struct HttpPost *more; /* if one field name has more than one file, this
link should link to following files */ link should link to following files */
long flags; /* as defined below */ long flags; /* as defined below */
@@ -155,7 +156,9 @@ typedef enum {
CURLE_OBSOLETE, /* 50 - removed after 7.7.3 */ CURLE_OBSOLETE, /* 50 - removed after 7.7.3 */
CURLE_SSL_PEER_CERTIFICATE, /* 51 - peer's certificate wasn't ok */ CURLE_SSL_PEER_CERTIFICATE, /* 51 - peer's certificate wasn't ok */
CURLE_GOT_NOTHING, /* 52 - when this is a specific error */ CURLE_GOT_NOTHING, /* 52 - when this is a specific error */
CURLE_SSL_ENGINE_NOTFOUND, /* 53 - SSL crypto engine not found */
CURLE_SSL_ENGINE_SETFAILED, /* 54 - can not set SSL crypto engine as default */
CURL_LAST /* never use! */ CURL_LAST /* never use! */
} CURLcode; } CURLcode;
@@ -278,8 +281,10 @@ typedef enum {
/* name of the file keeping your private SSL-certificate */ /* name of the file keeping your private SSL-certificate */
CINIT(SSLCERT, OBJECTPOINT, 25), CINIT(SSLCERT, OBJECTPOINT, 25),
/* password for the SSL-certificate */ /* password for the SSL-private key, keep this for compatibility */
CINIT(SSLCERTPASSWD, OBJECTPOINT, 26), CINIT(SSLCERTPASSWD, OBJECTPOINT, 26),
/* password for the SSL private key */
CINIT(SSLKEYPASSWD, OBJECTPOINT, 26),
/* send TYPE parameter? */ /* send TYPE parameter? */
CINIT(CRLF, LONG, 27), CINIT(CRLF, LONG, 27),
@@ -465,6 +470,29 @@ typedef enum {
default, that one will always be attempted before the more traditional default, that one will always be attempted before the more traditional
PASV command. */ PASV command. */
CINIT(FTP_USE_EPSV, LONG, 85), CINIT(FTP_USE_EPSV, LONG, 85),
/* type of the file keeping your SSL-certificate ("DER", "PEM", "ENG") */
CINIT(SSLCERTTYPE, OBJECTPOINT, 86),
/* name of the file keeping your private SSL-key */
CINIT(SSLKEY, OBJECTPOINT, 87),
/* type of the file keeping your private SSL-key ("DER", "PEM", "ENG") */
CINIT(SSLKEYTYPE, OBJECTPOINT, 88),
/* crypto engine for the SSL-sub system */
CINIT(SSLENGINE, OBJECTPOINT, 89),
/* set the crypto engine for the SSL-sub system as default
the param has no meaning...
*/
CINIT(SSLENGINE_DEFAULT, LONG, 90),
/* Non-zero value means to use the global dns cache */
CINIT(DNS_USE_GLOBAL_CACHE, LONG, 91),
/* DNS cache timeout */
CINIT(DNS_CACHE_TIMEOUT, LONG, 92),
CURLOPT_LASTENTRY /* the last unusued */ CURLOPT_LASTENTRY /* the last unusued */
} CURLoption; } CURLoption;
@@ -543,6 +571,7 @@ typedef enum {
CFINIT(ARRAY_START), /* below are the options allowed within a array */ CFINIT(ARRAY_START), /* below are the options allowed within a array */
CFINIT(FILE), CFINIT(FILE),
CFINIT(CONTENTTYPE), CFINIT(CONTENTTYPE),
CFINIT(CONTENTHEADER),
CFINIT(END), CFINIT(END),
CFINIT(ARRAY_END), /* up are the options allowed within a array */ CFINIT(ARRAY_END), /* up are the options allowed within a array */
@@ -584,8 +613,8 @@ CURLcode curl_global_init(long flags);
void curl_global_cleanup(void); void curl_global_cleanup(void);
/* This is the version number */ /* This is the version number */
#define LIBCURL_VERSION "7.9.2" #define LIBCURL_VERSION "7.9.3"
#define LIBCURL_VERSION_NUM 0x070902 #define LIBCURL_VERSION_NUM 0x070903
/* linked-list structure for the CURLOPT_QUOTE option (and other) */ /* linked-list structure for the CURLOPT_QUOTE option (and other) */
struct curl_slist { struct curl_slist {

View File

@@ -56,7 +56,9 @@ escape.c mprintf.c telnet.c \
escape.h getpass.c netrc.c telnet.h \ escape.h getpass.c netrc.c telnet.h \
getinfo.c getinfo.h transfer.c strequal.c strequal.h easy.c \ getinfo.c getinfo.h transfer.c strequal.c strequal.h easy.c \
security.h security.c krb4.c krb4.h memdebug.c memdebug.h inet_ntoa_r.h \ security.h security.c krb4.c krb4.h memdebug.c memdebug.h inet_ntoa_r.h \
http_chunks.c http_chunks.h strtok.c strtok.h connect.c connect.h http_chunks.c http_chunks.h strtok.c strtok.h connect.c connect.h \
llist.c llist.h hash.c hash.h multi.c multi.h
noinst_HEADERS = setup.h transfer.h noinst_HEADERS = setup.h transfer.h

View File

@@ -35,14 +35,14 @@ libcurl_a_SOURCES = arpa_telnet.h file.c getpass.h netrc.h timeval.c base64.c \
ldap.h ssluse.h escape.c getenv.h mprintf.c telnet.c escape.h getpass.c netrc.c \ ldap.h ssluse.h escape.c getenv.h mprintf.c telnet.c escape.h getpass.c netrc.c \
telnet.h getinfo.c strequal.c strequal.h easy.c security.h \ telnet.h getinfo.c strequal.c strequal.h easy.c security.h \
security.c krb4.h krb4.c memdebug.h memdebug.c inet_ntoa_r.h http_chunks.h http_chunks.c \ security.c krb4.h krb4.c memdebug.h memdebug.c inet_ntoa_r.h http_chunks.h http_chunks.c \
strtok.c connect.c strtok.c connect.c hash.c llist.c
libcurl_a_OBJECTS = file.o timeval.o base64.o hostip.o progress.o \ libcurl_a_OBJECTS = file.o timeval.o base64.o hostip.o progress.o \
formdata.o cookie.o http.o sendf.o ftp.o url.o dict.o if2ip.o \ formdata.o cookie.o http.o sendf.o ftp.o url.o dict.o if2ip.o \
speedcheck.o getdate.o transfer.o ldap.o ssluse.o version.o \ speedcheck.o getdate.o transfer.o ldap.o ssluse.o version.o \
getenv.o escape.o mprintf.o telnet.o getpass.o netrc.o getinfo.o \ getenv.o escape.o mprintf.o telnet.o getpass.o netrc.o getinfo.o \
strequal.o easy.o security.o krb4.o memdebug.o http_chunks.o \ strequal.o easy.o security.o krb4.o memdebug.o http_chunks.o \
strtok.o connect.o strtok.o connect.o hash.o llist.o
LIBRARIES = $(libcurl_a_LIBRARIES) LIBRARIES = $(libcurl_a_LIBRARIES)
SOURCES = $(libcurl_a_SOURCES) SOURCES = $(libcurl_a_SOURCES)

View File

@@ -5,7 +5,7 @@
# Usage: see usage message below # Usage: see usage message below
# Should be invoked from \lib directory # Should be invoked from \lib directory
# Edit the paths and desired library name # Edit the paths and desired library name
# SSL path is only required if you intend compiling # SSL path is only required if you intend compiling
# with SSL. # with SSL.
# #
# This make file leaves the result either a .lib or .dll file # This make file leaves the result either a .lib or .dll file
@@ -17,13 +17,13 @@
# #
# Another option would have been to leave the .lib and .dll # Another option would have been to leave the .lib and .dll
# 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.
# #
############################################################## ##############################################################
# CHANGE LOG # CHANGE LOG
# ------------------------------------------------------------ # ------------------------------------------------------------
# 05.11.2001 John Lask Initial Release # 05.11.2001 John Lask Initial Release
# #
# #
############################################################## ##############################################################
@@ -50,7 +50,7 @@ CFGSET = FALSE
###################### ######################
# release # release
!IF "$(CFG)" == "release" !IF "$(CFG)" == "release"
TARGET =$(LIB_NAME).lib TARGET =$(LIB_NAME).lib
DIROBJ =.\$(CFG) DIROBJ =.\$(CFG)
LNK = $(LNKLIB) /out:$(TARGET) LNK = $(LNKLIB) /out:$(TARGET)
@@ -61,7 +61,7 @@ CFGSET = TRUE
###################### ######################
# release-dll # release-dll
!IF "$(CFG)" == "release-dll" !IF "$(CFG)" == "release-dll"
TARGET =$(LIB_NAME).dll TARGET =$(LIB_NAME).dll
DIROBJ =.\$(CFG) DIROBJ =.\$(CFG)
LNK = $(LNKDLL) /out:$(TARGET) /IMPLIB:"$(LIB_NAME).lib" LNK = $(LNKDLL) /out:$(TARGET) /IMPLIB:"$(LIB_NAME).lib"
@@ -72,25 +72,25 @@ CFGSET = TRUE
###################### ######################
# release-ssl # release-ssl
!IF "$(CFG)" == "release-ssl" !IF "$(CFG)" == "release-ssl"
TARGET =$(LIB_NAME).lib TARGET =$(LIB_NAME).lib
DIROBJ =.\$(CFG) DIROBJ =.\$(CFG)
LNK = $(LNKLIB) $(LFLAGSSSL) /out:$(TARGET) LNK = $(LNKLIB) $(LFLAGSSSL) /out:$(TARGET)
LINKLIBS = $(LINKLIBS) $(SSLLIBS) LINKLIBS = $(LINKLIBS) $(SSLLIBS)
CC = $(CCNODBG) $(CFLAGSSSL) CC = $(CCNODBG) $(CFLAGSSSL)
CFGSET = TRUE CFGSET = TRUE
!ENDIF !ENDIF
###################### ######################
# release-ssl-dll # release-ssl-dll
!IF "$(CFG)" == "release-ssl-dll" !IF "$(CFG)" == "release-ssl-dll"
TARGET =$(LIB_NAME).dll TARGET =$(LIB_NAME).dll
DIROBJ =.\$(CFG) DIROBJ =.\$(CFG)
LNK = $(LNKDLL) $(LFLAGSSSL) /out:$(TARGET) /IMPLIB:"$(LIB_NAME).lib" LNK = $(LNKDLL) $(LFLAGSSSL) /out:$(TARGET) /IMPLIB:"$(LIB_NAME).lib"
LINKLIBS = $(LINKLIBS) $(SSLLIBS) LINKLIBS = $(LINKLIBS) $(SSLLIBS)
CC = $(CCNODBG) $(CFLAGSSSL) CC = $(CCNODBG) $(CFLAGSSSL)
CFGSET = TRUE CFGSET = TRUE
!ENDIF !ENDIF
@@ -99,7 +99,7 @@ CFGSET = TRUE
###################### ######################
# debug # debug
!IF "$(CFG)" == "debug" !IF "$(CFG)" == "debug"
TARGET =$(LIB_NAME_DEBUG).lib TARGET =$(LIB_NAME_DEBUG).lib
DIROBJ =.\$(CFG) DIROBJ =.\$(CFG)
LNK = $(LNKLIB) /out:$(TARGET) LNK = $(LNKLIB) /out:$(TARGET)
@@ -110,7 +110,7 @@ CFGSET = TRUE
###################### ######################
# debug-dll # debug-dll
!IF "$(CFG)" == "debug-dll" !IF "$(CFG)" == "debug-dll"
TARGET =$(LIB_NAME_DEBUG).dll TARGET =$(LIB_NAME_DEBUG).dll
DIROBJ =.\$(CFG) DIROBJ =.\$(CFG)
LNK = $(LNKDLL) /out:$(TARGET) /IMPLIB:"$(LIB_NAME_DEBUG).lib" LNK = $(LNKDLL) /out:$(TARGET) /IMPLIB:"$(LIB_NAME_DEBUG).lib"
@@ -121,7 +121,7 @@ CFGSET = TRUE
###################### ######################
# debug-ssl # debug-ssl
#todo #todo
!IF "$(CFG)" == "debug-ssl" !IF "$(CFG)" == "debug-ssl"
TARGET = $(LIB_NAME_DEBUG).lib TARGET = $(LIB_NAME_DEBUG).lib
DIROBJ =.\$(CFG) DIROBJ =.\$(CFG)
LNK = $(LNKLIB) $(LFLAGSSSL) /out:$(TARGET) LNK = $(LNKLIB) $(LFLAGSSSL) /out:$(TARGET)
@@ -133,10 +133,10 @@ CFGSET = TRUE
###################### ######################
# debug-ssl-dll # debug-ssl-dll
!IF "$(CFG)" == "debug-ssl-dll" !IF "$(CFG)" == "debug-ssl-dll"
TARGET =$(LIB_NAME_DEBUG).dll TARGET =$(LIB_NAME_DEBUG).dll
DIROBJ =.\$(CFG) DIROBJ =.\$(CFG)
LNK = $(LNKDLL) $(LFLAGSSSL) /out:$(TARGET) /IMPLIB:"$(LIB_NAME_DEBUG).lib" LNK = $(LNKDLL) $(LFLAGSSSL) /out:$(TARGET) /IMPLIB:"$(LIB_NAME_DEBUG).lib"
LINKLIBS = $(LINKLIBS) $(SSLLIBS) LINKLIBS = $(LINKLIBS) $(SSLLIBS)
CC = $(CCDEBUG) $(CFLAGSSSL) CC = $(CCDEBUG) $(CFLAGSSSL)
CFGSET = TRUE CFGSET = TRUE
@@ -193,8 +193,9 @@ X_OBJS= \
$(DIROBJ)\easy.obj \ $(DIROBJ)\easy.obj \
$(DIROBJ)\strequal.obj \ $(DIROBJ)\strequal.obj \
$(DIROBJ)\strtok.obj \ $(DIROBJ)\strtok.obj \
$(DIROBJ)\connect.obj $(DIROBJ)\connect.obj \
$(DIROBJ)\hash.obj \
$(DIROBJ)\llist.obj
all : $(TARGET) all : $(TARGET)

View File

@@ -193,7 +193,7 @@ static CURLcode bindlocal(struct connectdata *conn,
#ifdef HAVE_INET_NTOA #ifdef HAVE_INET_NTOA
#ifndef INADDR_NONE #ifndef INADDR_NONE
#define INADDR_NONE (unsigned long) ~0 #define INADDR_NONE (in_addr_t) ~0
#endif #endif
struct SessionHandle *data = conn->data; struct SessionHandle *data = conn->data;
@@ -207,14 +207,14 @@ static CURLcode bindlocal(struct connectdata *conn,
char *hostdataptr=NULL; char *hostdataptr=NULL;
size_t size; size_t size;
char myhost[256] = ""; char myhost[256] = "";
unsigned long in; in_addr_t in;
if(Curl_if2ip(data->set.device, myhost, sizeof(myhost))) { if(Curl_if2ip(data->set.device, myhost, sizeof(myhost))) {
h = Curl_getaddrinfo(data, myhost, 0, &hostdataptr); h = Curl_resolv(data, myhost, 0, &hostdataptr);
} }
else { else {
if(strlen(data->set.device)>1) { if(strlen(data->set.device)>1) {
h = Curl_getaddrinfo(data, data->set.device, 0, &hostdataptr); h = Curl_resolv(data, data->set.device, 0, &hostdataptr);
} }
if(h) { if(h) {
/* we know data->set.device is shorter than the myhost array */ /* we know data->set.device is shorter than the myhost array */
@@ -229,14 +229,13 @@ static CURLcode bindlocal(struct connectdata *conn,
hostent_buf, hostent_buf,
sizeof(hostent_buf)); sizeof(hostent_buf));
*/ */
if(hostdataptr)
free(hostdataptr); /* allocated by Curl_getaddrinfo() */
return CURLE_HTTP_PORT_FAILED; return CURLE_HTTP_PORT_FAILED;
} }
infof(data, "We bind local end to %s\n", myhost); infof(data, "We bind local end to %s\n", myhost);
if ( (in=inet_addr(myhost)) != INADDR_NONE ) { in=inet_addr(myhost);
if (INADDR_NONE != in) {
if ( h ) { if ( h ) {
memset((char *)&sa, 0, sizeof(sa)); memset((char *)&sa, 0, sizeof(sa));
@@ -284,7 +283,7 @@ static CURLcode bindlocal(struct connectdata *conn,
failf(data, "Insufficient kernel memory was available: %d", errno); failf(data, "Insufficient kernel memory was available: %d", errno);
break; break;
default: default:
failf(data, "errno %d\n", errno); failf(data, "errno %d", errno);
break; break;
} /* end of switch(errno) */ } /* end of switch(errno) */
@@ -303,9 +302,6 @@ static CURLcode bindlocal(struct connectdata *conn,
return CURLE_HTTP_PORT_FAILED; return CURLE_HTTP_PORT_FAILED;
} }
if(hostdataptr)
free(hostdataptr); /* allocated by Curl_getaddrinfo() */
return CURLE_OK; return CURLE_OK;
} /* end of device selection support */ } /* end of device selection support */
@@ -373,9 +369,11 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */
/* subtract the passed time */ /* subtract the passed time */
timeout_ms -= (long)has_passed; timeout_ms -= (long)has_passed;
if(timeout_ms < 0) if(timeout_ms < 0) {
/* a precaution, no need to continue if time already is up */ /* a precaution, no need to continue if time already is up */
failf(data, "Connection time-out");
return CURLE_OPERATION_TIMEOUTED; return CURLE_OPERATION_TIMEOUTED;
}
} }
#ifdef ENABLE_IPV6 #ifdef ENABLE_IPV6
@@ -452,8 +450,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */
return CURLE_COULDNT_CONNECT; return CURLE_COULDNT_CONNECT;
} }
/* now disable the non-blocking mode again */ /* leave the socket in non-blocking mode */
Curl_nonblock(sockfd, FALSE);
if(addr) if(addr)
*addr = ai; /* the address we ended up connected to */ *addr = ai; /* the address we ended up connected to */
@@ -558,9 +555,8 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */
failf(data, "Couldn't connect to host"); failf(data, "Couldn't connect to host");
return CURLE_COULDNT_CONNECT; return CURLE_COULDNT_CONNECT;
} }
/* now disable the non-blocking mode again */ /* leave the socket in non-blocking mode */
Curl_nonblock(sockfd, FALSE);
if(addr) if(addr)
/* this is the address we've connected to */ /* this is the address we've connected to */

View File

@@ -194,6 +194,11 @@ Curl_cookie_add(struct CookieInfo *c,
while(ptr && *ptr && isspace((int)*ptr)) while(ptr && *ptr && isspace((int)*ptr))
ptr++; ptr++;
semiptr=strchr(ptr, ';'); /* now, find the next semicolon */ semiptr=strchr(ptr, ';'); /* now, find the next semicolon */
if(!semiptr && *ptr)
/* There are no more semicolons, but there's a final name=value pair
coming up */
semiptr=ptr;
} while(semiptr); } while(semiptr);
if(NULL == co->domain) if(NULL == co->domain)
@@ -377,8 +382,15 @@ Curl_cookie_add(struct CookieInfo *c,
free(co); /* free the newly alloced memory */ free(co); /* free the newly alloced memory */
co = clist; /* point to the previous struct instead */ co = clist; /* point to the previous struct instead */
}
/* We have replaced a cookie, now skip the rest of the list but
make sure the 'lastc' pointer is properly set */
do {
lastc = clist;
clist = clist->next;
} while(clist);
break;
}
} }
lastc = clist; lastc = clist;
clist = clist->next; clist = clist->next;

View File

@@ -151,6 +151,10 @@ SOURCE=.\getpass.c
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=.\hash.c
# End Source File
# Begin Source File
SOURCE=.\hostip.c SOURCE=.\hostip.c
# End Source File # End Source File
# Begin Source File # Begin Source File
@@ -179,6 +183,10 @@ SOURCE=.\libcurl.def
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=.\llist.c
# End Source File
# Begin Source File
SOURCE=.\memdebug.c SOURCE=.\memdebug.c
# End Source File # End Source File
# Begin Source File # Begin Source File

View File

@@ -121,7 +121,7 @@ CURLcode Curl_dict(struct connectdata *conn)
} }
if ((word == NULL) || (*word == (char)0)) { if ((word == NULL) || (*word == (char)0)) {
failf(data, "lookup word is missing\n"); failf(data, "lookup word is missing");
} }
if ((database == NULL) || (*database == (char)0)) { if ((database == NULL) || (*database == (char)0)) {
database = (char *)"!"; database = (char *)"!";
@@ -174,7 +174,7 @@ CURLcode Curl_dict(struct connectdata *conn)
} }
if ((word == NULL) || (*word == (char)0)) { if ((word == NULL) || (*word == (char)0)) {
failf(data, "lookup word is missing\n"); failf(data, "lookup word is missing");
} }
if ((database == NULL) || (*database == (char)0)) { if ((database == NULL) || (*database == (char)0)) {
database = (char *)"!"; database = (char *)"!";

View File

@@ -76,6 +76,7 @@
#include "ssluse.h" #include "ssluse.h"
#include "url.h" #include "url.h"
#include "getinfo.h" #include "getinfo.h"
#include "hostip.h"
#define _MPRINTF_REPLACE /* use our functions only */ #define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h> #include <curl/mprintf.h>
@@ -139,7 +140,7 @@ CURLcode curl_global_init(long flags)
{ {
if (initialized) if (initialized)
return CURLE_OK; return CURLE_OK;
if (flags & CURL_GLOBAL_SSL) if (flags & CURL_GLOBAL_SSL)
Curl_SSL_init(); Curl_SSL_init();
@@ -162,6 +163,8 @@ void curl_global_cleanup(void)
if (!initialized) if (!initialized)
return; return;
Curl_global_host_cache_dtor();
if (init_flags & CURL_GLOBAL_SSL) if (init_flags & CURL_GLOBAL_SSL)
Curl_SSL_cleanup(); Curl_SSL_cleanup();
@@ -230,12 +233,24 @@ CURLcode curl_easy_perform(CURL *curl)
{ {
struct SessionHandle *data = (struct SessionHandle *)curl; struct SessionHandle *data = (struct SessionHandle *)curl;
if (!data->hostcache) {
if (Curl_global_host_cache_use(data)) {
data->hostcache = Curl_global_host_cache_get();
}
else {
data->hostcache = curl_hash_alloc(7, Curl_freeaddrinfo);
}
}
return Curl_perform(data); return Curl_perform(data);
} }
void curl_easy_cleanup(CURL *curl) void curl_easy_cleanup(CURL *curl)
{ {
struct SessionHandle *data = (struct SessionHandle *)curl; struct SessionHandle *data = (struct SessionHandle *)curl;
if (!Curl_global_host_cache_use(data)) {
curl_hash_destroy(data->hostcache);
}
Curl_close(data); Curl_close(data);
} }

View File

@@ -396,15 +396,16 @@ int curl_formparse(char *input,
* Returns newly allocated HttpPost on success and NULL if malloc failed. * Returns newly allocated HttpPost on success and NULL if malloc failed.
* *
***************************************************************************/ ***************************************************************************/
static struct HttpPost * AddHttpPost (char * name, static struct HttpPost * AddHttpPost(char * name,
long namelength, long namelength,
char * value, char * value,
long contentslength, long contentslength,
char *contenttype, char *contenttype,
long flags, long flags,
struct HttpPost *parent_post, struct curl_slist* contentHeader,
struct HttpPost **httppost, struct HttpPost *parent_post,
struct HttpPost **last_post) struct HttpPost **httppost,
struct HttpPost **last_post)
{ {
struct HttpPost *post; struct HttpPost *post;
post = (struct HttpPost *)malloc(sizeof(struct HttpPost)); post = (struct HttpPost *)malloc(sizeof(struct HttpPost));
@@ -415,6 +416,7 @@ static struct HttpPost * AddHttpPost (char * name,
post->contents = value; post->contents = value;
post->contentslength = contentslength; post->contentslength = contentslength;
post->contenttype = contenttype; post->contenttype = contenttype;
post->contentheader = contentHeader;
post->flags = flags; post->flags = flags;
} }
else else
@@ -823,6 +825,21 @@ FORMcode FormAdd(struct HttpPost **httppost,
} }
break; break;
} }
case CURLFORM_CONTENTHEADER:
{
struct curl_slist* list = NULL;
if( array_state )
list = (struct curl_slist*)array_value;
else
list = va_arg(params,struct curl_slist*);
if( current_form->contentheader )
return_value = FORMADD_OPTION_TWICE;
else
current_form->contentheader = list;
break;
}
default: default:
fprintf (stderr, "got unknown CURLFORM_OPTION: %d\n", option); fprintf (stderr, "got unknown CURLFORM_OPTION: %d\n", option);
return_value = FORMADD_UNKNOWN_OPTION; return_value = FORMADD_UNKNOWN_OPTION;
@@ -872,13 +889,16 @@ FORMcode FormAdd(struct HttpPost **httppost,
break; break;
} }
} }
if ( (post = AddHttpPost(form->name, form->namelength, post = AddHttpPost(form->name, form->namelength,
form->value, form->contentslength, form->value, form->contentslength,
form->contenttype, form->flags, form->contenttype, form->flags,
post, httppost, form->contentheader,
last_post)) == NULL) { post, httppost,
last_post);
if(!post)
return_value = FORMADD_MEMORY; return_value = FORMADD_MEMORY;
}
if (form->contenttype) if (form->contenttype)
prevtype = form->contenttype; prevtype = form->contenttype;
} }
@@ -1029,6 +1049,8 @@ struct FormData *Curl_getFormData(struct HttpPost *post,
int size =0; int size =0;
char *boundary; char *boundary;
char *fileboundary=NULL; char *fileboundary=NULL;
struct curl_slist* curList;
if(!post) if(!post)
return NULL; /* no input => no output! */ return NULL; /* no input => no output! */
@@ -1090,6 +1112,13 @@ struct FormData *Curl_getFormData(struct HttpPost *post,
file->contenttype); file->contenttype);
} }
curList = file->contentheader;
while( curList ) {
/* Process the additional headers specified for this form */
size += AddFormDataf( &form, "\r\n%s", curList->data );
curList = curList->next;
}
#if 0 #if 0
/* The header Content-Transfer-Encoding: seems to confuse some receivers /* The header Content-Transfer-Encoding: seems to confuse some receivers
* (like the built-in PHP engine). While I can't see any reason why it * (like the built-in PHP engine). While I can't see any reason why it
@@ -1126,10 +1155,13 @@ struct FormData *Curl_getFormData(struct HttpPost *post,
} }
if(fileread != stdin) if(fileread != stdin)
fclose(fileread); fclose(fileread);
} else {
size += AddFormData(&form, "[File wasn't found by client]", 0);
} }
} else { else {
/* File wasn't found, add a nothing field! */
size += AddFormData(&form, "", 0);
}
}
else {
/* include the contents we got */ /* include the contents we got */
size += AddFormData(&form, post->contents, post->contentslength); size += AddFormData(&form, post->contents, post->contentslength);
} }

View File

@@ -44,6 +44,7 @@ typedef struct FormInfo {
long contentslength; long contentslength;
char *contenttype; char *contenttype;
long flags; long flags;
struct curl_slist* contentheader;
struct FormInfo *more; struct FormInfo *more;
} FormInfo; } FormInfo;

129
lib/ftp.c
View File

@@ -84,6 +84,10 @@
#include "ssluse.h" #include "ssluse.h"
#include "connect.h" #include "connect.h"
#if defined(HAVE_INET_NTOA_R) && !defined(HAVE_INET_NTOA_R_DECL)
#include "inet_ntoa_r.h"
#endif
#define _MPRINTF_REPLACE /* use our functions only */ #define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h> #include <curl/mprintf.h>
@@ -192,9 +196,12 @@ int Curl_GetFTPResponse(char *buf,
char *line_start; char *line_start;
int code=0; /* default "error code" to return */ int code=0; /* default "error code" to return */
#define SELECT_OK 0 #define SELECT_OK 0
#define SELECT_ERROR 1 #define SELECT_ERROR 1 /* select() problems */
#define SELECT_TIMEOUT 2 #define SELECT_TIMEOUT 2 /* took too long */
#define SELECT_MEMORY 3 /* no available memory */
#define SELECT_CALLBACK 4 /* aborted by callback */
int error = SELECT_OK; int error = SELECT_OK;
struct FTP *ftp = conn->proto.ftp; struct FTP *ftp = conn->proto.ftp;
@@ -260,9 +267,16 @@ int Curl_GetFTPResponse(char *buf,
ftp->cache = NULL; /* clear the pointer */ ftp->cache = NULL; /* clear the pointer */
ftp->cache_size = 0; /* zero the size just in case */ ftp->cache_size = 0; /* zero the size just in case */
} }
else if(CURLE_OK != Curl_read(conn, sockfd, ptr, else {
BUFSIZE-nread, &gotbytes)) int res = Curl_read(conn, sockfd, ptr,
keepon = FALSE; BUFSIZE-nread, &gotbytes);
if(res < 0)
/* EWOULDBLOCK */
continue; /* go looping again */
if(CURLE_OK != res)
keepon = FALSE;
}
if(!keepon) if(!keepon)
; ;
@@ -283,6 +297,7 @@ int Curl_GetFTPResponse(char *buf,
if(*ptr=='\n') { if(*ptr=='\n') {
/* a newline is CRLF in ftp-talk, so the CR is ignored as /* a newline is CRLF in ftp-talk, so the CR is ignored as
the line isn't really terminated until the LF comes */ the line isn't really terminated until the LF comes */
CURLcode result;
/* output debug output if that is requested */ /* output debug output if that is requested */
if(data->set.verbose) { if(data->set.verbose) {
@@ -291,6 +306,16 @@ int Curl_GetFTPResponse(char *buf,
/* no need to output LF here, it is part of the data */ /* no need to output LF here, it is part of the data */
} }
/*
* We pass all response-lines to the callback function registered
* for "headers". The response lines can be seen as a kind of
* headers.
*/
result = Curl_client_write(data, CLIENTWRITE_HEADER,
line_start, perline);
if(result)
return -SELECT_CALLBACK;
#define lastline(line) (isdigit((int)line[0]) && isdigit((int)line[1]) && \ #define lastline(line) (isdigit((int)line[0]) && isdigit((int)line[1]) && \
isdigit((int)line[2]) && (' ' == line[3])) isdigit((int)line[2]) && (' ' == line[3]))
@@ -324,7 +349,7 @@ int Curl_GetFTPResponse(char *buf,
if(ftp->cache) if(ftp->cache)
memcpy(ftp->cache, line_start, ftp->cache_size); memcpy(ftp->cache, line_start, ftp->cache_size);
else else
return CURLE_OUT_OF_MEMORY; /**BANG**/ return -SELECT_MEMORY; /**BANG**/
} }
} /* there was data */ } /* there was data */
} /* if(no error) */ } /* if(no error) */
@@ -333,7 +358,7 @@ int Curl_GetFTPResponse(char *buf,
if(!error) if(!error)
code = atoi(buf); code = atoi(buf);
#if KRB4 #ifdef KRB4
/* handle the security-oriented responses 6xx ***/ /* handle the security-oriented responses 6xx ***/
/* FIXME: some errorchecking perhaps... ***/ /* FIXME: some errorchecking perhaps... ***/
switch(code) { switch(code) {
@@ -847,13 +872,17 @@ ftp_pasv_verbose(struct connectdata *conn,
#ifdef HAVE_INET_NTOA_R #ifdef HAVE_INET_NTOA_R
char ntoa_buf[64]; char ntoa_buf[64];
#endif #endif
char hostent_buf[9000]; /* The array size trick below is to make this a large chunk of memory
suitably 8-byte aligned on 64-bit platforms. This was thoughtfully
suggested by Philip Gladstone. */
long bigbuf[9000 / sizeof(long)];
#if defined(HAVE_INET_ADDR) #if defined(HAVE_INET_ADDR)
in_addr_t address; in_addr_t address;
# if defined(HAVE_GETHOSTBYADDR_R) # if defined(HAVE_GETHOSTBYADDR_R)
int h_errnop; int h_errnop;
# endif # endif
char *hostent_buf = (char *)bigbuf; /* get a char * to the buffer */
address = inet_addr(newhost); address = inet_addr(newhost);
# ifdef HAVE_GETHOSTBYADDR_R # ifdef HAVE_GETHOSTBYADDR_R
@@ -882,7 +911,7 @@ ftp_pasv_verbose(struct connectdata *conn,
# ifdef HAVE_GETHOSTBYADDR_R_7 # ifdef HAVE_GETHOSTBYADDR_R_7
/* Solaris and IRIX */ /* Solaris and IRIX */
answer = gethostbyaddr_r((char *) &address, sizeof(address), AF_INET, answer = gethostbyaddr_r((char *) &address, sizeof(address), AF_INET,
(struct hostent *)hostent_buf, (struct hostent *)bigbuf,
hostent_buf + sizeof(*answer), hostent_buf + sizeof(*answer),
sizeof(hostent_buf) - sizeof(*answer), sizeof(hostent_buf) - sizeof(*answer),
&h_errnop); &h_errnop);
@@ -1169,30 +1198,30 @@ CURLcode ftp_use_port(struct connectdata *conn)
struct sockaddr_in sa; struct sockaddr_in sa;
struct hostent *h=NULL; struct hostent *h=NULL;
char *hostdataptr=NULL; char *hostdataptr=NULL;
size_t size;
unsigned short porttouse; unsigned short porttouse;
char myhost[256] = ""; char myhost[256] = "";
if(data->set.ftpport) { if(data->set.ftpport) {
if(Curl_if2ip(data->set.ftpport, myhost, sizeof(myhost))) { if(Curl_if2ip(data->set.ftpport, myhost, sizeof(myhost))) {
h = Curl_getaddrinfo(data, myhost, 0, &hostdataptr); h = Curl_resolv(data, myhost, 0, &hostdataptr);
} }
else { else {
if(strlen(data->set.ftpport)>1) int len = strlen(data->set.ftpport);
h = Curl_getaddrinfo(data, data->set.ftpport, 0, &hostdataptr); if(len>1)
h = Curl_resolv(data, data->set.ftpport, 0, &hostdataptr);
if(h) if(h)
strcpy(myhost, data->set.ftpport); /* buffer overflow risk */ strcpy(myhost, data->set.ftpport); /* buffer overflow risk */
} }
} }
if(! *myhost) { if(! *myhost) {
h=Curl_getaddrinfo(data, char *tmp_host = getmyhost(myhost, sizeof(myhost));
getmyhost(myhost, sizeof(myhost)), h=Curl_resolv(data, tmp_host, 0, &hostdataptr);
0, &hostdataptr);
} }
infof(data, "We connect from %s\n", myhost); infof(data, "We connect from %s\n", myhost);
if ( h ) { if ( h ) {
if( (portsock = socket(AF_INET, SOCK_STREAM, 0)) >= 0 ) { if( (portsock = socket(AF_INET, SOCK_STREAM, 0)) >= 0 ) {
int size;
/* we set the secondary socket variable to this for now, it /* we set the secondary socket variable to this for now, it
is only so that the cleanup function will close it in case is only so that the cleanup function will close it in case
@@ -1211,10 +1240,10 @@ CURLcode ftp_use_port(struct connectdata *conn)
if(bind(portsock, (struct sockaddr *)&sa, size) >= 0) { if(bind(portsock, (struct sockaddr *)&sa, size) >= 0) {
/* we succeeded to bind */ /* we succeeded to bind */
struct sockaddr_in add; struct sockaddr_in add;
size = sizeof(add); socklen_t socksize = sizeof(add);
if(getsockname(portsock, (struct sockaddr *) &add, if(getsockname(portsock, (struct sockaddr *) &add,
(socklen_t *)&size)<0) { &socksize)<0) {
failf(data, "getsockname() failed"); failf(data, "getsockname() failed");
return CURLE_FTP_PORT_FAILED; return CURLE_FTP_PORT_FAILED;
} }
@@ -1237,9 +1266,6 @@ CURLcode ftp_use_port(struct connectdata *conn)
free(hostdataptr); free(hostdataptr);
return CURLE_FTP_PORT_FAILED; return CURLE_FTP_PORT_FAILED;
} }
if(hostdataptr)
/* free the memory used for name lookup */
Curl_freeaddrinfo(hostdataptr);
} }
else { else {
failf(data, "could't find my own IP address (%s)", myhost); failf(data, "could't find my own IP address (%s)", myhost);
@@ -1431,7 +1457,7 @@ CURLcode ftp_use_pasv(struct connectdata *conn)
} }
else { else {
/* normal, direct, ftp connection */ /* normal, direct, ftp connection */
addr = Curl_getaddrinfo(data, newhostp, newport, &hostdataptr); addr = Curl_resolv(data, newhostp, newport, &hostdataptr);
if(!addr) { if(!addr) {
failf(data, "Can't resolve new host %s", newhost); failf(data, "Can't resolve new host %s", newhost);
return CURLE_FTP_CANT_GET_HOST; return CURLE_FTP_CANT_GET_HOST;
@@ -1450,9 +1476,6 @@ CURLcode ftp_use_pasv(struct connectdata *conn)
/* this just dumps information about this second connection */ /* this just dumps information about this second connection */
ftp_pasv_verbose(conn, conninfo, newhost, connectport); ftp_pasv_verbose(conn, conninfo, newhost, connectport);
if(hostdataptr)
Curl_freeaddrinfo(hostdataptr);
if(CURLE_OK != result) if(CURLE_OK != result)
return result; return result;
@@ -1517,9 +1540,10 @@ CURLcode ftp_perform(struct connectdata *conn)
return result; return result;
} }
/* If we have selected NOBODY, it means that we only want file information. /* If we have selected NOBODY and HEADER, it means that we only want file
Which in FTP can't be much more than the file size! */ information. Which in FTP can't be much more than the file size and
if(data->set.no_body) { date. */
if(data->set.no_body && data->set.include_header) {
/* The SIZE command is _not_ RFC 959 specified, and therefor many servers /* The SIZE command is _not_ RFC 959 specified, and therefor many servers
may not support it! It is however the only way we have to get a file's may not support it! It is however the only way we have to get a file's
size! */ size! */
@@ -1565,20 +1589,27 @@ CURLcode ftp_perform(struct connectdata *conn)
return CURLE_OK; return CURLE_OK;
} }
if(data->set.no_body)
/* don't transfer the data */
;
/* Get us a second connection up and connected */ /* Get us a second connection up and connected */
if(data->set.ftp_use_port) else if(data->set.ftp_use_port) {
/* We have chosen to use the PORT command */ /* We have chosen to use the PORT command */
result = ftp_use_port(conn); result = ftp_use_port(conn);
else if(CURLE_OK == result)
/* we have the data connection ready */
infof(data, "Connected the data stream with PORT!\n");
}
else {
/* We have chosen (this is default) to use the PASV command */ /* We have chosen (this is default) to use the PASV command */
result = ftp_use_pasv(conn); result = ftp_use_pasv(conn);
if(CURLE_OK == result)
infof(data, "Connected the data stream with PASV!\n");
}
if(result) if(result)
return result; return result;
/* we have the data connection ready */
infof(data, "Connected the data stream!\n");
if(data->set.upload) { if(data->set.upload) {
/* Set type to binary (unless specified ASCII) */ /* Set type to binary (unless specified ASCII) */
@@ -1634,7 +1665,7 @@ CURLcode ftp_perform(struct connectdata *conn)
passed += actuallyread; passed += actuallyread;
if(actuallyread != readthisamountnow) { if(actuallyread != readthisamountnow) {
failf(data, "Could only read %d bytes from the input\n", passed); failf(data, "Could only read %d bytes from the input", passed);
return CURLE_FTP_COULDNT_USE_REST; return CURLE_FTP_COULDNT_USE_REST;
} }
} }
@@ -1701,7 +1732,7 @@ CURLcode ftp_perform(struct connectdata *conn)
return result; return result;
} }
else { else if(!data->set.no_body) {
/* Retrieve file or directory */ /* Retrieve file or directory */
bool dirlist=FALSE; bool dirlist=FALSE;
long downloadsize=-1; long downloadsize=-1;
@@ -2027,9 +2058,11 @@ CURLcode Curl_ftp(struct connectdata *conn)
CURLcode Curl_ftpsendf(struct connectdata *conn, CURLcode Curl_ftpsendf(struct connectdata *conn,
const char *fmt, ...) const char *fmt, ...)
{ {
size_t bytes_written; ssize_t bytes_written;
char s[256]; char s[256];
size_t write_len; ssize_t write_len;
char *sptr=s;
CURLcode res = CURLE_OK;
va_list ap; va_list ap;
va_start(ap, fmt); va_start(ap, fmt);
@@ -2043,9 +2076,23 @@ CURLcode Curl_ftpsendf(struct connectdata *conn,
bytes_written=0; bytes_written=0;
write_len = strlen(s); write_len = strlen(s);
Curl_write(conn, conn->firstsocket, s, write_len, &bytes_written);
return (bytes_written==write_len)?CURLE_OK:CURLE_WRITE_ERROR; do {
res = Curl_write(conn, conn->firstsocket, sptr, write_len,
&bytes_written);
if(CURLE_OK != res)
break;
if(bytes_written != write_len) {
write_len -= bytes_written;
sptr += bytes_written;
}
else
break;
} while(1);
return res;
} }
/*********************************************************************** /***********************************************************************

View File

@@ -45,6 +45,11 @@
# endif # endif
#endif #endif
#ifndef YYDEBUG
/* to satisfy gcc -Wundef, we set this to 0 */
#define YYDEBUG 0
#endif
/* Since the code of getdate.y is not included in the Emacs executable /* Since the code of getdate.y is not included in the Emacs executable
itself, there is no need to #define static in this file. Even if itself, there is no need to #define static in this file. Even if
the code were included in the Emacs executable, it probably the code were included in the Emacs executable, it probably
@@ -223,7 +228,7 @@ static int yyRelSeconds;
static int yyRelYear; static int yyRelYear;
#line 206 "getdate.y" #line 211 "getdate.y"
typedef union { typedef union {
int Number; int Number;
enum _MERIDIAN Meridian; enum _MERIDIAN Meridian;
@@ -306,11 +311,11 @@ static const short yyrhs[] = { -1,
#if YYDEBUG != 0 #if YYDEBUG != 0
static const short yyrline[] = { 0, static const short yyrline[] = { 0,
222, 223, 226, 229, 232, 235, 238, 241, 244, 250, 227, 228, 231, 234, 237, 240, 243, 246, 249, 255,
256, 265, 271, 283, 286, 289, 295, 299, 303, 309, 261, 270, 276, 288, 291, 294, 300, 304, 308, 314,
313, 331, 337, 343, 347, 352, 356, 363, 371, 374, 318, 336, 342, 348, 352, 357, 361, 368, 376, 379,
377, 380, 383, 386, 389, 392, 395, 398, 401, 404, 382, 385, 388, 391, 394, 397, 400, 403, 406, 409,
407, 410, 413, 416, 419, 422, 425, 430, 463, 467 412, 415, 418, 421, 424, 427, 430, 435, 468, 472
}; };
#endif #endif
@@ -934,37 +939,37 @@ yyreduce:
switch (yyn) { switch (yyn) {
case 3: case 3:
#line 226 "getdate.y" #line 231 "getdate.y"
{ {
yyHaveTime++; yyHaveTime++;
; ;
break;} break;}
case 4: case 4:
#line 229 "getdate.y" #line 234 "getdate.y"
{ {
yyHaveZone++; yyHaveZone++;
; ;
break;} break;}
case 5: case 5:
#line 232 "getdate.y" #line 237 "getdate.y"
{ {
yyHaveDate++; yyHaveDate++;
; ;
break;} break;}
case 6: case 6:
#line 235 "getdate.y" #line 240 "getdate.y"
{ {
yyHaveDay++; yyHaveDay++;
; ;
break;} break;}
case 7: case 7:
#line 238 "getdate.y" #line 243 "getdate.y"
{ {
yyHaveRel++; yyHaveRel++;
; ;
break;} break;}
case 9: case 9:
#line 244 "getdate.y" #line 249 "getdate.y"
{ {
yyHour = yyvsp[-1].Number; yyHour = yyvsp[-1].Number;
yyMinutes = 0; yyMinutes = 0;
@@ -973,7 +978,7 @@ case 9:
; ;
break;} break;}
case 10: case 10:
#line 250 "getdate.y" #line 255 "getdate.y"
{ {
yyHour = yyvsp[-3].Number; yyHour = yyvsp[-3].Number;
yyMinutes = yyvsp[-1].Number; yyMinutes = yyvsp[-1].Number;
@@ -982,7 +987,7 @@ case 10:
; ;
break;} break;}
case 11: case 11:
#line 256 "getdate.y" #line 261 "getdate.y"
{ {
yyHour = yyvsp[-3].Number; yyHour = yyvsp[-3].Number;
yyMinutes = yyvsp[-1].Number; yyMinutes = yyvsp[-1].Number;
@@ -994,7 +999,7 @@ case 11:
; ;
break;} break;}
case 12: case 12:
#line 265 "getdate.y" #line 270 "getdate.y"
{ {
yyHour = yyvsp[-5].Number; yyHour = yyvsp[-5].Number;
yyMinutes = yyvsp[-3].Number; yyMinutes = yyvsp[-3].Number;
@@ -1003,7 +1008,7 @@ case 12:
; ;
break;} break;}
case 13: case 13:
#line 271 "getdate.y" #line 276 "getdate.y"
{ {
yyHour = yyvsp[-5].Number; yyHour = yyvsp[-5].Number;
yyMinutes = yyvsp[-3].Number; yyMinutes = yyvsp[-3].Number;
@@ -1016,53 +1021,53 @@ case 13:
; ;
break;} break;}
case 14: case 14:
#line 283 "getdate.y" #line 288 "getdate.y"
{ {
yyTimezone = yyvsp[0].Number; yyTimezone = yyvsp[0].Number;
; ;
break;} break;}
case 15: case 15:
#line 286 "getdate.y" #line 291 "getdate.y"
{ {
yyTimezone = yyvsp[0].Number - 60; yyTimezone = yyvsp[0].Number - 60;
; ;
break;} break;}
case 16: case 16:
#line 290 "getdate.y" #line 295 "getdate.y"
{ {
yyTimezone = yyvsp[-1].Number - 60; yyTimezone = yyvsp[-1].Number - 60;
; ;
break;} break;}
case 17: case 17:
#line 295 "getdate.y" #line 300 "getdate.y"
{ {
yyDayOrdinal = 1; yyDayOrdinal = 1;
yyDayNumber = yyvsp[0].Number; yyDayNumber = yyvsp[0].Number;
; ;
break;} break;}
case 18: case 18:
#line 299 "getdate.y" #line 304 "getdate.y"
{ {
yyDayOrdinal = 1; yyDayOrdinal = 1;
yyDayNumber = yyvsp[-1].Number; yyDayNumber = yyvsp[-1].Number;
; ;
break;} break;}
case 19: case 19:
#line 303 "getdate.y" #line 308 "getdate.y"
{ {
yyDayOrdinal = yyvsp[-1].Number; yyDayOrdinal = yyvsp[-1].Number;
yyDayNumber = yyvsp[0].Number; yyDayNumber = yyvsp[0].Number;
; ;
break;} break;}
case 20: case 20:
#line 309 "getdate.y" #line 314 "getdate.y"
{ {
yyMonth = yyvsp[-2].Number; yyMonth = yyvsp[-2].Number;
yyDay = yyvsp[0].Number; yyDay = yyvsp[0].Number;
; ;
break;} break;}
case 21: case 21:
#line 313 "getdate.y" #line 318 "getdate.y"
{ {
/* Interpret as YYYY/MM/DD if $1 >= 1000, otherwise as MM/DD/YY. /* Interpret as YYYY/MM/DD if $1 >= 1000, otherwise as MM/DD/YY.
The goal in recognizing YYYY/MM/DD is solely to support legacy The goal in recognizing YYYY/MM/DD is solely to support legacy
@@ -1083,7 +1088,7 @@ case 21:
; ;
break;} break;}
case 22: case 22:
#line 331 "getdate.y" #line 336 "getdate.y"
{ {
/* ISO 8601 format. yyyy-mm-dd. */ /* ISO 8601 format. yyyy-mm-dd. */
yyYear = yyvsp[-2].Number; yyYear = yyvsp[-2].Number;
@@ -1092,7 +1097,7 @@ case 22:
; ;
break;} break;}
case 23: case 23:
#line 337 "getdate.y" #line 342 "getdate.y"
{ {
/* e.g. 17-JUN-1992. */ /* e.g. 17-JUN-1992. */
yyDay = yyvsp[-2].Number; yyDay = yyvsp[-2].Number;
@@ -1101,14 +1106,14 @@ case 23:
; ;
break;} break;}
case 24: case 24:
#line 343 "getdate.y" #line 348 "getdate.y"
{ {
yyMonth = yyvsp[-1].Number; yyMonth = yyvsp[-1].Number;
yyDay = yyvsp[0].Number; yyDay = yyvsp[0].Number;
; ;
break;} break;}
case 25: case 25:
#line 347 "getdate.y" #line 352 "getdate.y"
{ {
yyMonth = yyvsp[-3].Number; yyMonth = yyvsp[-3].Number;
yyDay = yyvsp[-2].Number; yyDay = yyvsp[-2].Number;
@@ -1116,14 +1121,14 @@ case 25:
; ;
break;} break;}
case 26: case 26:
#line 352 "getdate.y" #line 357 "getdate.y"
{ {
yyMonth = yyvsp[0].Number; yyMonth = yyvsp[0].Number;
yyDay = yyvsp[-1].Number; yyDay = yyvsp[-1].Number;
; ;
break;} break;}
case 27: case 27:
#line 356 "getdate.y" #line 361 "getdate.y"
{ {
yyMonth = yyvsp[-1].Number; yyMonth = yyvsp[-1].Number;
yyDay = yyvsp[-2].Number; yyDay = yyvsp[-2].Number;
@@ -1131,7 +1136,7 @@ case 27:
; ;
break;} break;}
case 28: case 28:
#line 363 "getdate.y" #line 368 "getdate.y"
{ {
yyRelSeconds = -yyRelSeconds; yyRelSeconds = -yyRelSeconds;
yyRelMinutes = -yyRelMinutes; yyRelMinutes = -yyRelMinutes;
@@ -1142,115 +1147,115 @@ case 28:
; ;
break;} break;}
case 30: case 30:
#line 374 "getdate.y" #line 379 "getdate.y"
{ {
yyRelYear += yyvsp[-1].Number * yyvsp[0].Number; yyRelYear += yyvsp[-1].Number * yyvsp[0].Number;
; ;
break;} break;}
case 31: case 31:
#line 377 "getdate.y" #line 382 "getdate.y"
{ {
yyRelYear += yyvsp[-1].Number * yyvsp[0].Number; yyRelYear += yyvsp[-1].Number * yyvsp[0].Number;
; ;
break;} break;}
case 32: case 32:
#line 380 "getdate.y" #line 385 "getdate.y"
{ {
yyRelYear += yyvsp[0].Number; yyRelYear += yyvsp[0].Number;
; ;
break;} break;}
case 33: case 33:
#line 383 "getdate.y" #line 388 "getdate.y"
{ {
yyRelMonth += yyvsp[-1].Number * yyvsp[0].Number; yyRelMonth += yyvsp[-1].Number * yyvsp[0].Number;
; ;
break;} break;}
case 34: case 34:
#line 386 "getdate.y" #line 391 "getdate.y"
{ {
yyRelMonth += yyvsp[-1].Number * yyvsp[0].Number; yyRelMonth += yyvsp[-1].Number * yyvsp[0].Number;
; ;
break;} break;}
case 35: case 35:
#line 389 "getdate.y" #line 394 "getdate.y"
{ {
yyRelMonth += yyvsp[0].Number; yyRelMonth += yyvsp[0].Number;
; ;
break;} break;}
case 36: case 36:
#line 392 "getdate.y" #line 397 "getdate.y"
{ {
yyRelDay += yyvsp[-1].Number * yyvsp[0].Number; yyRelDay += yyvsp[-1].Number * yyvsp[0].Number;
; ;
break;} break;}
case 37: case 37:
#line 395 "getdate.y" #line 400 "getdate.y"
{ {
yyRelDay += yyvsp[-1].Number * yyvsp[0].Number; yyRelDay += yyvsp[-1].Number * yyvsp[0].Number;
; ;
break;} break;}
case 38: case 38:
#line 398 "getdate.y" #line 403 "getdate.y"
{ {
yyRelDay += yyvsp[0].Number; yyRelDay += yyvsp[0].Number;
; ;
break;} break;}
case 39: case 39:
#line 401 "getdate.y" #line 406 "getdate.y"
{ {
yyRelHour += yyvsp[-1].Number * yyvsp[0].Number; yyRelHour += yyvsp[-1].Number * yyvsp[0].Number;
; ;
break;} break;}
case 40: case 40:
#line 404 "getdate.y" #line 409 "getdate.y"
{ {
yyRelHour += yyvsp[-1].Number * yyvsp[0].Number; yyRelHour += yyvsp[-1].Number * yyvsp[0].Number;
; ;
break;} break;}
case 41: case 41:
#line 407 "getdate.y" #line 412 "getdate.y"
{ {
yyRelHour += yyvsp[0].Number; yyRelHour += yyvsp[0].Number;
; ;
break;} break;}
case 42: case 42:
#line 410 "getdate.y" #line 415 "getdate.y"
{ {
yyRelMinutes += yyvsp[-1].Number * yyvsp[0].Number; yyRelMinutes += yyvsp[-1].Number * yyvsp[0].Number;
; ;
break;} break;}
case 43: case 43:
#line 413 "getdate.y" #line 418 "getdate.y"
{ {
yyRelMinutes += yyvsp[-1].Number * yyvsp[0].Number; yyRelMinutes += yyvsp[-1].Number * yyvsp[0].Number;
; ;
break;} break;}
case 44: case 44:
#line 416 "getdate.y" #line 421 "getdate.y"
{ {
yyRelMinutes += yyvsp[0].Number; yyRelMinutes += yyvsp[0].Number;
; ;
break;} break;}
case 45: case 45:
#line 419 "getdate.y" #line 424 "getdate.y"
{ {
yyRelSeconds += yyvsp[-1].Number * yyvsp[0].Number; yyRelSeconds += yyvsp[-1].Number * yyvsp[0].Number;
; ;
break;} break;}
case 46: case 46:
#line 422 "getdate.y" #line 427 "getdate.y"
{ {
yyRelSeconds += yyvsp[-1].Number * yyvsp[0].Number; yyRelSeconds += yyvsp[-1].Number * yyvsp[0].Number;
; ;
break;} break;}
case 47: case 47:
#line 425 "getdate.y" #line 430 "getdate.y"
{ {
yyRelSeconds += yyvsp[0].Number; yyRelSeconds += yyvsp[0].Number;
; ;
break;} break;}
case 48: case 48:
#line 431 "getdate.y" #line 436 "getdate.y"
{ {
if (yyHaveTime && yyHaveDate && !yyHaveRel) if (yyHaveTime && yyHaveDate && !yyHaveRel)
yyYear = yyvsp[0].Number; yyYear = yyvsp[0].Number;
@@ -1283,13 +1288,13 @@ case 48:
; ;
break;} break;}
case 49: case 49:
#line 464 "getdate.y" #line 469 "getdate.y"
{ {
yyval.Meridian = MER24; yyval.Meridian = MER24;
; ;
break;} break;}
case 50: case 50:
#line 468 "getdate.y" #line 473 "getdate.y"
{ {
yyval.Meridian = yyvsp[0].Meridian; yyval.Meridian = yyvsp[0].Meridian;
; ;
@@ -1516,7 +1521,7 @@ yyerrhandle:
} }
return 1; return 1;
} }
#line 473 "getdate.y" #line 478 "getdate.y"
/* Include this file down here because bison inserts code above which /* Include this file down here because bison inserts code above which
@@ -2126,11 +2131,3 @@ main (ac, av)
/* NOTREACHED */ /* NOTREACHED */
} }
#endif /* defined (TEST) */ #endif /* defined (TEST) */
/*
* local variables:
* eval: (load-file "../curl-mode.el")
* end:
* vim600: fdm=marker
* vim: et sw=2 ts=2 sts=2 tw=78
*/

View File

@@ -21,6 +21,11 @@
# endif # endif
#endif #endif
#ifndef YYDEBUG
/* to satisfy gcc -Wundef, we set this to 0 */
#define YYDEBUG 0
#endif
/* Since the code of getdate.y is not included in the Emacs executable /* Since the code of getdate.y is not included in the Emacs executable
itself, there is no need to #define static in this file. Even if itself, there is no need to #define static in this file. Even if
the code were included in the Emacs executable, it probably the code were included in the Emacs executable, it probably

View File

@@ -55,7 +55,6 @@ char *GetEnv(const char *variable)
if (env && strcmp("HOME",variable) == 0) { if (env && strcmp("HOME",variable) == 0) {
env = decc$translate_vms(env); env = decc$translate_vms(env);
} }
/* printf ("Getenv: %s=%s\n",variable,env); */
#else #else
/* no length control */ /* no length control */
char *env = getenv(variable); char *env = getenv(variable);

285
lib/hash.c Normal file
View File

@@ -0,0 +1,285 @@
/*****************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 2001, Daniel Stenberg, <daniel@haxx.se>, et al
*
* In order to be useful for every potential user, curl and libcurl are
* dual-licensed under the MPL and the MIT/X-derivate licenses.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the MPL or the MIT/X-derivate
* licenses. You may pick one of these licenses.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* $Id$
*****************************************************************************/
#include "setup.h"
#include <string.h>
#include "hash.h"
#include "llist.h"
#ifdef MALLOCDEBUG
/* this must be the last include file */
#include "memdebug.h"
#endif
static unsigned long
curl_hash_str(const char *key, unsigned int key_length)
{
register unsigned long h = 0;
register unsigned long g;
register char *p = (char *) key;
register char *end = (char *) key + key_length;
while (p < end) {
h = (h << 4) + *p++;
if ((g = (h & 0xF0000000))) {
h = h ^ (g >> 24);
h = h ^ g;
}
}
return h;
}
static unsigned long
curl_hash_num(unsigned long key)
{
key += ~(key << 15);
key ^= (key >> 10);
key += (key << 3);
key ^= (key >> 6);
key += (key << 11);
key ^= (key >> 16);
return key;
}
static void
hash_element_dtor(void *u, void *ele)
{
curl_hash_element *e = (curl_hash_element *) ele;
curl_hash *h = (curl_hash *) u;
if (e->key.type == CURL_HASH_KEY_IS_STRING) {
free(e->key.value.str.val);
}
h->dtor(e->ptr);
free(e);
e = NULL;
}
void
curl_hash_init(curl_hash *h, int slots, curl_hash_dtor dtor)
{
int i;
h->dtor = dtor;
h->size = 0;
h->slots = slots;
h->table = (curl_llist **) malloc(slots * sizeof(curl_llist *));
for (i = 0; i < h->slots; ++i) {
h->table[i] = curl_llist_alloc((curl_llist_dtor) hash_element_dtor);
}
}
curl_hash *
curl_hash_alloc(int slots, curl_hash_dtor dtor)
{
curl_hash *h;
h = (curl_hash *)malloc(sizeof(curl_hash));
if(NULL == h)
return NULL;
curl_hash_init(h, slots, dtor);
return h;
}
#define FIND_SLOT(__h, __s_key, __s_key_len, __n_key) \
((__s_key ? curl_hash_str(__s_key, __s_key_len) : curl_hash_num(__n_key)) % (__h)->slots)
#define KEY_CREATE(__k, __s_key, __s_key_len, __n_key, __dup) \
if (__s_key) { \
if (__dup) { \
(__k)->value.str.val = (char *) malloc(__s_key_len); \
memcpy((__k)->value.str.val, __s_key, __s_key_len); \
} else { \
(__k)->value.str.val = __s_key; \
} \
(__k)->value.str.len = __s_key_len; \
(__k)->type = CURL_HASH_KEY_IS_STRING; \
} else { \
(__k)->value.num = __n_key; \
(__k)->type = CURL_HASH_KEY_IS_NUM; \
}
#define MIN(a, b) (a > b ? b : a)
static int
curl_hash_key_compare(curl_hash_key *key1, curl_hash_key *key2)
{
if (key1->type == CURL_HASH_KEY_IS_NUM) {
if (key2->type == CURL_HASH_KEY_IS_STRING)
return 0;
if (key1->value.num == key2->value.num)
return 1;
} else {
if (key2->type == CURL_HASH_KEY_IS_NUM)
return 0;
if (memcmp(key1->value.str.val, key2->value.str.val,
MIN(key1->value.str.len, key2->value.str.len)) == 0)
return 1;
}
return 0;
}
int
curl_hash_add_or_update(curl_hash *h, char *str_key, unsigned int str_key_len,
unsigned long num_key, const void *p)
{
curl_hash_element *e;
curl_hash_key tmp;
curl_llist *l;
curl_llist_element *le;
int slot;
slot = FIND_SLOT(h, str_key, str_key_len, num_key);
l = h->table[slot];
KEY_CREATE(&tmp, str_key, str_key_len, num_key, 0);
for (le = CURL_LLIST_HEAD(l); le != NULL; le = CURL_LLIST_NEXT(le)) {
if (curl_hash_key_compare(&tmp, &((curl_hash_element *) CURL_LLIST_VALP(le))->key)) {
curl_hash_element *to_update = CURL_LLIST_VALP(le);
h->dtor(to_update->ptr);
to_update->ptr = (void *) p;
return 1;
}
}
e = (curl_hash_element *) malloc(sizeof(curl_hash_element));
KEY_CREATE(&e->key, str_key, str_key_len, num_key, 1);
e->ptr = (void *) p;
if (curl_llist_insert_next(l, CURL_LLIST_TAIL(l), e)) {
++h->size;
return 1;
} else {
return 0;
}
}
int
curl_hash_extended_delete(curl_hash *h, char *str_key, unsigned int str_key_len,
unsigned long num_key)
{
curl_llist *l;
curl_llist_element *le;
curl_hash_key tmp;
int slot;
slot = FIND_SLOT(h, str_key, str_key_len, num_key);
l = h->table[slot];
KEY_CREATE(&tmp, str_key, str_key_len, num_key, 0);
for (le = CURL_LLIST_HEAD(l); le != NULL; le = CURL_LLIST_NEXT(le)) {
if (curl_hash_key_compare(&tmp, &((curl_hash_element *) CURL_LLIST_VALP(le))->key)) {
curl_llist_remove(l, le, (void *) h);
--h->size;
return 1;
}
}
return 0;
}
int
curl_hash_extended_find(curl_hash *h, char *str_key, unsigned int str_key_len,
unsigned long num_key, void **p)
{
curl_llist *l;
curl_llist_element *le;
curl_hash_key tmp;
int slot;
slot = FIND_SLOT(h, str_key, str_key_len, num_key);
l = h->table[slot];
KEY_CREATE(&tmp, str_key, str_key_len, num_key, 0);
for (le = CURL_LLIST_HEAD(l); le != NULL; le = CURL_LLIST_NEXT(le)) {
if (curl_hash_key_compare(&tmp, &((curl_hash_element *) CURL_LLIST_VALP(le))->key)) {
*p = ((curl_hash_element *) CURL_LLIST_VALP(le))->ptr;
return 1;
}
}
return 0;
}
void
curl_hash_apply(curl_hash *h, void *user, void (*cb)(void *, curl_hash_element *))
{
curl_llist_element *le;
int i;
for (i = 0; i < h->slots; ++i) {
for (le = CURL_LLIST_HEAD(h->table[i]); le != NULL; le = CURL_LLIST_NEXT(le)) {
cb(user, (curl_hash_element *) CURL_LLIST_VALP(le));
}
}
}
void
curl_hash_clean(curl_hash *h)
{
int i;
for (i = 0; i < h->slots; ++i) {
curl_llist_destroy(h->table[i], (void *) h);
}
free(h->table);
h->table = NULL;
}
size_t
curl_hash_count(curl_hash *h)
{
return h->size;
}
void
curl_hash_destroy(curl_hash *h)
{
if (!h) {
return;
}
curl_hash_clean(h);
free(h);
h = NULL;
}
/*
* local variables:
* eval: (load-file "../curl-mode.el")
* end:
* vim600: fdm=marker
* vim: et sw=2 ts=2 sts=2 tw=78
*/

85
lib/hash.h Normal file
View File

@@ -0,0 +1,85 @@
#ifndef __HASH_H
#define __HASH_H
/*****************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 2000, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* In order to be useful for every potential user, curl and libcurl are
* dual-licensed under the MPL and the MIT/X-derivate licenses.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the MPL or the MIT/X-derivate
* licenses. You may pick one of these licenses.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* $Id$
*****************************************************************************/
#include "setup.h"
#include <stddef.h>
#include "llist.h"
#define CURL_HASH_KEY_IS_STRING 0
#define CURL_HASH_KEY_IS_NUM 1
typedef void (*curl_hash_dtor)(void *);
typedef struct _curl_hash {
curl_llist **table;
curl_hash_dtor dtor;
int slots;
size_t size;
} curl_hash;
typedef struct _curl_hash_key {
union {
struct {
char *val;
unsigned int len;
} str;
unsigned long num;
} value;
int type;
} curl_hash_key;
typedef struct _curl_hash_element {
curl_hash_key key;
void *ptr;
} curl_hash_element;
void curl_hash_init(curl_hash *h, int slots, curl_hash_dtor dtor);
curl_hash *curl_hash_alloc(int slots, curl_hash_dtor dtor);
int curl_hash_add_or_update(curl_hash *h, char *str_key, unsigned int str_key_len,
unsigned long num_key, const void *p);
int curl_hash_extended_delete(curl_hash *h, char *str_key, unsigned int str_key_len,
unsigned long num_key);
int curl_hash_extended_find(curl_hash *h, char *str_key, unsigned int str_key_len,
unsigned long num_key, void **p);
void curl_hash_apply(curl_hash *h, void *user, void (*cb)(void *, curl_hash_element *));
size_t curl_hash_count(curl_hash *h);
void curl_hash_clean(curl_hash *h);
void curl_hash_destroy(curl_hash *h);
#define curl_hash_find(h, key, key_len, p) curl_hash_extended_find(h, key, key_len, 0, p)
#define curl_hash_delete(h, key, key_len) curl_hash_extended_delete(h, key, key_len, 0)
#define curl_hash_add(h, key, key_len, p) curl_hash_add_or_update(h, key, key_len, 0, p)
#define curl_hash_update curl_hash_add
#define curl_hash_index_find(h, key, p) curl_hash_extended_find(h, NULL, 0, key, p)
#define curl_hash_index_delete(h, key) curl_hash_extended_delete(h, NULL, 0, key)
#define curl_hash_index_add(h, key, p) curl_hash_add_or_update(h, NULL, 0, key, p)
#define curl_hash_index_update curl_hash_index_add
#endif

View File

@@ -58,6 +58,10 @@
#include "urldata.h" #include "urldata.h"
#include "sendf.h" #include "sendf.h"
#include "hostip.h" #include "hostip.h"
#include "hash.h"
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
#if defined(HAVE_INET_NTOA_R) && !defined(HAVE_INET_NTOA_R_DECL) #if defined(HAVE_INET_NTOA_R) && !defined(HAVE_INET_NTOA_R_DECL)
#include "inet_ntoa_r.h" #include "inet_ntoa_r.h"
@@ -68,6 +72,151 @@
#include "memdebug.h" #include "memdebug.h"
#endif #endif
static curl_hash hostname_cache;
static int host_cache_initialized;
void Curl_global_host_cache_init(void)
{
if (!host_cache_initialized) {
curl_hash_init(&hostname_cache, 7, Curl_freeaddrinfo);
host_cache_initialized = 1;
}
}
curl_hash *Curl_global_host_cache_get(void)
{
return &hostname_cache;
}
void Curl_global_host_cache_dtor(void)
{
if (host_cache_initialized) {
curl_hash_clean(&hostname_cache);
host_cache_initialized = 0;
}
}
struct curl_dns_cache_entry {
Curl_addrinfo *addr;
time_t timestamp;
};
/* count the number of characters that an integer takes up */
static int _num_chars(int i)
{
int chars = 0;
/* While the number divided by 10 is greater than one,
* re-divide the number by 10, and increment the number of
* characters by 1.
*
* this relies on the fact that for every multiple of 10,
* a new digit is added onto every number
*/
do {
chars++;
i = (int) i / 10;
} while (i > 1);
return chars;
}
/* Create a hostcache id */
static char *
_create_hostcache_id(char *server, int port, ssize_t *entry_len)
{
char *id = NULL;
/* Get the length of the new entry id */
*entry_len = *entry_len + /* Hostname length */
1 + /* The ':' seperator */
_num_chars(port); /* The number of characters the port will take up */
/* Allocate the new entry id */
id = malloc(*entry_len + 1);
if (!id) {
return NULL;
}
/* Create the new entry */
/* If sprintf() doesn't return the entry length, that signals failure */
if (sprintf(id, "%s:%d", server, port) != *entry_len) {
/* Free the allocated id, set length to zero and return NULL */
*entry_len = 0;
free(id);
return NULL;
}
return id;
}
/* Macro to save redundant free'ing of entry_id */
#define _hostcache_return(__v) \
{ \
free(entry_id); \
return (__v); \
}
Curl_addrinfo *Curl_resolv(struct SessionHandle *data,
char *hostname,
int port,
char **bufp)
{
char *entry_id = NULL;
struct curl_dns_cache_entry *p = NULL;
ssize_t entry_len;
time_t now;
/* If the host cache timeout is 0, we don't do DNS cach'ing
so fall through */
if (data->set.dns_cache_timeout == 0) {
return Curl_getaddrinfo(data, hostname, port, bufp);
}
/* Create an entry id, based upon the hostname and port */
entry_len = strlen(hostname);
entry_id = _create_hostcache_id(hostname, port, &entry_len);
/* If we can't create the entry id, don't cache, just fall-through
to the plain Curl_getaddrinfo() */
if (!entry_id) {
return Curl_getaddrinfo(data, hostname, port, bufp);
}
time(&now);
/* See if its already in our dns cache */
if (entry_id && curl_hash_find(data->hostcache, entry_id, entry_len+1, (void **) &p)) {
/* Do we need to check for a cache timeout? */
if (data->set.dns_cache_timeout != -1) {
/* Return if the entry has not timed out */
if ((now - p->timestamp) < data->set.dns_cache_timeout) {
_hostcache_return(p->addr);
}
}
else {
_hostcache_return(p->addr);
}
}
/* Create a new cache entry */
p = (struct curl_dns_cache_entry *) malloc(sizeof(struct curl_dns_cache_entry));
if (!p) {
_hostcache_return(NULL);
}
p->addr = Curl_getaddrinfo(data, hostname, port, bufp);
if (!p->addr) {
free(p);
_hostcache_return(NULL);
}
p->timestamp = now;
/* Save it in our host cache */
curl_hash_update(data->hostcache, entry_id, entry_len+1, (const void *) p);
_hostcache_return(p->addr);
}
/* /*
* This is a wrapper function for freeing name information in a protocol * This is a wrapper function for freeing name information in a protocol
* independent way. This takes care of using the appropriate underlaying * independent way. This takes care of using the appropriate underlaying
@@ -75,11 +224,15 @@
*/ */
void Curl_freeaddrinfo(void *freethis) void Curl_freeaddrinfo(void *freethis)
{ {
struct curl_dns_cache_entry *p = (struct curl_dns_cache_entry *) freethis;
#ifdef ENABLE_IPV6 #ifdef ENABLE_IPV6
freeaddrinfo(freethis); freeaddrinfo(p->addr);
#else #else
free(freethis); free(p->addr);
#endif #endif
free(p);
} }
/* --- resolve name or IP-number --- */ /* --- resolve name or IP-number --- */
@@ -102,7 +255,7 @@ int curl_getaddrinfo(char *hostname, char *service,
/* success */ /* success */
if(logfile) if(logfile)
fprintf(logfile, "ADDR %s:%d getaddrinfo() = %p\n", fprintf(logfile, "ADDR %s:%d getaddrinfo() = %p\n",
source, line, *result); source, line, (void *)*result);
} }
else { else {
if(logfile) if(logfile)
@@ -118,7 +271,7 @@ void curl_freeaddrinfo(struct addrinfo *freethis,
(freeaddrinfo)(freethis); (freeaddrinfo)(freethis);
if(logfile) if(logfile)
fprintf(logfile, "ADDR %s:%d freeaddrinfo(%p)\n", fprintf(logfile, "ADDR %s:%d freeaddrinfo(%p)\n",
source, line, freethis); source, line, (void *)freethis);
} }
#endif #endif
@@ -265,7 +418,7 @@ Curl_addrinfo *Curl_getaddrinfo(struct SessionHandle *data,
char **bufp) char **bufp)
{ {
struct hostent *h = NULL; struct hostent *h = NULL;
unsigned long in; in_addr_t in;
int ret; /* this variable is unused on several platforms but used on some */ int ret; /* this variable is unused on several platforms but used on some */
#define CURL_NAMELOOKUP_SIZE 9000 #define CURL_NAMELOOKUP_SIZE 9000
@@ -273,10 +426,10 @@ Curl_addrinfo *Curl_getaddrinfo(struct SessionHandle *data,
* everything. OSF1 is known to require at least 8872 bytes. The buffer * everything. OSF1 is known to require at least 8872 bytes. The buffer
* required for storing all possible aliases and IP numbers is according to * required for storing all possible aliases and IP numbers is according to
* Stevens' Unix Network Programming 2nd editor, p. 304: 8192 bytes! */ * Stevens' Unix Network Programming 2nd editor, p. 304: 8192 bytes! */
char *buf = (char *)malloc(CURL_NAMELOOKUP_SIZE); int *buf = (int *)malloc(CURL_NAMELOOKUP_SIZE);
if(!buf) if(!buf)
return NULL; /* major failure */ return NULL; /* major failure */
*bufp = buf; *bufp = (char *)buf;
port=0; /* unused in IPv4 code */ port=0; /* unused in IPv4 code */
ret = 0; /* to prevent the compiler warning */ ret = 0; /* to prevent the compiler warning */
@@ -306,7 +459,7 @@ Curl_addrinfo *Curl_getaddrinfo(struct SessionHandle *data,
/* Solaris, IRIX and more */ /* Solaris, IRIX and more */
if ((h = gethostbyname_r(hostname, if ((h = gethostbyname_r(hostname,
(struct hostent *)buf, (struct hostent *)buf,
buf + sizeof(struct hostent), (char *)buf + sizeof(struct hostent),
CURL_NAMELOOKUP_SIZE - sizeof(struct hostent), CURL_NAMELOOKUP_SIZE - sizeof(struct hostent),
&h_errnop)) == NULL ) &h_errnop)) == NULL )
#endif #endif
@@ -372,3 +525,4 @@ Curl_addrinfo *Curl_getaddrinfo(struct SessionHandle *data,
* vim600: fdm=marker * vim600: fdm=marker
* vim: et sw=2 ts=2 sts=2 tw=78 * vim: et sw=2 ts=2 sts=2 tw=78
*/ */

View File

@@ -23,10 +23,23 @@
* $Id$ * $Id$
*****************************************************************************/ *****************************************************************************/
#include "hash.h"
struct addrinfo; struct addrinfo;
struct hostent; struct hostent;
struct SessionHandle; struct SessionHandle;
void Curl_global_host_cache_init(void);
void Curl_global_host_cache_dtor(void);
curl_hash *Curl_global_host_cache_get(void);
#define Curl_global_host_cache_use(__p) ((__p)->set.global_dns_cache)
Curl_addrinfo *Curl_resolv(struct SessionHandle *data,
char *hostname,
int port,
char **bufp);
/* Get name info */ /* Get name info */
Curl_addrinfo *Curl_getaddrinfo(struct SessionHandle *data, Curl_addrinfo *Curl_getaddrinfo(struct SessionHandle *data,
char *hostname, char *hostname,

View File

@@ -128,8 +128,10 @@ static
CURLcode add_buffer_send(int sockfd, struct connectdata *conn, send_buffer *in, CURLcode add_buffer_send(int sockfd, struct connectdata *conn, send_buffer *in,
long *bytes_written) long *bytes_written)
{ {
size_t amount; ssize_t amount;
CURLcode result; CURLcode res;
char *ptr;
int size;
if(conn->data->set.verbose) { if(conn->data->set.verbose) {
fputs("> ", conn->data->set.err); fputs("> ", conn->data->set.err);
@@ -137,7 +139,25 @@ CURLcode add_buffer_send(int sockfd, struct connectdata *conn, send_buffer *in,
fwrite(in->buffer, in->size_used, 1, conn->data->set.err); fwrite(in->buffer, in->size_used, 1, conn->data->set.err);
} }
result = Curl_write(conn, sockfd, in->buffer, in->size_used, &amount); /* The looping below is required since we use non-blocking sockets, but due
to the circumstances we will just loop and try again and again etc */
ptr = in->buffer;
size = in->size_used;
do {
res = Curl_write(conn, sockfd, ptr, size, &amount);
if(CURLE_OK != res)
break;
if(amount != size) {
size += amount;
ptr += amount;
}
else
break;
} while(1);
if(in->buffer) if(in->buffer)
free(in->buffer); free(in->buffer);
@@ -145,7 +165,7 @@ CURLcode add_buffer_send(int sockfd, struct connectdata *conn, send_buffer *in,
*bytes_written = amount; *bytes_written = amount;
return result; return res;
} }
@@ -235,6 +255,7 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn,
int subversion=0; int subversion=0;
struct SessionHandle *data=conn->data; struct SessionHandle *data=conn->data;
CURLcode result; CURLcode result;
int res;
int nread; /* total size read */ int nread; /* total size read */
int perline; /* count bytes per line */ int perline; /* count bytes per line */
@@ -317,8 +338,12 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn,
* to read, but when we use Curl_read() it may do so. Do confirm * to read, but when we use Curl_read() it may do so. Do confirm
* that this is still ok and then remove this comment! * that this is still ok and then remove this comment!
*/ */
if(CURLE_OK != Curl_read(conn, tunnelsocket, ptr, BUFSIZE-nread, res= Curl_read(conn, tunnelsocket, ptr, BUFSIZE-nread,
&gotbytes)) &gotbytes);
if(res< 0)
/* EWOULDBLOCK */
continue; /* go loop yourself */
else if(res)
keepon = FALSE; keepon = FALSE;
else if(gotbytes <= 0) { else if(gotbytes <= 0) {
keepon = FALSE; keepon = FALSE;
@@ -449,7 +474,7 @@ CURLcode Curl_http_done(struct connectdata *conn)
if(0 == (http->readbytecount + conn->headerbytecount)) { if(0 == (http->readbytecount + conn->headerbytecount)) {
/* nothing was read from the HTTP server, this can't be right /* nothing was read from the HTTP server, this can't be right
so we return an error here */ so we return an error here */
failf(data, "Empty reply from server\n"); failf(data, "Empty reply from server");
return CURLE_GOT_NOTHING; return CURLE_GOT_NOTHING;
} }
@@ -610,7 +635,7 @@ CURLcode Curl_http(struct connectdata *conn)
passed += actuallyread; passed += actuallyread;
if(actuallyread != readthisamountnow) { if(actuallyread != readthisamountnow) {
failf(data, "Could only read %d bytes from the input\n", failf(data, "Could only read %d bytes from the input",
passed); passed);
return CURLE_READ_ERROR; return CURLE_READ_ERROR;
} }
@@ -621,7 +646,7 @@ CURLcode Curl_http(struct connectdata *conn)
data->set.infilesize -= conn->resume_from; data->set.infilesize -= conn->resume_from;
if(data->set.infilesize <= 0) { if(data->set.infilesize <= 0) {
failf(data, "File already completely uploaded\n"); failf(data, "File already completely uploaded");
return CURLE_PARTIAL_FILE; return CURLE_PARTIAL_FILE;
} }
} }
@@ -735,10 +760,8 @@ CURLcode Curl_http(struct connectdata *conn)
* equal to UTC (Coordinated Universal Time)." (see page 20 of RFC2616). * equal to UTC (Coordinated Universal Time)." (see page 20 of RFC2616).
*/ */
#ifdef HAVE_LOCALTIME_R #ifdef HAVE_GMTIME_R
/* thread-safe version */ /* thread-safe version */
/* We assume that the presense of localtime_r() proves the presense
of gmtime_r() which is a bit ugly but might work */
struct tm keeptime; struct tm keeptime;
thistime = (struct tm *)gmtime_r(&data->set.timevalue, &keeptime); thistime = (struct tm *)gmtime_r(&data->set.timevalue, &keeptime);
#else #else
@@ -795,7 +818,7 @@ CURLcode Curl_http(struct connectdata *conn)
char contentType[256]; char contentType[256];
int linelength=0; int linelength=0;
if(Curl_FormInit(&http->form, http->sendit)) { if(Curl_FormInit(&http->form, http->sendit)) {
failf(data, "Internal HTTP POST error!\n"); failf(data, "Internal HTTP POST error!");
return CURLE_HTTP_POST_ERROR; return CURLE_HTTP_POST_ERROR;
} }
@@ -826,7 +849,7 @@ CURLcode Curl_http(struct connectdata *conn)
1, 1,
(FILE *)&http->form); (FILE *)&http->form);
if(linelength == -1) { if(linelength == -1) {
failf(data, "Could not get Content-Type header line!\n"); failf(data, "Could not get Content-Type header line!");
return CURLE_HTTP_POST_ERROR; return CURLE_HTTP_POST_ERROR;
} }
add_buffer(req_buffer, contentType, linelength); add_buffer(req_buffer, contentType, linelength);

View File

@@ -57,6 +57,10 @@
#include "ftp.h" #include "ftp.h"
#include "sendf.h" #include "sendf.h"
#if defined(HAVE_INET_NTOA_R) && !defined(HAVE_INET_NTOA_R_DECL)
#include "inet_ntoa_r.h"
#endif
/* The last #include file should be: */ /* The last #include file should be: */
#ifdef MALLOCDEBUG #ifdef MALLOCDEBUG
#include "memdebug.h" #include "memdebug.h"
@@ -193,10 +197,10 @@ krb4_auth(void *app_data, struct connectdata *conn)
int checksum; int checksum;
u_int32_t cs; u_int32_t cs;
struct krb4_data *d = app_data; struct krb4_data *d = app_data;
struct sockaddr_in *localaddr = (struct sockaddr_in *)LOCAL_ADDR;
char *host = conn->hostaddr->h_name; char *host = conn->hostaddr->h_name;
ssize_t nread; ssize_t nread;
int l = sizeof(conn->local_addr); int l = sizeof(conn->local_addr);
struct SessionHandle *data = conn->data;
if(getsockname(conn->firstsocket, if(getsockname(conn->firstsocket,
(struct sockaddr *)LOCAL_ADDR, &l) < 0) (struct sockaddr *)LOCAL_ADDR, &l) < 0)
@@ -207,80 +211,76 @@ krb4_auth(void *app_data, struct connectdata *conn)
if(ret == KDC_PR_UNKNOWN) if(ret == KDC_PR_UNKNOWN)
ret = mk_auth(d, &adat, "rcmd", host, checksum); ret = mk_auth(d, &adat, "rcmd", host, checksum);
if(ret) { if(ret) {
printf("%s\n", krb_get_err_text(ret)); Curl_infof(data, "%s\n", krb_get_err_text(ret));
return AUTH_CONTINUE; return AUTH_CONTINUE;
} }
#ifdef HAVE_KRB_GET_OUR_IP_FOR_REALM #ifdef HAVE_KRB_GET_OUR_IP_FOR_REALM
if (krb_get_config_bool("nat_in_use")) { if (krb_get_config_bool("nat_in_use")) {
struct sockaddr_in *localaddr = (struct sockaddr_in *)LOCAL_ADDR;
struct in_addr natAddr; struct in_addr natAddr;
if (krb_get_our_ip_for_realm(krb_realmofhost(host), if (krb_get_our_ip_for_realm(krb_realmofhost(host),
&natAddr) != KSUCCESS &natAddr) != KSUCCESS
&& krb_get_our_ip_for_realm(NULL, &natAddr) != KSUCCESS) && krb_get_our_ip_for_realm(NULL, &natAddr) != KSUCCESS)
printf("Can't get address for realm %s\n", Curl_infof(data, "Can't get address for realm %s\n",
krb_realmofhost(host)); krb_realmofhost(host));
else { else {
if (natAddr.s_addr != localaddr->sin_addr.s_addr) { if (natAddr.s_addr != localaddr->sin_addr.s_addr) {
printf("Using NAT IP address (%s) for kerberos 4\n", #ifdef HAVE_INET_NTOA_R
(char *)inet_ntoa(natAddr)); char ntoa_buf[64];
char *ip = (char *)inet_ntoa_r(natAddr, ntoa_buf, sizeof(ntoa_buf));
#else
char *ip = (char *)inet_ntoa(natAddr);
#endif
Curl_infof(data, "Using NAT IP address (%s) for kerberos 4\n", ip);
localaddr->sin_addr = natAddr; localaddr->sin_addr = natAddr;
/*
* This not the best place to do this, but it is here we know that
* (probably) NAT is in use! */
/*passivemode = 1;***/
/*printf("Setting: Passive mode on.\n");***/
} }
} }
} }
#endif #endif
/*printf("Local address is %s\n", inet_ntoa(localaddr->sin_addr));***/
/*printf("Remote address is %s\n", inet_ntoa(remoteaddr->sin_addr));***/
if(Curl_base64_encode(adat.dat, adat.length, &p) < 0) { if(Curl_base64_encode(adat.dat, adat.length, &p) < 0) {
printf("Out of memory base64-encoding.\n"); Curl_failf(data, "Out of memory base64-encoding");
return AUTH_CONTINUE; return AUTH_CONTINUE;
} }
if(Curl_ftpsendf(conn, "ADAT %s", p)) if(Curl_ftpsendf(conn, "ADAT %s", p))
return -2; return -2;
nread = Curl_GetFTPResponse(conn->data->state.buffer, conn, NULL); nread = Curl_GetFTPResponse(data->state.buffer, conn, NULL);
if(nread < 0) if(nread < 0)
return -1; return -1;
free(p); free(p);
if(/*ret != COMPLETE*/conn->data->state.buffer[0] != '2'){ if(data->state.buffer[0] != '2'){
printf("Server didn't accept auth data.\n"); Curl_failf(data, "Server didn't accept auth data");
return AUTH_ERROR; return AUTH_ERROR;
} }
p = strstr(conn->data->state.buffer, "ADAT="); p = strstr(data->state.buffer, "ADAT=");
if(!p){ if(!p) {
printf("Remote host didn't send adat reply.\n"); Curl_failf(data, "Remote host didn't send adat reply");
return AUTH_ERROR; return AUTH_ERROR;
} }
p += 5; p += 5;
len = Curl_base64_decode(p, adat.dat); len = Curl_base64_decode(p, adat.dat);
if(len < 0){ if(len < 0) {
printf("Failed to decode base64 from server.\n"); Curl_failf(data, "Failed to decode base64 from server");
return AUTH_ERROR; return AUTH_ERROR;
} }
adat.length = len; adat.length = len;
ret = krb_rd_safe(adat.dat, adat.length, &d->key, ret = krb_rd_safe(adat.dat, adat.length, &d->key,
(struct sockaddr_in *)hisctladdr, (struct sockaddr_in *)hisctladdr,
(struct sockaddr_in *)myctladdr, &msg_data); (struct sockaddr_in *)myctladdr, &msg_data);
if(ret){ if(ret) {
printf("Error reading reply from server: %s.\n", Curl_failf(data, "Error reading reply from server: %s",
krb_get_err_text(ret)); krb_get_err_text(ret));
return AUTH_ERROR; return AUTH_ERROR;
} }
krb_get_int(msg_data.app_data, &cs, 4, 0); krb_get_int(msg_data.app_data, &cs, 4, 0);
if(cs - checksum != 1){ if(cs - checksum != 1) {
printf("Bad checksum returned from server.\n"); Curl_failf(data, "Bad checksum returned from server");
return AUTH_ERROR; return AUTH_ERROR;
} }
return AUTH_OK; return AUTH_OK;
@@ -321,15 +321,14 @@ void Curl_krb_kauth(struct connectdata *conn)
if(nread < 0) if(nread < 0)
return /*CURLE_OPERATION_TIMEOUTED*/; return /*CURLE_OPERATION_TIMEOUTED*/;
if(/*ret != CONTINUE*/conn->data->state.buffer[0] != '3'){ if(conn->data->state.buffer[0] != '3'){
Curl_set_command_prot(conn, save); Curl_set_command_prot(conn, save);
/*code = -1;***/
return; return;
} }
p = strstr(conn->data->state.buffer, "T="); p = strstr(conn->data->state.buffer, "T=");
if(!p) { if(!p) {
printf("Bad reply from server.\n"); Curl_failf(conn->data, "Bad reply from server");
Curl_set_command_prot(conn, save); Curl_set_command_prot(conn, save);
return; return;
} }
@@ -337,7 +336,7 @@ void Curl_krb_kauth(struct connectdata *conn)
p += 2; p += 2;
tmp = Curl_base64_decode(p, &tkt.dat); tmp = Curl_base64_decode(p, &tkt.dat);
if(tmp < 0) { if(tmp < 0) {
printf("Failed to decode base64 in reply.\n"); Curl_failf(conn->data, "Failed to decode base64 in reply.\n");
Curl_set_command_prot(conn, save); Curl_set_command_prot(conn, save);
return; return;
} }
@@ -346,7 +345,7 @@ void Curl_krb_kauth(struct connectdata *conn)
p = strstr(conn->data->state.buffer, "P="); p = strstr(conn->data->state.buffer, "P=");
if(!p) { if(!p) {
printf("Bad reply from server.\n"); Curl_failf(conn->data, "Bad reply from server");
Curl_set_command_prot(conn, save); Curl_set_command_prot(conn, save);
return; return;
} }
@@ -374,7 +373,7 @@ void Curl_krb_kauth(struct connectdata *conn)
memset(schedule, 0, sizeof(schedule)); memset(schedule, 0, sizeof(schedule));
memset(passwd, 0, sizeof(passwd)); memset(passwd, 0, sizeof(passwd));
if(Curl_base64_encode(tktcopy.dat, tktcopy.length, &p) < 0) { if(Curl_base64_encode(tktcopy.dat, tktcopy.length, &p) < 0) {
failf(conn->data, "Out of memory base64-encoding.\n"); failf(conn->data, "Out of memory base64-encoding.");
Curl_set_command_prot(conn, save); Curl_set_command_prot(conn, save);
return; return;
} }

168
lib/llist.c Normal file
View File

@@ -0,0 +1,168 @@
/*****************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 2001, Daniel Stenberg, <daniel@haxx.se>, et al
*
* In order to be useful for every potential user, curl and libcurl are
* dual-licensed under the MPL and the MIT/X-derivate licenses.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the MPL or the MIT/X-derivate
* licenses. You may pick one of these licenses.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* $Id$
*****************************************************************************/
#include "setup.h"
#include <string.h>
#include "llist.h"
#ifdef MALLOCDEBUG
/* this must be the last include file */
#include "memdebug.h"
#endif
void
curl_llist_init(curl_llist *l, curl_llist_dtor dtor)
{
l->size = 0;
l->dtor = dtor;
l->head = NULL;
l->tail = NULL;
}
curl_llist *
curl_llist_alloc(curl_llist_dtor dtor)
{
curl_llist *list;
list = (curl_llist *)malloc(sizeof(curl_llist));
if(NULL == list)
return NULL;
curl_llist_init(list, dtor);
return list;
}
int
curl_llist_insert_next(curl_llist *list, curl_llist_element *e, const void *p)
{
curl_llist_element *ne;
ne = (curl_llist_element *) malloc(sizeof(curl_llist_element));
ne->ptr = (void *) p;
if (list->size == 0) {
list->head = ne;
list->head->prev = NULL;
list->head->next = NULL;
list->tail = ne;
} else {
ne->next = e->next;
ne->prev = e;
if (e->next) {
e->next->prev = ne;
} else {
list->tail = ne;
}
e->next = ne;
}
++list->size;
return 1;
}
int
curl_llist_insert_prev(curl_llist *list, curl_llist_element *e, const void *p)
{
curl_llist_element *ne;
ne = (curl_llist_element *) malloc(sizeof(curl_llist_element));
ne->ptr = (void *) p;
if (list->size == 0) {
list->head = ne;
list->head->prev = NULL;
list->head->next = NULL;
list->tail = ne;
} else {
ne->next = e;
ne->prev = e->prev;
if (e->prev)
e->prev->next = ne;
else
list->head = ne;
e->prev = ne;
}
++list->size;
return 1;
}
int
curl_llist_remove(curl_llist *list, curl_llist_element *e, void *user)
{
if (e == NULL || list->size == 0)
return 1;
if (e == list->head) {
list->head = e->next;
if (list->head == NULL)
list->tail = NULL;
else
e->next->prev = NULL;
} else {
e->prev->next = e->next;
if (!e->next)
list->tail = e->prev;
else
e->next->prev = e->prev;
}
list->dtor(user, e->ptr);
free(e);
--list->size;
return 1;
}
int
curl_llist_remove_next(curl_llist *list, curl_llist_element *e, void *user)
{
return curl_llist_remove(list, e->next, user);
}
int
curl_llist_remove_prev(curl_llist *list, curl_llist_element *e, void *user)
{
return curl_llist_remove(list, e->prev, user);
}
size_t
curl_llist_count(curl_llist *list)
{
return list->size;
}
void
curl_llist_destroy(curl_llist *list, void *user)
{
while (list->size > 0) {
curl_llist_remove(list, CURL_LLIST_TAIL(list), user);
}
free(list);
list = NULL;
}

64
lib/llist.h Normal file
View File

@@ -0,0 +1,64 @@
#ifndef __LLIST_H
#define __LLIST_H
/*****************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 2001, Daniel Stenberg, <daniel@haxx.se>, et al
*
* In order to be useful for every potential user, curl and libcurl are
* dual-licensed under the MPL and the MIT/X-derivate licenses.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the MPL or the MIT/X-derivate
* licenses. You may pick one of these licenses.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* $Id$
*****************************************************************************/
#include "setup.h"
#include <stddef.h>
typedef void (*curl_llist_dtor)(void *, void *);
typedef struct _curl_llist_element {
void *ptr;
struct _curl_llist_element *prev;
struct _curl_llist_element *next;
} curl_llist_element;
typedef struct _curl_llist {
curl_llist_element *head;
curl_llist_element *tail;
curl_llist_dtor dtor;
size_t size;
} curl_llist;
void curl_llist_init(curl_llist *, curl_llist_dtor);
curl_llist *curl_llist_alloc(curl_llist_dtor);
int curl_llist_insert_next(curl_llist *, curl_llist_element *, const void *);
int curl_llist_insert_prev(curl_llist *, curl_llist_element *, const void *);
int curl_llist_remove(curl_llist *, curl_llist_element *, void *);
int curl_llist_remove_next(curl_llist *, curl_llist_element *, void *);
size_t curl_llist_count(curl_llist *);
void curl_llist_destroy(curl_llist *, void *);
#define CURL_LLIST_HEAD(__l) ((__l)->head)
#define CURL_LLIST_TAIL(__l) ((__l)->tail)
#define CURL_LLIST_NEXT(__e) ((__e)->next)
#define CURL_LLIST_PREV(__e) ((__e)->prev)
#define CURL_LLIST_VALP(__e) ((__e)->ptr)
#define CURL_LLIST_IS_TAIL(__e) ((__e)->next ? 0 : 1)
#define CURL_LLIST_IS_HEAD(__e) ((__e)->prev ? 0 : 1)
#endif

View File

@@ -1,6 +1,14 @@
#ifdef MALLOCDEBUG #ifdef MALLOCDEBUG
#include "setup.h"
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h> #include <sys/socket.h>
#endif
#include <stdio.h> #include <stdio.h>
#ifdef HAVE_MEMORY_H #ifdef HAVE_MEMORY_H
#include <memory.h> #include <memory.h>

View File

@@ -24,73 +24,11 @@
* - Max 128 parameters * - Max 128 parameters
* - No 'long double' support. * - No 'long double' support.
* *
************************************************************************* * If you ever want truly portable and good *printf() clones, the project that
* * took on from here is named 'Trio' and you find more details on the trio web
* * page at http://daniel.haxx.se/trio/
* 1998/01/10 (v2.8) */
* Daniel
* - Updated version number.
* - Corrected a static non-zero prefixed width problem.
*
* 1998/11/17 - Daniel
* Added daprintf() and dvaprintf() for allocated printf() and vprintf().
* They return an allocated buffer with the result inside. The result must
* be free()ed!
*
* 1998/08/23 - breese
*
* Converted all non-printable (and non-whitespace) characters into
* their decimal ASCII value preceeded by a '\' character
* (this only applies to snprintf family so far)
*
* Added %S (which is the same as %#s)
*
* 1998/05/05 (v2.7)
*
* Fixed precision and width qualifiers (%.*s)
*
* Added support for snprintf()
*
* Quoting (%#s) is disabled for the (nil) pointer
*
* 1997/06/09 (v2.6)
*
* %#s means that the string will be quoted with "
* (I was getting tired of writing \"%s\" all the time)
*
* [ERR] for strings changed to (nil)
*
* v2.5
* - Added C++ support
* - Prepended all internal functions with dprintf_
* - Defined the booleans
*
* v2.4
* - Added dvsprintf(), dvfprintf() and dvprintf().
* - Made the formatting function available with the name _formatf() to enable
* other *printf()-inspired functions. (I considered adding a dmsprintf()
* that works like sprintf() but allocates the destination string and
* possibly enlarges it itself, but things like that should be done with the
* new _formatf() instead.)
*
* v2.3
* - Small modifications to make it compile nicely at both Daniel's and
* Bjorn's place.
*
* v2.2
* - Made it work with text to the right of the last %!
* - Introduced dprintf(), dsprintf() and dfprintf().
* - Float/double support enabled. This system is currently using the ordinary
* sprintf() function. NOTE that positional parameters, widths and precisions
* will still work like it should since the d-system takes care of that and
* passes that information re-formatted to the old sprintf().
*
* v2.1
* - Fixed space padding (i.e %d was extra padded previously)
* - long long output is supported
* - alternate output is done correct like in %#08x
*
****************************************************************************/
#include "setup.h" #include "setup.h"
#include <sys/types.h> #include <sys/types.h>
@@ -100,6 +38,15 @@
#include <ctype.h> #include <ctype.h>
#include <string.h> #include <string.h>
#ifndef SIZEOF_LONG_LONG
/* prevents warnings on picky compilers */
#define SIZEOF_LONG_LONG 0
#endif
#ifndef SIZEOF_LONG_DOUBLE
#define SIZEOF_LONG_DOUBLE 0
#endif
/* The last #include file should be: */ /* The last #include file should be: */
#ifdef MALLOCDEBUG #ifdef MALLOCDEBUG
#include "memdebug.h" #include "memdebug.h"
@@ -1191,7 +1138,7 @@ int main()
{ {
char buffer[129]; char buffer[129];
char *ptr; char *ptr;
#ifdef SIZEOF_LONG_LONG #if SIZEOF_LONG_LONG>0
long long hullo; long long hullo;
dprintf("%3$12s %1$s %2$qd %4$d\n", "daniel", hullo, "stenberg", 65); dprintf("%3$12s %1$s %2$qd %4$d\n", "daniel", hullo, "stenberg", 65);
#endif #endif

View File

@@ -22,10 +22,16 @@
*****************************************************************************/ *****************************************************************************/
#include "setup.h" #include "setup.h"
#include <stdlib.h>
#include <string.h>
#include <curl/curl.h> #include <curl/curl.h>
#include "multi.h" /* will become <curl/multi.h> soon */ #include "multi.h" /* will become <curl/multi.h> soon */
#include "urldata.h"
#include "transfer.h"
#include "url.h"
struct Curl_message { struct Curl_message {
/* the 'CURLMsg' is the part that is visible to the external user */ /* the 'CURLMsg' is the part that is visible to the external user */
struct CURLMsg extmsg; struct CURLMsg extmsg;
@@ -48,7 +54,9 @@ struct Curl_one_easy {
struct Curl_one_easy *next; struct Curl_one_easy *next;
struct Curl_one_easy *prev; struct Curl_one_easy *prev;
CURL *easy_handle; /* this is the easy handle for this unit */ struct SessionHandle *easy_handle; /* the easy handle for this unit */
struct connectdata *easy_conn; /* the "unit's" connection */
CURLMstate state; /* the handle's state */ CURLMstate state; /* the handle's state */
CURLcode result; /* previous result */ CURLcode result; /* previous result */
}; };
@@ -74,7 +82,8 @@ struct Curl_multi {
struct Curl_message *msgs; struct Curl_message *msgs;
/* amount of messages in the queue */ /* amount of messages in the queue */
int num_msgs; int num_msgs;
/* Hostname cache */
curl_hash *hostcache;
}; };
@@ -134,7 +143,7 @@ CURLMcode curl_multi_add_handle(CURLM *multi_handle,
/* increase the node-counter */ /* increase the node-counter */
multi->num_easy++; multi->num_easy++;
return CURLM_OK; return CURLM_CALL_MULTI_PERFORM;
} }
CURLMcode curl_multi_remove_handle(CURLM *multi_handle, CURLMcode curl_multi_remove_handle(CURLM *multi_handle,
@@ -190,23 +199,30 @@ CURLMcode curl_multi_fdset(CURLM *multi_handle,
and then we must make sure that is done. */ and then we must make sure that is done. */
struct Curl_multi *multi=(struct Curl_multi *)multi_handle; struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
struct Curl_one_easy *easy; struct Curl_one_easy *easy;
int this_max_fd=-1;
if(!GOOD_MULTI_HANDLE(multi)) if(!GOOD_MULTI_HANDLE(multi))
return CURLM_BAD_HANDLE; return CURLM_BAD_HANDLE;
*max_fd = -1; /* so far none! */
easy=multi->easy.next; easy=multi->easy.next;
while(easy) { while(easy) {
switch(easy->state) { switch(easy->state) {
case CURLM_STATE_INIT: default:
case CURLM_STATE_CONNECT:
case CURLM_STATE_DO:
case CURLM_STATE_DONE:
/* we want curl_multi_perform() to get called, but we don't have any
file descriptors to set */
break; break;
case CURLM_STATE_PERFORM: case CURLM_STATE_PERFORM:
/* This should have a set of file descriptors for us to set. */ /* This should have a set of file descriptors for us to set. */
/* after the transfer is done, go DONE */ /* after the transfer is done, go DONE */
Curl_single_fdset(easy->easy_conn,
read_fd_set, write_fd_set,
exc_fd_set, &this_max_fd);
/* remember the maximum file descriptor */
if(this_max_fd > *max_fd)
*max_fd = this_max_fd;
break; break;
} }
easy = easy->next; /* check next handle */ easy = easy->next; /* check next handle */
@@ -220,50 +236,73 @@ CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
struct Curl_multi *multi=(struct Curl_multi *)multi_handle; struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
struct Curl_one_easy *easy; struct Curl_one_easy *easy;
bool done; bool done;
CURLMcode result=CURLM_OK;
*running_handles = 0; /* bump this once for every living handle */
if(!GOOD_MULTI_HANDLE(multi)) if(!GOOD_MULTI_HANDLE(multi))
return CURLM_BAD_HANDLE; return CURLM_BAD_HANDLE;
easy=multi->easy.next; easy=multi->easy.next;
while(easy) { while(easy) {
switch(easy->state) { switch(easy->state) {
case CURLM_STATE_INIT: case CURLM_STATE_INIT:
/* init this transfer. Hm, uh, I can't think of anything to init /* init this transfer. */
right now, let's skip over to CONNECT at once! easy->result=Curl_pretransfer(easy->easy_handle);
if(CURLE_OK == easy->result) {
easy->result = Curl_init(easy->easy_handle); /* after init, go CONNECT */
if(CURLE_OK == easy->result) easy->state = CURLM_STATE_CONNECT;
*/ result = CURLM_CALL_MULTI_PERFORM;
/* after init, go CONNECT */ }
easy->state = CURLM_STATE_CONNECT;
break; break;
case CURLM_STATE_CONNECT: case CURLM_STATE_CONNECT:
/* connect */ if (Curl_global_host_cache_use(easy->easy_handle)) {
easy->result = Curl_connect(easy->easy_handle); easy->easy_handle->hostcache = Curl_global_host_cache_get();
}
else {
if (multi->hostcache == NULL) {
multi->hostcache = curl_hash_alloc(7, Curl_freeaddrinfo);
}
easy->easy_handle->hostcache = multi->hostcache;
}
/* Connect. We get a connection identifier filled in. */
easy->result = Curl_connect(easy->easy_handle, &easy->easy_conn);
/* after connect, go DO */ /* after connect, go DO */
if(CURLE_OK == easy->result) if(CURLE_OK == easy->result) {
easy->state = CURLM_STATE_DO; easy->state = CURLM_STATE_DO;
result = CURLM_CALL_MULTI_PERFORM;
}
break; break;
case CURLM_STATE_DO: case CURLM_STATE_DO:
/* Do the fetch or put request */ /* Do the fetch or put request */
easy->result = Curl_do(easy->easy_handle); easy->result = Curl_do(&easy->easy_conn);
/* after do, go PERFORM */ /* after do, go PERFORM */
if(CURLE_OK == easy->result) if(CURLE_OK == easy->result) {
easy->state = CURLM_STATE_PERFORM; if(CURLE_OK == Curl_readwrite_init(easy->easy_conn)) {
easy->state = CURLM_STATE_PERFORM;
result = CURLM_CALL_MULTI_PERFORM;
}
}
break; break;
case CURLM_STATE_PERFORM: case CURLM_STATE_PERFORM:
/* read/write data if it is ready to do so */ /* read/write data if it is ready to do so */
easy->result = Curl_readwrite(easy->easy_handle, &done); easy->result = Curl_readwrite(easy->easy_conn, &done);
/* hm, when we follow redirects, we may need to go back to the CONNECT /* hm, when we follow redirects, we may need to go back to the CONNECT
state */ state */
/* after the transfer is done, go DONE */ /* after the transfer is done, go DONE */
if(TRUE == done) if(TRUE == done) {
/* call this even if the readwrite function returned error */
easy->result = Curl_posttransfer(easy->easy_handle);
easy->state = CURLM_STATE_DONE; easy->state = CURLM_STATE_DONE;
result = CURLM_CALL_MULTI_PERFORM;
}
break; break;
case CURLM_STATE_DONE: case CURLM_STATE_DONE:
/* post-transfer command */ /* post-transfer command */
easy->result = Curl_done(easy->easy_handle); easy->result = Curl_done(easy->easy_conn);
/* after we have DONE what we're supposed to do, go COMPLETED */ /* after we have DONE what we're supposed to do, go COMPLETED */
if(CURLE_OK == easy->result) if(CURLE_OK == easy->result)
easy->state = CURLM_STATE_COMPLETED; easy->state = CURLM_STATE_COMPLETED;
@@ -274,7 +313,10 @@ CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
/* This node should be delinked from the list now and we should post /* This node should be delinked from the list now and we should post
an information message that we are complete. */ an information message that we are complete. */
break; break;
default:
return CURLM_INTERNAL_ERROR;
} }
if((CURLM_STATE_COMPLETED != easy->state) && if((CURLM_STATE_COMPLETED != easy->state) &&
(CURLE_OK != easy->result)) { (CURLE_OK != easy->result)) {
/* /*
@@ -283,10 +325,13 @@ CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
*/ */
easy->state = CURLM_STATE_COMPLETED; easy->state = CURLM_STATE_COMPLETED;
} }
else if(CURLM_STATE_COMPLETED != easy->state)
/* this one still lives! */
(*running_handles)++;
easy = easy->next; /* operate on next handle */ easy = easy->next; /* operate on next handle */
} }
return CURLM_OK; return result;
} }
CURLMcode curl_multi_cleanup(CURLM *multi_handle) CURLMcode curl_multi_cleanup(CURLM *multi_handle)
@@ -294,7 +339,7 @@ CURLMcode curl_multi_cleanup(CURLM *multi_handle)
struct Curl_multi *multi=(struct Curl_multi *)multi_handle; struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
if(GOOD_MULTI_HANDLE(multi)) { if(GOOD_MULTI_HANDLE(multi)) {
multi->type = 0; /* not good anymore */ multi->type = 0; /* not good anymore */
curl_hash_destroy(multi->hostcache);
/* remove all easy handles */ /* remove all easy handles */
free(multi); free(multi);
@@ -307,3 +352,10 @@ CURLMcode curl_multi_cleanup(CURLM *multi_handle)
CURLMsg *curl_multi_info_read(CURLM *multi_handle, int *msgs_in_queue); CURLMsg *curl_multi_info_read(CURLM *multi_handle, int *msgs_in_queue);
/*
* local variables:
* eval: (load-file "../curl-mode.el")
* end:
* vim600: fdm=marker
* vim: et sw=2 ts=2 sts=2 tw=78
*/

View File

@@ -50,15 +50,17 @@
#ifdef HAVE_SYS_SOCKET_H #ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h> #include <sys/socket.h>
#endif #endif
#include <curl/types.h> #include <curl/curl.h>
typedef void CURLM; typedef void CURLM;
typedef enum { typedef enum {
CURLM_CALL_MULTI_PERFORM=-1, /* please call curl_multi_perform() soon */
CURLM_OK, CURLM_OK,
CURLM_BAD_HANDLE, /* the passed-in handle is not a valid CURLM handle */ CURLM_BAD_HANDLE, /* the passed-in handle is not a valid CURLM handle */
CURLM_BAD_EASY_HANDLE, /* an easy handle was not good/valid */ CURLM_BAD_EASY_HANDLE, /* an easy handle was not good/valid */
CURLM_OUT_OF_MEMORY, /* if you ever get this, you're in deep sh*t */ CURLM_OUT_OF_MEMORY, /* if you ever get this, you're in deep sh*t */
CURLM_INTERNAL_ERROR, /* this is a libcurl bug */
CURLM_LAST CURLM_LAST
} CURLMcode; } CURLMcode;

View File

@@ -157,7 +157,7 @@ int Curl_parsenetrc(char *host,
} }
else if(state_password) { else if(state_password) {
strncpy(password, tok, PASSWORDSIZE-1); strncpy(password, tok, PASSWORDSIZE-1);
#if _NETRC_DEBUG #ifdef _NETRC_DEBUG
printf("PASSWORD: %s\n", password); printf("PASSWORD: %s\n", password);
#endif #endif
state_password=0; state_password=0;

View File

@@ -362,11 +362,11 @@ Curl_sec_vfprintf(struct connectdata *conn, FILE *f, const char *fmt, va_list ap
conn); conn);
free(buf); free(buf);
if(len < 0) { if(len < 0) {
failf(conn->data, "Failed to encode command.\n"); failf(conn->data, "Failed to encode command.");
return -1; return -1;
} }
if(Curl_base64_encode(enc, len, &buf) < 0){ if(Curl_base64_encode(enc, len, &buf) < 0){
failf(conn->data, "Out of memory base64-encoding.\n"); failf(conn->data, "Out of memory base64-encoding.");
return -1; return -1;
} }
if(conn->command_prot == prot_safe) if(conn->command_prot == prot_safe)
@@ -421,7 +421,7 @@ sec_prot_internal(struct connectdata *conn, int level)
return -1; return -1;
if(conn->data->state.buffer[0] != '2'){ if(conn->data->state.buffer[0] != '2'){
failf(conn->data, "Failed to set protection buffer size.\n"); failf(conn->data, "Failed to set protection buffer size.");
return -1; return -1;
} }
conn->buffer_size = s; conn->buffer_size = s;
@@ -441,7 +441,7 @@ sec_prot_internal(struct connectdata *conn, int level)
return -1; return -1;
if(conn->data->state.buffer[0] != '2'){ if(conn->data->state.buffer[0] != '2'){
failf(conn->data, "Failed to set protection level.\n"); failf(conn->data, "Failed to set protection level.");
return -1; return -1;
} }

View File

@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 2000, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 2002, Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* In order to be useful for every potential user, curl and libcurl are * In order to be useful for every potential user, curl and libcurl are
* dual-licensed under the MPL and the MIT/X-derivate licenses. * dual-licensed under the MPL and the MIT/X-derivate licenses.
@@ -26,6 +26,11 @@
#include <stdio.h> #include <stdio.h>
#include <stdarg.h> #include <stdarg.h>
#include <stdlib.h> #include <stdlib.h>
#include <errno.h>
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_SYS_SOCKET_H #ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h> /* required for send() & recv() prototypes */ #include <sys/socket.h> /* required for send() & recv() prototypes */
@@ -137,8 +142,9 @@ void Curl_infof(struct SessionHandle *data, const char *fmt, ...)
} }
} }
/* Curl_failf() is for messages stating why we failed, the LAST one will be /* Curl_failf() is for messages stating why we failed.
returned for the user (if requested) */ * The message SHALL NOT include any LF or CR.
*/
void Curl_failf(struct SessionHandle *data, const char *fmt, ...) void Curl_failf(struct SessionHandle *data, const char *fmt, ...)
{ {
@@ -156,7 +162,7 @@ CURLcode Curl_sendf(int sockfd, struct connectdata *conn,
const char *fmt, ...) const char *fmt, ...)
{ {
struct SessionHandle *data = conn->data; struct SessionHandle *data = conn->data;
size_t bytes_written; ssize_t bytes_written;
CURLcode result; CURLcode result;
char *s; char *s;
va_list ap; va_list ap;
@@ -183,26 +189,32 @@ CURLcode Curl_sendf(int sockfd, struct connectdata *conn,
*/ */
CURLcode Curl_write(struct connectdata *conn, int sockfd, CURLcode Curl_write(struct connectdata *conn, int sockfd,
void *mem, size_t len, void *mem, size_t len,
size_t *written) ssize_t *written)
{ {
size_t bytes_written; ssize_t bytes_written;
#ifdef USE_SSLEAY #ifdef USE_SSLEAY
/* SSL_write() is said to return 'int' while write() and send() returns /* SSL_write() is said to return 'int' while write() and send() returns
'size_t' */ 'size_t' */
int ssl_bytes;
if (conn->ssl.use) { if (conn->ssl.use) {
int loop=100; /* just a precaution to never loop endlessly */ int err;
while(loop--) { int rc = SSL_write(conn->ssl.handle, mem, len);
ssl_bytes = SSL_write(conn->ssl.handle, mem, len);
if((0 >= ssl_bytes) || if(rc < 0) {
(SSL_ERROR_WANT_WRITE != SSL_get_error(conn->ssl.handle, err = SSL_get_error(conn->ssl.handle, rc);
ssl_bytes) )) {
/* this converts from signed to unsigned... */ switch(err) {
bytes_written = ssl_bytes; case SSL_ERROR_WANT_READ:
break; case SSL_ERROR_WANT_WRITE:
/* this is basicly the EWOULDBLOCK equivalent */
*written = 0;
return CURLE_OK;
} }
/* a true error */
failf(conn->data, "SSL_write() return error %d\n", err);
return CURLE_WRITE_ERROR;
} }
bytes_written = rc;
} }
else { else {
#endif #endif
@@ -212,13 +224,27 @@ CURLcode Curl_write(struct connectdata *conn, int sockfd,
} }
else else
#endif /* KRB4 */ #endif /* KRB4 */
{
bytes_written = swrite(sockfd, mem, len); bytes_written = swrite(sockfd, mem, len);
}
if(-1 == bytes_written) {
#ifdef WIN32
if(WSAEWOULDBLOCK == GetLastError())
#else
if(EWOULDBLOCK == errno)
#endif
{
/* this is just a case of EWOULDBLOCK */
*written=0;
return CURLE_OK;
}
}
#ifdef USE_SSLEAY #ifdef USE_SSLEAY
} }
#endif #endif
*written = bytes_written; *written = bytes_written;
return (bytes_written==len)?CURLE_OK:CURLE_WRITE_ERROR; return (-1 != bytes_written)?CURLE_OK:CURLE_WRITE_ERROR;
} }
/* client_write() sends data to the write callback(s) /* client_write() sends data to the write callback(s)
@@ -262,26 +288,47 @@ CURLcode Curl_client_write(struct SessionHandle *data,
return CURLE_OK; return CURLE_OK;
} }
/* /*
* Internal read-from-socket function. This is meant to deal with plain * Internal read-from-socket function. This is meant to deal with plain
* sockets, SSL sockets and kerberos sockets. * sockets, SSL sockets and kerberos sockets.
*
* If the read would block (EWOULDBLOCK) we return -1. Otherwise we return
* a regular CURLcode value.
*/ */
CURLcode Curl_read(struct connectdata *conn, int sockfd, int Curl_read(struct connectdata *conn,
char *buf, size_t buffersize, int sockfd,
ssize_t *n) char *buf,
size_t buffersize,
ssize_t *n)
{ {
ssize_t nread; ssize_t nread;
#ifdef USE_SSLEAY #ifdef USE_SSLEAY
if (conn->ssl.use) { if (conn->ssl.use) {
int loop=100; /* just a precaution to never loop endlessly */ bool loop=TRUE;
while(loop--) { int err;
do {
nread = SSL_read(conn->ssl.handle, buf, buffersize); nread = SSL_read(conn->ssl.handle, buf, buffersize);
if((-1 != nread) ||
(SSL_ERROR_WANT_READ != SSL_get_error(conn->ssl.handle, nread) )) if(nread > 0)
/* successful read */
break; break;
}
err = SSL_get_error(conn->ssl.handle, nread);
switch(err) {
case SSL_ERROR_NONE: /* this is not an error */
case SSL_ERROR_ZERO_RETURN: /* no more data */
loop=0; /* get out of loop */
break;
case SSL_ERROR_WANT_READ:
case SSL_ERROR_WANT_WRITE:
/* if there's data pending, then we re-invoke SSL_read() */
break;
}
} while(0);
if(loop && SSL_pending(conn->ssl.handle))
return -1; /* basicly EWOULDBLOCK */
} }
else { else {
#endif #endif
@@ -291,6 +338,16 @@ CURLcode Curl_read(struct connectdata *conn, int sockfd,
else else
#endif #endif
nread = sread (sockfd, buf, buffersize); nread = sread (sockfd, buf, buffersize);
if(-1 == nread) {
#ifdef WIN32
if(WSAEWOULDBLOCK == GetLastError())
#else
if(EWOULDBLOCK == errno)
#endif
return -1;
}
#ifdef USE_SSLEAY #ifdef USE_SSLEAY
} }
#endif /* USE_SSLEAY */ #endif /* USE_SSLEAY */

View File

@@ -45,12 +45,12 @@ CURLcode Curl_client_write(struct SessionHandle *data, int type, char *ptr,
size_t len); size_t len);
/* internal read-function, does plain socket, SSL and krb4 */ /* internal read-function, does plain socket, SSL and krb4 */
CURLcode Curl_read(struct connectdata *conn, int sockfd, int Curl_read(struct connectdata *conn, int sockfd,
char *buf, size_t buffersize, char *buf, size_t buffersize,
ssize_t *n); ssize_t *n);
/* internal write-function, does plain socket, SSL and krb4 */ /* internal write-function, does plain socket, SSL and krb4 */
CURLcode Curl_write(struct connectdata *conn, int sockfd, CURLcode Curl_write(struct connectdata *conn, int sockfd,
void *mem, size_t len, void *mem, size_t len,
size_t *written); ssize_t *written);
#endif #endif

View File

@@ -34,9 +34,9 @@
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
#ifdef VMS #ifdef VMS
#include "config-vms.h" #include "../config-vms.h"
#else #else
#include "config.h" /* the configure script results */ #include "../config.h" /* the configure script results */
#endif #endif
#else #else
@@ -46,13 +46,14 @@
#endif #endif
#ifdef macintosh #ifdef macintosh
/* hand-modified MacOS config.h! */ /* hand-modified MacOS config.h! */
#include "config-mac.h" #include "../config-mac.h"
#endif #endif
#endif #endif
#ifndef __cplusplus /* (rabe) */ #ifndef __cplusplus /* (rabe) */
typedef char bool; typedef unsigned char bool;
#define typedef_bool
#endif /* (rabe) */ #endif /* (rabe) */
#ifdef NEED_REENTRANT #ifdef NEED_REENTRANT

View File

@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 2000, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 2001, Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* In order to be useful for every potential user, curl and libcurl are * In order to be useful for every potential user, curl and libcurl are
* dual-licensed under the MPL and the MIT/X-derivate licenses. * dual-licensed under the MPL and the MIT/X-derivate licenses.
@@ -22,11 +22,12 @@
*****************************************************************************/ *****************************************************************************/
/* /*
* The original SSL code was written by * The original SSL code for curl was written by
* Linas Vepstas <linas@linas.org> and Sampo Kellomaki <sampo@iki.fi> * Linas Vepstas <linas@linas.org> and Sampo Kellomaki <sampo@iki.fi>
*/ */
#include "setup.h" #include "setup.h"
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
@@ -42,6 +43,12 @@
#include "memdebug.h" #include "memdebug.h"
#endif #endif
#if OPENSSL_VERSION_NUMBER >= 0x0090581fL
#define HAVE_SSL_GET1_SESSION 1
#else
#undef HAVE_SSL_GET1_SESSION
#endif
#if OPENSSL_VERSION_NUMBER >= 0x00904100L #if OPENSSL_VERSION_NUMBER >= 0x00904100L
#define HAVE_USERDATA_IN_PWD_CALLBACK 1 #define HAVE_USERDATA_IN_PWD_CALLBACK 1
#else #else
@@ -171,37 +178,59 @@ int random_the_seed(struct connectdata *conn)
return nread; return nread;
} }
#ifndef SSL_FILETYPE_ENGINE
#define SSL_FILETYPE_ENGINE 42
#endif
static int do_file_type(const char *type)
{
if (!type || !type[0])
return SSL_FILETYPE_PEM;
if (curl_strequal(type, "PEM"))
return SSL_FILETYPE_PEM;
if (curl_strequal(type, "DER"))
return SSL_FILETYPE_ASN1;
if (curl_strequal(type, "ENG"))
return SSL_FILETYPE_ENGINE;
return -1;
}
static static
int cert_stuff(struct connectdata *conn, int cert_stuff(struct connectdata *conn,
char *cert_file, char *cert_file,
char *key_file) const char *cert_type,
char *key_file,
const char *key_type)
{ {
struct SessionHandle *data = conn->data; struct SessionHandle *data = conn->data;
int file_type;
if (cert_file != NULL) { if (cert_file != NULL) {
SSL *ssl; SSL *ssl;
X509 *x509; X509 *x509;
if(data->set.cert_passwd) { if(data->set.key_passwd) {
#ifndef HAVE_USERDATA_IN_PWD_CALLBACK #ifndef HAVE_USERDATA_IN_PWD_CALLBACK
/* /*
* If password has been given, we store that in the global * If password has been given, we store that in the global
* area (*shudder*) for a while: * area (*shudder*) for a while:
*/ */
strcpy(global_passwd, data->set.cert_passwd); strcpy(global_passwd, data->set.key_passwd);
#else #else
/* /*
* We set the password in the callback userdata * We set the password in the callback userdata
*/ */
SSL_CTX_set_default_passwd_cb_userdata(conn->ssl.ctx, data->set.cert_passwd); SSL_CTX_set_default_passwd_cb_userdata(conn->ssl.ctx,
data->set.key_passwd);
#endif #endif
/* Set passwd callback: */ /* Set passwd callback: */
SSL_CTX_set_default_passwd_cb(conn->ssl.ctx, passwd_callback); SSL_CTX_set_default_passwd_cb(conn->ssl.ctx, passwd_callback);
} }
#if 0
if (SSL_CTX_use_certificate_file(conn->ssl.ctx, if (SSL_CTX_use_certificate_file(conn->ssl.ctx,
cert_file, cert_file,
SSL_FILETYPE_PEM) != 1) { SSL_FILETYPE_PEM) != 1) {
failf(data, "unable to set certificate file (wrong password?)\n"); failf(data, "unable to set certificate file (wrong password?)");
return(0); return(0);
} }
if (key_file == NULL) if (key_file == NULL)
@@ -210,9 +239,86 @@ int cert_stuff(struct connectdata *conn,
if (SSL_CTX_use_PrivateKey_file(conn->ssl.ctx, if (SSL_CTX_use_PrivateKey_file(conn->ssl.ctx,
key_file, key_file,
SSL_FILETYPE_PEM) != 1) { SSL_FILETYPE_PEM) != 1) {
failf(data, "unable to set public key file\n"); failf(data, "unable to set public key file");
return(0); return(0);
} }
#else
/* The '#ifdef 0' section above was removed on 17-dec-2001 */
file_type = do_file_type(cert_type);
switch(file_type) {
case SSL_FILETYPE_PEM:
case SSL_FILETYPE_ASN1:
if (SSL_CTX_use_certificate_file(conn->ssl.ctx,
cert_file,
file_type) != 1) {
failf(data, "unable to set certificate file (wrong password?)");
return 0;
}
break;
case SSL_FILETYPE_ENGINE:
failf(data, "file type ENG for certificate not implemented");
return 0;
default:
failf(data, "not supported file type '%s' for certificate", cert_type);
return 0;
}
file_type = do_file_type(key_type);
switch(file_type) {
case SSL_FILETYPE_PEM:
if (key_file == NULL)
/* cert & key can only be in PEM case in the same file */
key_file=cert_file;
case SSL_FILETYPE_ASN1:
if (SSL_CTX_use_PrivateKey_file(conn->ssl.ctx,
key_file,
file_type) != 1) {
failf(data, "unable to set private key file\n");
return 0;
}
break;
case SSL_FILETYPE_ENGINE:
#ifdef HAVE_OPENSSL_ENGINE_H
{ /* XXXX still needs some work */
EVP_PKEY *priv_key = NULL;
if (conn && conn->data && conn->data->engine) {
if (!key_file || !key_file[0]) {
failf(data, "no key set to load from crypto engine\n");
return 0;
}
priv_key = ENGINE_load_private_key(conn->data->engine,key_file,
data->set.key_passwd);
if (!priv_key) {
failf(data, "failed to load private key from crypto engine\n");
return 0;
}
if (SSL_CTX_use_PrivateKey(conn->ssl.ctx, priv_key) != 1) {
failf(data, "unable to set private key\n");
EVP_PKEY_free(priv_key);
return 0;
}
EVP_PKEY_free(priv_key); /* we don't need the handle any more... */
}
else {
failf(data, "crypto engine not set, can't load private key\n");
return 0;
}
}
#else
failf(data, "file type ENG for private key not supported\n");
return 0;
#endif
break;
default:
failf(data, "not supported file type for private key\n");
return 0;
}
#endif
ssl=SSL_new(conn->ssl.ctx); ssl=SSL_new(conn->ssl.ctx);
x509=SSL_get_certificate(ssl); x509=SSL_get_certificate(ssl);
@@ -229,7 +335,7 @@ int cert_stuff(struct connectdata *conn,
/* Now we know that a key and cert have been set against /* Now we know that a key and cert have been set against
* the SSL context */ * the SSL context */
if (!SSL_CTX_check_private_key(conn->ssl.ctx)) { if (!SSL_CTX_check_private_key(conn->ssl.ctx)) {
failf(data, "Private key does not match the certificate public key\n"); failf(data, "Private key does not match the certificate public key");
return(0); return(0);
} }
#ifndef HAVE_USERDATA_IN_PWD_CALLBACK #ifndef HAVE_USERDATA_IN_PWD_CALLBACK
@@ -269,6 +375,10 @@ void Curl_SSL_init(void)
init_ssl++; /* never again */ init_ssl++; /* never again */
#ifdef HAVE_ENGINE_LOAD_BUILTIN_ENGINES
ENGINE_load_builtin_engines();
#endif
/* Lets get nice error messages */ /* Lets get nice error messages */
SSL_load_error_strings(); SSL_load_error_strings();
@@ -293,6 +403,10 @@ void Curl_SSL_cleanup(void)
table. */ table. */
EVP_cleanup(); EVP_cleanup();
#ifdef HAVE_ENGINE_cleanup
ENGINE_cleanup();
#endif
init_ssl=0; /* not inited any more */ init_ssl=0; /* not inited any more */
} }
#else #else
@@ -428,6 +542,13 @@ int Curl_SSL_Close_All(struct SessionHandle *data)
/* free the cache data */ /* free the cache data */
free(data->state.session); free(data->state.session);
} }
#ifdef HAVE_OPENSSL_ENGINE_H
if (data->engine)
{
ENGINE_free(data->engine);
data->engine = NULL;
}
#endif
return 0; return 0;
} }
@@ -437,23 +558,39 @@ int Curl_SSL_Close_All(struct SessionHandle *data)
static int Store_SSL_Session(struct connectdata *conn) static int Store_SSL_Session(struct connectdata *conn)
{ {
SSL_SESSION *ssl_sessionid; SSL_SESSION *ssl_sessionid;
struct curl_ssl_session *store;
int i; int i;
struct SessionHandle *data=conn->data; /* the mother of all structs */ struct SessionHandle *data=conn->data; /* the mother of all structs */
struct curl_ssl_session *store = &data->state.session[0];
int oldest_age=data->state.session[0].age; /* zero if unused */ int oldest_age=data->state.session[0].age; /* zero if unused */
/* ask OpenSSL, say please */ /* ask OpenSSL, say please */
#ifdef HAVE_SSL_GET1_SESSION
ssl_sessionid = SSL_get1_session(conn->ssl.handle); ssl_sessionid = SSL_get1_session(conn->ssl.handle);
/* SSL_get1_session() will increment the reference /* SSL_get1_session() will increment the reference
count and the session will stay in memory until explicitly freed with count and the session will stay in memory until explicitly freed with
SSL_SESSION_free(3), regardless of its state. */ SSL_SESSION_free(3), regardless of its state.
This function was introduced in openssl 0.9.5a. */
#else
ssl_sessionid = SSL_get_session(conn->ssl.handle);
/* if SSL_get1_session() is unavailable, use SSL_get_session().
This is an inferior option because the session can be flushed
at any time by openssl. It is included only so curl compiles
under versions of openssl < 0.9.5a.
WARNING: How curl behaves if it's session is flushed is
untested.
*/
#endif
/* Now we should add the session ID and the host name to the cache, (remove /* Now we should add the session ID and the host name to the cache, (remove
the oldest if necessary) */ the oldest if necessary) */
/* find an empty slot for us, or find the oldest */ /* find an empty slot for us, or find the oldest */
for(i=0; (i<data->set.ssl.numsessions) && data->state.session[i].sessionid; i++) { for(i=1; (i<data->set.ssl.numsessions) &&
data->state.session[i].sessionid; i++) {
if(data->state.session[i].age < oldest_age) { if(data->state.session[i].age < oldest_age) {
oldest_age = data->state.session[i].age; oldest_age = data->state.session[i].age;
store = &data->state.session[i]; store = &data->state.session[i];
@@ -569,7 +706,11 @@ Curl_SSLConnect(struct connectdata *conn)
} }
if(data->set.cert) { if(data->set.cert) {
if (!cert_stuff(conn, data->set.cert, data->set.cert)) { if (!cert_stuff(conn,
data->set.cert,
data->set.cert_type,
data->set.key,
data->set.key_type)) {
/* failf() is already done in cert_stuff() */ /* failf() is already done in cert_stuff() */
return CURLE_SSL_CONNECT_ERROR; return CURLE_SSL_CONNECT_ERROR;
} }
@@ -578,7 +719,7 @@ Curl_SSLConnect(struct connectdata *conn)
if(data->set.ssl.cipher_list) { if(data->set.ssl.cipher_list) {
if (!SSL_CTX_set_cipher_list(conn->ssl.ctx, if (!SSL_CTX_set_cipher_list(conn->ssl.ctx,
data->set.ssl.cipher_list)) { data->set.ssl.cipher_list)) {
failf(data, "failed setting cipher list\n"); failf(data, "failed setting cipher list");
return CURLE_SSL_CONNECT_ERROR; return CURLE_SSL_CONNECT_ERROR;
} }
} }
@@ -591,7 +732,7 @@ Curl_SSLConnect(struct connectdata *conn)
if (!SSL_CTX_load_verify_locations(conn->ssl.ctx, if (!SSL_CTX_load_verify_locations(conn->ssl.ctx,
data->set.ssl.CAfile, data->set.ssl.CAfile,
data->set.ssl.CApath)) { data->set.ssl.CApath)) {
failf(data,"error setting cerficate verify locations\n"); failf(data,"error setting cerficate verify locations");
return CURLE_SSL_CONNECT_ERROR; return CURLE_SSL_CONNECT_ERROR;
} }
} }
@@ -617,8 +758,80 @@ Curl_SSLConnect(struct connectdata *conn)
} }
/* pass the raw socket into the SSL layers */ /* pass the raw socket into the SSL layers */
SSL_set_fd (conn->ssl.handle, conn->firstsocket); SSL_set_fd(conn->ssl.handle, conn->firstsocket);
err = SSL_connect (conn->ssl.handle);
do {
int what;
fd_set writefd;
fd_set readfd;
struct timeval interval;
long timeout_ms;
err = SSL_connect(conn->ssl.handle);
what = SSL_get_error(conn->ssl.handle, err);
FD_ZERO(&writefd);
FD_ZERO(&readfd);
if(SSL_ERROR_WANT_READ == what)
FD_SET(conn->firstsocket, &readfd);
else if(SSL_ERROR_WANT_WRITE == what)
FD_SET(conn->firstsocket, &writefd);
else
break; /* untreated error */
/* Find out if any timeout is set. If not, use 300 seconds.
Otherwise, figure out the most strict timeout of the two possible one
and then how much time that has elapsed to know how much time we
allow for the connect call */
if(data->set.timeout || data->set.connecttimeout) {
double has_passed;
/* Evaluate in milliseconds how much time that has passed */
has_passed = Curl_tvdiff(Curl_tvnow(), data->progress.start);
#ifndef min
#define min(a, b) ((a) < (b) ? (a) : (b))
#endif
/* get the most strict timeout of the ones converted to milliseconds */
if(data->set.timeout &&
(data->set.timeout>data->set.connecttimeout))
timeout_ms = data->set.timeout*1000;
else
timeout_ms = data->set.connecttimeout*1000;
/* subtract the passed time */
timeout_ms -= (long)has_passed;
if(timeout_ms < 0) {
/* a precaution, no need to continue if time already is up */
failf(data, "SSL connection timeout");
return CURLE_OPERATION_TIMEOUTED;
}
}
else
/* no particular time-out has been set */
timeout_ms=300000; /* milliseconds, default to five minutes */
interval.tv_sec = timeout_ms/1000;
timeout_ms -= interval.tv_sec*1000;
interval.tv_usec = timeout_ms*1000;
what = select(conn->firstsocket+1, &readfd, &writefd, NULL, &interval);
if(what > 0)
/* reabable or writable, go loop yourself */
continue;
else if(0 == what) {
/* timeout */
failf(data, "SSL connection timeout");
return CURLE_OPERATION_TIMEOUTED;
}
else
break; /* get out of loop */
} while(1);
/* 1 is fine /* 1 is fine
0 is "not successful but was shut down controlled" 0 is "not successful but was shut down controlled"
@@ -713,7 +926,7 @@ Curl_SSLConnect(struct connectdata *conn)
if(data->set.ssl.verifypeer) { if(data->set.ssl.verifypeer) {
data->set.ssl.certverifyresult=SSL_get_verify_result(conn->ssl.handle); data->set.ssl.certverifyresult=SSL_get_verify_result(conn->ssl.handle);
if (data->set.ssl.certverifyresult != X509_V_OK) { if (data->set.ssl.certverifyresult != X509_V_OK) {
failf(data, "SSL certificate verify result: %d\n", failf(data, "SSL certificate verify result: %d",
data->set.ssl.certverifyresult); data->set.ssl.certverifyresult);
retcode = CURLE_SSL_PEER_CERTIFICATE; retcode = CURLE_SSL_PEER_CERTIFICATE;
} }

View File

@@ -226,9 +226,9 @@ static void printoption(struct SessionHandle *data,
if (cmd == IAC) if (cmd == IAC)
{ {
if (TELCMD_OK(option)) if (TELCMD_OK(option))
printf("%s IAC %s\n", direction, TELCMD(option)); Curl_infof(data, "%s IAC %s\n", direction, TELCMD(option));
else else
printf("%s IAC %d\n", direction, option); Curl_infof(data, "%s IAC %d\n", direction, option);
} }
else else
{ {
@@ -244,12 +244,12 @@ static void printoption(struct SessionHandle *data,
opt = NULL; opt = NULL;
if(opt) if(opt)
printf("%s %s %s\n", direction, fmt, opt); Curl_infof(data, "%s %s %s\n", direction, fmt, opt);
else else
printf("%s %s %d\n", direction, fmt, option); Curl_infof(data, "%s %s %d\n", direction, fmt, option);
} }
else else
printf("%s %d %d\n", direction, cmd, option); Curl_infof(data, "%s %d %d\n", direction, cmd, option);
} }
} }
} }
@@ -638,7 +638,7 @@ static void printsub(struct SessionHandle *data,
{ {
if (direction) if (direction)
{ {
printf("%s IAC SB ", (direction == '<')? "RCVD":"SENT"); Curl_infof(data, "%s IAC SB ", (direction == '<')? "RCVD":"SENT");
if (length >= 3) if (length >= 3)
{ {
int j; int j;
@@ -648,27 +648,27 @@ static void printsub(struct SessionHandle *data,
if (i != IAC || j != SE) if (i != IAC || j != SE)
{ {
printf("(terminated by "); Curl_infof(data, "(terminated by ");
if (TELOPT_OK(i)) if (TELOPT_OK(i))
printf("%s ", TELOPT(i)); Curl_infof(data, "%s ", TELOPT(i));
else if (TELCMD_OK(i)) else if (TELCMD_OK(i))
printf("%s ", TELCMD(i)); Curl_infof(data, "%s ", TELCMD(i));
else else
printf("%d ", i); Curl_infof(data, "%d ", i);
if (TELOPT_OK(j)) if (TELOPT_OK(j))
printf("%s", TELOPT(j)); Curl_infof(data, "%s", TELOPT(j));
else if (TELCMD_OK(j)) else if (TELCMD_OK(j))
printf("%s", TELCMD(j)); Curl_infof(data, "%s", TELCMD(j));
else else
printf("%d", j); Curl_infof(data, "%d", j);
printf(", not IAC SE!) "); Curl_infof(data, ", not IAC SE!) ");
} }
} }
length -= 2; length -= 2;
} }
if (length < 1) if (length < 1)
{ {
printf("(Empty suboption?)"); Curl_infof(data, "(Empty suboption?)");
return; return;
} }
@@ -677,28 +677,28 @@ static void printsub(struct SessionHandle *data,
case TELOPT_TTYPE: case TELOPT_TTYPE:
case TELOPT_XDISPLOC: case TELOPT_XDISPLOC:
case TELOPT_NEW_ENVIRON: case TELOPT_NEW_ENVIRON:
printf("%s", TELOPT(pointer[0])); Curl_infof(data, "%s", TELOPT(pointer[0]));
break; break;
default: default:
printf("%s (unsupported)", TELOPT(pointer[0])); Curl_infof(data, "%s (unsupported)", TELOPT(pointer[0]));
break; break;
} }
} }
else else
printf("%d (unknown)", pointer[i]); Curl_infof(data, "%d (unknown)", pointer[i]);
switch(pointer[1]) { switch(pointer[1]) {
case TELQUAL_IS: case TELQUAL_IS:
printf(" IS"); Curl_infof(data, " IS");
break; break;
case TELQUAL_SEND: case TELQUAL_SEND:
printf(" SEND"); Curl_infof(data, " SEND");
break; break;
case TELQUAL_INFO: case TELQUAL_INFO:
printf(" INFO/REPLY"); Curl_infof(data, " INFO/REPLY");
break; break;
case TELQUAL_NAME: case TELQUAL_NAME:
printf(" NAME"); Curl_infof(data, " NAME");
break; break;
} }
@@ -706,21 +706,21 @@ static void printsub(struct SessionHandle *data,
case TELOPT_TTYPE: case TELOPT_TTYPE:
case TELOPT_XDISPLOC: case TELOPT_XDISPLOC:
pointer[length] = 0; pointer[length] = 0;
printf(" \"%s\"", &pointer[2]); Curl_infof(data, " \"%s\"", &pointer[2]);
break; break;
case TELOPT_NEW_ENVIRON: case TELOPT_NEW_ENVIRON:
if(pointer[1] == TELQUAL_IS) { if(pointer[1] == TELQUAL_IS) {
printf(" "); Curl_infof(data, " ");
for(i = 3;i < length;i++) { for(i = 3;i < length;i++) {
switch(pointer[i]) { switch(pointer[i]) {
case NEW_ENV_VAR: case NEW_ENV_VAR:
printf(", "); Curl_infof(data, ", ");
break; break;
case NEW_ENV_VALUE: case NEW_ENV_VALUE:
printf(" = "); Curl_infof(data, " = ");
break; break;
default: default:
printf("%c", pointer[i]); Curl_infof(data, "%c", pointer[i]);
break; break;
} }
} }
@@ -728,13 +728,13 @@ static void printsub(struct SessionHandle *data,
break; break;
default: default:
for (i = 2; i < length; i++) for (i = 2; i < length; i++)
printf(" %.2x", pointer[i]); Curl_infof(data, " %.2x", pointer[i]);
break; break;
} }
if (direction) if (direction)
{ {
printf("\n"); Curl_infof(data, "\n");
} }
} }
} }
@@ -1090,7 +1090,7 @@ CURLcode Curl_telnet(struct connectdata *conn)
{ {
unsigned char outbuf[2]; unsigned char outbuf[2];
int out_count = 0; int out_count = 0;
size_t bytes_written; ssize_t bytes_written;
char *buffer = buf; char *buffer = buf;
if(!ReadFile(stdin_handle, buf, 255, &nread, NULL)) { if(!ReadFile(stdin_handle, buf, 255, &nread, NULL)) {
@@ -1116,6 +1116,7 @@ CURLcode Curl_telnet(struct connectdata *conn)
{ {
if(events.lNetworkEvents & FD_READ) if(events.lNetworkEvents & FD_READ)
{ {
/* This reallu OUGHT to check its return code. */
Curl_read(conn, sockfd, buf, BUFSIZE - 1, &nread); Curl_read(conn, sockfd, buf, BUFSIZE - 1, &nread);
telrcv(conn, (unsigned char *)buf, nread); telrcv(conn, (unsigned char *)buf, nread);
@@ -1159,7 +1160,7 @@ CURLcode Curl_telnet(struct connectdata *conn)
if(FD_ISSET(0, &readfd)) { /* read from stdin */ if(FD_ISSET(0, &readfd)) { /* read from stdin */
unsigned char outbuf[2]; unsigned char outbuf[2];
int out_count = 0; int out_count = 0;
size_t bytes_written; ssize_t bytes_written;
char *buffer = buf; char *buffer = buf;
nread = read(0, buf, 255); nread = read(0, buf, 255);
@@ -1176,6 +1177,7 @@ CURLcode Curl_telnet(struct connectdata *conn)
} }
if(FD_ISSET(sockfd, &readfd)) { if(FD_ISSET(sockfd, &readfd)) {
/* This OUGHT to check the return code... */
Curl_read(conn, sockfd, buf, BUFSIZE - 1, &nread); Curl_read(conn, sockfd, buf, BUFSIZE - 1, &nread);
/* if we receive 0 or less here, the server closed the connection and /* if we receive 0 or less here, the server closed the connection and

File diff suppressed because it is too large Load Diff

View File

@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 2000, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 2001, Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* In order to be useful for every potential user, curl and libcurl are * In order to be useful for every potential user, curl and libcurl are
* dual-licensed under the MPL and the MIT/X-derivate licenses. * dual-licensed under the MPL and the MIT/X-derivate licenses.
@@ -24,6 +24,17 @@
*****************************************************************************/ *****************************************************************************/
CURLcode Curl_perform(struct SessionHandle *data); CURLcode Curl_perform(struct SessionHandle *data);
CURLcode Curl_pretransfer(struct SessionHandle *data);
CURLcode Curl_posttransfer(struct SessionHandle *data);
CURLcode Curl_readwrite(struct connectdata *conn, bool *done);
void Curl_single_fdset(struct connectdata *conn,
fd_set *read_fd_set,
fd_set *write_fd_set,
fd_set *exc_fd_set,
int *max_fd);
CURLcode Curl_readwrite_init(struct connectdata *conn);
/* This sets up a forthcoming transfer */ /* This sets up a forthcoming transfer */
CURLcode CURLcode
Curl_Transfer (struct connectdata *data, Curl_Transfer (struct connectdata *data,

170
lib/url.c
View File

@@ -110,6 +110,10 @@
#include <curl/types.h> #include <curl/types.h>
#if defined(HAVE_INET_NTOA_R) && !defined(HAVE_INET_NTOA_R_DECL)
#include "inet_ntoa_r.h"
#endif
#define _MPRINTF_REPLACE /* use our functions only */ #define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h> #include <curl/mprintf.h>
@@ -247,13 +251,15 @@ CURLcode Curl_open(struct SessionHandle **curl)
data->set.httpreq = HTTPREQ_GET; /* Default HTTP request */ data->set.httpreq = HTTPREQ_GET; /* Default HTTP request */
data->set.ftp_use_epsv = TRUE; /* FTP defaults to EPSV operations */ data->set.ftp_use_epsv = TRUE; /* FTP defaults to EPSV operations */
data->set.dns_cache_timeout = 60; /* Timeout every 60 seconds by default */
/* make libcurl quiet by default: */ /* make libcurl quiet by default: */
data->set.hide_progress = TRUE; /* CURLOPT_NOPROGRESS changes these */ data->set.hide_progress = TRUE; /* CURLOPT_NOPROGRESS changes these */
data->progress.flags |= PGRS_HIDE; data->progress.flags |= PGRS_HIDE;
/* Set the default size of the SSL session ID cache */ /* Set the default size of the SSL session ID cache */
data->set.ssl.numsessions = 5; data->set.ssl.numsessions = 5;
/* create an array with connection data struct pointers */ /* create an array with connection data struct pointers */
data->state.numconnects = 5; /* hard-coded right now */ data->state.numconnects = 5; /* hard-coded right now */
data->state.connects = (struct connectdata **) data->state.connects = (struct connectdata **)
@@ -280,6 +286,19 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, ...)
va_start(param, option); va_start(param, option);
switch(option) { switch(option) {
case CURLOPT_DNS_CACHE_TIMEOUT:
data->set.dns_cache_timeout = va_arg(param, int);
break;
case CURLOPT_DNS_USE_GLOBAL_CACHE:
{
int use_cache = va_arg(param, int);
if (use_cache) {
Curl_global_host_cache_init();
}
data->set.global_dns_cache = use_cache;
}
break;
case CURLOPT_SSL_CIPHER_LIST: case CURLOPT_SSL_CIPHER_LIST:
/* set a list of cipher we want to use in the SSL connection */ /* set a list of cipher we want to use in the SSL connection */
data->set.ssl.cipher_list = va_arg(param, char *); data->set.ssl.cipher_list = va_arg(param, char *);
@@ -790,11 +809,75 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, ...)
*/ */
data->set.cert = va_arg(param, char *); data->set.cert = va_arg(param, char *);
break; break;
case CURLOPT_SSLCERTPASSWD: case CURLOPT_SSLCERTTYPE:
/* /*
* String that holds the SSL certificate password. * String that holds file type of the SSL certificate to use
*/ */
data->set.cert_passwd = va_arg(param, char *); data->set.cert_type = va_arg(param, char *);
break;
case CURLOPT_SSLKEY:
/*
* String that holds file name of the SSL certificate to use
*/
data->set.key = va_arg(param, char *);
break;
case CURLOPT_SSLKEYTYPE:
/*
* String that holds file type of the SSL certificate to use
*/
data->set.key_type = va_arg(param, char *);
break;
case CURLOPT_SSLKEYPASSWD:
/*
* String that holds the SSL private key password.
*/
data->set.key_passwd = va_arg(param, char *);
break;
case CURLOPT_SSLENGINE:
/*
* String that holds the SSL crypto engine.
*/
#ifdef HAVE_OPENSSL_ENGINE_H
{
const char *cpTemp = va_arg(param, char *);
ENGINE *e;
if (cpTemp && cpTemp[0]) {
e = ENGINE_by_id(cpTemp);
if (e) {
if (data->engine) {
ENGINE_free(data->engine);
}
data->engine = e;
}
else {
failf(data, "SSL Engine '%s' not found", cpTemp);
return CURLE_SSL_ENGINE_NOTFOUND;
}
}
}
#else
return CURLE_SSL_ENGINE_NOTFOUND;
#endif
break;
case CURLOPT_SSLENGINE_DEFAULT:
/*
* flag to set engine as default.
*/
#ifdef HAVE_OPENSSL_ENGINE_H
if (data->engine) {
if (ENGINE_set_default(data->engine, ENGINE_METHOD_ALL) > 0) {
#ifdef DEBUG
fprintf(stderr,"set default crypto engine\n");
#endif
}
else {
#ifdef DEBUG
failf(data, "set default crypto engine failed");
#endif
return CURLE_SSL_ENGINE_SETFAILED;
}
}
#endif
break; break;
case CURLOPT_CRLF: case CURLOPT_CRLF:
/* /*
@@ -876,9 +959,6 @@ CURLcode Curl_disconnect(struct connectdata *conn)
if(conn->proto.generic) if(conn->proto.generic)
free(conn->proto.generic); free(conn->proto.generic);
if(conn->hostent_buf) /* host name info */
Curl_freeaddrinfo(conn->hostent_buf);
if(conn->newurl) if(conn->newurl)
free(conn->newurl); free(conn->newurl);
@@ -1153,8 +1233,7 @@ static CURLcode ConnectPlease(struct connectdata *conn)
} }
static CURLcode CreateConnection(struct SessionHandle *data, static CURLcode CreateConnection(struct SessionHandle *data,
struct connectdata **in_connect, struct connectdata **in_connect)
bool allow_port) /* allow set.use_port? */
{ {
char *tmp; char *tmp;
char *buf; char *buf;
@@ -1164,6 +1243,9 @@ static CURLcode CreateConnection(struct SessionHandle *data,
struct connectdata *conn_temp; struct connectdata *conn_temp;
char endbracket; char endbracket;
int urllen; int urllen;
#ifdef HAVE_INET_NTOA_R
char ntoa_buf[64];
#endif
#ifdef HAVE_ALARM #ifdef HAVE_ALARM
unsigned int prev_alarm; unsigned int prev_alarm;
#endif #endif
@@ -1502,6 +1584,7 @@ static CURLcode CreateConnection(struct SessionHandle *data,
/* we have a proxy here to set */ /* we have a proxy here to set */
data->change.proxy = proxy; data->change.proxy = proxy;
data->change.proxy_alloc=TRUE; /* this needs to be freed later */ data->change.proxy_alloc=TRUE; /* this needs to be freed later */
conn->bits.httpproxy = TRUE;
} }
} /* if (!nope) - it wasn't specified non-proxy */ } /* if (!nope) - it wasn't specified non-proxy */
} /* NO_PROXY wasn't specified or '*' */ } /* NO_PROXY wasn't specified or '*' */
@@ -1552,7 +1635,8 @@ static CURLcode CreateConnection(struct SessionHandle *data,
*************************************************************/ *************************************************************/
if (strequal(conn->protostr, "HTTP")) { if (strequal(conn->protostr, "HTTP")) {
conn->port = (data->set.use_port && allow_port)?data->set.use_port:PORT_HTTP; conn->port = (data->set.use_port && data->state.allow_port)?
data->set.use_port:PORT_HTTP;
conn->remote_port = PORT_HTTP; conn->remote_port = PORT_HTTP;
conn->protocol |= PROT_HTTP; conn->protocol |= PROT_HTTP;
conn->curl_do = Curl_http; conn->curl_do = Curl_http;
@@ -1562,7 +1646,8 @@ static CURLcode CreateConnection(struct SessionHandle *data,
else if (strequal(conn->protostr, "HTTPS")) { else if (strequal(conn->protostr, "HTTPS")) {
#ifdef USE_SSLEAY #ifdef USE_SSLEAY
conn->port = (data->set.use_port && allow_port)?data->set.use_port:PORT_HTTPS; conn->port = (data->set.use_port && data->state.allow_port)?
data->set.use_port:PORT_HTTPS;
conn->remote_port = PORT_HTTPS; conn->remote_port = PORT_HTTPS;
conn->protocol |= PROT_HTTP|PROT_HTTPS|PROT_SSL; conn->protocol |= PROT_HTTP|PROT_HTTPS|PROT_SSL;
@@ -1577,7 +1662,8 @@ static CURLcode CreateConnection(struct SessionHandle *data,
#endif /* !USE_SSLEAY */ #endif /* !USE_SSLEAY */
} }
else if (strequal(conn->protostr, "GOPHER")) { else if (strequal(conn->protostr, "GOPHER")) {
conn->port = (data->set.use_port && allow_port)?data->set.use_port:PORT_GOPHER; conn->port = (data->set.use_port && data->state.allow_port)?
data->set.use_port:PORT_GOPHER;
conn->remote_port = PORT_GOPHER; conn->remote_port = PORT_GOPHER;
/* Skip /<item-type>/ in path if present */ /* Skip /<item-type>/ in path if present */
if (isdigit((int)conn->path[1])) { if (isdigit((int)conn->path[1])) {
@@ -1603,7 +1689,8 @@ static CURLcode CreateConnection(struct SessionHandle *data,
#endif /* !USE_SSLEAY */ #endif /* !USE_SSLEAY */
} }
conn->port = (data->set.use_port && allow_port)?data->set.use_port:PORT_FTP; conn->port = (data->set.use_port && data->state.allow_port)?
data->set.use_port:PORT_FTP;
conn->remote_port = PORT_FTP; conn->remote_port = PORT_FTP;
conn->protocol |= PROT_FTP; conn->protocol |= PROT_FTP;
@@ -1658,21 +1745,24 @@ static CURLcode CreateConnection(struct SessionHandle *data,
/* telnet testing factory */ /* telnet testing factory */
conn->protocol |= PROT_TELNET; conn->protocol |= PROT_TELNET;
conn->port = (data->set.use_port && allow_port)?data->set.use_port: PORT_TELNET; conn->port = (data->set.use_port && data->state.allow_port)?
data->set.use_port: PORT_TELNET;
conn->remote_port = PORT_TELNET; conn->remote_port = PORT_TELNET;
conn->curl_do = Curl_telnet; conn->curl_do = Curl_telnet;
conn->curl_done = Curl_telnet_done; conn->curl_done = Curl_telnet_done;
} }
else if (strequal(conn->protostr, "DICT")) { else if (strequal(conn->protostr, "DICT")) {
conn->protocol |= PROT_DICT; conn->protocol |= PROT_DICT;
conn->port = (data->set.use_port && allow_port)?data->set.use_port:PORT_DICT; conn->port = (data->set.use_port && data->state.allow_port)?
data->set.use_port:PORT_DICT;
conn->remote_port = PORT_DICT; conn->remote_port = PORT_DICT;
conn->curl_do = Curl_dict; conn->curl_do = Curl_dict;
conn->curl_done = NULL; /* no DICT-specific done */ conn->curl_done = NULL; /* no DICT-specific done */
} }
else if (strequal(conn->protostr, "LDAP")) { else if (strequal(conn->protostr, "LDAP")) {
conn->protocol |= PROT_LDAP; conn->protocol |= PROT_LDAP;
conn->port = (data->set.use_port && allow_port)?data->set.use_port:PORT_LDAP; conn->port = (data->set.use_port && data->state.allow_port)?
data->set.use_port:PORT_LDAP;
conn->remote_port = PORT_LDAP; conn->remote_port = PORT_LDAP;
conn->curl_do = Curl_ldap; conn->curl_do = Curl_ldap;
conn->curl_done = NULL; /* no LDAP-specific done */ conn->curl_done = NULL; /* no LDAP-specific done */
@@ -1995,8 +2085,8 @@ static CURLcode CreateConnection(struct SessionHandle *data,
/* Resolve target host right on */ /* Resolve target host right on */
if(!conn->hostaddr) { if(!conn->hostaddr) {
/* it might already be set if reusing a connection */ /* it might already be set if reusing a connection */
conn->hostaddr = Curl_getaddrinfo(data, conn->name, conn->port, conn->hostaddr = Curl_resolv(data, conn->name, conn->port,
&conn->hostent_buf); &conn->hostent_buf);
} }
if(!conn->hostaddr) { if(!conn->hostaddr) {
failf(data, "Couldn't resolve host '%s'", conn->name); failf(data, "Couldn't resolve host '%s'", conn->name);
@@ -2010,8 +2100,8 @@ static CURLcode CreateConnection(struct SessionHandle *data,
/* resolve proxy */ /* resolve proxy */
/* it might already be set if reusing a connection */ /* it might already be set if reusing a connection */
conn->hostaddr = Curl_getaddrinfo(data, conn->proxyhost, conn->port, conn->hostaddr = Curl_resolv(data, conn->proxyhost, conn->port,
&conn->hostent_buf); &conn->hostent_buf);
if(!conn->hostaddr) { if(!conn->hostaddr) {
failf(data, "Couldn't resolve proxy '%s'", conn->proxyhost); failf(data, "Couldn't resolve proxy '%s'", conn->proxyhost);
@@ -2146,7 +2236,12 @@ static CURLcode CreateConnection(struct SessionHandle *data,
struct in_addr in; struct in_addr in;
(void) memcpy(&in.s_addr, &conn->serv_addr.sin_addr, sizeof (in.s_addr)); (void) memcpy(&in.s_addr, &conn->serv_addr.sin_addr, sizeof (in.s_addr));
infof(data, "Connected to %s (%s)\n", conn->hostaddr->h_name, infof(data, "Connected to %s (%s)\n", conn->hostaddr->h_name,
inet_ntoa(in)); #if defined(HAVE_INET_NTOA_R)
inet_ntoa_r(in, ntoa_buf, sizeof(ntoa_buf))
#else
inet_ntoa(in)
#endif
);
} }
#endif #endif
@@ -2166,14 +2261,13 @@ static CURLcode CreateConnection(struct SessionHandle *data,
} }
CURLcode Curl_connect(struct SessionHandle *data, CURLcode Curl_connect(struct SessionHandle *data,
struct connectdata **in_connect, struct connectdata **in_connect)
bool allow_port)
{ {
CURLcode code; CURLcode code;
struct connectdata *conn; struct connectdata *conn;
/* call the stuff that needs to be called */ /* call the stuff that needs to be called */
code = CreateConnection(data, in_connect, allow_port); code = CreateConnection(data, in_connect);
if(CURLE_OK != code) { if(CURLE_OK != code) {
/* We're not allowed to return failure with memory left allocated /* We're not allowed to return failure with memory left allocated
@@ -2229,14 +2323,38 @@ CURLcode Curl_done(struct connectdata *conn)
return result; return result;
} }
CURLcode Curl_do(struct connectdata *conn) CURLcode Curl_do(struct connectdata **connp)
{ {
CURLcode result=CURLE_OK; CURLcode result=CURLE_OK;
struct connectdata *conn = *connp;
struct SessionHandle *data=conn->data;
if(conn->curl_do) if(conn->curl_do) {
/* generic protocol-specific function pointer set in curl_connect() */ /* generic protocol-specific function pointer set in curl_connect() */
result = conn->curl_do(conn); result = conn->curl_do(conn);
/* This was formerly done in transfer.c, but we better do it here */
if((CURLE_WRITE_ERROR == result) && conn->bits.reuse) {
/* This was a re-use of a connection and we got a write error in the
* DO-phase. Then we DISCONNECT this connection and have another attempt
* to CONNECT and then DO again! The retry cannot possibly find another
* connection to re-use, since we only keep one possible connection for
* each. */
infof(data, "Re-used connection seems dead, get a new one\n");
conn->bits.close = TRUE; /* enforce close of this connetion */
result = Curl_done(conn); /* we are so done with this */
if(CURLE_OK == result) {
/* Now, redo the connect and get a new connection */
result = Curl_connect(data, connp);
if(CURLE_OK == result)
/* ... finally back to actually retry the DO phase */
result = conn->curl_do(*connp);
}
}
}
return result; return result;
} }

View File

@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 2000, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 2001, Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* In order to be useful for every potential user, curl and libcurl are * In order to be useful for every potential user, curl and libcurl are
* dual-licensed under the MPL and the MIT/X-derivate licenses. * dual-licensed under the MPL and the MIT/X-derivate licenses.
@@ -29,11 +29,9 @@
CURLcode Curl_open(struct SessionHandle **curl); CURLcode Curl_open(struct SessionHandle **curl);
CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, ...); CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, ...);
CURLcode Curl_close(struct SessionHandle *data); /* the opposite of curl_open() */ CURLcode Curl_close(struct SessionHandle *data); /* opposite of curl_open() */
CURLcode Curl_connect(struct SessionHandle *, CURLcode Curl_connect(struct SessionHandle *, struct connectdata **);
struct connectdata **, CURLcode Curl_do(struct connectdata **);
bool allow_port);
CURLcode Curl_do(struct connectdata *);
CURLcode Curl_done(struct connectdata *); CURLcode Curl_done(struct connectdata *);
CURLcode Curl_disconnect(struct connectdata *); CURLcode Curl_disconnect(struct connectdata *);

View File

@@ -27,6 +27,7 @@
#include "setup.h" #include "setup.h"
#include "hostip.h" #include "hostip.h"
#include "hash.h"
#define PORT_FTP 21 #define PORT_FTP 21
#define PORT_TELNET 23 #define PORT_TELNET 23
@@ -58,6 +59,9 @@
#include "openssl/pem.h" #include "openssl/pem.h"
#include "openssl/ssl.h" #include "openssl/ssl.h"
#include "openssl/err.h" #include "openssl/err.h"
#ifdef HAVE_OPENSSL_ENGINE_H
#include <openssl/engine.h>
#endif
#else #else
#include "rsa.h" #include "rsa.h"
#include "crypto.h" #include "crypto.h"
@@ -79,7 +83,7 @@
#include "http_chunks.h" /* for the structs and enum stuff */ #include "http_chunks.h" /* for the structs and enum stuff */
/* Download buffer size, keep it fairly big for speed reasons */ /* Download buffer size, keep it fairly big for speed reasons */
#define BUFSIZE (1024*50) #define BUFSIZE (1024*20)
/* Defaul upload buffer size, keep it smallish to get faster progress meter /* Defaul upload buffer size, keep it smallish to get faster progress meter
updates. This is just default, it is dynamic and adjusts to the upload updates. This is just default, it is dynamic and adjusts to the upload
@@ -111,6 +115,9 @@ enum protection_level {
}; };
#endif #endif
#ifndef HAVE_OPENSSL_ENGINE_H
typedef void ENGINE;
#endif
/* struct for data related to SSL and SSL connections */ /* struct for data related to SSL and SSL connections */
struct ssl_connect_data { struct ssl_connect_data {
bool use; /* use ssl encrypted communications TRUE/FALSE */ bool use; /* use ssl encrypted communications TRUE/FALSE */
@@ -205,6 +212,58 @@ struct ConnectBits {
complete */ complete */
}; };
/*
* This struct is all the previously local variables from Curl_perform() moved
* to struct to allow the function to return and get re-invoked better without
* losing state.
*/
struct Curl_transfer_keeper {
int bytecount; /* total number of bytes read */
int writebytecount; /* number of bytes written */
long contentlength; /* size of incoming data */
struct timeval start; /* transfer started at this time */
struct timeval now; /* current time */
bool header; /* incoming data has HTTP header */
int headerline; /* counts header lines to better track the
first one */
char *hbufp; /* points at *end* of header line */
int hbuflen;
char *str; /* within buf */
char *str_start; /* within buf */
char *end_ptr; /* within buf */
char *p; /* within headerbuff */
bool content_range; /* set TRUE if Content-Range: was found */
int offset; /* possible resume offset read from the
Content-Range: header */
int httpcode; /* error code from the 'HTTP/1.? XXX' line */
int httpversion; /* the HTTP version*10 */
bool write_after_100_header; /* should we enable the write after
we received a 100-continue/timeout
or directly */
/* for the low speed checks: */
time_t timeofdoc;
long bodywrites;
int writetype;
/* the highest fd we use + 1 */
struct SessionHandle *data;
struct connectdata *conn;
char *buf;
char *uploadbuf;
int maxfd;
/* the file descriptors to play with */
fd_set readfd;
fd_set writefd;
fd_set rkeepfd;
fd_set wkeepfd;
int keepon;
};
/* /*
* The connectdata struct contains all fields and variables that should be * The connectdata struct contains all fields and variables that should be
* unique for an entire connection. * unique for an entire connection.
@@ -349,6 +408,18 @@ struct connectdata {
void *generic; void *generic;
} proto; } proto;
/* This struct is inited when needed */
struct Curl_transfer_keeper keep;
/* 'upload_present' is used to keep a byte counter of how much data there is
still left in the buffer, aimed for upload. */
int upload_present;
/* 'upload_fromhere' is used as a read-pointer when we uploaded parts of a
buffer, so the next read should read from where this pointer points to,
and the 'upload_present' contains the number of bytes available at this
position */
char *upload_fromhere;
}; };
/* /*
@@ -435,8 +506,8 @@ struct UrlState {
char *headerbuff; /* allocated buffer to store headers in */ char *headerbuff; /* allocated buffer to store headers in */
int headersize; /* size of the allocation */ int headersize; /* size of the allocation */
char buffer[BUFSIZE+1]; /* buffer with size BUFSIZE */ char buffer[BUFSIZE+1]; /* download buffer */
char uploadbuffer[BUFSIZE+1]; /* upload buffer */
double current_speed; /* the ProgressShow() funcion sets this */ double current_speed; /* the ProgressShow() funcion sets this */
bool this_is_a_follow; /* this is a followed Location: request */ bool this_is_a_follow; /* this is a followed Location: request */
@@ -454,6 +525,13 @@ struct UrlState {
bool errorbuf; /* Set to TRUE if the error buffer is already filled in. bool errorbuf; /* Set to TRUE if the error buffer is already filled in.
This must be set to FALSE every time _easy_perform() is This must be set to FALSE every time _easy_perform() is
called. */ called. */
#ifdef HAVE_SIGNAL
/* storage for the previous bag^H^H^HSIGPIPE signal handler :-) */
void (*prev_signal)(int sig);
#endif
bool allow_port; /* Is set.use_port allowed to take effect or not. This
is always set TRUE when curl_easy_perform() is called. */
}; };
@@ -525,8 +603,12 @@ struct UserDefined {
char *cookie; /* HTTP cookie string to send */ char *cookie; /* HTTP cookie string to send */
struct curl_slist *headers; /* linked list of extra headers */ struct curl_slist *headers; /* linked list of extra headers */
struct HttpPost *httppost; /* linked list of POST data */ struct HttpPost *httppost; /* linked list of POST data */
char *cert; /* PEM-formatted certificate */ char *cert; /* certificate */
char *cert_passwd; /* plain text certificate password */ char *cert_type; /* format for certificate (default: PEM) */
char *key; /* private key */
char *key_type; /* format for private key (default: PEM) */
char *key_passwd; /* plain text private key password */
char *crypto_engine; /* name of the crypto engine to use */
char *cookiejar; /* dump all cookies to this file */ char *cookiejar; /* dump all cookies to this file */
bool crlf; /* convert crlf on ftp upload(?) */ bool crlf; /* convert crlf on ftp upload(?) */
struct curl_slist *quote; /* before the transfer */ struct curl_slist *quote; /* before the transfer */
@@ -546,6 +628,8 @@ struct UserDefined {
char *krb4_level; /* what security level */ char *krb4_level; /* what security level */
struct ssl_config_data ssl; /* user defined SSL stuff */ struct ssl_config_data ssl; /* user defined SSL stuff */
int dns_cache_timeout; /* DNS cache timeout */
/* Here follows boolean settings that define how to behave during /* Here follows boolean settings that define how to behave during
this session. They are STATIC, set by libcurl users or at least initially this session. They are STATIC, set by libcurl users or at least initially
and they don't change during operations. */ and they don't change during operations. */
@@ -559,7 +643,9 @@ struct UserDefined {
bool hide_progress; bool hide_progress;
bool http_fail_on_error; bool http_fail_on_error;
bool http_follow_location; bool http_follow_location;
bool http_include_header; bool include_header;
#define http_include_header include_header /* former name */
bool http_set_referer; bool http_set_referer;
bool http_auto_referer; /* set "correct" referer when following location: */ bool http_auto_referer; /* set "correct" referer when following location: */
bool no_body; bool no_body;
@@ -572,6 +658,8 @@ struct UserDefined {
bool reuse_fresh; /* do not re-use an existing connection */ bool reuse_fresh; /* do not re-use an existing connection */
bool expect100header; /* TRUE if we added Expect: 100-continue */ bool expect100header; /* TRUE if we added Expect: 100-continue */
bool ftp_use_epsv; /* if EPSV is to be attempted or not */ bool ftp_use_epsv; /* if EPSV is to be attempted or not */
bool global_dns_cache;
}; };
/* /*
@@ -586,6 +674,7 @@ struct UserDefined {
* 'struct urlstate' instead. */ * 'struct urlstate' instead. */
struct SessionHandle { struct SessionHandle {
curl_hash *hostcache;
struct UserDefined set; /* values set by the libcurl user */ struct UserDefined set; /* values set by the libcurl user */
struct DynamicStatic change; /* possibly modified userdefined data */ struct DynamicStatic change; /* possibly modified userdefined data */
@@ -594,6 +683,9 @@ struct SessionHandle {
struct UrlState state; /* struct for fields used for state info and struct UrlState state; /* struct for fields used for state info and
other dynamic purposes */ other dynamic purposes */
struct PureInfo info; /* stats, reports and info data */ struct PureInfo info; /* stats, reports and info data */
#ifdef USE_SSLEAY
ENGINE* engine;
#endif /* USE_SSLEAY */
}; };
#define LIBCURL_NAME "libcurl" #define LIBCURL_NAME "libcurl"

View File

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

21
multi/Makefile.am Normal file
View File

@@ -0,0 +1,21 @@
#
# $Id$
#
INCLUDES = -I$(top_srcdir)/include
bin_PROGRAMS = app single double
app_SOURCES = app.c
app_LDADD = ../lib/libcurl.la
app_DEPENDENCIES = ../lib/libcurl.la
single_SOURCES = single.c
single_LDADD = ../lib/libcurl.la
single_DEPENDENCIES = ../lib/libcurl.la
double_SOURCES = double.c
double_LDADD = ../lib/libcurl.la
double_DEPENDENCIES = ../lib/libcurl.la
AUTOMAKE_OPTIONS = foreign no-dependencies

92
multi/app.c Normal file
View File

@@ -0,0 +1,92 @@
/*
* This is an example application source code using the multi interface.
*/
#include <stdio.h>
#include <string.h>
/* somewhat unix-specific */
#include <sys/time.h>
#include <unistd.h>
/* To start with, we include the header from the lib directory. This should
later of course be moved to the proper include dir. */
#include "../lib/multi.h"
/*
* Download a HTTP file and upload an FTP file simultaneously.
*/
int main(int argc, char **argv)
{
CURL *http_handle;
CURL *ftp_handle;
CURLM *multi_handle;
int still_running; /* keep number of running handles */
http_handle = curl_easy_init();
ftp_handle = curl_easy_init();
/* set the options (I left out a few, you'll get the point anyway) */
curl_easy_setopt(http_handle, CURLOPT_URL, "http://website.com");
curl_easy_setopt(ftp_handle, CURLOPT_URL, "ftp://ftpsite.com");
curl_easy_setopt(ftp_handle, CURLOPT_UPLOAD, TRUE);
/* init a multi stack */
multi_handle = curl_multi_init();
/* add the individual transfers */
curl_multi_add_handle(multi_handle, http_handle);
curl_multi_add_handle(multi_handle, ftp_handle);
/* we start some action by calling perform right away */
while(CURLM_CALL_MULTI_PERFORM ==
curl_multi_perform(multi_handle, &still_running));
while(still_running) {
struct timeval timeout;
int rc; /* select() return code */
fd_set fdread;
fd_set fdwrite;
fd_set fdexcep;
int maxfd;
FD_ZERO(&fdread);
FD_ZERO(&fdwrite);
FD_ZERO(&fdexcep);
/* set a suitable timeout to play around with */
timeout.tv_sec = 1;
timeout.tv_usec = 0;
/* get file descriptors from the transfers */
curl_multi_fdset(multi_handle, &fdread, &fdwrite, &fdexcep, &maxfd);
rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
switch(rc) {
case -1:
/* select error */
break;
case 0:
/* timeout, do something else */
break;
default:
/* one or more of curl's file descriptors say there's data to read
or write */
curl_multi_perform(multi_handle, &still_running);
break;
}
}
curl_multi_cleanup(multi_handle);
curl_easy_cleanup(http_handle);
curl_easy_cleanup(ftp_handle);
return 0;
}

87
multi/double.c Normal file
View File

@@ -0,0 +1,87 @@
/*
* This is a simple example using the multi interface.
*/
#include <stdio.h>
#include <string.h>
/* somewhat unix-specific */
#include <sys/time.h>
#include <unistd.h>
/* To start with, we include the header from the lib directory. This should
later of course be moved to the proper include dir. */
#include "../lib/multi.h"
/*
* Simply download two HTTP files!
*/
int main(int argc, char **argv)
{
CURL *http_handle;
CURL *http_handle2;
CURLM *multi_handle;
int still_running; /* keep number of running handles */
http_handle = curl_easy_init();
http_handle2 = curl_easy_init();
/* set options */
curl_easy_setopt(http_handle, CURLOPT_URL, "http://www.haxx.se/");
/* set options */
curl_easy_setopt(http_handle2, CURLOPT_URL, "http://localhost/");
/* init a multi stack */
multi_handle = curl_multi_init();
/* add the individual transfers */
curl_multi_add_handle(multi_handle, http_handle);
curl_multi_add_handle(multi_handle, http_handle2);
/* we start some action by calling perform right away */
while(CURLM_CALL_MULTI_PERFORM ==
curl_multi_perform(multi_handle, &still_running));
while(still_running) {
struct timeval timeout;
int rc; /* select() return code */
fd_set fdread;
fd_set fdwrite;
fd_set fdexcep;
int maxfd;
FD_ZERO(&fdread);
FD_ZERO(&fdwrite);
FD_ZERO(&fdexcep);
/* set a suitable timeout to play around with */
timeout.tv_sec = 1;
timeout.tv_usec = 0;
/* get file descriptors from the transfers */
curl_multi_fdset(multi_handle, &fdread, &fdwrite, &fdexcep, &maxfd);
rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
switch(rc) {
case -1:
/* select error */
break;
case 0:
default:
/* timeout or readable/writable sockets */
curl_multi_perform(multi_handle, &still_running);
break;
}
}
curl_multi_cleanup(multi_handle);
curl_easy_cleanup(http_handle);
curl_easy_cleanup(http_handle2);
return 0;
}

80
multi/single.c Normal file
View File

@@ -0,0 +1,80 @@
/*
* This is a very simple example using the multi interface.
*/
#include <stdio.h>
#include <string.h>
/* somewhat unix-specific */
#include <sys/time.h>
#include <unistd.h>
/* To start with, we include the header from the lib directory. This should
later of course be moved to the proper include dir. */
#include "../lib/multi.h"
/*
* Simply download a HTTP file.
*/
int main(int argc, char **argv)
{
CURL *http_handle;
CURLM *multi_handle;
int still_running; /* keep number of running handles */
http_handle = curl_easy_init();
/* set the options (I left out a few, you'll get the point anyway) */
curl_easy_setopt(http_handle, CURLOPT_URL, "http://www.haxx.se/");
/* init a multi stack */
multi_handle = curl_multi_init();
/* add the individual transfers */
curl_multi_add_handle(multi_handle, http_handle);
/* we start some action by calling perform right away */
while(CURLM_CALL_MULTI_PERFORM ==
curl_multi_perform(multi_handle, &still_running));
while(still_running) {
struct timeval timeout;
int rc; /* select() return code */
fd_set fdread;
fd_set fdwrite;
fd_set fdexcep;
int maxfd;
FD_ZERO(&fdread);
FD_ZERO(&fdwrite);
FD_ZERO(&fdexcep);
/* set a suitable timeout to play around with */
timeout.tv_sec = 1;
timeout.tv_usec = 0;
/* get file descriptors from the transfers */
curl_multi_fdset(multi_handle, &fdread, &fdwrite, &fdexcep, &maxfd);
rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
switch(rc) {
case -1:
/* select error */
break;
case 0:
default:
/* timeout or readable/writable sockets */
curl_multi_perform(multi_handle, &still_running);
break;
}
}
curl_multi_cleanup(multi_handle);
curl_easy_cleanup(http_handle);
return 0;
}

View File

@@ -10,8 +10,14 @@ Perl
elegantly used from within it. You can either invoke external curl command elegantly used from within it. You can either invoke external curl command
line or use the curl interface. line or use the curl interface.
Georg Horn's Perl interface to curl is available in the Curl_easy/ The latest release of Curl_easy, a Perl interface to curl is available from
subdirectory. Using the Curl::easy module is just straightforward and
http://curl.haxx.se/libcurl/perl/
(Georg Horn's original version of Curl_easy, supporting curl versions
before 7.7 is still available from: http://www.koblenz-net.de/~horn/export/ )
Using the Curl::easy module is just straightforward and
works much like using libcurl in a C programm, so please refer to the works much like using libcurl in a C programm, so please refer to the
documentation of libcurl. Have a look at test.pl to get an idea of how documentation of libcurl. Have a look at test.pl to get an idea of how
to start. to start.

View File

@@ -77,7 +77,9 @@
#define DEFAULT_MAXREDIRS 50L #define DEFAULT_MAXREDIRS 50L
#ifndef __cplusplus /* (rabe) */ #ifndef __cplusplus /* (rabe) */
#ifndef typedef_bool
typedef char bool; typedef char bool;
#endif
#endif /* (rabe) */ #endif /* (rabe) */
#define CURL_PROGRESS_STATS 0 /* default progress display */ #define CURL_PROGRESS_STATS 0 /* default progress display */
@@ -318,6 +320,11 @@ static void help(void)
" --egd-file <file> EGD socket path for random data (SSL)\n" " --egd-file <file> EGD socket path for random data (SSL)\n"
" -e/--referer Referer page (H)"); " -e/--referer Referer page (H)");
puts(" -E/--cert <cert[:passwd]> Specifies your certificate file and password (HTTPS)\n" puts(" -E/--cert <cert[:passwd]> Specifies your certificate file and password (HTTPS)\n"
" --cert-type <type> Specifies your certificate file type (DER/PEM/ENG) (HTTPS)\n"
" --key <key> Specifies your private key file (HTTPS)\n"
" --key-type <type> Specifies your private key file type (DER/PEM/ENG) (HTTPS)\n"
" --pass <pass> Specifies your passphrase for the private key (HTTPS)");
puts(" --engine <eng> Specifies the crypto engine to use (HTTPS)\n"
" --cacert <file> CA certifciate to verify peer against (SSL)\n" " --cacert <file> CA certifciate to verify peer against (SSL)\n"
" --ciphers <list> What SSL ciphers to use (SSL)\n" " --ciphers <list> What SSL ciphers to use (SSL)\n"
" --connect-timeout <seconds> Maximum time allowed for connection\n" " --connect-timeout <seconds> Maximum time allowed for connection\n"
@@ -420,8 +427,12 @@ struct Configurable {
char *cipher_list; char *cipher_list;
char *cert; char *cert;
char *cert_type;
char *cacert; char *cacert;
char *cert_passwd; char *key;
char *key_type;
char *key_passwd;
char *engine;
bool crlf; bool crlf;
char *customrequest; char *customrequest;
char *krb4level; char *krb4level;
@@ -884,6 +895,11 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */
{"e", "referer", TRUE}, {"e", "referer", TRUE},
{"E", "cert", TRUE}, {"E", "cert", TRUE},
{"Ea", "cacert", TRUE}, {"Ea", "cacert", TRUE},
{"Eb","cert-type", TRUE},
{"Ec","key", TRUE},
{"Ed","key-type", TRUE},
{"Ee","pass", TRUE},
{"Ef","engine", TRUE},
{"f", "fail", FALSE}, {"f", "fail", FALSE},
{"F", "form", TRUE}, {"F", "form", TRUE},
{"g", "globoff", FALSE}, {"g", "globoff", FALSE},
@@ -1180,35 +1196,53 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */
} }
break; break;
case 'E': case 'E':
if(subletter == 'a') { switch(subletter) {
case 'a': /* CA info PEM file */
/* CA info PEM file */ /* CA info PEM file */
GetStr(&config->cacert, nextarg); GetStr(&config->cacert, nextarg);
} break;
else { case 'b': /* cert file type */
char *ptr = strchr(nextarg, ':'); GetStr(&config->cert_type, nextarg);
/* Since we live in a world of weirdness and confusion, the win32 break;
dudes can use : when using drive letters and thus case 'c': /* private key file */
c:\file:password needs to work. In order not to break GetStr(&config->key, nextarg);
compatibility, we still use : as separator, but we try to detect break;
when it is used for a file name! On windows. */ case 'd': /* private key file type */
GetStr(&config->key_type, nextarg);
break;
case 'e': /* private key passphrase */
GetStr(&config->key_passwd, nextarg);
break;
case 'f': /* crypto engine */
GetStr(&config->engine, nextarg);
break;
default: /* certificate file */
{
char *ptr = strchr(nextarg, ':');
/* Since we live in a world of weirdness and confusion, the win32
dudes can use : when using drive letters and thus
c:\file:password needs to work. In order not to break
compatibility, we still use : as separator, but we try to detect
when it is used for a file name! On windows. */
#ifdef WIN32 #ifdef WIN32
if(ptr && if(ptr &&
(ptr == &nextarg[1]) && (ptr == &nextarg[1]) &&
(nextarg[2] == '\\') && (nextarg[2] == '\\') &&
(isalpha((int)nextarg[0])) ) (isalpha((int)nextarg[0])) )
/* colon in the second column, followed by a backslash, and the /* colon in the second column, followed by a backslash, and the
first character is an alphabetic letter: first character is an alphabetic letter:
this is a drive letter colon */ this is a drive letter colon */
ptr = strchr(&nextarg[3], ':'); /* find the next one instead */ ptr = strchr(&nextarg[3], ':'); /* find the next one instead */
#endif #endif
if(ptr) { if(ptr) {
/* we have a password too */ /* we have a password too */
*ptr=0; *ptr=0;
ptr++; ptr++;
GetStr(&config->cert_passwd, ptr); GetStr(&config->key_passwd, ptr);
} }
GetStr(&config->cert, nextarg); GetStr(&config->cert, nextarg);
}
} }
break; break;
case 'f': case 'f':
@@ -1245,10 +1279,23 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */
config->conf ^= CONF_HEADER; /* include the HTTP header as well */ config->conf ^= CONF_HEADER; /* include the HTTP header as well */
break; break;
case 'I': case 'I':
config->conf ^= CONF_HEADER; /* include the HTTP header in the output */ /*
config->conf ^= CONF_NOBODY; /* don't fetch the body at all */ * This is a bit tricky. We either SET both bits, or we clear both
if(SetHTTPrequest(HTTPREQ_HEAD, &config->httpreq)) * bits. Let's not make any other outcomes from this.
return PARAM_BAD_USE; */
if((CONF_HEADER|CONF_NOBODY) !=
(config->conf&(CONF_HEADER|CONF_NOBODY)) ) {
/* one of them weren't set, set both */
config->conf |= (CONF_HEADER|CONF_NOBODY);
if(SetHTTPrequest(HTTPREQ_HEAD, &config->httpreq))
return PARAM_BAD_USE;
}
else {
/* both were set, clear both */
config->conf &= ~(CONF_HEADER|CONF_NOBODY);
if(SetHTTPrequest(HTTPREQ_GET, &config->httpreq))
return PARAM_BAD_USE;
}
break; break;
case 'K': case 'K':
res = parseconfig(nextarg, config); res = parseconfig(nextarg, config);
@@ -2091,17 +2138,29 @@ operate(struct Configurable *config, int argc, char *argv[])
to be able to do so, we have to create a new URL in another to be able to do so, we have to create a new URL in another
buffer.*/ buffer.*/
urlbuffer=(char *)malloc(strlen(url) + strlen(config->infile) + 3); /* We only want the part of the local path that is on the right
side of the rightmost slash and backslash. */
char *filep = strrchr(config->infile, '/');
char *file2 = strrchr(filep?filep:config->infile, '\\');
if(file2)
filep = file2+1;
else if(filep)
filep++;
else
filep = config->infile;
urlbuffer=(char *)malloc(strlen(url) + strlen(filep) + 3);
if(!urlbuffer) { if(!urlbuffer) {
helpf("out of memory\n"); helpf("out of memory\n");
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
} }
if(ptr) if(ptr)
/* there is a trailing slash on the URL */ /* there is a trailing slash on the URL */
sprintf(urlbuffer, "%s%s", url, config->infile); sprintf(urlbuffer, "%s%s", url, filep);
else else
/* thers is no trailing slash on the URL */ /* thers is no trailing slash on the URL */
sprintf(urlbuffer, "%s/%s", url, config->infile); sprintf(urlbuffer, "%s/%s", url, filep);
url = urlbuffer; /* use our new URL instead! */ url = urlbuffer; /* use our new URL instead! */
} }
@@ -2202,6 +2261,8 @@ operate(struct Configurable *config, int argc, char *argv[])
} }
#endif #endif
curl_easy_setopt(curl, CURLOPT_SSLENGINE, config->engine);
curl_easy_setopt(curl, CURLOPT_SSLENGINE_DEFAULT, 1);
curl_easy_setopt(curl, CURLOPT_FILE, (FILE *)&outs); /* where to store */ curl_easy_setopt(curl, CURLOPT_FILE, (FILE *)&outs); /* where to store */
/* what call to write: */ /* what call to write: */
@@ -2249,7 +2310,10 @@ operate(struct Configurable *config, int argc, char *argv[])
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, config->headers); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, config->headers);
curl_easy_setopt(curl, CURLOPT_HTTPPOST, config->httppost); curl_easy_setopt(curl, CURLOPT_HTTPPOST, config->httppost);
curl_easy_setopt(curl, CURLOPT_SSLCERT, config->cert); curl_easy_setopt(curl, CURLOPT_SSLCERT, config->cert);
curl_easy_setopt(curl, CURLOPT_SSLCERTPASSWD, config->cert_passwd); curl_easy_setopt(curl, CURLOPT_SSLCERTTYPE, config->cert_type);
curl_easy_setopt(curl, CURLOPT_SSLKEY, config->key);
curl_easy_setopt(curl, CURLOPT_SSLKEYTYPE, config->key_type);
curl_easy_setopt(curl, CURLOPT_SSLKEYPASSWD, config->key_passwd);
if(config->cacert) { if(config->cacert) {
curl_easy_setopt(curl, CURLOPT_CAINFO, config->cacert); curl_easy_setopt(curl, CURLOPT_CAINFO, config->cacert);

View File

@@ -1,5 +1,5 @@
#ifndef __SETUP_H #ifndef __CLIENT_SETUP_H
#define __SETUP_H #define __CLIENT_SETUP_H
/***************************************************************************** /*****************************************************************************
* _ _ ____ _ * _ _ ____ _
* Project ___| | | | _ \| | * Project ___| | | | _ \| |

View File

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

View File

@@ -14,8 +14,10 @@ specified, that will be checked/used if specified. This document includes all
the subsections currently supported. the subsections currently supported.
<reply> <reply>
<data> <data [nocheck=1]>
data to sent to the client on its request data to sent to the client on its request and later verified that it arrived
safely. Set the nocheck=1 to prevent the test script to verify the arrival
of this data.
</data> </data>
<datacheck> <datacheck>
if the data is sent but this is what should be checked afterwards if the data is sent but this is what should be checked afterwards
@@ -30,16 +32,20 @@ reply is sent
<postcmd> <postcmd>
special purpose server-command to control its behavior *after* the special purpose server-command to control its behavior *after* the
reply is sent reply is sent
</oistcmd> </postcmd>
</reply> </reply>
<client> <client>
<name> <name>
test case description test case description
</name> </name>
<command> <command [option=no-output]>
command line to run, there's a bunch of %variables that get replaced command line to run, there's a bunch of %variables that get replaced
accordingly. more about them elsewhere accordingly. more about them elsewhere
Set 'option=no-output' to prevent the test script to slap on the --output
argument that directs the output to a file. The --output is also not added if
the client/stdout section is used.
</command> </command>
<file name="log/filename"> <file name="log/filename">
this creates the named file with this content before the test case is run this creates the named file with this content before the test case is run
@@ -59,6 +65,9 @@ changing protocol data such as port numbers or user-agent strings.
<protocol> <protocol>
the protocol dump curl should transmit the protocol dump curl should transmit
</protocol> </protocol>
<stdout>
This verfies that this data was passed to stdout.
</stdout>
<file name="log/filename"> <file name="log/filename">
the file's contents must be identical to this the file's contents must be identical to this
</file> </file>

View File

@@ -13,5 +13,5 @@ test102 test111 test120 test16 test21 test30 test400 test7 \
test103 test112 test121 test17 test22 test300 test401 test8 \ test103 test112 test121 test17 test22 test300 test401 test8 \
test104 test113 test122 test18 test23 test301 test402 test9 \ test104 test113 test122 test18 test23 test301 test402 test9 \
test105 test114 test123 test19 test24 test302 test43 \ test105 test114 test123 test19 test24 test302 test43 \
test106 test115 test124 test190 test25 test303 test44 \ test106 test115 test124 test190 test25 test303 test44 test38 \
test107 test116 test125 test2 test26 test33 test45 test126 test107 test116 test125 test2 test26 test33 test45 test126

49
tests/data/test38 Normal file
View File

@@ -0,0 +1,49 @@
# Server-side
<reply>
<data nocheck=1>
HTTP/1.0 200 Mooo
Date: Mon, 13 Nov 2000 13:41:09 GMT
Server: myown/1.0
Connection: close
todelooooo lalalala yada yada, we know nothing about ranges ;-)
</data>
</reply>
# Client-side
<client>
<name>
HTTP resume request without server supporting it
</name>
<command option="no-output">
http://%HOSTIP:%HOSTPORT/want/38 -C - -i -o log/fewl.txt
</command>
<file name="log/fewl.txt">
This text is here to simulate a partly downloaded file to resume
download on.
</file>
</client>
# Verify data after the test has been "shot"
<verify>
<errorcode>
33
</errorcode>
<strip>
^User-Agent:.*
</strip>
<protocol>
GET /want/38 HTTP/1.1
Range: bytes=78-
Host: 127.0.0.1:8999
Pragma: no-cache
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*
</protocol>
# the download target file must remain untouched
<file name="log/fewl.txt">
This text is here to simulate a partly downloaded file to resume
download on.
</file>
</verify>

View File

@@ -3,6 +3,9 @@
my @xml; my @xml;
my $warning=0;
my $trace=0;
sub getpartattr { sub getpartattr {
my ($section, $part)=@_; my ($section, $part)=@_;
@@ -63,12 +66,21 @@ sub getpart {
$inside--; $inside--;
} }
elsif((1==$inside) && ($_ =~ /^ *\<\/$section/)) { elsif((1==$inside) && ($_ =~ /^ *\<\/$section/)) {
if($trace) {
print STDERR "*** getpart.pm: $section/$part returned data!\n";
}
if(!@this && $warning) {
print STDERR "*** getpart.pm: $section/$part returned empty!\n";
}
return @this; return @this;
} }
elsif(2==$inside) { elsif(2==$inside) {
push @this, $_; push @this, $_;
} }
} }
if($warning) {
print STDERR "*** getpart.pm: $section/$part returned empty!\n";
}
return @this; #empty! return @this; #empty!
} }

View File

@@ -68,6 +68,8 @@ my $debugprotocol;
my $anyway; my $anyway;
my $gdbthis; # run test case with gdb debugger my $gdbthis; # run test case with gdb debugger
my $keepoutfiles; # keep stdout and stderr files after tests my $keepoutfiles; # keep stdout and stderr files after tests
my $listonly; # only list the tests
my $pwd; # current working directory my $pwd; # current working directory
chomp($pwd = `pwd`); chomp($pwd = `pwd`);
@@ -427,14 +429,6 @@ sub singletest {
my $CURLOUT="$LOGDIR/curl$testnum.out"; # curl output if not stdout my $CURLOUT="$LOGDIR/curl$testnum.out"; # curl output if not stdout
# remove previous server output logfile
unlink($SERVERIN);
if(@ftpservercmd) {
# write the instructions to file
writearray($FTPDCMD, \@ftpservercmd);
}
# name of the test # name of the test
my @testname= getpart("client", "name"); my @testname= getpart("client", "name");
@@ -445,6 +439,18 @@ sub singletest {
print "[$name]\n"; print "[$name]\n";
} }
if($listonly) {
return 0; # look successful
}
# remove previous server output logfile
unlink($SERVERIN);
if(@ftpservercmd) {
# write the instructions to file
writearray($FTPDCMD, \@ftpservercmd);
}
# get the command line options to use # get the command line options to use
my ($cmd, @blaha)= getpart("client", "command"); my ($cmd, @blaha)= getpart("client", "command");
@@ -477,9 +483,17 @@ sub singletest {
writearray($filename, \@inputfile); writearray($filename, \@inputfile);
} }
my %cmdhash = getpartattr("client", "command");
my $out=""; my $out="";
if (!@validstdout) {
$out="--output $CURLOUT "; if($cmdhash{'option'} eq "no-output") {
#print "*** We don't slap on --output\n";
}
else {
if (!@validstdout) {
$out="--output $CURLOUT ";
}
} }
# run curl, add -v for debug information output # run curl, add -v for debug information output
@@ -775,6 +789,10 @@ do {
# continue anyway, even if a test fail # continue anyway, even if a test fail
$anyway=1; $anyway=1;
} }
elsif($ARGV[0] eq "-l") {
# lists the test case names only
$listonly=1;
}
elsif($ARGV[0] eq "-k") { elsif($ARGV[0] eq "-k") {
# keep stdout and stderr files after tests # keep stdout and stderr files after tests
$keepoutfiles=1; $keepoutfiles=1;
@@ -788,6 +806,7 @@ Usage: runtests.pl [options]
-g run the test case with gdb -g run the test case with gdb
-h this help text -h this help text
-k keep stdout and stderr files present after tests -k keep stdout and stderr files present after tests
-l list all test case names/descriptions
-s short output -s short output
-v verbose output -v verbose output
[num] like "5 6 9" or " 5 to 22 " to run those tests only [num] like "5 6 9" or " 5 to 22 " to run those tests only
@@ -821,7 +840,9 @@ if($testthis[0] ne "") {
# Output curl version and host info being tested # Output curl version and host info being tested
# #
displaydata(); if(!$listonly) {
displaydata();
}
####################################################################### #######################################################################
# clear and create logging directory: # clear and create logging directory:
@@ -912,7 +933,8 @@ for(keys %run) {
} }
if($total) { if($total) {
print "$ok tests out of $total reported OK\n"; printf("$ok tests out of $total reported OK: %d%%\n",
$ok/$total*100);
if($ok != $total) { if($ok != $total) {
print "These test cases failed: $failed\n"; print "These test cases failed: $failed\n";