Compare commits

..

317 Commits

Author SHA1 Message Date
Daniel Stenberg
329bcf3a71 7.9.1 cleanup commit 2001-11-04 11:35:12 +00:00
Daniel Stenberg
0cb12d7e78 added test 30, it checks that we return error on no content returned from a
HTTP server
2001-11-04 11:21:32 +00:00
Daniel Stenberg
3bfa06c9a2 improved functionality for new timeout tests 2001-11-02 23:09:25 +00:00
Daniel Stenberg
f34573c8e2 new tests 2001-11-02 23:09:02 +00:00
Daniel Stenberg
4163b86cd2 failf() now only overwrites the error buffer the first time it gets called
for each *_perform(). It makes things a lot easier, as the first one that
detects the error get to write the final error reason...
2001-11-02 22:30:34 +00:00
Daniel Stenberg
5b948512f9 Replaced read() and write() with recv() and send() 2001-11-02 14:23:11 +00:00
Daniel Stenberg
2297a7a70c more accurate 2001-11-02 13:16:29 +00:00
Daniel Stenberg
dc82f9e6df Replaced read() and write() with recv() and send() for socket operations
even under normal unixes.
2001-11-02 13:04:23 +00:00
Daniel Stenberg
e60e7414b9 re-ordered, cleaned up 2001-11-02 12:51:18 +00:00
Daniel Stenberg
c6caa9fd60 Added connect.c. I really need someone to better maintain this makefile... 2001-11-02 08:32:38 +00:00
Daniel Stenberg
c84ad40ccd Jrn added connect.c 2001-11-02 08:32:13 +00:00
Daniel Stenberg
ab7f25ab41 another day another commit 2001-11-01 15:26:43 +00:00
Daniel Stenberg
6d213e207d libcurl can init winsock since 7.8.1 2001-11-01 14:51:02 +00:00
Daniel Stenberg
9b6545c479 ConnectionExists() now returns FALSE immediately if it finds a connection
that is dead, because it can only find one entry anyway and if that is dead
there won't be any other entry that matches
2001-11-01 13:54:32 +00:00
Daniel Stenberg
96fb118251 added comments and function headers 2001-11-01 12:47:22 +00:00
Daniel Stenberg
617d6eb7ce Update the byte counters in the loop so that aborted transfers have the
information as well. Improves debug outputs etc.
2001-11-01 12:18:53 +00:00
Daniel Stenberg
99888388dc Use Curl_tvdiff to compare times 2001-11-01 12:17:51 +00:00
Daniel Stenberg
7d24ce9651 less I, more we 2001-11-01 09:12:35 +00:00
Daniel Stenberg
cbc35b1fb8 minor mods to make solaris plain 'make' to not die on this 2001-11-01 07:27:09 +00:00
Daniel Stenberg
027fc719cc fixed FTPSENDF for ipv6 compiles 2001-10-31 20:59:24 +00:00
Daniel Stenberg
f6b2e9e8a4 a bunch 2001-10-31 20:54:21 +00:00
Daniel Stenberg
c4f1a9f690 Removed the SocketIsDead() stuff for SSL again as it doesn't work. We must
rely on the new go-ahead-and-try mechanism that I just added to Transfer()
2001-10-31 15:14:52 +00:00
Daniel Stenberg
542055074b If Curl_do() fails with CURLE_WRITE_ERROR on a re-used connection, this
new logic can retry the same operation on a new connection!
2001-10-31 15:13:19 +00:00
Daniel Stenberg
7b93348aae Curl_sendf now returns a CURLcode 2001-10-31 15:08:16 +00:00
Daniel Stenberg
eaf475b538 return type cleanup 2001-10-31 15:07:45 +00:00
Daniel Stenberg
4118c68df1 check Curl_ftpsendf return codes 2001-10-31 15:06:38 +00:00
Daniel Stenberg
69d5d88259 Added better checking of return codes when we send data to sockets/connections 2001-10-31 14:57:00 +00:00
Daniel Stenberg
7e6a36ea7b major commit, now we check the return code on every invoke of Curl_ftpsendf
- which now is made using a macro named FTPSENDF. I turned it all caps just
to make it more visible that it is in fact a macro.
2001-10-31 14:56:12 +00:00
Daniel Stenberg
6878c0b88f check return code when issuing the request 2001-10-31 14:48:10 +00:00
Daniel Stenberg
bbdc9f15e7 added typecasts to make the timers calculate with doubles, not longs as they
accidentally did after the Curl_tvdiff() interface change
2001-10-31 14:45:47 +00:00
Daniel Stenberg
ae4f8243a9 added some -c talk, spell checked 2001-10-31 13:42:38 +00:00
Daniel Stenberg
1c83dee948 no need for mumbojumbo 2001-10-31 12:48:18 +00:00
Daniel Stenberg
b66dedc017 added cool.haxx.se as an official mirror site 2001-10-31 10:19:16 +00:00
Daniel Stenberg
b07e2a08f9 nonblock => Curl_nonblock, remade the check for a live SSL connection (again) 2001-10-31 08:44:11 +00:00
Daniel Stenberg
64543e09ec Added -0/--http1.0 2001-10-30 15:39:11 +00:00
Daniel Stenberg
58936efff6 removed the 'in documentation' part, as I've expressed in public before 2001-10-30 15:32:48 +00:00
Daniel Stenberg
dbd32278f8 Added an additional SSL check for a dead socket before we re-use an SSL
connection. The simple socket-check is not enough in these cases.
2001-10-30 15:21:45 +00:00
Daniel Stenberg
6d35984286 prevent strdup()ing NULL -- Paul Harrington's report 2001-10-30 12:08:17 +00:00
Daniel Stenberg
c046dc904c Corrected the -T description 2001-10-30 08:09:57 +00:00
Daniel Stenberg
bc8375a1e8 removed silly old -t usage from here, added some blurb about the "new" -t
that sets telnet options
2001-10-30 08:09:08 +00:00
Daniel Stenberg
83877d5ec6 Kevin Roth updates 2001-10-29 22:17:19 +00:00
Daniel Stenberg
3f248dd163 corrected return code, general cleanup 2001-10-29 13:41:16 +00:00
Daniel Stenberg
c9954d1941 added curl_formadd 2001-10-29 13:28:44 +00:00
Daniel Stenberg
e165332211 minor fix to support multiple files in one formadd() call 2001-10-29 13:21:25 +00:00
Daniel Stenberg
d25310cb6f 29 October fixes 2001-10-29 10:46:20 +00:00
Daniel Stenberg
fbb9d23a25 Kevin Roth's cygwin package fixes 2001-10-29 10:32:39 +00:00
Daniel Stenberg
2d32e8831b Cygwin moved into the win32 drawer 2001-10-29 10:31:52 +00:00
Daniel Stenberg
42a9d96fae fixed conn->name error on connection re-use and enlarged the 'gname' array
to hold 512 bytes (for user+password+hostname)
2001-10-29 10:10:21 +00:00
Daniel Stenberg
3edd9b4dfc SM's waitconnect return code fix! 2001-10-29 07:49:57 +00:00
Daniel Stenberg
1a8cf79ae0 changed the Location: to match one Paul Harrington reports a problem with 2001-10-26 12:36:25 +00:00
Daniel Stenberg
b736bdc8e5 ldap fix, test28 added 2001-10-26 11:34:02 +00:00
Daniel Stenberg
babb985f1a made 'timespent' a double, which makes more accurate calculations for quick
downloads
2001-10-26 11:25:03 +00:00
Daniel Stenberg
b22a5f756c test28 added for "Location: extraspace" test 2001-10-26 11:01:33 +00:00
Daniel Stenberg
d733061873 bug report #474568 -
We need to set "no further data to download" before the Curl_ldap() function
returns, as otherwise it'll hang on that assumed transfer.
2001-10-25 08:28:29 +00:00
Daniel Stenberg
bca0c8d253 added "s390 Linux" as a platform that curl was compiled for, and I also sorted
the list of machines
2001-10-24 14:16:57 +00:00
Daniel Stenberg
53ac8004e7 added a section about cross compiling that Jim Duey wrote down for us 2001-10-24 11:54:42 +00:00
Daniel Stenberg
7b76499e82 lots and lots 2001-10-24 11:44:18 +00:00
Daniel Stenberg
9f45190fa1 test case 27 added, to make sure cookie replacing don't leak anything 2001-10-24 11:39:48 +00:00
Daniel Stenberg
f933cb3b75 now reports the CORRECT pid on demand 2001-10-24 11:39:15 +00:00
Daniel Stenberg
c6822f5a7f T. Bharath found this memory leak. It occurs when we replace an internally
already existing cookie with a new one.
2001-10-24 11:36:55 +00:00
Daniel Stenberg
4e276b1b68 pack_hostent() now aligns the data properly on 64bit boundaries to work on
more CPU architectures
2001-10-23 12:11:43 +00:00
Daniel Stenberg
50e9f8ffd3 grammar grammar! 2001-10-23 10:12:28 +00:00
Daniel Stenberg
7d3daa598f added "3.12 Why do FTP specific features over HTTP proxy fails?" 2001-10-23 10:12:00 +00:00
Daniel Stenberg
7349940bdb added AC_PREREQ(2.50) to prevent autoconf mistakes 2001-10-23 07:54:16 +00:00
Daniel Stenberg
78000dbd5d An SGI (IRIX) compiler doesn't like indended #-instructions, so they're all
in column zero now!
2001-10-22 22:15:50 +00:00
Daniel Stenberg
b585f411cd make sure the connect can't return OK but return a NULL as addr 2001-10-22 12:52:25 +00:00
Daniel Stenberg
5ccd6bb842 2000 => 2001 2001-10-22 06:39:47 +00:00
Daniel Stenberg
5193894603 rephrased the WRITEFUNCTION description a bit 2001-10-22 06:35:19 +00:00
Daniel Stenberg
29b76a52fb failed transfers will now close the connection 2001-10-22 06:34:14 +00:00
Daniel Stenberg
0436bc22f2 added cygwin package makefile 2001-10-22 06:32:54 +00:00
Daniel Stenberg
cd16efa2f2 Cygwin files 2001-10-22 06:27:12 +00:00
Daniel Stenberg
56562bad59 Kevin Roth's cygwin fixes 2001-10-22 06:26:30 +00:00
Daniel Stenberg
a26081b555 A Kevin Roth patch. -- It's a post 1.4.2 patch that will become part of
libtool 1.4.3, and it's required to allow "make install" to function properly
on cygwin.
2001-10-22 06:08:09 +00:00
Daniel Stenberg
aa9c01ad3e new return code: CURLE_GOT_NOTHING 2001-10-19 11:59:04 +00:00
Daniel Stenberg
4e37187e44 now counts header size return from server and if nothing is returned from a
HTTP server we return error
2001-10-19 11:58:32 +00:00
Daniel Stenberg
74d5a6fb3b curl_easy_duphandle() now properly clones the cookie option
- patch by T. Bharath
2001-10-19 11:57:50 +00:00
Daniel Stenberg
83da58ce91 added test 37 2001-10-19 11:56:23 +00:00
Daniel Stenberg
45cc78fdbc CURLOPT_FAILONERROR now only returns error if the HTTP code is 400 or above
unconditionalliy. Previously, the code check was for >= 300 unless follow-
location was enabled...
2001-10-19 06:27:24 +00:00
Daniel Stenberg
010044e03c the malloc debug system only logs data if the logfile FILE * is set, which
makes it easier to disable debug output when built with debug functions
2001-10-17 12:33:35 +00:00
Daniel Stenberg
db0e3cc60c call Curl_done() in Curl_perform() after Transfer() was called, even it it
returned an error as there might be stuff in there we must free/cleanup.
This fixes the memory leak Yanick Pelletier posted about 16 Oct 2001
2001-10-17 12:24:51 +00:00
Daniel Stenberg
8dd6a4e369 don't use 'strict' anymore, as it doesn't work good with the cygwin fixes
also, always kill/restart the HTTP server on startup if it is our test server
2001-10-17 11:51:02 +00:00
Daniel Stenberg
92abbcef4c Kevin Roth's cygwin adjustment 2001-10-16 07:59:43 +00:00
Daniel Stenberg
1e8f0c5771 added AC_LIBTOOL_WIN32_DLL for cygwin setup issues 2001-10-16 07:58:41 +00:00
Daniel Stenberg
532bca41e5 Curl_tvdiff() now returns a millisecond diff, no double like before 2001-10-12 12:32:20 +00:00
Daniel Stenberg
b438c46764 progress meter fixes 2001-10-12 12:31:43 +00:00
Daniel Stenberg
ef48c73783 extensively commented source code, parts refreshened, the "current speed" is
now more accurate since it is based on actual spent time without the
assumptions from before
2001-10-12 12:31:06 +00:00
Daniel Stenberg
2c5e416591 better check for absolute URL redirects, adjusted to new Curl_tvdiff() proto 2001-10-12 12:30:06 +00:00
Sterling Hughes
8e91d5de8e looks nicer and is better compatible with older vim versions 2001-10-11 09:32:19 +00:00
Daniel Stenberg
2f85f3b147 cleanup on language, content and facts 2001-10-11 09:07:46 +00:00
Daniel Stenberg
20a47acb3a getservbyname is not used by libcurl, don't check for it 2001-10-11 07:41:52 +00:00
Daniel Stenberg
6bc85a94f9 removed WRITEINFO from here, it's not been supported since 7.4... 2001-10-11 06:24:27 +00:00
Daniel Stenberg
71bf8a6985 checkserver() bugged, Kevin Roth detected and fixed 2001-10-10 22:04:42 +00:00
Daniel Stenberg
59a76e4010 Kevin Roth's fixes to make tests work on cygwin 2001-10-10 21:59:10 +00:00
Daniel Stenberg
65b9c0d44d CURLOPT_WRITEFUNCTION description corrected 2001-10-10 13:11:24 +00:00
Daniel Stenberg
f2a25966cf cookiejar now enables the cookie engine 2001-10-10 12:48:32 +00:00
Daniel Stenberg
51afc3d8c5 hm 2001-10-09 12:04:33 +00:00
Daniel Stenberg
0c2f60036a added chunked encoding tests 2001-10-09 12:03:52 +00:00
Daniel Stenberg
3dcdcfc572 added test 47 - enforced http 1.0 request 2001-10-09 11:34:49 +00:00
Daniel Stenberg
9f8c51cbd8 resolve problem fixed, memory leak with ipv6 gone, configure improved,
MSVC++ project files fixed, connecthost() compiler errors, ignore SIGPIPE,
support CURLOPT_HTTP_VERSION etc...
2001-10-09 06:57:17 +00:00
Daniel Stenberg
de79348a90 New: CURLOPT_HTTP_VERSION
Renamed: the TimeCond type to curl_TimeCond
2001-10-09 06:53:53 +00:00
Daniel Stenberg
56bc31e9f9 Added -0/--http1.0 to enforce HTTP 1.0 requests 2001-10-09 06:53:11 +00:00
Daniel Stenberg
a9181f8f00 added the option CURLOPT_HTTP_VERSION that can specify which HTTP version
libcurl should use in its request
2001-10-09 06:52:37 +00:00
Daniel Stenberg
3685f792cb ignore SIGPIPE, as that can be actually get sent when we write to a socket 2001-10-09 06:23:26 +00:00
Daniel Stenberg
e227a276ce updated the cookiejar comment 2001-10-08 11:07:06 +00:00
Daniel Stenberg
7b5b60d275 hm, an unknown error from bind() when binding the outgoing socket would
failf("%d") without the error as argument... it would always make a weird
number get output
2001-10-08 06:56:00 +00:00
Daniel Stenberg
e719f4169c corrected cookie-jar comment 2001-10-08 06:43:22 +00:00
Daniel Stenberg
d8fb2b2e63 using a HTTP proxy will disable some protocol-specific features that non-
HTTP procotols may allow
2001-10-05 07:30:07 +00:00
Daniel Stenberg
fdeaae678d SM's patch applied, we should not use arguments or variables that have the
same name as common functions...
2001-10-05 06:05:56 +00:00
sm
f30102f038 VC ID project workspace - fixes compile under win32 2001-10-05 02:30:27 +00:00
sm
a27ac6f394 VC ID project now uses ws2_32.lib - fixes compile under win32 2001-10-05 02:29:47 +00:00
sm
093c0a098e Makefile.vc6 changed to include connect.c 2001-10-05 02:27:26 +00:00
Daniel Stenberg
c3363f833c Albert Chin's improved gethostbyname_r() tests 2001-10-04 14:05:12 +00:00
Daniel Stenberg
47def8091c made sure the correct pieces of code are compiled on IPv4-only hosts, and
the pack_hostent() is only compiled if gethostbyname_r() isn't present.
2001-10-04 13:36:11 +00:00
Daniel Stenberg
cfb32ec0cd supports the new ADDR prefix for getaddrinfo() and freeaddrinfo() tracing 2001-10-04 13:25:40 +00:00
Daniel Stenberg
5d9ae88f58 getaddrinfo() cleanups 2001-10-04 13:25:12 +00:00
Daniel Stenberg
9d066935e5 Keith McGuigan's excellent fix that makes a cloned copy of the hostent struct
for when gethostbyname() is used so that we have the memory of the struct
allocated. This turns out to be needed if the curl handled is passed between
threads on Windows and possibly other operating systems where we use that
function.
2001-10-03 21:42:04 +00:00
Daniel Stenberg
bc40063e07 Nico Baggus' updated for 7.9 2001-10-03 21:28:01 +00:00
Daniel Stenberg
3c92d45386 Bjrn Stenberg reported successfully having built curl on StrongARM Linux 2001-10-03 15:08:36 +00:00
Daniel Stenberg
fcf4fccfa4 non-blocking connects *done* 2001-10-03 11:58:12 +00:00
Daniel Stenberg
eafd2c6bd5 me fix curl_formadd() again 2001-10-03 11:55:09 +00:00
Daniel Stenberg
64f00454e5 hm, I edited away the fine functionality and with this edit test case 9
is once again running OK
2001-10-03 09:31:16 +00:00
Daniel Stenberg
d678727430 7.9.1 pre-release 1 status 2001-10-03 08:16:26 +00:00
Daniel Stenberg
efc15fb128 The ARRAY stuff is now added 2001-10-03 08:02:17 +00:00
Daniel Stenberg
3d4cd8c9aa added new curl_formadd() stuff 2001-10-03 08:01:38 +00:00
Daniel Stenberg
420259993e Georg Huettenegger's fix that makes us no longer use curl_formparse() but
instead entirely rely on the curl_formadd() function. The former one is
subject for removal in a future release.
2001-10-03 08:00:12 +00:00
Daniel Stenberg
66087bdac6 Georg Huettenegger's curl_formadd fixes 2001-10-03 07:54:42 +00:00
Daniel Stenberg
ac70a43452 the changes done since the 7.9 release 2001-10-02 17:22:23 +00:00
Daniel Stenberg
72dbe9da72 praise Bjorn Reese for mastering these dusty corners of socket hacking, now
we check for the error state before believing we are connected in IPv6
cases
2001-10-02 17:18:46 +00:00
Daniel Stenberg
dd02881788 added port number in informational connect message 2001-10-02 12:51:15 +00:00
Daniel Stenberg
ced8955325 IPv6 adjustments, connect()ing to bad ports still don't work properly for
IPv6
2001-10-02 11:26:53 +00:00
Daniel Stenberg
51ca5fcbe0 major connecting updates 2001-10-02 09:40:06 +00:00
Daniel Stenberg
56ff2aa059 pick the correct timeout before the connecthost call 2001-10-01 23:25:59 +00:00
Daniel Stenberg
9f77771ff9 faster bailout on timeouts 2001-10-01 23:25:26 +00:00
Daniel Stenberg
f0fa858885 added comment to the tvdiff 2001-10-01 22:50:20 +00:00
Daniel Stenberg
3298630500 removed warning 2001-10-01 22:50:03 +00:00
Daniel Stenberg
dc27488c47 corrected for IPv6 2001-10-01 22:42:46 +00:00
Daniel Stenberg
375e615a6d added five non-blocking #defines 2001-10-01 22:34:08 +00:00
Daniel Stenberg
6918427fae conn->hp is now conn->hostaddr
changed the Curl_connethost() proto again
2001-10-01 22:32:37 +00:00
Daniel Stenberg
9d342bbf07 sessionhandle->hp => hostaddr 2001-10-01 22:31:43 +00:00
Daniel Stenberg
afc81ada0c renamed the stupid 'hp' to 'hostaddr' which actually says what it is 2001-10-01 22:31:10 +00:00
Daniel Stenberg
5cd267b2be removed obsoletetd myalarm() calls 2001-10-01 11:35:29 +00:00
Daniel Stenberg
09da90076f moved the myalarm() usage, and now makes sure to switch it off after the
name resolving, as that should be the *ONLY* section in libcurl that may
take a while in a synchronous call.
2001-10-01 11:27:39 +00:00
Daniel Stenberg
d0079d9054 fixed the connecthost proto: added the timeout argument 2001-10-01 11:26:21 +00:00
Daniel Stenberg
ede5b54edc corrected the #include files 2001-10-01 11:25:27 +00:00
Daniel Stenberg
c5fdeef41d introduced non-blocking connects 2001-10-01 08:59:17 +00:00
Daniel Stenberg
6ca45beaed Added non-blocking sockets test 2001-10-01 08:58:03 +00:00
Daniel Stenberg
2a07626aa8 moved to the java module 2001-10-01 07:46:45 +00:00
Daniel Stenberg
9127554852 moved to the perl module 2001-10-01 07:44:12 +00:00
Daniel Stenberg
9ff28a8237 moved to separate module 2001-10-01 07:40:32 +00:00
Daniel Stenberg
e9aa07f660 filetime should be -1 if the remote time was unknown as 0 is actually a
valid time. we now store the filetime as a long to know for sure it can
hold -1 (there exist some unsigned time_t cases)
2001-09-28 11:04:43 +00:00
Daniel Stenberg
88e21894c7 improved readability slightly 2001-09-28 09:25:59 +00:00
Daniel Stenberg
09da2c1767 fixed the missing getftpresponse edits 2001-09-28 09:19:35 +00:00
Daniel Stenberg
ae2ecfc5cb removed the socket argument from some functions that always passed in the
same socket and it was available from the passed-in struct anyway!
2001-09-28 09:15:19 +00:00
Daniel Stenberg
cc610f0d1f now compiles warning-free when IPv6-enabled 2001-09-28 09:02:57 +00:00
Daniel Stenberg
8333644c84 moved the PORT and PASV code into separate smaller functions for readability
renamed all static ^_ftp_* functions to ^ftp_, prefixing with underscore is
not nice
2001-09-28 08:58:18 +00:00
Daniel Stenberg
4d13b2cc64 more ipv6 cleanups to make smaller functions that are easier to read 2001-09-28 07:46:39 +00:00
Daniel Stenberg
48dc74aecc more transparant support for IPv6 name resolving 2001-09-28 07:05:26 +00:00
Daniel Stenberg
888d39e083 generate bzip2 and zip files too 2001-09-27 12:44:17 +00:00
Daniel Stenberg
7239ecd456 free cookiejar string 2001-09-26 07:12:07 +00:00
Daniel Stenberg
598e8dfbfb Now we're setting a default domain for received cookies so that we can
properly match those cookies in subsequent requests
2001-09-26 07:08:29 +00:00
Daniel Stenberg
9efdb68035 Added test 46, cookie jar functionality 2001-09-26 07:06:00 +00:00
Daniel Stenberg
14b898cb05 we can verify files too 2001-09-26 07:05:00 +00:00
Daniel Stenberg
8d16b2b119 winsock 2 fixes 2001-09-25 07:55:19 +00:00
Daniel Stenberg
4d2cb8b32a 7.9 commit 2001-09-25 06:39:18 +00:00
Daniel Stenberg
d5001a3f0b Added httpput.c 2001-09-25 05:55:56 +00:00
Daniel Stenberg
91f5ac4d5c two ipv6 fixes 2001-09-24 07:48:31 +00:00
Daniel Stenberg
f9977df50d moved to parent directory 2001-09-24 07:48:00 +00:00
Daniel Stenberg
711650b178 test 119 proved a memory leak in the FTP parts when IPv6 is enabled and the
RETR fails, this corrects it.
2001-09-23 12:47:07 +00:00
Daniel Stenberg
c9adbc9f1c Adjusted to run on ipv6-enabled hosts 2001-09-23 12:46:04 +00:00
Cris Bailiff
611fbfa917 Commit Curl_easy v1.1.8 - constants updated for libcurl 7.9 - tests modularised 2001-09-20 09:48:52 +00:00
Daniel Stenberg
ecfacfb334 redirect and ssl connect fixes 2001-09-19 21:57:26 +00:00
Daniel Stenberg
645413f5ef Lots of praise and glory to Vojtech Minarik for setting up a test server
and providing me with test-certificates that helped me nail the problem with
curl not discovering with a bad certificate was used.
2001-09-19 21:49:11 +00:00
Daniel Stenberg
5becdc38b3 http put with --crlf requires chunked content encoding 2001-09-19 14:49:23 +00:00
Daniel Stenberg
f36cea67fe This verifies that bug report #462600 is fixed, a Location: following when
the given URL has no protocol:// part and the Location: redirect contains a
:// section
2001-09-18 18:41:46 +00:00
Daniel Stenberg
b556d6caee fixed bug report #462600, following a Location: when the initial URL didn't
have a protocol:// part did wrong
2001-09-18 18:33:25 +00:00
Daniel Stenberg
a17a78c477 removed Curl_http_close() 2001-09-18 15:30:59 +00:00
Daniel Stenberg
146413a53c the stuff formerly done in Curl_http_close is now done in Curl_close 2001-09-18 15:30:38 +00:00
Daniel Stenberg
437fd064c9 modified GetLine(), removed Curl_http_close() 2001-09-18 15:29:57 +00:00
Daniel Stenberg
28dd4e4f1f made it respond as a http proxy on CONNECT 2001-09-18 15:26:54 +00:00
Daniel Stenberg
f92dc70beb added two https test cases 2001-09-18 15:26:32 +00:00
Daniel Stenberg
6d8f1328bf HTTPS test case 2001-09-18 15:13:40 +00:00
Daniel Stenberg
8d1d93d56d Linus Nielsen Feltzing fixed telnet for win32. 2001-09-17 22:51:48 +00:00
Daniel Stenberg
f8e102c485 curl_easy_duphandle is new 2001-09-17 22:24:35 +00:00
Daniel Stenberg
d816fcc965 Linus Nielsen Feltzing changed winsock lib for linking 2001-09-17 14:38:41 +00:00
Daniel Stenberg
e30dcd0501 Linus Nielsen Feltzing's telnet-for-win32 fixes 2001-09-17 14:10:38 +00:00
Daniel Stenberg
24dc7cffbd libtool 1.4.2 generated 2001-09-17 14:08:47 +00:00
Daniel Stenberg
3bc83926ce just a simple example that seems to work! 2001-09-17 12:20:44 +00:00
Daniel Stenberg
c5cca4d059 fixed the stunnel PEM path 2001-09-17 08:55:32 +00:00
Daniel Stenberg
0db04c4f56 added stunnel PEM 2001-09-17 08:41:45 +00:00
Daniel Stenberg
5c566c9aa3 added the stunnel PEM file 2001-09-17 08:41:28 +00:00
Daniel Stenberg
822f02313d changed the PEM path 2001-09-17 08:41:01 +00:00
Daniel Stenberg
d934890c1e libtool 1.4.2 2001-09-17 06:12:53 +00:00
Daniel Stenberg
0e25cf41c4 modified error message when PWD fails 2001-09-14 12:18:46 +00:00
Daniel Stenberg
5214dbbd02 duphandle(), cipher list, *18* new ftp tests 2001-09-14 12:12:50 +00:00
Daniel Stenberg
0c716d51ad added README and FILEFORMAT to distrbution archive 2001-09-14 12:07:11 +00:00
Daniel Stenberg
86367d675a new FTP tests 2001-09-14 12:03:33 +00:00
Daniel Stenberg
bd8cef5a70 the strip stuff 2001-09-14 12:02:02 +00:00
Daniel Stenberg
708431e2ea fixed the REST again 2001-09-14 12:01:21 +00:00
Daniel Stenberg
db5c1c61e5 added curl_easy_duphandle 2001-09-13 14:50:04 +00:00
Daniel Stenberg
aa4ff6d8b9 Added curl_easy_duphandle 2001-09-13 14:49:35 +00:00
Daniel Stenberg
6d5b8b50e1 minor informatinal output changes 2001-09-13 12:52:58 +00:00
Daniel Stenberg
600d7b11e6 moved lots of the verbose stuff to do logmsg instead 2001-09-13 12:52:24 +00:00
Daniel Stenberg
afa7648be6 initial test suite file format description 2001-09-13 12:51:32 +00:00
Daniel Stenberg
5c344fc23a ftp tests added 2001-09-13 12:51:07 +00:00
Cris Bailiff
5a905e0bb8 Release 1.1.7 - documentation update with licence info only. 2001-09-13 11:27:59 +00:00
Cris Bailiff
c31216949d Update documentation to explicitly state Curl::easy licence is dual MIT/X - MPL. 2001-09-13 05:00:13 +00:00
Daniel Stenberg
2cb893575d moved a 100K buffer from the transfer loop to the urlstate struct, as it
seriously decreases the amount of used stack space
2001-09-12 12:02:12 +00:00
Daniel Stenberg
63f1f58077 removed perl and php makefiles 2001-09-12 11:31:58 +00:00
Daniel Stenberg
36e9507e29 reverted. twas no memory leak and the "fix" didn't even compile on windows... 2001-09-12 08:59:00 +00:00
Daniel Stenberg
1fde1431c9 narrowed some source lines to fit in 80 cols 2001-09-12 08:14:35 +00:00
Daniel Stenberg
bec97a0999 ConnectionKillOne() _can_ return -1 as an indication of error
This is T. Bharath's fix
2001-09-12 08:00:30 +00:00
Daniel Stenberg
07de3c9df0 T. Bharath's patch that sets up a few necessary buffers in the duphandle()
function
2001-09-12 07:57:33 +00:00
Daniel Stenberg
8950a2dfa1 *TERRIBLE* terrible memory leak occuring on all systems that have no
gethostbyname_r() function, most notably windows machines...
2001-09-12 07:19:11 +00:00
Daniel Stenberg
be47d83555 added CURLOPT_SSL_CIPHER_LIST 2001-09-11 22:36:43 +00:00
Daniel Stenberg
d5054ad52d --ciphers now sets CURLOPT_SSL_CIPHER_LIST 2001-09-11 22:36:03 +00:00
Daniel Stenberg
051fad8d88 now can set list of ciphers 2001-09-11 22:35:23 +00:00
Daniel Stenberg
c4532b9a07 added --ciphers 2001-09-11 22:34:54 +00:00
Daniel Stenberg
0e7824d1a9 documented CURLOPT_SSL_CIPHER_LIST 2001-09-11 22:29:30 +00:00
Daniel Stenberg
a2c78607a6 CURLOPT_SSL_CIPHER_LIST support 2001-09-11 22:23:16 +00:00
Daniel Stenberg
cc1a4edf3d added cipher_list 2001-09-11 22:21:26 +00:00
Daniel Stenberg
db7bde1d7a added ability to set prefered list of ciphers 2001-09-11 22:21:02 +00:00
Daniel Stenberg
719008596a changes since pre3 2001-09-11 12:00:36 +00:00
Daniel Stenberg
377e78d917 removed the 'perl' and 'php' dirs from the release archive 2001-09-11 10:15:40 +00:00
Daniel Stenberg
894b47da9b ouputs the start and expire dates of the server certificate on verbose
output
2001-09-11 10:00:49 +00:00
Daniel Stenberg
54e7246342 cleaned up, now closes the listener port in PASV and it doesn't re-use the
same passive port number
2001-09-11 07:45:12 +00:00
Daniel Stenberg
9b3b050640 some unixes have the netrc description in the ftp(1) man page 2001-09-11 06:39:54 +00:00
Daniel Stenberg
a0e389caa2 generated .h file cut off 2001-09-10 12:17:23 +00:00
Daniel Stenberg
b747408f9e updated to allow separate packaging 2001-09-10 12:15:17 +00:00
Daniel Stenberg
d3e55d8155 Added project curl source header 2001-09-10 12:14:40 +00:00
Cris Bailiff
96c7253cea Fix perl segfault due to changes in header callback behaviour since curl-7.8.1-pre3 2001-09-10 09:17:02 +00:00
Daniel Stenberg
3f5227dfc7 Curl_cookie_output() must check that there's a cookie struct present before
trying to address it!
2001-09-10 07:43:08 +00:00
Daniel Stenberg
b91103099a updated tool versions 2001-09-10 06:05:38 +00:00
Daniel Stenberg
82d3ded922 checks for sys/utime.h 2001-09-07 09:53:40 +00:00
Daniel Stenberg
5a8d1c4cd1 HAVE_SYS_UTIME_H adjustments 2001-09-07 09:53:21 +00:00
Daniel Stenberg
46372c04ee made it compile properly when not building with SSL support 2001-09-07 09:40:46 +00:00
Sterling Hughes
6147879837 Added formatting sections for emacs and vim 2001-09-07 04:01:32 +00:00
Sterling Hughes
e2e3c95d3b fix for emacs 2001-09-07 03:30:30 +00:00
Daniel Stenberg
c3b448dcea moved the session ID cache state variables into the UrlState struct within
the SessionHandle. It was previously wrongly put in UserDefined
2001-09-06 08:32:01 +00:00
Daniel Stenberg
86da31e031 Curl_SSL_Close_All() now checks that we have a session cache before we run
around killing entries in it!
2001-09-06 06:26:24 +00:00
Daniel Stenberg
1d7075e339 added -R description 2001-09-05 13:26:54 +00:00
Daniel Stenberg
610ec27d93 first shaky and stumbling attempts at a *_duphandle() function 2001-09-05 07:24:01 +00:00
Daniel Stenberg
70f2717c11 added curl-mode.el 2001-09-05 06:56:24 +00:00
Daniel Stenberg
b31a54c46a emacs lisp setup for hacking curl code 2001-09-05 06:55:08 +00:00
Sterling Hughes
08238f4320 Fix formatting when tabs and spaces got mixed up (if tabstop was not set to
8 this looked quite funny :)

Added a small formatting section for vim at the bottom, it also contains an
emacs portion (copied it from another project I'm working on), I don't know
if this is correct, but its a step (the vim part is correct :)
2001-09-05 02:49:04 +00:00
Daniel Stenberg
06993556f3 defined HAVE_UTIME and HAVE_UTIME_H 2001-09-03 14:31:48 +00:00
Daniel Stenberg
144459d364 corrected the comment to be valid chunk format 2001-09-03 12:51:23 +00:00
Daniel Stenberg
0fa61eff77 -R removes a TODO 2001-09-03 12:32:44 +00:00
Daniel Stenberg
a0be515d2d -R added 2001-09-03 12:10:48 +00:00
Daniel Stenberg
5900c0f767 utime() and utime.h adjustments for curl -R 2001-09-03 12:00:38 +00:00
Daniel Stenberg
d10cf2ba94 introducing -R/--remote-time which uses the remote file's time to set the
local file's time
2001-09-03 12:00:08 +00:00
Daniel Stenberg
bae1a75731 use the LIBCURL_NAME instead of the "hardcoded" string 2001-09-03 07:01:49 +00:00
Daniel Stenberg
f5adc8e53f libtool 1.4.1 2001-09-03 07:00:59 +00:00
Daniel Stenberg
67df4c9e6c removed unused #defines 2001-09-01 10:20:12 +00:00
Daniel Stenberg
50adfe3be9 Heikki Korpela noticed openbsd problems and libtool 2001-09-01 09:43:52 +00:00
Daniel Stenberg
71794da389 as generated with libtool 1.4.0a 2001-09-01 09:42:22 +00:00
Daniel Stenberg
6ef11f0b13 Heikki Korpela fixed the 'make -C' invokes. make -C is banned. 2001-09-01 09:39:40 +00:00
Daniel Stenberg
a5705acc9c the big struct rename of the year 2001-08-30 23:03:22 +00:00
Daniel Stenberg
47e7a3e678 a few more struct fixes 2001-08-30 22:59:58 +00:00
Daniel Stenberg
0ece1b5c34 Major rename and redesign of the internal "backbone" structs. Details will
be posted in a minute to the libcurl list.
2001-08-30 22:48:34 +00:00
Daniel Stenberg
315954c175 updated a bit 2001-08-29 15:02:46 +00:00
Daniel Stenberg
27ce46a85d removed cookies and SSL sessions 2001-08-29 12:14:18 +00:00
Daniel Stenberg
ea3cc81487 new ftp upload example, brand new cookie functionality and more 2001-08-29 09:51:44 +00:00
Daniel Stenberg
a9b139b25c added CURLOPT_COOKIEJAR details 2001-08-29 09:47:33 +00:00
Daniel Stenberg
bbdd5adf6e '-c -' 2001-08-29 09:45:44 +00:00
Daniel Stenberg
d425f5389d -c/--cookie-jar documented 2001-08-29 09:44:35 +00:00
Daniel Stenberg
26983053c4 take port numbers into account when finding a previous session from the
cache
2001-08-29 09:36:41 +00:00
Daniel Stenberg
8e0043165a added COOKIEJAR 2001-08-29 09:32:50 +00:00
Daniel Stenberg
c13dbf7bae uses the new cookie jar feature 2001-08-29 09:32:35 +00:00
Daniel Stenberg
a2b6ef3478 cookie jar adjustments 2001-08-29 09:32:18 +00:00
Daniel Stenberg
b6526af442 added ftpupload.c 2001-08-29 07:12:04 +00:00
Daniel Stenberg
4edba42c7c lots of crap 2001-08-28 09:02:33 +00:00
Daniel Stenberg
1180ef4b31 added the most recent one from automake 1.5, it complained on the former
one being "too old"
2001-08-28 09:01:50 +00:00
Daniel Stenberg
94bf462473 up'ed the version-info 2001-08-28 08:58:27 +00:00
Daniel Stenberg
233b3f718f curl_formadd() adjustments by Georg Huettenegger 2001-08-28 08:55:59 +00:00
Daniel Stenberg
0452fd8657 Georg Huettenegger's updates 2001-08-28 08:55:26 +00:00
Daniel Stenberg
613eafaf02 automake 1.5 complained on my SUFFIXES line! 2001-08-28 08:55:12 +00:00
Daniel Stenberg
725bd1dddf Georg Huettenegger's fixes and improvements to curl_formadd() 2001-08-28 08:54:33 +00:00
Daniel Stenberg
9835629801 Georg Huettenegger added code to deal with error 417 when doing form posts.
NOTE: we might do this for *ALL* errors when doing form posts.
2001-08-28 08:54:09 +00:00
Daniel Stenberg
3c52c53ddd Added SSL session ID caching, moved some SSL code from url.c to ssluse.c 2001-08-28 08:37:54 +00:00
Sterling Hughes
321ba15a82 we should be using start here. 2001-08-26 20:51:16 +00:00
Daniel Stenberg
9e5dfc15ac improved the test 2001-08-26 14:28:05 +00:00
Daniel Stenberg
8d52681e1d Added #include <string.h> and removed a silly mistakenly added , 2001-08-26 14:27:07 +00:00
Daniel Stenberg
56f6815d3d rewrite to work around BSD announcement license issues, this is also
somewhat easier to understand if I may say so. It is slightly slower.
2001-08-24 10:25:02 +00:00
Daniel Stenberg
ce07e79f3c cookies are stored in the reversed order now (which in turn means that
the order is _not_ actually reversed like it used to be)
2001-08-24 10:18:14 +00:00
Daniel Stenberg
723ced9336 T. Bharath's patch => linking with multithreaded versions of the c runtime
library for use in multithreaded apps
2001-08-24 07:45:16 +00:00
Daniel Stenberg
73417b59c7 T. Bharath's patch. It is kind of dirty, as it #pragma aways a whole bunch
of compiler warnings, but I guess they make the life somewhat easier to live
for a ms dude compiling this. For a rainy day: remove the pragmas and correct
the source code that cause the warnings!
2001-08-24 07:43:24 +00:00
Daniel Stenberg
f4e2774ab8 newly re-generated from the modified getdate.y 2001-08-24 07:41:51 +00:00
Daniel Stenberg
d5112c0dec include setup.h properly, not config.h 2001-08-24 07:39:50 +00:00
Daniel Stenberg
aace68c91b extern declarations no longer done on windows (T. Bharath's patch) 2001-08-24 07:39:15 +00:00
Daniel Stenberg
4034f31823 cleanups 2001-08-24 07:24:34 +00:00
Daniel Stenberg
5323340cae Kevin Roth's comments about -G have been addressed:
o -G -I works on the same command line and makes HEAD instead of GET
o -G with an already present question mark in the URL makes an ampersand get
  added as a separator instead
2001-08-24 07:01:09 +00:00
Daniel Stenberg
3aae2ec511 Tim Costello's bug report #454856 2001-08-24 06:31:34 +00:00
Daniel Stenberg
df09214c62 strcasecmp() is banned from our code, should be strequal() everywhere!
Tim Costello reported bug report #454858.
2001-08-24 06:20:47 +00:00
Daniel Stenberg
12acab9b86 When setting *_URL or *_PROXY in *_setopt(), it is important that we check
and possibly free the existing pointer first, and then clear the "allocated"
bit. We previously mistakenly could free the new pointer passed to us by
the friendly user...!
2001-08-23 14:06:38 +00:00
Daniel Stenberg
c9c2115088 started working on a function for writing (all) cookies, made it possible
to read multiple cookie files, no longer writes to the URL string passed
to the _add() function. The new stuff is now conditionally compiled on the
COOKIE define. Changed the _init() proto.
2001-08-23 14:05:25 +00:00
Daniel Stenberg
d73d28a75b added FTPS to the list of supported protocols 2001-08-23 11:12:07 +00:00
Daniel Stenberg
13bf964b78 item 4.6 is now an indication of a crash, not a timeout 2001-08-23 11:11:13 +00:00
Daniel Stenberg
3fb9c5727c As Steve Lhomme pointed out, this generates 'libcurl.dll' now instead of
the previous 'curl.dll'
2001-08-23 11:06:10 +00:00
Daniel Stenberg
b69f33ed44 Nico's update: "modified the build procedure to restore to the right current
directory where the build was started and it will autosense where is was run
from and set up the correct default directory at start of the script."
2001-08-23 10:56:48 +00:00
Daniel Stenberg
56e8d073bf curl_formadd() using example, the 7.9 style of building rfc1867 form posts 2001-08-23 08:45:20 +00:00
Daniel Stenberg
83a8786fe1 I want Sterling to be my friend, so I wasted some time on splitting up the
huge monster function _ftp() into more little functions. There are still
more that can be done, but this is at least improving readability and
maintainability... :-)
2001-08-23 06:10:01 +00:00
Daniel Stenberg
e3d7cc895b Georg Huettenegger's fixes, man pages converted to HTML pages and included
in release archive
2001-08-22 11:25:39 +00:00
Daniel Stenberg
0f425b01aa CURLOPT_FTPASCII is the old name, CURLOPT_TRANSFERTEXT is the new 2001-08-22 11:24:57 +00:00
Daniel Stenberg
c5a4b52d83 libcurl.3 has the info now 2001-08-22 11:23:53 +00:00
Daniel Stenberg
fc2d24105c CURLOPT_POST isn't needed these days 2001-08-22 11:23:07 +00:00
Daniel Stenberg
6704d44dd4 updated 2001-08-22 11:22:43 +00:00
Daniel Stenberg
3d9aeccc90 libcurl.3 is the man page 2001-08-22 11:22:28 +00:00
Daniel Stenberg
08655d8d5d Georg Huettenegger's patch curl-7.8.1-pre5-patch-20010819 2001-08-21 13:18:07 +00:00
Daniel Stenberg
3e5dbac7a2 added test44 formpost without Expect:, modified test9 2001-08-21 12:46:23 +00:00
Daniel Stenberg
05d9c9b849 run 'make clean' before 'make dist' to make sure the HTML files are up-to-date 2001-08-21 09:16:43 +00:00
Daniel Stenberg
4c2fb64e21 added a 'html' target that builds HTML versions from the man page sources.
It requires 'gnroff' and 'man2html' for now. 'make html' will be invoked by
the 'maketgz' script and the HTML files are included in release archives.
2001-08-21 09:16:09 +00:00
Daniel Stenberg
46a897f604 make html runs make html in the docs dir 2001-08-21 09:14:31 +00:00
Daniel Stenberg
d4b23198fa this is replaced with libcurl.3 2001-08-21 06:56:13 +00:00
Daniel Stenberg
6581663687 fflush the progress output, fixed configure.in for SSL without --with-ssl 2001-08-21 06:50:45 +00:00
Daniel Stenberg
4398151fd5 Troy Engel's fix for running configure without --with-ssl 2001-08-21 06:36:30 +00:00
Daniel Stenberg
d5fbfa3d0b As Andrs Garca reported we need to fflush() the data->err so that the
progress meter looks better on windows (and if the data->err is redirected
from stderr it also makes a point)
2001-08-21 06:29:56 +00:00
Daniel Stenberg
3a588fc9e7 added "4.5 FIGURE OUT WHAT A POST LOOKS LIKE"
added an online URL to this document
corrected a bad use of -t
2001-08-20 13:22:37 +00:00
181 changed files with 9363 additions and 5429 deletions

460
CHANGES
View File

@@ -6,6 +6,464 @@
History of Changes History of Changes
Version 7.9.1
Daniel (4 November 2001)
- I've added a number of new test cases the last few days. A few of them since
I got reports that hinted on problems on timeouts, so I added four tests
with timeouts for all sorts of protocols and stuff. I also came to think of
a few other error scenarios that we currently didn't test properly, so I
wrote up tests for a few of those too.
Daniel (2 November 2001)
- Replaced read() and write() with recv() and send() for socket operations
even under normal unixes.
Daniel (1 November 2001)
- When an FTP transfer was aborted due to a timeout, it wasn't really aware of
how many bytes that had been transferred and the error text always said 0
bytes. I modified this to output the actually transferred amount! :-)
- The FTP fixes in pre7 didn't compile on IPv6 enabled hosts. Does now. I also
added more comments in the lib/ftp.c source file.
- Minor updates to the FAQ, added a brand new section to the web site about
the name issue (who owns "curl"? will someone sue us? etc etc):
http://curl.haxx.se/legal/thename.html
Version 7.9.1-pre7
Daniel (31 October 2001)
- The curl_easy_getinfo() timers accidentally lost they're subsecond accuracy
as the calculations used longs instead of doubles! Paul Harrington reported.
- The SSL SocketIsDead() checks weren't good enough (as expected really), so I
had to add a generic internal try-it-out system. If the request on a re-used
connection seems to fail, then we go back and get a new (fresh) connection
and re-tries the request on that instead. It kind of makes the
SocketIsDead() check obsolete, but I think it is a quicker way for those
cases where it actually discovers that the connection is dead.
- When fixing the above, I noticed that we did quite a few writes to sockets
in libcurl where we didn't check the return code (that it actually worked to
send the data). With the new "attempted request" system we must detect those
situations so I went over a bunch of functions, changed return types and
added checks for what they actually return.
Version 7.9.1-pre6
Daniel (31 October 2001)
- Paul Harrington detected a problem with persistant SSL connections. Or to be
more exact, we didn't properly detect that the connection was dead and then
a second connection would try to re-use it wrongly. The solution to this
problem is still not very clear and I'm working on it. One OpenSSL insider
said there is no way to know if the SSL connection is alive or not without
actually trying an operation.
Daniel (30 October 2001)
- If a cookie was read from a file, it could accidentally strdup() a NULL
pointer. Paul Harrington reported. [http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/curl/curl/lib/cookie.c.diff?r1=1.25&r2=1.26]
- The MANUAL file now documents -t correctly. I also fixed the -T description
in the curl.1 man page.
Daniel (29 October 2001)
- John Janssen found out that curl_formadd was missing in the libcurl.def file
and that the docs stated the wrong return type for the function.
- Andr<64>s Garc<72>a found a bug with multiple files in the curl_formadd() function,
that I removed with this patch [http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/curl/curl/lib/formdata.c.diff?r1=1.25&r2=1.26].
- Kevin Roth brought another patch that moved the cygwin package files to the
packages/Win32/cygwin directory.
- A bug in the connection re-use logic made repeated requests to the same FTP
server (when using name+pasword in the URL) sometimes use more than one
connection. [http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/curl/curl/lib/url.c.diff?r1=1.166&r2=1.167]
- Moonesamy tracked down and fixed a problem with the new 7.9.1 connect
code. This corrected the error Kevin Roth reported on the 7.9.1-pre5 release
(test 19)...
[http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/curl/curl/lib/connect.c.diff?r1=1.13&r2=1.14]
Daniel (26 October 2001)
- Added test28 which verifies that "Location:"-following works even if the
contents is separated with more than one space.
Daniel (25 October 2001)
- Ramana Mokkapati pointed out that LDAP transfers would 'hang' after the
correct data has been output.
Version 7.9.1-pre5
Daniel (24 October 2001)
- T. Bharath found a memory leak in the cookie engine. When we update a cookie
that we already knew about, we lost a chunk of memory in the progress... The
brand new test case 27 now tests for this occurrence. [http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/curl/curl/lib/cookie.c.diff?r1=1.24&r2=1.25]
Daniel (23 October 2001)
- pack_hostent() didn't properly align some pointers, so at least SPARC CPUs
would core. [http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/curl/curl/lib/hostip.c.diff?r1=1.34&r2=1.35]
Daniel (22 October 2001)
- Tom Benoist reported that this SGI IRIX compiler didn't handle indented
preprocessor instructions, so they're no longer in the source code!
- Applied Kevin Roth's patches to make it easier to build cygwin packages from
the out-of-the-box curl release archives.
- I forgot to mention it below, but libcurl now closes connections that report
transfer failures. Unconditionally. This could be made more nicely in the
future if we set a flag or something that the connection is still good to be
used for the errors that know that for a fact. We have to close the
connection for the cases where we abort for example a HTTP transfer in the
middle, or otherwise we might re-use that connection later with lots of data
still being sent to us on it. [http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/curl/curl/lib/transfer.c.diff?r1=1.63&r2=1.64]
Daniel (19 October 2001)
- CURLE_GOT_NOTHING is now returned when a HTTP server doesn't return
anything, not even a header. test case 37 was added to test for this.
- T. Bharath made curl_easy_duphandle() properly clone the cookie status as
well.
Version 7.9.1-pre4
Daniel (18 October 2001)
- CURLOPT_FAILONERROR, set with "curl --fail" no longer returns an error if
the HTTP return code is below 400.
Daniel (17 October 2001)
- The test suite now kills any running test http server when you re-start the
tests.
- We had to remove 'use strict' from two perl scripts, as the cygwin
adjustments didn't play nicely otherwise for some reason. Any perl wizard
out there who can put the scrict back and still make it run good on unix and
cygwin?
- A potential memory leak pointed out to us by Yanick Pelletier was removed.
It would occur when a http file transfer fails. [http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/curl/curl/lib/transfer.c.diff?r1=1.60&r2=1.61]
- The memory debugging system should no longer display anything to stderr
if the curl_memdebug() hasn't been used to explicitly say so. This makes it
easier to use the memory debug system and switch the logging on/off.
Daniel (16 October 2001)
- Kevin Roth provided fixes for building curl nicer in cygwin environments.
Daniel (12 October 2001)
- Cleaning up the progress meter/info code. The "current speed" is now more
accurate than before as we now use the true time spent between the measures,
and not just "assuming" every-second-update like before. The output should
now also be of the same width at all times, never to show "extra" zeroes on
the right edge.
- After talking about possible Location: bugs on the mailing list, I modified
the "absolute URL" checker in lib/transfer.c to be more strict when checking
if the redirected URL is absolute.
Daniel (11 October 2001)
- Kevin Roth provided patches that make the test suite run fine on Windows
2000 running cygwin.
Daniel (10 October 2001)
- Setting the -c or the CURLOPT_COOKIEJAR option now enables the cookie parser.
Previously -b or CURLOPT_COOKIEFILE was also required for the jar to work.
Version 7.9.1-pre3
Daniel (9 October 2001)
- Added a new option to the command line client: -0/--http1.0. It uses the new
libcurl option CURLOPT_HTTP_VERSION to request that libcurl uses HTTP 1.0
requests instead of the default version (1.1). It should only be used if you
really MUST do that because of a silly remote server.
- Renamed the 'TimeCond' typedef in curl/curl.h to use a 'curl_' prefix as
all public curl-symbols should.
- libcurl now explicitly ignores the SIGPIPE signal.
Daniel (8 October 2001)
- Kevin Roth's change to the cookie-jar comment (in the stored file) was
applied.
- Lucas Adamski's minor bug in the bind error code failf() was fixed.
Daniel (5 October 2001)
- Moonesamy fixed the Curl_connecthost() function to not give compiler errors
on a bunch of compilers, due to the argument named 'socket'.
- Moonesamy also provided updated VC++ makefiles and project files.
Version 7.9.1-pre2
Daniel (4 October 2001)
- Albert Chin provided a configure patch that makes the script detect proper
gethostbyname_r() method without actually running any code, only compiling
is necessary. This also removes the need of having a resolving 'localhost'
name.
- Found and removed memory leakage (name resolve data) in libcurl on
IPv6-enabled hosts. These could sneak through because we didn't have any
resource tracing on the IPv6-related functions. We do now.
Daniel (3 October 2001)
- Keith McGuigan patched away a (mainly Windows-) problem with the name
resolver data being kept in the static memory area, which is removed when a
thread is killed. The curl handle itself though perfectly handles being
passed between threads.
- Dirk Eddelbuettel reported an odd bug that turned out to be his proxy that
required an Authorization: header. Now, proxies are not supposed to require
that header, that is for true servers...
- I accidentally ruined Georg's curl_formadd(). Uh, bad me. Corrected now.
Version 7.9.1-pre1
Daniel (3 October 2001)
- Georg Huettenegger once again made an effort beyond the call of duty and not
only improved the curl_formadd() function, but also took care of adjusting
the curl command line client to use this new function instead of the
obsoleted curl_formparse.
Daniel (2 October 2001)
- Major fix in how libcurl does TCP connects. It now does non-blocking
connects to enable good timeouts without signals, and it now tries all IP
addresses for any given host (if it resolves more than one and the first
one(s) don't connect). Added a new source file 'connect.c' to deal with all
the TCP connect stuff.
- We now support IPv4-style IP-addresses in rfc2732-format, to better support
people writing scripts without knowing what address there is.
Daniel (28 September 2001)
- Cleanups in the FTP source code. Divided the code into even more smaller
functions and generally tried to make the differences between IPv4 and IPv6
get less noticable in the sources.
- If the remote file time is not readable/accessable/understood by libcurl,
libcurl now returns -1 in the CURLINFO_FILETIME data, not 0 as it previously
did. This should make curl not touch the file data unless there was a known
remote date when -R is used.
Daniel (27 September 2001)
- Working on getting non-blocking connects working platform independent. We
will also make curl try all IPs for a given host if the first one should
fail.
Daniel (26 September 2001)
- Kevin Roth provided a cookie example that proved the cookie jar
functionality wasn't working properly. I added test case 46 and made it
work.
Daniel (25 September 2001)
- J<>rn Hartroth updated the mingw32 makefiles.
Version 7.9
Daniel (23 September 2001)
- Found and removed a 'socket leak' that would occur on IPv6 enabled hosts
when FTP RETR failed.
- Made the FTP upload tests run fine on machines with IPv6 enabled.
Version 7.9-pre8
Daniel (19 September 2001)
- Vojtech Minarik set up a special-purpose test server and provided me with
test certificates in order for me to repeat the bug reports #440068 and
#440373. It turned out we didn't check all the error codes properly. We do
now, and connecting with a unacceptable certificate will make libcurl fail
to connect with an error code returned.
- Ramana Mokkapati found a case when the Location: following code did wrong.
I wrote a test case for this (45).
Version 7.9-pre7
Daniel (17 September 2001)
- Linus Nielsen Feltzing fixed telnet for win32. It makes libcurl require
winsock 2.0.
Version 7.9-pre6
- libtool 1.4.2 is now in use!
Version 7.9-pre5
Daniel (14 September 2001)
- Added another 14 ftp tests.
Daniel (13 September 2001)
- Added curl_easy_duphandle() to the easy.h header file. It has now been
tested and proved to work in a real-world tests by T Bharath. We still need
to write up some docs for this function.
- Added four more ftp tests to the test suite.
Daniel (12 September 2001)
- CURLOPT_SSL_CIPHER_LIST was added, and the curl tool option is named
--ciphers. Use them to specify a list of ciphers to use in the SSL
connection.
- T. Bharath found a memory leak in libcurl's windows version. It turned out
to be the new duphandle() that didn't quite work yet.
Version 7.9-pre4
Daniel (11 September 2001)
- Added verbose output for SSL connections that output the server
certificate's start and expire dates. As suggested by Paul Harrington.
- Heikki Korpela found problems in the perl ftp server used for the test
suite, when he runs on on OpenBSD with perl 5.6. Some changes have been
made, but nothing really certain.
- T. Bharath has experienced problems with libcurl's stack usage on windows
and works on reducing it.
Daniel (10 September 2001)
- Cris Bailiff fixed the perl interface. It stopped working since the changed
behavior with WRITEHEADER and NULL pointers.
- The "output cookies" function could dump core if no cookies were enabled.
Daniel (7 September 2001)
- SM pointed out that the SSL code didn't compile any longer if SSL was
disabled... Also, we needed to correct the #include for the utime stuff on
windows.
Daniel (6 September 2001)
- T. Bharath pointed out a flaw in the SSL session cache code that made it
sometimes read from a NULL pointer.
Version 7.9-pre3
Daniel (3 September 2001)
- Added the -R/--remote-time option, that uses the remote file's datestamp to
set the local file's datestamp. Thus, when you get a remote file your local
file will get the same time and date. Note that this only works when you use
-o or -O.
- Installed libtool 1.4.1, libtoolized and everything.
Daniel (1 September 2001)
- Heikki Korpela pointed out that I did not ship the proper libtool stuff in
the pre-releases, even though that was my intention. libtoolize has now
been re-run.
- Heikki also patched away the bad use of 'make -C' in the test suite
makefile. make -C is not very portable and is now banned from here.
Version 7.9-pre2
Daniel (31 August 2001)
- I just made a huge internal struct rehaul, and all the big internally used
structs have been renamed, redesigned and stuff have been moved around a bit
to make the source easier to follow, more logically grouped and to hopefully
decrease future bugs. I also hope that this will make new functions to get
easier to add, and make it less likely that we have bugs left like the URL-
free bug from August 23.
Version 7.9-pre1
Daniel (29 August 2001)
- The new cookie code have enabled the brand new '-c/--cookie-jar' option. Use
that to specify the file name in which you want to have all cookies curl
knows of, dumped to. It'll be written using the netscape cookie format.
This is internally done with the new CURLOPT_COOKIEJAR option to libcurl,
which in turn dumps this information when curl_easy_cleanup() is invoked.
There might be reasons to re-consider my choice of putting it there. Perhaps
it is better placed to get done just before *_perform() is done. It is all
of course depending on how you guys want to use this feature...
- Added ftpupload.c in the source examples section, based on source code posted
by Erick Nuwendam.
Daniel (28 August 2001)
- Now running libtool CVS branch-1-4 to generate stuff. Should fix problems
on OpenBSD and hopefully on FreeBSD as well!
- Georg Huettenegger modified the curl_formadd() functionality slightly, and
added support for error code 417 when doing form post and using the Expect:
header. Great work!
- Made some tests with cached SSL session IDs, and they seem to work. There
should be a significant speed improvement in the SSL connection phase, but
in my tiny tests it just isn't possible to notice any difference. Like other
caching in libcurl, you must reuse the same handle for the caching to take
effect. SSL session ID caching is done on a per host-name and destination
port number basis.
Set verbose, and you'll get informational tests when libcurl detects and
uses a previous SSL session ID.
- Upgraded to automake 1.5 on my development/release machine.
Daniel (27 August 2001)
- Slowly started writing SSL session ID caching code
Daniel (24 August 2001)
- T. Bharath removed compiler warnings on windows and updated the MS project
files.
- Kevin Roth reported two kinds of command line constructs with the new -G that
curl didn't really deal with the way one would like.
- Tim Costello patched away a use of strcasecmp() in the SSL code. We have our
own portable version named strequal() that should be used!
- Tim also pointed out a problem in the lib/Makefile.vc6 file that made it mix
debug object modules causing confusions.
Daniel (23 August 2001)
- T. Bharath accurately found a libcurl bug that would happen when doing a
second invoke of curl_easy_perform() with a new URL when the previous invoke
followed a Location: header.
- Started the improvement work on the cookie engine:
- Now keeps cookies in the same order as the cookie file
- A write to the possibly static string was removed
- Added a function that can output all cookies
- Now supports reading multiple cookie files
- Steve Lhomme corrected a DLL naming issue in the MSVC++ project file.
- Split up the monster function in lib/ftp.c to use more smallish functions to
increase readability and maintainability.
Daniel (21 August 2001)
- Georg Huettenegger's big patch was applied. Now we have:
o "Expect: 100-continue" support. We will from now on send that header in
all rfc1867-posts, as that makes us abort much faster when the server
rejects our POST. Posting without the Expect: header is still possible in
the standard replace-internal-header style.
o curl_formadd() is a new formpost building function that is introduced to
replace the now deprecated curl_formparse() function. The latter function
will still hang around for a while, but the curl_formadd() is the new way
and correct way to build form posts.
o Documentation has been updated to reflect these changes
These changes are reason enough to name the next curl release 7.9...
- We now convert man pages to HTML pages and include them in the release
archive. For the pleasure of everyone without nroff within reach.
- Andr<64>s Garc<72>a's suggested flushing of the progress meter output stream was
added. It should make the progress meter look better on Windows.
- Troy Engel pointed out a mistake in the configure script that made it fail
on many Red Hat boxes!
Daniel (20 August 2001)
- We need an updated libtool to make a better build environment for OpenBSD
as well as FreeBSD
Version 7.8.1
Daniel (20 August 2001) Daniel (20 August 2001)
- Brad pointed out that we ship two extra libtool files in the tarballs that - Brad pointed out that we ship two extra libtool files in the tarballs that
we really don't need to! Removing them makes the gz-archive about 60K we really don't need to! Removing them makes the gz-archive about 60K
@@ -993,7 +1451,7 @@ Version 7.6.1-pre2
Daniel (31 January 2001) Daniel (31 January 2001)
- Curl_read() and curl_read() now return a ssize_t for the size, as it had to - Curl_read() and curl_read() now return a ssize_t for the size, as it had to
be able to return -1. The telnet support crashed due to this and there was a be able to return -1. The telnet support crashed due to this and there was a
possibility to weird behaviour all over. Linus Nielsen Feltzing helped me possibility to weird behavior all over. Linus Nielsen Feltzing helped me
find this. find this.
- Added a configure.in check for a working getaddrinfo() if IPv6 is requested. - Added a configure.in check for a working getaddrinfo() if IPv6 is requested.

View File

@@ -10,8 +10,8 @@ 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.4 and libtool Use autoconf 2.50 and no earlier. Also, try having automake 1.5 and libtool
1.4 at least. 1.4.1 at least.
You will need perl to generate the src/hugehelp.c file. The file 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 src/hugehelp.c.cvs is a one-shot file that you can rename to src/hugehelp.c if

View File

@@ -10,8 +10,7 @@ in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, and/or sell copies of the to use, copy, modify, merge, publish, distribute, and/or sell copies of the
Software, and to permit persons to whom the Software is furnished to do so, Software, and to permit persons to whom the Software is furnished to do so,
provided that the above copyright notice(s) and this permission notice appear provided that the above copyright notice(s) and this permission notice appear
in all copies of the Software and that both the above copyright notice(s) and in all copies of the Software.
this permission notice appear in supporting documentation.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,

View File

@@ -8,16 +8,19 @@ EXTRA_DIST = \
CHANGES LEGAL maketgz MITX.txt MPL-1.1.txt \ CHANGES LEGAL maketgz MITX.txt MPL-1.1.txt \
config-win32.h reconf Makefile.dist \ config-win32.h reconf Makefile.dist \
curl-config.in build_vms.com config-riscos.h \ curl-config.in build_vms.com config-riscos.h \
config-vms.h config-vms.h curl-mode.el
bin_SCRIPTS = curl-config bin_SCRIPTS = curl-config
SUBDIRS = docs lib src include tests packages perl php SUBDIRS = docs lib src include tests packages
# create a root makefile in the distribution: # create a root makefile in the distribution:
dist-hook: dist-hook:
cp $(srcdir)/Makefile.dist $(distdir)/Makefile cp $(srcdir)/Makefile.dist $(distdir)/Makefile
html:
cd docs; make html
check: test check: test
test: test:
@@ -64,3 +67,9 @@ pkgadd:
make install DESTDIR=`/bin/pwd`/packages/Solaris/root ; \ make install DESTDIR=`/bin/pwd`/packages/Solaris/root ; \
cat LEGAL MITX.txt MPL-1.1.txt > $(srcdir)/packages/Solaris/copyright ; \ cat LEGAL MITX.txt MPL-1.1.txt > $(srcdir)/packages/Solaris/copyright ; \
cd $(srcdir)/packages/Solaris && $(MAKE) package cd $(srcdir)/packages/Solaris && $(MAKE) package
#
# Build a cygwin binary tarball installation file
# resulting .tar.bz2 file will end up at packages/Win32/cygwin
cygwinbin:
$(MAKE) -C packages/Win32/cygwin cygwinbin

3
README
View File

@@ -12,7 +12,7 @@ README
document. document.
libcurl is a library that Curl is using to do its job. It is readily libcurl is a library that Curl is using to do its job. It is readily
available to be used by your software. Read the libcurl.5 man page to available to be used by your software. Read the libcurl.3 man page to
find out how! find out how!
You find answers to the most frequent questions we get in the FAQ document. You find answers to the most frequent questions we get in the FAQ document.
@@ -26,6 +26,7 @@ README
The official download mirror sites are: The official download mirror sites are:
Sweden -- ftp://ftp.sunet.se/pub/www/utilities/curl/ Sweden -- ftp://ftp.sunet.se/pub/www/utilities/curl/
Sweden -- ftp://cool.haxx.se/curl/
Germany -- ftp://ftp.fu-berlin.de/pub/unix/network/curl/ Germany -- ftp://ftp.fu-berlin.de/pub/unix/network/curl/
To download the very latest source off the CVS server do this: To download the very latest source off the CVS server do this:

View File

@@ -54,3 +54,11 @@
/* Define if you have a working OpenSSL installation */ /* Define if you have a working OpenSSL installation */
#undef OPENSSL_ENABLED #undef OPENSSL_ENABLED
/* Define the one correct non-blocking socket method below */
#undef HAVE_FIONBIO
#undef HAVE_IOCTLSOCKET
#undef HAVE_IOCTLSOCKET_CASE
#undef HAVE_O_NONBLOCK
#undef HAVE_DISABLED_NONBLOCKING

View File

@@ -1,3 +1,107 @@
dnl Check for how to set a socket to non-blocking state. There seems to exist
dnl four known different ways, with the one used almost everywhere being POSIX
dnl and XPG3, while the other different ways for different systems (old BSD,
dnl Windows and Amiga).
dnl
dnl There are two known platforms (AIX 3.x and SunOS 4.1.x) where the
dnl O_NONBLOCK define is found but does not work. This condition is attempted
dnl to get caught in this script by using an excessive number of #ifdefs...
dnl
AC_DEFUN(CURL_CHECK_NONBLOCKING_SOCKET,
[
AC_MSG_CHECKING([non-blocking sockets style])
AC_TRY_COMPILE([
/* headers for O_NONBLOCK test */
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
],[
/* try to compile O_NONBLOCK */
#if defined(sun) || defined(__sun__) || defined(__SUNPRO_C) || defined(__SUNPRO_CC)
# if defined(__SVR4) || defined(__srv4__)
# define PLATFORM_SOLARIS
# else
# define PLATFORM_SUNOS4
# endif
#endif
#if (defined(_AIX) || defined(__xlC__)) && !defined(_AIX4)
# define PLATFORM_AIX_V3
#endif
#if defined(PLATFORM_SUNOS4) || defined(PLATFORM_AIX_V3)
#error "O_NONBLOCK does not work on this platform"
#endif
int socket;
int flags = fcntl(socket, F_SETFL, flags | O_NONBLOCK);
],[
dnl the O_NONBLOCK test was fine
nonblock="O_NONBLOCK"
AC_DEFINE(HAVE_O_NONBLOCK)
],[
dnl the code was bad, try a different program now, test 2
AC_TRY_COMPILE([
/* headers for FIONBIO test */
#include <unistd.h>
#include <stropts.h>
],[
/* FIONBIO source test */
int flags = ioctl(socket, FIONBIO, &flags);
],[
dnl FIONBIO test was good
nonblock="FIONBIO"
AC_DEFINE(HAVE_FIONBIO)
],[
dnl FIONBIO test was also bad
dnl the code was bad, try a different program now, test 3
AC_TRY_COMPILE([
/* headers for ioctlsocket test (cygwin?) */
#include <windows.h>
],[
/* ioctlsocket source code */
int flags = ioctlsocket(socket, FIONBIO, &flags);
],[
dnl ioctlsocket test was good
nonblock="ioctlsocket"
AC_DEFINE(HAVE_IOCTLSOCKET)
],[
dnl ioctlsocket didnt compile!
AC_TRY_COMPILE([
/* headers for IoctlSocket test (Amiga?) */
#include <sys/ioctl.h>
],[
/* IoctlSocket source code */
int flags = IoctlSocket(socket, FIONBIO, (long)1);
],[
dnl ioctlsocket test was good
nonblock="IoctlSocket"
AC_DEFINE(HAVE_IOCTLSOCKET_CASE)
],[
dnl ioctlsocket didnt compile!
nonblock="nada"
AC_DEFINE(HAVE_DISABLED_NONBLOCKING)
])
dnl end of forth test
])
dnl end of third test
])
dnl end of second test
])
dnl end of non-blocking try-compile test
AC_MSG_RESULT($nonblock)
if test "$nonblock" = "nada"; then
AC_MSG_WARN([non-block sockets disabled])
fi
])
dnl Check for socklen_t: historically on BSD it is an int, and in dnl Check for socklen_t: historically on BSD it is an int, and in
dnl POSIX 1g it is a type of its own, but some platforms use different dnl POSIX 1g it is a type of its own, but some platforms use different
dnl types for the argument to getsockopt, getpeername, etc. So we dnl types for the argument to getsockopt, getpeername, etc. So we
@@ -142,7 +246,6 @@ AC_DEFUN(CURL_CHECK_INET_NTOA_R,
AC_DEFINE(NEED_REENTRANT) AC_DEFINE(NEED_REENTRANT)
AC_MSG_RESULT(yes)], AC_MSG_RESULT(yes)],
AC_MSG_RESULT(no))])]) AC_MSG_RESULT(no))])])
]) ])
AC_DEFUN(CURL_CHECK_GETHOSTBYADDR_R, AC_DEFUN(CURL_CHECK_GETHOSTBYADDR_R,
@@ -220,8 +323,6 @@ rc = gethostbyaddr_r(address, length, type, &h,
ac_cv_gethostbyaddr_args=8],[ ac_cv_gethostbyaddr_args=8],[
AC_MSG_RESULT(no) AC_MSG_RESULT(no)
have_missing_r_funcs="$have_missing_r_funcs gethostbyaddr_r"])])])])]) have_missing_r_funcs="$have_missing_r_funcs gethostbyaddr_r"])])])])])
]) ])
AC_DEFUN(CURL_CHECK_GETHOSTBYNAME_R, AC_DEFUN(CURL_CHECK_GETHOSTBYNAME_R,
@@ -229,28 +330,21 @@ AC_DEFUN(CURL_CHECK_GETHOSTBYNAME_R,
dnl check for number of arguments to gethostbyname_r. it might take dnl check for number of arguments to gethostbyname_r. it might take
dnl either 3, 5, or 6 arguments. dnl either 3, 5, or 6 arguments.
AC_CHECK_FUNCS(gethostbyname_r,[ AC_CHECK_FUNCS(gethostbyname_r,[
AC_MSG_CHECKING(if gethostbyname_r takes 3 arguments) AC_MSG_CHECKING([if gethostbyname_r takes 3 arguments])
AC_TRY_RUN([ AC_TRY_COMPILE([
#include <string.h> #include <string.h>
#include <sys/types.h> #include <sys/types.h>
#include <netdb.h> #include <netdb.h>
int int
main () { gethostbyname_r(const char *, struct hostent *, struct hostent_data *);],[
struct hostent h; gethostbyname_r(NULL, NULL, NULL);],[
struct hostent_data hdata;
char *name = "localhost";
int rc;
memset(&h, 0, sizeof(struct hostent));
memset(&hdata, 0, sizeof(struct hostent_data));
rc = gethostbyname_r(name, &h, &hdata);
exit (rc != 0 ? 1 : 0); }],[
AC_MSG_RESULT(yes) AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_GETHOSTBYNAME_R_3) AC_DEFINE(HAVE_GETHOSTBYNAME_R_3)
ac_cv_gethostbyname_args=3],[ ac_cv_gethostbyname_args=3],[
AC_MSG_RESULT(no) AC_MSG_RESULT(no)
AC_MSG_CHECKING(if gethostbyname_r with -D_REENTRANT takes 3 arguments) AC_MSG_CHECKING([if gethostbyname_r with -D_REENTRANT takes 3 arguments])
AC_TRY_RUN([ AC_TRY_COMPILE([
#define _REENTRANT #define _REENTRANT
#include <string.h> #include <string.h>
@@ -258,53 +352,34 @@ exit (rc != 0 ? 1 : 0); }],[
#include <netdb.h> #include <netdb.h>
int int
main () { gethostbyname_r(const char *,struct hostent *, struct hostent_data *);],[
struct hostent h; gethostbyname_r(NULL, NULL, NULL);],[
struct hostent_data hdata;
char *name = "localhost";
int rc;
memset(&h, 0, sizeof(struct hostent));
memset(&hdata, 0, sizeof(struct hostent_data));
rc = gethostbyname_r(name, &h, &hdata);
exit (rc != 0 ? 1 : 0); }],[
AC_MSG_RESULT(yes) AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_GETHOSTBYNAME_R_3) AC_DEFINE(HAVE_GETHOSTBYNAME_R_3)
AC_DEFINE(NEED_REENTRANT) AC_DEFINE(NEED_REENTRANT)
ac_cv_gethostbyname_args=3],[ ac_cv_gethostbyname_args=3],[
AC_MSG_RESULT(no) AC_MSG_RESULT(no)
AC_MSG_CHECKING(if gethostbyname_r takes 5 arguments) AC_MSG_CHECKING([if gethostbyname_r takes 5 arguments])
AC_TRY_RUN([ AC_TRY_COMPILE([
#include <sys/types.h> #include <sys/types.h>
#include <netdb.h> #include <netdb.h>
int struct hostent *
main () { gethostbyname_r(const char *, struct hostent *, char *, int, int *);],[
struct hostent *hp; gethostbyname_r(NULL, NULL, NULL, 0, NULL);],[
struct hostent h;
char *name = "localhost";
char buffer[8192];
int h_errno;
hp = gethostbyname_r(name, &h, buffer, 8192, &h_errno);
exit (hp == NULL ? 1 : 0); }],[
AC_MSG_RESULT(yes) AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_GETHOSTBYNAME_R_5) AC_DEFINE(HAVE_GETHOSTBYNAME_R_5)
ac_cv_gethostbyname_args=5],[ ac_cv_gethostbyname_args=5],[
AC_MSG_RESULT(no) AC_MSG_RESULT(no)
AC_MSG_CHECKING(if gethostbyname_r takes 6 arguments) AC_MSG_CHECKING([if gethostbyname_r takes 6 arguments])
AC_TRY_RUN([ AC_TRY_COMPILE([
#include <sys/types.h> #include <sys/types.h>
#include <netdb.h> #include <netdb.h>
int int
main () { gethostbyname_r(const char *, struct hostent *, char *, size_t,
struct hostent h; struct hostent **, int *);],[
struct hostent *hp; gethostbyname_r(NULL, NULL, NULL, 0, NULL, NULL);],[
char *name = "localhost";
char buf[8192];
int rc;
int h_errno;
rc = gethostbyname_r(name, &h, buf, 8192, &hp, &h_errno);
exit (rc != 0 ? 1 : 0); }],[
AC_MSG_RESULT(yes) AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_GETHOSTBYNAME_R_6) AC_DEFINE(HAVE_GETHOSTBYNAME_R_6)
ac_cv_gethostbyname_args=6],[ ac_cv_gethostbyname_args=6],[

View File

@@ -1,55 +1,67 @@
$! $!
$ def = "sys_users:[nbaggus.curl]" $
$ set def 'def' $ on control_y then goto Common_Exit!
$ cc_qual = "/define=HAVE_CONFIG_H=1/include=(""../include/"",""../"")" $ orig = f$environment("DEFAULT")
$ if p1 .eqs. "LISTING" then cc_qual = cc_qual + "/LIST/MACHINE" $ loc = f$environment("PROCEDURE")
$ if p1 .eqs. "DEBUG" then cc_qual = cc_qual + "/LIST/MACHINE/DEBUG" $ def = f$parse("X.X;1",loc) - "X.X;1"
$ msg_qual = "" $
$ call build "[.lib]" "*.c" $ set def 'def'
$ call build "[.src]" "*.c" $ cc_qual = "/define=HAVE_CONFIG_H=1/include=(""../include/"",""../"")"
$ call build "[.src]" "*.msg" $ if p1 .eqs. "LISTING" then cc_qual = cc_qual + "/LIST/MACHINE"
$ link /exe=curl.exe [.src]curl/lib/include=main,[.lib]curl/lib $ if p1 .eqs. "DEBUG" then cc_qual = cc_qual + "/LIST/MACHINE/DEBUG"
$ $ msg_qual = ""
$ $ call build "[.lib]" "*.c"
$ goto Exit $ call build "[.src]" "*.c"
$build: subroutine $ call build "[.src]" "*.msg"
$ set noon $ link /exe=curl.exe [.src]curl/lib/include=main,[.lib]curl/lib
$ set default 'p1' $
$ search = p2 $
$Loop: $ goto Common_Exit
$ file = f$search(search,1) $build: subroutine
$ if file .eqs. "" then goto EndLoop $ set noon
$ obj = f$search(f$parse(".OBJ;",file),2) $ set default 'p1'
$ if (obj .nes. "") $ search = p2
$ then $ reset = f$search("reset")
$ if (f$cvtime(f$file(file,"rdt")) .gts. f$cvtime(f$file(obj,"rdt"))) $ if f$search("CURL.OLB") .eqs. ""
$ then $ then
$ call compile 'file' $ LIB/CREATE/OBJECT CURL.OLB
$ lib/object curl.OLB 'f$parse(".obj;",file)' $ endif
$ else $ reset = f$search("reset",1)
$! write sys$output "File: ''file' is up to date" $Loop:
$ endif $ file = f$search(search,1)
$ else $ if file .eqs. "" then goto EndLoop
$! write sys$output "Object for file: ''file' does not exist" $ obj = f$search(f$parse(".OBJ;",file),2)
$ call compile 'file' $ if (obj .nes. "")
$ lib/object curl.OLB 'f$parse(".obj;",file)' $ then
$ endif $ if (f$cvtime(f$file(file,"rdt")) .gts. f$cvtime(f$file(obj,"rdt")))
$ goto Loop $ then
$EndLoop: $ call compile 'file'
$ purge $ lib/object curl.OLB 'f$parse(".obj;",file)'
$ set def 'def' $ else
$ endsubroutine ! Build $! write sys$output "File: ''file' is up to date"
$ $ endif
$compile: subroutine $ else
$ set noon $! write sys$output "Object for file: ''file' does not exist"
$ file = p1 $ call compile 'file'
$ qual = p2+p3+p4+p5+p6+p7+p8 $ lib/object curl.OLB 'f$parse(".obj;",file)'
$ typ = f$parse(file,,,"TYPE") - "." $ endif
$ cmd_c = "CC "+cc_qual $ goto Loop
$ cmd_msg = "MESSAGE "+msg_qual $EndLoop:
$ x = cmd_'typ' $ purge
$ 'x' 'file' $ set def 'def'
$ ENDSUBROUTINE ! Compile $ endsubroutine ! Build
$ $
$Exit: $compile: subroutine
$ exit $ set noon
$ file = p1
$ qual = p2+p3+p4+p5+p6+p7+p8
$ typ = f$parse(file,,,"TYPE") - "."
$ cmd_c = "CC "+cc_qual
$ cmd_msg = "MESSAGE "+msg_qual
$ x = cmd_'typ'
$ 'x' 'file'
$ ENDSUBROUTINE ! Compile
$
$Common_Exit:
$ set default 'orig'
$ exit

View File

@@ -5,9 +5,7 @@ die(){
exit exit
} }
MAKEFILES=`find . -name Makefile.am | sed 's/\.am$//'` automake || die "The command 'automake $MAKEFILES' failed"
automake $MAKEFILES || 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"

View File

@@ -101,6 +101,9 @@
/* Define if you have the <alloca.h> header file. */ /* Define if you have the <alloca.h> header file. */
/*#define HAVE_ALLOCA_H 1*/ /*#define HAVE_ALLOCA_H 1*/
/* Define if you have the malloc.h file. */
#define HAVE_MALLOC_H 1
/* Define if you have the <arpa/inet.h> header file. */ /* Define if you have the <arpa/inet.h> header file. */
#define HAVE_ARPA_INET_H 1 #define HAVE_ARPA_INET_H 1
@@ -185,3 +188,28 @@
#define HAVE_UNISTD_H 1 #define HAVE_UNISTD_H 1
#endif #endif
/**************************************************
*This is to eliminate the warnings when compiled *
* using MS VC++ compiler *
**************************************************/
#ifdef _MSC_VER
#pragma warning (disable: 4244) /* truncation from 'const int' to 'char' */
#pragma warning (disable: 4127) /* conditional expression is constant */
#pragma warning (disable: 4706) /* assignment within conditional expression */
#pragma warning (disable: 4761) /* integral size mismatch in argument */
#pragma warning (disable: 4101) /* unreferenced local variable */
#pragma warning (disable: 4131) /* uses old-style declarator */
#pragma warning (disable: 4057) /* const char *' differs in indirection to
slightly different base types from
'unsigned char [x] */
#pragma warning (disable: 4100) /* unreferenced formal parameter */
#pragma warning (disable: 4055) /* type cast' : from data pointer 'void *' to
function pointer
'void *(__cdecl *)(char *,int ) */
#pragma warning (disable: 4701) /* local variable may be used without having
been initialized */
#pragma warning (disable: 4715) /* ToHour' : not all control paths return a
value */
#endif

240
config.guess vendored
View File

@@ -3,7 +3,7 @@
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
# Free Software Foundation, Inc. # Free Software Foundation, Inc.
timestamp='2001-04-20' timestamp='2001-09-04'
# This file is free software; you can redistribute it and/or modify it # This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by # under the terms of the GNU General Public License as published by
@@ -52,7 +52,7 @@ version="\
GNU config.guess ($timestamp) GNU config.guess ($timestamp)
Originally written by Per Bothner. Originally written by Per Bothner.
Copyright (C) 1992, 93, 94, 95, 96, 97, 98, 99, 2000 Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
Free Software Foundation, Inc. Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO This is free software; see the source for copying conditions. There is NO
@@ -95,25 +95,25 @@ trap 'rm -f $dummy.c $dummy.o $dummy.rel $dummy; exit 1' 1 2 15
# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still # Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
# use `HOST_CC' if defined, but it is deprecated. # use `HOST_CC' if defined, but it is deprecated.
case $CC_FOR_BUILD,$HOST_CC,$CC in set_cc_for_build='case $CC_FOR_BUILD,$HOST_CC,$CC in
,,) echo "int dummy(){}" > $dummy.c ,,) echo "int dummy(){}" > $dummy.c ;
for c in cc gcc c89 ; do for c in cc gcc c89 ; do
($c $dummy.c -c -o $dummy.o) >/dev/null 2>&1 ($c $dummy.c -c -o $dummy.o) >/dev/null 2>&1 ;
if test $? = 0 ; then if test $? = 0 ; then
CC_FOR_BUILD="$c"; break CC_FOR_BUILD="$c"; break ;
fi fi ;
done done ;
rm -f $dummy.c $dummy.o $dummy.rel rm -f $dummy.c $dummy.o $dummy.rel ;
if test x"$CC_FOR_BUILD" = x ; then if test x"$CC_FOR_BUILD" = x ; then
CC_FOR_BUILD=no_compiler_found CC_FOR_BUILD=no_compiler_found ;
fi fi
;; ;;
,,*) CC_FOR_BUILD=$CC ;; ,,*) CC_FOR_BUILD=$CC ;;
,*,*) CC_FOR_BUILD=$HOST_CC ;; ,*,*) CC_FOR_BUILD=$HOST_CC ;;
esac esac'
# This is needed to find uname on a Pyramid OSx when run in the BSD universe. # This is needed to find uname on a Pyramid OSx when run in the BSD universe.
# (ghazi@noc.rutgers.edu 8/24/94.) # (ghazi@noc.rutgers.edu 1994-08-24)
if (test -f /.attbin/uname) >/dev/null 2>&1 ; then if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
PATH=$PATH:/.attbin ; export PATH PATH=$PATH:/.attbin ; export PATH
fi fi
@@ -150,6 +150,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
# to ELF recently, or will in the future. # to ELF recently, or will in the future.
case "${UNAME_MACHINE}" in case "${UNAME_MACHINE}" in
i386|sparc|amiga|arm*|hp300|mvme68k|vax|atari|luna68k|mac68k|news68k|next68k|pc532|sun3*|x68k) i386|sparc|amiga|arm*|hp300|mvme68k|vax|atari|luna68k|mac68k|news68k|next68k|pc532|sun3*|x68k)
eval $set_cc_for_build
if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
| grep __ELF__ >/dev/null | grep __ELF__ >/dev/null
then then
@@ -204,6 +205,7 @@ main:
jsr \$26,exit jsr \$26,exit
.end main .end main
EOF EOF
eval $set_cc_for_build
$CC_FOR_BUILD $dummy.s -o $dummy 2>/dev/null $CC_FOR_BUILD $dummy.s -o $dummy 2>/dev/null
if test "$?" = 0 ; then if test "$?" = 0 ; then
case `./$dummy` in case `./$dummy` in
@@ -225,6 +227,9 @@ EOF
2-307) 2-307)
UNAME_MACHINE="alphaev67" UNAME_MACHINE="alphaev67"
;; ;;
2-1307)
UNAME_MACHINE="alphaev68"
;;
esac esac
fi fi
rm -f $dummy.s $dummy rm -f $dummy.s $dummy
@@ -328,6 +333,9 @@ EOF
aushp:SunOS:*:*) aushp:SunOS:*:*)
echo sparc-auspex-sunos${UNAME_RELEASE} echo sparc-auspex-sunos${UNAME_RELEASE}
exit 0 ;; exit 0 ;;
sparc*:NetBSD:*)
echo `uname -p`-unknown-netbsd${UNAME_RELEASE}
exit 0 ;;
atari*:OpenBSD:*:*) atari*:OpenBSD:*:*)
echo m68k-unknown-openbsd${UNAME_RELEASE} echo m68k-unknown-openbsd${UNAME_RELEASE}
exit 0 ;; exit 0 ;;
@@ -385,6 +393,7 @@ EOF
echo clipper-intergraph-clix${UNAME_RELEASE} echo clipper-intergraph-clix${UNAME_RELEASE}
exit 0 ;; exit 0 ;;
mips:*:*:UMIPS | mips:*:*:RISCos) mips:*:*:UMIPS | mips:*:*:RISCos)
eval $set_cc_for_build
sed 's/^ //' << EOF >$dummy.c sed 's/^ //' << EOF >$dummy.c
#ifdef __cplusplus #ifdef __cplusplus
#include <stdio.h> /* for printf() prototype */ #include <stdio.h> /* for printf() prototype */
@@ -475,6 +484,7 @@ EOF
exit 0 ;; exit 0 ;;
*:AIX:2:3) *:AIX:2:3)
if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
eval $set_cc_for_build
sed 's/^ //' << EOF >$dummy.c sed 's/^ //' << EOF >$dummy.c
#include <sys/systemcfg.h> #include <sys/systemcfg.h>
@@ -553,6 +563,7 @@ EOF
fi ;; fi ;;
esac esac
if [ "${HP_ARCH}" = "" ]; then if [ "${HP_ARCH}" = "" ]; then
eval $set_cc_for_build
sed 's/^ //' << EOF >$dummy.c sed 's/^ //' << EOF >$dummy.c
#define _HPUX_SOURCE #define _HPUX_SOURCE
@@ -586,9 +597,9 @@ EOF
exit (0); exit (0);
} }
EOF EOF
(CCOPTS= $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null ) && HP_ARCH=`./$dummy` (CCOPTS= $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null ) && HP_ARCH=`./$dummy`
if test -z "$HP_ARCH"; then HP_ARCH=hppa; fi if test -z "$HP_ARCH"; then HP_ARCH=hppa; fi
rm -f $dummy.c $dummy rm -f $dummy.c $dummy
fi ;; fi ;;
esac esac
echo ${HP_ARCH}-hp-hpux${HPUX_REV} echo ${HP_ARCH}-hp-hpux${HPUX_REV}
@@ -598,6 +609,7 @@ EOF
echo ia64-hp-hpux${HPUX_REV} echo ia64-hp-hpux${HPUX_REV}
exit 0 ;; exit 0 ;;
3050*:HI-UX:*:*) 3050*:HI-UX:*:*)
eval $set_cc_for_build
sed 's/^ //' << EOF >$dummy.c sed 's/^ //' << EOF >$dummy.c
#include <unistd.h> #include <unistd.h>
int int
@@ -633,7 +645,7 @@ EOF
9000/8??:4.3bsd:*:*) 9000/8??:4.3bsd:*:*)
echo hppa1.0-hp-bsd echo hppa1.0-hp-bsd
exit 0 ;; exit 0 ;;
*9??*:MPE/iX:*:*) *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
echo hppa1.0-hp-mpeix echo hppa1.0-hp-mpeix
exit 0 ;; exit 0 ;;
hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
@@ -677,12 +689,13 @@ EOF
echo xmp-cray-unicos echo xmp-cray-unicos
exit 0 ;; exit 0 ;;
CRAY*Y-MP:*:*:*) CRAY*Y-MP:*:*:*)
echo ymp-cray-unicos${UNAME_RELEASE} echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
exit 0 ;; exit 0 ;;
CRAY*[A-Z]90:*:*:*) CRAY*[A-Z]90:*:*:*)
echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
| sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
-e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
-e 's/\.[^.]*$/.X/'
exit 0 ;; exit 0 ;;
CRAY*TS:*:*:*) CRAY*TS:*:*:*)
echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
@@ -763,97 +776,29 @@ EOF
echo ${UNAME_MACHINE}-unknown-linux-gnu echo ${UNAME_MACHINE}-unknown-linux-gnu
exit 0 ;; exit 0 ;;
mips:Linux:*:*) mips:Linux:*:*)
cat >$dummy.c <<EOF case `sed -n '/^byte/s/^.*: \(.*\) endian/\1/p' < /proc/cpuinfo` in
#ifdef __cplusplus big) echo mips-unknown-linux-gnu && exit 0 ;;
#include <stdio.h> /* for printf() prototype */ little) echo mipsel-unknown-linux-gnu && exit 0 ;;
int main (int argc, char *argv[]) { esac
#else
int main (argc, argv) int argc; char *argv[]; {
#endif
#ifdef __MIPSEB__
printf ("%s-unknown-linux-gnu\n", argv[1]);
#endif
#ifdef __MIPSEL__
printf ("%sel-unknown-linux-gnu\n", argv[1]);
#endif
return 0;
}
EOF
$CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy "${UNAME_MACHINE}" && rm -f $dummy.c $dummy && exit 0
rm -f $dummy.c $dummy
;; ;;
ppc:Linux:*:*) ppc:Linux:*:*)
# Determine Lib Version echo powerpc-unknown-linux-gnu
cat >$dummy.c <<EOF exit 0 ;;
#include <features.h> ppc64:Linux:*:*)
#if defined(__GLIBC__) echo powerpc64-unknown-linux-gnu
extern char __libc_version[];
extern char __libc_release[];
#endif
main(argc, argv)
int argc;
char *argv[];
{
#if defined(__GLIBC__)
printf("%s %s\n", __libc_version, __libc_release);
#else
printf("unknown\n");
#endif
return 0;
}
EOF
LIBC=""
$CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null
if test "$?" = 0 ; then
./$dummy | grep 1\.99 > /dev/null
if test "$?" = 0 ; then LIBC="libc1" ; fi
fi
rm -f $dummy.c $dummy
echo powerpc-unknown-linux-gnu${LIBC}
exit 0 ;; exit 0 ;;
alpha:Linux:*:*) alpha:Linux:*:*)
cat <<EOF >$dummy.s case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
.data EV5) UNAME_MACHINE=alphaev5 ;;
\$Lformat: EV56) UNAME_MACHINE=alphaev56 ;;
.byte 37,100,45,37,120,10,0 # "%d-%x\n" PCA56) UNAME_MACHINE=alphapca56 ;;
.text PCA57) UNAME_MACHINE=alphapca56 ;;
.globl main EV6) UNAME_MACHINE=alphaev6 ;;
.align 4 EV67) UNAME_MACHINE=alphaev67 ;;
.ent main EV68*) UNAME_MACHINE=alphaev68 ;;
main: esac
.frame \$30,16,\$26,0 objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null
ldgp \$29,0(\$27) if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
.prologue 1
.long 0x47e03d80 # implver \$0
lda \$2,-1
.long 0x47e20c21 # amask \$2,\$1
lda \$16,\$Lformat
mov \$0,\$17
not \$1,\$18
jsr \$26,printf
ldgp \$29,0(\$26)
mov 0,\$16
jsr \$26,exit
.end main
EOF
LIBC=""
$CC_FOR_BUILD $dummy.s -o $dummy 2>/dev/null
if test "$?" = 0 ; then
case `./$dummy` in
0-0) UNAME_MACHINE="alpha" ;;
1-0) UNAME_MACHINE="alphaev5" ;;
1-1) UNAME_MACHINE="alphaev56" ;;
1-101) UNAME_MACHINE="alphapca56" ;;
2-303) UNAME_MACHINE="alphaev6" ;;
2-307) UNAME_MACHINE="alphaev67" ;;
esac
objdump --private-headers $dummy | \
grep ld.so.1 > /dev/null
if test "$?" = 0 ; then
LIBC="libc1"
fi
fi
rm -f $dummy.s $dummy
echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
exit 0 ;; exit 0 ;;
parisc:Linux:*:* | hppa:Linux:*:*) parisc:Linux:*:* | hppa:Linux:*:*)
@@ -883,40 +828,30 @@ EOF
# The BFD linker knows what the default object file format is, so # The BFD linker knows what the default object file format is, so
# first see if it will tell us. cd to the root directory to prevent # first see if it will tell us. cd to the root directory to prevent
# problems with other programs or directories called `ld' in the path. # problems with other programs or directories called `ld' in the path.
ld_supported_emulations=`cd /; ld --help 2>&1 \ ld_supported_targets=`cd /; ld --help 2>&1 \
| sed -ne '/supported emulations:/!d | sed -ne '/supported targets:/!d
s/[ ][ ]*/ /g s/[ ][ ]*/ /g
s/.*supported emulations: *// s/.*supported targets: *//
s/ .*// s/ .*//
p'` p'`
case "$ld_supported_emulations" in case "$ld_supported_targets" in
i*86linux) elf32-i386)
echo "${UNAME_MACHINE}-pc-linux-gnuaout"
exit 0
;;
elf_i*86)
TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu" TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu"
;; ;;
i*86coff) a.out-i386-linux)
echo "${UNAME_MACHINE}-pc-linux-gnuaout"
exit 0 ;;
coff-i386)
echo "${UNAME_MACHINE}-pc-linux-gnucoff" echo "${UNAME_MACHINE}-pc-linux-gnucoff"
exit 0 exit 0 ;;
;; "")
esac # Either a pre-BFD a.out linker (linux-gnuoldld) or
# Either a pre-BFD a.out linker (linux-gnuoldld) # one that does not give us useful --help.
# or one that does not give us useful --help. echo "${UNAME_MACHINE}-pc-linux-gnuoldld"
# GCC wants to distinguish between linux-gnuoldld and linux-gnuaout. exit 0 ;;
# If ld does not provide *any* "supported emulations:"
# that means it is gnuoldld.
test -z "$ld_supported_emulations" && echo "${UNAME_MACHINE}-pc-linux-gnuoldld" && exit 0
case "${UNAME_MACHINE}" in
i*86)
VENDOR=pc;
;;
*)
VENDOR=unknown;
;;
esac esac
# Determine whether the default compiler is a.out or elf # Determine whether the default compiler is a.out or elf
eval $set_cc_for_build
cat >$dummy.c <<EOF cat >$dummy.c <<EOF
#include <features.h> #include <features.h>
#ifdef __cplusplus #ifdef __cplusplus
@@ -928,15 +863,15 @@ EOF
#ifdef __ELF__ #ifdef __ELF__
# ifdef __GLIBC__ # ifdef __GLIBC__
# if __GLIBC__ >= 2 # if __GLIBC__ >= 2
printf ("%s-${VENDOR}-linux-gnu\n", argv[1]); printf ("%s-pc-linux-gnu\n", argv[1]);
# else # else
printf ("%s-${VENDOR}-linux-gnulibc1\n", argv[1]); printf ("%s-pc-linux-gnulibc1\n", argv[1]);
# endif # endif
# else # else
printf ("%s-${VENDOR}-linux-gnulibc1\n", argv[1]); printf ("%s-pc-linux-gnulibc1\n", argv[1]);
# endif # endif
#else #else
printf ("%s-${VENDOR}-linux-gnuaout\n", argv[1]); printf ("%s-pc-linux-gnuaout\n", argv[1]);
#endif #endif
return 0; return 0;
} }
@@ -945,9 +880,10 @@ EOF
rm -f $dummy.c $dummy rm -f $dummy.c $dummy
test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0 test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0
;; ;;
# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. earlier versions
# are messed up and put the nodename in both sysname and nodename.
i*86:DYNIX/ptx:4*:*) i*86:DYNIX/ptx:4*:*)
# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
# earlier versions are messed up and put the nodename in both
# sysname and nodename.
echo i386-sequent-sysv4 echo i386-sequent-sysv4
exit 0 ;; exit 0 ;;
i*86:UNIX_SV:4.2MP:2.*) i*86:UNIX_SV:4.2MP:2.*)
@@ -966,14 +902,13 @@ EOF
echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
fi fi
exit 0 ;; exit 0 ;;
i*86:*:5:7*) i*86:*:5:[78]*)
# Fixed at (any) Pentium or better case `/bin/uname -X | grep "^Machine"` in
UNAME_MACHINE=i586 *486*) UNAME_MACHINE=i486 ;;
if [ ${UNAME_SYSTEM} = "UnixWare" ] ; then *Pentium) UNAME_MACHINE=i586 ;;
echo ${UNAME_MACHINE}-sco-sysv${UNAME_RELEASE}uw${UNAME_VERSION} *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
else esac
echo ${UNAME_MACHINE}-pc-sysv${UNAME_RELEASE} echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
fi
exit 0 ;; exit 0 ;;
i*86:*:3.2:*) i*86:*:3.2:*)
if test -f /usr/options/cb.name; then if test -f /usr/options/cb.name; then
@@ -1067,8 +1002,8 @@ EOF
echo ns32k-sni-sysv echo ns32k-sni-sysv
fi fi
exit 0 ;; exit 0 ;;
PENTIUM:CPunix:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
# says <Richard.M.Bartel@ccMail.Census.GOV> # says <Richard.M.Bartel@ccMail.Census.GOV>
echo i586-unisys-sysv4 echo i586-unisys-sysv4
exit 0 ;; exit 0 ;;
*:UNIX_System_V:4*:FTX*) *:UNIX_System_V:4*:FTX*)
@@ -1080,6 +1015,10 @@ EOF
# From seanf@swdc.stratus.com. # From seanf@swdc.stratus.com.
echo i860-stratus-sysv4 echo i860-stratus-sysv4
exit 0 ;; exit 0 ;;
*:VOS:*:*)
# From Paul.Green@stratus.com.
echo hppa1.1-stratus-vos
exit 0 ;;
mc68*:A/UX:*:*) mc68*:A/UX:*:*)
echo m68k-apple-aux${UNAME_RELEASE} echo m68k-apple-aux${UNAME_RELEASE}
exit 0 ;; exit 0 ;;
@@ -1172,11 +1111,18 @@ EOF
*:ITS:*:*) *:ITS:*:*)
echo pdp10-unknown-its echo pdp10-unknown-its
exit 0 ;; exit 0 ;;
i*86:XTS-300:*:STOP)
echo ${UNAME_MACHINE}-unknown-stop
exit 0 ;;
i*86:atheos:*:*)
echo ${UNAME_MACHINE}-unknown-atheos
exit 0 ;;
esac esac
#echo '(No uname command or uname output not recognized.)' 1>&2 #echo '(No uname command or uname output not recognized.)' 1>&2
#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 #echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
eval $set_cc_for_build
cat >$dummy.c <<EOF cat >$dummy.c <<EOF
#ifdef _SEQUENT_ #ifdef _SEQUENT_
# include <sys/types.h> # include <sys/types.h>

149
config.sub vendored
View File

@@ -3,7 +3,7 @@
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
# Free Software Foundation, Inc. # Free Software Foundation, Inc.
timestamp='2001-04-20' timestamp='2001-09-07'
# This file is (in principle) common to ALL GNU software. # This file is (in principle) common to ALL GNU software.
# The presence of a machine in this file suggests that SOME GNU software # The presence of a machine in this file suggests that SOME GNU software
@@ -117,7 +117,7 @@ esac
# Here we must recognize all the valid KERNEL-OS combinations. # Here we must recognize all the valid KERNEL-OS combinations.
maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
case $maybe_os in case $maybe_os in
nto-qnx* | linux-gnu* | storm-chaos* | os2-emx*) nto-qnx* | linux-gnu* | storm-chaos* | os2-emx* | windows32-*)
os=-$maybe_os os=-$maybe_os
basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
;; ;;
@@ -157,6 +157,14 @@ case $os in
os=-vxworks os=-vxworks
basic_machine=$1 basic_machine=$1
;; ;;
-chorusos*)
os=-chorusos
basic_machine=$1
;;
-chorusrdb)
os=-chorusrdb
basic_machine=$1
;;
-hiux*) -hiux*)
os=-hiuxwe2 os=-hiuxwe2
;; ;;
@@ -215,26 +223,36 @@ esac
case $basic_machine in case $basic_machine in
# Recognize the basic CPU types without company name. # Recognize the basic CPU types without company name.
# Some are omitted here because they have special meanings below. # Some are omitted here because they have special meanings below.
tahoe | i860 | ia64 | m32r | m68k | m68000 | m88k | ns32k | arc \ 1750a | 580 \
| arm | arme[lb] | arm[bl]e | armv[2345] | armv[345][lb] | strongarm | xscale \ | a29k \
| pyramid | mn10200 | mn10300 | tron | a29k \ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
| 580 | i960 | h8300 \ | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \
| x86 | ppcbe | mipsbe | mipsle | shbe | shle \ | c4x | clipper \
| hppa | hppa1.0 | hppa1.1 | hppa2.0 | hppa2.0w | hppa2.0n \ | d10v | d30v | dsp16xx \
| hppa64 \ | fr30 \
| alpha | alphaev[4-8] | alphaev56 | alphapca5[67] \ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
| alphaev6[78] \ | i370 | i860 | i960 | ia64 \
| we32k | ns16k | clipper | i370 | sh | sh[34] \ | m32r | m68000 | m68k | m88k | mcore \
| powerpc | powerpcle \ | mips16 | mips64 | mips64el | mips64orion | mips64orionel \
| 1750a | dsp16xx | pdp10 | pdp11 \ | mips64vr4100 | mips64vr4100el | mips64vr4300 \
| mips16 | mips64 | mipsel | mips64el \ | mips64vr4300el | mips64vr5000 | mips64vr5000el \
| mips64orion | mips64orionel | mipstx39 | mipstx39el \ | mipsbe | mipseb | mipsel | mipsle | mipstx39 | mipstx39el \
| mips64vr4300 | mips64vr4300el | mips64vr4100 | mips64vr4100el \ | mipsisa32 \
| mips64vr5000 | miprs64vr5000el | mcore | s390 | s390x \ | mn10200 | mn10300 \
| sparc | sparclet | sparclite | sparc64 | sparcv9 | sparcv9b \ | ns16k | ns32k \
| v850 | c4x \ | openrisc \
| thumb | d10v | d30v | fr30 | avr | openrisc | tic80 \ | pdp10 | pdp11 | pj | pjl \
| pj | pjl | h8500) | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
| pyramid \
| s390 | s390x \
| sh | sh[34] | sh[34]eb | shbe | shle \
| sparc | sparc64 | sparclet | sparclite | sparcv9 | sparcv9b \
| stormy16 | strongarm \
| tahoe | thumb | tic80 | tron \
| v850 \
| we32k \
| x86 | xscale \
| z8k)
basic_machine=$basic_machine-unknown basic_machine=$basic_machine-unknown
;; ;;
m6811 | m68hc11 | m6812 | m68hc12) m6811 | m68hc11 | m6812 | m68hc12)
@@ -242,7 +260,7 @@ case $basic_machine in
basic_machine=$basic_machine-unknown basic_machine=$basic_machine-unknown
os=-none os=-none
;; ;;
m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | z8k | v70 | w65) m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
;; ;;
# We use `pc' rather than `unknown' # We use `pc' rather than `unknown'
@@ -257,31 +275,43 @@ case $basic_machine in
exit 1 exit 1
;; ;;
# Recognize the basic CPU types with company name. # Recognize the basic CPU types with company name.
# FIXME: clean up the formatting here. 580-* \
vax-* | tahoe-* | i*86-* | i860-* | ia64-* | m32r-* | m68k-* | m68000-* \ | a29k-* \
| m88k-* | sparc-* | ns32k-* | fx80-* | arc-* | c[123]* \ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
| arm-* | armbe-* | armle-* | armv*-* | strongarm-* | xscale-* \ | alphapca5[67]-* | arc-* \
| mips-* | pyramid-* | tron-* | a29k-* | romp-* | rs6000-* \ | arm-* | armbe-* | armle-* | armv*-* \
| power-* | none-* | 580-* | cray2-* | h8300-* | h8500-* | i960-* \ | bs2000-* \
| xmp-* | ymp-* \ | c[123]* | c30-* | [cjt]90-* | c54x-* \
| x86-* | ppcbe-* | mipsbe-* | mipsle-* | shbe-* | shle-* \ | clipper-* | cray2-* | cydra-* \
| hppa-* | hppa1.0-* | hppa1.1-* | hppa2.0-* | hppa2.0w-* \ | d10v-* | d30v-* \
| hppa2.0n-* | hppa64-* \ | elxsi-* \
| alpha-* | alphaev[4-8]-* | alphaev56-* | alphapca5[67]-* \ | f30[01]-* | f700-* | fr30-* | fx80-* \
| alphaev6[78]-* \ | h8300-* | h8500-* \
| we32k-* | cydra-* | ns16k-* | pn-* | np1-* | xps100-* \ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
| clipper-* | orion-* \ | i*86-* | i860-* | i960-* | ia64-* \
| sparclite-* | pdp10-* | pdp11-* | sh-* | powerpc-* | powerpcle-* \ | m32r-* \
| sparc64-* | sparcv9-* | sparcv9b-* | sparc86x-* \ | m68000-* | m680[01234]0-* | m68360-* | m683?2-* | m68k-* \
| mips16-* | mips64-* | mipsel-* \ | m88110-* | m88k-* | mcore-* \
| mips64el-* | mips64orion-* | mips64orionel-* \ | mips-* | mips16-* | mips64-* | mips64el-* | mips64orion-* \
| mips64vr4100-* | mips64vr4100el-* | mips64vr4300-* | mips64vr4300el-* \ | mips64orionel-* | mips64vr4100-* | mips64vr4100el-* \
| mipstx39-* | mipstx39el-* | mcore-* \ | mips64vr4300-* | mips64vr4300el-* | mipsbe-* | mipseb-* \
| f30[01]-* | f700-* | s390-* | s390x-* | sv1-* | t3e-* \ | mipsle-* | mipsel-* | mipstx39-* | mipstx39el-* \
| [cjt]90-* \ | none-* | np1-* | ns16k-* | ns32k-* \
| m88110-* | m680[01234]0-* | m683?2-* | m68360-* | z8k-* | d10v-* \ | orion-* \
| thumb-* | v850-* | d30v-* | tic30-* | tic80-* | c30-* | fr30-* \ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
| bs2000-* | tic54x-* | c54x-* | x86_64-* | pj-* | pjl-*) | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
| pyramid-* \
| romp-* | rs6000-* \
| s390-* | s390x-* \
| sh-* | sh[34]-* | sh[34]eb-* | shbe-* | shle-* \
| sparc-* | sparc64-* | sparc86x-* | sparclite-* \
| sparcv9-* | sparcv9b-* | stormy16-* | strongarm-* | sv1-* \
| t3e-* | tahoe-* | thumb-* | tic30-* | tic54x-* | tic80-* | tron-* \
| v850-* | vax-* \
| we32k-* \
| x86-* | x86_64-* | xmp-* | xps100-* | xscale-* \
| ymp-* \
| z8k-*)
;; ;;
# Recognize the various machine names and aliases which stand # Recognize the various machine names and aliases which stand
# for a CPU type and a company and sometimes even an OS. # for a CPU type and a company and sometimes even an OS.
@@ -727,6 +757,16 @@ case $basic_machine in
ppcle-* | powerpclittle-*) ppcle-* | powerpclittle-*)
basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
;; ;;
ppc64) basic_machine=powerpc64-unknown
;;
ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
ppc64le | powerpc64little | ppc64-le | powerpc64-little)
basic_machine=powerpc64le-unknown
;;
ppc64le-* | powerpc64little-*)
basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
ps2) ps2)
basic_machine=i386-ibm basic_machine=i386-ibm
;; ;;
@@ -881,6 +921,10 @@ case $basic_machine in
basic_machine=hppa1.1-winbond basic_machine=hppa1.1-winbond
os=-proelf os=-proelf
;; ;;
windows32)
basic_machine=i386-pc
os=-windows32-msvcrt
;;
xmp) xmp)
basic_machine=xmp-cray basic_machine=xmp-cray
os=-unicos os=-unicos
@@ -934,7 +978,7 @@ case $basic_machine in
we32k) we32k)
basic_machine=we32k-att basic_machine=we32k-att
;; ;;
sh3 | sh4) sh3 | sh4 | sh3eb | sh4eb)
basic_machine=sh-unknown basic_machine=sh-unknown
;; ;;
sparc | sparcv9 | sparcv9b) sparc | sparcv9 | sparcv9b)
@@ -1018,11 +1062,13 @@ case $os in
| -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
| -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
| -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
| -chorusos* | -chorusrdb* \
| -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
| -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \ | -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \
| -interix* | -uwin* | -rhapsody* | -darwin* | -opened* \ | -interix* | -uwin* | -rhapsody* | -darwin* | -opened* \
| -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
| -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* | -os2*) | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
| -os2* | -vos*)
# Remember, each alternative MUST END IN *, to match a version number. # Remember, each alternative MUST END IN *, to match a version number.
;; ;;
-qnx*) -qnx*)
@@ -1346,6 +1392,9 @@ case $basic_machine in
-*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
vendor=atari vendor=atari
;; ;;
-vos*)
vendor=stratus
;;
esac esac
basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
;; ;;

View File

@@ -1,9 +1,16 @@
dnl $Id$ dnl $Id$
dnl Process this file with autoconf to produce a configure script. dnl Process this file with autoconf to produce a configure script.
dnl Ensure that this file is processed with autoconf 2.50 or newer
dnl Don't even think about removing this check!
AC_PREREQ(2.50)
dnl First some basic init macros
AC_INIT AC_INIT
AC_CONFIG_SRCDIR([lib/urldata.h]) AC_CONFIG_SRCDIR([lib/urldata.h])
AM_CONFIG_HEADER(config.h src/config.h) AM_CONFIG_HEADER(config.h src/config.h)
dnl figure out the libcurl version
VERSION=`sed -ne 's/^#define LIBCURL_VERSION "\(.*\)"/\1/p' ${srcdir}/include/curl/curl.h` VERSION=`sed -ne 's/^#define LIBCURL_VERSION "\(.*\)"/\1/p' ${srcdir}/include/curl/curl.h`
AM_INIT_AUTOMAKE(curl,$VERSION) AM_INIT_AUTOMAKE(curl,$VERSION)
@@ -38,6 +45,10 @@ AC_PROG_CC
dnl check for how to do large files dnl check for how to do large files
AC_SYS_LARGEFILE AC_SYS_LARGEFILE
dnl check for cygwin stuff
AC_LIBTOOL_WIN32_DLL
dnl libtool setup
AM_PROG_LIBTOOL AM_PROG_LIBTOOL
dnl The install stuff has already been taken care of by the automake stuff dnl The install stuff has already been taken care of by the automake stuff
@@ -158,6 +169,24 @@ AC_CHECK_FUNC(gethostname, , AC_CHECK_LIB(ucb, gethostname))
dnl dl lib? dnl dl lib?
AC_CHECK_FUNC(dlclose, , AC_CHECK_LIB(dl, dlopen)) AC_CHECK_FUNC(dlclose, , AC_CHECK_LIB(dl, dlopen))
dnl **********************************************************************
dnl Check how non-blocking sockets are set
dnl **********************************************************************
AC_ARG_ENABLE(nonblocking,
[ --enable-nonblocking Makes the script detect how to do it
--disable-nonblocking Makes the script disable non-blocking sockets],
[
if test "$enableval" = "no" ; then
AC_MSG_WARN([non-blocking sockets disabled])
AC_DEFINE(HAVE_DISABLED_NONBLOCKING)
else
CURL_CHECK_NONBLOCKING_SOCKET
fi
],
[
CURL_CHECK_NONBLOCKING_SOCKET
])
dnl ********************************************************************** dnl **********************************************************************
dnl Check for the random seed preferences dnl Check for the random seed preferences
dnl ********************************************************************** dnl **********************************************************************
@@ -305,6 +334,8 @@ else
case "$OPT_SSL" in case "$OPT_SSL" in
yes) yes)
EXTRA_SSL=/usr/local/ssl ;; EXTRA_SSL=/usr/local/ssl ;;
off)
EXTRA_SSL= ;;
*) *)
dnl check the given spot right away! dnl check the given spot right away!
EXTRA_SSL=$OPT_SSL EXTRA_SSL=$OPT_SSL
@@ -426,9 +457,6 @@ then
Set to explicitly specify we don't want to use thread-safe functions) Set to explicitly specify we don't want to use thread-safe functions)
else else
dnl check that 'localhost' resolves first
CURL_CHECK_WORKING_RESOLVER
dnl dig around for gethostbyname_r() dnl dig around for gethostbyname_r()
CURL_CHECK_GETHOSTBYNAME_R() CURL_CHECK_GETHOSTBYNAME_R()
@@ -475,7 +503,9 @@ AC_CHECK_HEADERS( \
winsock.h \ winsock.h \
time.h \ time.h \
io.h \ io.h \
pwd.h pwd.h \
utime.h \
sys/utime.h
) )
dnl Check for libz header dnl Check for libz header
@@ -514,7 +544,6 @@ AC_CHECK_FUNCS( socket \
strcmpi \ strcmpi \
gethostname \ gethostname \
gethostbyaddr \ gethostbyaddr \
getservbyname \
gettimeofday \ gettimeofday \
inet_addr \ inet_addr \
inet_ntoa \ inet_ntoa \
@@ -529,7 +558,8 @@ AC_CHECK_FUNCS( socket \
strlcat \ strlcat \
getpwuid \ getpwuid \
geteuid \ geteuid \
dlopen dlopen \
utime
) )
dnl removed 'getpass' check on October 26, 2000 dnl removed 'getpass' check on October 26, 2000
@@ -566,15 +596,12 @@ AC_CONFIG_FILES([Makefile \
tests/data/Makefile \ tests/data/Makefile \
packages/Makefile \ packages/Makefile \
packages/Win32/Makefile \ packages/Win32/Makefile \
packages/Win32/cygwin/Makefile \
packages/Linux/Makefile \ packages/Linux/Makefile \
packages/Linux/RPM/Makefile \ packages/Linux/RPM/Makefile \
packages/Linux/RPM/curl.spec \ packages/Linux/RPM/curl.spec \
packages/Linux/RPM/curl-ssl.spec \ packages/Linux/RPM/curl-ssl.spec \
packages/Solaris/Makefile \ packages/Solaris/Makefile \
perl/Makefile \
perl/Curl_easy/Makefile \
php/Makefile \
php/examples/Makefile \
curl-config curl-config
]) ])
AC_OUTPUT AC_OUTPUT

21
curl-mode.el Normal file
View File

@@ -0,0 +1,21 @@
;;;; Emacs Lisp help for writing curl code. ;;;;
;;; In C files, put something like this to load this file automatically:
;;
;; /* -----------------------------------------------------------------
;; * local variables:
;; * eval: (load-file "../curl-mode.el")
;; * end:
;; */
;;
;; (note: make sure to get the path right in the argument to load-file).
;;; The curl hacker's C conventions
;;; we use intent-level 2
(setq c-basic-offset 2)
;;; never ever use tabs to indent!
(setq indent-tabs-mode nil)
;;; I like this, stolen from Subversion! ;-)
(setq angry-mob-with-torches-and-pitchforks t)

View File

@@ -10,6 +10,12 @@ To Think About When Contributing Source Code
in mind when you decide to write a contribution to the project. This concerns in mind when you decide to write a contribution to the project. This concerns
new features as well as corrections to existing flaws or bugs. new features as well as corrections to existing flaws or bugs.
Join the Community
Skip over to http://curl.haxx.se/mail/ and join the appropriate mailing
list(s). Read up on details before you post questions. Read this file before
you start sending patches!
The License Issue The License Issue
When contributing with code, you agree to put your changes and new code under When contributing with code, you agree to put your changes and new code under
@@ -21,6 +27,12 @@ The License Issue
GPL (as we don't want the GPL virus to attack users of libcurl) but they must GPL (as we don't want the GPL virus to attack users of libcurl) but they must
use "GPL compatible" licenses. use "GPL compatible" licenses.
What To Read
Source code, the man pages, the INTERALS document, the TODO, the most recent
CHANGES. Just lurking on the libcurl mailing list is gonna give you a lot of
insights on what's going on right now.
Naming Naming
Try using a non-confusing naming scheme for your new functions and variable Try using a non-confusing naming scheme for your new functions and variable
@@ -87,7 +99,9 @@ Write Access to CVS Repository
If you are a frequent contributor, or have another good reason, you can of If you are a frequent contributor, or have another good reason, you can of
course get write access to the CVS repository and then you'll be able to course get write access to the CVS repository and then you'll be able to
check-in all your changes straight into the CVS tree instead of sending all check-in all your changes straight into the CVS tree instead of sending all
changes by mail as patches. Just ask if this is what you'd want. changes by mail as patches. Just ask if this is what you'd want. You will be
required to have posted a few quality patches first, before you can be
granted write access.
Test Cases Test Cases

View File

@@ -1,4 +1,4 @@
Updated: August 7, 2001 (http://curl.haxx.se/docs/faq.shtml) Updated: November 1, 2001 (http://curl.haxx.se/docs/faq.shtml)
_ _ ____ _ _ _ ____ _
___| | | | _ \| | ___| | | | _ \| |
/ __| | | | |_) | | / __| | | | |_) | |
@@ -36,6 +36,7 @@ FAQ
3.9 How do I use curl in PHP, Perl, Tcl, Ruby or Java? 3.9 How do I use curl in PHP, Perl, Tcl, Ruby or Java?
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 fails?
4. Running Problems 4. Running Problems
4.1 Problems connecting to SSL servers. 4.1 Problems connecting to SSL servers.
@@ -81,7 +82,7 @@ FAQ
fact it can also be pronounced 'see URL' also helped. fact it can also be pronounced 'see URL' also helped.
Curl supports a range of common Internet protocols, currently including Curl supports a range of common Internet protocols, currently including
HTTP, HTTPS, FTP, GOPHER, LDAP, DICT, TELNET and FILE. HTTP, HTTPS, FTP, FTPS, GOPHER, LDAP, DICT, TELNET and FILE.
We spell it cURL or just curl. We pronounce it with an initial k sound: We spell it cURL or just curl. We pronounce it with an initial k sound:
[kurl]. [kurl].
@@ -96,10 +97,9 @@ FAQ
1.3 What is cURL not? 1.3 What is cURL not?
Curl is *not*, I repeat, *not* a wget clone even though that is a very Curl is *not* a wget clone even though that is a very common misconception.
common misconception. Never, during curl's development, have I intended curl Never, during curl's development, have we intended curl to replace wget or
to replace wget or compete on its market. Curl is targeted at single-shot compete on its market. Curl is targeted at single-shot file transfers.
file transfers.
Curl is not a web site mirroring program. If you wanna use curl to mirror Curl is not a web site mirroring program. If you wanna use curl to mirror
something: fine, go ahead and write a script that wraps around curl to make something: fine, go ahead and write a script that wraps around curl to make
@@ -134,7 +134,7 @@ FAQ
* We focus on protocol related issues and improvements. If you wanna do more * We focus on protocol related issues and improvements. If you wanna do more
magic with the supported protocols than curl currently does, chances are magic with the supported protocols than curl currently does, chances are
big I will agree. If you wanna add more protocols, I may very well big we will agree. If you wanna add more protocols, we may very well
agree. agree.
* If you want someone else to make all the work while you wait for us to * If you want someone else to make all the work while you wait for us to
@@ -375,6 +375,18 @@ FAQ
curl -d "datatopost" -H "Content-Type: text/xml" [URL] curl -d "datatopost" -H "Content-Type: text/xml" [URL]
3.12 Why do FTP specific features over HTTP proxy fail?
Because when you use a HTTP proxy, the protocol spoken on the network will
be HTTP, even if you specify a FTP URL. This effectively means that you
normally can't use FTP specific features such as ftp upload and ftp quote
etc.
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)
and is generally not available as proxy admins usuable disable tunneling to
other ports than 443 (which is used for HTTPS access through proxies).
4. Running Problems 4. Running Problems
4.1. Problems connecting to SSL servers. 4.1. Problems connecting to SSL servers.
@@ -467,9 +479,9 @@ FAQ
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
that curl has existed due to a timeout. There was no nice way for curl to that curl has exited due to a crash. This is a serious error, and we
abort from such a condition and that's why it got this undocumented appriciate a detailed bug report from you that describes how we could go
error. This should not occur in releases after 7.4.1. ahead and repeat this!
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?
@@ -573,13 +585,7 @@ FAQ
5.4 Does libcurl do Winsock initialization on win32 systems? 5.4 Does libcurl do Winsock initialization on win32 systems?
No. Yes (since 7.8.1) if told to in the curl_global_init() call.
On win32 systems, you need to init the winsock stuff manually, libcurl will
not do that for you. WSAStartup() and WSACleanup() should be used
accordingly. The reason for this is of course that a single application may
use several different libraries and parts, and there's no reason for every
single library to do this.
5.5 Does CURLOPT_FILE and CURLOPT_INFILE work on win32 ? 5.5 Does CURLOPT_FILE and CURLOPT_INFILE work on win32 ?

View File

@@ -8,9 +8,12 @@
Curl has been compiled and built on numerous different operating systems. Curl has been compiled and built on numerous different operating systems.
If you're using Windows (95/98/NT/ME/2000 or whatever), VMS, RISC OS or OS/2, Most systems build curl the same way (unix-style). Continue reading below for
you should continue reading from one the paragraphs further down. All other more details if you're one of them.
systems should be capable of being installed as described below.
If you're using Windows (95/98/NT/ME/2000/XP or similar), VMS, RISC OS or OS/2
or cross-compile, you should continue reading from one the paragraphs further
down.
UNIX UNIX
==== ====
@@ -325,13 +328,50 @@ VMS
13-jul-2001 13-jul-2001
N. Baggus N. Baggus
CROSS COMPILE
=============
(This section was graciously brought to us by Jim Duey, 23-oct-2001)
Download and unpack the cURL package. Version should be 7.9.1 or later.
'cd' to the new directory. (ie. curl-7.9.1-pre4)
Set environment variables to point to the cross-compile toolchain and call
configure with any options you need. Be sure and specify the '--host' and
'--build' parameters at configuration time. The following script is an
example of cross-compiling for the IBM 405GP PowerPC processor using the
toolchain from MonteVista for Hardhat Linux.
(begin script)
#! /bin/sh
export PATH=$PATH:/opt/hardhat/devkit/ppc/405/bin
export CPPFLAGS="-I/opt/hardhat/devkit/ppc/405/target/usr/include"
export AR=ppc_405-ar
export AS=ppc_405-as
export LD=ppc_405-ld
export RANLIB=ppc_405-ranlib
export CC=ppc_405-gcc
export NM=ppc_405-nm
configure --target=powerpc-hardhat-linux \
--host=powerpc-hardhat-linux \
--build=i586-pc-linux-gnu \
--prefix=/opt/hardhat/devkit/ppc/405/target/usr/local \
--exec-prefix=/usr/local
(end script)
The '--prefix' parameter specifies where cURL will be installed. If
'configure' completes successfully, do 'make' and 'make install' as usual.
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:
- Ultrix 4.3a
- SINIX-Z v5
- Alpha DEC OSF 4 - Alpha DEC OSF 4
- Alpha Digital UNIX v3.2 - Alpha Digital UNIX v3.2
- Alpha FreeBSD 4.1 - Alpha FreeBSD 4.1
@@ -344,9 +384,14 @@ PORTS
- PowerPC Darwin 1.0 - PowerPC Darwin 1.0
- PowerPC Linux - PowerPC Linux
- PowerPC Mac OS X - PowerPC Mac OS X
- SINIX-Z v5
- Sparc Linux - Sparc Linux
- Sparc Solaris 2.4, 2.5, 2.5.1, 2.6, 7, 8 - Sparc Solaris 2.4, 2.5, 2.5.1, 2.6, 7, 8
- Sparc SunOS 4.1.X - Sparc SunOS 4.1.X
- StrongARM (and other ARM) RISC OS 3.1, 4.02
- StrongARM Linux 2.4
- StrongARM NetBSD 1.4.1
- Ultrix 4.3a
- i386 BeOS - i386 BeOS
- i386 FreeBSD - i386 FreeBSD
- i386 Linux 1.3, 2.0, 2.2, 2.3, 2.4 - i386 Linux 1.3, 2.0, 2.2, 2.3, 2.4
@@ -359,8 +404,7 @@ PORTS
- ia64 Linux 2.3.99 - ia64 Linux 2.3.99
- m68k AmigaOS 3 - m68k AmigaOS 3
- m68k OpenBSD - m68k OpenBSD
- StrongARM NetBSD 1.4.1 - s390 Linux
- StrongARM (and other ARM) RISC OS 3.1, 4.02
OpenSSL OpenSSL
======= =======

View File

@@ -1,4 +1,4 @@
Updated for curl 7.8 on May 29, 2001 Updated for curl 7.9.1 on November 2, 2001
_ _ ____ _ _ _ ____ _
___| | | | _ \| | ___| | | | _ \| |
/ __| | | | |_) | | / __| | | | |_) | |
@@ -78,15 +78,15 @@ Library
makes sure we stay absolutely platform independent. makes sure we stay absolutely platform independent.
curl_easy_init() allocates an internal struct and makes some initializations. curl_easy_init() allocates an internal struct and makes some initializations.
The returned handle does not reveal internals. This is the 'UrlData' struct The returned handle does not reveal internals. This is the 'SessionHandle'
which works as a global "anchor" struct. All connections performed will get struct which works as an "anchor" struct for all curl_easy functions. All
connect-specific data allocated that should be used for things related to connections performed will get connect-specific data allocated that should be
particular connections/requests. used for things related to particular connections/requests.
curl_easy_setopt() takes three arguments, where the option stuff must be curl_easy_setopt() takes three arguments, where the option stuff must be
passed in pairs: the parameter-ID and the parameter-value. The list of passed in pairs: the parameter-ID and the parameter-value. The list of
options is documented in the man page. This function mainly sets things in options is documented in the man page. This function mainly sets things in
the 'UrlData' struct. the 'SessionHandle' struct.
curl_easy_perform() does a whole lot of things: curl_easy_perform() does a whole lot of things:
@@ -106,7 +106,7 @@ Library
This function makes sure there's an allocated and initiated 'connectdata' This function makes sure there's an allocated and initiated 'connectdata'
struct that is used for this particular connection only (although there may struct that is used for this particular connection only (although there may
be several requests performed on the same connect). A bunch of things are be several requests performed on the same connect). A bunch of things are
inited/inherited from the UrlData struct. inited/inherited from the SessionHandle struct.
o Curl_do() o Curl_do()
@@ -123,6 +123,13 @@ Library
Curl_Transfer() function (in lib/transfer.c) to setup the transfer and Curl_Transfer() function (in lib/transfer.c) to setup the transfer and
returns. returns.
Starting in 7.9.1, if this DO function fails and the connection is being
re-used, libcurl will then close this connection, setup a new connection
and re-issue the DO request on that. This is because there is no way to be
perfectly sure that we have discovered a dead connection before the DO
function and thus we might wrongly be re-using a connection that was closed
by the remote peer.
o Transfer() o Transfer()
Curl_perform() then calls Transfer() in lib/transfer.c that performs Curl_perform() then calls Transfer() in lib/transfer.c that performs
@@ -144,7 +151,7 @@ Library
o Curl_disconnect() o Curl_disconnect()
When doing normal connections and transfers, no one ever tries to close any When doing normal connections and transfers, no one ever tries to close any
connection so this is not normally called when curl_easy_perform() is connections so this is not normally called when curl_easy_perform() is
used. This function is only used when we are certain that no more transfers used. This function is only used when we are certain that no more transfers
is going to be made on the connection. It can be also closed by force, or is going to be made on the connection. It can be also closed by force, or
it can be called to make sure that libcurl doesn't keep too many it can be called to make sure that libcurl doesn't keep too many
@@ -258,12 +265,12 @@ Persistent Connections
The persistent connection support in libcurl requires some considerations on The persistent connection support in libcurl requires some considerations on
how to do things inside of the library. how to do things inside of the library.
o The 'UrlData' struct returned in the curl_easy_init() call must never o The 'SessionHandle' struct returned in the curl_easy_init() call must never
hold connection-oriented data. It is meant to hold the root data as well hold connection-oriented data. It is meant to hold the root data as well as
as all the options etc that the library-user may choose. all the options etc that the library-user may choose.
o The 'UrlData' struct holds the "connection cache" (an array of pointers to o The 'SessionHandle' struct holds the "connection cache" (an array of
'connectdata' structs). There's one connectdata struct allocated for each pointers to 'connectdata' structs). There's one connectdata struct
connection that libcurl knows about. allocated for each connection that libcurl knows about.
o This also enables the 'curl handle' to be reused on subsequent transfers, o This also enables the 'curl handle' to be reused on subsequent transfers,
something that was illegal before libcurl 7.7. something that was illegal before libcurl 7.7.
o When we are about to perform a transfer with curl_easy_perform(), we first o When we are about to perform a transfer with curl_easy_perform(), we first

View File

@@ -1,117 +0,0 @@
_ _ _ _
| (_) |__ ___ _ _ _ __| |
| | | '_ \ / __| | | | '__| |
| | | |_) | (__| |_| | | | |
|_|_|_.__/ \___|\__,_|_| |_|
How To Use Libcurl In Your C/C++ Program
[ libcurl can be used directly from within your Java, PHP, Perl, Ruby or Tcl
programs as well, look elsewhere for documentation on this ]
The interface is meant to be very simple for applictions/programmers, hence
the name "easy". We have therefore minimized the number of entries.
The Easy Interface
When using the easy interface, you init your session and get a handle, which
you use as input to the following interface functions you use. Use
curl_easy_init() to get the handle.
You continue by setting all the options you want in the upcoming transfer,
most important among them is the URL itself (you can't transfer anything
without a specified URL as you may have figured out yourself). You might want
to set some callbacks as well that will be called from the library when data
is available etc. curl_easy_setopt() is there for this.
When all is setup, you tell libcurl to perform the transfer using
curl_easy_perform(). It will then do the entire operation and won't return
until it is done or failed.
After the transfer has been made, you cleanup the session with
curl_easy_cleanup() and libcurl is entirely off the hook! If you want
persistant connections, you don't cleanup immediately, but instead run ahead
and perform other transfers. See the chapter below for Persistant
Connections.
While the above mentioned four functions are the main functions to use in the
easy interface, there is a series of other helpful functions to use. They
are:
curl_version() - displays the libcurl version
curl_getdate() - converts a date string to time_t
curl_getenv() - portable environment variable reader
curl_easy_getinfo() - get information about a performed transfer
curl_formparse() - helps building a HTTP form POST
curl_formfree() - free a list built with curl_formparse()
curl_slist_append() - builds a linked list
curl_slist_free_all() - frees a whole curl_slist
For details on these, read the separate man pages.
Linking with libcurl
Staring with 7.7.2 (on unix-like machines), there's a tool named curl-config
that gets installed with the rest of the curl stuff when 'make install' is
performed.
curl-config is added to make it easier for applications to link with
libcurl and developers to learn about libcurl and how to use it.
Run 'curl-config --libs' to get the (additional) linker options you need to
link with the particular version of libcurl you've installed.
For details, see the curl-config.1 man page.
libcurl symbol names
All public functions in the libcurl interface are prefixed with 'curl_' (with
a lowercase c). You can find other functions in the library source code, but
other prefixes indicate the functions are private and may change without
further notice in the next release.
Only use documented functions and functionality!
Portability
libcurl works *exactly* the same, on any of the platforms it compiles and
builds on.
There's only one caution, and that is the win32 platform that may(*) require
you to init the winsock stuff before you use the libcurl functions. Details
on this are noted on the curl_easy_init() man page.
(*) = it appears as if users of the cygwin environment get this done
automatically.
Threads
Never *ever* call curl-functions simultaneously using the same handle from
several threads. libcurl is thread-safe and can be used in any number of
threads, but you must use separate curl handles if you want to use libcurl in
more than one thread simultaneously.
Persistant Connections
With libcurl 7.7, persistant connections were added. Persistant connections
means that libcurl can re-use the same connection for several transfers, if
the conditions are right.
libcurl will *always* attempt to use persistant connections. Whenever you use
curl_easy_perform(), libcurl will attempt to use an existing connection to do
the transfer, and if none exists it'll open a new one that will be subject
for re-use on a possible following call to curl_easy_perform().
To allow libcurl to take full advantage of persistant connections, you should
do as many of your file transfers as possible using the same curl
handle. When you call curl_easy_cleanup(), all the possibly open connections
held by libcurl will be closed and forgotten.
Note that the options set with curl_easy_setopt() will be used in on every
repeat curl_easy_perform() call
Compatibility with older libcurls
Repeated curl_easy_perform() calls on the same handle were not supported in
pre-7.7 versions, and caused confusion and defined behaviour.

View File

@@ -132,7 +132,7 @@ UPLOADING
Upload all data on stdin to a specified ftp site: Upload all data on stdin to a specified ftp site:
curl -t ftp://ftp.upload.com/myfile curl -T - ftp://ftp.upload.com/myfile
Upload data from a specified file, login with user and password: Upload data from a specified file, login with user and password:
@@ -157,7 +157,7 @@ UPLOADING
Upload all data on stdin to a specified http site: Upload all data on stdin to a specified http site:
curl -t http://www.upload.com/myfile curl -T - http://www.upload.com/myfile
Note that the http server must've been configured to accept PUT before this Note that the http server must've been configured to accept PUT before this
can be done successfully. can be done successfully.
@@ -756,6 +756,17 @@ TELNET
You might want the -N/--no-buffer option to switch off the buffered output You might want the -N/--no-buffer option to switch off the buffered output
for slow connections or similar. for slow connections or similar.
Pass options to the telnet protocol negotiation, by using the -t option. To
tell the server we use a vt100 terminal, try something like:
curl -tTTYPE=vt100 telnet://remote.server.com
Other interesting options for it -t include:
- XDISPLOC=<X display> Sets the X display location.
- NEW_ENV=<var,val> Sets an environment variable.
NOTE: the telnet protocol does not specify any way to login with a specified NOTE: the telnet protocol does not specify any way to login with a specified
user and password so curl can't do that automatically. To do that, you need user and password so curl can't do that automatically. To do that, you need
to track when the login prompt is received and send the username and to track when the login prompt is received and send the username and

View File

@@ -12,7 +12,9 @@ man_MANS = \
curl_easy_init.3 \ curl_easy_init.3 \
curl_easy_perform.3 \ curl_easy_perform.3 \
curl_easy_setopt.3 \ curl_easy_setopt.3 \
curl_easy_duphandle.3 \
curl_formparse.3 \ curl_formparse.3 \
curl_formadd.3 \
curl_formfree.3 \ curl_formfree.3 \
curl_getdate.3 \ curl_getdate.3 \
curl_getenv.3 \ curl_getenv.3 \
@@ -28,8 +30,47 @@ man_MANS = \
curl_global_cleanup.3 \ curl_global_cleanup.3 \
libcurl.3 libcurl.3
SUBDIRS = examples
HTMLPAGES = \
curl.html \
curl-config.html \
curl_easy_cleanup.html \
curl_easy_getinfo.html \
curl_easy_init.html \
curl_easy_perform.html \
curl_easy_setopt.html \
curl_easy_duphandle.html \
curl_formadd.html \
curl_formparse.html \
curl_formfree.html \
curl_getdate.html \
curl_getenv.html \
curl_slist_append.html \
curl_slist_free_all.html \
curl_version.html \
curl_escape.html \
curl_unescape.html \
curl_strequal.html \
curl_strnequal.html \
curl_mprintf.html \
curl_global_init.html \
curl_global_cleanup.html \
libcurl.html
EXTRA_DIST = $(man_MANS) \ EXTRA_DIST = $(man_MANS) \
MANUAL BUGS CONTRIBUTE FAQ FEATURES INTERNALS \ MANUAL BUGS CONTRIBUTE FAQ FEATURES INTERNALS \
LIBCURL README.win32 RESOURCES TODO TheArtOfHttpScripting THANKS README.win32 RESOURCES TODO TheArtOfHttpScripting THANKS \
$(HTMLPAGES)
SUBDIRS = examples MAN2HTML= gnroff -man $< | man2html >$@
SUFFIXES = .1 .3 .html
html: $(HTMLPAGES)
.3.html:
$(MAN2HTML)
.1.html:
$(MAN2HTML)

117
docs/TODO
View File

@@ -10,81 +10,69 @@ TODO
send me patches that improve things! Also check the http://curl.haxx.se/dev send me patches that improve things! Also check the http://curl.haxx.se/dev
web section for various development notes. web section for various development notes.
To do in a future release (random order): LIBCURL
* Make the connect non-blocking so that timeouts work for connect in
multi-threaded programs
* Using FILE * in the libcurl API introduces a serious limitation since (at
least in the *nix falvours I know) you can fopen only the first 256
files. This means, that an application that first opens or fopens 256 files
has no chance to use libcurl. Using open and file descriptors instead of
FILE * would solve the problem. This implies a minor API
change/enhancement. ck1 <ck1@swissonline.ch>
* It would be nice to be able to use "-d" (or something similar) to attach
parameters of EITHER the GET or POST type... It would either require
another curl argument to specify "GET" (obviously the default should remain
POST), or it would require a new curl argument (perhaps -G/--get-data).
I know we're running out of letters, but it somehow feels a little
"cleaner" to just tag on each of your HTTP "parameters" (data-items) one by
one and let curl put them together, rather than having to put them together
myself and include them in the URL.
* Add an interface that enables a user to select prefered SSL ciphers to use.
* Make curl deal with cookies better. libcurl should be able to maintain a
"cookie jar". Updating it with cookies that is received, and using it to
pass cookies to the servers that have matching cookies in the jar.
http://curl.haxx.se/dev/cookie-jar.txt
* Consider an interface to libcurl that allows applications to easier get to * Consider an interface to libcurl that allows applications to easier get to
know what cookies that are sent back in the response headers. know what cookies that are sent back in the response headers.
* Make SSL session ids get used if multiple HTTPS documents from the same * Make content encoding/decoding internally be made using a filter system.
host is requested. http://curl.haxx.se/dev/SSL_session_id.txt
* HTTP PUT for files passed on stdin. Requires libcurl to send the file * The new 'multi' interface is being designed. Work out the details, start
with chunked content encoding. http://curl.haxx.se/dev/HTTP-PUT-stdin.txt implementing and write test applications!
[http://curl.haxx.se/dev/multi.h]
* Add a name resolve cache to libcurl to make repeated fetches to the same
host name (when persitancy isn't available) faster.
* 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.
http://curl.haxx.se/dev/no_copy_callbacks.txt [http://curl.haxx.se/dev/no_copy_callbacks.txt]
* Suggested on the mailing list: CURLOPT_FTP_MKDIR...!
* Add configure options that disables certain protocols in libcurl to * Add configure options that disables certain protocols in libcurl to
decrease footprint. '--disable-[protocol]' where protocol is http, ftp, decrease footprint. '--disable-[protocol]' where protocol is http, ftp,
telnet, ldap, dict or file. telnet, ldap, dict or file.
* Extend the test suite to include telnet. The telnet could just do ftp or * Add asynchronous name resolving. http://curl.haxx.se/dev/async-resolver.txt
http operations (for which we have test servers).
* Make TELNET work on windows! DOCUMENTATION
* Add a command line option that allows the output file to get the same time * Document all CURLcode error codes, why they happen and what most likely
stamp as the remote file. libcurl already is capable of fetching the remote will make them not happen again.
file's date.
* Make curl's SSL layer option capable of using other free SSL libraries. FTP
Such as the Mozilla Security Services
(http://www.mozilla.org/projects/security/pki/nss/) and GNUTLS
(http://gnutls.hellug.gr/)
* Add asynchronous name resolving, as this enables full timeout support for * FTP ASCII upload does not follow RFC959 section 3.1.1.1: "The sender
fork() systems. http://curl.haxx.se/dev/async-resolver.txt converts the data from an internal character representation to the standard
8-bit NVT-ASCII representation (see the Telnet specification). The
receiver will convert the data from the standard form to his own internal
form."
* Move non-URL related functions that are used by both the lib and the curl * An option to only download remote FTP files if they're newer than the local
application to a separate "portability lib". one is a good idea, and it would fit right into the same syntax as the
already working http dito works. It of course requires that 'MDTM' works,
and it isn't a standard FTP command.
* Add libcurl support/interfaces for more languages. C++ wrapper perhaps? * Suggested on the mailing list: CURLOPT_FTP_MKDIR...!
* Always use the FTP SIZE command before downloading, as that makes it more
likely that we know the size when downloading. Some sites support SIZE but
don't show the size in the RETR response!
* Make FTP PASV work with IPv6 support. RFC 2428 "FTP Extensions for IPv6 and
NATs" is interesting.
HTTP
* HTTP PUT for files passed on stdin *OR* when the --crlf option is
used. Requires libcurl to send the file with chunked content
encoding. [http://curl.haxx.se/dev/HTTP-PUT-stdin.txt] When the filter
system mentioned above gets real, it'll be a piece of cake to add.
* "Content-Encoding: compress/gzip/zlib" HTTP 1.1 clearly defines how to get * "Content-Encoding: compress/gzip/zlib" HTTP 1.1 clearly defines how to get
and decode compressed documents. There is the zlib that is pretty good at and decode compressed documents. There is the zlib that is pretty good at
decompressing stuff. This work was started in October 1999 but halted again decompressing stuff. This work was started in October 1999 but halted again
since it proved more work than we thought. It is still a good idea to since it proved more work than we thought. It is still a good idea to
implement though. implement though. This requires the filter system mentioned above.
* Authentication: NTLM. Support for that MS crap called NTLM * Authentication: NTLM. Support for that MS crap called NTLM
authentication. MS proxies and servers sometime require that. Since that authentication. MS proxies and servers sometime require that. Since that
@@ -107,10 +95,27 @@ To do in a future release (random order):
sends the password in cleartext over the network, this "Digest" method uses sends the password in cleartext over the network, this "Digest" method uses
a challange-response protocol which increases security quite a lot. a challange-response protocol which increases security quite a lot.
* Other proxies TELNET
Ftp-kind proxy, Socks5, whatever kind of proxies are there?
* Full IPv6 Awareness and support. (This is partly done.) RFC 2428 "FTP * Make TELNET work on windows98!
Extensions for IPv6 and NATs" is interesting. PORT should be replaced with
EPRT for IPv6 (done), and EPSV instead of PASV.
SSL
* Make curl's SSL layer option capable of using other free SSL libraries.
Such as the Mozilla Security Services
(http://www.mozilla.org/projects/security/pki/nss/) and GNUTLS
(http://gnutls.hellug.gr/)
LDAP
* Multiple URL requests don't work. [http://sourceforge.net/tracker/index.php?func=detail&aid=475407&group_id=976&atid=100976]
TEST SUITE
* Extend the test suite to include more protocols. The telnet could just do
ftp or http operations (for which we have test servers).
* Make the test suite work on more platforms. OpenBSD and Mac OS. Remove
fork()s and it should become even more portable.
* Introduce a test suite that tests libcurl better and more explicitly.

View File

@@ -1,6 +1,7 @@
Online: http://curl.haxx.se/docs/httpscripting.shtml
Author: Daniel Stenberg <daniel@haxx.se> Author: Daniel Stenberg <daniel@haxx.se>
Date: September 15, 2000 Date: October 31, 2001
Version: 0.3 Version: 0.5
The Art Of Scripting HTTP Requests Using Curl The Art Of Scripting HTTP Requests Using Curl
============================================= =============================================
@@ -47,7 +48,7 @@ Version: 0.3
2. URL 2. URL
The Uniform Resource Locator format is how you specify the address of a The Uniform Resource Locator format is how you specify the address of a
particular resource on the internet. You know these, you've seen URLs like particular resource on the Internet. You know these, you've seen URLs like
http://curl.haxx.se or https://yourbank.com a million times. http://curl.haxx.se or https://yourbank.com a million times.
3. GET a page 3. GET a page
@@ -55,7 +56,7 @@ Version: 0.3
The simplest and most common request/operation made using HTTP is to get a The simplest and most common request/operation made using HTTP is to get a
URL. The URL could itself refer to a web page, an image or a file. The client URL. The URL could itself refer to a web page, an image or a file. The client
issues a GET request to the server and receives the document it asked for. issues a GET request to the server and receives the document it asked for.
If you isse the command line If you issue the command line
curl http://curl.haxx.se curl http://curl.haxx.se
@@ -88,7 +89,7 @@ Version: 0.3
<input type=submit name=press value="OK"> <input type=submit name=press value="OK">
</form> </form>
In your favourite browser, this form will appear with a text box to fill in In your favorite browser, this form will appear with a text box to fill in
and a press-button labeled "OK". If you fill in '1905' and press the OK and a press-button labeled "OK". If you fill in '1905' and press the OK
button, your browser will then create a new URL to get for you. The URL will button, your browser will then create a new URL to get for you. The URL will
get "junk.cgi?birthyear=1905&press=OK" appended to the path part of the get "junk.cgi?birthyear=1905&press=OK" appended to the path part of the
@@ -135,8 +136,8 @@ Version: 0.3
4.3 FILE UPLOAD POST 4.3 FILE UPLOAD POST
Back in late 1995 they defined a new way to post data over HTTP. It was Back in late 1995 they defined a new way to post data over HTTP. It was
documented in the RFC 1867, why this method sometimes is refered to as documented in the RFC 1867, why this method sometimes is referred to as
a rfc1867-posting. a RFC1867-posting.
This method is mainly designed to better support file uploads. A form that This method is mainly designed to better support file uploads. A form that
allows a user to upload a file could be written like this in HTML: allows a user to upload a file could be written like this in HTML:
@@ -174,6 +175,19 @@ Version: 0.3
curl -d "birthyear=1905&press=OK&person=daniel" [URL] curl -d "birthyear=1905&press=OK&person=daniel" [URL]
4.5 FIGURE OUT WHAT A POST LOOKS LIKE
When you're about fill in a form and send to a server by using curl instead
of a browser, you're of course very interested in sending a POST exactly the
way your browser does.
An easy way to get to see this, is to save the HTML page with the form on
your local disk, modify the 'method' to a GET, and press the submit button
(you could also change the action URL if you want to).
You will then clearly see the data get appended to the URL, separated with a
'?'-letter as GET forms are supposed to.
5. PUT 5. PUT
The perhaps best way to upload data to a HTTP server is to use PUT. Then The perhaps best way to upload data to a HTTP server is to use PUT. Then
@@ -182,7 +196,7 @@ Version: 0.3
Put a file to a HTTP server with curl: Put a file to a HTTP server with curl:
curl -t uploadfile www.uploadhttp.com/receive.cgi curl -T uploadfile www.uploadhttp.com/receive.cgi
6. AUTHENTICATION 6. AUTHENTICATION
@@ -200,7 +214,7 @@ Version: 0.3
Sometimes your HTTP access is only available through the use of a HTTP Sometimes your HTTP access is only available through the use of a HTTP
proxy. This seems to be especially common at various companies. A HTTP proxy proxy. This seems to be especially common at various companies. A HTTP proxy
may require its own user and password to allow the client to get through to may require its own user and password to allow the client to get through to
the internet. To specify those with curl, run something like: the Internet. To specify those with curl, run something like:
curl -U proxyuser:proxypassword curl.haxx.se curl -U proxyuser:proxypassword curl.haxx.se
@@ -280,7 +294,7 @@ Version: 0.3
contents to the server, unless of course they are expired. contents to the server, unless of course they are expired.
Many applications and servers use this method to connect a series of requests Many applications and servers use this method to connect a series of requests
into a single logical session. To be able to use curl in such occations, we into a single logical session. To be able to use curl in such occasions, we
must be able to record and send back cookies the way the web application must be able to record and send back cookies the way the web application
expects them. The same way browsers deal with them. expects them. The same way browsers deal with them.
@@ -289,7 +303,6 @@ Version: 0.3
curl -b "name=Daniel" www.cookiesite.com curl -b "name=Daniel" www.cookiesite.com
Cookies are sent as common HTTP headers. This is practical as it allows curl Cookies are sent as common HTTP headers. This is practical as it allows curl
to record cookies simply by recording headers. Record cookies with curl by to record cookies simply by recording headers. Record cookies with curl by
using the -D option like: using the -D option like:
@@ -304,6 +317,23 @@ Version: 0.3
curl -b stored_cookies_in_file www.cookiesite.com curl -b stored_cookies_in_file www.cookiesite.com
Curl's "cookie engine" gets enabled when you use the -b option. If you only
want curl to understand received cookies, use -b with a file that doesn't
exist. Example, if you want to let curl understand cookies from a page and
follow a location (and thus possibly send back cookies it received), you can
invoke it like:
curl -b nada -L www.cookiesite.com
Curl has the ability to read and write cookie files that use the same file
format that Netscape and Mozilla do. It is a convenient way to share cookies
between browsers and automatic scripts. The -b switch automatically detects
if a given file is such a cookie file and parses it, and by using the
-c/--cookie-jar option you'll make curl write a new cookie file at the end of
an operation:
curl -b cookies.txt -c newcookies.txt www.cookiesite.com
11. HTTPS 11. HTTPS
There are a few ways to do secure HTTP transfers. The by far most common There are a few ways to do secure HTTP transfers. The by far most common
@@ -328,7 +358,7 @@ Version: 0.3
you need to enter the unlock-code before the certificate can be used by you need to enter the unlock-code before the certificate can be used by
curl. The PIN-code can be specified on the command line or if not, entered curl. The PIN-code can be specified on the command line or if not, entered
interactively when curl queries for it. Use a certificate with curl on a interactively when curl queries for it. Use a certificate with curl on a
https server like: HTTPS server like:
curl -E mycert.pem https://that.secure.server.com curl -E mycert.pem https://that.secure.server.com
@@ -337,10 +367,12 @@ Version: 0.3
RFC 2616 is a must to read if you want in-depth understanding of the HTTP RFC 2616 is a must to read if you want in-depth understanding of the HTTP
protocol. protocol.
RFC 2396 explains the URL syntax RFC 2396 explains the URL syntax.
RFC 2109 defines how cookies are supposed to work. RFC 2109 defines how cookies are supposed to work.
RFC 1867 defines the HTTP post upload format.
http://www.openssl.org is the home of the OpenSSL project http://www.openssl.org is the home of the OpenSSL project
http://curl.haxx.se is the home of the cURL project http://curl.haxx.se is the home of the cURL project

View File

@@ -2,7 +2,7 @@
.\" nroff -man curl.1 .\" nroff -man curl.1
.\" Written by Daniel Stenberg .\" Written by Daniel Stenberg
.\" .\"
.TH curl 1 "16 Aug 2001" "Curl 7.8.1" "Curl Manual" .TH curl 1 "30 Oct 2001" "Curl 7.9.1" "Curl Manual"
.SH NAME .SH NAME
curl \- get a URL with FTP, TELNET, LDAP, GOPHER, DICT, FILE, HTTP or curl \- get a URL with FTP, TELNET, LDAP, GOPHER, DICT, FILE, HTTP or
HTTPS syntax. HTTPS syntax.
@@ -91,6 +91,12 @@ also be enforced by using an URL that ends with ";type=A". This option causes
data sent to stdout to be in text mode for win32 systems. data sent to stdout to be in text mode for win32 systems.
If this option is used twice, the second one will disable ASCII usage. If this option is used twice, the second one will disable ASCII usage.
.IP "--ciphers <list of ciphers>"
(SSL) Specifies which ciphers to use in the connection. The list of ciphers
must be using valid ciphers. Read up on SSL cipher list details on this URL:
.I http://www.openssl.org/docs/apps/ciphers.html (Option added in curl 7.9)
If this option is used severl times, the last one will override the others.
.IP "--connect-timeout <seconds>" .IP "--connect-timeout <seconds>"
Maximum time in seconds that you allow the connection to the server to take. Maximum time in seconds that you allow the connection to the server to take.
This only limits the connection phase, once curl has connected this option is This only limits the connection phase, once curl has connected this option is
@@ -100,15 +106,16 @@ also the
option. option.
If this option is used several times, the last one will be used. If this option is used several times, the last one will be used.
.IP "-c/--continue" .IP "-c/--cookie-jar <file name>"
.B Deprecated. Use '-C -' instead. Specify to which file you want curl to write all cookies after a completed
Continue/Resume a previous file transfer. This instructs curl to operation. Curl writes all cookies previously read from a specified file as
continue appending data on the file where it was previously left, well as all cookies received from remote server(s). If no cookies are known,
possibly because of a broken connection to the server. There must be no file will be written. The file will be written using the Netscape cookie
a named physical file to append to for this to work. file format. If you set the file name to a single dash, "-", the cookies will
Note: Upload resume is depening on a command named SIZE not always be written to stdout. (Option added in curl 7.9)
present in all ftp servers! Upload resume is for FTP only.
HTTP resume is only possible with HTTP/1.1 or later servers. If this option is used several times, the last specfied file name will be
used.
.IP "-C/--continue-at <offset>" .IP "-C/--continue-at <offset>"
Continue/Resume a previous file transfer at the given offset. The Continue/Resume a previous file transfer at the given offset. The
given offset is the exact number of bytes that will be skipped given offset is the exact number of bytes that will be skipped
@@ -237,7 +244,7 @@ added in curl 7.6)
When used, this option will make all data specified with -d/--data or When used, this option will make all data specified with -d/--data or
--data-binary to be used in a HTTP GET request instead of the POST request --data-binary to be used in a HTTP GET request instead of the POST request
that otherwise would be used. The data will be appended to the URL with a '?' that otherwise would be used. The data will be appended to the URL with a '?'
separator. separator. (Option added in curl 7.9)
.IP "-h/--help" .IP "-h/--help"
Usage help. Usage help.
.IP "-H/--header <header>" .IP "-H/--header <header>"
@@ -324,6 +331,8 @@ file in the user's home directory for login name and password. This is
typically used for ftp on unix. If used with http, curl will enable user typically used for ftp on unix. If used with http, curl will enable user
authentication. See authentication. See
.BR netrc(4) .BR netrc(4)
or
.BR ftp(1)
for details on the file format. Curl will not complain if that file for details on the file format. Curl will not complain if that file
hasn't the right permissions (it should not be world nor group hasn't the right permissions (it should not be world nor group
readable). The environment variable "HOME" is used to find the home readable). The environment variable "HOME" is used to find the home
@@ -452,6 +461,12 @@ FTP range downloads only support the simple syntax 'start-stop' (optionally
with one of the numbers omitted). It depends on the non-RFC command SIZE. with one of the numbers omitted). It depends on the non-RFC command SIZE.
If this option is used several times, the last one will be used. If this option is used several times, the last one will be used.
.IP "-R/--remote-time"
When used, this will make libcurl attempt to figure out the timestamp of the
remote file, and if that is available make the local file get that same
timestamp.
If this option is used twice, the second time disables this again.
.IP "-s/--silent" .IP "-s/--silent"
Silent mode. Don't show progress meter or error messages. Makes Silent mode. Don't show progress meter or error messages. Makes
Curl mute. Curl mute.
@@ -470,14 +485,15 @@ XDISPLOC=<X display> Sets the X display location.
NEW_ENV=<var,val> Sets an environment variable. NEW_ENV=<var,val> Sets an environment variable.
.IP "-T/--upload-file <file>" .IP "-T/--upload-file <file>"
Like -t, but this transfers the specified local file. If there is no This transfers the specified local file to the remote URL. If there is no file
file part in the specified URL, Curl will append the local file part in the specified URL, Curl will append the local file name. NOTE that you
name. NOTE that you must use a trailing / on the last directory to must use a trailing / on the last directory to really prove to Curl that there
really prove to Curl that there is no file name or curl will is no file name or curl will think that your last directory name is the remote
think that your last directory name is the remote file name to file name to use. That will most likely cause the upload operation to fail. If
use. That will most likely cause the upload operation to fail. If
this is used on a http(s) server, the PUT command will be used. this is used on a http(s) server, the PUT command will be used.
Use the file name "-" (a single dash) to use stdin instead of a given file.
If this option is used several times, the last one will be used. If this option is used several times, the last one will be used.
.IP "-u/--user <user:password>" .IP "-u/--user <user:password>"
Specify user and password to use when fetching. See README.curl for detailed Specify user and password to use when fetching. See README.curl for detailed
@@ -574,8 +590,13 @@ The average upload speed that curl measured for the complete upload.
If this option is used several times, the last one will be used. If this option is used several times, the last one will be used.
.IP "-x/--proxy <proxyhost[:port]>" .IP "-x/--proxy <proxyhost[:port]>"
Use specified proxy. If the port number is not specified, it is assumed at Use specified HTTP proxy. If the port number is not specified, it is assumed
port 1080. at port 1080.
\fBNote\fP that all operations that are performed over a HTTP proxy will
transparantly be converted to HTTP. It means that certain protocol specific
operations might not be available. This is not the case if you can tunnel
through the proxy, as done with the \fI-p/--proxytunnel\fP option.
If this option is used several times, the last one will be used. If this option is used several times, the last one will be used.
.IP "-X/--request <command>" .IP "-X/--request <command>"
@@ -623,6 +644,9 @@ Forces curl to use SSL version 3 when negotiating with a remote SSL server.
.IP "-2/--sslv2" .IP "-2/--sslv2"
(HTTPS) (HTTPS)
Forces curl to use SSL version 2 when negotiating with a remote SSL server. Forces curl to use SSL version 2 when negotiating with a remote SSL server.
.IP "-0/--http1.0"
(HTTP) Forces curl to issue its requests using HTTP 1.0 instead of using its
internally preferred: HTTP 1.1.
.IP "-#/--progress-bar" .IP "-#/--progress-bar"
Make curl display progress information as a progress bar instead of the Make curl display progress information as a progress bar instead of the
default statistics. default statistics.

View File

@@ -0,0 +1,37 @@
.\" You can view this file with:
.\" nroff -man [file]
.\" $Id$
.\"
.TH curl_easy_duphandle 3 "18 September 2001" "libcurl 7.9" "libcurl Manual"
.SH NAME
curl_easy_duphandle - Clone a libcurl session handle
.SH SYNOPSIS
.B #include <curl/curl.h>
.sp
.BI "CURL *curl_easy_duphandle(CURL *"handle ");"
.ad
.SH DESCRIPTION
This function will return a new curl handle, a duplicate, using all the
options previously set in the input curl \fIhandle\fP. Both handles can
subsequently be used independently and they must both be freed with
\fIcurl_easy_cleanup()\fP.
All strings that the input handle has been told to point to (as opposed to
copy) with previous calls to \fIcurl_easy_setopt\fP using char * inputs, will
be pointed to by the new handle as well. You must therefore make sure to keep
the data around until both handles have been cleaned up.
The new handle will \fBnot\fP inherit any state information, no connections,
no SSL sessions and no cookies.
\fBNote\fP that even in multi-threaded programs, this function must be called
in a synchronous way, the input handle may not be in use when cloned.
This function was added in libcurl 7.9.
.SH RETURN VALUE
If this function returns NULL, something went wrong and no valid handle was
returned.
.SH "SEE ALSO"
.BR curl_easy_init "(3)," curl_easy_cleanup "(3)," curl_global_init "(3)
.SH BUGS
Surely there are some, you tell me!

View File

@@ -2,83 +2,84 @@
.\" nroff -man [file] .\" nroff -man [file]
.\" $Id$ .\" $Id$
.\" .\"
.TH curl_easy_setopt 3 "20 August 2001" "libcurl 7.8.1" "libcurl Manual" .TH curl_easy_setopt 3 "11 Oct 2001" "libcurl 7.9.1" "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
.B #include <curl/curl.h> #include <curl/curl.h>
.sp
.BI "CURLcode curl_easy_setopt(CURL *" handle ", CURLoption "option ", ...);" CURLcode curl_easy_setopt(CURL *handle, CURLoption option, parameter);
.ad .ad
.SH DESCRIPTION .SH DESCRIPTION
curl_easy_setopt() is called to tell libcurl how to behave in a number of curl_easy_setopt() is used to tell libcurl how to behave. Most operations in
ways. Most operations in libcurl have default actions, and by using the libcurl have default actions, and by using the appropriate options to
appropriate options you can make them behave differently (as documented). All \fIcurl_easy_setopt\fP, you can change them. All options are set with the
options are set with the \fIoption\fP followed by a \fIparameter\fP. That parameter can be a long, a
.I option function pointer or an object pointer, all depending on what the specific
followed by a parameter. That parameter can be a long, a function pointer or option expects. Read this manual carefully as bad input values may cause
an object pointer, all depending on what the option in question expects. Read libcurl to behave badly! You can only set one option in each function call. A
this manual carefully as bad input values may cause libcurl to behave badly! typical application uses many curl_easy_setopt() calls in the setup phase.
You can only set one option in each function call. A typical application uses
many curl_easy_setopt() calls in the setup phase.
NOTE: strings passed to libcurl as 'char *' arguments, will not be copied by \fBNOTE:\fP strings passed to libcurl as 'char *' arguments, will not be
the library. Instead you should keep them available until libcurl no longer copied by the library. Instead you should keep them available until libcurl no
needs them. Failing to do so will cause very odd behaviour or even crashes. longer needs them. Failing to do so will cause very odd behavior or even
crashes.
More note: the options set with this function call are valid for the \fBNOTE2:\fP options set with this function call are valid for the forthcoming
forthcoming data transfers that are performed when you invoke data transfers that are performed when you invoke \fIcurl_easy_perform\fP.
.I curl_easy_perform .
The options are not in any way reset between transfers, so if you want The options are not in any way reset between transfers, so if you want
subsequent transfers with different options, you must change them between the subsequent transfers with different options, you must change them between the
transfers. transfers.
The The \fIhandle\fP is the return code from a \fIcurl_easy_init(3)\fP or
.I "handle" \fIcurl_easy_duphandle(3)\fP call.
is the return code from the
.I "curl_easy_init"
call.
.SH OPTIONS .SH OPTIONS
These options are in a bit of random order, but you'll figure it out! The options are listed in a sort of random order, but you'll figure it out!
.TP 0.8i .TP 0.8i
.B CURLOPT_FILE .B CURLOPT_FILE
Data pointer to pass to file write function. Note that if you specify the Data pointer to pass to the file write function. Note that if you specify the
.I CURLOPT_WRITEFUNCTION \fICURLOPT_WRITEFUNCTION\fP, this is the pointer you'll get as input. If you
, this is the pointer you'll get as input. If you don't use a callback, you don't use a callback, you must pass a 'FILE *' as libcurl will pass this to
must pass a 'FILE *' as libcurl passes it to fwrite() when writing data. fwrite() when writing data.
NOTE: If you're using libcurl as a win32 DLL, you MUST use the \fBNOTE:\fP If you're using libcurl as a win32 DLL, you MUST use the
\fICURLOPT_WRITEFUNCTION\fP if you set this option. \fICURLOPT_WRITEFUNCTION\fP if you set this option or you will experience
crashes.
.TP .TP
.B CURLOPT_WRITEFUNCTION .B CURLOPT_WRITEFUNCTION
Function pointer that should match the following prototype: Function pointer that should match the following prototype: \fBsize_t
.BI "size_t function( void *ptr, size_t size, size_t nmemb, void *stream);" function( void *ptr, size_t size, size_t nmemb, void *stream);\fP This
This function gets called by libcurl as soon as there is received data that function gets called by libcurl as soon as there is data available to pass
needs to be written down. The size of the data pointed to by \fIptr\fP is available that needs to be saved. The size of the data pointed to by \fIptr\fP
\fIsize\fP multiplied with \fInmemb\fP. Return the number of bytes actually is \fIsize\fP multiplied with \fInmemb\fP. Return the number of bytes
written or return -1 to signal error to the library (it will cause it to abort actually taken care of. If that amount differs from the amount passed to your
the transfer with CURLE_WRITE_ERROR). function, it'll signal an error to the library and it will abort the transfer
and return \fICURLE_WRITE_ERROR\fP.
Set the \fIstream\fP argument with the \fBCURLOPT_FILE\fP option. Set the \fIstream\fP argument with the \fBCURLOPT_FILE\fP option.
\fBNOTE:\fP you will be passed as much data as possible in all invokes, but
you cannot possibly make any assumptions. It may be one byte, it may be
thousands.
.TP .TP
.B CURLOPT_INFILE .B CURLOPT_INFILE
Data pointer to pass to the file read function. Note that if you specify the Data pointer to pass to the file read function. Note that if you specify the
\fICURLOPT_READFUNCTION\fP, this is the pointer you'll get as input. If you \fICURLOPT_READFUNCTION\fP, this is the pointer you'll get as input. If you
don't specify a read callback, this must be a valid FILE *. don't specify a read callback, this must be a valid FILE *.
NOTE: If you're using libcurl as a win32 DLL, you MUST use a \fBNOTE:\fP If you're using libcurl as a win32 DLL, you MUST use a
\fICURLOPT_READFUNCTION\fP if you set this option. \fICURLOPT_READFUNCTION\fP if you set this option.
.TP .TP
.B CURLOPT_READFUNCTION .B CURLOPT_READFUNCTION
Function pointer that should match the following prototype: Function pointer that should match the following prototype: \fBsize_t
.BI "size_t function( void *ptr, size_t size, size_t nmemb, void *stream);" function( void *ptr, size_t size, size_t nmemb, void *stream);\fP This
This function gets called by libcurl as soon as it needs to read data in order function gets called by libcurl as soon as it needs to read data in order to
to send it to the peer. The data area pointed at by the pointer \fIptr\fP may send it to the peer. The data area pointed at by the pointer \fIptr\fP may be
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 -1 will signal an error to the library and cause
it to abort the current transfer immediately (with a CURLE_READ_ERROR return it to abort the current transfer immediately (with a \fICURLE_READ_ERROR\fP
code). 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
@@ -87,49 +88,67 @@ libcurl what the expected size of the infile is.
.B CURLOPT_URL .B CURLOPT_URL
The actual URL to deal with. The parameter should be a char * to a zero The actual URL to deal with. The parameter should be a char * to a zero
terminated string. The string must remain present until curl no longer needs terminated string. The string must remain present until curl no longer needs
it, as it doesn't copy the string. NOTE: this option is required to be set it, as it doesn't copy the string.
before curl_easy_perform() is called.
\fBNOTE:\fP this option is (the only one) required to be set before
\fIcurl_easy_perform(3)\fP is called.
.TP .TP
.B CURLOPT_PROXY .B CURLOPT_PROXY
If you need libcurl to use a http proxy to access the outside world, set the Set HTTP proxy to use. The parameter should be a char * to a zero terminated
proxy string with this option. The parameter should be a char * to a zero string holding the host name or dotted IP address. To specify port number in
terminated string. To specify port number in this string, append :[port] to this string, append :[port] to the end of the host name. The proxy string may
the end of the host name. The proxy string may be prefixed with be prefixed with [protocol]:// since any such prefix will be ignored. The
[protocol]:// since any such prefix will be ignored. proxy's port number may optionally be specified with the separate option
\fICURLOPT_PROXYPORT\fP.
\fBNOTE:\fP when you tell the library to use a HTTP proxy, libcurl will
transparently convert operations to HTTP even if you specify a FTP URL
etc. This may have an impact on what other features of the library you can
use, such as CURLOPT_QUOTE and similar FTP specifics that don't work unless
you tunnel through the HTTP proxy. Such tunneling is activated with
\fICURLOPT_HTTPPROXYTUNNEL\fP.
\fBNOTE2:\fP libcurl respects the environment variables \fBhttp_proxy\fP,
\fBftp_proxy\fP, \fBall_proxy\fP etc, if any of those is set.
.TP .TP
.B CURLOPT_PROXYPORT .B CURLOPT_PROXYPORT
Set this long with this option to set the proxy port to use unless it is Pass a long with this option to set the proxy port to connect to unless it is
specified in the proxy string CURLOPT_PROXY. specified in the proxy string \fICURLOPT_PROXY\fP.
.TP .TP
.B CURLOPT_HTTPPROXYTUNNEL .B CURLOPT_HTTPPROXYTUNNEL
Set the parameter to non-zero to get the library to tunnel all non-HTTP Set the parameter to non-zero to get the library to tunnel all operations
operations through the given HTTP proxy. Do note that there is a big through a given HTTP proxy. Note that there is a big difference between using
difference to use a proxy and to tunnel through it. If you don't know what a proxy and to tunnel through it. If you don't know what this means, you
this means, you probably don't want this tunnel option. (Added in libcurl 7.3) probably don't want this tunneling option. (Added in libcurl 7.3)
.TP .TP
.B CURLOPT_VERBOSE .B CURLOPT_VERBOSE
Set the parameter to non-zero to get the library to display a lot of verbose Set the parameter to non-zero to get the library to display a lot of verbose
information about its operations. Very useful for libcurl and/or protocl information about its operations. Very useful for libcurl and/or protocol
debugging and understanding. debugging and understanding.
You hardly ever want this set in production use, you will almost always want
this when you debug/report problems.
.TP .TP
.B CURLOPT_HEADER .B CURLOPT_HEADER
A non-zero parameter tells the library to include the header in the A non-zero parameter tells the library to include the header in the body
output. This is only relevant for protocols that actually has a header output. This is only relevant for protocols that actually have headers
preceeding the data (like HTTP). preceding the data (like HTTP).
.TP .TP
.B CURLOPT_NOPROGRESS .B CURLOPT_NOPROGRESS
A non-zero parameter tells the library to shut of the built-in progress meter A non-zero parameter tells the library to shut of the built-in progress meter
completely. (NOTE: future versions of the lib is likely to not have any completely.
built-in progress meter at all).
\fBNOTE:\fP future versions of libcurl is likely to not have any built-in
progress meter at all.
.TP .TP
.B CURLOPT_NOBODY .B CURLOPT_NOBODY
A non-zero parameter tells the library to not include the body-part in the A non-zero parameter tells the library to not include the body-part in the
output. This is only relevant for protocols that have a separate header and output. This is only relevant for protocols that have separate header and body
body part. parts.
.TP .TP
.B CURLOPT_FAILONERROR .B CURLOPT_FAILONERROR
A non-zero parameter tells the library to fail silently if the HTTP code A non-zero parameter tells the library to fail silently if the HTTP code
returned is equal or larger than 300. The default action would be to return returned is equal to or larger than 300. The default action would be to return
the page normally, ignoring that code. the page normally, ignoring that code.
.TP .TP
.B CURLOPT_UPLOAD .B CURLOPT_UPLOAD
@@ -140,11 +159,13 @@ CURLOPT_INFILE and CURLOPT_INFILESIZE are also interesting for uploads.
A non-zero parameter tells the library to do a regular HTTP post. This is a A non-zero parameter tells the library to do a regular HTTP post. This is a
normal application/x-www-form-urlencoded kind, which is the most commonly used normal application/x-www-form-urlencoded kind, which is the most commonly used
one by HTML forms. See the CURLOPT_POSTFIELDS option for how to specify the one by HTML forms. See the CURLOPT_POSTFIELDS option for how to specify the
data to post and CURLOPT_POSTFIELDSIZE in how to set the data size. data to post and CURLOPT_POSTFIELDSIZE in how to set the data size. Starting
with libcurl 7.8, this option is obsolete. Using the CURLOPT_POSTFIELDS option
will imply this option.
.TP .TP
.B CURLOPT_FTPLISTONLY .B CURLOPT_FTPLISTONLY
A non-zero parameter tells the library to just list the names of an ftp A non-zero parameter tells the library to just list the names of an ftp
directory, instead of doing a full directory listin that would include file directory, instead of doing a full directory listing that would include file
sizes, dates etc. sizes, dates etc.
.TP .TP
.B CURLOPT_FTPAPPEND .B CURLOPT_FTPAPPEND
@@ -152,90 +173,108 @@ A non-zero parameter tells the library to append to the remote file instead of
overwrite it. This is only useful when uploading to a ftp site. overwrite it. This is only useful when uploading to a ftp site.
.TP .TP
.B CURLOPT_NETRC .B CURLOPT_NETRC
A non-zero parameter tells the library to scan your A non-zero parameter tells the library to scan your \fI~/.netrc\fP file to
.I ~/.netrc find user name and password for the remote site you are about to access. Only
file to find user name and password for the remote site you are about to machine name, user name and password is taken into account (init macros and
access. Do note that curl does not verify that the file has the correct similar things aren't supported).
properties set (as the standard unix ftp client does), and that only machine
name, user name and password is taken into account (init macros and similar \fBNote:\fP libcurl does not verify that the file has the correct properties
things aren't supported). set (as the standard Unix ftp client does). It should only be readable by
user.
.TP .TP
.B CURLOPT_FOLLOWLOCATION .B CURLOPT_FOLLOWLOCATION
A non-zero parameter tells the library to follow any Location: header that the A non-zero parameter tells the library to follow any Location: header that the
server sends as part of a HTTP header. NOTE that this means that the library server sends as part of a HTTP header.
will resend the same request on the new location and follow new Location:
headers all the way until no more such headers are returned. \fBNOTE:\fP this means that the library will re-send the same request on the
new location and follow new Location: headers all the way until no more such
headers are returned. \fICURLOPT_MAXREDIRS\fP can be used to limit the number
of redirects libcurl will follow.
.TP .TP
.B CURLOPT_TRANSFERTEXT .B CURLOPT_TRANSFERTEXT
A non-zero parameter tells the library to use ASCII mode for ftp transfers, A non-zero parameter tells the library to use ASCII mode for ftp transfers,
instead of the default binary transfer. For LDAP transfers it gets the data in instead of the default binary transfer. For LDAP transfers it gets the data in
plain text instead of HTML and for win32 systems it does not set the stdout to plain text instead of HTML and for win32 systems it does not set the stdout to
binary mode. This option can be useable when transfering text data between binary mode. This option can be usable when transferring text data between
system with different views on certain characters, such as newlines or systems with different views on certain characters, such as newlines or
similar. similar.
.TP .TP
.B CURLOPT_PUT .B CURLOPT_PUT
A non-zero parameter tells the library to use HTTP PUT a file. The file to put A non-zero parameter tells the library to use HTTP PUT to transfer data. The
must be set with CURLOPT_INFILE and CURLOPT_INFILESIZE. data should be set with CURLOPT_INFILE and CURLOPT_INFILESIZE.
.TP .TP
.B CURLOPT_USERPWD .B CURLOPT_USERPWD
Pass a char * as parameter, which should be [username]:[password] to use for Pass a char * as parameter, which should be [user name]:[password] to use for
the connection. If the password is left out, you will be prompted for it. the connection. If the password is left out, you will be prompted for it.
\fICURLOPT_PASSWDFUNCTION\fP can be used to set your own prompt function.
.TP .TP
.B CURLOPT_PROXYUSERPWD .B CURLOPT_PROXYUSERPWD
Pass a char * as parameter, which should be [username]:[password] to use for Pass a char * as parameter, which should be [user name]:[password] to use for
the connection to the HTTP proxy. If the password is left out, you will be the connection to the HTTP proxy. If the password is left out, you will be
prompted for it. prompted for it. \fICURLOPT_PASSWDFUNCTION\fP can be used to set your own
prompt function.
.TP .TP
.B CURLOPT_RANGE .B CURLOPT_RANGE
Pass a char * as parameter, which should contain the specified range you Pass a char * as parameter, which should contain the specified range you
want. It should be in the format "X-Y", where X or Y may be left out. HTTP want. It should be in the format "X-Y", where X or Y may be left out. HTTP
transfers also support several intervals, separated with commas as in transfers also support several intervals, separated with commas as in
.I "X-Y,N-M" \fI"X-Y,N-M"\fP. Using this kind of multiple intervals will cause the HTTP
. Using this kind of multiple intervals will cause the HTTP server to send the server to send the response document in pieces (using standard MIME separation
response document in pieces. techniques).
.TP .TP
.B CURLOPT_ERRORBUFFER .B CURLOPT_ERRORBUFFER
Pass a char * to a buffer that the libcurl may store human readable error Pass a char * to a buffer that the libcurl may store human readable error
messages in. This may be more helpful than just the return code from the messages in. This may be more helpful than just the return code from the
library. The buffer must be at least CURL_ERROR_SIZE big. library. The buffer must be at least CURL_ERROR_SIZE big.
\fBNote:\fP if the library does not return an error, the buffer may not have
been touched. Do not rely on the contents in those cases.
.TP .TP
.B CURLOPT_TIMEOUT .B CURLOPT_TIMEOUT
Pass a long as parameter containing the maximum time in seconds that you allow Pass a long as parameter containing the maximum time in seconds that you allow
the libcurl transfer operation to take. Normally, name lookups can take a the libcurl transfer operation to take. Normally, name lookups can take a
considerable time and limiting operations to less than a few minutes risk considerable time and limiting operations to less than a few minutes risk
aborting perfectly normal operations. This option will cause curl to use the aborting perfectly normal operations. This option will cause curl to use the
SIGALRM to enable timeouting system calls. SIGALRM to enable time-outing system calls.
.B NOTE
that this does not work in multi-threaded programs! \fBNOTE:\fP this does not work in Unix multi-threaded programs, as it uses
signals.
.TP .TP
.B CURLOPT_POSTFIELDS .B CURLOPT_POSTFIELDS
Pass a char * as parameter, which should be the full data to post in a HTTP Pass a char * as parameter, which should be the full data to post in a HTTP
post operation. See also the CURLOPT_POST. post operation. This is a normal application/x-www-form-urlencoded kind, which
is the most commonly used one by HTML forms. See also the CURLOPT_POST. Since
7.8, using CURLOPT_POSTFIELDS implies CURLOPT_POST.
\fBNote:\fP to make multipart/formdata posts (aka rfc1867-posts), check out
the \fICURLOPT_HTTPPOST\fP option.
.TP .TP
.B CURLOPT_POSTFIELDSIZE .B CURLOPT_POSTFIELDSIZE
If you want to post data to the server without letting libcurl do a strlen() If you want to post data to the server without letting libcurl do a strlen()
to measure the data size, this option must be used. Also, when this option is to measure the data size, this option must be used. When this option is used
used, you can post fully binary data which otherwise is likely to fail. If you can post fully binary data, which otherwise is likely to fail. If this
this size is set to zero, the library will use strlen() to get the data size is set to zero, the library will use strlen() to get the size. (Added in
size. (Added in libcurl 7.2) libcurl 7.2)
.TP .TP
.B CURLOPT_REFERER .B CURLOPT_REFERER
Pass a pointer to a zero terminated string as parameter. It will be used to Pass a pointer to a zero terminated string as parameter. It will be used to
set the referer: header in the http request sent to the remote server. This set the Referer: header in the http request sent to the remote server. This
can be used to fool servers or scripts. can be used to fool servers or scripts. You can also set any custom header
with \fICURLOPT_HTTPHEADER\fP.
.TP .TP
.B CURLOPT_USERAGENT .B CURLOPT_USERAGENT
Pass a pointer to a zero terminated string as parameter. It will be used to Pass a pointer to a zero terminated string as parameter. It will be used to
set the user-agent: header in the http request sent to the remote server. This set the User-Agent: header in the http request sent to the remote server. This
can be used to fool servers or scripts. can be used to fool servers or scripts. You can also set any custom header
with \fICURLOPT_HTTPHEADER\fP.
.TP .TP
.B CURLOPT_FTPPORT .B CURLOPT_FTPPORT
Pass a pointer to a zero terminated string as parameter. It will be used to Pass a pointer to a zero terminated string as parameter. It will be used to
get the IP address to use for the ftp PORT instruction. The PORT instruction get the IP address to use for the ftp PORT instruction. The PORT instruction
tells the remote server to connect to our specified IP address. The string may tells the remote server to connect to our specified IP address. The string may
be a plain IP address, a host name, an network interface name (under unix) or be a plain IP address, a host name, an network interface name (under Unix) or
just a '-' letter to let the library use your systems default IP address. just a '-' letter to let the library use your systems default IP
address. Default FTP operations are passive, and thus won't use PORT.
.TP .TP
.B CURLOPT_LOW_SPEED_LIMIT .B CURLOPT_LOW_SPEED_LIMIT
Pass a long as parameter. It contains the transfer speed in bytes per second Pass a long as parameter. It contains the transfer speed in bytes per second
@@ -258,82 +297,71 @@ set a cookie in the http request. The format of the string should be
.TP .TP
.B CURLOPT_HTTPHEADER .B CURLOPT_HTTPHEADER
Pass a pointer to a linked list of HTTP headers to pass to the server in your Pass a pointer to a linked list of HTTP headers to pass to the server in your
HTTP request. The linked list should be a fully valid list of 'struct HTTP request. The linked list should be a fully valid list of \fBstruct
curl_slist' structs properly filled in. Use curl_slist\fP structs properly filled in. Use \fIcurl_slist_append(3)\fP to
.I curl_slist_append(3) create the list and \fIcurl_slist_free_all(3)\fP to clean up an entire
to create the list and list. If you add a header that is otherwise generated and used by libcurl
.I curl_slist_free_all(3) internally, your added one will be used instead. If you add a header with no
to clean up an entire list. If you add a header that is otherwise generated contents as in 'Accept:' (no data on the right side of the colon), the
and used by libcurl internally, your added one will be used instead. If you internally used header will get disabled. Thus, using this option you can add
add a header with no contents as in 'Accept:', the internally used header will new headers, replace internal headers and remove internal headers.
just get disabled. Thus, using this option you can add new headers, replace
internal headers and remove internal headers. \fBNOTE:\fPThe most commonly replaced headers have "shortcuts" in the options
CURLOPT_COOKIE, CURLOPT_USERAGENT and CURLOPT_REFERER.
.TP .TP
.B CURLOPT_HTTPPOST .B CURLOPT_HTTPPOST
Tells libcurl you want a multipart/formdata HTTP POST to be made and you Tells libcurl you want a multipart/formdata HTTP POST to be made and you
instruct what data to pass on to the server. Pass a pointer to a linked list instruct what data to pass on to the server. Pass a pointer to a linked list
of HTTP post structs as parameter. The linked list should be a fully valid of HTTP post structs as parameter. The linked list should be a fully valid
list of 'struct HttpPost' structs properly filled in. The best and most list of 'struct HttpPost' structs properly filled in. The best and most
elegant way to do this, is to use elegant way to do this, is to use \fIcurl_formadd(3)\fP as documented. The
.I curl_formparse(3) data in this list must remained intact until you close this curl handle again
as documented. The data in this list must remained intact until you close this with \fIcurl_easy_cleanup(3)\fP.
curl handle again with curl_easy_cleanup().
.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 certficicate in PEM format. the file name of your certificate in PEM format.
.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. is not supplied, you will be prompted for it. \fICURLOPT_PASSWDFUNCTION\fP can
be used to set your own prompt function.
.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.
.TP .TP
.B CURLOPT_QUOTE .B CURLOPT_QUOTE
Pass a pointer to a linked list of FTP commands to pass to the server prior to Pass a pointer to a linked list of FTP commands to pass to the server prior to
your ftp request. The linked list should be a fully valid list of 'struct your ftp request. The linked list should be a fully valid list of 'struct
curl_slist' structs properly filled in. Use curl_slist' structs properly filled in. Use \fIcurl_slist_append(3)\fP to
.I curl_slist_append(3) append strings (commands) to the list, and clear the entire list afterwards
to append strings (commands) to the list, and clear the entire list afterwards with \fIcurl_slist_free_all(3)\fP.
with
.I curl_slist_free_all(3)
.TP .TP
.B CURLOPT_POSTQUOTE .B CURLOPT_POSTQUOTE
Pass a pointer to a linked list of FTP commands to pass to the server after Pass a pointer to a linked list of FTP commands to pass to the server after
your ftp transfer request. The linked list should be a fully valid list of your ftp transfer request. The linked list should be a fully valid list of
struct curl_slist structs properly filled in as described for struct curl_slist structs properly filled in as described for
.I "CURLOPT_QUOTE" \fICURLOPT_QUOTE\fP.
.TP .TP
.B CURLOPT_WRITEHEADER .B CURLOPT_WRITEHEADER
Pass a pointer to be used to write the header part of the received data to. If Pass a pointer to be used to write the header part of the received data to. If
you don't use a callback to take care of the writing, this must be a FILE you don't use your own callback to take care of the writing, this must be a
*. The headers are guaranteed to be written one-by-one and only complete lines valid FILE *. See also the \fICURLOPT_HEADERFUNCTION\fP option below on how to set a
are written. Parsing headers should be easy enough using this. See also the custom get-all-headers callback.
\fICURLOPT_HEADERFUNCTION\fP option.
.TP .TP
.B CURLOPT_HEADERFUNCTION .B CURLOPT_HEADERFUNCTION
Function pointer that should match the following prototype: Function pointer that should match the following prototype: \fIsize_t
.BI "size_t function( void *ptr, size_t size, size_t nmemb, void *stream);" function( void *ptr, size_t size, size_t nmemb, void *stream);\fP. This
This function gets called by libcurl as soon as there is received header data function gets called by libcurl as soon as there is received header data that
that needs to be written down. The function will be called once for each needs to be written down. The headers are guaranteed to be written one-by-one
header with a complete header line in each invoke. The size of the data and only complete lines are written. Parsing headers should be easy enough
pointed to by using this. The size of the data pointed to by \fIptr\fP is \fIsize\fP
.I ptr multiplied with \fInmemb\fP. The pointer named \fIstream\fP will be the one
is you passed to libcurl with the \fICURLOPT_WRITEHEADER\fP option. Return the
.I size number of bytes actually written or return -1 to signal error to the library
multiplied with (it will cause it to abort the transfer with a \fICURLE_WRITE_ERROR\fP return
.I nmemb. code). (Added in libcurl 7.7.2)
The pointer named
.I stream
will be the one you passed to libcurl with the
.I CURLOPT_WRITEHEADER
option.
Return the number of bytes actually written or return -1 to signal error to
the library (it will cause it to abort the transfer with a
.I CURLE_WRITE_ERROR
return code). (Added in libcurl 7.7.2)
.TP .TP
.B CURLOPT_COOKIEFILE .B CURLOPT_COOKIEFILE
Pass a pointer to a zero terminated string as parameter. It should contain the Pass a pointer to a zero terminated string as parameter. It should contain the
@@ -344,12 +372,12 @@ file.
.B CURLOPT_SSLVERSION .B CURLOPT_SSLVERSION
Pass a long as parameter. Set what version of SSL to attempt to use, 2 or Pass a long as parameter. Set what version of SSL to attempt to use, 2 or
3. By default, the SSL library will try to solve this by itself although some 3. By default, the SSL library will try to solve this by itself although some
servers make this difficult why you at times will have to use this option. servers make this difficult why you at times may have to use this option.
.TP .TP
.B CURLOPT_TIMECONDITION .B CURLOPT_TIMECONDITION
Pass a long as parameter. This defines how the CURLOPT_TIMEVALUE time value is Pass a long as parameter. This defines how the CURLOPT_TIMEVALUE time value is
treated. You can set this parameter to TIMECOND_IFMODSINCE or treated. You can set this parameter to TIMECOND_IFMODSINCE or
TIMECOND_IFUNMODSINCE. This is aa HTTP-only feature. (TBD) TIMECOND_IFUNMODSINCE. This is a HTTP-only feature. (TBD)
.TP .TP
.B CURLOPT_TIMEVALUE .B CURLOPT_TIMEVALUE
Pass a long as parameter. This should be the time in seconds since 1 jan 1970, Pass a long as parameter. This should be the time in seconds since 1 jan 1970,
@@ -359,8 +387,8 @@ isn't used, it will be TIMECOND_IFMODSINCE by default.
.B CURLOPT_CUSTOMREQUEST .B CURLOPT_CUSTOMREQUEST
Pass a pointer to a zero terminated string as parameter. It will be user Pass a pointer to a zero terminated string as parameter. It will be user
instead of GET or HEAD when doing the HTTP request. This is useful for doing instead of GET or HEAD when doing the HTTP request. This is useful for doing
DELETE or other more obscure HTTP requests. Don't do this at will, make sure DELETE or other more or less obscure HTTP requests. Don't do this at will,
your server supports the command first. make sure your server supports the command first.
.TP .TP
.B CURLOPT_STDERR .B CURLOPT_STDERR
Pass a FILE * as parameter. This is the stream to use instead of stderr Pass a FILE * as parameter. This is the stream to use instead of stderr
@@ -378,29 +406,18 @@ krb4 awareness. This is a string, 'clear', 'safe', 'confidential' or
will be used. Set the string to NULL to disable kerberos4. The kerberos will be used. Set the string to NULL to disable kerberos4. The kerberos
support only works for FTP. (Added in libcurl 7.3) support only works for FTP. (Added in libcurl 7.3)
.TP .TP
.B CURLOPT_WRITEINFO
(NOT PRESENT IN 7.4 or later!)
Pass a pointer to a zero terminated string as parameter. It will be used to
report information after a successful request. This string may contain
variables that will be substituted by their contents when output. Described
elsewhere.
.TP
.B CURLOPT_PROGRESSFUNCTION .B CURLOPT_PROGRESSFUNCTION
Function pointer that should match the Function pointer that should match the \fIcurl_progress_callback\fP prototype
.BI curl_progress_callback found in \fI<curl/curl.h>\fP. This function gets called by libcurl instead of
prototype found in its internal equivalent with a frequent interval during data transfer.
.I <curl/curl.h> Unknown/unused argument values will be set to zero (like if you only download
This function gets called by libcurl instead of its internal data, the upload size will remain 0). Returning a non-zero value from this
equivalent. Unknown/unused argument values will be set to zero (like if you callback will cause libcurl to abort the transfer and return
only download data, the upload size will remain 0). Returning a non-zero value \fICURLE_ABORTED_BY_CALLBACK\fP.
from this callback will cause libcurl to abort the transfer and return
CURLE_ABORTED_BY_CALLBACK.
.TP .TP
.B CURLOPT_PROGRESSDATA .B CURLOPT_PROGRESSDATA
Pass a pointer that will be untouched by libcurl and passed as the first Pass a pointer that will be untouched by libcurl and passed as the first
argument in the progress callback set with argument in the progress callback set with \fICURLOPT_PROGRESSFUNCTION\fP.
.I CURLOPT_PROGRESSFUNCTION
.
.TP .TP
.B CURLOPT_SSL_VERIFYPEER .B CURLOPT_SSL_VERIFYPEER
Pass a long that is set to a non-zero value to make curl verify the peer's Pass a long that is set to a non-zero value to make curl verify the peer's
@@ -413,67 +430,66 @@ verify the peer with. This only makes sense when used in combination with the
CURLOPT_SSL_VERIFYPEER option. (Added in 7.4.2) CURLOPT_SSL_VERIFYPEER option. (Added in 7.4.2)
.TP .TP
.B CURLOPT_PASSWDFUNCTION .B CURLOPT_PASSWDFUNCTION
Pass a pointer to a curl_passwd_callback function that will then be called Pass a pointer to a \fIcurl_passwd_callback\fP function that will be called
instead of the internal one if libcurl requests a password. The function must instead of the internal one if libcurl requests a password. The function must
match this prototype: match this prototype: \fBint my_getpass(void *client, char *prompt, char*
.BI "int my_getpass(void *client, char *prompt, char* buffer, int buflen );" buffer, int buflen );\fP. If set to NULL, it equals to making the function
If set to NULL, it equals to making the function always fail. If the function always fail. If the function returns a non-zero value, it will abort the
returns a non-zero value, it will abort the operation and an error operation and an error (CURLE_BAD_PASSWORD_ENTERED) will be returned.
(CURLE_BAD_PASSWORD_ENTERED) will be returned. \fIclient\fP is a generic pointer, see \fICURLOPT_PASSWDDATA\fP. \fIprompt\fP
.I client
is a generic pointer, see CURLOPT_PASSWDDATA.
.I prompt
is a zero-terminated string that is text that prefixes the input request. is a zero-terminated string that is text that prefixes the input request.
.I buffer \fIbuffer\fP is a pointer to data where the entered password should be stored
is a pointer to data where the entered password should be stored and and \fIbuflen\fP is the maximum number of bytes that may be written in the
.I buflen buffer. (Added in 7.4.2)
is the maximum number of bytes that may be written in the buffer.
(Added in 7.4.2)
.TP .TP
.B CURLOPT_PASSWDDATA .B CURLOPT_PASSWDDATA
Pass a void * to whatever data you want. The passed pointer will be the first Pass a void * to whatever data you want. The passed pointer will be the first
argument sent to the specifed CURLOPT_PASSWDFUNCTION function. (Added in argument sent to the specifed \fICURLOPT_PASSWDFUNCTION\fP function. (Added in
7.4.2) 7.4.2)
.TP .TP
.B CURLOPT_FILETIME .B CURLOPT_FILETIME
Pass a long. If it is a non-zero value, libcurl will attempt to get the Pass a long. If it is a non-zero value, libcurl will attempt to get the
modification date of the remote document in this operation. This requires that modification date of the remote document in this operation. This requires that
the remote server sends the time or replies to a time querying command. The the remote server sends the time or replies to a time querying command. The
curl_easy_getinfo() function with the CURLINFO_FILETIME argument can be used \fIcurl_easy_getinfo(3)\fP function with the \fICURLINFO_FILETIME\fP argument
after a transfer to extract the received time (if any). (Added in 7.5) can be used after a transfer to extract the received time (if any). (Added in
7.5)
.TP .TP
.B CURLOPT_MAXREDIRS .B CURLOPT_MAXREDIRS
Pass a long. The set number will be the redirection limit. If that many Pass a long. The set number will be the redirection limit. If that many
redirections have been followed, the next redirect will cause an error. This redirections have been followed, the next redirect will cause an error
option only makes sense if the CURLOPT_FOLLOWLOCATION is used at the same (\fICURLE_TOO_MANY_REDIRECTS\fP). This option only makes sense if the
time. (Added in 7.5) \fICURLOPT_FOLLOWLOCATION\fP is used at the same time. (Added in 7.5)
.TP .TP
.B CURLOPT_MAXCONNECTS .B CURLOPT_MAXCONNECTS
Pass a long. The set number will be the persistant connection cache size. The Pass a long. The set number will be the persistant connection cache size. The
set amount will be the maximum amount of simultaneous connections that libcurl set amount will be the maximum amount of simultaneous connections that libcurl
may cache between file transfers. Default is 5, and there isn't much point in may cache between file transfers. Default is 5, and there isn't much point in
changing this value unless you are perfectly aware of how this work and changing this value unless you are perfectly aware of how this work and
changes libcurl's behaviour. Note: if you have already performed transfers changes libcurl's behaviour.
with this curl handle, setting a smaller MAXCONNECTS than before may cause
open connections to unnecessarily get closed. (Added in 7.7) \fBNOTE:\fP if you already have performed transfers with this curl handle,
setting a smaller MAXCONNECTS than before may cause open connections to get
closed unnecessarily. (Added in 7.7)
.TP .TP
.B CURLOPT_CLOSEPOLICY .B CURLOPT_CLOSEPOLICY
Pass a long. This option sets what policy libcurl should use when the Pass a long. This option sets what policy libcurl should use when the
connection cache is filled and one of the open connections has to be closed to connection cache is filled and one of the open connections has to be closed to
make room for a new connection. This must be one of the CURLCLOSEPOLICY_* make room for a new connection. This must be one of the CURLCLOSEPOLICY_*
defines. Use CURLCLOSEPOLICY_LEAST_RECENTLY_USED to make libcurl close the defines. Use \fICURLCLOSEPOLICY_LEAST_RECENTLY_USED\fP to make libcurl close
connection that was least recently used, that connection is also least likely the connection that was least recently used, that connection is also least
to be capable of re-use. Use CURLCLOSEPOLICY_OLDEST to make libcurl close the likely to be capable of re-use. Use \fICURLCLOSEPOLICY_OLDEST\fP to make
oldest connection, the one that was created first among the ones in the libcurl close the oldest connection, the one that was created first among the
connection cache. The other close policies are not support yet. (Added in 7.7) ones in the connection cache. The other close policies are not support
yet. (Added in 7.7)
.TP .TP
.B CURLOPT_FRESH_CONNECT .B CURLOPT_FRESH_CONNECT
Pass a long. Set to non-zero to make the next transfer use a new connection by Pass a long. Set to non-zero to make the next transfer use a new (fresh)
force. If the connection cache is full before this connection, one of the connection by force. If the connection cache is full before this connection,
existinf connections will be closed as according to the set policy. This one of the existing connections will be closed as according to the selected or
option should be used with caution and only if you understand what it default policy. This option should be used with caution and only if you
does. Set to 0 to have libcurl attempt re-use of an existing connection. understand what it does. Set this to 0 to have libcurl attempt re-using an
(Added in 7.7) existing connection (default behavior). (Added in 7.7)
.TP .TP
.B CURLOPT_FORBID_REUSE .B CURLOPT_FORBID_REUSE
Pass a long. Set to non-zero to make the next transfer explicitly close the Pass a long. Set to non-zero to make the next transfer explicitly close the
@@ -481,7 +497,7 @@ connection when done. Normally, libcurl keep all connections alive when done
with one transfer in case there comes a succeeding one that can re-use them. with one transfer in case there comes a succeeding one that can re-use them.
This option should be used with caution and only if you understand what it This option should be used with caution and only if you understand what it
does. Set to 0 to have libcurl keep the connection open for possibly later does. Set to 0 to have libcurl keep the connection open for possibly later
re-use. (Added in 7.7) re-use (default behavior). (Added in 7.7)
.TP .TP
.B CURLOPT_RANDOM_FILE .B CURLOPT_RANDOM_FILE
Pass a char * to a zero terminated file name. The file will be used to read Pass a char * to a zero terminated file name. The file will be used to read
@@ -497,11 +513,10 @@ Pass a long. It should contain the maximum time in seconds that you allow the
connection to the server to take. This only limits the connection phase, once connection to the server to take. This only limits the connection phase, once
it has connected, this option is of no more use. Set to zero to disable it has connected, this option is of no more use. Set to zero to disable
connection timeout (it will then only timeout on the system's internal connection timeout (it will then only timeout on the system's internal
timeouts). See also the timeouts). See also the \fICURLOPT_TIMEOUT\fP option.
.I CURLOPT_TIMEOUT
option. \fBNOTE:\fP this does not work in unix multi-threaded programs, as it uses
.B NOTE signals.
that this does not work in multi-threaded programs!
.TP .TP
.B CURLOPT_HTTPGET .B CURLOPT_HTTPGET
Pass a long. If the long is non-zero, this forces the HTTP request to get back Pass a long. If the long is non-zero, this forces the HTTP request to get back
@@ -512,12 +527,31 @@ previously using the same curl handle. (Added in 7.8.1)
Pass a long. Set if we should verify the Common name from the peer certificate Pass a long. Set if we should verify the Common name from the peer certificate
in the SSL handshake, set 1 to check existence, 2 to ensure that it matches in the SSL handshake, set 1 to check existence, 2 to ensure that it matches
the provided hostname. (Added in 7.8.1) the provided hostname. (Added in 7.8.1)
.TP
.B CURLOPT_COOKIEJAR
Pass a file name as char *, zero terminated. This will make libcurl dump all
internally known cookies to the specified file when \fIcurl_easy_cleanup(3)\fP
is called. If no cookies are known, no file will be created. Specify "-" to
instead have the cookies written to stdout.
.TP
.B CURLOPT_SSL_CIPHER_LIST
Pass a char *, pointing to a zero terminated string holding the list of
ciphers to use for the SSL connection. The list must be syntactly correct, it
consists of one or more cipher strings separated by colons. Commas or spaces
are also acceptable separators but colons are normally used, \!, \- and \+ can
be used as operators. Valid examples of cipher lists include 'RC4-SHA',
\'SHA1+DES\', 'TLSv1' and 'DEFAULT'. The default list is normally set when you
compile OpenSSL.
You'll find more details about cipher lists on this URL:
\fIhttp://www.openssl.org/docs/apps/ciphers.html\fP
.PP .PP
.SH RETURN VALUE .SH RETURN VALUE
0 means the option was set properly, non-zero means an error as CURLE_OK (zero) means that the option was set properly, non-zero means an
.I <curl/curl.h> error occurred as \fI<curl/curl.h>\fP defines.
defines
.SH "SEE ALSO" .SH "SEE ALSO"
.BR curl_easy_init "(3), " curl_easy_cleanup "(3), " .BR curl_easy_init "(3), " curl_easy_cleanup "(3), "
.SH BUGS .SH BUGS
Surely there are some, you tell me! If you find any bugs, or just have questions, subscribe to one of the mailing
lists and post. We won't bite.

158
docs/curl_formadd.3 Normal file
View File

@@ -0,0 +1,158 @@
.\" You can view this file with:
.\" nroff -man [file]
.\" $Id$
.\"
.TH curl_formadd 3 "29 October 2001" "libcurl 7.9.1" "libcurl Manual"
.SH NAME
curl_formadd - add a section to a multipart/formdata HTTP POST
.SH SYNOPSIS
.B #include <curl/curl.h>
.sp
.BI "int curl_formadd(struct HttpPost ** " firstitem,
.BI "struct HttpPost ** " lastitem, " ...);"
.ad
.SH DESCRIPTION
curl_formadd() is used to append sections when building a multipart/formdata
HTTP POST (sometimes refered to as rfc1867-style posts). Append one section at
a time until you've added all the sections you want included and then you pass
the \fIfirstitem\fP pointer as parameter to \fBCURLOPT_HTTPPOST\fP.
\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 faster.
After the \fIlastitem\fP pointer follow the real arguments. (If the following
description confuses you, jump directly to the examples):
\fBCURLFORM_COPYNAME\fP or \fBCURLFORM_PTRNAME\fP followed by a string is used
for the name of the section. Optionally one may use \fBCURLFORM_NAMELENGTH\fP
to specify the length of the name (allowing null characters within the
name). All options that use the word COPY in their names copy the given
contents, while the ones with PTR in their names simply points to the (static)
data you must make sure remain until curl no longer needs it.
The four options for providing values are: \fBCURLFORM_COPYCONTENTS\fP,
\fBCURLFORM_PTRCONTENTS\fP, \fBCURLFORM_FILE\fP, or \fBCURLFORM_FILECONTENT\fP
followed by a char or void pointer (allowed for PTRCONTENTS).
\fBCURLFORM_FILECONTENT\fP does a normal post like \fBCURLFORM_COPYCONTENTS\fP
but the actual value is read from the filename given as a string.
Other arguments may be \fBCURLFORM_CONTENTTYPE\fP if the user wishes to
specify one (for FILE if no type is given the library tries to provide the
correct one; for CONTENTS no Content-Type is sent in this case).
For \fBCURLFORM_PTRCONTENTS\fP or \fBCURLFORM_COPYNAME\fP the user may also
add \fBCURLFORM_CONTENTSLENGTH\fP followed by the length as a long (if not
given the library will use strlen to determine the length).
For \fBCURLFORM_FILE\fP the user may send multiple files in one section by
providing multiple \fBCURLFORM_FILE\fP arguments each followed by the filename
(and each FILE is allowed to have a CONTENTTYPE).
Another possibility to send single or multiple files in one section is to use
\fBCURLFORM_ARRAY\fP that gets a struct curl_forms array pointer as its
value. Each structure element has a CURLformoption and a char pointer. For the
options only \fBCURLFORM_FILE\fP, \fBCURLFORM_CONTENTTYPE\fP, and
\fBCURLFORM_END\fP (that is used to determine the end of the array and thus
must be the option of the last and no other element of the curl_forms array)
are allowed. The effect of this parameter is the same as giving multiple
\fBCURLFORM_FILE\fP options possibly with \fBCURLFORM_CONTENTTYPE\fP after or
before each \fBCURLFORM_FILE\fP option.
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
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 except the data pointed to by the
arguments after \fBCURLFORM_PTRNAME\fP and \fBCURLFORM_PTRCONTENTS\fP 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. If
you provide a pointer as an arguments after \fBCURLFORM_PTRNAME\fP or
\fBCURLFORM_PTRCONTENTS\fP you must ensure that the pointer stays valid until
you call \fIcurl_form_free\fP and \fIcurl_easy_cleanup\fP.
See example below.
.SH RETURN VALUE
Returns non-zero if an error occurs.
.SH EXAMPLE
.nf
HttpPost* post = NULL;
HttpPost* last = NULL;
char namebuffer[] = "name buffer";
long namelength = strlen(namebuffer);
char buffer[] = "test buffer";
char htmlbuffer[] = "<HTML>test buffer</HTML>";
long htmlbufferlength = strlen(htmlbuffer);
struct curl_forms forms[3];
char file1[] = "my-face.jpg";
char file2[] = "your-face.jpg";
/* add null character into htmlbuffer, to demonstrate that
transfers of buffers containing null characters actually work
*/
htmlbuffer[8] = '\\0';
/* Add simple name/content section */
curl_formadd(&post, &last, CURLFORM_COPYNAME, "name",
CURLFORM_COPYCONTENTS, "content", CURLFORM_END);
/* Add simple name/content/contenttype section */
curl_formadd(&post, &last, CURLFORM_COPYNAME, "htmlcode",
CURLFORM_COPYCONTENTS, "<HTML></HTML>",
CURLFORM_CONTENTTYPE, "text/html", CURLFORM_END);
/* Add name/ptrcontent section */
curl_formadd(&post, &last, CURLFORM_COPYNAME, "name_for_ptrcontent",
CURLFORM_PTRCONTENTS, buffer, CURLFORM_END);
/* Add ptrname/ptrcontent section */
curl_formadd(&post, &last, CURLFORM_PTRNAME, namebuffer,
CURLFORM_PTRCONTENTS, buffer, CURLFORM_NAMELENGTH,
namelength, CURLFORM_END);
/* Add name/ptrcontent/contenttype section */
curl_formadd(&post, &last, CURLFORM_COPYNAME, "html_code_with_hole",
CURLFORM_PTRCONTENTS, htmlbuffer,
CURLFORM_CONTENTSLENGTH, htmlbufferlength,
CURLFORM_CONTENTTYPE, "text/html", CURLFORM_END);
/* Add simple file section */
curl_formadd(&post, &last, CURLFORM_COPYNAME, "picture",
CURLFORM_FILE, "my-face.jpg", CURLFORM_END);
/* Add file/contenttype section */
curl_formadd(&post, &last, CURLFORM_COPYNAME, "picture",
CURLFORM_FILE, "my-face.jpg",
CURLFORM_CONTENTTYPE, "image/jpeg", CURLFORM_END);
/* Add two file section */
curl_formadd(&post, &last, CURLFORM_COPYNAME, "pictures",
CURLFORM_FILE, "my-face.jpg",
CURLFORM_FILE, "your-face.jpg", CURLFORM_END);
/* Add two file section using CURLFORM_ARRAY */
forms[0].option = CURLFORM_FILE;
forms[0].value = file1;
forms[1].option = CURLFORM_FILE;
forms[1].value = file2;
forms[2].option = CURLFORM_END;
/* no option needed for the end marker */
curl_formadd(&post, &last, CURLFORM_COPYNAME, "pictures",
CURLFORM_ARRAY, forms, CURLFORM_END);
/* Add the content of a file as a normal post text value */
curl_formadd(&post, &last, CURLFORM_COPYNAME, "filecontent",
CURLFORM_FILECONTENT, ".bashrc", CURLFORM_END);
/* Set the form info */
curl_easy_setopt(curl, CURLOPT_HTTPPOST, post);
.SH "SEE ALSO"
.BR curl_easy_setopt "(3), "
.BR curl_formparse "(3) [deprecated], "
.BR curl_formfree "(3)"
.SH BUGS
Surely there are some, you tell me!

View File

@@ -12,12 +12,14 @@ curl_formfree - free a previously build multipart/formdata HTTP POST chain
.ad .ad
.SH DESCRIPTION .SH DESCRIPTION
curl_formfree() is used to clean up data previously built/appended with curl_formfree() is used to clean up data previously built/appended with
curl_formparse(). This must be called when the data has been used, which curl_formadd()/curl_formparse(). This must be called when the data has
typically means after the curl_easy_perform() has been called. been used, which typically means after the curl_easy_perform() has
been called.
.SH RETURN VALUE .SH RETURN VALUE
None None
.SH "SEE ALSO" .SH "SEE ALSO"
.BR curl_formparse "(3) " .BR curl_formparse "(3) [deprecated], "
.BR curl_formadd "(3) "
.SH BUGS .SH BUGS
libcurl 7.7.1 and earlier versions does not allow a NULL pointer to be used as libcurl 7.7.1 and earlier versions does not allow a NULL pointer to be used as
argument. argument.

View File

@@ -4,7 +4,8 @@
.\" .\"
.TH curl_formparse 3 "21 May 2001" "libcurl 7.7.4" "libcurl Manual" .TH curl_formparse 3 "21 May 2001" "libcurl 7.7.4" "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)
.SH SYNOPSIS .SH SYNOPSIS
.B #include <curl/curl.h> .B #include <curl/curl.h>
.sp .sp
@@ -79,6 +80,7 @@ Returns non-zero if an error occurs.
.SH "SEE ALSO" .SH "SEE ALSO"
.BR curl_easy_setopt "(3), " .BR curl_easy_setopt "(3), "
.BR curl_formadd "(3), "
.BR curl_formfree "(3) .BR curl_formfree "(3)
.SH BUGS .SH BUGS
Surely there are some, you tell me! Surely there are some, you tell me!

View File

@@ -8,7 +8,7 @@ curl_slist_append - add a string to an slist
.SH SYNOPSIS .SH SYNOPSIS
.B #include <curl/curl.h> .B #include <curl/curl.h>
.sp .sp
.BI "struct curl_slist *curl_slist_append(struct curl_slit *" list, .BI "struct curl_slist *curl_slist_append(struct curl_slist *" list,
.BI "const char * "string ");" .BI "const char * "string ");"
.ad .ad
.SH DESCRIPTION .SH DESCRIPTION

View File

@@ -4,9 +4,9 @@
AUTOMAKE_OPTIONS = foreign no-dependencies AUTOMAKE_OPTIONS = foreign no-dependencies
EXTRA_DIST = README curlgtk.c sepheaders.c simple.c postit.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 multithread.c getinmemory.c ftpupload.c httpput.c
all: all:
@echo "done" @echo "done"

88
docs/examples/ftpupload.c Normal file
View File

@@ -0,0 +1,88 @@
/*****************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* $Id$
*/
#include <stdio.h>
#include <curl/curl.h>
/*
* This example shows an FTP upload, with a rename of the file just after
* a successful upload.
*
* Example based on source code provided by Erick Nuwendam. Thanks!
*/
#define LOCAL_FILE "/tmp/uploadthis.txt"
#define UPLOAD_FILE_AS "while-uploading.txt"
#define REMOTE_URL "ftp://localhost/" UPLOAD_FILE_AS
#define RENAME_FILE_TO "renamed-and-fine.txt"
int main(int argc, char **argv)
{
CURL *curl;
CURLcode res;
FILE *ftpfile;
FILE * hd_src ;
int hd ;
struct stat file_info;
struct curl_slist *headerlist=NULL;
char buf_1 [] = "RNFR " UPLOAD_FILE_AS;
char buf_2 [] = "RNTO " RENAME_FILE_TO;
/* get the file size of the local file */
hd = open(LOCAL_FILE, O_RDONLY) ;
fstat(hd, &file_info);
close(hd) ;
/* get a FILE * of the same file, could also be made with
fdopen() from the previous descriptor, but hey this is just
an example! */
hd_src = fopen(LOCAL_FILE, "rb");
/* In windows, this will init the winsock stuff */
curl_global_init(CURL_GLOBAL_ALL);
/* get a curl handle */
curl = curl_easy_init();
if(curl) {
/* build a list of commands to pass to libcurl */
headerlist = curl_slist_append(headerlist, buf_1);
headerlist = curl_slist_append(headerlist, buf_2);
/* enable uploading */
curl_easy_setopt(curl, CURLOPT_UPLOAD, TRUE) ;
/* specify target */
curl_easy_setopt(curl,CURLOPT_URL, REMOTE_URL);
/* pass in that last of FTP commands to run after the transfer */
curl_easy_setopt(curl, CURLOPT_POSTQUOTE, headerlist);
/* now specify which file to upload */
curl_easy_setopt(curl, CURLOPT_INFILE, hd_src);
/* and give the size of the upload (optional) */
curl_easy_setopt(curl, CURLOPT_INFILESIZE, file_info.st_size);
/* Now run off and do what you've been told! */
res = curl_easy_perform(curl);
/* clean up the FTP commands list */
curl_slist_free_all (headerlist);
/* always cleanup */
curl_easy_cleanup(curl);
}
fclose(hd_src); /* close the local file */
curl_global_cleanup();
return 0;
}

100
docs/examples/httpput.c Normal file
View File

@@ -0,0 +1,100 @@
/*****************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* $Id$
*/
#include <stdio.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <curl/curl.h>
/*
* This example shows a HTTP PUT operation. PUTs a file given as a command
* line argument to the URL also given on the command line.
*
* This example also uses its own read callback.
*/
size_t read_callback(void *ptr, size_t size, size_t nmemb, void *stream)
{
size_t retcode;
/* in real-world cases, this would probably get this data differently
as this fread() stuff is exactly what the library already would do
by default internally */
retcode = fread(ptr, size, nmemb, stream);
fprintf(stderr, "*** We read %d bytes from file\n", retcode);
return retcode;
}
int main(int argc, char **argv)
{
CURL *curl;
CURLcode res;
FILE *ftpfile;
FILE * hd_src ;
int hd ;
struct stat file_info;
char *file;
char *url;
if(argc < 3)
return 1;
file= argv[1];
url = argv[2];
/* get the file size of the local file */
hd = open(file, O_RDONLY) ;
fstat(hd, &file_info);
close(hd) ;
/* get a FILE * of the same file, could also be made with
fdopen() from the previous descriptor, but hey this is just
an example! */
hd_src = fopen(file, "rb");
/* In windows, this will init the winsock stuff */
curl_global_init(CURL_GLOBAL_ALL);
/* get a curl handle */
curl = curl_easy_init();
if(curl) {
/* we want to use our own read function */
curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_callback);
/* enable uploading */
curl_easy_setopt(curl, CURLOPT_UPLOAD, TRUE) ;
/* HTTP PUT please */
curl_easy_setopt(curl, CURLOPT_PUT, TRUE);
/* specify target */
curl_easy_setopt(curl,CURLOPT_URL, url);
/* now specify which file to upload */
curl_easy_setopt(curl, CURLOPT_INFILE, hd_src);
/* and give the size of the upload (optional) */
curl_easy_setopt(curl, CURLOPT_INFILESIZE, file_info.st_size);
/* Now run off and do what you've been told! */
res = curl_easy_perform(curl);
/* always cleanup */
curl_easy_cleanup(curl);
}
fclose(hd_src); /* close the local file */
curl_global_cleanup();
return 0;
}

92
docs/examples/postit2.c Normal file
View File

@@ -0,0 +1,92 @@
/*****************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* $Id$
*
* Example code that uploads a file name 'foo' to a remote script that accepts
* "HTML form based" (as described in RFC1738) uploads using HTTP POST.
*
* The imaginary form we'll fill in looks like:
*
* <form method="post" enctype="multipart/form-data" action="examplepost.cgi">
* Enter file: <input type="file" name="sendfile" size="40">
* Enter file name: <input type="text" name="filename" size="30">
* <input type="submit" value="send" name="submit">
* </form>
*
* This exact source code has not been verified to work.
*/
/* to make this work under windows, use the win32-functions from the
win32socket.c file as well */
#include <stdio.h>
#include <string.h>
#include <curl/curl.h>
#include <curl/types.h>
#include <curl/easy.h>
#if LIBCURL_VERSION_NUM < 0x070900
#error "curl_formadd() is not introduced until libcurl 7.9 and later"
#endif
int main(int argc, char *argv[])
{
CURL *curl;
CURLcode res;
struct HttpPost *formpost=NULL;
struct HttpPost *lastptr=NULL;
struct curl_slist *headerlist=NULL;
char buf[] = "Expect:";
/* Fill in the file upload field */
curl_formadd(&formpost,
&lastptr,
CURLFORM_COPYNAME, "sendfile",
CURLFORM_FILE, "postit2.c",
CURLFORM_END);
/* Fill in the filename field */
curl_formadd(&formpost,
&lastptr,
CURLFORM_COPYNAME, "filename",
CURLFORM_COPYCONTENTS, "postit2.c",
CURLFORM_END);
/* Fill in the submit field too, even if this is rarely needed */
curl_formadd(&formpost,
&lastptr,
CURLFORM_COPYNAME, "submit",
CURLFORM_COPYCONTENTS, "send",
CURLFORM_END);
curl = curl_easy_init();
/* initalize custom header list (stating that Expect: 100-continue is not
wanted */
headerlist = curl_slist_append(headerlist, buf);
if(curl) {
/* what URL that receives this POST */
curl_easy_setopt(curl, CURLOPT_URL, "http://curl.haxx.se/examplepost.cgi");
if ( (argc == 2) && (!strcmp(argv[1], "noexpectheader")) )
/* only disable 100-continue header if explicitly requested */
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerlist);
curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);
res = curl_easy_perform(curl);
/* always cleanup */
curl_easy_cleanup(curl);
/* then cleanup the formpost chain */
curl_formfree(formpost);
/* free slist */
curl_slist_free_all (headerlist);
}
return 0;
}

View File

@@ -53,11 +53,14 @@ portable environment variable reader
.B curl_easy_getinfo() .B curl_easy_getinfo()
get information about a performed transfer get information about a performed transfer
.TP .TP
.B curl_formparse() .B curl_formadd()
helps building a HTTP form POST helps building a HTTP form POST
.TP .TP
.B curl_formparse()
helps building a HTTP form POST (deprecated since 7.9 use curl_formadd()!)
.TP
.B curl_formfree() .B curl_formfree()
free a list built with curl_formparse() free a list built with curl_formparse()/curl_formadd()
.TP .TP
.B curl_slist_append() .B curl_slist_append()
builds a linked list builds a linked list

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.
@@ -58,13 +58,19 @@ extern "C" {
struct HttpPost { struct HttpPost {
struct HttpPost *next; /* next entry in the list */ struct HttpPost *next; /* next entry in the list */
char *name; /* pointer to allocated name */ char *name; /* pointer to allocated name */
long namelength; /* length of name length */
char *contents; /* pointer to allocated data contents */ char *contents; /* pointer to allocated data contents */
long contentslength; /* length of contents field */
char *contenttype; /* Content-Type */ char *contenttype; /* Content-Type */
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 */
#define HTTPPOST_FILENAME (1<<0) /* specified content is a file name */ #define HTTPPOST_FILENAME (1<<0) /* specified content is a file name */
#define HTTPPOST_READFILE (1<<1) /* specified content is a file name */ #define HTTPPOST_READFILE (1<<1) /* specified content is a file name */
#define HTTPPOST_PTRNAME (1<<2) /* name is only stored pointer
do not free in formfree */
#define HTTPPOST_PTRCONTENTS (1<<3) /* contents is only stored pointer
do not free in formfree */
}; };
typedef int (*curl_progress_callback)(void *clientp, typedef int (*curl_progress_callback)(void *clientp,
@@ -148,6 +154,7 @@ typedef enum {
CURLE_TELNET_OPTION_SYNTAX , /* 49 - Malformed telnet option */ CURLE_TELNET_OPTION_SYNTAX , /* 49 - Malformed telnet option */
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 */
CURL_LAST /* never use! */ CURL_LAST /* never use! */
} CURLcode; } CURLcode;
@@ -447,10 +454,33 @@ typedef enum {
* handshake, set 1 to check existence, 2 to ensure that it matches the * handshake, set 1 to check existence, 2 to ensure that it matches the
* provided hostname. */ * provided hostname. */
CINIT(SSL_VERIFYHOST, LONG, 81), CINIT(SSL_VERIFYHOST, LONG, 81),
/* Specify which file name to write all known cookies in after completed
operation. Set file name to "-" (dash) to make it go to stdout. */
CINIT(COOKIEJAR, OBJECTPOINT, 82),
/* Specify which SSL ciphers to use */
CINIT(SSL_CIPHER_LIST, OBJECTPOINT, 83),
/* Specify which HTTP version to use! This must be set to one of the
CURL_HTTP_VERSION* enums set below. */
CINIT(HTTP_VERSION, LONG, 84),
CURLOPT_LASTENTRY /* the last unusued */ CURLOPT_LASTENTRY /* the last unusued */
} CURLoption; } CURLoption;
/* These enums are for use with the CURLOPT_HTTP_VERSION option. */
enum {
CURL_HTTP_VERSION_NONE, /* setting this means we don't care, and that we'd
like the library to choose the best possible
for us! */
CURL_HTTP_VERSION_1_0, /* please use HTTP 1.0 in the request */
CURL_HTTP_VERSION_1_1, /* please use HTTP 1.1 in the request */
CURL_HTTP_VERSION_LAST /* *ILLEGAL* http version */
};
typedef enum { typedef enum {
TIMECOND_NONE, TIMECOND_NONE,
@@ -459,7 +489,7 @@ typedef enum {
TIMECOND_LASTMOD, TIMECOND_LASTMOD,
TIMECOND_LAST TIMECOND_LAST
} TimeCond; } curl_TimeCond;
#ifdef __BEOS__ #ifdef __BEOS__
#include <support/SupportDefs.h> #include <support/SupportDefs.h>
@@ -483,6 +513,44 @@ int curl_formparse(char *string,
struct HttpPost **httppost, struct HttpPost **httppost,
struct HttpPost **last_post); struct HttpPost **last_post);
/* name is uppercase CURLFORM_<name> */
#ifdef CFINIT
#undef CFINIT
#endif
#define CFINIT(name) CURLFORM_ ## name
typedef enum {
CFINIT(NOTHING), /********* the first one is unused ************/
/* */
CFINIT(COPYNAME),
CFINIT(PTRNAME),
CFINIT(NAMELENGTH),
CFINIT(COPYCONTENTS),
CFINIT(PTRCONTENTS),
CFINIT(CONTENTSLENGTH),
CFINIT(FILECONTENT),
CFINIT(ARRAY),
CFINIT(ARRAY_START), /* below are the options allowed within a array */
CFINIT(FILE),
CFINIT(CONTENTTYPE),
CFINIT(END),
CFINIT(ARRAY_END), /* up are the options allowed within a array */
CURLFORM_LASTENTRY /* the last unusued */
} CURLformoption;
/* structure to be used as parameter for CURLFORM_ARRAY */
struct curl_forms {
CURLformoption option;
const char *value;
};
/* new external form function */
int curl_formadd(struct HttpPost **httppost,
struct HttpPost **last_post,
...);
/* cleanup a form: */ /* cleanup a form: */
void curl_formfree(struct HttpPost *form); void curl_formfree(struct HttpPost *form);
@@ -495,8 +563,8 @@ char *curl_version(void);
/* Escape and unescape URL encoding in strings. The functions return a new /* Escape and unescape URL encoding in strings. The functions return a new
* allocated string or NULL if an error occurred. */ * allocated string or NULL if an error occurred. */
char *curl_escape(char *string, int length); char *curl_escape(const char *string, int length);
char *curl_unescape(char *string, int length); char *curl_unescape(const char *string, int length);
/* curl_global_init() should be invoked exactly once for each application that /* curl_global_init() should be invoked exactly once for each application that
uses libcurl */ uses libcurl */
@@ -507,8 +575,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.8.1" #define LIBCURL_VERSION "7.9.1"
#define LIBCURL_VERSION_NUM 0x070801 #define LIBCURL_VERSION_NUM 0x070901
/* 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

@@ -46,6 +46,21 @@ void curl_easy_cleanup(CURL *curl);
*/ */
CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ...); CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ...);
/*
* NAME curl_easy_duphandle()
*
* DESCRIPTION
*
* Creates a new curl session handle with the same options set for the handle
* passed in. Duplicating a handle could only be a matter of cloning data and
* options, internal state info and things like persistant connections cannot
* be transfered. It is useful in multithreaded applications when you can run
* curl_easy_duphandle() for each new thread to avoid a series of identical
* curl_easy_setopt() invokes in every thread.
*/
CURL* curl_easy_duphandle(CURL *curl);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@@ -1,134 +0,0 @@
/**
* The curl class is a JNI wrapper for libcurl. Please bear with me, I'm no
* true java dude (yet). Improve what you think is bad and send me the
* updates!
* daniel@haxx.se
*
* This is meant as a raw, crude and low-level interface to libcurl. If you
* want fancy stuff, build upon this.
*/
public class CurlGlue
{
// start of imported generated list, make a new list with
// define2java.pl on demand
public static final int CURLOPT_NOTHING = 0;
public static final int CURLOPT_FILE = 10001;
public static final int CURLOPT_URL = 10002;
public static final int CURLOPT_PORT = 3;
public static final int CURLOPT_PROXY = 10004;
public static final int CURLOPT_USERPWD = 10005;
public static final int CURLOPT_PROXYUSERPWD = 10006;
public static final int CURLOPT_RANGE = 10007;
public static final int CURLOPT_INFILE = 10009;
public static final int CURLOPT_ERRORBUFFER = 10010;
public static final int CURLOPT_WRITEFUNCTION = 20011;
public static final int CURLOPT_READFUNCTION = 20012;
public static final int CURLOPT_TIMEOUT = 13;
public static final int CURLOPT_INFILESIZE = 14;
public static final int CURLOPT_POSTFIELDS = 10015;
public static final int CURLOPT_REFERER = 10016;
public static final int CURLOPT_FTPPORT = 10017;
public static final int CURLOPT_USERAGENT = 10018;
public static final int CURLOPT_LOW_SPEED_LIMIT = 19;
public static final int CURLOPT_LOW_SPEED_TIME = 20;
public static final int CURLOPT_RESUME_FROM = 21;
public static final int CURLOPT_COOKIE = 10022;
public static final int CURLOPT_HTTPHEADER = 10023;
public static final int CURLOPT_HTTPPOST = 10024;
public static final int CURLOPT_SSLCERT = 10025;
public static final int CURLOPT_SSLCERTPASSWD = 10026;
public static final int CURLOPT_CRLF = 27;
public static final int CURLOPT_QUOTE = 10028;
public static final int CURLOPT_WRITEHEADER = 10029;
public static final int CURLOPT_COOKIEFILE = 10031;
public static final int CURLOPT_SSLVERSION = 32;
public static final int CURLOPT_TIMECONDITION = 33;
public static final int CURLOPT_TIMEVALUE = 34;
public static final int CURLOPT_HTTPREQUEST = 10035;
public static final int CURLOPT_CUSTOMREQUEST = 10036;
public static final int CURLOPT_STDERR = 10037;
public static final int CURLOPT_POSTQUOTE = 10039;
public static final int CURLOPT_WRITEINFO = 10040;
public static final int CURLOPT_VERBOSE = 41;
public static final int CURLOPT_HEADER = 42;
public static final int CURLOPT_NOPROGRESS = 43;
public static final int CURLOPT_NOBODY = 44;
public static final int CURLOPT_FAILONERROR = 45;
public static final int CURLOPT_UPLOAD = 46;
public static final int CURLOPT_POST = 47;
public static final int CURLOPT_FTPLISTONLY = 48;
public static final int CURLOPT_FTPAPPEND = 50;
public static final int CURLOPT_NETRC = 51;
public static final int CURLOPT_FOLLOWLOCATION = 52;
public static final int CURLOPT_FTPASCII = 53;
public static final int CURLOPT_TRANSFERTEXT = 53;
public static final int CURLOPT_PUT = 54;
public static final int CURLOPT_MUTE = 55;
public static final int CURLOPT_PROGRESSFUNCTION = 20056;
public static final int CURLOPT_PROGRESSDATA = 10057;
public static final int CURLOPT_AUTOREFERER = 58;
public static final int CURLOPT_PROXYPORT = 59;
public static final int CURLOPT_POSTFIELDSIZE = 60;
public static final int CURLOPT_HTTPPROXYTUNNEL = 61;
public static final int CURLOPT_INTERFACE = 10062;
public static final int CURLOPT_KRB4LEVEL = 10063;
public static final int CURLOPT_SSL_VERIFYPEER = 64;
public static final int CURLOPT_CAINFO = 10065;
public static final int CURLOPT_PASSWDFUNCTION = 20066;
public static final int CURLOPT_PASSWDDATA = 10067;
public static final int CURLOPT_MAXREDIRS = 68;
public static final int CURLOPT_FILETIME = 10069;
public static final int CURLOPT_TELNETOPTIONS = 10070;
public static final int CURLOPT_MAXCONNECTS = 71;
public static final int CURLOPT_CLOSEPOLICY = 72;
public static final int CURLOPT_CLOSEFUNCTION = 20073;
public static final int CURLOPT_FRESH_CONNECT = 74;
public static final int CURLOPT_FORBID_REUSE = 75;
public static final int CURLOPT_RANDOM_FILE = 10076;
public static final int CURLOPT_EGDSOCKET = 10077;
public static final int CURLOPT_CONNECTTIMEOUT = 78;
public static final int CURLOPT_HEADERFUNCTION = 20079;
// end of generated list
public CurlGlue() {
javacurl_handle = jni_init();
}
public void finalize() {
jni_cleanup(javacurl_handle);
}
private int javacurl_handle;
/* constructor and destructor for the libcurl handle */
private native int jni_init();
private native void jni_cleanup(int javacurl_handle);
private native synchronized int jni_perform(int javacurl_handle);
// Instead of varargs, we have different functions for each
// kind of type setopt() can take
private native int jni_setopt(int libcurl, int option, String value);
private native int jni_setopt(int libcurl, int option, int value);
private native int jni_setopt(int libcurl, int option, CurlWrite value);
public native int getinfo();
public int perform() {
return jni_perform(javacurl_handle);
}
public int setopt(int option, int value) {
return jni_setopt(javacurl_handle, option, value);
}
public int setopt(int option, String value) {
return jni_setopt(javacurl_handle, option, value);
}
public int setopt(int option, CurlWrite value) {
return jni_setopt(javacurl_handle, option, value);
}
static {
System.loadLibrary("javacurl");
}
}

View File

@@ -1,9 +0,0 @@
public interface CurlWrite
{
/**
* handleString gets called by libcurl on each chunk of data
* we receive from the remote server
*/
public int handleString(byte s[]);
}

View File

@@ -1,35 +0,0 @@
TARGET = libjavacurl.so
OBJS = javacurl.o
CC = gcc
CFLAGS = -c
CPPFLAGS = -I/usr/j2se/include -I/usr/local/include -I/usr/j2se/include/solaris
# Linux might use -shared -Wl,-soname,libnative.so instead of -G
LDFLAGS = -G -lcurl -ldl -L/usr/local/ssl/lib -lssl -lcrypto
all: CurlGlue.h CurlGlue.class javacurl.o $(TARGET) test.class
test:
java test
javacurl.o: javacurl.c CurlGlue.h
$(CC) $(CPPFLAGS) $(CFLAGS) $<
CurlGlue.h: CurlGlue.java CurlGlue.class
javah CurlGlue
touch CurlGlue.h
test.class: CurlGlue.class javacurl.o
javac test.java
CurlGlue.class: CurlGlue.java
javac $<
$(TARGET): $(OBJS)
$(CC) -o $(TARGET) $(LDFLAGS) $(OBJS)
clean:
rm -f javacurl.o CurlGlue.h CurlGlue.class

View File

@@ -1,15 +0,0 @@
_ _ ____ _
___| | | | _ \| |
/ __| | | | |_) | |
| (__| |_| | _ <| |___
\___|\___/|_| \_\_____|
Java Interface
This is not a complete implementation of a libcurl interface. I've made the
core work and it needs additional code to be added to get the rest of the
stuff supported.
The interface is not set yet, bring your suggestions!
Feel free to grab the source files in here and help out!

View File

@@ -1,22 +0,0 @@
#!/usr/bin/perl
open(GCC, "gcc -E ../include/curl/curl.h|");
while(<GCC>) {
if($_ =~ /(CURLOPT_(.*)) += (.*)/) {
$var= $1;
$expr = $3;
$f=$3;
if($expr =~ / *(\d+) *\+ *(\d+)/) {
$expr = $1+$2;
}
# nah, keep the CURL prefix to make them look like other
# languages' defines
# $var =~ s/^CURL//g;
print " public static final int $var = $expr;\n";
}
}
close(GCC);

View File

@@ -1,196 +0,0 @@
#include <curl/curl.h> /* libcurl header */
#include "CurlGlue.h" /* the JNI-generated glue header file */
/*
* This is a private struct allocated for every 'CurlGlue' object.
*/
struct javacurl {
void *libcurl;
void *whatever;
struct writecallback {
jmethodID mid;
JNIEnv *java;
jclass cls; /* global reference */
jobject object;
} write;
};
JNIEXPORT jint JNICALL Java_CurlGlue_jni_1init(JNIEnv *java,
jobject myself)
{
void *libhandle;
struct javacurl *jcurl=NULL;
libhandle = curl_easy_init();
if(libhandle) {
jcurl=(struct javacurl *)malloc(sizeof(struct javacurl));
if(jcurl) {
memset(jcurl, 0, sizeof(struct javacurl));
jcurl->libcurl = libhandle;
}
else {
curl_easy_cleanup(libhandle);
return (jint)0;
}
}
return (jint) jcurl; /* nasty typecast */
}
JNIEXPORT void JNICALL Java_CurlGlue_jni_1cleanup(JNIEnv *java,
jobject myself,
jint jcurl)
{
struct javacurl *curl = (struct javacurl*)jcurl;
if(curl->write.cls) {
/* a global reference we must delete */
(*java)->DeleteGlobalRef(java, curl->write.cls);
(*java)->DeleteGlobalRef(java, curl->write.object);
}
curl_easy_cleanup(curl->libcurl); /* cleanup libcurl stuff */
free((void *)curl); /* free the struct too */
}
/*
* setopt() int + string
*/
JNIEXPORT jint JNICALL Java_CurlGlue_jni_1setopt__IILjava_lang_String_2
(JNIEnv *java, jobject myself, jint jcurl, jint option, jstring value)
{
/* get the actual string C-style */
const char *str = (*java)->GetStringUTFChars(java, value, 0);
void *handle = (void *)((struct javacurl*)jcurl)->libcurl;
puts("setopt int + string");
return (jint)curl_easy_setopt(handle, (CURLoption)option, str);
}
/*
* setopt() int + int
*/
JNIEXPORT jint JNICALL Java_CurlGlue_jni_1setopt__III
(JNIEnv *java, jobject myself, jint jcurl, jint option, jint value)
{
void *handle = (void *)((struct javacurl*)jcurl)->libcurl;
CURLoption opt = (CURLoption)option;
puts("setopt int + int");
switch(opt) {
case CURLOPT_FILE:
/* silently ignored, we don't need user-specified callback data when
we have an object, and besides the CURLOPT_FILE is not exported
to the java interface */
return 0;
}
return (jint)curl_easy_setopt(handle, (CURLoption)option, value);
}
static int javacurl_write_callback(void *ptr,
size_t size,
size_t nmemb,
FILE *stream)
{
struct javacurl *curl = (struct javacurl *)stream;
size_t realsize = size * nmemb;
JNIEnv *java = curl->write.java;
jbyteArray jb=NULL;
int ret=0;
fprintf(stderr, "%d bytes data received in callback:\n"
"ptr=%p, java=%p cls=%p\n",
realsize, curl, java, curl->write.cls);
jb=(*java)->NewByteArray(java, realsize);
(*java)->SetByteArrayRegion(java, jb, 0,
realsize, (jbyte *)ptr);
fprintf(stderr, "created byte-array\n");
ret = (*java)->CallIntMethod(java,
curl->write.object,
curl->write.mid,
jb);
fprintf(stderr, "java-method returned %d\n", ret);
return realsize;
}
/*
* setopt() int + object
*/
JNIEXPORT jint JNICALL Java_CurlGlue_jni_1setopt__IILCurlWrite_2
(JNIEnv *java, jobject myself, jint jcurl, jint option, jobject object)
{
jclass cls_local = (*java)->GetObjectClass(java, object);
jmethodID mid;
struct javacurl *curl = (struct javacurl *)jcurl;
jclass cls;
jobject obj_global;
switch(option) {
case CURLOPT_WRITEFUNCTION:
/* this makes a reference that'll be alive until we kill it! */
cls = (*java)->NewGlobalRef(java, cls_local);
printf("setopt int + object, option = %d cls= %p\n",
option, cls);
if(!cls) {
puts("couldn't make local reference global");
return 0;
}
/* this is the write callback */
mid = (*java)->GetMethodID(java, cls, "handleString", "([B)I");
if(!mid) {
puts("no callback method found");
return 0;
}
obj_global = (*java)->NewGlobalRef(java, object);
curl->write.mid = mid;
curl->write.cls = cls;
curl->write.object = obj_global;
/*curl->write.java = java; stored on perform */
fprintf(stderr, "setopt write callback and write file pointer %p, java = %p\n",
curl, java);
curl_easy_setopt(curl->libcurl, CURLOPT_WRITEFUNCTION,
javacurl_write_callback);
curl_easy_setopt(curl->libcurl, CURLOPT_FILE,
curl);
break;
}
return 0;
}
JNIEXPORT jint JNICALL Java_CurlGlue_getinfo
(JNIEnv *java, jobject value)
{
return 0;
}
JNIEXPORT jint JNICALL Java_CurlGlue_jni_1perform
(JNIEnv *java, jobject myself, jint jcurl)
{
struct javacurl *curl=(struct javacurl*)jcurl;
curl->write.java = java;
return (jint)curl_easy_perform(curl->libcurl);
}

View File

@@ -1,27 +0,0 @@
import CurlGlue;
import CurlWrite;
class test implements CurlWrite {
public int handleString(byte s[])
{
/* output everything */
System.out.println("IIIIIIIIIII -------------- OOOOOOOOOOOOOOOOOOO");
try {
System.out.write(s);
}
catch (java.io.IOException moo) {
// nothing
}
return 0;
}
public static void main(String[] args)
{
CurlGlue cg = new CurlGlue();
test cw = new test();
cg.setopt(CurlGlue.CURLOPT_URL, "http://www.contactor.se/");
cg.setopt(CurlGlue.CURLOPT_WRITEFUNCTION, cw);
cg.perform();
}
}

View File

@@ -16,7 +16,7 @@ lib_LTLIBRARIES = libcurl.la
INCLUDES = -I$(top_srcdir)/include INCLUDES = -I$(top_srcdir)/include
libcurl_la_LDFLAGS = -version-info 2:1:0 libcurl_la_LDFLAGS = -no-undefined -version-info 2:2:0
# This flag accepts an argument of the form current[:revision[:age]]. So, # This flag accepts an argument of the form current[:revision[:age]]. So,
# passing -version-info 3:12:1 sets current to 3, revision to 12, and age to # passing -version-info 3:12:1 sets current to 3, revision to 12, and age to
# 1. # 1.
@@ -59,7 +59,7 @@ 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 http_chunks.c http_chunks.h strtok.c strtok.h connect.c connect.h
noinst_HEADERS = setup.h transfer.h noinst_HEADERS = setup.h transfer.h

View File

@@ -58,7 +58,8 @@ SOURCES = \
version.c \ version.c \
easy.c \ easy.c \
strequal.c \ strequal.c \
strtok.c strtok.c \
connect.c
OBJECTS = $(SOURCES:.c=.obj) OBJECTS = $(SOURCES:.c=.obj)

View File

@@ -1,5 +1,4 @@
############################################################# #############################################################
# $Id$
# #
## Makefile for building libcurl.a with MingW32 (GCC-2.95) and ## Makefile for building libcurl.a with MingW32 (GCC-2.95) and
## optionally OpenSSL (0.9.6) ## optionally OpenSSL (0.9.6)
@@ -12,7 +11,7 @@ CC = gcc
AR = ar AR = ar
RANLIB = ranlib RANLIB = ranlib
STRIP = strip -g STRIP = strip -g
OPENSSL_PATH = ../../openssl-0.9.6 OPENSSL_PATH = ../../openssl-0.9.6b
######################################################## ########################################################
## Nothing more to do below this line! ## Nothing more to do below this line!
@@ -36,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 strtok.c connect.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 strtok.o connect.o
LIBRARIES = $(libcurl_a_LIBRARIES) LIBRARIES = $(libcurl_a_LIBRARIES)
SOURCES = $(libcurl_a_SOURCES) SOURCES = $(libcurl_a_SOURCES)
@@ -62,7 +61,7 @@ libcurl.a: $(libcurl_a_OBJECTS) $(libcurl_a_DEPENDENCIES)
libcurl.dll libcurldll.a: libcurl.a libcurl.def dllinit.o libcurl.dll libcurldll.a: libcurl.a libcurl.def dllinit.o
-@erase $@ -@erase $@
dllwrap --dllname $@ --output-lib libcurldll.a --export-all --def libcurl.def $(libcurl_a_LIBRARIES) dllinit.o -L$(OPENSSL_PATH)/out $(DLL_LIBS) -lwsock32 dllwrap --dllname $@ --output-lib libcurldll.a --export-all --def libcurl.def $(libcurl_a_LIBRARIES) dllinit.o -L$(OPENSSL_PATH)/out $(DLL_LIBS) -lwsock32 -lws2_32
$(STRIP) $@ $(STRIP) $@
# remove the last line above to keep debug info # remove the last line above to keep debug info

View File

@@ -1,11 +1,10 @@
############################################################# #############################################################
# $Id: Makefile.am,v 1.20 2001/08/08 07:46:44 bagder Exp $
# #
## Makefile for building libcurl.lib with MSVC6 ## Makefile for building libcurl.lib with MSVC6
## Use: nmake -f makefile.vc6 [release | release-ssl | debug] ## Use: nmake -f makefile.vc6 [release | release-ssl | debug]
## (default is release) ## (default is release)
## ##
## Comments to: Troy Engel <tengel@sonic.net> ## Originally written by: Troy Engel <tengel@sonic.net>
## Updated by: Craig Davison <cd@securityfocus.com> ## Updated by: Craig Davison <cd@securityfocus.com>
## Updated by: SM <sm@technologist.com> ## Updated by: SM <sm@technologist.com>
@@ -30,7 +29,7 @@ LINKRS = link.exe -lib /out:$(PROGRAM_NAME) /LIBPATH:$(OPENSSL_PATH)/out32dll
CFLAGS = /I "../include" /nologo /W3 /GX /D "WIN32" /D "VC6" /D "_MBCS" /D "_LIB" /YX /FD /c /D "MSDOS" CFLAGS = /I "../include" /nologo /W3 /GX /D "WIN32" /D "VC6" /D "_MBCS" /D "_LIB" /YX /FD /c /D "MSDOS"
LFLAGS = /nologo LFLAGS = /nologo
LINKLIBS = wsock32.lib LINKLIBS = ws2_32.lib
LINKSLIBS = libeay32.lib ssleay32.lib RSAglue.lib LINKSLIBS = libeay32.lib ssleay32.lib RSAglue.lib
RELEASE_OBJS= \ RELEASE_OBJS= \
@@ -63,7 +62,8 @@ RELEASE_OBJS= \
versionr.obj \ versionr.obj \
easyr.obj \ easyr.obj \
strequalr.obj \ strequalr.obj \
strtokr.obj strtokr.obj \
connectr.obj
DEBUG_OBJS= \ DEBUG_OBJS= \
base64d.obj \ base64d.obj \
@@ -95,7 +95,8 @@ DEBUG_OBJS= \
versiond.obj \ versiond.obj \
easyd.obj \ easyd.obj \
strequald.obj \ strequald.obj \
strtokd.obj strtokd.obj \
connectd.obj
RELEASE_SSL_OBJS= \ RELEASE_SSL_OBJS= \
base64rs.obj \ base64rs.obj \
@@ -127,7 +128,8 @@ RELEASE_SSL_OBJS= \
versionrs.obj \ versionrs.obj \
easyrs.obj \ easyrs.obj \
strequalrs.obj \ strequalrs.obj \
strtokd.obj strtokrs.obj \
connectrs.obj
LINK_OBJS= \ LINK_OBJS= \
base64.obj \ base64.obj \
@@ -159,7 +161,8 @@ LINK_OBJS= \
version.obj \ version.obj \
easy.obj \ easy.obj \
strequal.obj \ strequal.obj \
strtok.obj strtok.obj \
connect.obj
all : release all : release
@@ -233,6 +236,8 @@ strequalr.obj: strequal.c
$(CCR) $(CFLAGS) strequal.c $(CCR) $(CFLAGS) strequal.c
strtokr.obj:strtok.c strtokr.obj:strtok.c
$(CCR) $(CFLAGS) strtok.c $(CCR) $(CFLAGS) strtok.c
connectr.obj:connect.c
$(CCR) $(CFLAGS) connect.c
## Debug ## Debug
base64d.obj: base64.c base64d.obj: base64.c
@@ -295,6 +300,8 @@ strequald.obj: strequal.c
$(CCD) $(CFLAGS) strequal.c $(CCD) $(CFLAGS) strequal.c
strtokd.obj:strtok.c strtokd.obj:strtok.c
$(CCD) $(CFLAGS) strtok.c $(CCD) $(CFLAGS) strtok.c
connectd.obj:connect.c
$(CCR) $(CFLAGS) connect.c
## Release SSL ## Release SSL
base64rs.obj: base64.c base64rs.obj: base64.c
@@ -310,7 +317,7 @@ formdatars.obj: formdata.c
ftprs.obj: ftp.c ftprs.obj: ftp.c
$(CCRS) $(CFLAGS) ftp.c $(CCRS) $(CFLAGS) ftp.c
httprs.obj: http.c httprs.obj: http.c
$(CCR) $(CFLAGS) http.c $(CCRS) $(CFLAGS) http.c
http_chunksrs.obj: http_chunks.c http_chunksrs.obj: http_chunks.c
$(CCRS) $(CFLAGS) http_chunks.c $(CCRS) $(CFLAGS) http_chunks.c
ldaprs.obj: ldap.c ldaprs.obj: ldap.c
@@ -357,7 +364,8 @@ strequalrs.obj: strequal.c
$(CCRS) $(CFLAGS) strequal.c $(CCRS) $(CFLAGS) strequal.c
strtokrs.obj:strtok.c strtokrs.obj:strtok.c
$(CCRS) $(CFLAGS) strtok.c $(CCRS) $(CFLAGS) strtok.c
connectrs.obj:connect.c
$(CCR) $(CFLAGS) connect.c
clean: clean:
-@erase *.obj -@erase *.obj

View File

@@ -32,9 +32,8 @@
* This code will break if int is smaller than 32 bits * This code will break if int is smaller than 32 bits
*/ */
#ifdef HAVE_CONFIG_H #include "setup.h"
#include <config.h>
#endif
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@@ -261,3 +260,11 @@ void *suck(int *lenptr) {
} }
#endif #endif
/*
* local variables:
* eval: (load-file "../curl-mode.el")
* end:
* vim600: fdm=marker
* vim: et sw=2 ts=2 sts=2 tw=78
*/

562
lib/connect.c Normal file
View File

@@ -0,0 +1,562 @@
/*****************************************************************************
* _ _ ____ _
* 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"
#ifndef WIN32
/* headers for non-win32 */
#include <sys/time.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAVE_NETDB_H
#include <netdb.h>
#endif
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
#endif
#include <stdio.h>
#include <errno.h>
#include <string.h>
#ifndef TRUE
#define TRUE 1
#define FALSE 0
#endif
#ifdef WIN32
#define HAVE_IOCTLSOCKET
#include <windows.h>
#include <winsock.h>
#define EINPROGRESS WSAEINPROGRESS
#define EWOULDBLOCK WSAEWOULDBLOCK
#endif
#include "urldata.h"
#include "sendf.h"
#include "if2ip.h"
/* The last #include file should be: */
#ifdef MALLOCDEBUG
#include "memdebug.h"
#endif
static
int geterrno(void)
{
#ifdef WIN32
return (int)GetLastError();
#else
return errno;
#endif
}
/*************************************************************************
* Curl_nonblock
*
* Description:
* Set the socket to either blocking or non-blocking mode.
*/
int Curl_nonblock(int socket, /* operate on this */
int nonblock /* TRUE or FALSE */)
{
#undef SETBLOCK
#ifdef HAVE_O_NONBLOCK
int flags;
flags = fcntl(socket, F_GETFL, 0);
if (TRUE == nonblock)
return fcntl(socket, F_SETFL, flags | O_NONBLOCK);
else
return fcntl(socket, F_SETFL, flags & (~O_NONBLOCK));
#define SETBLOCK 1
#endif
#ifdef HAVE_FIONBIO
int flags;
flags = nonblock;
return ioctl(socket, FIONBIO, &flags);
#define SETBLOCK 2
#endif
#ifdef HAVE_IOCTLSOCKET
int flags;
flags = nonblock;
return ioctlsocket(socket, FIONBIO, &flags);
#define SETBLOCK 3
#endif
#ifdef HAVE_IOCTLSOCKET_CASE
return IoctlSocket(socket, FIONBIO, (long)nonblock);
#define SETBLOCK 4
#endif
#ifdef HAVE_DISABLED_NONBLOCKING
return 0; /* returns success */
#define SETBLOCK 5
#endif
#ifndef SETBLOCK
#error "no non-blocking method was found/used/set"
#endif
}
/*
* Return 0 on fine connect, -1 on error and 1 on timeout.
*/
static
int waitconnect(int sockfd, /* socket */
int timeout_msec)
{
fd_set fd;
fd_set errfd;
struct timeval interval;
int rc;
/* now select() until we get connect or timeout */
FD_ZERO(&fd);
FD_SET(sockfd, &fd);
FD_ZERO(&errfd);
FD_SET(sockfd, &errfd);
interval.tv_sec = timeout_msec/1000;
timeout_msec -= interval.tv_sec*1000;
interval.tv_usec = timeout_msec*1000;
rc = select(sockfd+1, NULL, &fd, &errfd, &interval);
if(-1 == rc)
/* error, no connect here, try next */
return -1;
else if(0 == rc)
/* timeout, no connect today */
return 1;
if(FD_ISSET(sockfd, &errfd)) {
/* error condition caught */
return 2;
}
/* we have a connect! */
return 0;
}
#ifndef ENABLE_IPV6
static CURLcode bindlocal(struct connectdata *conn,
int sockfd)
{
#if !defined(WIN32)||defined(__CYGWIN32__)
/* We don't generally like checking for OS-versions, we should make this
HAVE_XXXX based, although at the moment I don't have a decent test for
this! */
#ifdef HAVE_INET_NTOA
#ifndef INADDR_NONE
#define INADDR_NONE (unsigned long) ~0
#endif
struct SessionHandle *data = conn->data;
/*************************************************************
* Select device to bind socket to
*************************************************************/
if (strlen(data->set.device)<255) {
struct sockaddr_in sa;
struct hostent *h=NULL;
char *hostdataptr=NULL;
size_t size;
char myhost[256] = "";
unsigned long in;
if(Curl_if2ip(data->set.device, myhost, sizeof(myhost))) {
h = Curl_getaddrinfo(data, myhost, 0, &hostdataptr);
}
else {
if(strlen(data->set.device)>1) {
h = Curl_getaddrinfo(data, data->set.device, 0, &hostdataptr);
}
if(h) {
/* we know data->set.device is shorter than the myhost array */
strcpy(myhost, data->set.device);
}
}
if(! *myhost) {
/* need to fix this
h=Curl_gethost(data,
getmyhost(*myhost,sizeof(myhost)),
hostent_buf,
sizeof(hostent_buf));
*/
if(hostdataptr)
free(hostdataptr); /* allocated by Curl_getaddrinfo() */
return CURLE_HTTP_PORT_FAILED;
}
infof(data, "We bind local end to %s\n", myhost);
if ( (in=inet_addr(myhost)) != INADDR_NONE ) {
if ( h ) {
memset((char *)&sa, 0, sizeof(sa));
memcpy((char *)&sa.sin_addr,
h->h_addr,
h->h_length);
sa.sin_family = AF_INET;
sa.sin_addr.s_addr = in;
sa.sin_port = 0; /* get any port */
if( bind(sockfd, (struct sockaddr *)&sa, sizeof(sa)) >= 0) {
/* we succeeded to bind */
struct sockaddr_in add;
size = sizeof(add);
if(getsockname(sockfd, (struct sockaddr *) &add,
(socklen_t *)&size)<0) {
failf(data, "getsockname() failed");
return CURLE_HTTP_PORT_FAILED;
}
}
else {
switch(errno) {
case EBADF:
failf(data, "Invalid descriptor: %d", errno);
break;
case EINVAL:
failf(data, "Invalid request: %d", errno);
break;
case EACCES:
failf(data, "Address is protected, user not superuser: %d", errno);
break;
case ENOTSOCK:
failf(data,
"Argument is a descriptor for a file, not a socket: %d",
errno);
break;
case EFAULT:
failf(data, "Inaccessable memory error: %d", errno);
break;
case ENAMETOOLONG:
failf(data, "Address too long: %d", errno);
break;
case ENOMEM:
failf(data, "Insufficient kernel memory was available: %d", errno);
break;
default:
failf(data, "errno %d\n", errno);
break;
} /* end of switch(errno) */
return CURLE_HTTP_PORT_FAILED;
} /* end of else */
} /* end of if h */
else {
failf(data,"could't find my own IP address (%s)", myhost);
return CURLE_HTTP_PORT_FAILED;
}
} /* end of inet_addr */
else {
failf(data, "could't find my own IP address (%s)", myhost);
return CURLE_HTTP_PORT_FAILED;
}
if(hostdataptr)
free(hostdataptr); /* allocated by Curl_getaddrinfo() */
return CURLE_OK;
} /* end of device selection support */
#endif /* end of HAVE_INET_NTOA */
#endif /* end of not WIN32 */
return CURLE_HTTP_PORT_FAILED;
}
#else /* end of ipv4-specific section */
/* we only use socketerror() on IPv6-enabled machines */
static
int socketerror(int sockfd)
{
int err = 0;
socklen_t errSize = sizeof(err);
if( -1 == getsockopt(sockfd, SOL_SOCKET, SO_ERROR,
(void *)&err, &errSize))
err = geterrno();
return err;
}
#endif
/*
* TCP connect to the given host with timeout, proxy or remote doesn't matter.
* There might be more than one IP address to try out. Fill in the passed
* pointer with the connected socket.
*/
CURLcode Curl_connecthost(struct connectdata *conn, /* context */
Curl_addrinfo *remotehost, /* use one in here */
int port, /* connect to this */
int *sockconn, /* the connected socket */
Curl_ipconnect **addr) /* the one we used */
{
struct SessionHandle *data = conn->data;
int rc;
int sockfd=-1;
int aliasindex=0;
struct timeval after;
struct timeval before = Curl_tvnow();
/*************************************************************
* Figure out what maximum time we have left
*************************************************************/
long timeout_ms=300000; /* milliseconds, default to five minutes */
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 */
return CURLE_OPERATION_TIMEOUTED;
}
#ifdef ENABLE_IPV6
/*
* Connecting with IPv6 support is so much easier and cleanly done
*/
{
struct addrinfo *ai;
port =0; /* prevent compiler warning */
for (ai = remotehost; ai; ai = ai->ai_next, aliasindex++) {
sockfd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
if (sockfd < 0)
continue;
/* set socket non-blocking */
Curl_nonblock(sockfd, TRUE);
rc = connect(sockfd, ai->ai_addr, ai->ai_addrlen);
if(-1 == rc) {
int error=geterrno();
switch (error) {
case EINPROGRESS:
case EWOULDBLOCK:
#if defined(EAGAIN) && EAGAIN != EWOULDBLOCK
/* On some platforms EAGAIN and EWOULDBLOCK are the
* same value, and on others they are different, hence
* the odd #if
*/
case EAGAIN:
#endif
case EINTR:
/* asynchronous connect, wait for connect or timeout */
rc = waitconnect(sockfd, timeout_ms);
break;
case ECONNREFUSED: /* no one listening */
default:
/* unknown error, fallthrough and try another address! */
failf(data, "Failed to connect");
break;
}
}
if(0 == rc) {
/* we might be connected, if the socket says it is OK! Ask it! */
int err;
err = socketerror(sockfd);
if ((0 == err) || (EISCONN == err)) {
/* we are connected, awesome! */
break;
}
/* we are _not_ connected, it was a false alert, continue please */
}
/* connect failed or timed out */
sclose(sockfd);
sockfd = -1;
/* get a new timeout for next attempt */
after = Curl_tvnow();
timeout_ms -= Curl_tvdiff(after, before);
if(timeout_ms < 0) {
failf(data, "connect() timed out!");
return CURLE_OPERATION_TIMEOUTED;
}
before = after;
continue;
}
if (sockfd < 0) {
failf(data, "connect() failed");
return CURLE_COULDNT_CONNECT;
}
/* now disable the non-blocking mode again */
Curl_nonblock(sockfd, FALSE);
if(addr)
*addr = ai; /* the address we ended up connected to */
}
#else
/*
* Connecting with IPv4-only support
*/
if(!remotehost->h_addr_list[0]) {
/* If there is no addresses in the address list, then we return
error right away */
failf(data, "no address available");
return CURLE_COULDNT_CONNECT;
}
/* create an IPv4 TCP socket */
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(-1 == sockfd) {
failf(data, "couldn't create socket");
return CURLE_COULDNT_CONNECT; /* big time error */
}
if(conn->data->set.device) {
/* user selected to bind the outgoing socket to a specified "device"
before doing connect */
CURLcode res = bindlocal(conn, sockfd);
if(res)
return res;
}
/* Convert socket to non-blocking type */
Curl_nonblock(sockfd, TRUE);
/* This is the loop that attempts to connect to all IP-addresses we
know for the given host. One by one. */
for(rc=-1, aliasindex=0;
rc && (struct in_addr *)remotehost->h_addr_list[aliasindex];
aliasindex++) {
struct sockaddr_in serv_addr;
/* do this nasty work to do the connect */
memset((char *) &serv_addr, '\0', sizeof(serv_addr));
memcpy((char *)&(serv_addr.sin_addr),
(struct in_addr *)remotehost->h_addr_list[aliasindex],
sizeof(struct in_addr));
serv_addr.sin_family = remotehost->h_addrtype;
serv_addr.sin_port = htons(port);
rc = connect(sockfd, (struct sockaddr *)&serv_addr,
sizeof(serv_addr));
if(-1 == rc) {
int error=geterrno();
switch (error) {
case EINPROGRESS:
case EWOULDBLOCK:
#if defined(EAGAIN) && EAGAIN != EWOULDBLOCK
/* On some platforms EAGAIN and EWOULDBLOCK are the
* same value, and on others they are different, hence
* the odd #if
*/
case EAGAIN:
#endif
/* asynchronous connect, wait for connect or timeout */
rc = waitconnect(sockfd, timeout_ms);
break;
default:
/* unknown error, fallthrough and try another address! */
failf(data, "Failed to connect to IP number %d", aliasindex+1);
break;
}
}
if(0 != rc) {
/* get a new timeout for next attempt */
after = Curl_tvnow();
timeout_ms -= Curl_tvdiff(after, before);
if(timeout_ms < 0) {
failf(data, "Connect timeout on IP number %d", aliasindex+1);
break;
}
before = after;
continue; /* try next address */
}
break;
}
if(0 != rc) {
/* no good connect was made */
sclose(sockfd);
*sockconn = -1;
return CURLE_COULDNT_CONNECT;
}
/* now disable the non-blocking mode again */
Curl_nonblock(sockfd, FALSE);
if(addr)
/* this is the address we've connected to */
*addr = (struct in_addr *)remotehost->h_addr_list[aliasindex];
#endif
/* allow NULL-pointers to get passed in */
if(sockconn)
*sockconn = sockfd; /* the socket descriptor we've connected */
return CURLE_OK;
}

35
lib/connect.h Normal file
View File

@@ -0,0 +1,35 @@
#ifndef __CONNECT_H
#define __CONNECT_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$
*****************************************************************************/
int Curl_nonblock(int socket, /* operate on this */
int nonblock /* TRUE or FALSE */);
CURLcode Curl_connecthost(struct connectdata *conn,
Curl_addrinfo *host, /* connect to this */
long port, /* connect to this port number */
int *sockconn, /* not set if error is returned */
Curl_ipconnect **addr /* the one we used */
); /* index we used */
#endif

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.
@@ -95,7 +95,7 @@ Example set of cookies:
/**************************************************************************** /****************************************************************************
* *
* cookie_add() * Curl_cookie_add()
* *
* Add a single cookie line to the cookie keeping object. * Add a single cookie line to the cookie keeping object.
* *
@@ -104,7 +104,8 @@ Example set of cookies:
struct Cookie * struct Cookie *
Curl_cookie_add(struct CookieInfo *c, Curl_cookie_add(struct CookieInfo *c,
bool httpheader, /* TRUE if HTTP header-style line */ bool httpheader, /* TRUE if HTTP header-style line */
char *lineptr) /* first non-space of the line */ char *lineptr, /* first non-space of the line */
char *domain) /* default domain */
{ {
struct Cookie *clist; struct Cookie *clist;
char what[MAX_COOKIE_LINE]; char what[MAX_COOKIE_LINE];
@@ -112,6 +113,7 @@ Curl_cookie_add(struct CookieInfo *c,
char *ptr; char *ptr;
char *semiptr; char *semiptr;
struct Cookie *co; struct Cookie *co;
struct Cookie *lastc=NULL;
time_t now = time(NULL); time_t now = time(NULL);
bool replace_old = FALSE; bool replace_old = FALSE;
@@ -129,13 +131,11 @@ Curl_cookie_add(struct CookieInfo *c,
semiptr=strchr(lineptr, ';'); /* first, find a semicolon */ semiptr=strchr(lineptr, ';'); /* first, find a semicolon */
ptr = lineptr; ptr = lineptr;
do { do {
if(semiptr)
*semiptr='\0'; /* zero terminate for a while */
/* we have a <what>=<this> pair or a 'secure' word here */ /* we have a <what>=<this> pair or a 'secure' word here */
if(strchr(ptr, '=')) { if(strchr(ptr, '=')) {
name[0]=what[0]=0; /* init the buffers */ name[0]=what[0]=0; /* init the buffers */
if(1 <= sscanf(ptr, "%" MAX_NAME_TXT "[^=]=%" if(1 <= sscanf(ptr, "%" MAX_NAME_TXT "[^=]=%"
MAX_COOKIE_LINE_TXT "[^\r\n]", MAX_COOKIE_LINE_TXT "[^;\r\n]",
name, what)) { name, what)) {
/* this is a legal <what>=<this> pair */ /* this is a legal <what>=<this> pair */
if(strequal("path", name)) { if(strequal("path", name)) {
@@ -178,7 +178,7 @@ Curl_cookie_add(struct CookieInfo *c,
} }
} }
else { else {
if(sscanf(ptr, "%" MAX_COOKIE_LINE_TXT "[^\r\n]", if(sscanf(ptr, "%" MAX_COOKIE_LINE_TXT "[^;\r\n]",
what)) { what)) {
if(strequal("secure", what)) if(strequal("secure", what))
co->secure = TRUE; co->secure = TRUE;
@@ -190,12 +190,15 @@ Curl_cookie_add(struct CookieInfo *c,
if(!semiptr) if(!semiptr)
continue; /* we already know there are no more cookies */ continue; /* we already know there are no more cookies */
*semiptr=';'; /* put the semicolon back */
ptr=semiptr+1; ptr=semiptr+1;
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 */
} while(semiptr); } while(semiptr);
if(NULL == co->domain)
/* no domain given in the header line, set the default now */
co->domain=domain?strdup(domain):NULL;
} }
else { else {
/* This line is NOT a HTTP header style line, we do offer support for /* This line is NOT a HTTP header style line, we do offer support for
@@ -245,6 +248,7 @@ Curl_cookie_add(struct CookieInfo *c,
We don't currently take advantage of this knowledge. We don't currently take advantage of this knowledge.
*/ */
co->field1=strequal(ptr, "TRUE")+1; /* store information */
break; break;
case 2: case 2:
/* It turns out, that sometimes the file format allows the path /* It turns out, that sometimes the file format allows the path
@@ -293,6 +297,8 @@ Curl_cookie_add(struct CookieInfo *c,
} }
co->livecookie = c->running;
/* now, we have parsed the incoming line, we must now check if this /* now, we have parsed the incoming line, we must now check if this
superceeds an already existing cookie, which it may if the previous have superceeds an already existing cookie, which it may if the previous have
the same domain and path as this */ the same domain and path as this */
@@ -327,6 +333,26 @@ Curl_cookie_add(struct CookieInfo *c,
} }
if(replace_old && !co->livecookie && clist->livecookie) {
/* Both cookies matched fine, except that the already present
cookie is "live", which means it was set from a header, while
the new one isn't "live" and thus only read from a file. We let
live cookies stay alive */
/* Free the newcomer and get out of here! */
if(co->domain)
free(co->domain);
if(co->path)
free(co->path);
if(co->name)
free(co->name);
if(co->value)
free(co->value);
free(co);
return NULL;
}
if(replace_old) { if(replace_old) {
co->next = clist->next; /* get the next-pointer first */ co->next = clist->next; /* get the next-pointer first */
@@ -348,44 +374,59 @@ Curl_cookie_add(struct CookieInfo *c,
free(clist->maxage); free(clist->maxage);
*clist = *co; /* then store all the new data */ *clist = *co; /* then store all the new data */
free(co); /* free the newly alloced memory */
co = clist; /* point to the previous struct instead */
} }
} }
lastc = clist;
clist = clist->next; clist = clist->next;
} }
if(!replace_old) { if(!replace_old) {
/* then make the last item point on this new one */
/* first, point to our "next" */ if(lastc)
co->next = c->cookies; lastc->next = co;
/* then make ourselves first in the list */ else
c->cookies = co; c->cookies = co;
} }
c->numcookies++; /* one more cookie in the jar */
return co; return co;
} }
/***************************************************************************** /*****************************************************************************
* *
* cookie_init() * Curl_cookie_init()
* *
* Inits a cookie struct to read data from a local file. This is always * Inits a cookie struct to read data from a local file. This is always
* called before any cookies are set. File may be NULL. * called before any cookies are set. File may be NULL.
* *
****************************************************************************/ ****************************************************************************/
struct CookieInfo *Curl_cookie_init(char *file) struct CookieInfo *Curl_cookie_init(char *file, struct CookieInfo *inc)
{ {
char line[MAX_COOKIE_LINE]; char line[MAX_COOKIE_LINE];
struct CookieInfo *c; struct CookieInfo *c;
FILE *fp; FILE *fp;
bool fromfile=TRUE; bool fromfile=TRUE;
c = (struct CookieInfo *)malloc(sizeof(struct CookieInfo)); if(NULL == inc) {
if(!c) /* we didn't get a struct, create one */
return NULL; /* failed to get memory */ c = (struct CookieInfo *)malloc(sizeof(struct CookieInfo));
memset(c, 0, sizeof(struct CookieInfo)); if(!c)
c->filename = strdup(file?file:"none"); /* copy the name just in case */ return NULL; /* failed to get memory */
memset(c, 0, sizeof(struct CookieInfo));
c->filename = strdup(file?file:"none"); /* copy the name just in case */
}
else {
/* we got an already existing one, use that */
c = inc;
}
c->running = FALSE; /* this is not running, this is init */
if(strequal(file, "-")) { if(file && strequal(file, "-")) {
fp = stdin; fp = stdin;
fromfile=FALSE; fromfile=FALSE;
} }
@@ -393,34 +434,35 @@ struct CookieInfo *Curl_cookie_init(char *file)
fp = file?fopen(file, "r"):NULL; fp = file?fopen(file, "r"):NULL;
if(fp) { if(fp) {
char *lineptr;
bool headerline;
while(fgets(line, MAX_COOKIE_LINE, fp)) { while(fgets(line, MAX_COOKIE_LINE, fp)) {
if(strnequal("Set-Cookie:", line, 11)) { if(strnequal("Set-Cookie:", line, 11)) {
/* This is a cookie line, get it! */ /* This is a cookie line, get it! */
char *lineptr=&line[11]; lineptr=&line[11];
while(*lineptr && isspace((int)*lineptr)) headerline=TRUE;
lineptr++;
Curl_cookie_add(c, TRUE, lineptr);
} }
else { else {
/* This might be a netscape cookie-file line, get it! */ lineptr=line;
char *lineptr=line; headerline=FALSE;
while(*lineptr && isspace((int)*lineptr))
lineptr++;
Curl_cookie_add(c, FALSE, lineptr);
} }
while(*lineptr && isspace((int)*lineptr))
lineptr++;
Curl_cookie_add(c, headerline, lineptr, NULL);
} }
if(fromfile) if(fromfile)
fclose(fp); fclose(fp);
} }
c->running = TRUE; /* now, we're running */
return c; return c;
} }
/***************************************************************************** /*****************************************************************************
* *
* cookie_getlist() * Curl_cookie_getlist()
* *
* For a given host and path, return a linked list of cookies that the * For a given host and path, return a linked list of cookies that the
* client should send to the server if used now. The secure boolean informs * client should send to the server if used now. The secure boolean informs
@@ -492,9 +534,9 @@ struct Cookie *Curl_cookie_getlist(struct CookieInfo *c,
/***************************************************************************** /*****************************************************************************
* *
* cookie_freelist() * Curl_cookie_freelist()
* *
* Free a list previously returned by cookie_getlist(); * Free a list of cookies previously returned by Curl_cookie_getlist();
* *
****************************************************************************/ ****************************************************************************/
@@ -513,7 +555,7 @@ void Curl_cookie_freelist(struct Cookie *co)
/***************************************************************************** /*****************************************************************************
* *
* cookie_cleanup() * Curl_cookie_cleanup()
* *
* Free a "cookie object" previous created with cookie_init(). * Free a "cookie object" previous created with cookie_init().
* *
@@ -552,3 +594,101 @@ void Curl_cookie_cleanup(struct CookieInfo *c)
} }
} }
/*
* Curl_cookie_output()
*
* Writes all internally known cookies to the specified file. Specify
* "-" as file name to write to stdout.
*
* The function returns non-zero on write failure.
*/
int Curl_cookie_output(struct CookieInfo *c, char *dumphere)
{
struct Cookie *co;
FILE *out;
bool use_stdout=FALSE;
if((NULL == c) || (0 == c->numcookies))
/* If there are no known cookies, we don't write or even create any
destination file */
return 0;
if(strequal("-", dumphere)) {
/* use stdout */
out = stdout;
use_stdout=TRUE;
}
else {
out = fopen(dumphere, "w");
if(!out)
return 1; /* failure */
}
if(c) {
fputs("# Netscape HTTP Cookie File\n"
"# http://www.netscape.com/newsref/std/cookie_spec.html\n"
"# This file was generated by libcurl! Edit at your own risk.\n\n",
out);
co = c->cookies;
while(co) {
fprintf(out,
"%s\t" /* domain */
"%s\t" /* field1 */
"%s\t" /* path */
"%s\t" /* secure */
"%u\t" /* expires */
"%s\t" /* name */
"%s\n", /* value */
co->domain?co->domain:"unknown",
co->field1==2?"TRUE":"FALSE",
co->path?co->path:"/",
co->secure?"TRUE":"FALSE",
(unsigned int)co->expires,
co->name,
co->value?co->value:"");
co=co->next;
}
}
if(!use_stdout)
fclose(out);
return 0;
}
#ifdef CURL_COOKIE_DEBUG
/*
* On my Solaris box, this command line builds this test program:
*
* gcc -g -o cooktest -DCURL_COOKIE_DEBUG -DHAVE_CONFIG_H -I.. -I../include cookie.c strequal.o getdate.o memdebug.o mprintf.o strtok.o -lnsl -lsocket
*
*/
int main(int argc, char **argv)
{
struct CookieInfo *c=NULL;
if(argc>1) {
c = Curl_cookie_init(argv[1], c);
Curl_cookie_add(c, TRUE, "PERSONALIZE=none;expires=Monday, 13-Jun-1988 03:04:55 GMT; domain=.fidelity.com; path=/ftgw; secure");
Curl_cookie_add(c, TRUE, "foobar=yes; domain=.haxx.se; path=/looser;");
c = Curl_cookie_init(argv[1], c);
Curl_cookie_output(c);
Curl_cookie_cleanup(c);
return 0;
}
return 1;
}
#endif
/*
* local variables:
* eval: (load-file "../curl-mode.el")
* end:
* vim600: fdm=marker
* vim: et sw=2 ts=2 sts=2 tw=78
*/

View File

@@ -40,19 +40,24 @@ struct Cookie {
char *domain; /* domain = <this> */ char *domain; /* domain = <this> */
time_t expires; /* expires = <this> */ time_t expires; /* expires = <this> */
char *expirestr; /* the plain text version */ char *expirestr; /* the plain text version */
char field1; /* read from a cookie file, 1 => FALSE, 2=> TRUE */
/* RFC 2109 keywords. Version=1 means 2109-compliant cookie sending */ /* RFC 2109 keywords. Version=1 means 2109-compliant cookie sending */
char *version; /* Version = <value> */ char *version; /* Version = <value> */
char *maxage; /* Max-Age = <value> */ char *maxage; /* Max-Age = <value> */
bool secure; /* whether the 'secure' keyword was used */ bool secure; /* whether the 'secure' keyword was used */
bool livecookie; /* updated from a server, not a stored file */
}; };
struct CookieInfo { struct CookieInfo {
/* linked list of cookies we know of */ /* linked list of cookies we know of */
struct Cookie *cookies; struct Cookie *cookies;
char *filename; /* file we read from/write to */ char *filename; /* file we read from/write to */
bool running; /* state info, for cookie adding information */
long numcookies; /* number of cookies in the "jar" */
}; };
/* This is the maximum line length we accept for a cookie line */ /* This is the maximum line length we accept for a cookie line */
@@ -63,10 +68,17 @@ struct CookieInfo {
#define MAX_NAME 256 #define MAX_NAME 256
#define MAX_NAME_TXT "255" #define MAX_NAME_TXT "255"
struct Cookie *Curl_cookie_add(struct CookieInfo *, bool, char *); /*
struct CookieInfo *Curl_cookie_init(char *); * Add a cookie to the internal list of cookies. The domain argument is only
* used if the header boolean is TRUE.
*/
struct Cookie *Curl_cookie_add(struct CookieInfo *, bool header, char *line,
char *domain);
struct CookieInfo *Curl_cookie_init(char *, struct CookieInfo *);
struct Cookie *Curl_cookie_getlist(struct CookieInfo *, char *, char *, bool); struct Cookie *Curl_cookie_getlist(struct CookieInfo *, char *, char *, bool);
void Curl_cookie_freelist(struct Cookie *); void Curl_cookie_freelist(struct Cookie *);
void Curl_cookie_cleanup(struct CookieInfo *); void Curl_cookie_cleanup(struct CookieInfo *);
int Curl_cookie_output(struct CookieInfo *, char *);
#endif #endif

View File

@@ -43,7 +43,8 @@ RSC=rc.exe
# PROP Ignore_Export_Lib 0 # PROP Ignore_Export_Lib 0
# PROP Target_Dir "" # PROP Target_Dir ""
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CURLLIB_EXPORTS" /YX /FD /c # ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CURLLIB_EXPORTS" /YX /FD /c
# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CURLLIB_EXPORTS" /YX /FD /c # ADD CPP /nologo /MD /W3 /GX /Zi /O2 /I "..\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CURLLIB_EXPORTS" /FR /FD /c
# SUBTRACT CPP /YX
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD BASE RSC /l 0x409 /d "NDEBUG"
@@ -53,7 +54,7 @@ BSC32=bscmake.exe
# ADD BSC32 /nologo # ADD BSC32 /nologo
LINK32=link.exe LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
# ADD LINK32 kernel32.lib wsock32.lib /nologo /dll /machine:I386 /out:"Release/curl.dll" # ADD LINK32 kernel32.lib ws2_32.lib /nologo /dll /map /debug /machine:I386 /out:"Release/libcurl.dll"
!ELSEIF "$(CFG)" == "curllib - Win32 Debug" !ELSEIF "$(CFG)" == "curllib - Win32 Debug"
@@ -69,7 +70,8 @@ LINK32=link.exe
# PROP Ignore_Export_Lib 0 # PROP Ignore_Export_Lib 0
# PROP Target_Dir "" # PROP Target_Dir ""
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CURLLIB_EXPORTS" /YX /FD /GZ /c # ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CURLLIB_EXPORTS" /YX /FD /GZ /c
# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CURLLIB_EXPORTS" /YX /FD /GZ /c # ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I "..\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CURLLIB_EXPORTS" /FR /FD /GZ /c
# SUBTRACT CPP /WX /YX
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x409 /d "_DEBUG" # ADD BASE RSC /l 0x409 /d "_DEBUG"
@@ -79,7 +81,7 @@ BSC32=bscmake.exe
# ADD BSC32 /nologo # ADD BSC32 /nologo
LINK32=link.exe LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
# ADD LINK32 kernel32.lib wsock32.lib /nologo /dll /debug /machine:I386 /out:"Debug/curl.dll" /pdbtype:sept # ADD LINK32 kernel32.lib ws2_32.lib /nologo /dll /incremental:no /map /debug /machine:I386 /out:"Debug/libcurl.dll" /pdbtype:sept
# SUBTRACT LINK32 /nodefaultlib # SUBTRACT LINK32 /nodefaultlib
!ENDIF !ENDIF
@@ -97,6 +99,10 @@ SOURCE=.\base64.c
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=.\connect.c
# End Source File
# Begin Source File
SOURCE=.\cookie.c SOURCE=.\cookie.c
# End Source File # End Source File
# Begin Source File # Begin Source File
@@ -245,6 +251,10 @@ SOURCE=.\base64.h
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=.\connect.h
# End Source File
# Begin Source File
SOURCE=.\cookie.h SOURCE=.\cookie.h
# End Source File # End Source File
# Begin Source File # Begin Source File

View File

@@ -90,7 +90,7 @@ CURLcode Curl_dict(struct connectdata *conn)
char *nthdef = NULL; /* This is not part of the protocol, but required char *nthdef = NULL; /* This is not part of the protocol, but required
by RFC 2229 */ by RFC 2229 */
CURLcode result=CURLE_OK; CURLcode result=CURLE_OK;
struct UrlData *data=conn->data; struct SessionHandle *data=conn->data;
char *path = conn->path; char *path = conn->path;
long *bytecount = &conn->bytecount; long *bytecount = &conn->bytecount;
@@ -136,25 +136,25 @@ CURLcode Curl_dict(struct connectdata *conn)
nth = atoi(nthdef); nth = atoi(nthdef);
} }
Curl_sendf(conn->firstsocket, conn, result = Curl_sendf(conn->firstsocket, conn,
"CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\n" "CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\n"
"MATCH " "MATCH "
"%s " /* database */ "%s " /* database */
"%s " /* strategy */ "%s " /* strategy */
"%s\n" /* word */ "%s\n" /* word */
"QUIT\n", "QUIT\n",
database, database,
strategy, strategy,
word word
); );
if(result)
result = Curl_Transfer(conn, conn->firstsocket, -1, FALSE, bytecount, failf(data, "Failed sending DICT request");
-1, NULL); /* no upload */ else
result = Curl_Transfer(conn, conn->firstsocket, -1, FALSE, bytecount,
-1, NULL); /* no upload */
if(result) if(result)
return result; return result;
} }
else if (strnequal(path, DICT_DEFINE, sizeof(DICT_DEFINE)-1) || else if (strnequal(path, DICT_DEFINE, sizeof(DICT_DEFINE)-1) ||
strnequal(path, DICT_DEFINE2, sizeof(DICT_DEFINE2)-1) || strnequal(path, DICT_DEFINE2, sizeof(DICT_DEFINE2)-1) ||
@@ -186,19 +186,19 @@ CURLcode Curl_dict(struct connectdata *conn)
nth = atoi(nthdef); nth = atoi(nthdef);
} }
Curl_sendf(conn->firstsocket, conn, result = Curl_sendf(conn->firstsocket, conn,
"CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\n" "CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\n"
"DEFINE " "DEFINE "
"%s " /* database */ "%s " /* database */
"%s\n" /* word */ "%s\n" /* word */
"QUIT\n", "QUIT\n",
database,
database, word);
word if(result)
); failf(data, "Failed sending DICT request");
else
result = Curl_Transfer(conn, conn->firstsocket, -1, FALSE, bytecount, result = Curl_Transfer(conn, conn->firstsocket, -1, FALSE, bytecount,
-1, NULL); /* no upload */ -1, NULL); /* no upload */
if(result) if(result)
return result; return result;
@@ -215,20 +215,27 @@ CURLcode Curl_dict(struct connectdata *conn)
if (ppath[i] == ':') if (ppath[i] == ':')
ppath[i] = ' '; ppath[i] = ' ';
} }
Curl_sendf(conn->firstsocket, conn, result = Curl_sendf(conn->firstsocket, conn,
"CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\n" "CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\n"
"%s\n" "%s\n"
"QUIT\n", "QUIT\n", ppath);
ppath); if(result)
failf(data, "Failed sending DICT request");
result = Curl_Transfer(conn, conn->firstsocket, -1, FALSE, bytecount, else
-1, NULL); result = Curl_Transfer(conn, conn->firstsocket, -1, FALSE, bytecount,
-1, NULL);
if(result) if(result)
return result; return result;
} }
} }
return CURLE_OK; return CURLE_OK;
} }
/*
* local variables:
* eval: (load-file "../curl-mode.el")
* end:
* vim600: fdm=marker
* vim: et sw=2 ts=2 sts=2 tw=78
*/

View File

@@ -82,3 +82,11 @@ DllMain (
return TRUE; return TRUE;
} }
#endif #endif
/*
* local variables:
* eval: (load-file "../curl-mode.el")
* end:
* vim600: fdm=marker
* vim: et sw=2 ts=2 sts=2 tw=78
*/

View File

@@ -94,7 +94,7 @@ static CURLcode win32_init(void)
WORD wVersionRequested; WORD wVersionRequested;
WSADATA wsaData; WSADATA wsaData;
int err; int err;
wVersionRequested = MAKEWORD(1, 1); wVersionRequested = MAKEWORD(2, 0);
err = WSAStartup(wVersionRequested, &wsaData); err = WSAStartup(wVersionRequested, &wsaData);
@@ -103,14 +103,14 @@ static CURLcode win32_init(void)
/* winsock.dll. */ /* winsock.dll. */
return CURLE_FAILED_INIT; return CURLE_FAILED_INIT;
/* Confirm that the Windows Sockets DLL supports 1.1.*/ /* Confirm that the Windows Sockets DLL supports 2.0.*/
/* Note that if the DLL supports versions greater */ /* Note that if the DLL supports versions greater */
/* than 1.1 in addition to 1.1, it will still return */ /* than 2.0 in addition to 2.0, it will still return */
/* 1.1 in wVersion since that is the version we */ /* 2.0 in wVersion since that is the version we */
/* requested. */ /* requested. */
if ( LOBYTE( wsaData.wVersion ) != 1 || if ( LOBYTE( wsaData.wVersion ) != 2 ||
HIBYTE( wsaData.wVersion ) != 1 ) { HIBYTE( wsaData.wVersion ) != 0 ) {
/* Tell the user that we couldn't find a useable */ /* Tell the user that we couldn't find a useable */
/* winsock.dll. */ /* winsock.dll. */
@@ -175,7 +175,7 @@ void curl_global_cleanup(void)
CURL *curl_easy_init(void) CURL *curl_easy_init(void)
{ {
CURLcode res; CURLcode res;
struct UrlData *data; struct SessionHandle *data;
/* Make sure we inited the global SSL stuff */ /* Make sure we inited the global SSL stuff */
if (!initialized) if (!initialized)
@@ -186,9 +186,6 @@ CURL *curl_easy_init(void)
if(res != CURLE_OK) if(res != CURLE_OK)
return NULL; return NULL;
/* SAC */
data->device = NULL;
return data; return data;
} }
@@ -199,7 +196,7 @@ CURLcode curl_easy_setopt(CURL *curl, CURLoption tag, ...)
func_T param_func = (func_T)0; func_T param_func = (func_T)0;
long param_long = 0; long param_long = 0;
void *param_obj = NULL; void *param_obj = NULL;
struct UrlData *data = curl; struct SessionHandle *data = curl;
va_start(arg, tag); va_start(arg, tag);
@@ -231,14 +228,14 @@ CURLcode curl_easy_setopt(CURL *curl, CURLoption tag, ...)
CURLcode curl_easy_perform(CURL *curl) CURLcode curl_easy_perform(CURL *curl)
{ {
struct UrlData *data = (struct UrlData *)curl; struct SessionHandle *data = (struct SessionHandle *)curl;
return Curl_perform(data); return Curl_perform(data);
} }
void curl_easy_cleanup(CURL *curl) void curl_easy_cleanup(CURL *curl)
{ {
struct UrlData *data = (struct UrlData *)curl; struct SessionHandle *data = (struct SessionHandle *)curl;
Curl_close(data); Curl_close(data);
} }
@@ -246,10 +243,83 @@ CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ...)
{ {
va_list arg; va_list arg;
void *paramp; void *paramp;
struct UrlData *data = (struct UrlData *)curl; struct SessionHandle *data = (struct SessionHandle *)curl;
va_start(arg, info); va_start(arg, info);
paramp = va_arg(arg, void *); paramp = va_arg(arg, void *);
return Curl_getinfo(data, info, paramp); return Curl_getinfo(data, info, paramp);
} }
CURL *curl_easy_duphandle(CURL *incurl)
{
struct SessionHandle *data=(struct SessionHandle *)incurl;
struct SessionHandle *outcurl = (struct SessionHandle *)
malloc(sizeof(struct SessionHandle));
if(NULL == outcurl)
return NULL; /* failure */
/* start with clearing the entire new struct */
memset(outcurl, 0, sizeof(struct SessionHandle));
/*
* We setup a few buffers we need. We should probably make them
* get setup on-demand in the code, as that would probably decrease
* the likeliness of us forgetting to init a buffer here in the future.
*/
outcurl->state.headerbuff=(char*)malloc(HEADERSIZE);
if(!outcurl->state.headerbuff) {
free(outcurl); /* free the memory again */
return NULL;
}
outcurl->state.headersize=HEADERSIZE;
/* copy all userdefined values */
outcurl->set = data->set;
outcurl->state.numconnects = data->state.numconnects;
outcurl->state.connects = (struct connectdata **)
malloc(sizeof(struct connectdata *) * outcurl->state.numconnects);
if(!outcurl->state.connects) {
free(outcurl->state.headerbuff);
free(outcurl);
return NULL;
}
memset(outcurl->state.connects, 0,
sizeof(struct connectdata *)*outcurl->state.numconnects);
outcurl->progress.flags = data->progress.flags;
outcurl->progress.callback = data->progress.callback;
if(data->cookies)
/* If cookies are enabled in the parent handle, we enable them
in the clone as well! */
outcurl->cookies = Curl_cookie_init(data->cookies->filename,
outcurl->cookies);
/* duplicate all values in 'change' */
if(data->change.url) {
outcurl->change.url = strdup(data->change.url);
outcurl->change.url_alloc = TRUE;
}
if(data->change.proxy) {
outcurl->change.proxy = strdup(data->change.proxy);
outcurl->change.proxy_alloc = TRUE;
}
if(data->change.referer) {
outcurl->change.referer = strdup(data->change.referer);
outcurl->change.referer_alloc = TRUE;
}
return outcurl;
}
/*
* local variables:
* eval: (load-file "../curl-mode.el")
* end:
* vim600: fdm=marker
* vim: et sw=2 ts=2 sts=2 tw=78
*/

View File

@@ -37,7 +37,7 @@
#include "memdebug.h" #include "memdebug.h"
#endif #endif
char *curl_escape(char *string, int length) char *curl_escape(const char *string, int length)
{ {
int alloc = (length?length:(int)strlen(string))+1; int alloc = (length?length:(int)strlen(string))+1;
char *ns = malloc(alloc); char *ns = malloc(alloc);
@@ -75,7 +75,7 @@ char *curl_escape(char *string, int length)
return ns; return ns;
} }
char *curl_unescape(char *string, int length) char *curl_unescape(const char *string, int length)
{ {
int alloc = (length?length:(int)strlen(string))+1; int alloc = (length?length:(int)strlen(string))+1;
char *ns = malloc(alloc); char *ns = malloc(alloc);
@@ -110,3 +110,11 @@ char *curl_unescape(char *string, int length)
return ns; return ns;
} }
/*
* local variables:
* eval: (load-file "../curl-mode.el")
* end:
* vim600: fdm=marker
* vim: et sw=2 ts=2 sts=2 tw=78
*/

View File

@@ -26,7 +26,7 @@
/* Escape and unescape URL encoding in strings. The functions return a new /* Escape and unescape URL encoding in strings. The functions return a new
* allocated string or NULL if an error occurred. */ * allocated string or NULL if an error occurred. */
char *curl_escape(char *string, int length); char *curl_escape(const char *string, int length);
char *curl_unescape(char *string, int length); char *curl_unescape(const char *string, int length);
#endif #endif

View File

@@ -142,8 +142,8 @@ CURLcode Curl_file(struct connectdata *conn)
struct stat statbuf; struct stat statbuf;
ssize_t expected_size=-1; ssize_t expected_size=-1;
ssize_t nread; ssize_t nread;
struct UrlData *data = conn->data; struct SessionHandle *data = conn->data;
char *buf = data->buffer; char *buf = data->state.buffer;
int bytecount = 0; int bytecount = 0;
struct timeval start = Curl_tvnow(); struct timeval start = Curl_tvnow();
struct timeval now = start; struct timeval now = start;
@@ -196,3 +196,11 @@ CURLcode Curl_file(struct connectdata *conn)
return res; return res;
} }
/*
* local variables:
* eval: (load-file "../curl-mode.el")
* end:
* vim600: fdm=marker
* vim: et sw=2 ts=2 sts=2 tw=78
*/

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.
@@ -24,7 +24,82 @@
/* /*
Debug the form generator stand-alone by compiling this source file with: Debug the form generator stand-alone by compiling this source file with:
gcc -DHAVE_CONFIG_H -I../ -g -D_FORM_DEBUG -o formdata -I../include formdata.c gcc -DHAVE_CONFIG_H -I../ -g -D_FORM_DEBUG -o formdata -I../include formdata.c strequal.c
run the 'formdata' executable the output should end with:
All Tests seem to have worked ...
and the following parts should be there:
Content-Disposition: form-data; name="simple_COPYCONTENTS"
value for simple COPYCONTENTS
Content-Disposition: form-data; name="COPYCONTENTS_+_CONTENTTYPE"
Content-Type: image/gif
value for COPYCONTENTS + CONTENTTYPE
Content-Disposition: form-data; name="PRNAME_+_NAMELENGTH_+_COPYNAME_+_CONTENTSLENGTH"
vlue for PTRNAME + NAMELENGTH + COPYNAME + CONTENTSLENGTH
(or you might see P^@RNAME and v^@lue at the start)
Content-Disposition: form-data; name="simple_PTRCONTENTS"
value for simple PTRCONTENTS
Content-Disposition: form-data; name="PTRCONTENTS_+_CONTENTSLENGTH"
vlue for PTRCONTENTS + CONTENTSLENGTH
(or you might see v^@lue at the start)
Content-Disposition: form-data; name="PTRCONTENTS_+_CONTENTSLENGTH_+_CONTENTTYPE"
Content-Type: text/plain
vlue for PTRCOTNENTS + CONTENTSLENGTH + CONTENTTYPE
(or you might see v^@lue at the start)
Content-Disposition: form-data; name="FILE1_+_CONTENTTYPE"; filename="inet_ntoa_r.h"
Content-Type: text/html
...
Content-Disposition: form-data; name="FILE1_+_FILE2"
Content-Type: multipart/mixed, boundary=curlz1s0dkticx49MV1KGcYP5cvfSsz
...
Content-Disposition: attachment; filename="inet_ntoa_r.h"
Content-Type: text/plain
...
Content-Disposition: attachment; filename="Makefile.b32.resp"
Content-Type: text/plain
...
Content-Disposition: form-data; name="FILE1_+_FILE2_+_FILE3"
Content-Type: multipart/mixed, boundary=curlirkYPmPwu6FrJ1vJ1u1BmtIufh1
...
Content-Disposition: attachment; filename="inet_ntoa_r.h"
Content-Type: text/plain
...
Content-Disposition: attachment; filename="Makefile.b32.resp"
Content-Type: text/plain
...
Content-Disposition: attachment; filename="inet_ntoa_r.h"
Content-Type: text/plain
...
Content-Disposition: form-data; name="ARRAY: FILE1_+_FILE2_+_FILE3"
Content-Type: multipart/mixed, boundary=curlirkYPmPwu6FrJ1vJ1u1BmtIufh1
...
Content-Disposition: attachment; filename="inet_ntoa_r.h"
Content-Type: text/plain
...
Content-Disposition: attachment; filename="Makefile.b32.resp"
Content-Type: text/plain
...
Content-Disposition: attachment; filename="inet_ntoa_r.h"
Content-Type: text/plain
...
Content-Disposition: form-data; name="FILECONTENT"
...
For the old FormParse used by curl_formparse use:
gcc -DHAVE_CONFIG_H -I../ -g -D_OLD_FORM_DEBUG -o formdata -I../include formdata.c strequal.c
run the 'formdata' executable and make sure the output is ok! run the 'formdata' executable and make sure the output is ok!
@@ -64,7 +139,7 @@
/* This is a silly duplicate of the function in main.c to enable this source /* This is a silly duplicate of the function in main.c to enable this source
to compile stand-alone for better debugging */ to compile stand-alone for better debugging */
static void GetStr(char **string, static void GetStr(char **string,
char *value) const char *value)
{ {
if(*string) if(*string)
free(*string); free(*string);
@@ -227,6 +302,7 @@ int FormParse(char *input,
memset(post, 0, sizeof(struct HttpPost)); memset(post, 0, sizeof(struct HttpPost));
GetStr(&post->name, name); /* get the name */ GetStr(&post->name, name); /* get the name */
GetStr(&post->contents, contp); /* get the contents */ GetStr(&post->contents, contp); /* get the contents */
post->contentslength = 0;
post->flags = flags; post->flags = flags;
if(type) { if(type) {
GetStr(&post->contenttype, (char *)type); /* get type */ GetStr(&post->contenttype, (char *)type); /* get type */
@@ -250,6 +326,7 @@ int FormParse(char *input,
memset(subpost, 0, sizeof(struct HttpPost)); memset(subpost, 0, sizeof(struct HttpPost));
GetStr(&subpost->name, name); /* get the name */ GetStr(&subpost->name, name); /* get the name */
GetStr(&subpost->contents, contp); /* get the contents */ GetStr(&subpost->contents, contp); /* get the contents */
subpost->contentslength = 0;
subpost->flags = flags; subpost->flags = flags;
if(type) { if(type) {
GetStr(&subpost->contenttype, (char *)type); /* get type */ GetStr(&subpost->contenttype, (char *)type); /* get type */
@@ -272,10 +349,12 @@ int FormParse(char *input,
GetStr(&post->name, name); /* get the name */ GetStr(&post->name, name); /* get the name */
if( contp[0]=='<' ) { if( contp[0]=='<' ) {
GetStr(&post->contents, contp+1); /* get the contents */ GetStr(&post->contents, contp+1); /* get the contents */
post->contentslength = 0;
post->flags = HTTPPOST_READFILE; post->flags = HTTPPOST_READFILE;
} }
else { else {
GetStr(&post->contents, contp); /* get the contents */ GetStr(&post->contents, contp); /* get the contents */
post->contentslength = 0;
post->flags = 0; post->flags = 0;
} }
@@ -307,6 +386,530 @@ int curl_formparse(char *input,
return FormParse(input, httppost, last_post); return FormParse(input, httppost, last_post);
} }
/***************************************************************************
*
* AddHttpPost()
*
* Adds a HttpPost structure to the list, if parent_post is given becomes
* a subpost of parent_post instead of a direct list element.
*
* Returns newly allocated HttpPost on success and NULL if malloc failed.
*
***************************************************************************/
static struct HttpPost * AddHttpPost (char * name,
long namelength,
char * value,
long contentslength,
char *contenttype,
long flags,
struct HttpPost *parent_post,
struct HttpPost **httppost,
struct HttpPost **last_post)
{
struct HttpPost *post;
post = (struct HttpPost *)malloc(sizeof(struct HttpPost));
if(post) {
memset(post, 0, sizeof(struct HttpPost));
post->name = name;
post->namelength = name?(namelength?namelength:(long)strlen(name)):0;
post->contents = value;
post->contentslength = contentslength;
post->contenttype = contenttype;
post->flags = flags;
}
else
return NULL;
if (parent_post) {
/* now, point our 'more' to the original 'more' */
post->more = parent_post->more;
/* then move the original 'more' to point to ourselves */
parent_post->more = post;
}
else {
/* make the previous point to this */
if(*last_post)
(*last_post)->next = post;
else
(*httppost) = post;
(*last_post) = post;
}
return post;
}
/***************************************************************************
*
* AddFormInfo()
*
* Adds a FormInfo structure to the list presented by parent_form_info.
*
* Returns newly allocated FormInfo on success and NULL if malloc failed/
* parent_form_info is NULL.
*
***************************************************************************/
static FormInfo * AddFormInfo(char *value,
char *contenttype,
FormInfo *parent_form_info)
{
FormInfo *form_info;
form_info = (FormInfo *)malloc(sizeof(FormInfo));
if(form_info) {
memset(form_info, 0, sizeof(FormInfo));
if (value)
form_info->value = value;
if (contenttype)
form_info->contenttype = contenttype;
form_info->flags = HTTPPOST_FILENAME;
}
else
return NULL;
if (parent_form_info) {
/* now, point our 'more' to the original 'more' */
form_info->more = parent_form_info->more;
/* then move the original 'more' to point to ourselves */
parent_form_info->more = form_info;
}
else
return NULL;
return form_info;
}
/***************************************************************************
*
* ContentTypeForFilename()
*
* Provides content type for filename if one of the known types (else
* (either the prevtype or the default is returned).
*
* Returns some valid contenttype for filename.
*
***************************************************************************/
static const char * ContentTypeForFilename (const char *filename,
const char *prevtype)
{
const char *contenttype = NULL;
unsigned int i;
/*
* No type was specified, we scan through a few well-known
* extensions and pick the first we match!
*/
struct ContentType {
const char *extension;
const char *type;
};
static struct ContentType ctts[]={
{".gif", "image/gif"},
{".jpg", "image/jpeg"},
{".jpeg", "image/jpeg"},
{".txt", "text/plain"},
{".html", "text/plain"}
};
if(prevtype)
/* default to the previously set/used! */
contenttype = prevtype;
else
/* It seems RFC1867 defines no Content-Type to default to
text/plain so we don't actually need to set this: */
contenttype = HTTPPOST_CONTENTTYPE_DEFAULT;
for(i=0; i<sizeof(ctts)/sizeof(ctts[0]); i++) {
if(strlen(filename) >= strlen(ctts[i].extension)) {
if(strequal(filename +
strlen(filename) - strlen(ctts[i].extension),
ctts[i].extension)) {
contenttype = ctts[i].type;
break;
}
}
}
/* we have a contenttype by now */
return contenttype;
}
/***************************************************************************
*
* AllocAndCopy()
*
* Copies the data currently available under *buffer using newly allocated
* buffer (that becomes *buffer). Uses buffer_length if not null, else
* uses strlen to determine the length of the buffer to be copied
*
* Returns 0 on success and 1 if the malloc failed.
*
***************************************************************************/
static int AllocAndCopy (char **buffer, int buffer_length)
{
const char *src = *buffer;
int length, add = 0;
if (buffer_length)
length = buffer_length;
else {
length = strlen(*buffer);
add = 1;
}
*buffer = (char*)malloc(length+add);
if (!*buffer)
return 1;
memcpy(*buffer, src, length);
/* if length unknown do null termination */
if (add)
(*buffer)[length] = '\0';
return 0;
}
/***************************************************************************
*
* FormAdd()
*
* Stores a 'name=value' formpost parameter and builds the appropriate
* linked list.
*
* Has two principal functionalities: using files and byte arrays as
* post parts. Byte arrays are either copied or just the pointer is stored
* (as the user requests) while for files only the filename and not the
* content is stored.
*
* While you may have only one byte array for each name, multiple filenames
* are allowed (and because of this feature CURLFORM_END is needed after
* using CURLFORM_FILE).
*
* Examples:
*
* Simple name/value pair with copied contents:
* curl_formadd (&post, &last, CURLFORM_COPYNAME, "name",
* CURLFORM_COPYCONTENTS, "value", CURLFORM_END);
*
* name/value pair where only the content pointer is remembered:
* curl_formadd (&post, &last, CURLFORM_COPYNAME, "name",
* CURLFORM_PTRCONTENTS, ptr, CURLFORM_CONTENTSLENGTH, 10, CURLFORM_END);
* (if CURLFORM_CONTENTSLENGTH is missing strlen () is used)
*
* storing a filename (CONTENTTYPE is optional!):
* curl_formadd (&post, &last, CURLFORM_COPYNAME, "name",
* CURLFORM_FILE, "filename1", CURLFORM_CONTENTTYPE, "plain/text",
* CURLFORM_END);
*
* storing multiple filenames:
* curl_formadd (&post, &last, CURLFORM_COPYNAME, "name",
* CURLFORM_FILE, "filename1", CURLFORM_FILE, "filename2", CURLFORM_END);
*
* Returns:
* FORMADD_OK on success
* FORMADD_MEMORY if the FormInfo allocation fails
* FORMADD_OPTION_TWICE if one option is given twice for one Form
* FORMADD_NULL if a null pointer was given for a char
* FORMADD_MEMORY if the allocation of a FormInfo struct failed
* FORMADD_UNKNOWN_OPTION if an unknown option was used
* FORMADD_INCOMPLETE if the some FormInfo is not complete (or an error)
* FORMADD_MEMORY if a HttpPost struct cannot be allocated
* FORMADD_MEMORY if some allocation for string copying failed.
* FORMADD_ILLEGAL_ARRAY if an illegal option is used in an array
*
***************************************************************************/
typedef enum {
FORMADD_OK, /* first, no error */
FORMADD_MEMORY,
FORMADD_OPTION_TWICE,
FORMADD_NULL,
FORMADD_UNKNOWN_OPTION,
FORMADD_INCOMPLETE,
FORMADD_ILLEGAL_ARRAY,
FORMADD_LAST /* last */
} FORMcode;
static
FORMcode FormAdd(struct HttpPost **httppost,
struct HttpPost **last_post,
va_list params)
{
FormInfo *first_form, *current_form, *form;
FORMcode return_value = FORMADD_OK;
const char *prevtype = NULL;
struct HttpPost *post = NULL;
CURLformoption option;
struct curl_forms *forms = NULL;
const char *array_value; /* value read from an array */
/* This is a state variable, that if TRUE means that we're parsing an
array that we got passed to us. If FALSE we're parsing the input
va_list arguments. */
bool array_state = FALSE;
/*
* We need to allocate the first struct to fill in.
*/
first_form = (FormInfo *)malloc(sizeof(struct FormInfo));
if(first_form) {
memset(first_form, 0, sizeof(FormInfo));
current_form = first_form;
}
else
return FORMADD_MEMORY;
/*
* Loop through all the options set.
*/
while (1) {
/* break if we have an error to report */
if (return_value != FORMADD_OK)
break;
/* first see if we have more parts of the array param */
if ( array_state ) {
/* get the upcoming option from the given array */
option = forms->option;
array_value = forms->value;
forms++; /* advance this to next entry */
if (CURLFORM_END == option) {
/* end of array state */
array_state = FALSE;
continue;
}
else {
/* check that the option is OK in an array */
/* Daniel's note: do we really need to do this? */
if ( (option <= CURLFORM_ARRAY_START) ||
(option >= CURLFORM_ARRAY_END) ) {
return_value = FORMADD_ILLEGAL_ARRAY;
break;
}
}
}
else {
/* This is not array-state, get next option */
option = va_arg(params, CURLformoption);
if (CURLFORM_END == option)
break;
}
switch (option) {
case CURLFORM_ARRAY:
forms = va_arg(params, struct curl_forms *);
if (forms)
array_state = TRUE;
else
return_value = FORMADD_NULL;
break;
/*
* Set the Name property.
*/
case CURLFORM_PTRNAME:
current_form->flags |= HTTPPOST_PTRNAME; /* fall through */
case CURLFORM_COPYNAME:
if (current_form->name)
return_value = FORMADD_OPTION_TWICE;
else {
char *name = va_arg(params, char *);
if (name)
current_form->name = name; /* store for the moment */
else
return_value = FORMADD_NULL;
}
break;
case CURLFORM_NAMELENGTH:
if (current_form->namelength)
return_value = FORMADD_OPTION_TWICE;
else
current_form->namelength = va_arg(params, long);
break;
/*
* Set the contents property.
*/
case CURLFORM_PTRCONTENTS:
current_form->flags |= HTTPPOST_PTRCONTENTS; /* fall through */
case CURLFORM_COPYCONTENTS:
if (current_form->value)
return_value = FORMADD_OPTION_TWICE;
else {
char *value = va_arg(params, char *);
if (value)
current_form->value = value; /* store for the moment */
else
return_value = FORMADD_NULL;
}
break;
case CURLFORM_CONTENTSLENGTH:
if (current_form->contentslength)
return_value = FORMADD_OPTION_TWICE;
else
current_form->contentslength = va_arg(params, long);
break;
/* Get contents from a given file name */
case CURLFORM_FILECONTENT:
if (current_form->flags != 0)
return_value = FORMADD_OPTION_TWICE;
else {
char *filename = va_arg(params, char *);
if (filename) {
current_form->value = strdup(filename);
current_form->flags |= HTTPPOST_READFILE;
}
else
return_value = FORMADD_NULL;
}
break;
/* We upload a file */
case CURLFORM_FILE:
{
const char *filename = NULL;
if (array_state)
filename = array_value;
else
filename = va_arg(params, const char *);
if (current_form->value) {
if (current_form->flags & HTTPPOST_FILENAME) {
if (filename) {
if (!(current_form = AddFormInfo(strdup(filename),
NULL, current_form)))
return_value = FORMADD_MEMORY;
}
else
return_value = FORMADD_NULL;
}
else
return_value = FORMADD_OPTION_TWICE;
}
else {
if (filename)
current_form->value = strdup(filename);
else
return_value = FORMADD_NULL;
current_form->flags |= HTTPPOST_FILENAME;
}
break;
}
case CURLFORM_CONTENTTYPE:
{
const char *contenttype = NULL;
if (array_state)
contenttype = array_value;
else
contenttype = va_arg(params, const char *);
if (current_form->contenttype) {
if (current_form->flags & HTTPPOST_FILENAME) {
if (contenttype) {
if (!(current_form = AddFormInfo(NULL,
strdup(contenttype),
current_form)))
return_value = FORMADD_MEMORY;
}
else
return_value = FORMADD_NULL;
}
else
return_value = FORMADD_OPTION_TWICE;
}
else {
if (contenttype)
current_form->contenttype = strdup(contenttype);
else
return_value = FORMADD_NULL;
}
break;
}
default:
fprintf (stderr, "got unknown CURLFORM_OPTION: %d\n", option);
return_value = FORMADD_UNKNOWN_OPTION;
}
}
if(FORMADD_OK == return_value) {
/* go through the list, check for copleteness and if everything is
* alright add the HttpPost item otherwise set return_value accordingly */
post = NULL;
for(form = first_form;
form != NULL;
form = form->more) {
if ( ((!form->name || !form->value) && !post) ||
( (form->contentslength) &&
(form->flags & HTTPPOST_FILENAME) ) ||
( (form->flags & HTTPPOST_FILENAME) &&
(form->flags & HTTPPOST_PTRCONTENTS) ) ||
( (form->flags & HTTPPOST_READFILE) &&
(form->flags & HTTPPOST_PTRCONTENTS) )
) {
return_value = FORMADD_INCOMPLETE;
break;
}
else {
if ( (form->flags & HTTPPOST_FILENAME) &&
!form->contenttype ) {
/* our contenttype is missing */
form->contenttype
= strdup(ContentTypeForFilename(form->value, prevtype));
}
if ( !(form->flags & HTTPPOST_PTRNAME) &&
(form == first_form) ) {
/* copy name (without strdup; possibly contains null characters) */
if (AllocAndCopy(&form->name, form->namelength)) {
return_value = FORMADD_MEMORY;
break;
}
}
if ( !(form->flags & HTTPPOST_FILENAME) &&
!(form->flags & HTTPPOST_READFILE) &&
!(form->flags & HTTPPOST_PTRCONTENTS) ) {
/* copy value (without strdup; possibly contains null characters) */
if (AllocAndCopy(&form->value, form->contentslength)) {
return_value = FORMADD_MEMORY;
break;
}
}
if ( (post = AddHttpPost(form->name, form->namelength,
form->value, form->contentslength,
form->contenttype, form->flags,
post, httppost,
last_post)) == NULL) {
return_value = FORMADD_MEMORY;
}
if (form->contenttype)
prevtype = form->contenttype;
}
}
}
/* always delete the allocated memory before returning */
form = first_form;
while (form != NULL) {
FormInfo *delete_form;
delete_form = form;
form = form->more;
free (delete_form);
}
return return_value;
}
int curl_formadd(struct HttpPost **httppost,
struct HttpPost **last_post,
...)
{
va_list arg;
int result;
va_start(arg, last_post);
result = FormAdd(httppost, last_post, arg);
va_end(arg);
return result;
}
static int AddFormData(struct FormData **formp, static int AddFormData(struct FormData **formp,
const void *line, const void *line,
long length) long length)
@@ -404,9 +1007,9 @@ void curl_formfree(struct HttpPost *form)
if(form->more) if(form->more)
curl_formfree(form->more); curl_formfree(form->more);
if(form->name) if( !(form->flags & HTTPPOST_PTRNAME) && form->name)
free(form->name); /* free the name */ free(form->name); /* free the name */
if(form->contents) if( !(form->flags & HTTPPOST_PTRCONTENTS) && form->contents)
free(form->contents); /* free the contents */ free(form->contents); /* free the contents */
if(form->contenttype) if(form->contenttype)
free(form->contenttype); /* free the content type */ free(form->contenttype); /* free the content type */
@@ -446,9 +1049,12 @@ struct FormData *Curl_getFormData(struct HttpPost *post,
/* boundary */ /* boundary */
size += AddFormDataf(&form, "\r\n--%s\r\n", boundary); size += AddFormDataf(&form, "\r\n--%s\r\n", boundary);
size += AddFormDataf(&form, size += AddFormData(&form,
"Content-Disposition: form-data; name=\"%s\"", "Content-Disposition: form-data; name=\"", 0);
post->name);
size += AddFormData(&form, post->name, post->namelength);
size += AddFormData(&form, "\"", 0);
if(post->more) { if(post->more) {
/* If used, this is a link to more file names, we must then do /* If used, this is a link to more file names, we must then do
@@ -525,7 +1131,7 @@ struct FormData *Curl_getFormData(struct HttpPost *post,
} }
} else { } else {
/* include the contents we got */ /* include the contents we got */
size += AddFormData(&form, post->contents, 0); size += AddFormData(&form, post->contents, post->contentslength);
} }
} while((file = file->more)); /* for each specified file for this field */ } while((file = file->more)); /* for each specified file for this field */
@@ -568,6 +1174,52 @@ int Curl_FormReader(char *buffer,
size_t size, size_t size,
size_t nitems, size_t nitems,
FILE *mydata) FILE *mydata)
{
struct Form *form;
int wantedsize;
int gotsize = 0;
form=(struct Form *)mydata;
wantedsize = size * nitems;
if(!form->data)
return -1; /* nothing, error, empty */
do {
if( (form->data->length - form->sent ) > wantedsize - gotsize) {
memcpy(buffer + gotsize , form->data->line + form->sent,
wantedsize - gotsize);
form->sent += wantedsize-gotsize;
return wantedsize;
}
memcpy(buffer+gotsize,
form->data->line + form->sent,
(form->data->length - form->sent) );
gotsize += form->data->length - form->sent;
form->sent = 0;
form->data = form->data->next; /* advance */
} while(form->data);
/* If we got an empty line and we have more data, we proceed to the next
line immediately to avoid returning zero before we've reached the end.
This is the bug reported November 22 1999 on curl 6.3. (Daniel) */
return gotsize;
}
/* possible (old) fread() emulation that copies at most one line */
int Curl_FormReadOneLine(char *buffer,
size_t size,
size_t nitems,
FILE *mydata)
{ {
struct Form *form; struct Form *form;
int wantedsize; int wantedsize;
@@ -609,6 +1261,152 @@ int Curl_FormReader(char *buffer,
#ifdef _FORM_DEBUG #ifdef _FORM_DEBUG
int FormAddTest(const char * errormsg,
struct HttpPost **httppost,
struct HttpPost **last_post,
...)
{
int result;
va_list arg;
va_start(arg, last_post);
if ((result = FormAdd(httppost, last_post, arg)))
fprintf (stderr, "ERROR doing FormAdd ret: %d action: %s\n", result,
errormsg);
va_end(arg);
return result;
}
int main()
{
char name1[] = "simple_COPYCONTENTS";
char name2[] = "COPYCONTENTS_+_CONTENTTYPE";
char name3[] = "PTRNAME_+_NAMELENGTH_+_COPYNAME_+_CONTENTSLENGTH";
char name4[] = "simple_PTRCONTENTS";
char name5[] = "PTRCONTENTS_+_CONTENTSLENGTH";
char name6[] = "PTRCONTENTS_+_CONTENTSLENGTH_+_CONTENTTYPE";
char name7[] = "FILE1_+_CONTENTTYPE";
char name8[] = "FILE1_+_FILE2";
char name9[] = "FILE1_+_FILE2_+_FILE3";
char name10[] = "ARRAY: FILE1_+_FILE2_+_FILE3";
char name11[] = "FILECONTENT";
char value1[] = "value for simple COPYCONTENTS";
char value2[] = "value for COPYCONTENTS + CONTENTTYPE";
char value3[] = "value for PTRNAME + NAMELENGTH + COPYNAME + CONTENTSLENGTH";
char value4[] = "value for simple PTRCONTENTS";
char value5[] = "value for PTRCONTENTS + CONTENTSLENGTH";
char value6[] = "value for PTRCOTNENTS + CONTENTSLENGTH + CONTENTTYPE";
char value7[] = "inet_ntoa_r.h";
char value8[] = "Makefile.b32.resp";
char type2[] = "image/gif";
char type6[] = "text/plain";
char type7[] = "text/html";
int name3length = strlen(name3);
int value3length = strlen(value3);
int value5length = strlen(value4);
int value6length = strlen(value5);
int errors = 0;
int size;
int nread;
char buffer[4096];
struct HttpPost *httppost=NULL;
struct HttpPost *last_post=NULL;
struct curl_forms forms[4];
struct FormData *form;
struct Form formread;
if (FormAddTest("simple COPYCONTENTS test", &httppost, &last_post,
CURLFORM_COPYNAME, name1, CURLFORM_COPYCONTENTS, value1,
CURLFORM_END))
++errors;
if (FormAddTest("COPYCONTENTS + CONTENTTYPE test", &httppost, &last_post,
CURLFORM_COPYNAME, name2, CURLFORM_COPYCONTENTS, value2,
CURLFORM_CONTENTTYPE, type2, CURLFORM_END))
++errors;
/* make null character at start to check that contentslength works
correctly */
name3[1] = '\0';
value3[1] = '\0';
if (FormAddTest("PTRNAME + NAMELENGTH + COPYNAME + CONTENTSLENGTH test",
&httppost, &last_post,
CURLFORM_PTRNAME, name3, CURLFORM_COPYCONTENTS, value3,
CURLFORM_CONTENTSLENGTH, value3length,
CURLFORM_NAMELENGTH, name3length, CURLFORM_END))
++errors;
if (FormAddTest("simple PTRCONTENTS test", &httppost, &last_post,
CURLFORM_COPYNAME, name4, CURLFORM_PTRCONTENTS, value4,
CURLFORM_END))
++errors;
/* make null character at start to check that contentslength works
correctly */
value5[1] = '\0';
if (FormAddTest("PTRCONTENTS + CONTENTSLENGTH test", &httppost, &last_post,
CURLFORM_COPYNAME, name5, CURLFORM_PTRCONTENTS, value5,
CURLFORM_CONTENTSLENGTH, value5length, CURLFORM_END))
++errors;
/* make null character at start to check that contentslength works
correctly */
value6[1] = '\0';
if (FormAddTest("PTRCONTENTS + CONTENTSLENGTH + CONTENTTYPE test",
&httppost, &last_post,
CURLFORM_COPYNAME, name6, CURLFORM_PTRCONTENTS, value6,
CURLFORM_CONTENTSLENGTH, value6length,
CURLFORM_CONTENTTYPE, type6, CURLFORM_END))
++errors;
if (FormAddTest("FILE + CONTENTTYPE test", &httppost, &last_post,
CURLFORM_COPYNAME, name7, CURLFORM_FILE, value7,
CURLFORM_CONTENTTYPE, type7, CURLFORM_END))
++errors;
if (FormAddTest("FILE1 + FILE2 test", &httppost, &last_post,
CURLFORM_COPYNAME, name8, CURLFORM_FILE, value7,
CURLFORM_FILE, value8, CURLFORM_END))
++errors;
if (FormAddTest("FILE1 + FILE2 + FILE3 test", &httppost, &last_post,
CURLFORM_COPYNAME, name9, CURLFORM_FILE, value7,
CURLFORM_FILE, value8, CURLFORM_FILE, value7, CURLFORM_END))
++errors;
forms[0].option = CURLFORM_FILE;
forms[0].value = value7;
forms[1].option = CURLFORM_FILE;
forms[1].value = value8;
forms[2].option = CURLFORM_FILE;
forms[2].value = value7;
forms[3].option = CURLFORM_END;
if (FormAddTest("FILE1 + FILE2 + FILE3 ARRAY test", &httppost, &last_post,
CURLFORM_COPYNAME, name10, CURLFORM_ARRAY, forms,
CURLFORM_END))
++errors;
if (FormAddTest("FILECONTENT test", &httppost, &last_post,
CURLFORM_COPYNAME, name11, CURLFORM_FILECONTENT, value7,
CURLFORM_END))
++errors;
form=Curl_getFormData(httppost, &size);
Curl_FormInit(&formread, form);
do {
nread = Curl_FormReader(buffer, 1, sizeof(buffer),
(FILE *)&formread);
if(-1 == nread)
break;
fwrite(buffer, nread, 1, stdout);
} while(1);
fprintf(stdout, "size: %d\n", size);
if (errors)
fprintf(stdout, "\n==> %d Test(s) failed!\n", errors);
else
fprintf(stdout, "\nAll Tests seem to have worked (please check output)\n");
return 0;
}
#endif
#ifdef _OLD_FORM_DEBUG
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
@@ -661,3 +1459,11 @@ int main(int argc, char **argv)
} }
#endif #endif
/*
* local variables:
* eval: (load-file "../curl-mode.el")
* end:
* vim600: fdm=marker
* vim: et sw=2 ts=2 sts=2 tw=78
*/

View File

@@ -36,6 +36,17 @@ struct Form {
been sent in a previous invoke */ been sent in a previous invoke */
}; };
/* used by FormAdd for temporary storage */
typedef struct FormInfo {
char *name;
long namelength;
char *value;
long contentslength;
char *contenttype;
long flags;
struct FormInfo *more;
} FormInfo;
int Curl_FormInit(struct Form *form, struct FormData *formdata ); int Curl_FormInit(struct Form *form, struct FormData *formdata );
struct FormData *Curl_getFormData(struct HttpPost *post, struct FormData *Curl_getFormData(struct HttpPost *post,
@@ -47,8 +58,15 @@ int Curl_FormReader(char *buffer,
size_t nitems, size_t nitems,
FILE *mydata); FILE *mydata);
/* possible (old) fread() emulation that copies at most one line */
int Curl_FormReadOneLine(char *buffer,
size_t size,
size_t nitems,
FILE *mydata);
char *Curl_FormBoundary(void); char *Curl_FormBoundary(void);
void Curl_formclean(struct FormData *); void Curl_formclean(struct FormData *);
#endif #endif

1742
lib/ftp.c

File diff suppressed because it is too large Load Diff

View File

@@ -28,11 +28,10 @@ CURLcode Curl_ftp_done(struct connectdata *conn);
CURLcode Curl_ftp_connect(struct connectdata *conn); CURLcode Curl_ftp_connect(struct connectdata *conn);
CURLcode Curl_ftp_disconnect(struct connectdata *conn); CURLcode Curl_ftp_disconnect(struct connectdata *conn);
size_t Curl_ftpsendf(int fd, struct connectdata *, const char *fmt, ...); size_t Curl_ftpsendf(struct connectdata *, const char *fmt, ...);
/* The kerberos stuff needs this: */ /* The kerberos stuff needs this: */
int Curl_GetFTPResponse(int sockfd, char *buf, int Curl_GetFTPResponse(char *buf, struct connectdata *conn,
struct connectdata *conn,
int *ftpcode); int *ftpcode);
#endif #endif

View File

@@ -1524,9 +1524,11 @@ yyerrhandle:
the same signature as the function definition does. */ the same signature as the function definition does. */
#include "getdate.h" #include "getdate.h"
#ifndef WIN32 /* the windows dudes don't need these, does anyone really? */
extern struct tm *gmtime (); extern struct tm *gmtime ();
extern struct tm *localtime (); extern struct tm *localtime ();
extern time_t mktime (); extern time_t mktime ();
#endif
/* Month and day table. */ /* Month and day table. */
static TABLE const MonthDayTable[] = { static TABLE const MonthDayTable[] = {
@@ -2124,3 +2126,11 @@ 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

@@ -477,9 +477,11 @@ o_merid : /* NULL */
the same signature as the function definition does. */ the same signature as the function definition does. */
#include "getdate.h" #include "getdate.h"
#ifndef WIN32 /* the windows dudes don't need these, does anyone really? */
extern struct tm *gmtime (); extern struct tm *gmtime ();
extern struct tm *localtime (); extern struct tm *localtime ();
extern time_t mktime (); extern time_t mktime ();
#endif
/* Month and day table. */ /* Month and day table. */
static TABLE const MonthDayTable[] = { static TABLE const MonthDayTable[] = {

View File

@@ -66,3 +66,11 @@ char *curl_getenv(const char *v)
{ {
return GetEnv(v); return GetEnv(v);
} }
/*
* local variables:
* eval: (load-file "../curl-mode.el")
* end:
* vim600: fdm=marker
* vim: et sw=2 ts=2 sts=2 tw=78
*/

View File

@@ -35,22 +35,23 @@
* This is supposed to be called in the beginning of a permform() session * This is supposed to be called in the beginning of a permform() session
* and should reset all session-info variables * and should reset all session-info variables
*/ */
CURLcode Curl_initinfo(struct UrlData *data) CURLcode Curl_initinfo(struct SessionHandle *data)
{ {
struct Progress *pro = &data->progress; struct Progress *pro = &data->progress;
struct PureInfo *info =&data->info;
pro->t_nslookup = 0; pro->t_nslookup = 0;
pro->t_connect = 0; pro->t_connect = 0;
pro->t_pretransfer = 0; pro->t_pretransfer = 0;
pro->httpcode = 0; info->httpcode = 0;
pro->httpversion=0; info->httpversion=0;
pro->filetime=0; info->filetime=-1; /* -1 is an illegal time and thus means unknown */
return CURLE_OK; return CURLE_OK;
} }
CURLcode Curl_getinfo(struct UrlData *data, CURLINFO info, ...) CURLcode Curl_getinfo(struct SessionHandle *data, CURLINFO info, ...)
{ {
va_list arg; va_list arg;
long *param_longp; long *param_longp;
@@ -80,19 +81,19 @@ CURLcode Curl_getinfo(struct UrlData *data, CURLINFO info, ...)
switch(info) { switch(info) {
case CURLINFO_EFFECTIVE_URL: case CURLINFO_EFFECTIVE_URL:
*param_charp = data->url?data->url:(char *)""; *param_charp = data->change.url?data->change.url:(char *)"";
break; break;
case CURLINFO_HTTP_CODE: case CURLINFO_HTTP_CODE:
*param_longp = data->progress.httpcode; *param_longp = data->info.httpcode;
break; break;
case CURLINFO_FILETIME: case CURLINFO_FILETIME:
*param_longp = data->progress.filetime; *param_longp = data->info.filetime;
break; break;
case CURLINFO_HEADER_SIZE: case CURLINFO_HEADER_SIZE:
*param_longp = data->header_size; *param_longp = data->info.header_size;
break; break;
case CURLINFO_REQUEST_SIZE: case CURLINFO_REQUEST_SIZE:
*param_longp = data->request_size; *param_longp = data->info.request_size;
break; break;
case CURLINFO_TOTAL_TIME: case CURLINFO_TOTAL_TIME:
*param_doublep = data->progress.timespent; *param_doublep = data->progress.timespent;
@@ -119,7 +120,7 @@ CURLcode Curl_getinfo(struct UrlData *data, CURLINFO info, ...)
*param_doublep = data->progress.ulspeed; *param_doublep = data->progress.ulspeed;
break; break;
case CURLINFO_SSL_VERIFYRESULT: case CURLINFO_SSL_VERIFYRESULT:
*param_longp = data->ssl.certverifyresult; *param_longp = data->set.ssl.certverifyresult;
break; break;
case CURLINFO_CONTENT_LENGTH_DOWNLOAD: case CURLINFO_CONTENT_LENGTH_DOWNLOAD:
*param_doublep = data->progress.size_dl; *param_doublep = data->progress.size_dl;
@@ -132,3 +133,11 @@ CURLcode Curl_getinfo(struct UrlData *data, CURLINFO info, ...)
} }
return CURLE_OK; return CURLE_OK;
} }
/*
* local variables:
* eval: (load-file "../curl-mode.el")
* end:
* vim600: fdm=marker
* vim: et sw=2 ts=2 sts=2 tw=78
*/

View File

@@ -22,7 +22,7 @@
* *
* $Id$ * $Id$
*****************************************************************************/ *****************************************************************************/
CURLcode Curl_getinfo(struct UrlData *data, CURLINFO info, ...); CURLcode Curl_getinfo(struct SessionHandle *data, CURLINFO info, ...);
CURLcode Curl_initinfo(struct UrlData *data); CURLcode Curl_initinfo(struct SessionHandle *data);
#endif #endif

View File

@@ -244,3 +244,11 @@ char *getpass(const char *prompt)
return getpass_r(prompt, buf, sizeof(buf)); return getpass_r(prompt, buf, sizeof(buf));
} }
#endif #endif
/*
* local variables:
* eval: (load-file "../curl-mode.el")
* end:
* vim600: fdm=marker
* vim: et sw=2 ts=2 sts=2 tw=78
*/

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.
@@ -55,6 +55,7 @@
#include "urldata.h" #include "urldata.h"
#include "sendf.h" #include "sendf.h"
#include "hostip.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"
@@ -65,8 +66,168 @@
#include "memdebug.h" #include "memdebug.h"
#endif #endif
/*
* This is a wrapper function for freeing name information in a protocol
* independent way. This takes care of using the appropriate underlaying
* proper function.
*/
void Curl_freeaddrinfo(void *freethis)
{
#ifdef ENABLE_IPV6
freeaddrinfo(freethis);
#else
free(freethis);
#endif
}
/* --- resolve name or IP-number --- */ /* --- resolve name or IP-number --- */
#ifdef ENABLE_IPV6
#ifdef MALLOCDEBUG
/* These two are strictly for memory tracing and are using the same
* style as the family otherwise present in memdebug.c. I put these ones
* here since they require a bunch of struct types I didn't wanna include
* in memdebug.c
*/
int curl_getaddrinfo(char *hostname, char *service,
struct addrinfo *hints,
struct addrinfo **result,
int line, const char *source)
{
int res=(getaddrinfo)(hostname, service, hints, result);
if(0 == res) {
/* success */
if(logfile)
fprintf(logfile, "ADDR %s:%d getaddrinfo() = %p\n",
source, line, *result);
}
else {
if(logfile)
fprintf(logfile, "ADDR %s:%d getaddrinfo() failed\n",
source, line);
}
return res;
}
void curl_freeaddrinfo(struct addrinfo *freethis,
int line, const char *source)
{
(freeaddrinfo)(freethis);
if(logfile)
fprintf(logfile, "ADDR %s:%d freeaddrinfo(%p)\n",
source, line, freethis);
}
#endif
/*
* Return name information about the given hostname and port number. If
* successful, the 'addrinfo' is returned and the forth argument will point to
* memory we need to free after use. That meory *MUST* be freed with
* Curl_freeaddrinfo(), nothing else.
*/
Curl_addrinfo *Curl_getaddrinfo(struct SessionHandle *data,
char *hostname,
int port,
char **bufp)
{
struct addrinfo hints, *res;
int error;
char sbuf[NI_MAXSERV];
memset(&hints, 0, sizeof(hints));
hints.ai_family = PF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_CANONNAME;
snprintf(sbuf, sizeof(sbuf), "%d", port);
error = getaddrinfo(hostname, sbuf, &hints, &res);
if (error) {
infof(data, "getaddrinfo(3) failed for %s\n", hostname);
return NULL;
}
*bufp=(char *)res; /* make it point to the result struct */
return res;
}
#else /* following code is IPv4-only */
#ifndef HAVE_GETHOSTBYNAME_R
/**
* Performs a "deep" copy of a hostent into a buffer (returns a pointer to the
* copy). Make absolutely sure the destination buffer is big enough!
*
* Keith McGuigan
* 10/3/2001 */
static struct hostent* pack_hostent(char* buf, struct hostent* orig)
{
char* bufptr;
struct hostent* copy;
int i;
char* str;
int len;
bufptr = buf;
copy = (struct hostent*)bufptr;
bufptr += sizeof(struct hostent);
copy->h_name = bufptr;
len = strlen(orig->h_name) + 1;
strncpy(bufptr, orig->h_name, len);
bufptr += len;
/* we align on even 64bit boundaries for safety */
#define MEMALIGN(x) (((unsigned long)(x)&0xfffffff8)+8)
/* This must be aligned properly to work on many CPU architectures! */
copy->h_aliases = (char**)MEMALIGN(bufptr);
/* Figure out how many aliases there are */
for (i = 0; orig->h_aliases[i] != NULL; ++i);
/* Reserve room for the array */
bufptr += (i + 1) * sizeof(char*);
/* Clone all known aliases */
for(i = 0; (str = orig->h_aliases[i]); i++) {
len = strlen(str) + 1;
strncpy(bufptr, str, len);
copy->h_aliases[i] = bufptr;
bufptr += len;
}
/* Terminate the alias list with a NULL */
copy->h_aliases[i] = NULL;
copy->h_addrtype = orig->h_addrtype;
copy->h_length = orig->h_length;
/* align it for (at least) 32bit accesses */
bufptr = (char *)MEMALIGN(bufptr);
copy->h_addr_list = (char**)bufptr;
/* Figure out how many addresses there are */
for (i = 0; orig->h_addr_list[i] != NULL; ++i);
/* Reserve room for the array */
bufptr += (i + 1) * sizeof(char*);
i = 0;
len = orig->h_length;
str = orig->h_addr_list[i];
while (str != NULL) {
memcpy(bufptr, str, len);
copy->h_addr_list[i] = bufptr;
bufptr += len;
str = orig->h_addr_list[++i];
}
copy->h_addr_list[i] = NULL;
return copy;
}
#endif
static char *MakeIP(unsigned long num,char *addr, int addr_len) static char *MakeIP(unsigned long num,char *addr, int addr_len)
{ {
#if defined(HAVE_INET_NTOA) || defined(HAVE_INET_NTOA_R) #if defined(HAVE_INET_NTOA) || defined(HAVE_INET_NTOA_R)
@@ -88,29 +249,6 @@ static char *MakeIP(unsigned long num,char *addr, int addr_len)
return (addr); return (addr);
} }
#ifdef ENABLE_IPV6
struct addrinfo *Curl_getaddrinfo(struct UrlData *data,
char *hostname,
int port)
{
struct addrinfo hints, *res;
int error;
char sbuf[NI_MAXSERV];
memset(&hints, 0, sizeof(hints));
hints.ai_family = PF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_CANONNAME;
snprintf(sbuf, sizeof(sbuf), "%d", port);
error = getaddrinfo(hostname, sbuf, &hints, &res);
if (error) {
infof(data, "getaddrinfo(3) failed for %s\n", hostname);
return NULL;
}
return res;
}
#endif
/* The original code to this function was once stolen from the Dancer source /* The original code to this function was once stolen from the Dancer source
code, written by Bjorn Reese, it has since been patched and modified code, written by Bjorn Reese, it has since been patched and modified
considerably. */ considerably. */
@@ -119,9 +257,10 @@ struct addrinfo *Curl_getaddrinfo(struct UrlData *data,
#define INADDR_NONE (unsigned long) ~0 #define INADDR_NONE (unsigned long) ~0
#endif #endif
struct hostent *Curl_gethost(struct UrlData *data, Curl_addrinfo *Curl_getaddrinfo(struct SessionHandle *data,
char *hostname, char *hostname,
char **bufp) int port,
char **bufp)
{ {
struct hostent *h = NULL; struct hostent *h = NULL;
unsigned long in; unsigned long in;
@@ -137,6 +276,7 @@ struct hostent *Curl_gethost(struct UrlData *data,
return NULL; /* major failure */ return NULL; /* major failure */
*bufp = buf; *bufp = buf;
port=0; /* unused in IPv4 code */
ret = 0; /* to prevent the compiler warning */ ret = 0; /* to prevent the compiler warning */
if ( (in=inet_addr(hostname)) != INADDR_NONE ) { if ( (in=inet_addr(hostname)) != INADDR_NONE ) {
@@ -211,7 +351,22 @@ struct hostent *Curl_gethost(struct UrlData *data,
free(buf); free(buf);
*bufp=NULL; *bufp=NULL;
} }
else
/* we make a copy of the hostent right now, right here, as the
static one we got a pointer to might get removed when we don't
want/expect that */
h = pack_hostent(buf, h);
#endif #endif
} }
return (h); return (h);
} }
#endif /* end of IPv4-specific code */
/*
* local variables:
* eval: (load-file "../curl-mode.el")
* end:
* vim600: fdm=marker
* vim: et sw=2 ts=2 sts=2 tw=78
*/

View File

@@ -24,12 +24,24 @@
*****************************************************************************/ *****************************************************************************/
struct addrinfo; struct addrinfo;
struct addrinfo *Curl_getaddrinfo(struct UrlData *data, struct hostent;
char *hostname, struct SessionHandle;
int port);
struct hostent *Curl_gethost(struct UrlData *data, /* Get name info */
char *hostname, Curl_addrinfo *Curl_getaddrinfo(struct SessionHandle *data,
char **bufp); char *hostname,
int port,
char **bufp);
/* free name info */
void Curl_freeaddrinfo(void *freethis);
#ifdef MALLOCDEBUG
void curl_freeaddrinfo(struct addrinfo *freethis,
int line, const char *source);
int curl_getaddrinfo(char *hostname, char *service,
struct addrinfo *hints,
struct addrinfo **result,
int line, const char *source);
#endif
#endif #endif

View File

@@ -125,22 +125,27 @@ send_buffer *add_buffer_init(void)
* add_buffer_send() sends a buffer and frees all associated memory. * add_buffer_send() sends a buffer and frees all associated memory.
*/ */
static static
size_t 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)
{ {
size_t amount; size_t amount;
if(conn->data->bits.verbose) { CURLcode result;
fputs("> ", conn->data->err);
if(conn->data->set.verbose) {
fputs("> ", conn->data->set.err);
/* this data _may_ contain binary stuff */ /* this data _may_ contain binary stuff */
fwrite(in->buffer, in->size_used, 1, conn->data->err); fwrite(in->buffer, in->size_used, 1, conn->data->set.err);
} }
Curl_write(conn, sockfd, in->buffer, in->size_used, &amount); result = Curl_write(conn, sockfd, in->buffer, in->size_used, &amount);
if(in->buffer) if(in->buffer)
free(in->buffer); free(in->buffer);
free(in); free(in);
return amount; *bytes_written = amount;
return result;
} }
@@ -204,31 +209,18 @@ CURLcode add_buffer(send_buffer *in, const void *inptr, size_t size)
*/ */
static static
int GetLine(int sockfd, char *buf, struct connectdata *conn) int GetLine(int sockfd, char *ptr, struct connectdata *conn)
{ {
ssize_t nread; ssize_t nread;
int read_rc=1;
char *ptr;
struct UrlData *data=conn->data;
ptr=buf;
/* get us a full line, terminated with a newline */ /* get us a full line, terminated with a newline */
for(nread=0; for(nread=0; (nread<BUFSIZE); nread++, ptr++) {
(nread<BUFSIZE) && read_rc;
nread++, ptr++) {
if((CURLE_OK != Curl_read(conn, sockfd, ptr, 1, &nread)) || if((CURLE_OK != Curl_read(conn, sockfd, ptr, 1, &nread)) ||
(nread <= 0) || (nread <= 0) || (*ptr == '\n'))
(*ptr == '\n'))
break; break;
} }
*ptr=0; /* zero terminate */ *ptr=0; /* zero terminate */
if(data->bits.verbose) {
fputs("< ", data->err);
fwrite(buf, 1, nread, data->err);
fputs("\n", data->err);
}
return nread>0?nread:0; return nread>0?nread:0;
} }
@@ -238,12 +230,12 @@ int GetLine(int sockfd, char *buf, struct connectdata *conn)
* This function checks the linked list of custom HTTP headers for a particular * This function checks the linked list of custom HTTP headers for a particular
* header (prefix). * header (prefix).
*/ */
static bool checkheaders(struct UrlData *data, const char *thisheader) static bool checkheaders(struct SessionHandle *data, const char *thisheader)
{ {
struct curl_slist *head; struct curl_slist *head;
size_t thislen = strlen(thisheader); size_t thislen = strlen(thisheader);
for(head = data->headers; head; head=head->next) { for(head = data->set.headers; head; head=head->next) {
if(strnequal(head->data, thisheader, thislen)) { if(strnequal(head->data, thisheader, thislen)) {
return TRUE; return TRUE;
} }
@@ -263,26 +255,35 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn,
{ {
int httperror=0; int httperror=0;
int subversion=0; int subversion=0;
struct UrlData *data=conn->data; struct SessionHandle *data=conn->data;
CURLcode result;
infof(data, "Establish HTTP proxy tunnel to %s:%d\n", hostname, remote_port); infof(data, "Establish HTTP proxy tunnel to %s:%d\n", hostname, remote_port);
/* OK, now send the connect request to the proxy */ /* OK, now send the connect request to the proxy */
Curl_sendf(tunnelsocket, conn, result =
"CONNECT %s:%d HTTP/1.0\015\012" Curl_sendf(tunnelsocket, conn,
"%s" "CONNECT %s:%d HTTP/1.0\015\012"
"%s" "%s"
"\r\n", "%s"
hostname, remote_port, "\r\n",
(conn->bits.proxy_user_passwd)?conn->allocptr.proxyuserpwd:"", hostname, remote_port,
(data->useragent?conn->allocptr.uagent:"") (conn->bits.proxy_user_passwd)?conn->allocptr.proxyuserpwd:"",
); (data->set.useragent?conn->allocptr.uagent:"")
);
if(result) {
failf(data, "Failed sending CONNECT to proxy");
return result;
}
/* wait for the proxy to send us a HTTP/1.0 200 OK header */ /* wait for the proxy to send us a HTTP/1.0 200 OK header */
while(GetLine(tunnelsocket, data->buffer, conn)) { while(GetLine(tunnelsocket, data->state.buffer, conn)) {
if('\r' == data->buffer[0]) if('\r' == data->state.buffer[0])
break; /* end of headers */ break; /* end of headers */
if(2 == sscanf(data->buffer, "HTTP/1.%d %d", if(data->set.verbose)
fprintf(data->set.err, "< %s\n", data->state.buffer);
if(2 == sscanf(data->state.buffer, "HTTP/1.%d %d",
&subversion, &subversion,
&httperror)) { &httperror)) {
; ;
@@ -306,7 +307,7 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn,
*/ */
CURLcode Curl_http_connect(struct connectdata *conn) CURLcode Curl_http_connect(struct connectdata *conn)
{ {
struct UrlData *data; struct SessionHandle *data;
CURLcode result; CURLcode result;
data=conn->data; data=conn->data;
@@ -318,7 +319,7 @@ CURLcode Curl_http_connect(struct connectdata *conn)
* has occured, can we start talking SSL * has occured, can we start talking SSL
*/ */
if (conn->protocol & PROT_HTTPS) { if (conn->protocol & PROT_HTTPS) {
if (data->bits.httpproxy) { if (data->change.proxy) {
/* HTTPS through a proxy can only be done with a tunnel */ /* HTTPS through a proxy can only be done with a tunnel */
result = Curl_ConnectHTTPProxyTunnel(conn, conn->firstsocket, result = Curl_ConnectHTTPProxyTunnel(conn, conn->firstsocket,
conn->hostname, conn->remote_port); conn->hostname, conn->remote_port);
@@ -332,53 +333,51 @@ CURLcode Curl_http_connect(struct connectdata *conn)
return result; return result;
} }
if(conn->bits.user_passwd && !data->bits.this_is_a_follow) { if(conn->bits.user_passwd && !data->state.this_is_a_follow) {
/* Authorization: is requested, this is not a followed location, get the /* Authorization: is requested, this is not a followed location, get the
original host name */ original host name */
data->auth_host = strdup(conn->hostname); data->state.auth_host = strdup(conn->hostname);
} }
return CURLE_OK; return CURLE_OK;
} }
/* called from curl_close() when this struct is about to get wasted, free
protocol-specific resources */
CURLcode Curl_http_close(struct connectdata *conn)
{
if(conn->data->auth_host)
free(conn->data->auth_host);
return CURLE_OK;
}
CURLcode Curl_http_done(struct connectdata *conn) CURLcode Curl_http_done(struct connectdata *conn)
{ {
struct UrlData *data; struct SessionHandle *data;
long *bytecount = &conn->bytecount; long *bytecount = &conn->bytecount;
struct HTTP *http; struct HTTP *http;
data=conn->data; data=conn->data;
http=conn->proto.http; http=conn->proto.http;
if(HTTPREQ_POST_FORM == data->httpreq) { if(HTTPREQ_POST_FORM == data->set.httpreq) {
*bytecount = http->readbytecount + http->writebytecount; *bytecount = http->readbytecount + http->writebytecount;
Curl_formclean(http->sendit); /* Now free that whole lot */ Curl_formclean(http->sendit); /* Now free that whole lot */
data->fread = http->storefread; /* restore */ data->set.fread = http->storefread; /* restore */
data->in = http->in; /* restore */ data->set.in = http->in; /* restore */
} }
else if(HTTPREQ_PUT == data->httpreq) { else if(HTTPREQ_PUT == data->set.httpreq) {
*bytecount = http->readbytecount + http->writebytecount; *bytecount = http->readbytecount + http->writebytecount;
} }
if(0 == (http->readbytecount + conn->headerbytecount)) {
/* nothing was read from the HTTP server, this can't be right
so we return an error here */
failf(data, "Empty reply from server\n");
return CURLE_GOT_NOTHING;
}
return CURLE_OK; return CURLE_OK;
} }
CURLcode Curl_http(struct connectdata *conn) CURLcode Curl_http(struct connectdata *conn)
{ {
struct UrlData *data=conn->data; struct SessionHandle *data=conn->data;
char *buf = data->buffer; /* this is a short cut to the buffer */ char *buf = data->state.buffer; /* this is a short cut to the buffer */
CURLcode result=CURLE_OK; CURLcode result=CURLE_OK;
struct HTTP *http; struct HTTP *http;
struct Cookie *co=NULL; /* no cookies from start */ struct Cookie *co=NULL; /* no cookies from start */
@@ -402,8 +401,8 @@ CURLcode Curl_http(struct connectdata *conn)
conn->bits.close = FALSE; conn->bits.close = FALSE;
if ( (conn->protocol&(PROT_HTTP|PROT_FTP)) && if ( (conn->protocol&(PROT_HTTP|PROT_FTP)) &&
data->bits.upload) { data->set.upload) {
data->httpreq = HTTPREQ_PUT; data->set.httpreq = HTTPREQ_PUT;
} }
/* The User-Agent string has been built in url.c already, because it might /* The User-Agent string has been built in url.c already, because it might
@@ -420,45 +419,45 @@ CURLcode Curl_http(struct connectdata *conn)
/* To prevent the user+password to get sent to other than the original /* To prevent the user+password to get sent to other than the original
host due to a location-follow, we do some weirdo checks here */ host due to a location-follow, we do some weirdo checks here */
if(!data->bits.this_is_a_follow || if(!data->state.this_is_a_follow ||
!data->auth_host || !data->state.auth_host ||
strequal(data->auth_host, conn->hostname)) { strequal(data->state.auth_host, conn->hostname)) {
sprintf(data->buffer, "%s:%s", data->user, data->passwd); sprintf(data->state.buffer, "%s:%s",
if(Curl_base64_encode(data->buffer, strlen(data->buffer), data->state.user, data->state.passwd);
if(Curl_base64_encode(data->state.buffer, strlen(data->state.buffer),
&authorization) >= 0) { &authorization) >= 0) {
if(conn->allocptr.userpwd) if(conn->allocptr.userpwd)
free(conn->allocptr.userpwd); free(conn->allocptr.userpwd);
conn->allocptr.userpwd = aprintf( "Authorization: Basic %s\015\012", conn->allocptr.userpwd = aprintf( "Authorization: Basic %s\015\012",
authorization); authorization);
free(authorization); free(authorization);
} }
} }
} }
if((data->bits.http_set_referer) && !checkheaders(data, "Referer:")) { if((data->change.referer) && !checkheaders(data, "Referer:")) {
if(conn->allocptr.ref) if(conn->allocptr.ref)
free(conn->allocptr.ref); free(conn->allocptr.ref);
conn->allocptr.ref = aprintf("Referer: %s\015\012", data->referer); conn->allocptr.ref = aprintf("Referer: %s\015\012", data->change.referer);
} }
if(data->cookie && !checkheaders(data, "Cookie:")) { if(data->set.cookie && !checkheaders(data, "Cookie:")) {
if(conn->allocptr.cookie) if(conn->allocptr.cookie)
free(conn->allocptr.cookie); free(conn->allocptr.cookie);
conn->allocptr.cookie = aprintf("Cookie: %s\015\012", data->cookie); conn->allocptr.cookie = aprintf("Cookie: %s\015\012", data->set.cookie);
} }
if(data->cookies) { if(data->cookies) {
co = Curl_cookie_getlist(data->cookies, co = Curl_cookie_getlist(data->cookies,
host, host, ppath,
ppath,
conn->protocol&PROT_HTTPS?TRUE:FALSE); conn->protocol&PROT_HTTPS?TRUE:FALSE);
} }
if ((data->bits.httpproxy) && !(conn->protocol&PROT_HTTPS)) { if ((data->change.proxy) && !(conn->protocol&PROT_HTTPS)) {
/* The path sent to the proxy is in fact the entire URL */ /* The path sent to the proxy is in fact the entire URL */
ppath = data->url; ppath = data->change.url;
} }
if(HTTPREQ_POST_FORM == data->httpreq) { if(HTTPREQ_POST_FORM == data->set.httpreq) {
/* we must build the whole darned post sequence first, so that we have /* we must build the whole darned post sequence first, so that we have
a size of the whole shebang before we start to send it */ a size of the whole shebang before we start to send it */
http->sendit = Curl_getFormData(data->httppost, &http->postsize); http->sendit = Curl_getFormData(data->set.httppost, &http->postsize);
} }
if(!checkheaders(data, "Host:")) { if(!checkheaders(data, "Host:")) {
@@ -486,9 +485,9 @@ CURLcode Curl_http(struct connectdata *conn)
if(!checkheaders(data, "Accept:")) if(!checkheaders(data, "Accept:"))
http->p_accept = "Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*\r\n"; http->p_accept = "Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*\r\n";
if(( (HTTPREQ_POST == data->httpreq) || if(( (HTTPREQ_POST == data->set.httpreq) ||
(HTTPREQ_POST_FORM == data->httpreq) || (HTTPREQ_POST_FORM == data->set.httpreq) ||
(HTTPREQ_PUT == data->httpreq) ) && (HTTPREQ_PUT == data->set.httpreq) ) &&
conn->resume_from) { conn->resume_from) {
/********************************************************************** /**********************************************************************
* Resuming upload in HTTP means that we PUT or POST and that we have * Resuming upload in HTTP means that we PUT or POST and that we have
@@ -521,7 +520,8 @@ CURLcode Curl_http(struct connectdata *conn)
readthisamountnow = BUFSIZE; readthisamountnow = BUFSIZE;
actuallyread = actuallyread =
data->fread(data->buffer, 1, readthisamountnow, data->in); data->set.fread(data->state.buffer, 1, readthisamountnow,
data->set.in);
passed += actuallyread; passed += actuallyread;
if(actuallyread != readthisamountnow) { if(actuallyread != readthisamountnow) {
@@ -532,10 +532,10 @@ CURLcode Curl_http(struct connectdata *conn)
} while(passed != conn->resume_from); /* loop until done */ } while(passed != conn->resume_from); /* loop until done */
/* now, decrease the size of the read */ /* now, decrease the size of the read */
if(data->infilesize>0) { if(data->set.infilesize>0) {
data->infilesize -= conn->resume_from; data->set.infilesize -= conn->resume_from;
if(data->infilesize <= 0) { if(data->set.infilesize <= 0) {
failf(data, "File already completely uploaded\n"); failf(data, "File already completely uploaded\n");
return CURLE_PARTIAL_FILE; return CURLE_PARTIAL_FILE;
} }
@@ -549,16 +549,16 @@ CURLcode Curl_http(struct connectdata *conn)
* or uploading and we always let customized headers override our internal * or uploading and we always let customized headers override our internal
* ones if any such are specified. * ones if any such are specified.
*/ */
if((data->httpreq == HTTPREQ_GET) && if((data->set.httpreq == HTTPREQ_GET) &&
!checkheaders(data, "Range:")) { !checkheaders(data, "Range:")) {
conn->allocptr.rangeline = aprintf("Range: bytes=%s\r\n", conn->range); conn->allocptr.rangeline = aprintf("Range: bytes=%s\r\n", conn->range);
} }
else if((data->httpreq != HTTPREQ_GET) && else if((data->set.httpreq != HTTPREQ_GET) &&
!checkheaders(data, "Content-Range:")) { !checkheaders(data, "Content-Range:")) {
if(conn->resume_from) { if(conn->resume_from) {
/* This is because "resume" was selected */ /* This is because "resume" was selected */
long total_expected_size= conn->resume_from + data->infilesize; long total_expected_size= conn->resume_from + data->set.infilesize;
conn->allocptr.rangeline = aprintf("Content-Range: bytes %s%ld/%ld\r\n", conn->allocptr.rangeline = aprintf("Content-Range: bytes %s%ld/%ld\r\n",
conn->range, total_expected_size-1, conn->range, total_expected_size-1,
total_expected_size); total_expected_size);
@@ -567,14 +567,18 @@ CURLcode Curl_http(struct connectdata *conn)
/* Range was selected and then we just pass the incoming range and /* Range was selected and then we just pass the incoming range and
append total size */ append total size */
conn->allocptr.rangeline = aprintf("Content-Range: bytes %s/%d\r\n", conn->allocptr.rangeline = aprintf("Content-Range: bytes %s/%d\r\n",
conn->range, data->infilesize); conn->range, data->set.infilesize);
} }
} }
} }
do { do {
/* Use 1.1 unless the use specificly asked for 1.0 */
const char *httpstring=
data->set.httpversion==CURL_HTTP_VERSION_1_0?"1.0":"1.1";
send_buffer *req_buffer; send_buffer *req_buffer;
struct curl_slist *headers=data->headers; struct curl_slist *headers=data->set.headers;
/* initialize a dynamic send-buffer */ /* initialize a dynamic send-buffer */
req_buffer = add_buffer_init(); req_buffer = add_buffer_init();
@@ -582,7 +586,7 @@ CURLcode Curl_http(struct connectdata *conn)
/* add the main request stuff */ /* add the main request stuff */
add_bufferf(req_buffer, add_bufferf(req_buffer,
"%s " /* GET/HEAD/POST/PUT */ "%s " /* GET/HEAD/POST/PUT */
"%s HTTP/1.1\r\n" /* path */ "%s HTTP/%s\r\n" /* path */
"%s" /* proxyuserpwd */ "%s" /* proxyuserpwd */
"%s" /* userpwd */ "%s" /* userpwd */
"%s" /* range */ "%s" /* range */
@@ -593,25 +597,25 @@ CURLcode Curl_http(struct connectdata *conn)
"%s" /* accept */ "%s" /* accept */
"%s", /* referer */ "%s", /* referer */
data->customrequest?data->customrequest: data->set.customrequest?data->set.customrequest:
(data->bits.no_body?"HEAD": (data->set.no_body?"HEAD":
((HTTPREQ_POST == data->httpreq) || ((HTTPREQ_POST == data->set.httpreq) ||
(HTTPREQ_POST_FORM == data->httpreq))?"POST": (HTTPREQ_POST_FORM == data->set.httpreq))?"POST":
(HTTPREQ_PUT == data->httpreq)?"PUT":"GET"), (HTTPREQ_PUT == data->set.httpreq)?"PUT":"GET"),
ppath, ppath, httpstring,
(conn->bits.proxy_user_passwd && (conn->bits.proxy_user_passwd &&
conn->allocptr.proxyuserpwd)?conn->allocptr.proxyuserpwd:"", conn->allocptr.proxyuserpwd)?conn->allocptr.proxyuserpwd:"",
(conn->bits.user_passwd && conn->allocptr.userpwd)? (conn->bits.user_passwd && conn->allocptr.userpwd)?
conn->allocptr.userpwd:"", conn->allocptr.userpwd:"",
(conn->bits.use_range && conn->allocptr.rangeline)? (conn->bits.use_range && conn->allocptr.rangeline)?
conn->allocptr.rangeline:"", conn->allocptr.rangeline:"",
(data->useragent && *data->useragent && conn->allocptr.uagent)? (data->set.useragent && *data->set.useragent && conn->allocptr.uagent)?
conn->allocptr.uagent:"", conn->allocptr.uagent:"",
(conn->allocptr.cookie?conn->allocptr.cookie:""), /* Cookie: <data> */ (conn->allocptr.cookie?conn->allocptr.cookie:""), /* Cookie: <data> */
(conn->allocptr.host?conn->allocptr.host:""), /* Host: host */ (conn->allocptr.host?conn->allocptr.host:""), /* Host: host */
http->p_pragma?http->p_pragma:"", http->p_pragma?http->p_pragma:"",
http->p_accept?http->p_accept:"", http->p_accept?http->p_accept:"",
(data->bits.http_set_referer && conn->allocptr.ref)?conn->allocptr.ref:"" /* Referer: <data> <CRLF> */ (data->change.referer && conn->allocptr.ref)?conn->allocptr.ref:"" /* Referer: <data> <CRLF> */
); );
if(co) { if(co) {
@@ -636,7 +640,7 @@ CURLcode Curl_http(struct connectdata *conn)
co=NULL; co=NULL;
} }
if(data->timecondition) { if(data->set.timecondition) {
struct tm *thistime; struct tm *thistime;
/* Phil Karn (Fri, 13 Apr 2001) pointed out that the If-Modified-Since /* Phil Karn (Fri, 13 Apr 2001) pointed out that the If-Modified-Since
@@ -651,9 +655,9 @@ CURLcode Curl_http(struct connectdata *conn)
/* We assume that the presense of localtime_r() proves the presense /* We assume that the presense of localtime_r() proves the presense
of gmtime_r() which is a bit ugly but might work */ of gmtime_r() which is a bit ugly but might work */
struct tm keeptime; struct tm keeptime;
thistime = (struct tm *)gmtime_r(&data->timevalue, &keeptime); thistime = (struct tm *)gmtime_r(&data->set.timevalue, &keeptime);
#else #else
thistime = gmtime(&data->timevalue); thistime = gmtime(&data->set.timevalue);
#endif #endif
if(NULL == thistime) { if(NULL == thistime) {
failf(data, "localtime() failed!"); failf(data, "localtime() failed!");
@@ -667,7 +671,7 @@ CURLcode Curl_http(struct connectdata *conn)
/* TODO: Right, we *could* write a replacement here */ /* TODO: Right, we *could* write a replacement here */
strcpy(buf, "no strftime() support"); strcpy(buf, "no strftime() support");
#endif #endif
switch(data->timecondition) { switch(data->set.timecondition) {
case TIMECOND_IFMODSINCE: case TIMECOND_IFMODSINCE:
default: default:
add_bufferf(req_buffer, add_bufferf(req_buffer,
@@ -702,76 +706,107 @@ CURLcode Curl_http(struct connectdata *conn)
headers = headers->next; headers = headers->next;
} }
if(HTTPREQ_POST_FORM == data->httpreq) { if(HTTPREQ_POST_FORM == data->set.httpreq) {
char contentType[256];
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!\n");
return CURLE_HTTP_POST_ERROR; return CURLE_HTTP_POST_ERROR;
} }
http->storefread = data->fread; /* backup */ http->storefread = data->set.fread; /* backup */
http->in = data->in; /* backup */ http->in = data->set.in; /* backup */
data->fread = (curl_read_callback) data->set.fread = (curl_read_callback)
Curl_FormReader; /* set the read function to read from the Curl_FormReader; /* set the read function to read from the
generated form data */ generated form data */
data->in = (FILE *)&http->form; data->set.in = (FILE *)&http->form;
add_bufferf(req_buffer, add_bufferf(req_buffer,
"Content-Length: %d\r\n", http->postsize-2); "Content-Length: %d\r\n", http->postsize-2);
if(!checkheaders(data, "Expect:")) {
/* if not disabled explicitly we add a Expect: 100-continue
to the headers which actually speeds up post operations (as
there is one packet coming back from the web server) */
add_bufferf(req_buffer,
"Expect: 100-continue\r\n");
data->set.expect100header = TRUE;
/* Get Content-Type: line from Curl_FormReadOneLine, which happens
to always be the first line. We can know this for sure since
we always build the formpost linked list the same way! */
linelength = Curl_FormReadOneLine (contentType,
sizeof(contentType),
1,
(FILE *)&http->form);
if(linelength == -1) {
failf(data, "Could not get Content-Type header line!\n");
return CURLE_HTTP_POST_ERROR;
}
add_buffer(req_buffer, contentType, linelength);
}
/* set upload size to the progress meter */ /* set upload size to the progress meter */
Curl_pgrsSetUploadSize(data, http->postsize); Curl_pgrsSetUploadSize(data, http->postsize);
data->request_size = /* fire away the whole request to the server */
add_buffer_send(conn->firstsocket, conn, req_buffer); result = add_buffer_send(conn->firstsocket, conn, req_buffer,
result = Curl_Transfer(conn, conn->firstsocket, -1, TRUE, &data->info.request_size);
&http->readbytecount, if(result)
conn->firstsocket, failf(data, "Failed sending POST request");
&http->writebytecount); else
/* setup variables for the upcoming transfer */
result = Curl_Transfer(conn, conn->firstsocket, -1, TRUE,
&http->readbytecount,
conn->firstsocket,
&http->writebytecount);
if(result) { if(result) {
Curl_formclean(http->sendit); /* free that whole lot */ Curl_formclean(http->sendit); /* free that whole lot */
return result; return result;
} }
} }
else if(HTTPREQ_PUT == data->httpreq) { else if(HTTPREQ_PUT == data->set.httpreq) {
/* Let's PUT the data to the server! */ /* Let's PUT the data to the server! */
if(data->infilesize>0) { if(data->set.infilesize>0) {
add_bufferf(req_buffer, add_bufferf(req_buffer,
"Content-Length: %d\r\n\r\n", /* file size */ "Content-Length: %d\r\n\r\n", /* file size */
data->infilesize ); data->set.infilesize );
} }
else else
add_bufferf(req_buffer, "\015\012"); add_bufferf(req_buffer, "\015\012");
/* set the upload size to the progress meter */ /* set the upload size to the progress meter */
Curl_pgrsSetUploadSize(data, data->infilesize); Curl_pgrsSetUploadSize(data, data->set.infilesize);
/* this sends the buffer and frees all the buffer resources */ /* this sends the buffer and frees all the buffer resources */
data->request_size = result = add_buffer_send(conn->firstsocket, conn, req_buffer,
add_buffer_send(conn->firstsocket, conn, req_buffer); &data->info.request_size);
if(result)
/* prepare for transfer */ failf(data, "Faied sending POST request");
result = Curl_Transfer(conn, conn->firstsocket, -1, TRUE, else
&http->readbytecount, /* prepare for transfer */
conn->firstsocket, result = Curl_Transfer(conn, conn->firstsocket, -1, TRUE,
&http->writebytecount); &http->readbytecount,
conn->firstsocket,
&http->writebytecount);
if(result) if(result)
return result; return result;
} }
else { else {
if(HTTPREQ_POST == data->httpreq) { if(HTTPREQ_POST == data->set.httpreq) {
/* this is the simple POST, using x-www-form-urlencoded style */ /* this is the simple POST, using x-www-form-urlencoded style */
if(!data->postfields) { if(!data->set.postfields) {
/* /*
* This is an attempt to do a POST without having anything to * This is an attempt to do a POST without having anything to
* actually send. Let's make a NULL pointer equal "" here. Good/bad * actually send. Let's make a NULL pointer equal "" here. Good/bad
* ? * ?
*/ */
data->postfields = (char *)""; data->set.postfields = (char *)"";
data->postfieldsize = 0; /* it might been set to something illegal, data->set.postfieldsize = 0; /* it might been set to something illegal,
anything > 0 would be! */ anything > 0 would be! */
} }
@@ -780,37 +815,40 @@ CURLcode Curl_http(struct connectdata *conn)
actually set your own */ actually set your own */
add_bufferf(req_buffer, add_bufferf(req_buffer,
"Content-Length: %d\r\n", "Content-Length: %d\r\n",
(data->postfieldsize?data->postfieldsize: (data->set.postfieldsize?data->set.postfieldsize:
strlen(data->postfields)) ); strlen(data->set.postfields)) );
if(!checkheaders(data, "Content-Type:")) if(!checkheaders(data, "Content-Type:"))
add_bufferf(req_buffer, add_bufferf(req_buffer,
"Content-Type: application/x-www-form-urlencoded\r\n"); "Content-Type: application/x-www-form-urlencoded\r\n");
/* and here comes the actual data */ /* and here comes the actual data */
if(data->postfieldsize) { if(data->set.postfieldsize) {
add_buffer(req_buffer, "\r\n", 2); add_buffer(req_buffer, "\r\n", 2);
add_buffer(req_buffer, data->postfields, add_buffer(req_buffer, data->set.postfields,
data->postfieldsize); data->set.postfieldsize);
add_buffer(req_buffer, "\r\n", 2); add_buffer(req_buffer, "\r\n", 2);
} }
else { else {
add_bufferf(req_buffer, add_bufferf(req_buffer,
"\r\n" "\r\n"
"%s\r\n", "%s\r\n",
data->postfields ); data->set.postfields );
} }
} }
else else
add_buffer(req_buffer, "\r\n", 2); add_buffer(req_buffer, "\r\n", 2);
/* issue the request */ /* issue the request */
data->request_size = result = add_buffer_send(conn->firstsocket, conn, req_buffer,
add_buffer_send(conn->firstsocket, conn, req_buffer); &data->info.request_size);
/* HTTP GET/HEAD download: */ if(result)
result = Curl_Transfer(conn, conn->firstsocket, -1, TRUE, bytecount, failf(data, "Failed sending HTTP request");
-1, NULL); /* nothing to upload */ else
/* HTTP GET/HEAD download: */
result = Curl_Transfer(conn, conn->firstsocket, -1, TRUE, bytecount,
-1, NULL); /* nothing to upload */
} }
if(result) if(result)
return result; return result;
@@ -820,3 +858,11 @@ CURLcode Curl_http(struct connectdata *conn)
return CURLE_OK; return CURLE_OK;
} }
/*
* local variables:
* eval: (load-file "../curl-mode.el")
* end:
* vim600: fdm=marker
* vim: et sw=2 ts=2 sts=2 tw=78
*/

View File

@@ -33,7 +33,6 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn,
CURLcode Curl_http(struct connectdata *conn); CURLcode Curl_http(struct connectdata *conn);
CURLcode Curl_http_done(struct connectdata *conn); CURLcode Curl_http_done(struct connectdata *conn);
CURLcode Curl_http_connect(struct connectdata *conn); CURLcode Curl_http_connect(struct connectdata *conn);
CURLcode Curl_http_close(struct connectdata *conn);
/* The following functions are defined in http_chunks.c */ /* The following functions are defined in http_chunks.c */
void Curl_httpchunk_init(struct connectdata *conn); void Curl_httpchunk_init(struct connectdata *conn);

View File

@@ -44,7 +44,7 @@
* Chunk format (simplified): * Chunk format (simplified):
* *
* <HEX SIZE>[ chunk extension ] CRLF * <HEX SIZE>[ chunk extension ] CRLF
* <DATA> * <DATA> CRLF
* *
* Highlights from RFC2616 section 3.6 say: * Highlights from RFC2616 section 3.6 say:
@@ -220,3 +220,11 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
} }
return CHUNKE_OK; return CHUNKE_OK;
} }
/*
* local variables:
* eval: (load-file "../curl-mode.el")
* end:
* vim600: fdm=marker
* vim: et sw=2 ts=2 sts=2 tw=78
*/

View File

@@ -124,3 +124,11 @@ char *Curl_if2ip(char *interface, char *buf, int buf_size)
#else #else
#define if2ip(x) NULL #define if2ip(x) NULL
#endif #endif
/*
* local variables:
* eval: (load-file "../curl-mode.el")
* end:
* vim600: fdm=marker
* vim: et sw=2 ts=2 sts=2 tw=78
*/

View File

@@ -194,7 +194,7 @@ krb4_auth(void *app_data, struct connectdata *conn)
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; struct sockaddr_in *localaddr = (struct sockaddr_in *)LOCAL_ADDR;
char *host = conn->hp->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);
@@ -245,20 +245,20 @@ krb4_auth(void *app_data, struct connectdata *conn)
return AUTH_CONTINUE; return AUTH_CONTINUE;
} }
Curl_ftpsendf(conn->firstsocket, conn, "ADAT %s", p); if(Curl_ftpsendf(conn, "ADAT %s", p))
return -2;
nread = Curl_GetFTPResponse(conn->firstsocket, nread = Curl_GetFTPResponse(conn->data->state.buffer, conn, NULL);
conn->data->buffer, conn, NULL);
if(nread < 0) if(nread < 0)
return /*CURLE_OPERATION_TIMEOUTED*/-1; return -1;
free(p); free(p);
if(/*ret != COMPLETE*/conn->data->buffer[0] != '2'){ if(/*ret != COMPLETE*/conn->data->state.buffer[0] != '2'){
printf("Server didn't accept auth data.\n"); printf("Server didn't accept auth data.\n");
return AUTH_ERROR; return AUTH_ERROR;
} }
p = strstr(conn->data->buffer, "ADAT="); p = strstr(conn->data->state.buffer, "ADAT=");
if(!p){ if(!p){
printf("Remote host didn't send adat reply.\n"); printf("Remote host didn't send adat reply.\n");
return AUTH_ERROR; return AUTH_ERROR;
@@ -313,21 +313,21 @@ void Curl_krb_kauth(struct connectdata *conn)
save = Curl_set_command_prot(conn, prot_private); save = Curl_set_command_prot(conn, prot_private);
Curl_ftpsendf(conn->firstsocket, conn, if(Curl_ftpsendf(conn, "SITE KAUTH %s", conn->data->state.user))
"SITE KAUTH %s", conn->data->user); return;
nread = Curl_GetFTPResponse(conn->firstsocket, conn->data->buffer, nread = Curl_GetFTPResponse(conn->data->state.buffer,
conn, NULL); conn, NULL);
if(nread < 0) if(nread < 0)
return /*CURLE_OPERATION_TIMEOUTED*/; return /*CURLE_OPERATION_TIMEOUTED*/;
if(/*ret != CONTINUE*/conn->data->buffer[0] != '3'){ if(/*ret != CONTINUE*/conn->data->state.buffer[0] != '3'){
Curl_set_command_prot(conn, save); Curl_set_command_prot(conn, save);
/*code = -1;***/ /*code = -1;***/
return; return;
} }
p = strstr(conn->data->buffer, "T="); p = strstr(conn->data->state.buffer, "T=");
if(!p) { if(!p) {
printf("Bad reply from server.\n"); printf("Bad reply from server.\n");
Curl_set_command_prot(conn, save); Curl_set_command_prot(conn, save);
@@ -344,7 +344,7 @@ void Curl_krb_kauth(struct connectdata *conn)
tkt.length = tmp; tkt.length = tmp;
tktcopy.length = tkt.length; tktcopy.length = tkt.length;
p = strstr(conn->data->buffer, "P="); p = strstr(conn->data->state.buffer, "P=");
if(!p) { if(!p) {
printf("Bad reply from server.\n"); printf("Bad reply from server.\n");
Curl_set_command_prot(conn, save); Curl_set_command_prot(conn, save);
@@ -354,7 +354,7 @@ void Curl_krb_kauth(struct connectdata *conn)
for(; *p && *p != ' ' && *p != '\r' && *p != '\n'; p++); for(; *p && *p != ' ' && *p != '\r' && *p != '\n'; p++);
*p = 0; *p = 0;
des_string_to_key (conn->data->passwd, &key); des_string_to_key (conn->data->state.passwd, &key);
des_key_sched(&key, schedule); des_key_sched(&key, schedule);
des_pcbc_encrypt((des_cblock*)tkt.dat, (des_cblock*)tktcopy.dat, des_pcbc_encrypt((des_cblock*)tkt.dat, (des_cblock*)tktcopy.dat,
@@ -363,7 +363,7 @@ void Curl_krb_kauth(struct connectdata *conn)
if (strcmp ((char*)tktcopy.dat + 8, if (strcmp ((char*)tktcopy.dat + 8,
KRB_TICKET_GRANTING_TICKET) != 0) { KRB_TICKET_GRANTING_TICKET) != 0) {
afs_string_to_key (passwd, afs_string_to_key (passwd,
krb_realmofhost(/*hostname*/conn->hp->h_name), krb_realmofhost(conn->hostaddr->h_name),
&key); &key);
des_key_sched (&key, schedule); des_key_sched (&key, schedule);
des_pcbc_encrypt((des_cblock*)tkt.dat, (des_cblock*)tktcopy.dat, des_pcbc_encrypt((des_cblock*)tkt.dat, (des_cblock*)tktcopy.dat,
@@ -380,10 +380,10 @@ void Curl_krb_kauth(struct connectdata *conn)
} }
memset (tktcopy.dat, 0, tktcopy.length); memset (tktcopy.dat, 0, tktcopy.length);
Curl_ftpsendf(conn->firstsocket, conn, if(Curl_ftpsendf(conn, "SITE KAUTH %s %s", name, p))
"SITE KAUTH %s %s", name, p); return;
nread = Curl_GetFTPResponse(conn->firstsocket, conn->data->buffer, nread = Curl_GetFTPResponse(conn->data->state.buffer,
conn, NULL); conn, NULL);
if(nread < 0) if(nread < 0)
return /*CURLE_OPERATION_TIMEOUTED*/; return /*CURLE_OPERATION_TIMEOUTED*/;
@@ -392,3 +392,11 @@ void Curl_krb_kauth(struct connectdata *conn)
} }
#endif /* KRB4 */ #endif /* KRB4 */
/*
* local variables:
* eval: (load-file "../curl-mode.el")
* end:
* vim600: fdm=marker
* vim: et sw=2 ts=2 sts=2 tw=78
*/

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.
@@ -47,6 +47,7 @@
#include <curl/curl.h> #include <curl/curl.h>
#include "sendf.h" #include "sendf.h"
#include "escape.h" #include "escape.h"
#include "transfer.h"
#define _MPRINTF_REPLACE /* use our functions only */ #define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h> #include <curl/mprintf.h>
@@ -116,7 +117,7 @@ static void * DynaGetFunction(const char *name)
static int WriteProc(void *param, char *text, int len) static int WriteProc(void *param, char *text, int len)
{ {
struct UrlData *data = (struct UrlData *)param; struct SessionHandle *data = (struct SessionHandle *)param;
len = 0; /* prevent compiler warning */ len = 0; /* prevent compiler warning */
Curl_client_write(data, CLIENTWRITE_BODY, text, 0); Curl_client_write(data, CLIENTWRITE_BODY, text, 0);
return 0; return 0;
@@ -142,9 +143,9 @@ CURLcode Curl_ldap(struct connectdata *conn)
void *entryIterator; void *entryIterator;
int ldaptext; int ldaptext;
struct UrlData *data=conn->data; struct SessionHandle *data=conn->data;
infof(data, "LDAP: %s %s\n", data->url); infof(data, "LDAP: %s %s\n", data->change.url);
DynaOpen(); DynaOpen();
if (libldap == NULL) { if (libldap == NULL) {
@@ -152,7 +153,7 @@ CURLcode Curl_ldap(struct connectdata *conn)
return CURLE_LIBRARY_NOT_FOUND; return CURLE_LIBRARY_NOT_FOUND;
} }
ldaptext = data->bits.ftp_ascii; /* This is a dirty hack */ ldaptext = data->set.ftp_ascii; /* This is a dirty hack */
/* The types are needed because ANSI C distinguishes between /* The types are needed because ANSI C distinguishes between
* pointer-to-object (data) and pointer-to-function. * pointer-to-object (data) and pointer-to-function.
@@ -173,12 +174,12 @@ CURLcode Curl_ldap(struct connectdata *conn)
conn->hostname, conn->port); conn->hostname, conn->port);
status = CURLE_COULDNT_CONNECT; status = CURLE_COULDNT_CONNECT;
} else { } else {
rc = ldap_simple_bind_s(server, data->user, data->passwd); rc = ldap_simple_bind_s(server, data->state.user, data->state.passwd);
if (rc != 0) { if (rc != 0) {
failf(data, "LDAP: %s", ldap_err2string(rc)); failf(data, "LDAP: %s", ldap_err2string(rc));
status = CURLE_LDAP_CANNOT_BIND; status = CURLE_LDAP_CANNOT_BIND;
} else { } else {
rc = ldap_url_search_s(server, data->url, 0, &result); rc = ldap_url_search_s(server, data->change.url, 0, &result);
if (rc != 0) { if (rc != 0) {
failf(data, "LDAP: %s", ldap_err2string(rc)); failf(data, "LDAP: %s", ldap_err2string(rc));
status = CURLE_LDAP_SEARCH_FAILED; status = CURLE_LDAP_SEARCH_FAILED;
@@ -210,6 +211,17 @@ CURLcode Curl_ldap(struct connectdata *conn)
} }
} }
DynaClose(); DynaClose();
/* no data to transfer */
Curl_Transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
return status; return status;
} }
/*
* local variables:
* eval: (load-file "../curl-mode.el")
* end:
* vim600: fdm=marker
* vim: et sw=2 ts=2 sts=2 tw=78
*/

View File

@@ -31,4 +31,6 @@ EXPORTS
curl_mvfprintf @ 22 ; curl_mvfprintf @ 22 ;
curl_strequal @ 23 ; curl_strequal @ 23 ;
curl_strnequal @ 24 ; curl_strnequal @ 24 ;
curl_easy_duphandle @ 25 ;
curl_formadd @ 26 ;

View File

@@ -60,15 +60,19 @@ FILE *logfile;
/* this sets the log file name */ /* this sets the log file name */
void curl_memdebug(const char *logname) void curl_memdebug(const char *logname)
{ {
logfile = fopen(logname, "w"); if(logname)
logfile = fopen(logname, "w");
else
logfile = stderr;
} }
void *curl_domalloc(size_t size, int line, const char *source) void *curl_domalloc(size_t size, int line, const char *source)
{ {
void *mem=(malloc)(size); void *mem=(malloc)(size);
fprintf(logfile?logfile:stderr, "MEM %s:%d malloc(%d) = %p\n", if(logfile)
source, line, size, mem); fprintf(logfile, "MEM %s:%d malloc(%d) = %p\n",
source, line, size, mem);
return mem; return mem;
} }
@@ -85,16 +89,18 @@ char *curl_dostrdup(const char *str, int line, const char *source)
mem=(strdup)(str); mem=(strdup)(str);
len=strlen(str)+1; len=strlen(str)+1;
fprintf(logfile?logfile:stderr, "MEM %s:%d strdup(%p) (%d) = %p\n", if(logfile)
source, line, str, len, mem); fprintf(logfile, "MEM %s:%d strdup(%p) (%d) = %p\n",
source, line, str, len, mem);
return mem; return mem;
} }
void *curl_dorealloc(void *ptr, size_t size, int line, const char *source) void *curl_dorealloc(void *ptr, size_t size, int line, const char *source)
{ {
void *mem=(realloc)(ptr, size); void *mem=(realloc)(ptr, size);
fprintf(logfile?logfile:stderr, "MEM %s:%d realloc(%p, %d) = %p\n", if(logfile)
source, line, ptr, size, mem); fprintf(logfile, "MEM %s:%d realloc(%p, %d) = %p\n",
source, line, ptr, size, mem);
return mem; return mem;
} }
@@ -108,15 +114,16 @@ void curl_dofree(void *ptr, int line, const char *source)
(free)(ptr); (free)(ptr);
fprintf(logfile?logfile:stderr, "MEM %s:%d free(%p)\n", if(logfile)
source, line, ptr); fprintf(logfile, "MEM %s:%d free(%p)\n", source, line, ptr);
} }
int curl_socket(int domain, int type, int protocol, int line, char *source) int curl_socket(int domain, int type, int protocol, int line, char *source)
{ {
int sockfd=(socket)(domain, type, protocol); int sockfd=(socket)(domain, type, protocol);
fprintf(logfile?logfile:stderr, "FD %s:%d socket() = %d\n", if(logfile)
source, line, sockfd); fprintf(logfile, "FD %s:%d socket() = %d\n",
source, line, sockfd);
return sockfd; return sockfd;
} }
@@ -124,8 +131,9 @@ int curl_accept(int s, struct sockaddr *addr, socklen_t *addrlen,
int line, const char *source) int line, const char *source)
{ {
int sockfd=(accept)(s, addr, addrlen); int sockfd=(accept)(s, addr, addrlen);
fprintf(logfile?logfile:stderr, "FD %s:%d accept() = %d\n", if(logfile)
source, line, sockfd); fprintf(logfile, "FD %s:%d accept() = %d\n",
source, line, sockfd);
return sockfd; return sockfd;
} }
@@ -133,8 +141,9 @@ int curl_accept(int s, struct sockaddr *addr, socklen_t *addrlen,
int curl_sclose(int sockfd, int line, char *source) int curl_sclose(int sockfd, int line, char *source)
{ {
int res=sclose(sockfd); int res=sclose(sockfd);
fprintf(logfile?logfile:stderr, "FD %s:%d sclose(%d)\n", if(logfile)
source, line, sockfd); fprintf(logfile, "FD %s:%d sclose(%d)\n",
source, line, sockfd);
return res; return res;
} }
@@ -142,17 +151,27 @@ FILE *curl_fopen(const char *file, const char *mode,
int line, const char *source) int line, const char *source)
{ {
FILE *res=(fopen)(file, mode); FILE *res=(fopen)(file, mode);
fprintf(logfile?logfile:stderr, "FILE %s:%d fopen(\"%s\") = %p\n", if(logfile)
source, line, file, res); fprintf(logfile, "FILE %s:%d fopen(\"%s\") = %p\n",
source, line, file, res);
return res; return res;
} }
int curl_fclose(FILE *file, int line, const char *source) int curl_fclose(FILE *file, int line, const char *source)
{ {
int res=(fclose)(file); int res=(fclose)(file);
fprintf(logfile?logfile:stderr, "FILE %s:%d fclose(%p)\n", if(logfile)
source, line, file); fprintf(logfile, "FILE %s:%d fclose(%p)\n",
source, line, file);
return res; return res;
} }
#endif /* MALLOCDEBUG */ #endif /* MALLOCDEBUG */
/*
* local variables:
* eval: (load-file "../curl-mode.el")
* end:
* vim600: fdm=marker
* vim: et sw=2 ts=2 sts=2 tw=78
*/

View File

@@ -6,6 +6,8 @@
#include <memory.h> #include <memory.h>
#endif #endif
extern FILE *logfile;
/* memory functions */ /* memory functions */
void *curl_domalloc(size_t size, int line, const char *source); void *curl_domalloc(size_t size, int line, const char *source);
void *curl_dorealloc(void *ptr, size_t size, int line, const char *source); void *curl_dorealloc(void *ptr, size_t size, int line, const char *source);
@@ -35,6 +37,11 @@ int curl_fclose(FILE *file, int line, const char *source);
#define accept(sock,addr,len)\ #define accept(sock,addr,len)\
curl_accept(sock,addr,len,__LINE__,__FILE__) curl_accept(sock,addr,len,__LINE__,__FILE__)
#define getaddrinfo(host,serv,hint,res) \
curl_getaddrinfo(host,serv,hint,res,__LINE__,__FILE__)
#define freeaddrinfo(data) \
curl_freeaddrinfo(data,__LINE__,__FILE__)
/* sclose is probably already defined, redefine it! */ /* sclose is probably already defined, redefine it! */
#undef sclose #undef sclose
#define sclose(sockfd) curl_sclose(sockfd,__LINE__,__FILE__) #define sclose(sockfd) curl_sclose(sockfd,__LINE__,__FILE__)

View File

@@ -1151,7 +1151,9 @@ int curl_msprintf(char *buffer, const char *format, ...)
return retcode; return retcode;
} }
#ifndef WIN32 /* not needed on win32 */
extern int fputc(int, FILE *); extern int fputc(int, FILE *);
#endif
int curl_mprintf(const char *format, ...) int curl_mprintf(const char *format, ...)
{ {
@@ -1230,3 +1232,11 @@ int main()
} }
#endif #endif
/*
* local variables:
* eval: (load-file "../curl-mode.el")
* end:
* vim600: fdm=marker
* vim: et sw=2 ts=2 sts=2 tw=78
*/

View File

@@ -201,3 +201,11 @@ int main(int argc, char **argv)
} }
#endif #endif
/*
* local variables:
* eval: (load-file "../curl-mode.el")
* end:
* vim600: fdm=marker
* vim: et sw=2 ts=2 sts=2 tw=78
*/

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.
@@ -70,7 +70,7 @@ static char *max5data(double bytes, char *max5)
} }
if(bytes < (100*ONE_MEGABYTE)) { if(bytes < (100*ONE_MEGABYTE)) {
/* 'XX.XM' is good as long as we're less than 100 megs */ /* 'XX.XM' is good as long as we're less than 100 megs */
sprintf(max5, "%2.1fM", bytes/ONE_MEGABYTE); sprintf(max5, "%4.1fM", bytes/ONE_MEGABYTE);
return max5; return max5;
} }
sprintf(max5, "%4dM", (int)bytes/ONE_MEGABYTE); sprintf(max5, "%4dM", (int)bytes/ONE_MEGABYTE);
@@ -93,17 +93,17 @@ static char *max5data(double bytes, char *max5)
void Curl_pgrsDone(struct connectdata *conn) void Curl_pgrsDone(struct connectdata *conn)
{ {
struct UrlData *data = conn->data; struct SessionHandle *data = conn->data;
if(!(data->progress.flags & PGRS_HIDE)) { if(!(data->progress.flags & PGRS_HIDE)) {
data->progress.lastshow=0; data->progress.lastshow=0;
Curl_pgrsUpdate(conn); /* the final (forced) update */ Curl_pgrsUpdate(conn); /* the final (forced) update */
if(!data->progress.callback) if(!data->progress.callback)
/* only output if we don't use progress callback */ /* only output if we don't use progress callback */
fprintf(data->err, "\n"); fprintf(data->set.err, "\n");
} }
} }
void Curl_pgrsTime(struct UrlData *data, timerid timer) void Curl_pgrsTime(struct SessionHandle *data, timerid timer)
{ {
switch(timer) { switch(timer) {
default: default:
@@ -118,16 +118,16 @@ void Curl_pgrsTime(struct UrlData *data, timerid timer)
break; break;
case TIMER_NAMELOOKUP: case TIMER_NAMELOOKUP:
data->progress.t_nslookup += Curl_tvdiff(Curl_tvnow(), data->progress.t_nslookup +=
data->progress.t_startsingle); (double)Curl_tvdiff(Curl_tvnow(), data->progress.t_startsingle)/1000;
break; break;
case TIMER_CONNECT: case TIMER_CONNECT:
data->progress.t_connect += Curl_tvdiff(Curl_tvnow(), data->progress.t_connect +=
data->progress.t_startsingle); (double)Curl_tvdiff(Curl_tvnow(), data->progress.t_startsingle)/1000;
break; break;
case TIMER_PRETRANSFER: case TIMER_PRETRANSFER:
data->progress.t_pretransfer += Curl_tvdiff(Curl_tvnow(), data->progress.t_pretransfer +=
data->progress.t_startsingle); (double)Curl_tvdiff(Curl_tvnow(), data->progress.t_startsingle)/1000;
break; break;
case TIMER_POSTRANSFER: case TIMER_POSTRANSFER:
/* this is the normal end-of-transfer thing */ /* this is the normal end-of-transfer thing */
@@ -135,23 +135,23 @@ void Curl_pgrsTime(struct UrlData *data, timerid timer)
} }
} }
void Curl_pgrsStartNow(struct UrlData *data) void Curl_pgrsStartNow(struct SessionHandle *data)
{ {
data->progress.speeder_c = 0; /* reset the progress meter display */ data->progress.speeder_c = 0; /* reset the progress meter display */
data->progress.start = Curl_tvnow(); data->progress.start = Curl_tvnow();
} }
void Curl_pgrsSetDownloadCounter(struct UrlData *data, double size) void Curl_pgrsSetDownloadCounter(struct SessionHandle *data, double size)
{ {
data->progress.downloaded = size; data->progress.downloaded = size;
} }
void Curl_pgrsSetUploadCounter(struct UrlData *data, double size) void Curl_pgrsSetUploadCounter(struct SessionHandle *data, double size)
{ {
data->progress.uploaded = size; data->progress.uploaded = size;
} }
void Curl_pgrsSetDownloadSize(struct UrlData *data, double size) void Curl_pgrsSetDownloadSize(struct SessionHandle *data, double size)
{ {
if(size > 0) { if(size > 0) {
data->progress.size_dl = size; data->progress.size_dl = size;
@@ -159,7 +159,7 @@ void Curl_pgrsSetDownloadSize(struct UrlData *data, double size)
} }
} }
void Curl_pgrsSetUploadSize(struct UrlData *data, double size) void Curl_pgrsSetUploadSize(struct SessionHandle *data, double size)
{ {
if(size > 0) { if(size > 0) {
data->progress.size_ul = size; data->progress.size_ul = size;
@@ -187,12 +187,14 @@ int Curl_pgrsUpdate(struct connectdata *conn)
double total_transfer; double total_transfer;
double total_expected_transfer; double total_expected_transfer;
double timespent;
struct UrlData *data = conn->data; struct SessionHandle *data = conn->data;
int nowindex = data->progress.speeder_c% CURR_TIME; int nowindex = data->progress.speeder_c% CURR_TIME;
int checkindex; int checkindex;
int count;
int countindex; /* amount of seconds stored in the speeder array */
char time_left[10]; char time_left[10];
char time_total[10]; char time_total[10];
@@ -211,9 +213,9 @@ int Curl_pgrsUpdate(struct connectdata *conn)
else if(!(data->progress.flags & PGRS_HEADERS_OUT)) { else if(!(data->progress.flags & PGRS_HEADERS_OUT)) {
if (!data->progress.callback) { if (!data->progress.callback) {
if(conn->resume_from) if(conn->resume_from)
fprintf(data->err, "** Resuming transfer from byte position %d\n", fprintf(data->set.err, "** Resuming transfer from byte position %d\n",
conn->resume_from); conn->resume_from);
fprintf(data->err, fprintf(data->set.err,
" %% Total %% Received %% Xferd Average Speed Time Curr.\n" " %% Total %% Received %% Xferd Average Speed Time Curr.\n"
" Dload Upload Total Current Left Speed\n"); " Dload Upload Total Current Left Speed\n");
} }
@@ -222,14 +224,18 @@ int Curl_pgrsUpdate(struct connectdata *conn)
now = Curl_tvnow(); /* what time is it */ now = Curl_tvnow(); /* what time is it */
/* The exact time spent so far */ /* The exact time spent so far (from the start) */
data->progress.timespent = Curl_tvdiff (now, data->progress.start); timespent = (double)Curl_tvdiff (now, data->progress.start)/1000;
data->progress.timespent = (long)timespent;
/* The average download speed this far */ /* The average download speed this far */
data->progress.dlspeed = data->progress.downloaded/(data->progress.timespent!=0.0?data->progress.timespent:1.0); data->progress.dlspeed =
data->progress.downloaded/(timespent>0.01?timespent:1);
/* The average upload speed this far */ /* The average upload speed this far */
data->progress.ulspeed = data->progress.uploaded/(data->progress.timespent!=0.0?data->progress.timespent:1.0); data->progress.ulspeed =
data->progress.uploaded/(timespent>0.01?timespent:1);
if(data->progress.lastshow == Curl_tvlong(now)) if(data->progress.lastshow == Curl_tvlong(now))
return 0; /* never update this more than once a second if the end isn't return 0; /* never update this more than once a second if the end isn't
@@ -237,35 +243,67 @@ int Curl_pgrsUpdate(struct connectdata *conn)
data->progress.lastshow = now.tv_sec; data->progress.lastshow = now.tv_sec;
/* Let's do the "current speed" thing, which should use the fastest /* Let's do the "current speed" thing, which should use the fastest
of the dl/ul speeds */ of the dl/ul speeds. Store the fasted speed at entry 'nowindex'. */
data->progress.speeder[ nowindex ] = data->progress.speeder[ nowindex ] =
data->progress.downloaded>data->progress.uploaded? data->progress.downloaded>data->progress.uploaded?
data->progress.downloaded:data->progress.uploaded; data->progress.downloaded:data->progress.uploaded;
data->progress.speeder_c++; /* increase */
count = ((data->progress.speeder_c>=CURR_TIME)?
CURR_TIME:data->progress.speeder_c) - 1;
checkindex = (data->progress.speeder_c>=CURR_TIME)?
data->progress.speeder_c%CURR_TIME:0;
/* find out the average speed the last CURR_TIME seconds */ /* remember the exact time for this moment */
data->progress.current_speed = data->progress.speeder_time [ nowindex ] = now;
(data->progress.speeder[nowindex]-
data->progress.speeder[checkindex])/(count?count:1); /* advance our speeder_c counter, which is increased every time we get
here and we expect it to never wrap as 2^32 is a lot of seconds! */
data->progress.speeder_c++;
/* figure out how many index entries of data we have stored in our speeder
array. With N_ENTRIES filled in, we have about N_ENTRIES-1 seconds of
transfer. Imagine, after one second we have filled in two entries,
after two seconds we've filled in three entries etc. */
countindex = ((data->progress.speeder_c>=CURR_TIME)?
CURR_TIME:data->progress.speeder_c) - 1;
/* first of all, we don't do this if there's no counted seconds yet */
if(countindex) {
long span_ms;
/* Get the index position to compare with the 'nowindex' position.
Get the oldest entry possible. While we have less than CURR_TIME
entries, the first entry will remain the oldest. */
checkindex = (data->progress.speeder_c>=CURR_TIME)?
data->progress.speeder_c%CURR_TIME:0;
/* Figure out the exact time for the time span */
span_ms = Curl_tvdiff(now,
data->progress.speeder_time[checkindex]);
/* Calculate the average speed the last 'countindex' seconds */
data->progress.current_speed =
(data->progress.speeder[nowindex]-
data->progress.speeder[checkindex])/((double)span_ms/1000);
}
else
/* the first second we use the main average */
data->progress.current_speed =
(data->progress.ulspeed>data->progress.dlspeed)?
data->progress.ulspeed:data->progress.dlspeed;
if(data->progress.flags & PGRS_HIDE) if(data->progress.flags & PGRS_HIDE)
return 0; return 0;
else if(data->fprogress) {
result= data->fprogress(data->progress_client, else if(data->set.fprogress) {
data->progress.size_dl, /* There's a callback set, so we call that instead of writing
data->progress.downloaded, anything ourselves. This really is the way to go. */
data->progress.size_ul, result= data->set.fprogress(data->set.progress_client,
data->progress.uploaded); data->progress.size_dl,
data->progress.downloaded,
data->progress.size_ul,
data->progress.uploaded);
if(result) if(result)
failf(data, "Callback aborted"); failf(data, "Callback aborted");
return result; return result;
} }
/* Figure out the estimated time of arrival for the upload */ /* Figure out the estimated time of arrival for the upload */
if((data->progress.flags & PGRS_UL_SIZE_KNOWN) && data->progress.ulspeed){ if((data->progress.flags & PGRS_UL_SIZE_KNOWN) && data->progress.ulspeed){
ulestimate = data->progress.size_ul / data->progress.ulspeed; ulestimate = data->progress.size_ul / data->progress.ulspeed;
ulpercen = (data->progress.uploaded / data->progress.size_ul)*100; ulpercen = (data->progress.uploaded / data->progress.size_ul)*100;
@@ -278,12 +316,12 @@ int Curl_pgrsUpdate(struct connectdata *conn)
} }
/* Now figure out which of them that is slower and use for the for /* Now figure out which of them that is slower and use for the for
total estimate! */ total estimate! */
total_estimate = ulestimate>dlestimate?ulestimate:dlestimate; total_estimate = ulestimate>dlestimate?ulestimate:dlestimate;
/* If we have a total estimate, we can display that and the expected /* If we have a total estimate, we can display that and the expected
time left */ time left */
if(total_estimate) { if(total_estimate) {
time2str(time_left, total_estimate-(int) data->progress.timespent); time2str(time_left, total_estimate-(int) data->progress.timespent);
time2str(time_total, total_estimate); time2str(time_total, total_estimate);
@@ -310,7 +348,7 @@ int Curl_pgrsUpdate(struct connectdata *conn)
if(total_expected_transfer) if(total_expected_transfer)
total_percen=(double)(total_transfer/total_expected_transfer)*100; total_percen=(double)(total_transfer/total_expected_transfer)*100;
fprintf(data->err, fprintf(data->set.err,
"\r%3d %s %3d %s %3d %s %s %s %s %s %s %s", "\r%3d %s %3d %s %3d %s %s %s %s %s %s %s",
(int)total_percen, /* total % */ (int)total_percen, /* total % */
max5data(total_expected_transfer, max5[2]), /* total size */ max5data(total_expected_transfer, max5[2]), /* total size */
@@ -327,5 +365,16 @@ int Curl_pgrsUpdate(struct connectdata *conn)
max5data(data->progress.current_speed, max5[5]) /* current speed */ max5data(data->progress.current_speed, max5[5]) /* current speed */
); );
/* we flush the output stream to make it appear as soon as possible */
fflush(data->set.err);
return 0; return 0;
} }
/*
* local variables:
* eval: (load-file "../curl-mode.el")
* end:
* vim600: fdm=marker
* vim: et sw=2 ts=2 sts=2 tw=78
*/

View File

@@ -37,13 +37,13 @@ typedef enum {
} timerid; } timerid;
void Curl_pgrsDone(struct connectdata *); void Curl_pgrsDone(struct connectdata *);
void Curl_pgrsStartNow(struct UrlData *data); void Curl_pgrsStartNow(struct SessionHandle *data);
void Curl_pgrsSetDownloadSize(struct UrlData *data, double size); void Curl_pgrsSetDownloadSize(struct SessionHandle *data, double size);
void Curl_pgrsSetUploadSize(struct UrlData *data, double size); void Curl_pgrsSetUploadSize(struct SessionHandle *data, double size);
void Curl_pgrsSetDownloadCounter(struct UrlData *data, double size); void Curl_pgrsSetDownloadCounter(struct SessionHandle *data, double size);
void Curl_pgrsSetUploadCounter(struct UrlData *data, double size); void Curl_pgrsSetUploadCounter(struct SessionHandle *data, double size);
int Curl_pgrsUpdate(struct connectdata *); int Curl_pgrsUpdate(struct connectdata *);
void Curl_pgrsTime(struct UrlData *data, timerid timer); void Curl_pgrsTime(struct SessionHandle *data, timerid timer);
/* Don't show progress for sizes smaller than: */ /* Don't show progress for sizes smaller than: */

View File

@@ -413,33 +413,34 @@ sec_prot_internal(struct connectdata *conn, int level)
} }
if(level){ if(level){
Curl_ftpsendf(conn->firstsocket, conn, if(Curl_ftpsendf(conn, "PBSZ %u", s))
"PBSZ %u", s); return -1;
/* wait for feedback */
nread = Curl_GetFTPResponse(conn->firstsocket, nread = Curl_GetFTPResponse(conn->data->state.buffer, conn, NULL);
conn->data->buffer, conn, NULL);
if(nread < 0) if(nread < 0)
return /*CURLE_OPERATION_TIMEOUTED*/-1; return -1;
if(/*ret != COMPLETE*/conn->data->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.\n");
return -1; return -1;
} }
conn->buffer_size = s; conn->buffer_size = s;
p = strstr(/*reply_string*/conn->data->buffer, "PBSZ=");
p = strstr(conn->data->state.buffer, "PBSZ=");
if(p) if(p)
sscanf(p, "PBSZ=%u", &s); sscanf(p, "PBSZ=%u", &s);
if(s < conn->buffer_size) if(s < conn->buffer_size)
conn->buffer_size = s; conn->buffer_size = s;
} }
Curl_ftpsendf(conn->firstsocket, conn, if(Curl_ftpsendf(conn, "PROT %c", level["CSEP"]))
"PROT %c", level["CSEP"]); return -1;
/* wait for feedback */
nread = Curl_GetFTPResponse(conn->firstsocket, nread = Curl_GetFTPResponse(conn->data->state.buffer, conn, NULL);
conn->data->buffer, conn, NULL);
if(nread < 0) if(nread < 0)
return /*CURLE_OPERATION_TIMEOUTED*/-1; return -1;
if(/*ret != COMPLETE*/conn->data->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.\n");
return -1; return -1;
} }
@@ -472,7 +473,8 @@ Curl_sec_login(struct connectdata *conn)
int ret; int ret;
struct Curl_sec_client_mech **m; struct Curl_sec_client_mech **m;
ssize_t nread; ssize_t nread;
struct UrlData *data=conn->data; struct SessionHandle *data=conn->data;
int ftpcode;
for(m = mechs; *m && (*m)->name; m++) { for(m = mechs; *m && (*m)->name; m++) {
void *tmp; void *tmp;
@@ -489,31 +491,35 @@ Curl_sec_login(struct connectdata *conn)
continue; continue;
} }
infof(data, "Trying %s...\n", (*m)->name); infof(data, "Trying %s...\n", (*m)->name);
/*ret = command("AUTH %s", (*m)->name);***/
Curl_ftpsendf(conn->firstsocket, conn, if(Curl_ftpsendf(conn, "AUTH %s", (*m)->name))
"AUTH %s", (*m)->name); return -1;
/* wait for feedback */
nread = Curl_GetFTPResponse(conn->firstsocket, nread = Curl_GetFTPResponse(conn->data->state.buffer, conn, &ftpcode);
conn->data->buffer, conn, NULL);
if(nread < 0) if(nread < 0)
return /*CURLE_OPERATION_TIMEOUTED*/-1; return -1;
if(/*ret != CONTINUE*/conn->data->buffer[0] != '3'){
if(/*code == 504*/strncmp(conn->data->buffer,"504",3) == 0) { if(conn->data->state.buffer[0] != '3'){
switch(ftpcode) {
case 504:
infof(data, infof(data,
"%s is not supported by the server.\n", (*m)->name); "%s is not supported by the server.\n", (*m)->name);
} break;
else if(/*code == 534*/strncmp(conn->data->buffer,"534",3) == 0) { case 534:
infof(data, "%s rejected as security mechanism.\n", (*m)->name); infof(data, "%s rejected as security mechanism.\n", (*m)->name);
} break;
else if(/*ret == ERROR*/conn->data->buffer[0] == '5') { default:
infof(data, "The server doesn't support the FTP " if(conn->data->state.buffer[0] == '5') {
"security extensions.\n"); infof(data, "The server doesn't support the FTP "
return -1; "security extensions.\n");
return -1;
}
break;
} }
continue; continue;
} }
ret = (*(*m)->auth)(conn->app_data, /*host***/conn); ret = (*(*m)->auth)(conn->app_data, conn);
if(ret == AUTH_CONTINUE) if(ret == AUTH_CONTINUE)
continue; continue;
@@ -546,3 +552,11 @@ Curl_sec_end(struct connectdata *conn)
} }
#endif /* KRB4 */ #endif /* KRB4 */
/*
* local variables:
* eval: (load-file "../curl-mode.el")
* end:
* vim600: fdm=marker
* vim: et sw=2 ts=2 sts=2 tw=78
*/

View File

@@ -122,13 +122,13 @@ void curl_slist_free_all(struct curl_slist *list)
/* Curl_infof() is for info message along the way */ /* Curl_infof() is for info message along the way */
void Curl_infof(struct UrlData *data, const char *fmt, ...) void Curl_infof(struct SessionHandle *data, const char *fmt, ...)
{ {
va_list ap; va_list ap;
if(data->bits.verbose) { if(data->set.verbose) {
va_start(ap, fmt); va_start(ap, fmt);
fputs("* ", data->err); fputs("* ", data->set.err);
vfprintf(data->err, fmt, ap); vfprintf(data->set.err, fmt, ap);
va_end(ap); va_end(ap);
} }
} }
@@ -136,21 +136,24 @@ void Curl_infof(struct UrlData *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, the LAST one will be
returned for the user (if requested) */ returned for the user (if requested) */
void Curl_failf(struct UrlData *data, const char *fmt, ...) void Curl_failf(struct SessionHandle *data, const char *fmt, ...)
{ {
va_list ap; va_list ap;
va_start(ap, fmt); va_start(ap, fmt);
if(data->errorbuffer) if(data->set.errorbuffer && !data->state.errorbuf) {
vsnprintf(data->errorbuffer, CURL_ERROR_SIZE, fmt, ap); vsnprintf(data->set.errorbuffer, CURL_ERROR_SIZE, fmt, ap);
data->state.errorbuf = TRUE; /* wrote error string */
}
va_end(ap); va_end(ap);
} }
/* Curl_sendf() sends formated data to the server */ /* Curl_sendf() sends formated data to the server */
size_t Curl_sendf(int sockfd, struct connectdata *conn, CURLcode Curl_sendf(int sockfd, struct connectdata *conn,
const char *fmt, ...) const char *fmt, ...)
{ {
struct UrlData *data = conn->data; struct SessionHandle *data = conn->data;
size_t bytes_written; size_t bytes_written;
CURLcode result;
char *s; char *s;
va_list ap; va_list ap;
va_start(ap, fmt); va_start(ap, fmt);
@@ -158,15 +161,15 @@ size_t Curl_sendf(int sockfd, struct connectdata *conn,
va_end(ap); va_end(ap);
if(!s) if(!s)
return 0; /* failure */ return 0; /* failure */
if(data->bits.verbose) if(data->set.verbose)
fprintf(data->err, "> %s", s); fprintf(data->set.err, "> %s", s);
/* Write the buffer to the socket */ /* Write the buffer to the socket */
Curl_write(conn, sockfd, s, strlen(s), &bytes_written); result = Curl_write(conn, sockfd, s, strlen(s), &bytes_written);
free(s); /* free the output string */ free(s); /* free the output string */
return bytes_written; return result;
} }
/* /*
@@ -211,7 +214,7 @@ CURLcode Curl_write(struct connectdata *conn, int sockfd,
#endif #endif
*written = bytes_written; *written = bytes_written;
return CURLE_OK; return (bytes_written==len)?CURLE_OK:CURLE_WRITE_ERROR;
} }
/* client_write() sends data to the write callback(s) /* client_write() sends data to the write callback(s)
@@ -219,7 +222,7 @@ CURLcode Curl_write(struct connectdata *conn, int sockfd,
The bit pattern defines to what "streams" to write to. Body and/or header. The bit pattern defines to what "streams" to write to. Body and/or header.
The defines are in sendf.h of course. The defines are in sendf.h of course.
*/ */
CURLcode Curl_client_write(struct UrlData *data, CURLcode Curl_client_write(struct SessionHandle *data,
int type, int type,
char *ptr, char *ptr,
size_t len) size_t len)
@@ -230,22 +233,22 @@ CURLcode Curl_client_write(struct UrlData *data,
len = strlen(ptr); len = strlen(ptr);
if(type & CLIENTWRITE_BODY) { if(type & CLIENTWRITE_BODY) {
wrote = data->fwrite(ptr, 1, len, data->out); wrote = data->set.fwrite(ptr, 1, len, data->set.out);
if(wrote != len) { if(wrote != len) {
failf (data, "Failed writing body"); failf (data, "Failed writing body");
return CURLE_WRITE_ERROR; return CURLE_WRITE_ERROR;
} }
} }
if((type & CLIENTWRITE_HEADER) && if((type & CLIENTWRITE_HEADER) &&
(data->fwrite_header || data->writeheader) ) { (data->set.fwrite_header || data->set.writeheader) ) {
/* /*
* Write headers to the same callback or to the especially setup * Write headers to the same callback or to the especially setup
* header callback function (added after version 7.7.1). * header callback function (added after version 7.7.1).
*/ */
curl_write_callback writeit= curl_write_callback writeit=
data->fwrite_header?data->fwrite_header:data->fwrite; data->set.fwrite_header?data->set.fwrite_header:data->set.fwrite;
wrote = writeit(ptr, 1, len, data->writeheader); wrote = writeit(ptr, 1, len, data->set.writeheader);
if(wrote != len) { if(wrote != len) {
failf (data, "Failed writing header"); failf (data, "Failed writing header");
return CURLE_WRITE_ERROR; return CURLE_WRITE_ERROR;
@@ -291,3 +294,11 @@ CURLcode Curl_read(struct connectdata *conn, int sockfd,
return CURLE_OK; return CURLE_OK;
} }
/*
* local variables:
* eval: (load-file "../curl-mode.el")
* end:
* vim600: fdm=marker
* vim: et sw=2 ts=2 sts=2 tw=78
*/

View File

@@ -23,9 +23,9 @@
* $Id$ * $Id$
*****************************************************************************/ *****************************************************************************/
size_t Curl_sendf(int fd, struct connectdata *, const char *fmt, ...); CURLcode Curl_sendf(int fd, struct connectdata *, const char *fmt, ...);
void Curl_infof(struct UrlData *, const char *fmt, ...); void Curl_infof(struct SessionHandle *, const char *fmt, ...);
void Curl_failf(struct UrlData *, const char *fmt, ...); void Curl_failf(struct SessionHandle *, const char *fmt, ...);
#define infof Curl_infof #define infof Curl_infof
#define failf Curl_failf #define failf Curl_failf
@@ -41,7 +41,7 @@ typedef struct send_buffer send_buffer;
#define CLIENTWRITE_HEADER 2 #define CLIENTWRITE_HEADER 2
#define CLIENTWRITE_BOTH (CLIENTWRITE_BODY|CLIENTWRITE_HEADER) #define CLIENTWRITE_BOTH (CLIENTWRITE_BODY|CLIENTWRITE_HEADER)
CURLcode Curl_client_write(struct UrlData *data, int type, char *ptr, 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 */

View File

@@ -96,24 +96,6 @@ defined(HAVE_LIBSSL) && defined(HAVE_LIBCRYPTO)
#endif #endif
#endif #endif
#if 0 /* zlib experiments are halted 17th october, 1999 (Daniel) */
#if defined(HAVE_ZLIB_H) && defined(HAVE_LIBZ)
/* Both lib and header file exist, we have libz! */
#define USE_ZLIB
#endif
#endif
#if 0
#ifdef HAVE_STRCASECMP
#define strnequal(x,y,z) !(strncasecmp)(x,y,z)
#define strequal(x,y) !(strcasecmp)(x,y)
#else
#define strnequal(x,y,z) !strnicmp(x,y,z)
#define strequal(x,y) !stricmp(x,y)
#endif
#endif
/* Below we define four functions. They should /* Below we define four functions. They should
1. close a socket 1. close a socket
2. read from a socket 2. read from a socket
@@ -143,8 +125,8 @@ defined(HAVE_LIBSSL) && defined(HAVE_LIBCRYPTO)
#else #else
#define sclose(x) close(x) #define sclose(x) close(x)
#define sread(x,y,z) read(x,y,z) #define sread(x,y,z) recv(x,y,z,0)
#define swrite(x,y,z) write(x,y,z) #define swrite(x,y,z) send(x,y,z,0)
#define myalarm(x) alarm(x) #define myalarm(x) alarm(x)
#define PATH_CHAR ":" #define PATH_CHAR ":"
@@ -162,4 +144,19 @@ int fileno( FILE *stream);
#endif #endif
/*
* Curl_addrinfo MUST be used for name resolving information.
* Information regarding a single IP witin a Curl_addrinfo MUST be stored in
* a Curl_ipconnect struct.
*/
#ifdef ENABLE_IPV6
typedef struct addrinfo Curl_addrinfo;
typedef struct addrinfo Curl_ipconnect;
#else
typedef struct hostent Curl_addrinfo;
typedef struct in_addr Curl_ipconnect;
#endif
#endif /* __CONFIG_H */ #endif /* __CONFIG_H */

View File

@@ -34,37 +34,45 @@
#include "sendf.h" #include "sendf.h"
#include "speedcheck.h" #include "speedcheck.h"
void Curl_speedinit(struct UrlData *data) void Curl_speedinit(struct SessionHandle *data)
{ {
memset(&data->keeps_speed, 0, sizeof(struct timeval)); memset(&data->state.keeps_speed, 0, sizeof(struct timeval));
} }
CURLcode Curl_speedcheck(struct UrlData *data, CURLcode Curl_speedcheck(struct SessionHandle *data,
struct timeval now) struct timeval now)
{ {
if((data->progress.current_speed >= 0) && if((data->progress.current_speed >= 0) &&
data->low_speed_time && data->set.low_speed_time &&
(Curl_tvlong(data->keeps_speed) != 0) && (Curl_tvlong(data->state.keeps_speed) != 0) &&
(data->progress.current_speed < data->low_speed_limit)) { (data->progress.current_speed < data->set.low_speed_limit)) {
/* We are now below the "low speed limit". If we are below it /* We are now below the "low speed limit". If we are below it
for "low speed time" seconds we consider that enough reason for "low speed time" seconds we consider that enough reason
to abort the download. */ to abort the download. */
if( Curl_tvdiff(now, data->keeps_speed) > data->low_speed_time) { if( (Curl_tvdiff(now, data->state.keeps_speed)/1000) >
data->set.low_speed_time) {
/* we have been this slow for long enough, now die */ /* we have been this slow for long enough, now die */
failf(data, failf(data,
"Operation too slow. " "Operation too slow. "
"Less than %d bytes/sec transfered the last %d seconds", "Less than %d bytes/sec transfered the last %d seconds",
data->low_speed_limit, data->set.low_speed_limit,
data->low_speed_time); data->set.low_speed_time);
return CURLE_OPERATION_TIMEOUTED; return CURLE_OPERATION_TIMEOUTED;
} }
} }
else { else {
/* we keep up the required speed all right */ /* we keep up the required speed all right */
data->keeps_speed = now; data->state.keeps_speed = now;
} }
return CURLE_OK; return CURLE_OK;
} }
/*
* local variables:
* eval: (load-file "../curl-mode.el")
* end:
* vim600: fdm=marker
* vim: et sw=2 ts=2 sts=2 tw=78
*/

View File

@@ -27,8 +27,8 @@
#include "timeval.h" #include "timeval.h"
void Curl_speedinit(struct UrlData *data); void Curl_speedinit(struct SessionHandle *data);
CURLcode Curl_speedcheck(struct UrlData *data, CURLcode Curl_speedcheck(struct SessionHandle *data,
struct timeval now); struct timeval now);
#endif #endif

View File

@@ -94,9 +94,9 @@ bool seed_enough(struct connectdata *conn, /* unused for now */
static static
int random_the_seed(struct connectdata *conn) int random_the_seed(struct connectdata *conn)
{ {
char *buf = conn->data->buffer; /* point to the big buffer */ char *buf = conn->data->state.buffer; /* point to the big buffer */
int nread=0; int nread=0;
struct UrlData *data=conn->data; struct SessionHandle *data=conn->data;
/* Q: should we add support for a random file name as a libcurl option? /* Q: should we add support for a random file name as a libcurl option?
A: Yes, it is here */ A: Yes, it is here */
@@ -104,13 +104,13 @@ int random_the_seed(struct connectdata *conn)
#ifndef RANDOM_FILE #ifndef RANDOM_FILE
/* if RANDOM_FILE isn't defined, we only perform this if an option tells /* if RANDOM_FILE isn't defined, we only perform this if an option tells
us to! */ us to! */
if(data->ssl.random_file) if(data->set.ssl.random_file)
#define RANDOM_FILE "" /* doesn't matter won't be used */ #define RANDOM_FILE "" /* doesn't matter won't be used */
#endif #endif
{ {
/* let the option override the define */ /* let the option override the define */
nread += RAND_load_file((data->ssl.random_file? nread += RAND_load_file((data->set.ssl.random_file?
data->ssl.random_file:RANDOM_FILE), data->set.ssl.random_file:RANDOM_FILE),
16384); 16384);
if(seed_enough(conn, nread)) if(seed_enough(conn, nread))
return nread; return nread;
@@ -122,13 +122,13 @@ int random_the_seed(struct connectdata *conn)
#ifndef EGD_SOCKET #ifndef EGD_SOCKET
/* If we don't have the define set, we only do this if the egd-option /* If we don't have the define set, we only do this if the egd-option
is set */ is set */
if(data->ssl.egdsocket) if(data->set.ssl.egdsocket)
#define EGD_SOCKET "" /* doesn't matter won't be used */ #define EGD_SOCKET "" /* doesn't matter won't be used */
#endif #endif
{ {
/* If there's an option and a define, the option overrides the /* If there's an option and a define, the option overrides the
define */ define */
int ret = RAND_egd(data->ssl.egdsocket?data->ssl.egdsocket:EGD_SOCKET); int ret = RAND_egd(data->set.ssl.egdsocket?data->set.ssl.egdsocket:EGD_SOCKET);
if(-1 != ret) { if(-1 != ret) {
nread += ret; nread += ret;
if(seed_enough(conn, nread)) if(seed_enough(conn, nread))
@@ -176,23 +176,23 @@ int cert_stuff(struct connectdata *conn,
char *cert_file, char *cert_file,
char *key_file) char *key_file)
{ {
struct UrlData *data = conn->data; struct SessionHandle *data = conn->data;
if (cert_file != NULL) { if (cert_file != NULL) {
SSL *ssl; SSL *ssl;
X509 *x509; X509 *x509;
if(data->cert_passwd) { if(data->set.cert_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->cert_passwd); strcpy(global_passwd, data->set.cert_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->cert_passwd); SSL_CTX_set_default_passwd_cb_userdata(conn->ssl.ctx, data->set.cert_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);
@@ -200,7 +200,7 @@ int cert_stuff(struct connectdata *conn,
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) <= 0) { SSL_FILETYPE_PEM) != 1) {
failf(data, "unable to set certificate file (wrong password?)\n"); failf(data, "unable to set certificate file (wrong password?)\n");
return(0); return(0);
} }
@@ -209,7 +209,7 @@ 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) <= 0) { SSL_FILETYPE_PEM) != 1) {
failf(data, "unable to set public key file\n"); failf(data, "unable to set public key file\n");
return(0); return(0);
} }
@@ -263,7 +263,6 @@ static int init_ssl=0;
void Curl_SSL_init(void) void Curl_SSL_init(void)
{ {
#ifdef USE_SSLEAY #ifdef USE_SSLEAY
/* make sure this is only done once */ /* make sure this is only done once */
if(0 != init_ssl) if(0 != init_ssl)
return; return;
@@ -275,6 +274,8 @@ void Curl_SSL_init(void)
/* Setup all the global SSL stuff */ /* Setup all the global SSL stuff */
SSLeay_add_ssl_algorithms(); SSLeay_add_ssl_algorithms();
#else
/* SSL disabled, do nothing */
#endif #endif
} }
@@ -292,9 +293,233 @@ void Curl_SSL_cleanup(void)
table. */ table. */
EVP_cleanup(); EVP_cleanup();
} }
#endif #else
/* SSL disabled, do nothing */
#endif
} }
#ifdef USE_SSLEAY
/*
* This function is called when an SSL connection is closed.
*/
void Curl_SSL_Close(struct connectdata *conn)
{
if (conn->ssl.use) {
/*
ERR_remove_state() frees the error queue associated with
thread pid. If pid == 0, the current thread will have its
error queue removed.
Since error queue data structures are allocated
automatically for new threads, they must be freed when
threads are terminated in oder to avoid memory leaks.
*/
ERR_remove_state(0);
if(conn->ssl.handle) {
(void)SSL_shutdown(conn->ssl.handle);
SSL_set_connect_state(conn->ssl.handle);
SSL_free (conn->ssl.handle);
conn->ssl.handle = NULL;
}
if(conn->ssl.ctx) {
SSL_CTX_free (conn->ssl.ctx);
conn->ssl.ctx = NULL;
}
conn->ssl.use = FALSE; /* get back to ordinary socket usage */
}
}
/*
* This sets up a session cache to the specified size.
*/
CURLcode Curl_SSL_InitSessions(struct SessionHandle *data, long amount)
{
struct curl_ssl_session *session;
if(data->state.session)
/* this is just a precaution to prevent multiple inits */
return CURLE_OK;
session = (struct curl_ssl_session *)
malloc(amount * sizeof(struct curl_ssl_session));
if(!session)
return CURLE_OUT_OF_MEMORY;
/* "blank out" the newly allocated memory */
memset(session, 0, amount * sizeof(struct curl_ssl_session));
/* store the info in the SSL section */
data->set.ssl.numsessions = amount;
data->state.session = session;
data->state.sessionage = 1; /* this is brand new */
return CURLE_OK;
}
/*
* Check if there's a session ID for the given connection in the cache,
* and if there's one suitable, it is returned.
*/
static int Get_SSL_Session(struct connectdata *conn,
SSL_SESSION **ssl_sessionid)
{
struct curl_ssl_session *check;
struct SessionHandle *data = conn->data;
long i;
for(i=0; i< data->set.ssl.numsessions; i++) {
check = &data->state.session[i];
if(!check->sessionid)
/* not session ID means blank entry */
continue;
if(strequal(conn->name, check->name) &&
(conn->remote_port == check->remote_port) ) {
/* yes, we have a session ID! */
data->state.sessionage++; /* increase general age */
check->age = data->state.sessionage; /* set this as used in this age */
*ssl_sessionid = check->sessionid;
return FALSE;
}
}
*ssl_sessionid = (SSL_SESSION *)NULL;
return TRUE;
}
/*
* Kill a single session ID entry in the cache.
*/
static int Kill_Single_Session(struct curl_ssl_session *session)
{
if(session->sessionid) {
/* defensive check */
/* free the ID */
SSL_SESSION_free(session->sessionid);
session->sessionid=NULL;
session->age = 0; /* fresh */
free(session->name);
session->name = NULL; /* no name */
return 0; /* ok */
}
else
return 1;
}
/*
* This function is called when the 'data' struct is going away. Close
* down everything and free all resources!
*/
int Curl_SSL_Close_All(struct SessionHandle *data)
{
int i;
if(data->state.session) {
for(i=0; i< data->set.ssl.numsessions; i++)
/* the single-killer function handles empty table slots */
Kill_Single_Session(&data->state.session[i]);
/* free the cache data */
free(data->state.session);
}
return 0;
}
/*
* Extract the session id and store it in the session cache.
*/
static int Store_SSL_Session(struct connectdata *conn)
{
SSL_SESSION *ssl_sessionid;
struct curl_ssl_session *store;
int i;
struct SessionHandle *data=conn->data; /* the mother of all structs */
int oldest_age=data->state.session[0].age; /* zero if unused */
/* ask OpenSSL, say please */
ssl_sessionid = SSL_get1_session(conn->ssl.handle);
/* SSL_get1_session() will increment the reference
count and the session will stay in memory until explicitly freed with
SSL_SESSION_free(3), regardless of its state. */
/* Now we should add the session ID and the host name to the cache, (remove
the oldest if necessary) */
/* find an empty slot for us, or find the oldest */
for(i=0; (i<data->set.ssl.numsessions) && data->state.session[i].sessionid; i++) {
if(data->state.session[i].age < oldest_age) {
oldest_age = data->state.session[i].age;
store = &data->state.session[i];
}
}
if(i == data->set.ssl.numsessions)
/* cache is full, we must "kill" the oldest entry! */
Kill_Single_Session(store);
else
store = &data->state.session[i]; /* use this slot */
/* now init the session struct wisely */
store->sessionid = ssl_sessionid;
store->age = data->state.sessionage; /* set current age */
store->name = strdup(conn->name); /* clone host name */
store->remote_port = conn->remote_port; /* port number */
return 0;
}
static int Curl_ASN1_UTCTIME_output(struct connectdata *conn,
const char *prefix,
ASN1_UTCTIME *tm)
{
char *asn1_string;
int gmt=FALSE;
int i;
int year=0,month=0,day=0,hour=0,minute=0,second=0;
struct SessionHandle *data = conn->data;
if(!data->set.verbose)
return 0;
i=tm->length;
asn1_string=(char *)tm->data;
if (i < 10)
return 1;
if (asn1_string[i-1] == 'Z')
gmt=TRUE;
for (i=0; i<10; i++)
if ((asn1_string[i] > '9') || (asn1_string[i] < '0'))
return 2;
year= (asn1_string[0]-'0')*10+(asn1_string[1]-'0');
if (year < 50)
year+=100;
month= (asn1_string[2]-'0')*10+(asn1_string[3]-'0');
if ((month > 12) || (month < 1))
return 3;
day= (asn1_string[4]-'0')*10+(asn1_string[5]-'0');
hour= (asn1_string[6]-'0')*10+(asn1_string[7]-'0');
minute= (asn1_string[8]-'0')*10+(asn1_string[9]-'0');
if ( (asn1_string[10] >= '0') && (asn1_string[10] <= '9') &&
(asn1_string[11] >= '0') && (asn1_string[11] <= '9'))
second= (asn1_string[10]-'0')*10+(asn1_string[11]-'0');
infof(data,
"%s%04d-%02d-%02d %02d:%02d:%02d %s\n",
prefix, year+1900, month, day, hour, minute, second, (gmt?"GMT":""));
return 0;
}
#endif
/* ====================================================== */ /* ====================================================== */
CURLcode CURLcode
@@ -303,10 +528,12 @@ Curl_SSLConnect(struct connectdata *conn)
CURLcode retcode = CURLE_OK; CURLcode retcode = CURLE_OK;
#ifdef USE_SSLEAY #ifdef USE_SSLEAY
struct UrlData *data = conn->data; struct SessionHandle *data = conn->data;
int err; int err;
char * str; char * str;
SSL_METHOD *req_method; SSL_METHOD *req_method;
SSL_SESSION *ssl_sessionid=NULL;
ASN1_TIME *certdate;
/* mark this is being ssl enabled from here on out. */ /* mark this is being ssl enabled from here on out. */
conn->ssl.use = TRUE; conn->ssl.use = TRUE;
@@ -314,7 +541,7 @@ Curl_SSLConnect(struct connectdata *conn)
/* Make funny stuff to get random input */ /* Make funny stuff to get random input */
random_the_seed(conn); random_the_seed(conn);
switch(data->ssl.version) { switch(data->set.ssl.version) {
default: default:
req_method = SSLv23_client_method(); req_method = SSLv23_client_method();
break; break;
@@ -333,21 +560,29 @@ Curl_SSLConnect(struct connectdata *conn)
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
} }
if(data->cert) { if(data->set.cert) {
if (!cert_stuff(conn, data->cert, data->cert)) { if (!cert_stuff(conn, data->set.cert, data->set.cert)) {
/* failf() is already done in cert_stuff() */ /* failf() is already done in cert_stuff() */
return CURLE_SSL_CONNECT_ERROR; return CURLE_SSL_CONNECT_ERROR;
} }
} }
if(data->ssl.verifypeer){ if(data->set.ssl.cipher_list) {
if (!SSL_CTX_set_cipher_list(conn->ssl.ctx,
data->set.ssl.cipher_list)) {
failf(data, "failed setting cipher list\n");
return CURLE_SSL_CONNECT_ERROR;
}
}
if(data->set.ssl.verifypeer){
SSL_CTX_set_verify(conn->ssl.ctx, SSL_CTX_set_verify(conn->ssl.ctx,
SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT| SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT|
SSL_VERIFY_CLIENT_ONCE, SSL_VERIFY_CLIENT_ONCE,
cert_verify_callback); cert_verify_callback);
if (!SSL_CTX_load_verify_locations(conn->ssl.ctx, if (!SSL_CTX_load_verify_locations(conn->ssl.ctx,
data->ssl.CAfile, data->set.ssl.CAfile,
data->ssl.CApath)) { data->set.ssl.CApath)) {
failf(data,"error setting cerficate verify locations\n"); failf(data,"error setting cerficate verify locations\n");
return CURLE_SSL_CONNECT_ERROR; return CURLE_SSL_CONNECT_ERROR;
} }
@@ -362,11 +597,25 @@ Curl_SSLConnect(struct connectdata *conn)
conn->ssl.server_cert = 0x0; conn->ssl.server_cert = 0x0;
if(!conn->bits.reuse) {
/* We're not re-using a connection, check if there's a cached ID we
can/should use here! */
if(!Get_SSL_Session(conn, &ssl_sessionid)) {
/* we got a session id, use it! */
SSL_set_session(conn->ssl.handle, ssl_sessionid);
/* Informational message */
infof (data, "SSL re-using session ID\n");
}
}
/* 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); err = SSL_connect (conn->ssl.handle);
if (-1 == err) { /* 1 is fine
0 is "not successful but was shut down controlled"
<0 is "handshake was not successful, because a fatal error occurred" */
if (err <= 0) {
err = ERR_get_error(); err = ERR_get_error();
failf(data, "SSL: %s", ERR_error_string(err, NULL)); failf(data, "SSL: %s", ERR_error_string(err, NULL));
return CURLE_SSL_CONNECT_ERROR; return CURLE_SSL_CONNECT_ERROR;
@@ -375,6 +624,13 @@ Curl_SSLConnect(struct connectdata *conn)
/* Informational message */ /* Informational message */
infof (data, "SSL connection using %s\n", infof (data, "SSL connection using %s\n",
SSL_get_cipher(conn->ssl.handle)); SSL_get_cipher(conn->ssl.handle));
if(!ssl_sessionid) {
/* Since this is not a cached session ID, then we want to stach this one
in the cache! */
Store_SSL_Session(conn);
}
/* Get server's certificate (note: beware of dynamic allocation) - opt */ /* Get server's certificate (note: beware of dynamic allocation) - opt */
/* major serious hack alert -- we should check certificates /* major serious hack alert -- we should check certificates
@@ -399,23 +655,35 @@ Curl_SSLConnect(struct connectdata *conn)
infof(data, "\t subject: %s\n", str); infof(data, "\t subject: %s\n", str);
CRYPTO_free(str); CRYPTO_free(str);
if (data->ssl.verifyhost) { certdate = X509_get_notBefore(conn->ssl.server_cert);
Curl_ASN1_UTCTIME_output(conn, "\t start date: ", certdate);
certdate = X509_get_notAfter(conn->ssl.server_cert);
Curl_ASN1_UTCTIME_output(conn, "\t expire date: ", certdate);
if (data->set.ssl.verifyhost) {
char peer_CN[257]; char peer_CN[257];
if (X509_NAME_get_text_by_NID(X509_get_subject_name(conn->ssl.server_cert), NID_commonName, peer_CN, sizeof(peer_CN)) < 0) { if (X509_NAME_get_text_by_NID(X509_get_subject_name(conn->ssl.server_cert),
NID_commonName,
peer_CN,
sizeof(peer_CN)) < 0) {
failf(data, "SSL: unable to obtain common name from peer certificate"); failf(data, "SSL: unable to obtain common name from peer certificate");
X509_free(conn->ssl.server_cert); X509_free(conn->ssl.server_cert);
return CURLE_SSL_PEER_CERTIFICATE; return CURLE_SSL_PEER_CERTIFICATE;
} }
if (strcasecmp(peer_CN, conn->hostname) != 0) { if (!strequal(peer_CN, conn->hostname)) {
if (data->ssl.verifyhost > 1) { if (data->set.ssl.verifyhost > 1) {
failf(data, "SSL: certificate subject name '%s' does not match target host name '%s'", failf(data, "SSL: certificate subject name '%s' does not match "
peer_CN, conn->hostname); "target host name '%s'",
peer_CN, conn->hostname);
X509_free(conn->ssl.server_cert); X509_free(conn->ssl.server_cert);
return CURLE_SSL_PEER_CERTIFICATE; return CURLE_SSL_PEER_CERTIFICATE;
} }
else else
infof(data, "\t common name: %s (does not match '%s')\n", peer_CN, conn->hostname); infof(data,
"\t common name: %s (does not match '%s')\n",
peer_CN, conn->hostname);
} }
else else
infof(data, "\t common name: %s (matched)\n", peer_CN); infof(data, "\t common name: %s (matched)\n", peer_CN);
@@ -434,16 +702,16 @@ Curl_SSLConnect(struct connectdata *conn)
/* We could do all sorts of certificate verification stuff here before /* We could do all sorts of certificate verification stuff here before
deallocating the certificate. */ deallocating the certificate. */
if(data->ssl.verifypeer) { if(data->set.ssl.verifypeer) {
data->ssl.certverifyresult=SSL_get_verify_result(conn->ssl.handle); data->set.ssl.certverifyresult=SSL_get_verify_result(conn->ssl.handle);
if (data->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\n",
data->ssl.certverifyresult); data->set.ssl.certverifyresult);
retcode = CURLE_SSL_PEER_CERTIFICATE; retcode = CURLE_SSL_PEER_CERTIFICATE;
} }
} }
else else
data->ssl.certverifyresult=0; data->set.ssl.certverifyresult=0;
X509_free(conn->ssl.server_cert); X509_free(conn->ssl.server_cert);
#else /* USE_SSLEAY */ #else /* USE_SSLEAY */
@@ -452,3 +720,11 @@ Curl_SSLConnect(struct connectdata *conn)
#endif #endif
return retcode; return retcode;
} }
/*
* local variables:
* eval: (load-file "../curl-mode.el")
* end:
* vim600: fdm=marker
* vim: et sw=2 ts=2 sts=2 tw=78
*/

View File

@@ -24,8 +24,15 @@
*****************************************************************************/ *****************************************************************************/
#include "urldata.h" #include "urldata.h"
CURLcode Curl_SSLConnect(struct connectdata *conn); CURLcode Curl_SSLConnect(struct connectdata *conn);
/* Global SSL init */
void Curl_SSL_init(void); void Curl_SSL_init(void); /* Global SSL init */
/* Global SSL cleanup */ void Curl_SSL_cleanup(void); /* Global SSL cleanup */
void Curl_SSL_cleanup(void);
/* init the SSL session ID cache */
CURLcode Curl_SSL_InitSessions(struct SessionHandle *, long);
void Curl_SSL_Close(struct connectdata *conn); /* close a SSL connection */
/* tell the SSL stuff to close down all open information regarding
connections (and thus session ID caching etc) */
int Curl_SSL_Close_All(struct SessionHandle *data);
#endif #endif

View File

@@ -28,11 +28,11 @@
int curl_strequal(const char *first, const char *second) int curl_strequal(const char *first, const char *second)
{ {
#if defined(HAVE_STRCASECMP) #if defined(HAVE_STRCASECMP)
return !strcasecmp(first, second); return !(strcasecmp)(first, second);
#elif defined(HAVE_STRCMPI) #elif defined(HAVE_STRCMPI)
return !strcmpi(first, second); return !(strcmpi)(first, second);
#elif defined(HAVE_STRICMP) #elif defined(HAVE_STRICMP)
return !stricmp(first, second); return !(stricmp)(first, second);
#else #else
while (*first && *second) { while (*first && *second) {
if (toupper(*first) != toupper(*second)) { if (toupper(*first) != toupper(*second)) {
@@ -107,3 +107,11 @@ size_t Curl_strlcat(char *dst, const char *src, size_t siz)
return(dlen + (s - src)); /* count does not include NUL */ return(dlen + (s - src)); /* count does not include NUL */
} }
#endif #endif
/*
* local variables:
* eval: (load-file "../curl-mode.el")
* end:
* vim600: fdm=marker
* vim: et sw=2 ts=2 sts=2 tw=78
*/

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.
@@ -21,108 +21,54 @@
* $Id$ * $Id$
*****************************************************************************/ *****************************************************************************/
#include "setup.h" #include "setup.h"
#ifndef HAVE_STRTOK_R #ifndef HAVE_STRTOK_R
/*
* Copyright (c) 1998 Softweyr LLC. All rights reserved.
*
* strtok_r, from Berkeley strtok
* Oct 13, 1998 by Wes Peters <wes@softweyr.com>
*
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notices, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notices, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
*
* This product includes software developed by Softweyr LLC, the
* University of California, Berkeley, and its contributors.
*
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY SOFTWEYR LLC, THE REGENTS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SOFTWEYR LLC, THE
* REGENTS, OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stddef.h> #include <stddef.h>
#include <string.h>
char * char *
Curl_strtok_r(char *s, const char *delim, char **last) Curl_strtok_r(char *ptr, const char *sep, char **end)
{ {
char *spanp; if (!ptr)
int c, sc; /* we got NULL input so then we get our last position instead */
char *tok; ptr = *end;
if (s == NULL && (s = *last) == NULL) { /* pass all letters that are including in the separator string */
return NULL; while (*ptr && strchr(sep, *ptr))
} ++ptr;
/* if (*ptr) {
* Skip (span) leading delimiters (s += strspn(s, delim), sort of). /* so this is where the next piece of string starts */
*/ char *start = ptr;
cont:
c = *s++; /* set the end pointer to the first byte after the start */
for (spanp = (char *)delim; (sc = *spanp++) != 0; ) { *end = start + 1;
if (c == sc) {
goto cont; /* scan through the string to find where it ends, it ends on a
null byte or a character that exists in the separator string */
while (**end && !strchr(sep, **end))
++*end;
if (**end) {
/* the end is not a null byte */
**end = '\0'; /* zero terminate it! */
++*end; /* advance the last pointer to beyond the null byte */
} }
return start; /* return the position where the string starts */
} }
if (c == 0) { /* no non-delimiter characters */ /* we ended up on a null byte, there are no more strings to find! */
*last = NULL; return NULL;
return NULL;
}
tok = s - 1;
/*
* Scan token (scan for delimiters: s += strcspn(s, delim), sort of).
* Note that delim must have one NUL; we stop if we see that, too.
*/
for (;;) {
c = *s++;
spanp = (char *)delim;
do {
if ((sc = *spanp++) == c) {
if (c == 0) {
s = NULL;
}
else {
char *w = s - 1;
*w = '\0';
}
*last = s;
return tok;
}
}
while (sc != 0);
}
/* NOTREACHED */
} }
#endif #endif /* this was only compiled if strtok_r wasn't present */
/*
* local variables:
* eval: (load-file "../curl-mode.el")
* end:
* vim600: fdm=marker
* vim: et sw=2 ts=2 sts=2 tw=78
*/

View File

@@ -35,7 +35,7 @@
#include <errno.h> #include <errno.h>
#if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__) #if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__)
#include <winsock.h> #include <winsock2.h>
#include <time.h> #include <time.h>
#include <io.h> #include <io.h>
#else #else
@@ -105,7 +105,7 @@ void telrcv(struct connectdata *,
unsigned char *inbuf, /* Data received from socket */ unsigned char *inbuf, /* Data received from socket */
int count); /* Number of bytes received */ int count); /* Number of bytes received */
static void printoption(struct UrlData *data, static void printoption(struct SessionHandle *data,
const char *direction, const char *direction,
int cmd, int option); int cmd, int option);
@@ -114,7 +114,7 @@ static void send_negotiation(struct connectdata *, int cmd, int option);
static void set_local_option(struct connectdata *, int cmd, int option); static void set_local_option(struct connectdata *, int cmd, int option);
static void set_remote_option(struct connectdata *, int cmd, int option); static void set_remote_option(struct connectdata *, int cmd, int option);
static void printsub(struct UrlData *data, static void printsub(struct SessionHandle *data,
int direction, unsigned char *pointer, int length); int direction, unsigned char *pointer, int length);
static void suboption(struct connectdata *); static void suboption(struct connectdata *);
@@ -152,8 +152,8 @@ struct TELNET {
int him[256]; int him[256];
int himq[256]; int himq[256];
int him_preferred[256]; int him_preferred[256];
char *subopt_ttype; /* Set with suboption TTYPE */ char subopt_ttype[32]; /* Set with suboption TTYPE */
char *subopt_xdisploc; /* Set with suboption XDISPLOC */ char subopt_xdisploc[128]; /* Set with suboption XDISPLOC */
struct curl_slist *telnet_vars; /* Environment variables */ struct curl_slist *telnet_vars; /* Environment variables */
/* suboptions */ /* suboptions */
@@ -215,13 +215,13 @@ static void negotiate(struct connectdata *conn)
} }
} }
static void printoption(struct UrlData *data, static void printoption(struct SessionHandle *data,
const char *direction, int cmd, int option) const char *direction, int cmd, int option)
{ {
const char *fmt; const char *fmt;
const char *opt; const char *opt;
if (data->bits.verbose) if (data->set.verbose)
{ {
if (cmd == IAC) if (cmd == IAC)
{ {
@@ -627,14 +627,14 @@ void rec_dont(struct connectdata *conn, int option)
} }
static void printsub(struct UrlData *data, static void printsub(struct SessionHandle *data,
int direction, /* '<' or '>' */ int direction, /* '<' or '>' */
unsigned char *pointer, /* where suboption data is */ unsigned char *pointer, /* where suboption data is */
int length) /* length of suboption data */ int length) /* length of suboption data */
{ {
int i = 0; int i = 0;
if (data->bits.verbose) if (data->set.verbose)
{ {
if (direction) if (direction)
{ {
@@ -745,7 +745,7 @@ static int check_telnet_options(struct connectdata *conn)
char option_keyword[128]; char option_keyword[128];
char option_arg[256]; char option_arg[256];
char *buf; char *buf;
struct UrlData *data = conn->data; struct SessionHandle *data = conn->data;
struct TELNET *tn = (struct TELNET *)conn->proto.telnet; struct TELNET *tn = (struct TELNET *)conn->proto.telnet;
/* Add the user name as an environment variable if it /* Add the user name as an environment variable if it
@@ -753,26 +753,28 @@ static int check_telnet_options(struct connectdata *conn)
if(conn->bits.user_passwd) if(conn->bits.user_passwd)
{ {
char *buf = malloc(256); char *buf = malloc(256);
sprintf(buf, "USER,%s", data->user); sprintf(buf, "USER,%s", data->state.user);
tn->telnet_vars = curl_slist_append(tn->telnet_vars, buf); tn->telnet_vars = curl_slist_append(tn->telnet_vars, buf);
tn->us_preferred[TELOPT_NEW_ENVIRON] = YES; tn->us_preferred[TELOPT_NEW_ENVIRON] = YES;
} }
for(head = data->telnet_options; head; head=head->next) { for(head = data->set.telnet_options; head; head=head->next) {
if(sscanf(head->data, "%127[^= ]%*[ =]%255s", if(sscanf(head->data, "%127[^= ]%*[ =]%255s",
option_keyword, option_arg) == 2) { option_keyword, option_arg) == 2) {
/* Terminal type */ /* Terminal type */
if(strequal(option_keyword, "TTYPE")) { if(strequal(option_keyword, "TTYPE")) {
tn->subopt_ttype = option_arg; strncpy(tn->subopt_ttype, option_arg, 31);
tn->subopt_ttype[31] = 0; /* String termination */
tn->us_preferred[TELOPT_TTYPE] = YES; tn->us_preferred[TELOPT_TTYPE] = YES;
continue; continue;
} }
/* Display variable */ /* Display variable */
if(strequal(option_keyword, "XDISPLOC")) { if(strequal(option_keyword, "XDISPLOC")) {
tn->subopt_xdisploc = option_arg; strncpy(tn->subopt_xdisploc, option_arg, 127);
tn->subopt_xdisploc[127] = 0; /* String termination */
tn->us_preferred[TELOPT_XDISPLOC] = YES; tn->us_preferred[TELOPT_XDISPLOC] = YES;
continue; continue;
} }
@@ -814,7 +816,7 @@ static void suboption(struct connectdata *conn)
int tmplen; int tmplen;
char varname[128]; char varname[128];
char varval[128]; char varval[128];
struct UrlData *data = conn->data; struct SessionHandle *data = conn->data;
struct TELNET *tn = (struct TELNET *)conn->proto.telnet; struct TELNET *tn = (struct TELNET *)conn->proto.telnet;
printsub(data, '<', (unsigned char *)tn->subbuffer, SB_LEN(tn)+2); printsub(data, '<', (unsigned char *)tn->subbuffer, SB_LEN(tn)+2);
@@ -868,7 +870,7 @@ void telrcv(struct connectdata *conn,
{ {
unsigned char c; unsigned char c;
int index = 0; int index = 0;
struct UrlData *data = conn->data; struct SessionHandle *data = conn->data;
struct TELNET *tn = (struct TELNET *)conn->proto.telnet; struct TELNET *tn = (struct TELNET *)conn->proto.telnet;
while(count--) while(count--)
@@ -1031,13 +1033,20 @@ CURLcode Curl_telnet_done(struct connectdata *conn)
CURLcode Curl_telnet(struct connectdata *conn) CURLcode Curl_telnet(struct connectdata *conn)
{ {
CURLcode code; CURLcode code;
struct UrlData *data = conn->data; struct SessionHandle *data = conn->data;
int sockfd = conn->firstsocket; int sockfd = conn->firstsocket;
#ifdef WIN32
WSAEVENT event_handle;
WSANETWORKEVENTS events;
HANDLE stdin_handle;
HANDLE objs[2];
DWORD waitret;
#else
fd_set readfd; fd_set readfd;
fd_set keepfd; fd_set keepfd;
#endif
bool keepon = TRUE; bool keepon = TRUE;
char *buf = data->buffer; char *buf = data->state.buffer;
ssize_t nread; ssize_t nread;
struct TELNET *tn; struct TELNET *tn;
@@ -1050,7 +1059,87 @@ CURLcode Curl_telnet(struct connectdata *conn)
code = check_telnet_options(conn); code = check_telnet_options(conn);
if(code) if(code)
return code; return code;
#ifdef WIN32
/* We want to wait for both stdin and the socket. Since
** the select() function in winsock only works on sockets
** we have to use the WaitForMultipleObjects() call.
*/
/* First, create a sockets event object */
event_handle = WSACreateEvent();
/* The get the Windows file handle for stdin */
stdin_handle = GetStdHandle(STD_INPUT_HANDLE);
/* Create the list of objects to wait for */
objs[0] = stdin_handle;
objs[1] = event_handle;
/* Tell winsock what events we want to listen to */
if(WSAEventSelect(sockfd, event_handle, FD_READ|FD_CLOSE) == SOCKET_ERROR) {
return 0;
}
/* Keep on listening and act on events */
while(keepon) {
waitret = WaitForMultipleObjects(2, objs, FALSE, INFINITE);
switch(waitret - WAIT_OBJECT_0)
{
case 0:
{
unsigned char outbuf[2];
int out_count = 0;
size_t bytes_written;
char *buffer = buf;
if(!ReadFile(stdin_handle, buf, 255, &nread, NULL)) {
keepon = FALSE;
break;
}
while(nread--) {
outbuf[0] = *buffer++;
out_count = 1;
if(outbuf[0] == IAC)
outbuf[out_count++] = IAC;
Curl_write(conn, conn->firstsocket, outbuf,
out_count, &bytes_written);
}
}
break;
case 1:
if(WSAEnumNetworkEvents(sockfd, event_handle, &events)
!= SOCKET_ERROR)
{
if(events.lNetworkEvents & FD_READ)
{
Curl_read(conn, sockfd, buf, BUFSIZE - 1, &nread);
telrcv(conn, (unsigned char *)buf, nread);
fflush(stdout);
/* Negotiate if the peer has started negotiating,
otherwise don't. We don't want to speak telnet with
non-telnet servers, like POP or SMTP. */
if(tn->please_negotiate && !tn->already_negotiated) {
negotiate(conn);
tn->already_negotiated = 1;
}
}
if(events.lNetworkEvents & FD_CLOSE)
{
keepon = FALSE;
}
}
break;
}
}
#else
FD_ZERO (&readfd); /* clear it */ FD_ZERO (&readfd); /* clear it */
FD_SET (sockfd, &readfd); FD_SET (sockfd, &readfd);
FD_SET (1, &readfd); FD_SET (1, &readfd);
@@ -1108,6 +1197,15 @@ CURLcode Curl_telnet(struct connectdata *conn)
} }
} }
} }
#endif
/* mark this as "no further transfer wanted" */ /* mark this as "no further transfer wanted" */
return Curl_Transfer(conn, -1, -1, FALSE, NULL, -1, NULL); return Curl_Transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
} }
/*
* local variables:
* eval: (load-file "../curl-mode.el")
* end:
* vim600: fdm=marker
* vim: et sw=2 ts=2 sts=2 tw=78
*/

View File

@@ -65,12 +65,25 @@ struct timeval Curl_tvnow (void)
return now; return now;
} }
double Curl_tvdiff (struct timeval t1, struct timeval t2) /*
* Make sure that the first argument is the more recent time, as otherwise
* we'll get a weird negative time-diff back...
*/
long Curl_tvdiff (struct timeval t1, struct timeval t2)
{ {
return (double)(t1.tv_sec - t2.tv_sec) + ((t1.tv_usec-t2.tv_usec)/1000000.0); return (t1.tv_sec*1000 + t1.tv_usec/1000)-
(t2.tv_sec*1000 + t2.tv_usec/1000);
} }
long Curl_tvlong (struct timeval t1) long Curl_tvlong (struct timeval t1)
{ {
return t1.tv_sec; return t1.tv_sec;
} }
/*
* local variables:
* eval: (load-file "../curl-mode.el")
* end:
* vim600: fdm=marker
* vim: et sw=2 ts=2 sts=2 tw=78
*/

View File

@@ -43,7 +43,10 @@ struct timeval {
#endif #endif
struct timeval Curl_tvnow (); struct timeval Curl_tvnow ();
double Curl_tvdiff (struct timeval t1, struct timeval t2);
/* the diff is from now on returned in number of milliseconds! */
long Curl_tvdiff (struct timeval t1, struct timeval t2);
long Curl_tvlong (struct timeval t1); long Curl_tvlong (struct timeval t1);
#endif #endif

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.
@@ -92,6 +92,7 @@
#include "http.h" #include "http.h"
#include "url.h" #include "url.h"
#include "getinfo.h" #include "getinfo.h"
#include "ssluse.h"
#define _MPRINTF_REPLACE /* use our functions only */ #define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h> #include <curl/mprintf.h>
@@ -197,6 +198,9 @@ Transfer(struct connectdata *c_conn)
Content-Range: header */ Content-Range: header */
int httpcode = 0; /* error code from the 'HTTP/1.? XXX' line */ int httpcode = 0; /* error code from the 'HTTP/1.? XXX' line */
int httpversion = -1; /* the HTTP version*10 */ int httpversion = -1; /* the HTTP version*10 */
bool write_after_100_header = FALSE; /* should we enable the write after
we received a 100-continue/timeout
or directly */
/* for the low speed checks: */ /* for the low speed checks: */
CURLcode urg; CURLcode urg;
@@ -205,18 +209,16 @@ Transfer(struct connectdata *c_conn)
int writetype; int writetype;
/* the highest fd we use + 1 */ /* the highest fd we use + 1 */
struct UrlData *data; struct SessionHandle *data;
struct connectdata *conn = (struct connectdata *)c_conn; struct connectdata *conn = (struct connectdata *)c_conn;
char *buf; char *buf;
int maxfd; int maxfd;
data = conn->data; /* there's the root struct */ data = conn->data; /* there's the root struct */
buf = data->buffer; buf = data->state.buffer;
maxfd = (conn->sockfd>conn->writesockfd?conn->sockfd:conn->writesockfd)+1; maxfd = (conn->sockfd>conn->writesockfd?conn->sockfd:conn->writesockfd)+1;
hbufp = data->headerbuff; hbufp = data->state.headerbuff;
myalarm (0); /* switch off the alarm-style timeout */
now = Curl_tvnow(); now = Curl_tvnow();
start = now; start = now;
@@ -240,7 +242,7 @@ Transfer(struct connectdata *c_conn)
} }
/* we want header and/or body, if neither then don't do this! */ /* we want header and/or body, if neither then don't do this! */
if(conn->getheader || if(conn->getheader ||
!data->bits.no_body) { !data->set.no_body) {
fd_set readfd; fd_set readfd;
fd_set writefd; fd_set writefd;
fd_set rkeepfd; fd_set rkeepfd;
@@ -263,8 +265,13 @@ Transfer(struct connectdata *c_conn)
FD_ZERO (&writefd); /* clear it */ FD_ZERO (&writefd); /* clear it */
if(conn->writesockfd != -1) { if(conn->writesockfd != -1) {
FD_SET (conn->writesockfd, &writefd); /* write socket */ if (data->set.expect100header)
keepon |= KEEP_WRITE; /* wait with write until we either got 100-continue or a timeout */
write_after_100_header = TRUE;
else {
FD_SET (conn->writesockfd, &writefd); /* write socket */
keepon |= KEEP_WRITE;
}
} }
/* get these in backup variables to be able to restore them on each lap in /* get these in backup variables to be able to restore them on each lap in
@@ -290,6 +297,12 @@ Transfer(struct connectdata *c_conn)
keepon = 0; /* no more read or write */ keepon = 0; /* no more read or write */
continue; continue;
case 0: /* timeout */ case 0: /* timeout */
if (write_after_100_header) {
write_after_100_header = FALSE;
FD_SET (conn->writesockfd, &writefd); /* write socket */
keepon |= KEEP_WRITE;
wkeepfd = writefd;
}
break; break;
default: default:
if((keepon & KEEP_READ) && FD_ISSET(conn->sockfd, &readfd)) { if((keepon & KEEP_READ) && FD_ISSET(conn->sockfd, &readfd)) {
@@ -335,19 +348,19 @@ Transfer(struct connectdata *c_conn)
* We enlarge the header buffer if it seems to be too * We enlarge the header buffer if it seems to be too
* smallish * smallish
*/ */
if (hbuflen + (int)str_length >= data->headersize) { if (hbuflen + (int)str_length >= data->state.headersize) {
char *newbuff; char *newbuff;
long newsize=MAX((hbuflen+str_length)*3/2, long newsize=MAX((hbuflen+str_length)*3/2,
data->headersize*2); data->state.headersize*2);
hbufp_index = hbufp - data->headerbuff; hbufp_index = hbufp - data->state.headerbuff;
newbuff = (char *)realloc(data->headerbuff, newsize); newbuff = (char *)realloc(data->state.headerbuff, newsize);
if(!newbuff) { if(!newbuff) {
failf (data, "Failed to alloc memory for big header!"); failf (data, "Failed to alloc memory for big header!");
return CURLE_READ_ERROR; return CURLE_READ_ERROR;
} }
data->headersize=newsize; data->state.headersize=newsize;
data->headerbuff = newbuff; data->state.headerbuff = newbuff;
hbufp = data->headerbuff + hbufp_index; hbufp = data->state.headerbuff + hbufp_index;
} }
strcpy (hbufp, str); strcpy (hbufp, str);
hbufp += strlen (str); hbufp += strlen (str);
@@ -363,19 +376,19 @@ Transfer(struct connectdata *c_conn)
* fit in the allocated header buffer, or else we enlarge * fit in the allocated header buffer, or else we enlarge
* it. * it.
*/ */
if (hbuflen + (str - str_start) >= data->headersize) { if (hbuflen + (str - str_start) >= data->state.headersize) {
char *newbuff; char *newbuff;
long newsize=MAX((hbuflen+(str-str_start))*3/2, long newsize=MAX((hbuflen+(str-str_start))*3/2,
data->headersize*2); data->state.headersize*2);
hbufp_index = hbufp - data->headerbuff; hbufp_index = hbufp - data->state.headerbuff;
newbuff = (char *)realloc(data->headerbuff, newsize); newbuff = (char *)realloc(data->state.headerbuff, newsize);
if(!newbuff) { if(!newbuff) {
failf (data, "Failed to alloc memory for big header!"); failf (data, "Failed to alloc memory for big header!");
return CURLE_READ_ERROR; return CURLE_READ_ERROR;
} }
data->headersize= newsize; data->state.headersize= newsize;
data->headerbuff = newbuff; data->state.headerbuff = newbuff;
hbufp = data->headerbuff + hbufp_index; hbufp = data->state.headerbuff + hbufp_index;
} }
/* copy to end of line */ /* copy to end of line */
@@ -384,7 +397,7 @@ Transfer(struct connectdata *c_conn)
hbuflen += str - str_start; hbuflen += str - str_start;
*hbufp = 0; *hbufp = 0;
p = data->headerbuff; p = data->state.headerbuff;
/**** /****
* We now have a FULL header line that p points to * We now have a FULL header line that p points to
@@ -408,22 +421,43 @@ Transfer(struct connectdata *c_conn)
*/ */
header = TRUE; header = TRUE;
headerline = 0; /* we restart the header line counter */ headerline = 0; /* we restart the header line counter */
/* if we did wait for this do enable write now! */
if (write_after_100_header) {
write_after_100_header = FALSE;
FD_SET (conn->writesockfd, &writefd); /* write socket */
keepon |= KEEP_WRITE;
wkeepfd = writefd;
}
} }
else else
header = FALSE; /* no more header to parse! */ header = FALSE; /* no more header to parse! */
if (417 == httpcode) {
/*
* we got: "417 Expectation Failed" this means:
* we have made a HTTP call and our Expect Header
* seems to cause a problem => abort the write operations
* (or prevent them from starting
*/
write_after_100_header = FALSE;
keepon &= ~KEEP_WRITE;
FD_ZERO(&wkeepfd);
}
/* now, only output this if the header AND body are requested: /* now, only output this if the header AND body are requested:
*/ */
writetype = CLIENTWRITE_HEADER; writetype = CLIENTWRITE_HEADER;
if (data->bits.http_include_header) if (data->set.http_include_header)
writetype |= CLIENTWRITE_BODY; writetype |= CLIENTWRITE_BODY;
urg = Curl_client_write(data, writetype, data->headerbuff, urg = Curl_client_write(data, writetype,
p - data->headerbuff); data->state.headerbuff,
p - data->state.headerbuff);
if(urg) if(urg)
return urg; return urg;
data->header_size += p - data->headerbuff; data->info.header_size += p - data->state.headerbuff;
conn->headerbytecount += p - data->state.headerbuff;
if(!header) { if(!header) {
/* /*
@@ -432,7 +466,7 @@ Transfer(struct connectdata *c_conn)
* If we requested a "no body", this is a good time to get * If we requested a "no body", this is a good time to get
* out and return home. * out and return home.
*/ */
if(data->bits.no_body) if(data->set.no_body)
return CURLE_OK; return CURLE_OK;
if(!conn->bits.close) { if(!conn->bits.close) {
@@ -455,7 +489,7 @@ Transfer(struct connectdata *c_conn)
/* We continue reading headers, so reset the line-based /* We continue reading headers, so reset the line-based
header parsing variables hbufp && hbuflen */ header parsing variables hbufp && hbuflen */
hbufp = data->headerbuff; hbufp = data->state.headerbuff;
hbuflen = 0; hbuflen = 0;
continue; continue;
} }
@@ -482,17 +516,12 @@ Transfer(struct connectdata *c_conn)
} }
if (nc) { if (nc) {
data->progress.httpcode = httpcode; data->info.httpcode = httpcode;
data->progress.httpversion = httpversion; data->info.httpversion = httpversion;
/* 404 -> URL not found! */ /* 404 -> URL not found! */
if ( if (data->set.http_fail_on_error &&
( ((data->bits.http_follow_location) && (httpcode >= 400)) {
(httpcode >= 400))
||
(!data->bits.http_follow_location &&
(httpcode >= 300)))
&& (data->bits.http_fail_on_error)) {
/* If we have been told to fail hard on HTTP-errors, /* If we have been told to fail hard on HTTP-errors,
here is the check for that: */ here is the check for that: */
/* serious error, go home! */ /* serious error, go home! */
@@ -586,18 +615,18 @@ Transfer(struct connectdata *c_conn)
} }
else if(data->cookies && else if(data->cookies &&
strnequal("Set-Cookie:", p, 11)) { strnequal("Set-Cookie:", p, 11)) {
Curl_cookie_add(data->cookies, TRUE, &p[12]); Curl_cookie_add(data->cookies, TRUE, &p[12], conn->name);
} }
else if(strnequal("Last-Modified:", p, else if(strnequal("Last-Modified:", p,
strlen("Last-Modified:")) && strlen("Last-Modified:")) &&
(data->timecondition || data->bits.get_filetime) ) { (data->set.timecondition || data->set.get_filetime) ) {
time_t secs=time(NULL); time_t secs=time(NULL);
timeofdoc = curl_getdate(p+strlen("Last-Modified:"), &secs); timeofdoc = curl_getdate(p+strlen("Last-Modified:"), &secs);
if(data->bits.get_filetime) if(data->set.get_filetime>=0)
data->progress.filetime = timeofdoc; data->info.filetime = timeofdoc;
} }
else if ((httpcode >= 300 && httpcode < 400) && else if ((httpcode >= 300 && httpcode < 400) &&
(data->bits.http_follow_location) && (data->set.http_follow_location) &&
strnequal("Location:", p, 9)) { strnequal("Location:", p, 9)) {
/* this is the URL that the server advices us to get instead */ /* this is the URL that the server advices us to get instead */
char *ptr; char *ptr;
@@ -626,17 +655,17 @@ Transfer(struct connectdata *c_conn)
*/ */
writetype = CLIENTWRITE_HEADER; writetype = CLIENTWRITE_HEADER;
if (data->bits.http_include_header) if (data->set.http_include_header)
writetype |= CLIENTWRITE_BODY; writetype |= CLIENTWRITE_BODY;
urg = Curl_client_write(data, writetype, p, hbuflen); urg = Curl_client_write(data, writetype, p, hbuflen);
if(urg) if(urg)
return urg; return urg;
data->header_size += hbuflen; data->info.header_size += hbuflen;
/* reset hbufp pointer && hbuflen */ /* reset hbufp pointer && hbuflen */
hbufp = data->headerbuff; hbufp = data->state.headerbuff;
hbuflen = 0; hbuflen = 0;
} }
while (*str); /* header line within buffer */ while (*str); /* header line within buffer */
@@ -672,7 +701,7 @@ Transfer(struct connectdata *c_conn)
} }
else if (conn->resume_from && else if (conn->resume_from &&
!content_range && !content_range &&
(data->httpreq==HTTPREQ_GET)) { (data->set.httpreq==HTTPREQ_GET)) {
/* we wanted to resume a download, although the server /* we wanted to resume a download, although the server
doesn't seem to support this and we did this with a GET doesn't seem to support this and we did this with a GET
(if it wasn't a GET we did a POST or PUT resume) */ (if it wasn't a GET we did a POST or PUT resume) */
@@ -680,23 +709,23 @@ Transfer(struct connectdata *c_conn)
"byte ranges. Cannot resume."); "byte ranges. Cannot resume.");
return CURLE_HTTP_RANGE_ERROR; return CURLE_HTTP_RANGE_ERROR;
} }
else if(data->timecondition && !conn->range) { else if(data->set.timecondition && !conn->range) {
/* A time condition has been set AND no ranges have been /* A time condition has been set AND no ranges have been
requested. This seems to be what chapter 13.3.4 of requested. This seems to be what chapter 13.3.4 of
RFC 2616 defines to be the correct action for a RFC 2616 defines to be the correct action for a
HTTP/1.1 client */ HTTP/1.1 client */
if((timeofdoc > 0) && (data->timevalue > 0)) { if((timeofdoc > 0) && (data->set.timevalue > 0)) {
switch(data->timecondition) { switch(data->set.timecondition) {
case TIMECOND_IFMODSINCE: case TIMECOND_IFMODSINCE:
default: default:
if(timeofdoc < data->timevalue) { if(timeofdoc < data->set.timevalue) {
infof(data, infof(data,
"The requested document is not new enough\n"); "The requested document is not new enough\n");
return CURLE_OK; return CURLE_OK;
} }
break; break;
case TIMECOND_IFUNMODSINCE: case TIMECOND_IFUNMODSINCE:
if(timeofdoc > data->timevalue) { if(timeofdoc > data->set.timevalue) {
infof(data, infof(data,
"The requested document is not old enough\n"); "The requested document is not old enough\n");
return CURLE_OK; return CURLE_OK;
@@ -763,14 +792,10 @@ Transfer(struct connectdata *c_conn)
if((keepon & KEEP_WRITE) && FD_ISSET(conn->writesockfd, &writefd)) { if((keepon & KEEP_WRITE) && FD_ISSET(conn->writesockfd, &writefd)) {
/* write */ /* write */
char scratch[BUFSIZE * 2];
int i, si; int i, si;
size_t bytes_written; size_t bytes_written;
if(data->crlf) nread = data->set.fread(buf, 1, conn->upload_bufsize, data->set.in);
buf = data->buffer; /* put it back on the buffer */
nread = data->fread(buf, 1, conn->upload_bufsize, data->in);
/* the signed int typecase of nread of for systems that has /* the signed int typecase of nread of for systems that has
unsigned size_t */ unsigned size_t */
@@ -784,18 +809,18 @@ Transfer(struct connectdata *c_conn)
Curl_pgrsSetUploadCounter(data, (double)writebytecount); Curl_pgrsSetUploadCounter(data, (double)writebytecount);
/* convert LF to CRLF if so asked */ /* convert LF to CRLF if so asked */
if (data->crlf) { if (data->set.crlf) {
for(i = 0, si = 0; i < (int)nread; i++, si++) { for(i = 0, si = 0; i < (int)nread; i++, si++) {
if (buf[i] == 0x0a) { if (buf[i] == 0x0a) {
scratch[si++] = 0x0d; data->state.scratch[si++] = 0x0d;
scratch[si] = 0x0a; data->state.scratch[si] = 0x0a;
} }
else { else {
scratch[si] = buf[i]; data->state.scratch[si] = buf[i];
} }
} }
nread = si; nread = si;
buf = scratch; /* point to the new buffer */ buf = data->state.scratch; /* point to the new buffer */
} }
/* write to socket */ /* write to socket */
@@ -806,12 +831,20 @@ Transfer(struct connectdata *c_conn)
failf(data, "Failed uploading data"); failf(data, "Failed uploading data");
return CURLE_WRITE_ERROR; return CURLE_WRITE_ERROR;
} }
if(data->set.crlf)
buf = data->state.buffer; /* put it back on the buffer */
} }
break; break;
} }
/* Update read/write counters */
if(conn->bytecountp)
*conn->bytecountp = bytecount; /* read count */
if(conn->writebytecountp)
*conn->writebytecountp = writebytecount; /* write count */
now = Curl_tvnow(); now = Curl_tvnow();
if(Curl_pgrsUpdate(conn)) if(Curl_pgrsUpdate(conn))
urg = CURLE_ABORTED_BY_CALLBACK; urg = CURLE_ABORTED_BY_CALLBACK;
@@ -829,11 +862,13 @@ Transfer(struct connectdata *c_conn)
conn->upload_bufsize=(long)min(data->progress.ulspeed, BUFSIZE); conn->upload_bufsize=(long)min(data->progress.ulspeed, BUFSIZE);
} }
if (data->timeout && (Curl_tvdiff (now, start) > data->timeout)) { if (data->set.timeout &&
((Curl_tvdiff(now, start)/1000) >= data->set.timeout)) {
failf (data, "Operation timed out with %d out of %d bytes received", failf (data, "Operation timed out with %d out of %d bytes received",
bytecount, conn->size); bytecount, conn->size);
return CURLE_OPERATION_TIMEOUTED; return CURLE_OPERATION_TIMEOUTED;
} }
} }
} }
@@ -842,7 +877,7 @@ Transfer(struct connectdata *c_conn)
* returning. * returning.
*/ */
if(!(data->bits.no_body) && contentlength && if(!(data->set.no_body) && contentlength &&
(bytecount != contentlength)) { (bytecount != contentlength)) {
failf(data, "transfer closed with %d bytes remaining to read", failf(data, "transfer closed with %d bytes remaining to read",
contentlength-bytecount); contentlength-bytecount);
@@ -856,27 +891,30 @@ Transfer(struct connectdata *c_conn)
if(Curl_pgrsUpdate(conn)) if(Curl_pgrsUpdate(conn))
return CURLE_ABORTED_BY_CALLBACK; return CURLE_ABORTED_BY_CALLBACK;
if(conn->bytecountp)
*conn->bytecountp = bytecount; /* read count */
if(conn->writebytecountp)
*conn->writebytecountp = writebytecount; /* write count */
return CURLE_OK; return CURLE_OK;
} }
CURLcode Curl_perform(struct UrlData *data) CURLcode Curl_perform(struct SessionHandle *data)
{ {
CURLcode res; CURLcode res;
struct connectdata *conn=NULL; struct connectdata *conn=NULL;
bool port=TRUE; /* allow data->use_port to set port to use */ bool port=TRUE; /* allow data->set.use_port to set port to use */
char *newurl = NULL; /* possibly a new URL to follow to! */ char *newurl = NULL; /* possibly a new URL to follow to! */
if(!data->url) if(!data->change.url)
/* we can't do anything wihout URL */ /* we can't do anything wihout URL */
return CURLE_URL_MALFORMAT; return CURLE_URL_MALFORMAT;
data->followlocation=0; /* reset the location-follow counter */ #ifdef USE_SSLEAY
data->bits.this_is_a_follow = FALSE; /* reset this */ /* Init the SSL session ID cache here. We do it here since we want to
do it after the *_setopt() calls (that could change the size) but
before any transfer. */
Curl_SSL_InitSessions(data, data->set.ssl.numsessions);
#endif
data->set.followlocation=0; /* reset the location-follow counter */
data->state.this_is_a_follow = FALSE; /* reset this */
data->state.errorbuf = FALSE; /* no error has occurred */
Curl_initinfo(data); /* reset session-specific information "variables" */ Curl_initinfo(data); /* reset session-specific information "variables" */
@@ -887,7 +925,31 @@ CURLcode Curl_perform(struct UrlData *data)
res = Curl_connect(data, &conn, port); res = Curl_connect(data, &conn, port);
if(res == CURLE_OK) { if(res == CURLE_OK) {
res = Curl_do(conn); res = Curl_do(conn);
if((CURLE_WRITE_ERROR == res) && 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, "The re-used connection seems dead, get a new one\n");
conn->bits.close = TRUE; /* enforce close of this connetion */
res = Curl_done(conn); /* we are so done with this */
if(CURLE_OK == res) {
/* Now, redo the connect */
res = Curl_connect(data, &conn, port);
if(CURLE_OK == res)
/* ... finally back to actually retry the DO phase */
res = Curl_do(conn);
}
}
if(res == CURLE_OK) { if(res == CURLE_OK) {
CURLcode res2; /* just a local extra result container */
if(conn->protocol&PROT_FTPS) if(conn->protocol&PROT_FTPS)
/* FTPS, disable ssl while transfering data */ /* FTPS, disable ssl while transfering data */
conn->ssl.use = FALSE; conn->ssl.use = FALSE;
@@ -896,15 +958,24 @@ CURLcode Curl_perform(struct UrlData *data)
/* FTPS, enable ssl again after havving transferred data */ /* FTPS, enable ssl again after havving transferred data */
conn->ssl.use = TRUE; conn->ssl.use = TRUE;
if(res == CURLE_OK) { if(res == CURLE_OK)
/* /*
* We must duplicate the new URL here as the connection data * We must duplicate the new URL here as the connection data
* may be free()ed in the Curl_done() function. * may be free()ed in the Curl_done() function.
*/ */
newurl = conn->newurl?strdup(conn->newurl):NULL; newurl = conn->newurl?strdup(conn->newurl):NULL;
else
/* The transfer phase returned error, we mark the connection to get
* closed to prevent being re-used. This is becasue we can't
* possibly know if the connection is in a good shape or not now. */
conn->bits.close = TRUE;
res = Curl_done(conn); /* Always run Curl_done(), even if some of the previous calls
} failed, but return the previous (original) error code */
res2 = Curl_done(conn);
if(CURLE_OK == res)
res = res2;
} }
/* /*
@@ -923,33 +994,31 @@ CURLcode Curl_perform(struct UrlData *data)
port=TRUE; /* by default we use the user set port number even after port=TRUE; /* by default we use the user set port number even after
a Location: */ a Location: */
if (data->maxredirs && (data->followlocation >= data->maxredirs)) { if (data->set.maxredirs && (data->set.followlocation >= data->set.maxredirs)) {
failf(data,"Maximum (%d) redirects followed", data->maxredirs); failf(data,"Maximum (%d) redirects followed", data->set.maxredirs);
res=CURLE_TOO_MANY_REDIRECTS; res=CURLE_TOO_MANY_REDIRECTS;
break; break;
} }
/* mark the next request as a followed location: */ /* mark the next request as a followed location: */
data->bits.this_is_a_follow = TRUE; data->state.this_is_a_follow = TRUE;
data->followlocation++; /* count location-followers */ data->set.followlocation++; /* count location-followers */
if(data->bits.http_auto_referer) { if(data->set.http_auto_referer) {
/* We are asked to automatically set the previous URL as the /* We are asked to automatically set the previous URL as the
referer when we get the next URL. We pick the ->url field, referer when we get the next URL. We pick the ->url field,
which may or may not be 100% correct */ which may or may not be 100% correct */
if(data->free_referer) { if(data->change.referer_alloc)
/* If we already have an allocated referer, free this first */ /* If we already have an allocated referer, free this first */
free(data->referer); free(data->change.referer);
}
data->referer = strdup(data->url); data->change.referer = strdup(data->change.url);
data->free_referer = TRUE; /* yes, free this later */ data->change.referer_alloc = TRUE; /* yes, free this later */
data->bits.http_set_referer = TRUE; /* might have been false */
} }
if(2 != sscanf(newurl, "%15[^:]://%c", prot, &letter)) { if(2 != sscanf(newurl, "%15[^?&/:]://%c", prot, &letter)) {
/*** /***
*DANG* this is an RFC 2068 violation. The URL is supposed *DANG* this is an RFC 2068 violation. The URL is supposed
to be absolute and this doesn't seem to be that! to be absolute and this doesn't seem to be that!
@@ -964,7 +1033,7 @@ CURLcode Curl_perform(struct UrlData *data)
/* we must make our own copy of the URL to play with, as it may /* we must make our own copy of the URL to play with, as it may
point to read-only data */ point to read-only data */
char *url_clone=strdup(data->url); char *url_clone=strdup(data->change.url);
if(!url_clone) if(!url_clone)
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
@@ -1014,16 +1083,16 @@ CURLcode Curl_perform(struct UrlData *data)
port = FALSE; port = FALSE;
} }
if(data->bits.urlstringalloc) if(data->change.url_alloc)
free(data->url); free(data->change.url);
else
data->change.url_alloc = TRUE; /* the URL is allocated */
/* TBD: set the URL with curl_setopt() */ /* TBD: set the URL with curl_setopt() */
data->url = newurl; data->change.url = newurl;
newurl = NULL; /* don't free! */ newurl = NULL; /* don't free! */
data->bits.urlstringalloc = TRUE; /* the URL is allocated */ infof(data, "Follows Location: to new URL: '%s'\n", data->change.url);
infof(data, "Follows Location: to new URL: '%s'\n", data->url);
/* /*
* We get here when the HTTP code is 300-399. We need to perform * We get here when the HTTP code is 300-399. We need to perform
@@ -1031,7 +1100,7 @@ CURLcode Curl_perform(struct UrlData *data)
* Discussed on the curl mailing list and posted about on the 26th * Discussed on the curl mailing list and posted about on the 26th
* of January 2001. * of January 2001.
*/ */
switch(data->progress.httpcode) { switch(data->info.httpcode) {
case 300: /* Multiple Choices */ case 300: /* Multiple Choices */
case 301: /* Moved Permanently */ case 301: /* Moved Permanently */
case 306: /* Not used */ case 306: /* Not used */
@@ -1062,7 +1131,7 @@ CURLcode Curl_perform(struct UrlData *data)
case 303: /* See Other */ case 303: /* See Other */
/* Disable both types of POSTs, since doing a second POST when /* Disable both types of POSTs, since doing a second POST when
* following isn't what anyone would want! */ * following isn't what anyone would want! */
data->httpreq = HTTPREQ_GET; /* enforce GET request */ data->set.httpreq = HTTPREQ_GET; /* enforce GET request */
infof(data, "Disables POST, goes with GET\n"); infof(data, "Disables POST, goes with GET\n");
break; break;
case 304: /* Not Modified */ case 304: /* Not Modified */
@@ -1090,8 +1159,8 @@ CURLcode Curl_perform(struct UrlData *data)
if(newurl) if(newurl)
free(newurl); free(newurl);
/* make sure the alarm is switched off! */ /* make absolutely sure the alarm is switched off! */
if(data->timeout || data->connecttimeout) if(data->set.timeout || data->set.connecttimeout)
myalarm(0); myalarm(0);
return res; return res;
@@ -1125,3 +1194,10 @@ Curl_Transfer(struct connectdata *c_conn, /* connection data */
} }
/*
* local variables:
* eval: (load-file "../curl-mode.el")
* end:
* vim600: fdm=marker
* vim: et sw=2 ts=2 sts=2 tw=78
*/

View File

@@ -22,7 +22,7 @@
* *
* $Id$ * $Id$
*****************************************************************************/ *****************************************************************************/
CURLcode Curl_perform(struct UrlData *data); CURLcode Curl_perform(struct SessionHandle *data);
/* This sets up a forthcoming transfer */ /* This sets up a forthcoming transfer */
CURLcode CURLcode

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