Compare commits

..

207 Commits

Author SHA1 Message Date
Daniel Stenberg
ea409d0374 7.7-beta5 commit 2001-03-19 08:42:00 +00:00
Daniel Stenberg
eaaa1a1fd4 test case 39 added, HTTP location and continue 2001-03-19 08:36:08 +00:00
Daniel Stenberg
78b4851da1 Added support for HTTP code 100 continue, as 8.2.3 in RFC2616 defines 2001-03-19 07:47:57 +00:00
Daniel Stenberg
38c47803dd detect if chunked transfers are aborted 2001-03-16 15:45:12 +00:00
Daniel Stenberg
455663ba5e corrected the close to sclose() so that the memdebug stuff works 2001-03-16 15:44:38 +00:00
Daniel Stenberg
efb5d9a403 new directories 2001-03-16 15:22:51 +00:00
Daniel Stenberg
b1a5208e6b removed the CURL_SEPARATORS define 2001-03-16 15:21:26 +00:00
Daniel Stenberg
e6dacd92ec re-generated with the memdebug.h include 2001-03-16 15:20:36 +00:00
Daniel Stenberg
952b3a2c0f added memdebug.h include 2001-03-16 15:19:36 +00:00
Daniel Stenberg
721f9bca84 moved to ../../php/examples/ 2001-03-16 13:45:42 +00:00
Daniel Stenberg
ad4d5fabf8 the PHP examples are moved 2001-03-16 13:44:57 +00:00
Daniel Stenberg
aa860990ad fix the new makefiles in php/ and perl/ 2001-03-16 13:35:45 +00:00
Daniel Stenberg
0fa9135d9f use perl in two ways 2001-03-16 13:35:11 +00:00
Daniel Stenberg
8f0114a4dd Short about the perl interface 2001-03-16 13:34:08 +00:00
Daniel Stenberg
5980c2977b filled in 2001-03-16 13:30:56 +00:00
Daniel Stenberg
19f8d71508 for the php examples 2001-03-16 13:29:57 +00:00
Daniel Stenberg
6f3bccd911 PHP examples 2001-03-16 13:28:11 +00:00
Daniel Stenberg
96f81a5c4a new PHP section 2001-03-16 13:27:42 +00:00
Daniel Stenberg
ca05d1b59c a perl script that can be used to mirror all curl archives 2001-03-16 13:10:42 +00:00
Daniel Stenberg
895dc5e530 Added README for releases 2001-03-16 13:09:21 +00:00
Daniel Stenberg
bcc6ca6fd1 Added to build proper releases 2001-03-16 13:09:05 +00:00
Daniel Stenberg
d538241a58 Georg Horn's Curl::easy interface for perl 2001-03-16 13:05:39 +00:00
Daniel Stenberg
71b4b2ffa9 moved to contrib/ 2001-03-16 13:05:18 +00:00
Daniel Stenberg
65b4a63f56 moved here from ../ 2001-03-16 13:04:57 +00:00
Daniel Stenberg
ecbee01f4b moved the documentation item to 7.8, it is rather important to have things
documented
2001-03-15 14:45:03 +00:00
Daniel Stenberg
34fed76a35 updated to have the windows builds instructions use the root Makefile that
is delivered with each source archive
2001-03-15 14:44:01 +00:00
Daniel Stenberg
0adf0cfde7 connection timeouts added 2001-03-15 14:38:54 +00:00
Daniel Stenberg
d6c456db85 added connect timeout support 2001-03-15 14:38:30 +00:00
Daniel Stenberg
36c88343d3 Added --connect-timeout support 2001-03-15 14:38:03 +00:00
Daniel Stenberg
2360e5ce12 Added CURLOPT_CONNECTTIMEOUT 2001-03-15 14:37:41 +00:00
Daniel Stenberg
d445eac162 connection timeout is now supported 2001-03-15 14:37:17 +00:00
Daniel Stenberg
e0a6d20e20 Jrn's win32-fix to make it work better 2001-03-15 12:34:40 +00:00
Daniel Stenberg
3bb979b897 corrected it, did I mention IPv6 with HTTP proxy? 2001-03-15 09:14:43 +00:00
Daniel Stenberg
010daec776 Put more concentrated unix install help already at the top, with a note that
you might need to be root to use 'make install'.
2001-03-15 08:38:15 +00:00
Daniel Stenberg
e2b0ad8429 added some text for -d that says it "emulates filling in HTML forms" as that
is what most people will use -d for
2001-03-14 19:48:29 +00:00
Daniel Stenberg
6eed95103a ipv6 adjustments 2001-03-14 18:26:54 +00:00
Daniel Stenberg
4eb2a165e8 removed a bunch of warnings for IPv6-compiles 2001-03-14 18:24:07 +00:00
Daniel Stenberg
b7fc1e45b5 now works with IPv6 and HTTP proxy 2001-03-14 18:18:02 +00:00
Daniel Stenberg
3395a2fa9e netrc fix 2001-03-14 16:59:49 +00:00
Daniel Stenberg
a564a54e21 hm, don't free the home dir and append the .netrc part properly 2001-03-14 16:12:47 +00:00
Daniel Stenberg
92186dc3d3 checks for a few functions and include files more for the new getpwuid()
stuff in lib/netrc.c
2001-03-14 16:05:31 +00:00
Daniel Stenberg
7bd6507eec uses getpwuid() to find user's home dir 2001-03-14 16:05:00 +00:00
Daniel Stenberg
d4cc810de3 added a missing \ 2001-03-14 14:35:35 +00:00
Daniel Stenberg
bea7bbee1b always append the incoming request to the server.input file, it allows
the mainscript to verify a whole series of requests
2001-03-14 14:26:56 +00:00
Daniel Stenberg
fe64570d5d updated to work with the modified http server 2001-03-14 14:26:16 +00:00
Daniel Stenberg
df6ad8d8d6 Added test case 38 2001-03-14 14:25:57 +00:00
Daniel Stenberg
f8e1fc32de Edin Kadribaic's bug report #408488 forced a rearrange of two struct fields
from urldata to connectdata, quite correctly.
2001-03-14 14:11:11 +00:00
Daniel Stenberg
8c6d56f1f9 Added the --egd-file and --random-file options 2001-03-14 11:47:55 +00:00
Daniel Stenberg
1841c8ee6a curl 7.7 beta 3 2001-03-14 11:25:44 +00:00
Daniel Stenberg
70793595fe removed the two unnecessary include files 2001-03-14 10:27:13 +00:00
Daniel Stenberg
28a8e1602d ssluse fixed, various win32 fixes 2001-03-14 10:21:52 +00:00
Daniel Stenberg
cce05b9138 Bjrn Stenberg corrected the silly '(void)data' usage when SSL is not
used
2001-03-14 10:15:42 +00:00
Daniel Stenberg
72a7fd4dc7 Jrn's updated file 2001-03-14 10:06:23 +00:00
Daniel Stenberg
9a6a476cf5 the URL escape/unescape functions are also public but undocumented 2001-03-14 08:59:34 +00:00
Daniel Stenberg
5d0efedd2d First Jrn's updates were applied, then
my take at removing the private functions from the list, then I renamed
the *str(n)equal functions...
2001-03-14 08:58:36 +00:00
Daniel Stenberg
a426818a78 no longer includes the curl/types.h and curl/easy.h include files
explicitly, as they're taken care of indirectly by curl/curl.h these
days.
2001-03-14 08:55:17 +00:00
Daniel Stenberg
bfe413d8bd increased the 'current' number for the interface 2001-03-14 08:54:18 +00:00
Daniel Stenberg
dbbd20646f Curl_str(n)equal renamed to curl_str(n)equal 2001-03-14 08:53:31 +00:00
Daniel Stenberg
b8fe4deb13 documented the undocumented public functions in libcurl 2001-03-14 08:51:04 +00:00
Daniel Stenberg
332a016e3c chunked bugfix, Jrn's fixes, the interface number increase 2001-03-14 08:49:11 +00:00
Daniel Stenberg
3738e4bdc0 The Curl_* prefixes are now changed for curl_* ones, as these two functions
are used externally and thus are public symbols.
2001-03-14 08:47:56 +00:00
Daniel Stenberg
3201d2dafa Jrn added "#define socklen_t int" 2001-03-14 08:28:54 +00:00
Daniel Stenberg
0a1e002ca4 Jrn fixed it to compile on win32 again 2001-03-14 08:28:19 +00:00
Daniel Stenberg
9195bb64d4 Jrn Hartroth added a set of files 2001-03-14 08:23:51 +00:00
Daniel Stenberg
11ee547a0e Jrn Hartroth fixed a bad #endif placement 2001-03-14 08:20:41 +00:00
Daniel Stenberg
147de35d41 re-added the default switch for weird states 2001-03-13 23:29:53 +00:00
Daniel Stenberg
e16e9b91ae removed the random seeding and persistant stuff, as both are already in
this version!
2001-03-13 22:31:56 +00:00
Daniel Stenberg
f9cde0646f Added a failf() error message when the chunked read returns failure 2001-03-13 22:20:14 +00:00
Daniel Stenberg
195233ed5c updated the chunked state-machine to deal with the trailing CRLF that comes
after the data part
2001-03-13 22:16:42 +00:00
Daniel Stenberg
048e654514 made 'X to Y' sequences not include X twice 2001-03-13 22:14:53 +00:00
Daniel Stenberg
dfbd45142d corrected the chunked format 2001-03-13 22:13:06 +00:00
Daniel Stenberg
ff681f7bfd 7.7 beta 2 fixes 2001-03-13 15:44:31 +00:00
Daniel Stenberg
60bbb64a81 EXTRA_DIST got too long, I shortened it now but we have to do something
else as it will grow a lot more...
2001-03-13 13:31:14 +00:00
Daniel Stenberg
c622f2bb4e failf() now respects the mute flag 2001-03-13 13:22:58 +00:00
Daniel Stenberg
cd59f13da6 Guenole Bescon's bug found on march 8 is added 2001-03-13 13:14:21 +00:00
Daniel Stenberg
11d718bf52 exchanged I and me to we and us in a lot of places
updated for persistant connections and 7.7
2001-03-13 11:47:30 +00:00
Daniel Stenberg
8e8846d876 Added test case 37, HTTP GET with name+password in the URL 2001-03-13 09:44:09 +00:00
Daniel Stenberg
7d562bb685 a whole new section on persitant connections and how they're treated
internally
2001-03-13 08:16:54 +00:00
Daniel Stenberg
20ddd35669 we speak HTTP 1.1 now
more braging about the portability
2001-03-13 08:16:25 +00:00
Daniel Stenberg
063f88cd14 close policies 2001-03-13 07:59:19 +00:00
Daniel Stenberg
87b0b7cab9 initial close policy support 2001-03-13 07:54:18 +00:00
Daniel Stenberg
70d0d9d4da Added 'created' to the connectdata struct to hold the creation date, to
be used for the close policy decision
2001-03-13 07:53:59 +00:00
Daniel Stenberg
4ae3bd71ea Curl_tvnow is now properly declared with (void) 2001-03-13 07:53:06 +00:00
Daniel Stenberg
a9390665b8 curl_getinfo is removed, not a public function 2001-03-13 07:46:19 +00:00
Daniel Stenberg
fb7a6e3423 added --random-file and --egd-file to the command line client 2001-03-12 16:02:29 +00:00
Daniel Stenberg
cc99e3f7de Added the two new seeding options 2001-03-12 15:52:18 +00:00
Daniel Stenberg
e6b40bb6ac two new random seed options for the ssl config struct 2001-03-12 15:47:41 +00:00
Daniel Stenberg
f2fd1b8856 two new random seed options: CURLOPT_RANDOM_FILE and CURLOPT_EGDSOCKET 2001-03-12 15:47:17 +00:00
Daniel Stenberg
cb4efcf275 better chunked error detection 2001-03-12 15:29:04 +00:00
Daniel Stenberg
56a27d608a Added test case 36:
[HTTP GET with badly formatted chunked Transfer-Encoding]
2001-03-12 15:27:01 +00:00
Daniel Stenberg
46c9075eab updated the comment for the chunked reading 2001-03-12 15:21:11 +00:00
Daniel Stenberg
d95fa648e9 made it return illegal hex in case no hexadecimal digit was read when at
least one was expected
2001-03-12 15:20:35 +00:00
Daniel Stenberg
563ad213dc added an error code for illegal hex values in the chunked stream 2001-03-12 15:20:02 +00:00
Daniel Stenberg
0121d7d731 Added new libcurl options in include/curl/curl.h, they're documented in
curl_easy_setopt.3 and they're partly implemented in lib/url.c

Slowly, we're getting there...
2001-03-12 15:11:38 +00:00
Daniel Stenberg
8495fac1c5 Added options for the persistant support, they're also documented in
curl_easy_setopt.3 now
2001-03-12 15:06:29 +00:00
Daniel Stenberg
38c349f751 support for a few new libcurl 7.7 CURLOPT_* options added 2001-03-12 15:05:54 +00:00
Daniel Stenberg
542df800ab Added four new options that come with the new persitant support:
CURLOPT_MAXCONNECTS, CURLOPT_CLOSEPOLICY, CURLOPT_FRESH_CONNECT and
CURLOPT_FORBID_REUSE
2001-03-12 14:54:00 +00:00
Daniel Stenberg
3e88b1cac5 the client is adjusted to work with persistant curl handles, and *gee* it
seems to be working!!!
2001-03-12 13:59:38 +00:00
Daniel Stenberg
d774b10afb Added infof() calls for persistant connection info, we are very likely to
need these at least for debugging 7.7 and probably later as well...
2001-03-12 13:58:03 +00:00
Daniel Stenberg
b449b94393 moved the libcurl init call 2001-03-12 13:57:02 +00:00
Daniel Stenberg
a6cb9b08b2 persistant updates 2001-03-12 13:55:06 +00:00
Daniel Stenberg
440a3101d0 added a note about persitant connections through HTTP proxies 2001-03-12 13:54:46 +00:00
Daniel Stenberg
9778a5356b Added some persistant notes 2001-03-12 13:54:10 +00:00
Daniel Stenberg
de7dcdbc54 modified to make the curl client with persistant connection support do
correct
2001-03-12 13:47:07 +00:00
Daniel Stenberg
070968abbc include the failed test case numbers in the end summary 2001-03-12 13:46:23 +00:00
Daniel Stenberg
e97fc2aab5 Added description of the new test case ranges support 2001-03-12 12:58:57 +00:00
Daniel Stenberg
a23ac24192 made it support test case ranges on the command line, specified as
"X to Y", where X is smaller than Y.
2001-03-12 12:58:30 +00:00
Daniel Stenberg
9ee14644a7 adjusted to work with the HTTP 1.1-speaking libcurl 2001-03-12 12:45:12 +00:00
Daniel Stenberg
c576e114b9 output the protocol data to stderr when verbose is on 2001-03-12 12:44:44 +00:00
Daniel Stenberg
639a7982ba server problems,
libcurl *works* persistant over HTTP proxy!!!!
2001-03-12 10:18:01 +00:00
Daniel Stenberg
5bbe189420 modified Curl_disconnect() so that it unlinks itself from the data struct,
it saves me from more mistakes when the connectindex is -1 ... also, there's
no point in having its parent do it as all parents would do it anyway.
2001-03-12 10:13:42 +00:00
Daniel Stenberg
93ff159e32 split up the big printf() into several ones to never use strings longer
than 509 letters (as newer gcc warns on with -Wall)
2001-03-12 09:47:23 +00:00
Daniel Stenberg
8eb8a0a8e4 bugfix: don't use the connectindex if it is -1 2001-03-12 09:44:57 +00:00
Daniel Stenberg
a4af638867 added persistant connection details 2001-03-12 09:44:08 +00:00
Daniel Stenberg
75a9a87ec2 replaced I and my with we and us 2001-03-12 09:43:43 +00:00
Daniel Stenberg
b5ba011110 updated 2001-03-12 09:42:22 +00:00
Daniel Stenberg
e9b763ff05 use the new name and hostname even though an old connection is reused, since
we can re-use a proxy connection that actually has different host names on
the same connection
2001-03-09 16:50:08 +00:00
Daniel Stenberg
ac0bad2433 remake Host: for each connection and it'll work with proxies too 2001-03-09 16:48:18 +00:00
Daniel Stenberg
67d5c0a970 for HTTP/1.0 we default to non keep-alive connections, but when we get a
1.0-reply from a proxy we use and the Proxy-Connection: keep-alive header
is used, we switch it on and live happily ever after
2001-03-09 16:02:59 +00:00
Daniel Stenberg
580896d615 Added httpversion to the progress struct, we do read it, we can just as well
store it.
2001-03-09 15:58:36 +00:00
Daniel Stenberg
11693c0faa the socklen_t check is more involved now, but works on linux at least 2001-03-09 15:38:59 +00:00
Daniel Stenberg
26cd8eda4a Added socklen_t 2001-03-09 15:24:33 +00:00
Daniel Stenberg
8cd3f44040 added a check for socklen_t
removed the tiny/Makefile that was added accidentaly before
2001-03-09 15:21:00 +00:00
Daniel Stenberg
2b30bfc349 all comments for the former public "low level" interface have been removed
since they were out-of-date and not correct anymore.

moved around some struct fields
2001-03-09 15:19:42 +00:00
Daniel Stenberg
8ec4dba599 removed handles and states from the main structs
renamed prefixes from curl_ to Curl_
made persistant connections work with http proxies (at least partly)
2001-03-09 15:18:25 +00:00
Daniel Stenberg
1efec6572e curl_transfer became Curl_perform() to better match the public name and
use the correct prefix
2001-03-09 15:17:09 +00:00
Daniel Stenberg
781dd7a9bf prefix changes curl_ to Curl_
made it work (partly) with persistant connections for HTTP/1.0 replies
moved the 'newurl' struct field for Location: to the connectdata struct
2001-03-09 15:16:28 +00:00
Daniel Stenberg
beb8761b22 #include <string.h> removed a warning 2001-03-09 15:14:51 +00:00
Daniel Stenberg
071c7de9fe removed curl_read() and curl_write() - they weren't used and the public
"low leve" interface is dumped
2001-03-09 15:14:22 +00:00
Daniel Stenberg
3e7ebcd051 uses socklen_t now 2001-03-09 15:13:34 +00:00
Daniel Stenberg
c67952fc5c curl_ prefix modified to Curl_ 2001-03-09 15:13:11 +00:00
Daniel Stenberg
7d7c24f915 accept() and getsockname() now use socklen_t types, as that was just added
to configure
2001-03-09 15:12:22 +00:00
Daniel Stenberg
0dc8c4d451 use unsigned int hex to receive the hex digit in, caused a warning with
-Wall and a new gcc
2001-03-09 15:11:39 +00:00
Daniel Stenberg
9cf4434ae2 Modified to use Curl_* functions instead of curl_* ones 2001-03-09 15:10:58 +00:00
Daniel Stenberg
8ccd8b6dbc only generate maximum 509 characters in each string 2001-03-09 13:11:28 +00:00
Daniel Stenberg
b4f70aa2c8 version 7.7-beta1 2001-03-08 12:35:51 +00:00
Daniel Stenberg
f54a282ccc persistant adjusts 2001-03-08 12:32:03 +00:00
Daniel Stenberg
2a11bdc216 HTTP HEAD tests 2001-03-08 10:39:36 +00:00
Daniel Stenberg
5cd4c3ed24 return from transfer when all headers have been received and nobody is set,
as is the case when doing HEAD requests
2001-03-08 10:32:27 +00:00
Daniel Stenberg
147a673063 updated for persistant connections 2001-03-08 09:25:09 +00:00
Daniel Stenberg
9ce5827fc1 made it split the version number on - too to make 7.7-blabla make a better
version number define in the header file
2001-03-08 09:23:11 +00:00
Daniel Stenberg
97f1c93674 added lots of numbers for the error codes as they're often printed
and used
2001-03-08 09:04:43 +00:00
Daniel Stenberg
e61ceaf1bd clarified the 0001-files use a bit, I couldn't understand it myself! :-) 2001-03-08 08:33:17 +00:00
Daniel Stenberg
1118612249 Added test #34 - HTTP GET with chunked Transfer-Encoding 2001-03-08 08:30:35 +00:00
Daniel Stenberg
a23db7b7c7 "Transfer-Encoding: chunked" support added 2001-03-07 23:51:41 +00:00
Daniel Stenberg
f6b6dff46a added the http_chunks files 2001-03-07 23:50:00 +00:00
Daniel Stenberg
55b8ceac18 chunked transfer encoding support 2001-03-07 23:28:22 +00:00
Daniel Stenberg
bcf448ee32 connection timeout is in for 7.7 2001-03-07 23:24:23 +00:00
Daniel Stenberg
91e4da7ddb initial chunked transfer-encoding support 2001-03-07 17:12:12 +00:00
Daniel Stenberg
2873c18132 removed compiler warning if HAVE_RAND_STATUS is false 2001-03-07 17:08:20 +00:00
Daniel Stenberg
5dd0a8a63e Added persistant connections blurb even if it doesn't really work yet... 2001-03-06 14:37:37 +00:00
Daniel Stenberg
2103dc41f5 cleaned up for the 7.7 fixes 2001-03-06 12:50:42 +00:00
Daniel Stenberg
2ef13230cb new seeding stuff as mentioned by Albert Chin 2001-03-06 00:04:58 +00:00
Daniel Stenberg
9479ac6dda Added a persistant connection example 2001-03-05 16:56:10 +00:00
Daniel Stenberg
4e878eae79 updated to libcurl 7.7 conditions 2001-03-05 15:51:34 +00:00
Daniel Stenberg
1e8e90a220 mucho updated with new 7.7 concepts 2001-03-05 15:38:06 +00:00
Daniel Stenberg
fe95c7dc34 removed an incorrect comment 2001-03-05 14:52:23 +00:00
Daniel Stenberg
6dae34d5da all test cases run OK now (again) 2001-03-05 14:13:15 +00:00
Daniel Stenberg
36c621c9df more details on debugging with the test suite 2001-03-05 14:08:22 +00:00
Daniel Stenberg
1717963e3d show the ftp server invoke line when -d is used 2001-03-05 14:03:48 +00:00
Daniel Stenberg
4646a1ffa9 talks more on verbose 2001-03-05 14:03:20 +00:00
Daniel Stenberg
0cb4eba002 free the struct on done 2001-03-05 14:01:13 +00:00
Daniel Stenberg
5eba359b5d telnet without any static variables 2001-03-05 13:59:43 +00:00
Daniel Stenberg
07ce7539a8 set download size properly for HTTP downloads 2001-03-05 13:40:31 +00:00
Daniel Stenberg
c21f848c1c enable persistant connections by default 2001-03-05 13:40:08 +00:00
Daniel Stenberg
84e94fda8b remade FILE:// support to look more as the other protocols 2001-03-05 13:39:01 +00:00
Daniel Stenberg
ebd6897b10 runtests -g explained 2001-03-04 18:11:25 +00:00
Daniel Stenberg
5ab8a9d32f persistant support protocol updates 2001-03-04 18:07:13 +00:00
Daniel Stenberg
cf8704ccdf 7.7 alpha 2 commit 2001-03-04 16:34:20 +00:00
Daniel Stenberg
5543c2f11f Added include of easy.h to enable libcurl-using programs to *only* have to
include <curl/curl.h>
2001-03-04 15:32:44 +00:00
Daniel Stenberg
90ac37a683 Curl_http() could crash on connection re-use 2001-03-04 15:25:54 +00:00
Daniel Stenberg
dd893fd8a4 ipv6 fix for the 'port' no longer in urldata 2001-03-03 17:50:01 +00:00
Daniel Stenberg
834f079918 fixed for persistant stuff 2001-03-03 16:28:59 +00:00
Daniel Stenberg
2665c763df latest 2001-03-02 15:38:06 +00:00
Daniel Stenberg
d1cfbd51b5 remade the port number stuff so that following locations work and doing
intermixed HTTP and FTP persistant connections also work!
2001-03-02 15:34:15 +00:00
Daniel Stenberg
a3ba6b7a6a Added the disconnect proto 2001-03-02 07:44:22 +00:00
Daniel Stenberg
415d2e7cb7 removed the slist -functions from here
added the Curl_ftp_disconnect function for FTP-specific disconnects
2001-03-02 07:44:05 +00:00
Daniel Stenberg
af4451ec26 improved connections 2001-03-02 07:43:20 +00:00
Daniel Stenberg
7c6562683a extending connectdata 2001-03-02 07:42:35 +00:00
Daniel Stenberg
b6fa2f882c moved the slist-functions here from FTP since they're more generic than simply
for FTP-stuff
2001-03-02 07:42:11 +00:00
Daniel Stenberg
b6c5da337a strdup() takes a const char * now 2001-03-02 07:41:40 +00:00
Daniel Stenberg
9bc24e4876 cleanup better when connects fail 2001-02-28 14:03:46 +00:00
Daniel Stenberg
4af55809e4 added some infof() calls for persistant info 2001-02-22 23:51:17 +00:00
Daniel Stenberg
9c63fcf210 we only allocate the HTTP struct if we need to 2001-02-22 23:41:15 +00:00
Daniel Stenberg
1f17fb5f89 Now persistant connection download works thanks to the Content-Length taken
into account
2001-02-22 23:32:41 +00:00
Daniel Stenberg
584dbffe60 moved the dynamicly set pointers to the connectdata struct 2001-02-22 23:32:02 +00:00
Daniel Stenberg
1c6f6f6972 Douglas R. Horner's corrections applied 2001-02-22 22:33:49 +00:00
Daniel Stenberg
da06a6e7e3 IPv6-adjustments 2001-02-21 17:15:09 +00:00
Daniel Stenberg
46e0937263 corrected memory leaks when re-using connections 2001-02-20 17:46:35 +00:00
Daniel Stenberg
a1d6ad2610 multiple connection support initial commit 2001-02-20 17:35:51 +00:00
Daniel Stenberg
5f3d63ed5b bugfix 2001-02-20 13:58:56 +00:00
Daniel Stenberg
63b5748eb6 -g runs the specified test(s) with gdb! 2001-02-20 13:58:39 +00:00
Daniel Stenberg
e2590430c5 removed the #ifdef 2001-02-20 13:57:50 +00:00
Daniel Stenberg
ada9bc2b24 win32sockets.c is now added with winsock init/cleanup example functions 2001-02-20 13:56:38 +00:00
Daniel Stenberg
43da41e73e Added three tiny PHP examples 2001-02-19 13:39:21 +00:00
Daniel Stenberg
720fa45b56 blurb about different languages and environments added 2001-02-19 13:38:29 +00:00
Daniel Stenberg
7de874c438 just a few PHP/curl examples 2001-02-19 13:38:05 +00:00
Daniel Stenberg
2078c1a01a added two VC++ files for project stuff 2001-02-19 09:29:40 +00:00
Daniel Stenberg
f7a8909372 Made CURLOPT_POST no longer necessary when CURLOPT_POSTFIELDS is used 2001-02-19 09:29:19 +00:00
Daniel Stenberg
250df30e64 Moved a bunch of prototypes from curl.h here, they're no longer public and
I merely stuffed them here before I decide where they belong and if they
are to remain at all
2001-02-19 09:28:10 +00:00
Daniel Stenberg
b887cf7521 removed a bunch of "low level" functions that were never used and are about
to never become reality either
2001-02-19 09:27:12 +00:00
Daniel Stenberg
630e932091 MS VC++ stuff 2001-02-19 09:26:29 +00:00
Daniel Stenberg
cdabd67aa9 Bob Schader updated this 2001-02-19 09:26:01 +00:00
Daniel Stenberg
42e4f9d776 added stuff to the mailing list chapter 2001-02-19 09:25:18 +00:00
Daniel Stenberg
c111033595 removed --continue task (done)
added URL to the NTLM task
2001-02-16 13:41:34 +00:00
Daniel Stenberg
26d1aaccdf 2.2 - rephrased 2001-02-16 13:41:09 +00:00
Daniel Stenberg
ce95d2020f better english timeouted => timed out, as suggested by Larry Fahnoe 2001-02-13 21:57:04 +00:00
198 changed files with 6533 additions and 3092 deletions

253
CHANGES
View File

@@ -6,6 +6,259 @@
History of Changes History of Changes
Version 7.7-beta5
Daniel (19 March 2001)
- Georg Ottinger reported problems with using -C together with -L in the sense
that the -C info got lost when it was redirected. I could not repeat this
problem on the 7.7 branch why I leave this for the moment. Test case 39 was
added to do exactly this, and it seems to do right.
- Christian Robottom Reis reported how his 7.7 beta didn't successfully do
form posts as elegantly as 7.6.1 did. Indeed, this was a flaw in the header
engine, as HTTP 1.1 has introduced a new 100 "transient" return code for PUT
and POST operations that I need to add support for. Section 8.2.3 in RFC2616
has all the details. Seems to work now!
Daniel (16 March 2001)
- After having experienced another machine break-down, we're back.
- Georg Horn's perl interface Curl::easy is now included in the curl release
archive. The perl/ directory is now present. Please help me with docs,
examples and updates you think fit.
- Made a new php/ directory in the release archive and moved the PHP examples
into a subdirectory in there. Not much PHP info yet, but I plan to. Please
help me here as well!
- Made libcurl return error if a transfer is aborted in the middle of a
"chunk". It actually enables libcurl to discover premature transfer aborts
even if the Content-Length: size is unknown.
Daniel (15 March 2001)
- Added --connect-timeout to curl, which sets the new CURLOPT_CONNECTTIMEOUT
option in libcurl. It limits the time curl is allowed to spend in the
connection phase. This differs from -m/--max-time that limits the entire
file transfer operation. Requested by Larry Fahnoe and others.
I also updated the curl.1 and curl_easy_setopt.3 man pages and removed the
item from the TODO.
Version 7.7-beta4
Daniel (14 March 2001)
- Made curl grok IPv6 with HTTP proxies and got everything to compile nicely
again when ENABLE_IPV6 is set.
I need to remake things in the test suite. I can't test the FTP parts with
curl built for IPv6 as it uses a different set of FTP commands then!
- I fell onto a bug report on php.net (posted by Lars Torben Wilson) that was
a report meant for our project. Anyway, it said the .netrc parsing didn't
work as supposed, and as I agreed with Lars, I made the netrc parser use
getpwuid() to figure out the home directory of the effective user and try
that netrc. It still uses the environment variable HOME for those that don't
have that function or if the user doesn't return valid pwd info.
- Edin Kadribaic posted a bug report where he got a crash when a fetch with
user+password in the URL followed a Location: to a second URL (absolute,
without name+password). This bug has been around for a long while and
crashes due to a read at address zero. Fixed now. Wrote test case 38, that
tests this.
- Modified the test suite's httpserver slightly to append all client request
data to its log file so that the test script now better can verify a range
of requests and not only the last one, as it did previously.
- Updated the curl man page with --random-file and --egd-file details.
Version 7.7-beta3
Daniel (14 March 2001)
- Bj<42>rn Stenberg provided similar fixes as J<>rn did and some additional patches
for non-SSL compiles.
- I increased the interface number for libcurl as I've removed the low level
functions from the interface. I also took this opportunity to rename the
Curl_strequal function to curl_strequal and Curl_strnequal to
curl_strnequal, as they're public libcurl functions (even if they're still
undocumented).
This will make older programs not capable of using the new libcurl with
just a drop-in replacement.
- J<>rn Hartroth updated stuff for win32 compiles:
o config-win32.h was fixed for socklen_t
o lib/ssluse.c had a bad #endif placement
o lib/file.c was made to compile on win32 again
o lib/Makefile.m32 was updated with the new files
o lib/libcurl.def matches the current interface state
Daniel (13 March 2001)
- It only took an hour or so before J<>rn Hartroth found a problem in the
chunked transfer-encoding. Given his fine example-site, I could easily spot
the problem and when I re-read the spec (the part I have pasted in the top
of the http_chunks.h file), I realized I had made my state-machine slightly
wrong and didn't expect/handle the trailing CRLF that comes after the data
in each chunk (and those extra two bytes sure feel wasted).
Had to modify test case 34 to match this as well.
Version 7.7-beta2
Daniel (13 March 2001)
- Added the policy stuff to the curl_easy_setopt man page for the two supported
policies.
- Implemented some support for the CURLOPT_CLOSEPOLICY option. The policies
CURLCLOSEPOLICY_LEAST_RECENTLY_USED and CURLCLOSEPOLICY_OLDEST are now
supported, and the "least recently used" is used as default if no policy
is chosen.
Daniel (12 March 2001)
- Added CURLOPT_RANDOM_FILE and CURLOPT_EGDSOCKET to libcurl for seeding the
SSL random engine. The random seeding support was also brought to the curl
client with the new options --random-file <file> and --egd-file <file>. I
need some people to really test this to know they work as supposed. Remember
that libcurl now informs (if verbose is on) if the random seed is considered
weak (HTTPS connections).
- Made the chunked transfer-encoding engine detected bad formatted data length
and return error if so (we can't possibly extract sensible data if this is
the case). Added a test case that detects this. Number 36. Now there are 60
test cases.
- Added 5 new libcurl options to curl/curl.h that can be used to control the
persistant connection support in libcurl. They're also documented (fairly
thoroughly) in the curl_easy_setopt.3 man page. Three of them are now
implemented, although not really tested at this point... Anyway, the new
implemented options are named CURLOPT_MAXCONNECTS, CURLOPT_FRESH_CONNECT,
CURLOPT_FORBID_REUSE. The ones still left to write code for are:
CURLOPT_CLOSEPOLICY and its related option CURLOPT_CLOSEFUNCTION.
- Made curl (the actual command line tool) use the new libcurl 7.7 persistant
connection support by re-using the same curl handle for every specified file
transfer and after some more test case tweaking we have 100% test case OK.
I made some test cases return HTTP/1.0 now to make sure that works as well.
- Had to add 'Connection: close' to the headers of a bunch of test cases so
that curl behaves "old-style" since the test http server doesn't do multiple
connections... Now I get 100% test case OK.
- The curl.haxx.se site, the main curl mailing list and my personal email are
all dead today due to power blackout in the area where the main servers are
located. Horrible.
- I've made persistance work over a squid HTTP proxy. I find it disturbing
that it uses headers that aren't present in any HTTP standard though
(Proxy-Connection:) and that makes me feel that I'm now on the edge of what
the standard actually defines. I need to get this code excercised on a lot
of different HTTP proxies before I feel safe.
Now I'm facing the problem with my test suite servers (both FTP and HTTP)
not supporting persistant connections and libcurl is doing them now. I have
to fix the test servers to get all the test cases do OK.
Daniel (8 March 2001)
- Guenole Bescon reported that libcurl did output errors to stderr even if
MUTE and NOPROGRESS was set. It turned out to be a bug and happens if
there's an error and no ERRORBUFFER is set. This is now corrected.
Version 7.7-beta1
Daniel (8 March 2001)
- "Transfer-Encoding: chunked" is no longer any trouble for libcurl. I've
added two source files and I've run some test downloads that look fine.
- HTTP HEAD works too, even on 1.1 servers.
Daniel (5 March 2001)
- The current 57 test cases now pass OK. It would suggest that libcurl works
using the old-style with one connection per handle. The test suite doesn't
handle multiple connections yet so there are no test cases for this.
- I patched the telnet.c heavily to not use any global variables anymore. It
should make it a lot nicer library-wise.
- The file:// support was modified slightly to use the internal connect-first-
then-do approach.
Daniel (4 March 2001)
- More bugs erased.
Version 7.7-alpha2
Daniel (4 March 2001)
- Now, there's even a basic check that a re-used connection is still alive
before it is assumed so. A few first tests have proven that libcurl will
then re-connect instead of re-use the dead connection!
Daniel (2 March 2001)
- Now they work intermixed as well. Major coolness!
- More fiddling around, my 'tiny' client I have for testing purposes now has
proved to download both FTP and HTTP with persistant connections. They do
not work intermixed yet though.
Daniel (1 March 2001)
- Wilfredo Sanchez pointed out a minor spelling mistake in a man page and that
curl_slist_append() should take a const char * as second argument. It does
now.
Daniel (22 February 2001)
- The persistant connections start to look good for HTTP. On a subsequent
request, it seems that libcurl now can pick an already existing connection
if a suitable one exists, or it opens a new one.
- Douglas R. Horner mailed me corrections to the curl_formparse() man page
that I applied.
Daniel (20 February 2001)
- Added the docs/examples/win32sockets.c file for our windows friends.
- Linus Nielsen Feltzing provided brand new TELNET functionality and
improvements:
* Negotiation is now passive. Curl does not negotiate until the peer does.
* Possibility to set negotiation options on the command line, currently only
XDISPLOC, TTYPE and NEW_ENVIRON (called NEW_ENV).
* Now sends the USER environment variable if the -u switch is used.
* Use -t to set telnet options (Linus even updated the man page, awesome!)
- Haven't done this big changes to curl for a while. Moved around a lot of
struct fields and stuff to make multiple connections get connection specific
data in separate structs so that they can co-exist in a nice way. See the
mailing lists for discussions around how this is gonna be implemented. Docs
and more will follow.
Studied the HTTP RFC to find out better how persistant connections should
work. Seems cool enough.
Daniel (19 February 2001)
- Bob Schader brought me two files that help set up a MS VC++ libcurl project
easier. He also provided me with an up-to-date libcurl.def file.
- I moved a bunch of prototypes from the public <curl/curl.h> file to the
library private urldata.h. This is because of the upcoming changes. The
low level interface is no longer being planned to become reality.
Daniel (15 February 2001)
- CURLOPT_POST is not required anymore. Just setting the POST string with
CURLOPT_POSTFIELDS will switch on the HTTP POST. Most other things in
libcurl already works this way, i.e they require only the parameter to
switch on a feature so I think this works well with the rest. Setting a NULL
string switches off the POST again.
- Excellent suggestions from Rich Gray, Rick Jones, Johan Nilsson and Bjorn
Reese helped me define a way how to incorporate persistant connections into
libcurl in a very smooth way. If done right, no change may have to be made
to older programs and they will just start using persistant connections when
applicable!
Daniel (13 February 2001)
- Changed the word 'timeouted' to 'timed out' in two different error messages.
Suggested by Larry Fahnoe.
Version 7.6.1 Version 7.6.1
Daniel (9 February 2001) Daniel (9 February 2001)

View File

@@ -10,7 +10,7 @@ memanalyze.pl is for analyzing the output generated by curl if -DMALLOCDEBUG
Makefile.dist is included as the root Makefile in distribution archives Makefile.dist is included as the root Makefile in distribution archives
perl/ is a subdirectory with various perl scripts perl/contrib/ is a subdirectory with various perl scripts
To build after having extracted everything from CVS, do this: To build after having extracted everything from CVS, do this:

View File

@@ -8,7 +8,7 @@ EXTRA_DIST = \
CHANGES LEGAL maketgz MITX.txt MPL-1.1.txt \ CHANGES LEGAL maketgz MITX.txt MPL-1.1.txt \
config-win32.h reconf packages/README Makefile.dist config-win32.h reconf packages/README Makefile.dist
SUBDIRS = docs lib src include tests packages SUBDIRS = docs lib src include tests packages perl php
# create a root makefile in the distribution: # create a root makefile in the distribution:
dist-hook: dist-hook:

View File

@@ -30,16 +30,16 @@ ssl:
make make
borland: borland:
cd lib; make -f Makefile.b32 cd lib & make -f Makefile.b32
cd src; make -f Makefile.b32 cd src & make -f Makefile.b32
mingw32: mingw32:
cd lib; make -f Makefile.m32 cd lib & make -f Makefile.m32
cd src; make -f Makefile.m32 cd src & make -f Makefile.m32
mingw32-ssl: mingw32-ssl:
cd lib; make -f Makefile.m32 SSL=1 cd lib & make -f Makefile.m32 SSL=1
cd src; make -f Makefile.m32 SSL=1 cd src & make -f Makefile.m32 SSL=1
vc: vc:
cd lib cd lib

View File

@@ -43,3 +43,11 @@
/* Define this to 'int' if ssize_t is not an available typedefed type */ /* Define this to 'int' if ssize_t is not an available typedefed type */
#undef ssize_t #undef ssize_t
/* Define this to 'int' if socklen_t is not an available typedefed type */
#undef socklen_t
/* Define this as a suitable file to read random data from */
#undef RANDOM_FILE
/* Define this to your Entropy Gathering Daemon socket pathname */
#undef EGD_SOCKET

View File

@@ -26,6 +26,9 @@
/* Define this to 'int' if ssize_t is not an available typedefed type */ /* Define this to 'int' if ssize_t is not an available typedefed type */
#define ssize_t int #define ssize_t int
/* Define this to 'int' if socklen_t is not an available typedefed type */
#define socklen_t int
/* Define if you have the ANSI C header files. */ /* Define if you have the ANSI C header files. */
#define STDC_HEADERS 1 #define STDC_HEADERS 1

View File

@@ -391,6 +391,36 @@ AC_CHECK_FUNC(gethostname, , AC_CHECK_LIB(ucb, gethostname))
dnl dl lib? dnl dl lib?
AC_CHECK_FUNC(dlopen, , AC_CHECK_LIB(dl, dlopen)) AC_CHECK_FUNC(dlopen, , AC_CHECK_LIB(dl, dlopen))
dnl **********************************************************************
dnl Check for the random seed preferences
dnl **********************************************************************
AC_ARG_WITH(egd-socket,
[ --with-egd-socket=FILE Entropy Gathering Daemon socket pathname],
[ EGD_SOCKET="$withval" ]
)
if test -n "$EGD_SOCKET" ; then
AC_DEFINE_UNQUOTED(EGD_SOCKET, "$EGD_SOCKET")
fi
dnl Check for user-specified random device
AC_ARG_WITH(random,
[ --with-random=FILE read randomness from FILE (default=/dev/urandom)],
[ RANDOM_FILE="$withval" ],
[
dnl Check for random device
AC_CHECK_FILE("/dev/urandom",
[
RANDOM_FILE="/dev/urandom";
]
)
]
)
if test -n "$RANDOM_FILE" ; then
AC_SUBST(RANDOM_FILE)
AC_DEFINE_UNQUOTED(RANDOM_FILE, "$RANDOM_FILE")
fi
dnl ********************************************************************** dnl **********************************************************************
dnl Check for the presence of Kerberos4 libraries and headers dnl Check for the presence of Kerberos4 libraries and headers
dnl ********************************************************************** dnl **********************************************************************
@@ -545,7 +575,8 @@ else
dnl these can only exist if openssl exists dnl these can only exist if openssl exists
AC_CHECK_FUNCS( RAND_status \ AC_CHECK_FUNCS( RAND_status \
RAND_screen ) RAND_screen \
RAND_egd )
fi fi
@@ -642,6 +673,7 @@ AC_CHECK_HEADERS( \
winsock.h \ winsock.h \
time.h \ time.h \
io.h \ io.h \
pwd.h
) )
dnl Check for libz header dnl Check for libz header
@@ -662,6 +694,28 @@ AC_CHECK_SIZEOF(long long, 4)
# check for ssize_t # check for ssize_t
AC_CHECK_TYPE(ssize_t, int) AC_CHECK_TYPE(ssize_t, int)
dnl
dnl We can't just AC_CHECK_TYPE() for socklen_t since it doesn't appear
dnl in the standard headers. We egrep for it in the socket headers and
dnl if it is used there we assume we have the type defined, otherwise
dnl we search for it with AC_CHECK_TYPE() the "normal" way
dnl
if test "$ac_cv_header_sys_socket_h" = "yes"; then
AC_MSG_CHECKING(for socklen_t in sys/socket.h)
AC_EGREP_HEADER(socklen_t,
sys/socket.h,
socklen_t=yes
AC_MSG_RESULT(yes),
AC_MSG_RESULT(no))
fi
if test "$socklen_t" != "yes"; then
# check for socklen_t the standard way if it wasn't found before
AC_CHECK_TYPE(socklen_t, int)
fi
dnl Get system canonical name dnl Get system canonical name
AC_CANONICAL_HOST AC_CANONICAL_HOST
AC_DEFINE_UNQUOTED(OS, "${host}") AC_DEFINE_UNQUOTED(OS, "${host}")
@@ -693,7 +747,9 @@ AC_CHECK_FUNCS( socket \
sigaction \ sigaction \
signal \ signal \
getpass_r \ getpass_r \
strlcat strlcat \
getpwuid \
geteuid
) )
dnl removed 'getpass' check on October 26, 2000 dnl removed 'getpass' check on October 26, 2000
@@ -733,5 +789,10 @@ AC_OUTPUT( 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 \
perl/Makefile \
perl/Curl_easy/Makefile \
php/Makefile \
php/examples/Makefile
)

View File

@@ -6,9 +6,9 @@
BUGS BUGS
Curl has grown substantially from that day, several years ago, when I Curl and libcurl have grown substantially since the beginning. At the time
started fiddling with it. When I write this, there are 16500 lines of source of writing (mid March 2001), there are 23000 lines of source code, and by
code, and by the time you read this it has probably grown even more. the time you read this it has probably grown even more.
Of course there are lots of bugs left. And lots of misfeatures. Of course there are lots of bugs left. And lots of misfeatures.
@@ -21,10 +21,11 @@ BUGS
http://sourceforge.net/bugs/?group_id=976 http://sourceforge.net/bugs/?group_id=976
When reporting a bug, you should include information that will help us When reporting a bug, you should include information that will help us
understand what's wrong, what's expected and how to repeat it. You therefore understand what's wrong, what you expected to happen and how to repeat the
need to supply your operating system's name and version number (uname -a bad behaviour. You therefore need to supply your operating system's name and
under a unix is fine), what version of curl you're using (curl -v is fine), version number (uname -a under a unix is fine), what version of curl you're
what URL you were working with and anything else you think matters. using (curl -V is fine), what URL you were working with and anything else
you think matters.
If curl crashed, causing a core dump (in unix), there is hardly any use to If curl crashed, causing a core dump (in unix), there is hardly any use to
send that huge file to anyone of us. Unless we have an exact same system send that huge file to anyone of us. Unless we have an exact same system
@@ -32,7 +33,7 @@ BUGS
a stack trace and send that (much smaller) output to us instead! a stack trace and send that (much smaller) output to us instead!
The address and how to subscribe to the mailing list is detailed in the The address and how to subscribe to the mailing list is detailed in the
README.curl file. MANUAL file.
HOW TO GET A STACK TRACE with a common unix debugger HOW TO GET A STACK TRACE with a common unix debugger
==================================================== ====================================================

View File

@@ -13,7 +13,7 @@ To Think About When Contributing Source Code
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
the same license curl and libcurl is already using. the same license curl and libcurl is already using unless stated otherwise.
If you add a larger piece of code, you can opt to make that file or set of If you add a larger piece of code, you can opt to make that file or set of
files to use a different license as long as they don't enfore any changes to files to use a different license as long as they don't enfore any changes to
@@ -26,19 +26,19 @@ 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
names. It doesn't necessarily have to mean that you should use the same as in names. It doesn't necessarily have to mean that you should use the same as in
other places of the code, just that the names should be logical, other places of the code, just that the names should be logical,
understandable and be named according to what they're used for. understandable and be named according to what they're used for. File-local
functions should be made static.
Indenting Indenting
Please try using the same indenting levels and bracing method as all the Please try using the same indenting levels and bracing method as all the
other code already does. It makes the source code a lot easier to follow if other code already does. It makes the source code a lot easier to follow if
all of it is written using the same style. I don't ask you to like it, I just all of it is written using the same style. We don't ask you to like it, we
ask you to follow the tradition! ;-) just ask you to follow the tradition! ;-)
Commenting Commenting
Comment your source code extensively. I don't see myself as a very good Comment your source code extensively. Commented code is quality code and
source commenter, but I try to become one. Commented code is quality code and
enables future modifications much more. Uncommented code much more risk being enables future modifications much more. Uncommented code much more risk being
completely replaced when someone wants to extend things, since other persons' completely replaced when someone wants to extend things, since other persons'
source code can get quite hard to read. source code can get quite hard to read.
@@ -71,9 +71,9 @@ Separate Patches Doing Different Things
Patch Against Recent Sources Patch Against Recent Sources
Please try to get the latest available sources to make your patches Please try to get the latest available sources to make your patches
against. It makes my life so much easier. The very best is if you get the against. It makes the life of the developers so much easier. The very best is
most up-to-date sources from the CVS repository, but the latest release if you get the most up-to-date sources from the CVS repository, but the
archive is quite OK as well! latest release archive is quite OK as well!
Document Document
@@ -91,9 +91,9 @@ Write Access to CVS Repository
Test Cases Test Cases
Since the introduction of the test suite, we will get the possibility to Since the introduction of the test suite, we can quickly verify that the main
quickly verify that the main features are working as supposed to. To maintain features are working as they're supposed to. To maintain this situation and
this situation and improve it, all new features and functions that are added improve it, all new features and functions that are added need to be tested
need tro be tested. Every feature that is added should get at least one valid in the test suite. Every feature that is added should get at least one valid
test case that verifies that it works as documented. If every submitter also test case that verifies that it works as documented. If every submitter also
post a few test cases, it won't end up as a heavy burden on a single person! post a few test cases, it won't end up as a heavy burden on a single person!

119
docs/FAQ
View File

@@ -1,4 +1,4 @@
Updated: February 12, 2001 (http://curl.haxx.se/docs/faq.shtml) Updated: March 13, 2001 (http://curl.haxx.se/docs/faq.shtml)
_ _ ____ _ _ _ ____ _
___| | | | _ \| | ___| | | | _ \| |
/ __| | | | |_) | | / __| | | | |_) | |
@@ -31,7 +31,7 @@ FAQ
3.7 Can I use curl to delete/rename a file through FTP? 3.7 Can I use curl to delete/rename a file through FTP?
3.8 How do I tell curl to follow HTTP redirects? 3.8 How do I tell curl to follow HTTP redirects?
3.9 How do I use curl in PHP? 3.9 How do I use curl in PHP?
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?
4. Running Problems 4. Running Problems
4.1 Problems connecting to SSL servers. 4.1 Problems connecting to SSL servers.
@@ -112,29 +112,30 @@ FAQ
1.4 When will you make curl do XXXX ? 1.4 When will you make curl do XXXX ?
I love suggestions of what to change in order to make curl and libcurl We love suggestions of what to change in order to make curl and libcurl
better. I do however believe in a few rules when it comes to the future of better. We do however believe in a few rules when it comes to the future of
curl: curl:
* It is to remain a command line tool. If you want GUIs or fancy scripting * Curl is to remain a command line tool. If you want GUIs or fancy scripting
capabilities, you're free to write another tool that uses libcurl and that capabilities, you're free to write another tool that uses libcurl and that
offers this. There's no point in having one single tool that does every offers this. There's no point in having a single tool that does every
imaginable thing. That's also one of the great advantages of having the imaginable thing. That's also one of the great advantages of having the
core of curl as a library: libcurl. core of curl as a library.
* I do not add things to curl that other small and available tools already * We do not add things to curl that other small and available tools already
do very fine at the side. Curl's output is fine to pipe into another do very fine at the side. Curl's output is fine to pipe into another
program or redirect to another file for the next program to interpret. program or redirect to another file for the next program to interpret.
* I 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 I will agree. If you wanna add more protocols, I may very well
agree. agree.
* If you want me to make all the work while you wait for me to implement it * If you want someone else to make all the work while you wait for us to
for you, that is not a very friendly attitude. I spend a considerable time implement it for you, that is not a very friendly attitude. We spend a
already on maintaining and developing curl. In order to get more out of considerable time already on maintaining and developing curl. In order to
me, I trust you will offer some of your time and efforts in return. get more out of us, you should consider trading in some of your time and
efforts in return.
* If you write the code, chances are bigger that it will get into curl * If you write the code, chances are bigger that it will get into curl
faster. faster.
@@ -182,26 +183,24 @@ FAQ
2.2. Does curl work/build with other SSL libraries? 2.2. Does curl work/build with other SSL libraries?
Curl has been written to use OpenSSL, although I doubt there would be much Curl has been written to use OpenSSL, although there should not be much
problems using a different library. I just don't know any other free one and problems using a different library. If anyone does "port" curl to use a
that has limited my possibilities to develop against anything else. different SSL library, we are of course very interested in getting the
patch!
If anyone does "port" curl to use a commercial SSL library, I am of course
very interested in getting the patch!
2.3. Where can I find a copy of LIBEAY32.DLL? 2.3. Where can I find a copy of LIBEAY32.DLL?
That is an OpenSSL binary built for Windows. That is an OpenSSL binary built for Windows.
Curl uses OpenSSL to do the SSL stuff. The LIBEAY32.DLL is what curl needs Curl uses OpenSSL to do the SSL stuff. The LIBEAY32.DLL is what curl needs
on a windows machine to do https://. Check out the curl web page to find on a windows machine to do https://. Check out the curl web site to find
accurate and up-to-date pointers to recent OpenSSL DDLs and other binary accurate and up-to-date pointers to recent OpenSSL DDLs and other binary
packages. packages.
2.4. Does cURL support Socks (RFC 1928) ? 2.4. Does cURL support Socks (RFC 1928) ?
No. Nobody has wanted it that badly yet. I would appriciate patches that No. Nobody has wanted it that badly yet. We appriciate patches that bring
brings this functionality. this functionality.
3. Usage problems 3. Usage problems
@@ -223,7 +222,7 @@ FAQ
3.2. How do I tell curl to resume a transfer? 3.2. How do I tell curl to resume a transfer?
Curl supports resume both ways on FTP, download ways on HTTP. Curl supports resumed transfers both ways on both FTP and HTTP.
Try the -C option. Try the -C option.
@@ -235,10 +234,10 @@ FAQ
use the -F type. In all the most common cases, you should use -d which then use the -F type. In all the most common cases, you should use -d which then
causes a posting with the type 'application/x-www-form-urlencoded'. causes a posting with the type 'application/x-www-form-urlencoded'.
I have described this in some detail in the README.curl file, and if you This is described in some detail in the README.curl file, and if you don't
don't understand it the first time, read it again before you post questions understand it the first time, read it again before you post questions about
about this to the mailing list. I would also suggest that you read through this to the mailing list. Also, try reading through the mailing list
the mailing list archives for old postings and questions regarding this. archives for old postings and questions regarding this.
3.4. How do I tell curl to run custom FTP commands? 3.4. How do I tell curl to run custom FTP commands?
@@ -295,7 +294,7 @@ FAQ
invoke the curl tool using a command line. This is the way to use curl if invoke the curl tool using a command line. This is the way to use curl if
you're using PHP3 or PHP4 built without curl module support. you're using PHP3 or PHP4 built without curl module support.
3.10 What about SOAP, WEBDAV, XML-RPC or similar protocols over HTTP? 3.10 What about SOAP, WebDAV, XML-RPC or similar protocols over HTTP?
Curl adheres to the HTTP spec, which basically means you can play with *any* Curl adheres to the HTTP spec, which basically means you can play with *any*
protocol that is built ontop of HTTP. Protocols such as SOAP, WEBDAV and protocol that is built ontop of HTTP. Protocols such as SOAP, WEBDAV and
@@ -309,9 +308,9 @@ FAQ
4.1. Problems connecting to SSL servers. 4.1. Problems connecting to SSL servers.
It took a very long time before I could sort out why curl had problems It took a very long time before we could sort out why curl had problems to
to connect to certain SSL servers when using SSLeay or OpenSSL v0.9+. connect to certain SSL servers when using SSLeay or OpenSSL v0.9+. The
The error sometimes showed up similar to: error sometimes showed up similar to:
16570:error:1407D071:SSL routines:SSL2_READ:bad mac decode:s2_pkt.c:233: 16570:error:1407D071:SSL routines:SSL2_READ:bad mac decode:s2_pkt.c:233:
@@ -319,12 +318,12 @@ FAQ
requests properly. To correct this problem, tell curl to select SSLv2 from requests properly. To correct this problem, tell curl to select SSLv2 from
the command line (-2/--sslv2). the command line (-2/--sslv2).
I have also seen examples where the remote server didn't like the SSLv2 There has also been examples where the remote server didn't like the SSLv2
request and instead you had to force curl to use SSLv3 with -3/--sslv3. request and instead you had to force curl to use SSLv3 with -3/--sslv3.
4.2. Why do I get problems when I use & or % in the URL? 4.2. Why do I get problems when I use & or % in the URL?
In general unix shells, the & letter is treated special and when used it In general unix shells, the & letter is treated special and when used, it
runs the specified command in the background. To safely send the & as a part runs the specified command in the background. To safely send the & as a part
of a URL, you should qoute the entire URL by using single (') or double (") of a URL, you should qoute the entire URL by using single (') or double (")
quotes around it. quotes around it.
@@ -349,8 +348,8 @@ FAQ
curl '{curl,www}.haxx.se' curl '{curl,www}.haxx.se'
To be able to use those letters as actual parts of the URL (without using To be able to use those letters as actual parts of the URL (without using
them for the curl URL "globbing" system), use the -g/--globoff option them for the curl URL "globbing" system), use the -g/--globoff option (curl
(included in curl 7.6 and later): 7.6 and later):
curl -g 'www.site.com/weirdname[].html' curl -g 'www.site.com/weirdname[].html'
@@ -366,8 +365,8 @@ FAQ
4.5 Why do I get return code XXX from a HTTP server? 4.5 Why do I get return code XXX from a HTTP server?
RFC2616 clearly explains the return codes. I'll make a short transcript RFC2616 clearly explains the return codes. This is a short transcript. Go
here. Go read the RFC for exact details: read the RFC for exact details:
4.5.1 "400 Bad Request" 4.5.1 "400 Bad Request"
@@ -403,7 +402,7 @@ FAQ
4.7. How do I keep usernames and passwords secret in Curl command lines? 4.7. How do I keep usernames and passwords secret in Curl command lines?
I see this problem as two parts: This problem has two sides:
The first part is to avoid having clear-text passwords in the command line The first part is to avoid having clear-text passwords in the command line
so that they don't appear in 'ps' outputs and similar. That is easily so that they don't appear in 'ps' outputs and similar. That is easily
@@ -450,9 +449,8 @@ FAQ
programs. libcurl will use thread-safe functions instead of non-safe ones if programs. libcurl will use thread-safe functions instead of non-safe ones if
your system has such. your system has such.
I am very interested in once and for all getting some kind of report or We would appriciate some kind of report or README file from those who have
README file from those who have used libcurl in a threaded environment, used libcurl in a threaded environment.
since I haven't and I get this question more and more frequently!
5.2 How can I receive all data into a large memory chunk? 5.2 How can I receive all data into a large memory chunk?
@@ -489,9 +487,16 @@ FAQ
5.3 How do I fetch multiple files with libcurl? 5.3 How do I fetch multiple files with libcurl?
The easy interface of libcurl does not support multiple requests using the Starting with version 7.7, curl and libcurl will have excellent support for
same connection. The only available way to do multiple requests is to transferring multiple files. You should just repeatedly set new URLs with
init/perform/cleanup for each request. curl_easy_setopt() and then transfer it with curl_easy_perform(). The handle
you get from curl_easy_init() is not only reusable starting with libcurl
7.7, but also you're encouraged to reuse it if you can, as that will enable
libcurl to use persistant connections.
For libcurl prior to 7.7, there was no multiple file support. The only
available way to do multiple requests was to init/perform/cleanup for each
transfer.
5.4 Does libcurl do Winsock initing on win32 systems? 5.4 Does libcurl do Winsock initing on win32 systems?
@@ -515,17 +520,16 @@ FAQ
5.6 What about Keep-Alive or persistant connections? 5.6 What about Keep-Alive or persistant connections?
This is closely related to issue 5.3. Since libcurl has no real support Starting with version 7.7, curl and libcurl will have excellent support for
for doing multiple file transfers, there's no support for Keep-Alive or persistant connections when transferring several files from the same server.
persistant connections either. Curl will attempt to reuse connections for all URLs specified on the same
command line/config file, and libcurl will reuse connections for all
transfers that are made using the same libcurl handle.
This is of course subject to change as soon as libcurl gets support for Previous versions had no persistant connection support.
multiple files. Feel free to join in and make this change happen sooner!
6. License Issues 6. License Issues
NOTE: This section concerns curl 7.5.2 or later!
Curl and libcurl are released under a MIT/X derivate license *or* the MPL, Curl and libcurl are released under a MIT/X derivate license *or* the MPL,
the Mozilla Public License. To get a really good answer to your license the Mozilla Public License. To get a really good answer to your license
conflict questions, you should study the MPL and MIT/X licenses and the conflict questions, you should study the MPL and MIT/X licenses and the
@@ -570,9 +574,10 @@ FAQ
No. No.
We carefully picked this license years ago and a large amount of people have We have carefully picked this license after years of development and
contributed with source code knowing that this is the license we use. This discussions and a large amount of people have contributed with source code
license puts the restrictions we want on curl/libcurl and it does not spread knowing that this is the license we use. This license puts the restrictions
to other programs or libraries that use it. The recent dual license we want on curl/libcurl and it does not spread to other programs or
modification should make it possible for everyone to use libcurl or curl in libraries that use it. The recent dual license modification should make it
their projects, no matter what license they already have in use. possible for everyone to use libcurl or curl in their projects, no matter
what license they already have in use.

View File

@@ -17,18 +17,21 @@ Misc
- progress bar/time specs while downloading - progress bar/time specs while downloading
- "standard" proxy environment variables support - "standard" proxy environment variables support
- config file support - config file support
- compiles on win32 - compiles on win32 (reported built on 29 operating systems)
- redirectable stderr - redirectable stderr
- use selected network interface for outgoing traffic - use selected network interface for outgoing traffic
- IPv6 support
- persistant connections
HTTP HTTP
- HTTP/1.1 compliant
- GET - GET
- PUT - PUT
- HEAD - HEAD
- POST - POST
- multipart POST - multipart POST
- authentication - authentication
- resume - resume (both GET and PUT)
- follow redirects - follow redirects
- maximum amount of redirects to follow - maximum amount of redirects to follow
- custom HTTP request - custom HTTP request
@@ -71,6 +74,7 @@ FTP
TELNET TELNET
- connection negotiation - connection negotiation
- custom telnet options
- stdin/stdout I/O - stdin/stdout I/O
LDAP (*2) LDAP (*2)

View File

@@ -10,21 +10,32 @@ Curl has been compiled and built on numerous different operating systems. The
way to proceed is mainly divided in two different ways: the unix way or the way to proceed is mainly divided in two different ways: the unix way or the
windows way. windows way.
If you're using Windows (95, 98, NT) or OS/2, you should continue reading from If you're using Windows (95/98/NT/ME/2000 or whatever) or OS/2, you should
the Win32 or OS/2 headers further down. All other systems should be capable of continue reading from the Win32 or OS/2 headers further down. All other
being installed as described below. systems should be capable of being installed as described below.
UNIX UNIX
==== ====
The configure script *always* tries to find a working SSL library unless A normal unix installation is made in three or four steps (after you've
explicitly told not to. If you have OpenSSL installed in the default unpacked the source archive):
search path for your compiler/linker, you don't need to do anything
special:
./configure ./configure
make
make test (optional)
make install
If you have OpenSSL installed in /usr/local/ssl, you can run configure You probably need to be root when doing the last command.
If you want to install curl in a different file hierarchy than /usr/local,
you need to specify that already when running configure:
./configure --prefix=/path/to/curl/tree
The configure script always tries to find a working SSL library unless
explicitly told not to. If you have OpenSSL installed in the default search
path for your compiler/linker, you don't need to do anything special. If
you have OpenSSL installed in e.g /usr/local/ssl, you can run configure
like: like:
./configure --with-ssl ./configure --with-ssl
@@ -54,33 +65,11 @@ UNIX
env CPPFLAGS="-I/path/to/ssl/include" LDFLAGS="-L/path/to/ssl/lib" \ env CPPFLAGS="-I/path/to/ssl/include" LDFLAGS="-L/path/to/ssl/lib" \
./configure ./configure
If your SSL library was compiled with rsaref (usually for use in If your SSL library was compiled with rsaref (usually for use in the United
the United States), you may also need to set: States), you may also need to set:
LIBS=-lRSAglue -lrsaref LIBS=-lRSAglue -lrsaref
(from Doug Kaufman <dkaufman@rahul.net>) (as suggested by Doug Kaufman)
Without SSL support, just run:
./configure
Then run:
make
Use the executable `curl` in src/ directory.
To install curl on your system, run
make install
This will copy curl to /usr/local/bin/ (or $prefix/bin if you used the
--prefix option to configure) and it copies the man pages, the lib and the
include files to suitable places.
To make sure everything runs as supposed, run the test suite:
make test
KNOWN PROBLEMS KNOWN PROBLEMS
@@ -109,7 +98,7 @@ UNIX
they're executable and set to appear in the path *BEFORE* the actual (but they're executable and set to appear in the path *BEFORE* the actual (but
obsolete) autoconf and autoheader scripts. obsolete) autoconf and autoheader scripts.
OPTIONS MORE OPTIONS
Remember, to force configure to use the standard cc compiler if both Remember, to force configure to use the standard cc compiler if both
cc and gcc are present, run configure like cc and gcc are present, run configure like
@@ -156,29 +145,27 @@ Win32
MingW32 (GCC-2.95) style MingW32 (GCC-2.95) style
------------------------ ------------------------
Run the 'mingw32.bat' file to get the proper environment variables Run the 'mingw32.bat' file to get the proper environment variables
set, then run 'make -f Makefile.m32' in the lib/ dir and then set, then run 'make mingw32' in the root dir.
'make -f Makefile.m32' in the src/ dir.
If you have any problems linking libraries or finding header files, If you have any problems linking libraries or finding header files, be
be sure to look at the provided "Makefile.m32" files for the proper sure to verify that the provided "Makefile.m32" files use the proper
paths, and adjust as necessary. paths, and adjust as necessary.
Cygwin style Cygwin style
------------ ------------
Almost identical to the unix installation. Run the configure script Almost identical to the unix installation. Run the configure script in
in the curl root with 'sh configure'. Make sure you have the sh the curl root with 'sh configure'. Make sure you have the sh
executable in /bin/ or you'll see the configure fail towards the executable in /bin/ or you'll see the configure fail towards the end.
end.
Run 'make' Run 'make'
Microsoft command line style Microsoft command line style
---------------------------- ----------------------------
Run the 'vcvars32.bat' file to get the proper environment variables Run the 'vcvars32.bat' file to get the proper environment variables
set, then run 'nmake -f Makefile.vc6' in the lib/ dir and then set, then run 'nmake vc' in the root dir.
'nmake -f Makefile.vc6' in the src/ dir.
The vcvars32.bat file is part of the Microsoft development environment. The vcvars32.bat file is part of the Microsoft development
environment.
IDE-style IDE-style
------------------------- -------------------------
@@ -206,26 +193,24 @@ Win32
MingW32 (GCC-2.95) style MingW32 (GCC-2.95) style
------------------------ ------------------------
Run the 'mingw32.bat' file to get the proper environment variables Run the 'mingw32.bat' file to get the proper environment variables
set, then run 'make -f Makefile.m32 SSL=1' in the lib/ dir and then set, then run 'make mingw32-ssl' in the root dir.
'make -f Makefile.m32 SSL=1' in the src/ dir.
If you have any problems linking libraries or finding header files, If you have any problems linking libraries or finding header files, be
be sure to look at the provided "Makefile.m32" files for the proper sure to look at the provided "Makefile.m32" files for the proper
paths, and adjust as necessary. paths, and adjust as necessary.
Cygwin style Cygwin style
------------ ------------
Haven't done, nor got any reports on how to do. It should although be Haven't done, nor got any reports on how to do. It should although be
identical to the unix setup for the same purpose. See above. identical to the unix setup for the same purpose. See above.
Microsoft command line style Microsoft command line style
---------------------------- ----------------------------
Run the 'vcvars32.bat' file to get the proper environment variables Run the 'vcvars32.bat' file to get the proper environment variables
set, then run 'nmake -f Makefile.vc6 release-ssl' in the lib/ dir and set, then run 'nmake vc-ssl' in the root dir.
then 'nmake -f Makefile.vc6' in the src/ dir.
The vcvars32.bat file is part of the Microsoft development environment. The vcvars32.bat file is part of the Microsoft development
environment.
Microsoft / Borland style Microsoft / Borland style
------------------------- -------------------------

View File

@@ -1,4 +1,4 @@
Updated for curl 7.6 on January 26, 2001 Updated for curl 7.7 on March 13, 2001
_ _ ____ _ _ _ ____ _
___| | | | _ \| | ___| | | | _ \| |
/ __| | | | |_) | | / __| | | | |_) | |
@@ -7,11 +7,11 @@
INTERNALS INTERNALS
The project is kind of split in two. The library and the client. The client The project is split in two. The library and the client. The client part uses
part uses the library, but the library is meant to be designed to allow other the library, but the library is designed to allow other applications to use
applications to use it. it.
Thus, the largest amount of code and complexity is in the library part. The largest amount of code and complexity is in the library part.
CVS CVS
=== ===
@@ -35,13 +35,13 @@ Windows vs Unix
the same at all places except for the header file that defines them. The the same at all places except for the header file that defines them. The
macros in use are sclose(), sread() and swrite(). macros in use are sclose(), sread() and swrite().
2. Windows requires a couple of init calls for the socket stuff 2. Windows requires a couple of init calls for the socket stuff.
Those must be made by the application that uses libcurl, in curl that means Those must be made by the application that uses libcurl, in curl that means
src/main.c has some code #ifdef'ed to do just that. src/main.c has some code #ifdef'ed to do just that.
3. The file descriptors for network communication and file operations are 3. The file descriptors for network communication and file operations are
not easily interchangable as in unix not easily interchangable as in unix.
We avoid this by not trying any funny tricks on file descriptors. We avoid this by not trying any funny tricks on file descriptors.
@@ -51,10 +51,10 @@ Windows vs Unix
We set stdout to binary under windows We set stdout to binary under windows
Inside the source code, I do make an effort to avoid '#ifdef WIN32'. All Inside the source code, We make an effort to avoid '#ifdef [Your OS]'. All
conditionals that deal with features *should* instead be in the format conditionals that deal with features *should* instead be in the format
'#ifdef HAVE_THAT_WEIRD_FUNCTION'. Since Windows can't run configure scripts, '#ifdef HAVE_THAT_WEIRD_FUNCTION'. Since Windows can't run configure scripts,
I maintain two config-win32.h files (one in / and one in src/) that are we maintain two config-win32.h files (one in / and one in src/) that are
supposed to look exactly as a config.h file would have looked like on a supposed to look exactly as a config.h file would have looked like on a
Windows machine! Windows machine!
@@ -64,12 +64,6 @@ Windows vs Unix
Library Library
======= =======
As described elsewhere, libcurl is meant to get two different "layers" of
interfaces. At the present point only the high-level, the "easy", interface
has been fully implemented and documented. We assume the easy-interface in
this description, the low-level interface will be documented when fully
implemented.
There are plenty of entry points to the library, namely each publicly defined There are plenty of entry points to the library, namely each publicly defined
function that libcurl offers to applications. All of those functions are function that libcurl offers to applications. All of those functions are
rather small and easy-to-follow. All the ones prefixed with 'curl_easy' are rather small and easy-to-follow. All the ones prefixed with 'curl_easy' are
@@ -103,8 +97,9 @@ Library
lib/sendf.c) function to send printf-style formatted data to the remote host lib/sendf.c) function to send printf-style formatted data to the remote host
and when they're ready to make the actual file transfer they call the and when they're ready to make the actual file transfer they call the
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. curl_transfer() then calls _Tranfer() in lib/transfer.c that returns. Curl_perform() then calls Transfer() in lib/transfer.c that performs
performs the entire file transfer. the entire file transfer. Curl_perform() is what does the main "connect - do
- transfer - done" loop. It loops if there's a Location: to follow.
During transfer, the progress functions in lib/progress.c are called at a During transfer, the progress functions in lib/progress.c are called at a
frequent interval (or at the user's choice, a specified callback might get frequent interval (or at the user's choice, a specified callback might get
@@ -114,6 +109,22 @@ Library
When completed, the curl_easy_cleanup() should be called to free up used When completed, the curl_easy_cleanup() should be called to free up used
resources. resources.
A quick roundup on internal function sequences (many of these call
protocol-specific function-pointers):
curl_connect - connects to a remote site and does initial connect fluff
This also checks for an existing connection to the requested site and uses
that one if it is possible.
curl_do - starts a transfer
curl_transfer() - transfers data
curl_done - ends a transfer
curl_disconnect - disconnects from a remote site. This is called when the
disconnect is really requested, which doesn't necessarily have to be
exactly after curl_done in case we want to keep the connection open for
a while.
HTTP(S) HTTP(S)
HTTP offers a lot and is the protocol in curl that uses the most lines of HTTP offers a lot and is the protocol in curl that uses the most lines of
@@ -129,6 +140,14 @@ Library
the source by the use of curl_read() for reading and curl_write() for writing the source by the use of curl_read() for reading and curl_write() for writing
data to the remote server. data to the remote server.
http_chunks.c contains functions that understands HTTP 1.1 chunked transfer
encoding.
An interesting detail with the HTTP(S) request, is the add_buffer() series of
functions we use. They append data to one single buffer, and when the
building is done the entire request is sent off in one single write. This is
done this way to overcome problems with flawed firewalls and lame servers.
FTP FTP
The Curl_if2ip() function can be used for getting the IP number of a The Curl_if2ip() function can be used for getting the IP number of a
@@ -160,7 +179,7 @@ Library
URL encoding and decoding, called escaping and unescaping in the source code, URL encoding and decoding, called escaping and unescaping in the source code,
is found in lib/escape.c. is found in lib/escape.c.
While transfering data in _Transfer() a few functions might get While transfering data in Transfer() a few functions might get
used. curl_getdate() in lib/getdate.c is for HTTP date comparisons (and used. curl_getdate() in lib/getdate.c is for HTTP date comparisons (and
more). more).
@@ -182,6 +201,34 @@ Library
exists in lib/getpass.c. libcurl offers a custom callback that can be used exists in lib/getpass.c. libcurl offers a custom callback that can be used
instead of this, but it doesn't change much to us. instead of this, but it doesn't change much to us.
Persistant Connections
======================
With curl 7.7, we added persistant connection support to libcurl which has
introduced a somewhat different treatmeant of things inside of libcurl.
o The 'UrlData' struct returned in the curl_easy_init() call must never
hold connection-oriented data. It is meant to hold the root data as well
as all the options etc that the library-user may choose.
o The 'UrlData' struct holds the cache array of pointers to 'connectdata'
structs. There's one connectdata struct for each connection that libcurl
knows about.
o This also enables the 'curl handle' to be reused on subsequent transfers,
something that was illegal in pre-7.7 versions.
o When we are about to perform a transfer with curl_easy_perform(), we first
check for an already existing connection in the cache that we can use,
otherwise we create a new one and add to the cache. If the cache is full
already when we add a new connection, we close one of the present ones. We
select which one to close dependent on the close policy that may have been
previously set.
o When the tranfer operation is complete, we try to leave the connection open.
Particular options may tell us not to, and protocols may signal closure on
connections and then we don't keep it open of course.
o When curl_easy_cleanup() is called, we close all still opened connections.
You do realize that the curl handle must be re-used in order for the
persistant connections to work.
Library Symbols Library Symbols
=============== ===============
@@ -236,12 +283,12 @@ Memory Debugging
deal with resources that might give us problems if we "leak" them. The deal with resources that might give us problems if we "leak" them. The
functions in the memdebug system do nothing fancy, they do their normal functions in the memdebug system do nothing fancy, they do their normal
function and then log information about what they just did. The logged data function and then log information about what they just did. The logged data
is then analyzed after a complete session, can then be analyzed after a complete session,
memanalyze.pl is a perl script present only in CVS (not part of the release memanalyze.pl is a perl script present only present in CVS (not part of the
archives) that analyzes a log file generated by the memdebug system. It release archives) that analyzes a log file generated by the memdebug
detects if resources are allocated but never freed and other kinds of errors system. It detects if resources are allocated but never freed and other kinds
related to resource management. of errors related to resource management.
Use -DMALLOCDEBUG when compiling to enable memory debugging. Use -DMALLOCDEBUG when compiling to enable memory debugging.
@@ -256,8 +303,8 @@ Test Suite
httpserver.pl and ftpserver.pl before all the test cases are performed. The httpserver.pl and ftpserver.pl before all the test cases are performed. The
test suite currently only runs on unix-like platforms. test suite currently only runs on unix-like platforms.
You'll find a complete description of the test case data files in the README You'll find a complete description of the test case data files in the
file in the test directory. tests/README file.
The test suite automatically detects if curl was built with the memory The test suite automatically detects if curl was built with the memory
debugging enabled, and if it was it will detect memory leaks too. debugging enabled, and if it was it will detect memory leaks too.
@@ -269,6 +316,7 @@ Building Releases
released, run the 'maketgz' script (using 'make distcheck' will give you a released, run the 'maketgz' script (using 'make distcheck' will give you a
pretty good view on the status of the current sources). maketgz prompts for pretty good view on the status of the current sources). maketgz prompts for
version number of the client and the library before it creates a release version number of the client and the library before it creates a release
archive. archive. maketgz uses 'make dist' for the actual archive building, why you
need to fill in the Makefile.am files properly for which files that should
be included in the release archives.
You must have autoconf installed to build release archives.

View File

@@ -4,58 +4,91 @@
| | | |_) | (__| |_| | | | | | | | |_) | (__| |_| | | | |
|_|_|_.__/ \___|\__,_|_| |_| |_|_|_.__/ \___|\__,_|_| |_|
How To Use Libcurl In Your C/C++ Program
How To Use Libcurl In Your Program [ libcurl can be used directly from within your PHP or Perl programs as well,
look elsewhere for documentation on this ]
Interfaces The interface is meant to be very simple for applictions/programmers, hence
the name "easy". We have therefore minimized the number of entries.
libcurl currently offers two different interfaces to the URL transfer
engine. They can be seen as one low-level and one high-level, in the sense
that the low-level one will allow you to deal with a lot more details but on
the other hand not offer as many fancy features (such as Location:
following). The high-level interface is supposed to be a built-in
implementation of the low-level interface. You will not be able to mix
function calls from the different layers.
As we currently ONLY support the high-level interface, the so called easy
interface, I will not attempt to describe any low-level functions at this
point.
Function descriptions
The interface is meant to be very simple for very simple
implementations. Thus, we have minimized the number of entries.
The Easy Interface The Easy Interface
When using the easy interface, you init your easy-session and get a handle, When using the easy interface, you init your session and get a handle, which
which you use as input to the following interface functions you use. 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, You continue by setting all the options you want in the upcoming transfer,
most important among them is the URL itself. You might want to set some most important among them is the URL itself (you can't transfer anything
callbacks as well that will be called from the library when data is available without a specified URL as you may have figured out yourself). You might want
etc. 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. It will then do When all is setup, you tell libcurl to perform the transfer using
the entire operation and won't return until it is done or failed. 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 easy-session's handle and After the transfer has been made, you cleanup the session with
libcurl is entirely off the hook! 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.
curl_easy_init() While the above mentioned four functions are the main functions to use in the
curl_easy_setopt() easy interface, there is a series of other helpful functions to use. They
curl_easy_perform() are:
curl_easy_cleanup()
While the above four functions are the main functions to use in the easy curl_version() - displays the libcurl version
interface, there is a series of helpful functions to use. They are: 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
curl_version() - displays the libcurl version For details on these, read the separate man pages.
curl_getdate() - converts a date string to time_t
curl_getenv() - portable environment variable reader
curl_formparse() - helps building a HTTP form POST
curl_slist_append() - builds a linked list
curl_slist_free_all() - frees a whole curl_slist
Read the separate man pages for these functions for details! 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

@@ -25,12 +25,16 @@ SIMPLE USAGE
Get a list of the root directory of an FTP site: Get a list of the root directory of an FTP site:
curl ftp://ftp.fts.frontec.se/ curl ftp://cool.haxx.se/
Get the definition of curl from a dictionary: Get the definition of curl from a dictionary:
curl dict://dict.org/m:curl curl dict://dict.org/m:curl
Fetch two documents at once:
curl ftp://cool.haxx.se/ http://www.weirdserver.com:8000/
DOWNLOAD TO A FILE DOWNLOAD TO A FILE
Get a web page and store in a local file: Get a web page and store in a local file:
@@ -43,6 +47,10 @@ DOWNLOAD TO A FILE
curl -O http://www.netscape.com/index.html curl -O http://www.netscape.com/index.html
Fetch two files and store them with their remote names:
curl -O www.haxx.se/index.html -O curl.haxx.se/download.html
USING PASSWORDS USING PASSWORDS
FTP FTP
@@ -455,9 +463,13 @@ EXTRA HEADERS
curl -H "X-you-and-me: yes" www.love.com curl -H "X-you-and-me: yes" www.love.com
This can also be useful in case you want curl to send a different text in This can also be useful in case you want curl to send a different text in a
a header than it normally does. The -H header you specify then replaces the header than it normally does. The -H header you specify then replaces the
header curl would normally send. header curl would normally send. If you replace an internal header with an
empty one, you prevent that header from being sent. To prevent the Host:
header from being used:
curl -H "Host:" www.server.com
FTP and PATH NAMES FTP and PATH NAMES
@@ -745,16 +757,41 @@ TELNET
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
password accordingly. password accordingly.
MAILING LIST PERSISTANT CONNECTIONS
We have an open mailing list to discuss curl, its development and things Specifying multiple files on a single command line will make curl transfer
relevant to this. all of them, one after the other in the specified order.
To subscribe, mail curl-request@contactor.se with "subscribe <fill in your libcurl will attempt to use persistant connections for the transfers so that
email address>" in the body. the second transfer to the same host can use the same connection that was
already initiated and was left open in the previous transfer. This greatly
decreases connection time for all but the first transfer and it makes a far
better use of the network.
To post to the list, mail curl@contactor.se. Note that curl cannot use persistant connections for transfers that are used
in subsequence curl invokes. Try to stuff as many URLs as possible on the
same command line if they are using the same host, as that'll make the
transfers faster. If you use a http proxy for file transfers, practicly
all transfers will be persistant.
To unsubcribe, mail curl-request@contactor.se with "unsubscribe <your Persistant connections were introduced in curl 7.7.
subscribed email address>" in the body.
MAILING LISTS
For your convenience, we have several open mailing lists to discuss curl,
its development and things relevant to this.
To subscribe to the main curl list, mail curl-request@contactor.se with
"subscribe <fill in your email address>" in the body.
To subscribe to the curl-library users/deverlopers list, follow the
instructions at http://curl.haxx.se/mail/
To subscribe to the curl-announce list, to only get information about new
releases, follow the instructions at http://curl.haxx.se/mail/
To subscribe to the curl-and-PHP list in which curl using with PHP is
discussed, follow the instructions at http://curl.haxx.se/mail/
Please direct curl questions, feature requests and trouble reports to one of
these mailing lists instead of mailing any individual.

View File

@@ -6,44 +6,42 @@
TODO TODO
For the future Things to do in project cURL. Please tell me what you think, contribute and
send me patches that improve things!
Ok, this is what I wanna do with Curl. Please tell me what you think, and To do for the 7.8 release:
please don't hesitate to contribute and send me patches that improve this
product! (Yes, you may add things not mentioned here, these are just a
few teasers...)
* Make SSL session ids get used if multiple HTTPS documents from the same * Make SSL session ids get used if multiple HTTPS documents from the same
host is requested. host is requested.
* Make the curl tool support URLs that start with @ that would then mean that * Document the undocumented libcurl functions: the printf clones (like
the following is a plain list with URLs to download. Thus @filename.txt curl_msprintf, curl_mfprintf, curl_msnprintf, curl_maprintf and
reads a list of URLs from a local file. A fancy option would then be to curl_mvfprintf), the string compare functions (curl_strequal
support @http://whatever.com that would first load a list and then get the and curl_strnequal) and the URL escape/unescape functions.
URLs mentioned in the list. I figure -O or something would have to be
implied by such an action.
* Improve the regular progress meter with --continue is used. It should be To do in a future release (random order):
noticable when there's a resume going on.
* Add configure options that disables certain protocols in libcurl to
decrease footprint. '--disable-[protocol]' where protocol is http, ftp,
telnet, ldap, dict or file.
* Extend the test suite to include telnet and https. The telnet could just do
ftp or http operations (for which we have test servers) and the https would
probably work against/with some of the openssl tools.
* Add a command line option that allows the output file to get the same time * Add a command line option that allows the output file to get the same time
stamp as the remote file. We already are capable of fetching the remote stamp as the remote file. libcurl already is capable of fetching the remote
file's date. file's date.
* Make the SSL layer option capable of using the Mozilla Security Services as * Make the SSL layer option capable of using the Mozilla Security Services as
an alternative to OpenSSL: an alternative to OpenSSL:
http://www.mozilla.org/projects/security/pki/nss/ http://www.mozilla.org/projects/security/pki/nss/
* Make sure the low-level interface works. highlevel.c should basically be
possible to write using that interface. Document the low-level interface
* Make the easy-interface support multiple file transfers. If they're done
to the same host, they should use persistant connections or similar.
Figure out a nice design for this.
* Add asynchronous name resolving, as this enables full timeout support for * Add asynchronous name resolving, as this enables full timeout support for
fork() systems. fork() systems.
* Non-blocking connect(), also to make timeouts work on windows.
* Move non-URL related functions that are used by both the lib and the curl * Move non-URL related functions that are used by both the lib and the curl
application to a separate "portability lib". application to a separate "portability lib".
@@ -51,50 +49,40 @@ For the future
something being worked on in this area) and perl (we have seen the first something being worked on in this area) and perl (we have seen the first
versions of this!) comes to mind. Python anyone? versions of this!) comes to mind. Python anyone?
* "Content-Encoding: compress/gzip/zlib" * "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
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
implement though.
HTTP 1.1 clearly defines how to get and decode compressed documents. There * Authentication: NTLM. Support for that MS crap called NTLM
is the zlib that is pretty good at 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 implement though.
* Authentication: NTLM. It would be cool to support 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
protocol is a proprietary one, it involves reverse engineering and network protocol is a proprietary one, it involves reverse engineering and network
sniffing. This should however be a library-based functionality. There are a sniffing. This should however be a library-based functionality. There are a
few different efforts "out there" to make open source HTTP clients support few different efforts "out there" to make open source HTTP clients support
this and it should be possible to take advantage of other people's hard this and it should be possible to take advantage of other people's hard
work. http://modntlm.sourceforge.net/ is one. work. http://modntlm.sourceforge.net/ is one. There's a web page at
http://www.innovation.ch/java/ntlm.html that contains detailed reverse-
engineered info.
* RFC2617 compliance, "Digest Access Authentication" * RFC2617 compliance, "Digest Access Authentication"
A valid test page seem to exist at: A valid test page seem to exist at:
http://hopf.math.nwu.edu/testpage/digest/ http://hopf.math.nwu.edu/testpage/digest/
And some friendly person's server source code is available at And some friendly person's server source code is available at
http://hopf.math.nwu.edu/digestauth/index.html http://hopf.math.nwu.edu/digestauth/index.html
Then there's the Apache mod_digest source code too of course. It seems as Then there's the Apache mod_digest source code too of course. It seems as
if Netscape doesn't support this, and not many servers do. Although this is if Netscape doesn't support this, and not many servers do. Although this is
a lot better authentication method than the more common "Basic". Basic a lot better authentication method than the more common "Basic". Basic
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.
* Multiple Proxies?
Is there anyone that actually uses serial-proxies? I mean, send CONNECT to
the first proxy to connect to the second proxy to which you send CONNECT to
connect to the remote host (or even more iterations). Is there anyone
wanting curl to support it? (Not that it would be hard, just confusing...)
* Other proxies * Other proxies
Ftp-kind proxy, Socks5, whatever kind of proxies are there? Ftp-kind proxy, Socks5, whatever kind of proxies are there?
* IPv6 Awareness and support * IPv6 Awareness and support. (This is partly done.) RFC 2428 "FTP
Where ever it would fit. configure search for v6-versions of a few Extensions for IPv6 and NATs" is interesting. PORT should be replaced with
functions and then use them instead is of course the first thing to do... EPRT for IPv6 (done), and EPSV instead of PASV. HTTP proxies are left to
RFC 2428 "FTP Extensions for IPv6 and NATs" will be interesting. PORT add support for.
should be replaced with EPRT for IPv6, and EPSV instead of PASV.
* SSL for more protocols, like SSL-FTP... * SSL for more protocols, like SSL-FTP...
(http://search.ietf.org/internet-drafts/draft-murray-auth-ftp-ssl-05.txt) (http://search.ietf.org/internet-drafts/draft-murray-auth-ftp-ssl-05.txt)
* HTTP POST resume using Range:

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 "19 January 2001" "Curl 7.6" "Curl Manual" .TH curl 1 "15 March 2001" "Curl 7.7" "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.
@@ -41,6 +41,12 @@ supported at the moment:
Starting with curl 7.6, you can specify any amount of URLs on the command Starting with curl 7.6, you can specify any amount of URLs on the command
line. They will be fetched in a sequential manner in the specified order. line. They will be fetched in a sequential manner in the specified order.
Starting with curl 7.7, curl will attempt to re-use connections for multiple
file transfers, so that getting many files from the same server will not do
multiple connects/handshakes. This improves speed. Of course this is only done
on files specified on a single command line and cannot be used between
separate curl invokes.
.SH OPTIONS .SH OPTIONS
.IP "-a/--append" .IP "-a/--append"
(FTP) (FTP)
@@ -85,6 +91,14 @@ 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 "--connect-timeout <seconds>"
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
of no more use. This option doesn't work in win32 systems. See also the
.I "--max-time"
option.
If this option is used serveral times, the last one will be used.
.IP "-c/--continue" .IP "-c/--continue"
.B Deprecated. Use '-C -' instead. .B Deprecated. Use '-C -' instead.
Continue/Resume a previous file transfer. This instructs curl to Continue/Resume a previous file transfer. This instructs curl to
@@ -105,14 +119,15 @@ HTTP resume is only possible with HTTP/1.1 or later servers.
If this option is used serveral times, the last one will be used. If this option is used serveral times, the last one will be used.
.IP "-d/--data <data>" .IP "-d/--data <data>"
(HTTP) Sends the specified data in a POST request to the HTTP server. Note (HTTP) Sends the specified data in a POST request to the HTTP server, in a way
that the data is sent exactly as specified with no extra processing (with all that can emulate as if a user has filled in a HTML form and pressed the submit
newlines cut off). The data is expected to be "url-encoded". This will cause button. Note that the data is sent exactly as specified with no extra
curl to pass the data to the server using the content-type processing (with all newlines cut off). The data is expected to be
application/x-www-form-urlencoded. Compare to -F. If more than one -d/--data "url-encoded". This will cause curl to pass the data to the server using the
option is used on the same command line, the data pieces specified will be content-type application/x-www-form-urlencoded. Compare to -F. If more than
merged together with a separating &-letter. Thus, using '-d name=daniel -d one -d/--data option is used on the same command line, the data pieces
skill=lousy' would generate a post chunk that looks like specified will be merged together with a separating &-letter. Thus, using '-d
name=daniel -d skill=lousy' would generate a post chunk that looks like
'name=daniel&skill=lousy'. 'name=daniel&skill=lousy'.
If you start the data with the letter @, the rest should be a file name to If you start the data with the letter @, the rest should be a file name to
@@ -160,6 +175,11 @@ previous URL when it follows a Location: header. The ";auto" string can be
used alone, even if you don't set an initial referer. used alone, even if you don't set an initial referer.
If this option is used serveral times, the last one will be used. If this option is used serveral times, the last one will be used.
.IP "--egd-file <file>"
(HTTPS) Specify the path name to the Entropy Gathering Daemon socket. The
socket is used to seed the random engine for SSL connections. See also the
.I "--random-file"
option.
.IP "-E/--cert <certificate[:password]>" .IP "-E/--cert <certificate[:password]>"
(HTTPS) (HTTPS)
Tells curl to use the specified certificate file when getting a file Tells curl to use the specified certificate file when getting a file
@@ -283,6 +303,9 @@ If this option is used twice, the second will again disable location following.
Maximum time in seconds that you allow the whole operation to take. This is Maximum time in seconds that you allow the whole operation to take. This is
useful for preventing your batch jobs from hanging for hours due to slow useful for preventing your batch jobs from hanging for hours due to slow
networks or links going down. This doesn't work fully in win32 systems. networks or links going down. This doesn't work fully in win32 systems.
See also the
.I "--connect-timeout"
option.
If this option is used serveral times, the last one will be used. If this option is used serveral times, the last one will be used.
.IP "-M/--manual" .IP "-M/--manual"
@@ -377,6 +400,12 @@ to be run before and after the transfer. If the server returns failure for one
of the commands, the entire operation will be aborted. of the commands, the entire operation will be aborted.
This option can be used multiple times. This option can be used multiple times.
.IP "--random-file <file>"
(HTTPS) Specify the path name to file containing what will be considered as
random data. The data is used to seed the random engine for SSL connections.
See also the
.I "--edg-file"
option.
.IP "-r/--range <range>" .IP "-r/--range <range>"
(HTTP/FTP) (HTTP/FTP)
Retrieve a byte range (i.e a partial document) from a HTTP/1.1 or FTP Retrieve a byte range (i.e a partial document) from a HTTP/1.1 or FTP
@@ -425,11 +454,14 @@ If this option is used twice, the second will again disable mute.
When used with -s it makes curl show error message if it fails. When used with -s it makes curl show error message if it fails.
If this option is used twice, the second will again disable show error. If this option is used twice, the second will again disable show error.
.IP "-t/--upload" .IP "-t/--telnet-option <OPT=val>"
.B Deprecated. Use '-T -' instead. Pass options to the telnet protocol. Supported options are:
Transfer the stdin data to the specified file. Curl will read
everything from stdin until EOF and store with the supplied name. If TTYPE=<term> Sets the terminal type.
this is used on a http(s) server, the PUT command will be used.
XDISPLOC=<X display> Sets the X display location.
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 Like -t, but this transfers the specified local file. If there is no
file part in the specified URL, Curl will append the local file file part in the specified URL, Curl will append the local file
@@ -758,7 +790,7 @@ If you do find bugs, mail them to curl-bug@haxx.se.
- Lars J. Aas <larsa@sim.no> - Lars J. Aas <larsa@sim.no>
- J<>rn Hartroth <Joern.Hartroth@computer.org> - J<>rn Hartroth <Joern.Hartroth@computer.org>
- Matthew Clarke <clamat@van.maves.ca> - Matthew Clarke <clamat@van.maves.ca>
- Linus Nielsen <Linus.Nielsen@haxx.se> - Linus Nielsen Feltzing <linus@haxx.se>
- Felix von Leitner <felix@convergence.de> - Felix von Leitner <felix@convergence.de>
- Dan Zitter <dzitter@zitter.net> - Dan Zitter <dzitter@zitter.net>
- Jongki Suwandi <Jongki.Suwandi@eng.sun.com> - Jongki Suwandi <Jongki.Suwandi@eng.sun.com>

View File

@@ -2,13 +2,13 @@
.\" nroff -man [file] .\" nroff -man [file]
.\" Written by daniel@haxx.se .\" Written by daniel@haxx.se
.\" .\"
.TH curl_easy_cleanup 3 "22 May 2000" "Curl 7.0" "libcurl Manual" .TH curl_easy_cleanup 3 "5 March 2001" "libcurl 7.7" "libcurl Manual"
.SH NAME .SH NAME
curl_easy_cleanup - End a libcurl "easy" session curl_easy_cleanup - End a libcurl session
.SH SYNOPSIS .SH SYNOPSIS
.B #include <curl/easy.h> .B #include <curl/curl.h>
.sp .sp
.BI "curl_easy_cleanup(CURL *" handle "); .BI "curl_easy_cleanup(CURL *" handle ");"
.ad .ad
.SH DESCRIPTION .SH DESCRIPTION
This function must be the last function to call for a curl session. It is the This function must be the last function to call for a curl session. It is the
@@ -17,6 +17,10 @@ opposite of the
function and must be called with the same function and must be called with the same
.I handle .I handle
as input as the curl_easy_init call returned. as input as the curl_easy_init call returned.
This will effectively close all connections libcurl has been used and possibly
has kept open until now. Don't call this function if you intend to transfer
more files (libcurl 7.7 or later).
.SH RETURN VALUE .SH RETURN VALUE
None None
.SH "SEE ALSO" .SH "SEE ALSO"

View File

@@ -2,11 +2,11 @@
.\" nroff -man [file] .\" nroff -man [file]
.\" Written by daniel@haxx.se .\" Written by daniel@haxx.se
.\" .\"
.TH curl_easy_init 3 "4 February 2001" "Curl 7.6.1" "libcurl Manual" .TH curl_easy_init 3 "5 March 2001" "libcurl 7.6.1" "libcurl Manual"
.SH NAME .SH NAME
curl_easy_getinfo - Extract information from a curl session (added in 7.4) curl_easy_getinfo - Extract information from a curl session (added in 7.4)
.SH SYNOPSIS .SH SYNOPSIS
.B #include <curl/easy.h> .B #include <curl/curl.h>
.sp .sp
.BI "CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ... );" .BI "CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ... );"
.ad .ad
@@ -83,8 +83,8 @@ verification that was requested (using the CURLOPT_SSL_VERIFYPEER option to
curl_easy_setopt). (Added in 7.4.2) curl_easy_setopt). (Added in 7.4.2)
.TP .TP
.B CURLINFO_CONTENT_LENGTH_DOWNLOAD .B CURLINFO_CONTENT_LENGTH_DOWNLOAD
Pass a pointer to a double to receive the content-length of the download. Pass a pointer to a double to receive the content-length of the download. This
(Added in 7.6.1) is the value read from the Content-Length: field. (Added in 7.6.1)
.TP .TP
.B CURLINFO_CONTENT_LENGTH_UPLOAD .B CURLINFO_CONTENT_LENGTH_UPLOAD
Pass a pointer to a double to receive the specified size of the upload. Pass a pointer to a double to receive the specified size of the upload.

View File

@@ -2,11 +2,11 @@
.\" nroff -man [file] .\" nroff -man [file]
.\" Written by daniel@haxx.se .\" Written by daniel@haxx.se
.\" .\"
.TH curl_easy_init 3 "26 September 2000" "Curl 7.0" "libcurl Manual" .TH curl_easy_init 3 "5 March 2001" "libcurl 7.7" "libcurl Manual"
.SH NAME .SH NAME
curl_easy_init - Start a libcurl "easy" session curl_easy_init - Start a libcurl session
.SH SYNOPSIS .SH SYNOPSIS
.B #include <curl/easy.h> .B #include <curl/curl.h>
.sp .sp
.BI "CURL *curl_easy_init( );" .BI "CURL *curl_easy_init( );"
.ad .ad
@@ -19,6 +19,10 @@ when the operation is complete.
On win32 systems, you need to init the winsock stuff manually, libcurl will 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. not do that for you. WSAStartup() and WSACleanup() should be used accordingly.
Using libcurl 7.7 and later, you should perform all your sequential file
transfers using the same curl handle. This enables libcurl to use persistant
connections where possible.
.SH RETURN VALUE .SH RETURN VALUE
If this function returns NULL, something went wrong and you cannot use the If this function returns NULL, something went wrong and you cannot use the
other curl functions. other curl functions.

View File

@@ -2,11 +2,11 @@
.\" nroff -man [file] .\" nroff -man [file]
.\" Written by daniel@haxx.se .\" Written by daniel@haxx.se
.\" .\"
.TH curl_easy_perform 3 "25 Jan 2001" "Curl 7.0" "libcurl Manual" .TH curl_easy_perform 3 "5 Mar 2001" "libcurl 7.7" "libcurl Manual"
.SH NAME .SH NAME
curl_easy_perform - Do the actual transfer in a "easy" session curl_easy_perform - Perform a file transfer
.SH SYNOPSIS .SH SYNOPSIS
.B #include <curl/easy.h> .B #include <curl/curl.h>
.sp .sp
.BI "CURLcode curl_easy_perform(CURL *" handle "); .BI "CURLcode curl_easy_perform(CURL *" handle ");
.ad .ad
@@ -17,15 +17,28 @@ It must be called with the same
.I handle .I handle
as input as the curl_easy_init call returned. as input as the curl_easy_init call returned.
You are only allowed to call this function once using the same handle. If you libcurl version 7.7 or later (for older versions see below): You can do any
want to do repeated calls, you must call curl_easy_cleanup and curl_easy_init amount of calls to curl_easy_perform() while using the same handle. If you
again first. intend to transfer more than one file, you are even encouraged to do
so. libcurl will then attempt to re-use the same connection for the following
transfers, thus making the operations faster, less CPU intense and using less
network resources. Just note that you will have to use
.I curl_easy_setopt
between the invokes to set options for the following curl_easy_perform.
You must never call this function simultaneously from two places using the
same handle. Let the function return first before invoking it another time. If
you want parallel transfers, you must use several curl handles.
Before libcurl version 7.7: You are only allowed to call this function once
using the same handle. If you want to do repeated calls, you must call
curl_easy_cleanup and curl_easy_init again first.
.SH RETURN VALUE .SH RETURN VALUE
0 means everything was ok, non-zero means an error occurred as 0 means everything was ok, non-zero means an error occurred as
.I <curl/curl.h> .I <curl/curl.h>
defines. If the CURLOPT_ERRORBUFFER was set with defines. If the CURLOPT_ERRORBUFFER was set with
.I curl_easy_setopt .I curl_easy_setopt
there willo be a readable error message in the error buffer when non-zero is there will be a readable error message in the error buffer when non-zero is
returned. returned.
.SH "SEE ALSO" .SH "SEE ALSO"
.BR curl_easy_init "(3), " curl_easy_setopt "(3), " .BR curl_easy_init "(3), " curl_easy_setopt "(3), "

View File

@@ -2,11 +2,11 @@
.\" nroff -man [file] .\" nroff -man [file]
.\" Written by daniel@haxx.se .\" Written by daniel@haxx.se
.\" .\"
.TH curl_easy_setopt 3 "2 February 2001" "Curl 7.5" "libcurl Manual" .TH curl_easy_setopt 3 "13 March 2001" "libcurl 7.7" "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/easy.h> .B #include <curl/curl.h>
.sp .sp
.BI "CURLcode curl_easy_setopt(CURL *" handle ", CURLoption "option ", ...); .BI "CURLcode curl_easy_setopt(CURL *" handle ", CURLoption "option ", ...);
.ad .ad
@@ -20,7 +20,18 @@ followed by a parameter. That parameter can be a long, a function pointer or
an object pointer, all depending on what the option in question expects. Read an object pointer, all depending on what the option in question expects. Read
this manual carefully as bad input values may cause libcurl to behave badly! this manual carefully as bad input values may cause libcurl to behave badly!
You can only set one option in each function call. A typical application uses You can only set one option in each function call. A typical application uses
many calls in the setup phase. many curl_easy_setopt() calls in the setup phase.
NOTE: strings passed to libcurl as 'char *' arguments, will not be copied by
the library. Instead you should keep them available until libcurl no longer
needs them. Failing to do so will cause very odd behaviour or even crashes.
More note: the options set with this function call are valid for the
forthcoming data transfers that are performed when you invoke
.I curl_easy_perform .
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
transfers.
The The
.I "handle" .I "handle"
@@ -86,14 +97,16 @@ libcurl what the expected size of the infile is.
.TP .TP
.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. NOTE: this option is currently required! 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
before curl_easy_perform() 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 If you need libcurl to use a http proxy to access the outside world, set the
proxy string with this option. The parameter should be a char * to a zero proxy string with this option. The parameter should be a char * to a zero
terminated string. To specify port number in this string, append":[port]" to terminated string. To specify port number in this string, append :[port] to
the end of the host name. The proxy string may be prefixed with the end of the host name. The proxy string may be prefixed with
"[protocol]://" since any such prefix will be ignored. [protocol]:// since any such prefix will be ignored.
.TP .TP
.B CURLOPT_PROXYPORT .B CURLOPT_PROXYPORT
Set this long with this option to set the proxy port to use unless it is Set this long with this option to set the proxy port to use unless it is
@@ -189,9 +202,11 @@ prompted for it.
.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. The 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". .I "X-Y,N-M"
. Using this kind of multiple intervals will cause the HTTP server to send the
response document in pieces.
.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
@@ -202,7 +217,8 @@ library. The buffer must be at least CURL_ERROR_SIZE big.
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. Do note that normally, name lookups the libcurl transfer operation to take. Do note that normally, name lookups
maky take a considerable time and that limiting the operation to less than a maky take a considerable time and that limiting the operation to less than a
few minutes risk aborting perfectly normal operations. few minutes risk aborting perfectly normal operations. This option will cause
curl to use the SIGALRM to enable timeouting system calls.
.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
@@ -410,6 +426,59 @@ 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. This
option only makes sense if the CURLOPT_FOLLOWLOCATION is used at the same option only makes sense if the CURLOPT_FOLLOWLOCATION is used at the same
time. (Added in 7.5) time. (Added in 7.5)
.TP
.B CURLOPT_MAXCONNECTS
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
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
changes libcurl's behaviour. Note: if you have already performed transfers
with this curl handle, setting a smaller MAXCONNECTS than before may cause
open connections to unnecessarily get closed. (Added in 7.7)
.TP
.B CURLOPT_CLOSEPOLICY
Pass a long. This option sets what policy libcurl should use when the
connection cache is filled and one of the open connections has to be closed to
make room for a new connection. This must be one of the CURLCLOSEPOLICY_*
defines. Use CURLCLOSEPOLICY_LEAST_RECENTLY_USED to make libcurl close the
connection that was least recently used, that connection is also least likely
to be capable of re-use. Use CURLCLOSEPOLICY_OLDEST to make libcurl close the
oldest connection, the one that was created first among the ones in the
connection cache. The other close policies are not support yet. (Added in 7.7)
.TP
.B CURLOPT_FRESH_CONNECT
Pass a long. Set to non-zero to make the next transfer use a new connection by
force. If the connection cache is full before this connection, one of the
existinf connections will be closed as according to the set policy. This
option should be used with caution and only if you understand what it
does. Set to 0 to have libcurl attempt re-use of an existing connection.
(Added in 7.7)
.TP
.B CURLOPT_FORBID_REUSE
Pass a long. Set to non-zero to make the next transfer explicitly close the
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.
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
re-use. (Added in 7.7)
.TP
.B CURLOPT_RANDOM_FILE
Pass a char * to a zero terminated file name. The file will be used to read
from to seed the random engine for SSL. The more random the specified file is,
the more secure will the SSL connection become.
.TP
.B CURLOPT_FORBID_REUSE
Pass a char * to the zero terminated path name to the Entropy Gathering Daemon
socket. It will be used to seed the random engine for SSL.
.TP
.B CURLOPT_CONNECTTIMEOUT
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
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
timeouts). This option doesn't work in win32 systems. See also the
.I CURLOPT_TIMEOUT
option.
.PP .PP
.SH RETURN VALUE .SH RETURN VALUE
0 means the option was set properly, non-zero means an error as 0 means the option was set properly, non-zero means an error as

View File

@@ -2,7 +2,7 @@
.\" nroff -man [file] .\" nroff -man [file]
.\" Written by daniel@haxx.se .\" Written by daniel@haxx.se
.\" .\"
.TH curl_formfree 3 "17 November 2000" "Curl 7.5" "libcurl Manual" .TH curl_formfree 3 "5 March 2001" "libcurl 7.5" "libcurl Manual"
.SH NAME .SH NAME
curl_formfree - free a previously build multipart/formdata HTTP POST chain curl_formfree - free a previously build multipart/formdata HTTP POST chain
.SH SYNOPSIS .SH SYNOPSIS

View File

@@ -2,7 +2,7 @@
.\" nroff -man [file] .\" nroff -man [file]
.\" Written by daniel@haxx.se .\" Written by daniel@haxx.se
.\" .\"
.TH curl_formparse 3 "8 February 2001" "Curl 7.0" "libcurl Manual" .TH curl_formparse 3 "5 March 2001" "libcurl 7.0" "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
.SH SYNOPSIS .SH SYNOPSIS
@@ -42,14 +42,14 @@ Add a form field named 'name' with the contents as read from the local files
named 'filename1' and 'filename2'. This is identical to the upper, except that named 'filename1' and 'filename2'. This is identical to the upper, except that
you get the contents of several files in one section. you get the contents of several files in one section.
.TP .TP
.B [name]=@[filename];[content-type] .B [name]=@[filename];[type=<content-type>]
Whenever you specify a file to read from, you can optionally specify the Whenever you specify a file to read from, you can optionally specify the
content-type as well. The content-type is passed to the server together with content-type as well. The content-type is passed to the server together with
the contents of the file. curl_formparse() will guess content-type for a the contents of the file. curl_formparse() will guess content-type for a
number of well-known extensions and otherwise it will set it to binary. You number of well-known extensions and otherwise it will set it to binary. You
can override the internal decision by using this option. can override the internal decision by using this option.
.TP .TP
.B [name]=@[filename1,filename2,...];[content-type] .B [name]=@[filename1,filename2,...];[type=<content-type>]
When you specify several files to read the contents from, you can set the When you specify several files to read the contents from, you can set the
content-type for all of them in the same way as with a single file. content-type for all of them in the same way as with a single file.
.PP .PP

View File

@@ -2,7 +2,7 @@
.\" nroff -man [file] .\" nroff -man [file]
.\" Written by daniel@haxx.se .\" Written by daniel@haxx.se
.\" .\"
.TH curl_getdate 3 "2 June 2000" "Curl 7.0" "libcurl Manual" .TH curl_getdate 3 "5 March 2001" "libcurl 7.0" "libcurl Manual"
.SH NAME .SH NAME
curl_getdate - Convert an date in a ASCII string to number of seconds since curl_getdate - Convert an date in a ASCII string to number of seconds since
January 1, 1970 January 1, 1970

View File

@@ -2,7 +2,7 @@
.\" nroff -man [file] .\" nroff -man [file]
.\" Written by daniel@haxx.se .\" Written by daniel@haxx.se
.\" .\"
.TH curl_getenv 3 "2 June 2000" "Curl 7.0" "libcurl Manual" .TH curl_getenv 3 "5 March 2001" "libcurl 7.0" "libcurl Manual"
.SH NAME .SH NAME
curl_getenv - return value for environment name curl_getenv - return value for environment name
.SH SYNOPSIS .SH SYNOPSIS

View File

@@ -2,14 +2,14 @@
.\" nroff -man [file] .\" nroff -man [file]
.\" Written by daniel@haxx.se .\" Written by daniel@haxx.se
.\" .\"
.TH curl_slist_append 3 "2 June 2000" "Curl 7.0" "libcurl Manual" .TH curl_slist_append 3 "5 March 2001" "libcurl 7.0" "libcurl Manual"
.SH NAME .SH NAME
curl_slist_append - add a string to an slist 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_slit *" list,
.BI "char * "string ");" .BI "const char * "string ");"
.ad .ad
.SH DESCRIPTION .SH DESCRIPTION
curl_slist_append() appends a specified string to a linked list of curl_slist_append() appends a specified string to a linked list of

View File

@@ -2,13 +2,13 @@
.\" nroff -man [file] .\" nroff -man [file]
.\" Written by daniel@haxx.se .\" Written by daniel@haxx.se
.\" .\"
.TH curl_slist_free_all 3 "2 June 2000" "Curl 7.0" "libcurl Manual" .TH curl_slist_free_all 3 "5 March 2001" "libcurl 7.0" "libcurl Manual"
.SH NAME .SH NAME
curl_slist_free_all - free an entire curl_slist list curl_slist_free_all - free an entire curl_slist list
.SH SYNOPSIS .SH SYNOPSIS
.B #include <curl/curl.h> .B #include <curl/curl.h>
.sp .sp
.BI "void curl_slist_free_all(struct curl_slit *" list); .BI "void curl_slist_free_all(struct curl_slist *" list);
.ad .ad
.SH DESCRIPTION .SH DESCRIPTION
curl_slist_free_all() removes all traces of a previously built curl_slist curl_slist_free_all() removes all traces of a previously built curl_slist

View File

@@ -2,11 +2,11 @@
.\" nroff -man [file] .\" nroff -man [file]
.\" Written by daniel@haxx.se .\" Written by daniel@haxx.se
.\" .\"
.TH curl_version 3 "2 June 2000" "Curl 7.0" "libcurl Manual" .TH curl_version 3 "5 March 2001" "libcurl 7.0" "libcurl Manual"
.SH NAME .SH NAME
curl_version - returns the libcurl version string curl_version - returns the libcurl version string
.SH SYNOPSIS .SH SYNOPSIS
.B #include <curl/easy.h> .B #include <curl/curl.h>
.sp .sp
.BI "char *curl_version( );" .BI "char *curl_version( );"
.ad .ad
@@ -14,9 +14,9 @@ curl_version - returns the libcurl version string
Returns a human readable string with the version number of libcurl and some of Returns a human readable string with the version number of libcurl and some of
its important components (like OpenSSL version). its important components (like OpenSSL version).
Do note that this returns the actual running lib's version, you might have Note: this returns the actual running lib's version, you might have installed
installed a newer lib's include files in your system which may turn your a newer lib's include files in your system which may turn your LIBCURL_VERSION
LIBCURL_VERSION #define value to differ from this result. #define value to differ from this result.
.SH RETURN VALUE .SH RETURN VALUE
A pointer to a zero terminated string. A pointer to a zero terminated string.
.SH "SEE ALSO" .SH "SEE ALSO"

View File

@@ -5,7 +5,9 @@
AUTOMAKE_OPTIONS = foreign no-dependencies AUTOMAKE_OPTIONS = foreign no-dependencies
EXTRA_DIST = EXTRA_DIST =
README curlgtk.c sepheaders.c simple.c postit.c README curlgtk.c sepheaders.c simple.c postit.c \
win32sockets.c persistant.c \
getpageinvar.php simpleget.php simplepost.php
all: all:
@echo "done" @echo "done"

View File

@@ -6,3 +6,5 @@ advantage of libcurl.
If you end up with other small but still useful example sources, please mail If you end up with other small but still useful example sources, please mail
them for submission in future packages and on the web site. them for submission in future packages and on the web site.
Try the php/examples/ directory for PHP programming snippets!

View File

@@ -1,4 +1,12 @@
/* curlgtk.c */ /*****************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* $Id$
*/
/* Copyright (c) 2000 David Odin (aka DindinX) for MandrakeSoft */ /* Copyright (c) 2000 David Odin (aka DindinX) for MandrakeSoft */
/* an attempt to use the curl library in concert with a gtk-threaded application */ /* an attempt to use the curl library in concert with a gtk-threaded application */

View File

@@ -0,0 +1,53 @@
/*****************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* $Id$
*/
#include <stdio.h>
#include <unistd.h>
#include <curl/curl.h>
/* to make this work under windows, use the win32-functions from the
docs/examples/win32socket.c file as well */
/* This example REQUIRES libcurl 7.7 or later */
#if (LIBCURL_VERSION_NUM < 0x070700)
#error Too old libcurl version, upgrade or stay away.
#endif
int main(int argc, char **argv)
{
CURL *curl;
CURLcode res;
#ifdef MALLOCDEBUG
/* this sends all memory debug messages to a specified logfile */
curl_memdebug("memdump");
#endif
curl = curl_easy_init();
if(curl) {
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
curl_easy_setopt(curl, CURLOPT_HEADER, 1);
/* get the first document */
curl_easy_setopt(curl, CURLOPT_URL, "http://curl.haxx.se/");
res = curl_easy_perform(curl);
/* get another document from the same server using the same
connection */
curl_easy_setopt(curl, CURLOPT_URL, "http://curl.haxx.se/docs/");
res = curl_easy_perform(curl);
/* always cleanup */
curl_easy_cleanup(curl);
}
return 0;
}

View File

@@ -21,6 +21,9 @@
* This exact source code has not been verified to work. * 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 <stdio.h>
#include <curl/curl.h> #include <curl/curl.h>

View File

@@ -1,3 +1,16 @@
/*****************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* $Id$
*/
/* to make this work under windows, use the win32-functions from the
win32socket.c file as well */
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h> #include <unistd.h>

View File

@@ -1,9 +1,22 @@
/*****************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* $Id$
*/
#include <stdio.h> #include <stdio.h>
#include <curl/curl.h> #include <curl/curl.h>
#include <curl/types.h> #include <curl/types.h>
#include <curl/easy.h> #include <curl/easy.h>
/* to make this work under windows, use the win32-functions from the
win32socket.c file as well */
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
CURL *curl; CURL *curl;

View File

@@ -0,0 +1,40 @@
/*
* These are example functions doing socket init that Windows
* require. If you don't use windows, you can safely ignore this crap.
*/
static void win32_cleanup(void)
{
WSACleanup();
}
static CURLcode win32_init(void)
{
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD(1, 1);
err = WSAStartup(wVersionRequested, &wsaData);
if (err != 0)
/* Tell the user that we couldn't find a useable */
/* winsock.dll. */
return 1;
/* Confirm that the Windows Sockets DLL supports 1.1.*/
/* Note that if the DLL supports versions greater */
/* than 1.1 in addition to 1.1, it will still return */
/* 1.1 in wVersion since that is the version we */
/* requested. */
if ( LOBYTE( wsaData.wVersion ) != 1 ||
HIBYTE( wsaData.wVersion ) != 1 ) {
/* Tell the user that we couldn't find a useable */
/* winsock.dll. */
WSACleanup();
return 1;
}
return 0; /* 0 is ok */
}

View File

@@ -97,68 +97,57 @@ typedef int (*curl_passwd_callback)(void *clientp,
typedef enum { typedef enum {
CURLE_OK = 0, CURLE_OK = 0,
CURLE_UNSUPPORTED_PROTOCOL, CURLE_UNSUPPORTED_PROTOCOL, /* 1 */
CURLE_FAILED_INIT, CURLE_FAILED_INIT, /* 2 */
CURLE_URL_MALFORMAT, CURLE_URL_MALFORMAT, /* 3 */
CURLE_URL_MALFORMAT_USER, CURLE_URL_MALFORMAT_USER, /* 4 */
CURLE_COULDNT_RESOLVE_PROXY, CURLE_COULDNT_RESOLVE_PROXY, /* 5 */
CURLE_COULDNT_RESOLVE_HOST, CURLE_COULDNT_RESOLVE_HOST, /* 6 */
CURLE_COULDNT_CONNECT, CURLE_COULDNT_CONNECT, /* 7 */
CURLE_FTP_WEIRD_SERVER_REPLY, CURLE_FTP_WEIRD_SERVER_REPLY, /* 8 */
CURLE_FTP_ACCESS_DENIED, CURLE_FTP_ACCESS_DENIED, /* 9 */
CURLE_FTP_USER_PASSWORD_INCORRECT, CURLE_FTP_USER_PASSWORD_INCORRECT, /* 10 */
CURLE_FTP_WEIRD_PASS_REPLY, CURLE_FTP_WEIRD_PASS_REPLY, /* 11 */
CURLE_FTP_WEIRD_USER_REPLY, CURLE_FTP_WEIRD_USER_REPLY, /* 12 */
CURLE_FTP_WEIRD_PASV_REPLY, CURLE_FTP_WEIRD_PASV_REPLY, /* 13 */
CURLE_FTP_WEIRD_227_FORMAT, CURLE_FTP_WEIRD_227_FORMAT, /* 14 */
CURLE_FTP_CANT_GET_HOST, CURLE_FTP_CANT_GET_HOST, /* 15 */
CURLE_FTP_CANT_RECONNECT, CURLE_FTP_CANT_RECONNECT, /* 16 */
CURLE_FTP_COULDNT_SET_BINARY, CURLE_FTP_COULDNT_SET_BINARY, /* 17 */
CURLE_PARTIAL_FILE, CURLE_PARTIAL_FILE, /* 18 */
CURLE_FTP_COULDNT_RETR_FILE, CURLE_FTP_COULDNT_RETR_FILE, /* 19 */
CURLE_FTP_WRITE_ERROR, CURLE_FTP_WRITE_ERROR, /* 20 */
CURLE_FTP_QUOTE_ERROR, CURLE_FTP_QUOTE_ERROR, /* 21 */
CURLE_HTTP_NOT_FOUND, CURLE_HTTP_NOT_FOUND, /* 22 */
CURLE_WRITE_ERROR, CURLE_WRITE_ERROR, /* 23 */
CURLE_MALFORMAT_USER, /* 24 - user name is illegally specified */
CURLE_FTP_COULDNT_STOR_FILE, /* 25 - failed FTP upload */
CURLE_READ_ERROR, /* 26 - could open/read from file */
CURLE_OUT_OF_MEMORY, /* 27 */
CURLE_OPERATION_TIMEOUTED, /* 28 - the timeout time was reached */
CURLE_FTP_COULDNT_SET_ASCII, /* 29 - TYPE A failed */
CURLE_FTP_PORT_FAILED, /* 30 - FTP PORT operation failed */
CURLE_FTP_COULDNT_USE_REST, /* 31 - the REST command failed */
CURLE_FTP_COULDNT_GET_SIZE, /* 32 - the SIZE command failed */
CURLE_HTTP_RANGE_ERROR, /* 33 - RANGE "command" didn't work */
CURLE_HTTP_POST_ERROR, /* 34 */
CURLE_SSL_CONNECT_ERROR, /* 35 - wrong when connecting with SSL */
CURLE_FTP_BAD_DOWNLOAD_RESUME, /* 36 - couldn't resume download */
CURLE_FILE_COULDNT_READ_FILE, /* 37 */
CURLE_LDAP_CANNOT_BIND, /* 38 */
CURLE_LDAP_SEARCH_FAILED, /* 39 */
CURLE_LIBRARY_NOT_FOUND, /* 40 */
CURLE_FUNCTION_NOT_FOUND, /* 41 */
CURLE_ABORTED_BY_CALLBACK, /* 42 */
CURLE_BAD_FUNCTION_ARGUMENT, /* 43 */
CURLE_BAD_CALLING_ORDER, /* 44 */
CURLE_HTTP_PORT_FAILED, /* 45 - HTTP Interface operation failed */
CURLE_BAD_PASSWORD_ENTERED, /* 46 - my_getpass() returns fail */
CURLE_TOO_MANY_REDIRECTS , /* 47 - catch endless re-direct loops */
CURLE_UNKNOWN_TELNET_OPTION, /* 48 - User specified an unknown option */
CURLE_TELNET_OPTION_SYNTAX , /* 49 - Malformed telnet option */
CURLE_MALFORMAT_USER, /* the user name is illegally specified */ CURL_LAST /* never use! */
CURLE_FTP_COULDNT_STOR_FILE, /* failed FTP upload */
CURLE_READ_ERROR, /* could open/read from file */
CURLE_OUT_OF_MEMORY,
CURLE_OPERATION_TIMEOUTED, /* the timeout time was reached */
CURLE_FTP_COULDNT_SET_ASCII, /* TYPE A failed */
CURLE_FTP_PORT_FAILED, /* FTP PORT operation failed */
CURLE_FTP_COULDNT_USE_REST, /* the REST command failed */
CURLE_FTP_COULDNT_GET_SIZE, /* the SIZE command failed */
CURLE_HTTP_RANGE_ERROR, /* The RANGE "command" didn't seem to work */
CURLE_HTTP_POST_ERROR,
CURLE_SSL_CONNECT_ERROR, /* something was wrong when connecting with SSL */
CURLE_FTP_BAD_DOWNLOAD_RESUME, /* couldn't resume download */
CURLE_FILE_COULDNT_READ_FILE,
CURLE_LDAP_CANNOT_BIND,
CURLE_LDAP_SEARCH_FAILED,
CURLE_LIBRARY_NOT_FOUND,
CURLE_FUNCTION_NOT_FOUND,
CURLE_ABORTED_BY_CALLBACK,
CURLE_BAD_FUNCTION_ARGUMENT,
CURLE_BAD_CALLING_ORDER,
CURLE_HTTP_PORT_FAILED, /* HTTP Interface operation failed */
CURLE_BAD_PASSWORD_ENTERED, /* when the my_getpass() returns fail */
CURLE_TOO_MANY_REDIRECTS , /* catch endless re-direct loops */
CURL_LAST
} CURLcode; } CURLcode;
/* This is just to make older programs not break: */ /* This is just to make older programs not break: */
@@ -406,6 +395,41 @@ typedef enum {
document! Pass a NULL to shut it off. */ document! Pass a NULL to shut it off. */
CINIT(FILETIME, OBJECTPOINT, 69), CINIT(FILETIME, OBJECTPOINT, 69),
/* This points to a linked list of telnet options */
CINIT(TELNETOPTIONS, OBJECTPOINT, 70),
/* Max amount of cached alive connections */
CINIT(MAXCONNECTS, LONG, 71),
/* What policy to use when closing connections when the cache is filled
up */
CINIT(CLOSEPOLICY, LONG, 72),
/* Callback to use when CURLCLOSEPOLICY_CALLBACK is set */
CINIT(CLOSEFUNCTION, FUNCTIONPOINT, 73),
/* Set to explicitly use a new connection for the upcoming transfer.
Do not use this unless you're absolutely sure of this, as it makes the
operation slower and is less friendly for the network. */
CINIT(FRESH_CONNECT, LONG, 74),
/* Set to explicitly forbid the upcoming transfer's connection to be re-used
when done. Do not use this unless you're absolutely sure of this, as it
makes the operation slower and is less friendly for the network. */
CINIT(FORBID_REUSE, LONG, 75),
/* Set to a file name that contains random data for libcurl to use to
seed the random engine when doing SSL connects. */
CINIT(RANDOM_FILE, OBJECTPOINT, 76),
/* Set to the Entropy Gathering Daemon socket pathname */
CINIT(EGDSOCKET, OBJECTPOINT, 77),
/* Time-out connect operations after this amount of seconds, if connects
are OK within this time, then fine... This only aborts the connect
phase. [Only works on unix-style/SIGALRM operating systems] */
CINIT(CONNECTTIMEOUT, LONG, 78),
CURLOPT_LASTENTRY /* the last unusued */ CURLOPT_LASTENTRY /* the last unusued */
} CURLoption; } CURLoption;
@@ -431,10 +455,10 @@ typedef enum {
NOTE: they return TRUE if the strings match *case insensitively*. NOTE: they return TRUE if the strings match *case insensitively*.
*/ */
extern int (Curl_strequal)(const char *s1, const char *s2); extern int (curl_strequal)(const char *s1, const char *s2);
extern int (Curl_strnequal)(const char *s1, const char *s2, size_t n); extern int (curl_strnequal)(const char *s1, const char *s2, size_t n);
#define strequal(a,b) Curl_strequal(a,b) #define strequal(a,b) curl_strequal(a,b)
#define strnequal(a,b,c) Curl_strnequal(a,b,c) #define strnequal(a,b,c) curl_strnequal(a,b,c)
/* external form function */ /* external form function */
int curl_formparse(char *string, int curl_formparse(char *string,
@@ -452,8 +476,8 @@ char *curl_getenv(char *variable);
char *curl_version(void); char *curl_version(void);
/* This is the version number */ /* This is the version number */
#define LIBCURL_VERSION "7.6.1" #define LIBCURL_VERSION "7.7-beta5"
#define LIBCURL_VERSION_NUM 0x070601 #define LIBCURL_VERSION_NUM 0x070700
/* 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 {
@@ -461,184 +485,8 @@ struct curl_slist {
struct curl_slist *next; struct curl_slist *next;
}; };
struct curl_slist *curl_slist_append(struct curl_slist *list, char *data); struct curl_slist *curl_slist_append(struct curl_slist *, const char *);
void curl_slist_free_all(struct curl_slist *list); void curl_slist_free_all(struct curl_slist *);
/*
* NAME curl_init()
*
* DESCRIPTION
*
* Inits libcurl globally. This must be used before any libcurl calls can
* be used. This may install global plug-ins or whatever. (This does not
* do winsock inits in Windows.)
*
* EXAMPLE
*
* curl_init();
*
*/
CURLcode curl_init(void);
/*
* NAME curl_init()
*
* DESCRIPTION
*
* Frees libcurl globally. This must be used after all libcurl calls have
* been used. This may remove global plug-ins or whatever. (This does not
* do winsock cleanups in Windows.)
*
* EXAMPLE
*
* curl_free(curl);
*
*/
void curl_free(void);
/*
* NAME curl_open()
*
* DESCRIPTION
*
* Opens a general curl session. It does not try to connect or do anything
* on the network because of this call. The specified URL is only required
* to enable curl to figure out what protocol to "activate".
*
* A session should be looked upon as a series of requests to a single host. A
* session interacts with one host only, using one single protocol.
*
* The URL is not required. If set to "" or NULL, it can still be set later
* using the curl_setopt() function. If the curl_connect() function is called
* without the URL being known, it will return error.
*
* EXAMPLE
*
* CURLcode result;
* CURL *curl;
* result = curl_open(&curl, "http://curl.haxx.nu/libcurl/");
* if(result != CURL_OK) {
* return result;
* }
* */
CURLcode curl_open(CURL **curl, char *url);
/*
* NAME curl_setopt()
*
* DESCRIPTION
*
* Sets a particular option to the specified value.
*
* EXAMPLE
*
* CURL curl;
* curl_setopt(curl, CURL_HTTP_FOLLOW_LOCATION, TRUE);
*/
CURLcode curl_setopt(CURL *handle, CURLoption option, ...);
/*
* NAME curl_close()
*
* DESCRIPTION
*
* Closes a session previously opened with curl_open()
*
* EXAMPLE
*
* CURL *curl;
* CURLcode result;
*
* result = curl_close(curl);
*/
CURLcode curl_close(CURL *curl); /* the opposite of curl_open() */
CURLcode curl_read(CURLconnect *c_conn, char *buf, size_t buffersize,
ssize_t *n);
CURLcode curl_write(CURLconnect *c_conn, char *buf, size_t amount,
size_t *n);
/*
* NAME curl_connect()
*
* DESCRIPTION
*
* Connects to the peer server and performs the initial setup. This function
* writes a connect handle to its second argument that is a unique handle for
* this connect. This allows multiple connects from the same handle returned
* by curl_open().
*
* EXAMPLE
*
* CURLCode result;
* CURL curl;
* CURLconnect connect;
* result = curl_connect(curl, &connect);
*/
CURLcode curl_connect(CURL *curl, CURLconnect **in_connect);
/*
* NAME curl_do()
*
* DESCRIPTION
*
* (Note: May 3rd 2000: this function does not currently allow you to
* specify a document, it will use the one set previously)
*
* This function asks for the particular document, file or resource that
* resides on the server we have connected to. You may specify a full URL,
* just an absolute path or even a relative path. That means, if you're just
* getting one file from the remote site, you can use the same URL as input
* for both curl_open() as well as for this function.
*
* In the even there is a host name, port number, user name or password parts
* in the URL, you can use the 'flags' argument to ignore them completely, or
* at your choice, make the function fail if you're trying to get a URL from
* different host than you connected to with curl_connect().
*
* You can only get one document at a time using the same connection. When one
* document has been received you can although request again.
*
* When the transfer is done, curl_done() MUST be called.
*
* EXAMPLE
*
* CURLCode result;
* char *url;
* CURLconnect *connect;
* result = curl_do(connect, url, CURL_DO_NONE); */
CURLcode curl_do(CURLconnect *in_conn);
/*
* NAME curl_done()
*
* DESCRIPTION
*
* When the transfer following a curl_do() call is done, this function should
* get called.
*
* EXAMPLE
*
* CURLCode result;
* char *url;
* CURLconnect *connect;
* result = curl_done(connect); */
CURLcode curl_done(CURLconnect *connect);
/*
* NAME curl_disconnect()
*
* DESCRIPTION
*
* Disconnects from the peer server and performs connection cleanup.
*
* EXAMPLE
*
* CURLcode result;
* CURLconnect *connect;
* result = curl_disconnect(connect); */
CURLcode curl_disconnect(CURLconnect *connect);
/* /*
* NAME curl_getdate() * NAME curl_getdate()
@@ -682,19 +530,22 @@ typedef enum {
CURLINFO_LASTONE = 17 CURLINFO_LASTONE = 17
} CURLINFO; } CURLINFO;
/* /* unfortunately, the easy.h include file needs the options and info stuff
* NAME curl_getinfo() before it can be included! */
* #include <curl/easy.h> /* nothing in curl is fun without the easy stuff */
* DESCRIPTION
* typedef enum {
* Request internal information from the curl session with this function. CURLCLOSEPOLICY_NONE, /* first, never use this */
* The third argument MUST be a pointer to a long or a pointer to a char *.
* The data pointed to will be filled in accordingly and can be relied upon CURLCLOSEPOLICY_OLDEST,
* only if the function returns CURLE_OK. CURLCLOSEPOLICY_LEAST_RECENTLY_USED,
* This function is intended to get used *AFTER* a performed transfer, all CURLCLOSEPOLICY_LEAST_TRAFFIC,
* results are undefined before the transfer is completed. CURLCLOSEPOLICY_SLOWEST,
*/ CURLCLOSEPOLICY_CALLBACK,
CURLcode curl_getinfo(CURL *curl, CURLINFO info, ...);
CURLCLOSEPOLICY_LAST /* last, never use this */
} curl_closepolicy;
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@@ -6,7 +6,7 @@ AUTOMAKE_OPTIONS = foreign
EXTRA_DIST = getdate.y \ EXTRA_DIST = getdate.y \
Makefile.b32 Makefile.b32.resp Makefile.m32 Makefile.vc6 \ Makefile.b32 Makefile.b32.resp Makefile.m32 Makefile.vc6 \
libcurl.def dllinit.c libcurl.def dllinit.c curllib.dsp curllib.dsw
lib_LTLIBRARIES = libcurl.la lib_LTLIBRARIES = libcurl.la
@@ -16,7 +16,7 @@ lib_LTLIBRARIES = libcurl.la
INCLUDES = -I$(top_srcdir)/include INCLUDES = -I$(top_srcdir)/include
libcurl_la_LDFLAGS = -version-info 1:0:0 libcurl_la_LDFLAGS = -version-info 2:0: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.
@@ -58,7 +58,8 @@ getenv.c ldap.h ssluse.h \
escape.c mprintf.c telnet.c \ escape.c mprintf.c telnet.c \
escape.h getpass.c netrc.c telnet.h \ escape.h getpass.c netrc.c telnet.h \
getinfo.c transfer.c strequal.c strequal.h easy.c \ getinfo.c 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
noinst_HEADERS = setup.h transfer.h noinst_HEADERS = setup.h transfer.h

View File

@@ -33,13 +33,13 @@ libcurl_a_SOURCES = arpa_telnet.h file.c getpass.h netrc.h timeval.c base64.c \
urldata.h transfer.c getdate.h ldap.c ssluse.c version.c transfer.h getenv.c \ urldata.h transfer.c getdate.h ldap.c ssluse.c version.c transfer.h getenv.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.c security.c krb4.h krb4.c memdebug.h memdebug.c inet_ntoa_r.h http_chunks.h http_chunks.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 strequal.o easy.o security.o krb4.o memdebug.o http_chunks.o
LIBRARIES = $(libcurl_a_LIBRARIES) LIBRARIES = $(libcurl_a_LIBRARIES)
SOURCES = $(libcurl_a_SOURCES) SOURCES = $(libcurl_a_SOURCES)

367
lib/curllib.dsp Normal file
View File

@@ -0,0 +1,367 @@
# Microsoft Developer Studio Project File - Name="curllib" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
CFG=curllib - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "curllib.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "curllib.mak" CFG="curllib - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "curllib - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE "curllib - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
MTL=midl.exe
RSC=rc.exe
!IF "$(CFG)" == "curllib - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release"
# PROP Ignore_Export_Lib 0
# 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 CPP /nologo /MT /W3 /GX /O2 /I "C:\jdk1.3.0_01\include" /I "C:\jdk1.3.0_01\include\win32" /I "..\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CURLLIB_EXPORTS" /YX /FD /c
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
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 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 wsock32.lib /nologo /dll /machine:I386 /out:"Release/curl.dll"
!ELSEIF "$(CFG)" == "curllib - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug"
# PROP BASE Intermediate_Dir "Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug"
# PROP Intermediate_Dir "Debug"
# PROP Ignore_Export_Lib 0
# 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 CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "C:\jdk1.3.0_01\include" /I "C:\jdk1.3.0_01\include\win32" /I "..\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CURLLIB_EXPORTS" /YX /FD /GZ /c
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
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 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 wsock32.lib /nologo /dll /debug /machine:I386 /out:"Debug/curl.dll" /pdbtype:sept
!ENDIF
# Begin Target
# Name "curllib - Win32 Release"
# Name "curllib - Win32 Debug"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
SOURCE=.\base64.c
# End Source File
# Begin Source File
SOURCE=.\cookie.c
# End Source File
# Begin Source File
SOURCE=.\dict.c
# End Source File
# Begin Source File
SOURCE=.\dllinit.c
# End Source File
# Begin Source File
SOURCE=.\easy.c
# End Source File
# Begin Source File
SOURCE=.\easyswig.c
# End Source File
# Begin Source File
SOURCE=.\easyswig_wrap.c
# End Source File
# Begin Source File
SOURCE=.\escape.c
# End Source File
# Begin Source File
SOURCE=.\file.c
# End Source File
# Begin Source File
SOURCE=.\formdata.c
# End Source File
# Begin Source File
SOURCE=.\ftp.c
# End Source File
# Begin Source File
SOURCE=.\getdate.c
# End Source File
# Begin Source File
SOURCE=.\getenv.c
# End Source File
# Begin Source File
SOURCE=.\getinfo.c
# End Source File
# Begin Source File
SOURCE=.\getpass.c
# End Source File
# Begin Source File
SOURCE=.\hostip.c
# End Source File
# Begin Source File
SOURCE=.\http.c
# End Source File
# Begin Source File
SOURCE=.\if2ip.c
# End Source File
# Begin Source File
SOURCE=.\krb4.c
# End Source File
# Begin Source File
SOURCE=.\ldap.c
# End Source File
# Begin Source File
SOURCE=.\libcurl.def
# End Source File
# Begin Source File
SOURCE=.\memdebug.c
# End Source File
# Begin Source File
SOURCE=.\mprintf.c
# End Source File
# Begin Source File
SOURCE=.\netrc.c
# End Source File
# Begin Source File
SOURCE=.\progress.c
# End Source File
# Begin Source File
SOURCE=.\security.c
# End Source File
# Begin Source File
SOURCE=.\sendf.c
# End Source File
# Begin Source File
SOURCE=.\speedcheck.c
# End Source File
# Begin Source File
SOURCE=.\ssluse.c
# End Source File
# Begin Source File
SOURCE=.\strequal.c
# End Source File
# Begin Source File
SOURCE=.\telnet.c
# End Source File
# Begin Source File
SOURCE=.\timeval.c
# End Source File
# Begin Source File
SOURCE=.\transfer.c
# End Source File
# Begin Source File
SOURCE=.\url.c
# End Source File
# Begin Source File
SOURCE=.\version.c
# End Source File
# End Group
# Begin Group "Header Files"
# PROP Default_Filter "h;hpp;hxx;hm;inl"
# Begin Source File
SOURCE=.\arpa_telnet.h
# End Source File
# Begin Source File
SOURCE=.\base64.h
# End Source File
# Begin Source File
SOURCE=.\cookie.h
# End Source File
# Begin Source File
SOURCE=.\dict.h
# End Source File
# Begin Source File
SOURCE=.\escape.h
# End Source File
# Begin Source File
SOURCE=.\file.h
# End Source File
# Begin Source File
SOURCE=.\formdata.h
# End Source File
# Begin Source File
SOURCE=.\ftp.h
# End Source File
# Begin Source File
SOURCE=.\getdate.h
# End Source File
# Begin Source File
SOURCE=.\getenv.h
# End Source File
# Begin Source File
SOURCE=.\getpass.h
# End Source File
# Begin Source File
SOURCE=.\hostip.h
# End Source File
# Begin Source File
SOURCE=.\http.h
# End Source File
# Begin Source File
SOURCE=.\if2ip.h
# End Source File
# Begin Source File
SOURCE=.\inet_ntoa_r.h
# End Source File
# Begin Source File
SOURCE=.\krb4.h
# End Source File
# Begin Source File
SOURCE=.\ldap.h
# End Source File
# Begin Source File
SOURCE=.\memdebug.h
# End Source File
# Begin Source File
SOURCE=.\netrc.h
# End Source File
# Begin Source File
SOURCE=.\progress.h
# End Source File
# Begin Source File
SOURCE=.\security.h
# End Source File
# Begin Source File
SOURCE=.\sendf.h
# End Source File
# Begin Source File
SOURCE=.\setup.h
# End Source File
# Begin Source File
SOURCE=.\speedcheck.h
# End Source File
# Begin Source File
SOURCE=.\ssluse.h
# End Source File
# Begin Source File
SOURCE=.\strequal.h
# End Source File
# Begin Source File
SOURCE=.\telnet.h
# End Source File
# Begin Source File
SOURCE=.\timeval.h
# End Source File
# Begin Source File
SOURCE=.\transfer.h
# End Source File
# Begin Source File
SOURCE=.\url.h
# End Source File
# Begin Source File
SOURCE=.\urldata.h
# End Source File
# End Group
# Begin Group "Resource Files"
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
# End Group
# End Target
# End Project

29
lib/curllib.dsw Normal file
View File

@@ -0,0 +1,29 @@
Microsoft Developer Studio Workspace File, Format Version 6.00
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
###############################################################################
Project: "curllib"=".\curllib.dsp" - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Global:
Package=<5>
{{{
}}}
Package=<3>
{{{
}}}
###############################################################################

View File

@@ -100,7 +100,7 @@ CURLcode Curl_dict(struct connectdata *conn)
char *path = conn->path; char *path = conn->path;
long *bytecount = &conn->bytecount; long *bytecount = &conn->bytecount;
if(data->bits.user_passwd) { if(conn->bits.user_passwd) {
/* AUTH is missing */ /* AUTH is missing */
} }
@@ -141,7 +141,7 @@ CURLcode Curl_dict(struct connectdata *conn)
nth = atoi(nthdef); nth = atoi(nthdef);
} }
Curl_sendf(data->firstsocket, conn, Curl_sendf(conn->firstsocket, conn,
"CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\n" "CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\n"
"MATCH " "MATCH "
"%s " /* database */ "%s " /* database */
@@ -154,7 +154,7 @@ CURLcode Curl_dict(struct connectdata *conn)
word word
); );
result = Curl_Transfer(conn, data->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)
@@ -191,7 +191,7 @@ CURLcode Curl_dict(struct connectdata *conn)
nth = atoi(nthdef); nth = atoi(nthdef);
} }
Curl_sendf(data->firstsocket, conn, Curl_sendf(conn->firstsocket, conn,
"CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\n" "CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\n"
"DEFINE " "DEFINE "
"%s " /* database */ "%s " /* database */
@@ -202,7 +202,7 @@ CURLcode Curl_dict(struct connectdata *conn)
word word
); );
result = Curl_Transfer(conn, data->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)
@@ -220,13 +220,13 @@ CURLcode Curl_dict(struct connectdata *conn)
if (ppath[i] == ':') if (ppath[i] == ':')
ppath[i] = ' '; ppath[i] = ' ';
} }
Curl_sendf(data->firstsocket, conn, 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);
result = Curl_Transfer(conn, data->firstsocket, -1, FALSE, bytecount, result = Curl_Transfer(conn, conn->firstsocket, -1, FALSE, bytecount,
-1, NULL); -1, NULL);
if(result) if(result)

View File

@@ -83,15 +83,11 @@ CURL *curl_easy_init(void)
CURLcode res; CURLcode res;
struct UrlData *data; struct UrlData *data;
if(curl_init())
return NULL;
/* We use curl_open() with undefined URL so far */ /* We use curl_open() with undefined URL so far */
res = curl_open((CURL **)&data, NULL); res = Curl_open((CURL **)&data, NULL);
if(res != CURLE_OK) if(res != CURLE_OK)
return NULL; return NULL;
data->interf = CURLI_EASY; /* mark it as an easy one */
/* SAC */ /* SAC */
data->device = NULL; data->device = NULL;
@@ -119,16 +115,16 @@ CURLcode curl_easy_setopt(CURL *curl, CURLoption tag, ...)
if(tag < CURLOPTTYPE_OBJECTPOINT) { if(tag < CURLOPTTYPE_OBJECTPOINT) {
/* This is a LONG type */ /* This is a LONG type */
param_long = va_arg(arg, long); param_long = va_arg(arg, long);
curl_setopt(data, tag, param_long); Curl_setopt(data, tag, param_long);
} }
else if(tag < CURLOPTTYPE_FUNCTIONPOINT) { else if(tag < CURLOPTTYPE_FUNCTIONPOINT) {
/* This is a object pointer type */ /* This is a object pointer type */
param_obj = va_arg(arg, void *); param_obj = va_arg(arg, void *);
curl_setopt(data, tag, param_obj); Curl_setopt(data, tag, param_obj);
} }
else { else {
param_func = va_arg(arg, func_T ); param_func = va_arg(arg, func_T );
curl_setopt(data, tag, param_func); Curl_setopt(data, tag, param_func);
} }
va_end(arg); va_end(arg);
@@ -137,13 +133,12 @@ CURLcode curl_easy_setopt(CURL *curl, CURLoption tag, ...)
CURLcode curl_easy_perform(CURL *curl) CURLcode curl_easy_perform(CURL *curl)
{ {
return curl_transfer(curl); return Curl_perform(curl);
} }
void curl_easy_cleanup(CURL *curl) void curl_easy_cleanup(CURL *curl)
{ {
curl_close(curl); Curl_close(curl);
curl_free();
} }
CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ...) CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ...)
@@ -153,5 +148,5 @@ CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ...)
va_start(arg, info); va_start(arg, info);
paramp = va_arg(arg, void *); paramp = va_arg(arg, void *);
return curl_getinfo(curl, info, paramp); return Curl_getinfo(curl, info, paramp);
} }

View File

@@ -78,7 +78,7 @@ char *curl_unescape(char *string, int length)
char *ns = malloc(alloc); char *ns = malloc(alloc);
unsigned char in; unsigned char in;
int index=0; int index=0;
int hex; unsigned int hex;
char querypart=FALSE; /* everything to the right of a '?' letter is char querypart=FALSE; /* everything to the right of a '?' letter is
the "query part" where '+' should become ' '. the "query part" where '+' should become ' '.
RFC 2316, section 3.10 */ RFC 2316, section 3.10 */

View File

@@ -91,29 +91,24 @@
#include "memdebug.h" #include "memdebug.h"
#endif #endif
CURLcode file(struct connectdata *conn) /* Emulate a connect-then-transfer protocol. We connect to the file here */
CURLcode Curl_file_connect(struct connectdata *conn)
{ {
/* This implementation ignores the host name in conformance with char *actual_path = curl_unescape(conn->path, 0);
RFC 1738. Only local files (reachable via the standard file system) struct FILE *file;
are supported. This means that files on remotely mounted directories
(via NFS, Samba, NT sharing) can be accessed through a file:// URL
*/
CURLcode res = CURLE_OK;
char *path = conn->path;
struct stat statbuf;
size_t expected_size=-1;
size_t nread;
struct UrlData *data = conn->data;
char *buf = data->buffer;
int bytecount = 0;
struct timeval start = Curl_tvnow();
struct timeval now = start;
int fd; int fd;
char *actual_path = curl_unescape(path, 0);
#if defined(WIN32) || defined(__EMX__) #if defined(WIN32) || defined(__EMX__)
int i; int i;
#endif
file = (struct FILE *)malloc(sizeof(struct FILE));
if(!file)
return CURLE_OUT_OF_MEMORY;
memset(file, 0, sizeof(struct FILE));
conn->proto.file = file;
#if defined(WIN32) || defined(__EMX__)
/* change path separators from '/' to '\\' for Windows and OS/2 */ /* change path separators from '/' to '\\' for Windows and OS/2 */
for (i=0; actual_path[i] != '\0'; ++i) for (i=0; actual_path[i] != '\0'; ++i)
if (actual_path[i] == '/') if (actual_path[i] == '/')
@@ -126,9 +121,37 @@ CURLcode file(struct connectdata *conn)
free(actual_path); free(actual_path);
if(fd == -1) { if(fd == -1) {
failf(data, "Couldn't open file %s", path); failf(conn->data, "Couldn't open file %s", conn->path);
return CURLE_FILE_COULDNT_READ_FILE; return CURLE_FILE_COULDNT_READ_FILE;
} }
file->fd = fd;
return CURLE_OK;
}
/* This is the do-phase, separated from the connect-phase above */
CURLcode Curl_file(struct connectdata *conn)
{
/* This implementation ignores the host name in conformance with
RFC 1738. Only local files (reachable via the standard file system)
are supported. This means that files on remotely mounted directories
(via NFS, Samba, NT sharing) can be accessed through a file:// URL
*/
CURLcode res = CURLE_OK;
struct stat statbuf;
size_t expected_size=-1;
size_t nread;
struct UrlData *data = conn->data;
char *buf = data->buffer;
int bytecount = 0;
struct timeval start = Curl_tvnow();
struct timeval now = start;
int fd;
/* get the fd from the connection phase */
fd = conn->proto.file->fd;
if( -1 != fstat(fd, &statbuf)) { if( -1 != fstat(fd, &statbuf)) {
/* we could stat it, then read out the size */ /* we could stat it, then read out the size */
expected_size = statbuf.st_size; expected_size = statbuf.st_size;

View File

@@ -23,6 +23,6 @@
* *
* $Id$ * $Id$
*****************************************************************************/ *****************************************************************************/
CURLcode file(struct connectdata *conn); CURLcode Curl_file(struct connectdata *conn);
CURLcode Curl_file_connect(struct connectdata *conn);
#endif #endif

349
lib/ftp.c
View File

@@ -77,6 +77,8 @@
#include "krb4.h" #include "krb4.h"
#endif #endif
#include "strequal.h"
#define _MPRINTF_REPLACE /* use our functions only */ #define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h> #include <curl/mprintf.h>
@@ -88,76 +90,8 @@
/* easy-to-use macro: */ /* easy-to-use macro: */
#define ftpsendf Curl_ftpsendf #define ftpsendf Curl_ftpsendf
/* returns last node in linked list */
static struct curl_slist *slist_get_last(struct curl_slist *list)
{
struct curl_slist *item;
/* if caller passed us a NULL, return now */
if (!list)
return NULL;
/* loop through to find the last item */
item = list;
while (item->next) {
item = item->next;
}
return item;
}
/* append a struct to the linked list. It always retunrs the address of the
* first record, so that you can sure this function as an initialization
* function as well as an append function. If you find this bothersome,
* then simply create a separate _init function and call it appropriately from
* within the proram. */
struct curl_slist *curl_slist_append(struct curl_slist *list, char *data)
{
struct curl_slist *last;
struct curl_slist *new_item;
new_item = (struct curl_slist *) malloc(sizeof(struct curl_slist));
if (new_item) {
new_item->next = NULL;
new_item->data = strdup(data);
}
else {
fprintf(stderr, "Cannot allocate memory for QUOTE list.\n");
return NULL;
}
if (list) {
last = slist_get_last(list);
last->next = new_item;
return list;
}
/* if this is the first item, then new_item *is* the list */
return new_item;
}
/* be nice and clean up resources */
void curl_slist_free_all(struct curl_slist *list)
{
struct curl_slist *next;
struct curl_slist *item;
if (!list)
return;
item = list;
do {
next = item->next;
if (item->data) {
free(item->data);
}
free(item);
item = next;
} while (next);
}
static CURLcode AllowServerConnect(struct UrlData *data, static CURLcode AllowServerConnect(struct UrlData *data,
struct connectdata *conn,
int sock) int sock)
{ {
fd_set rdset; fd_set rdset;
@@ -187,8 +121,8 @@ static CURLcode AllowServerConnect(struct UrlData *data,
size_t size = sizeof(struct sockaddr_in); size_t size = sizeof(struct sockaddr_in);
struct sockaddr_in add; struct sockaddr_in add;
getsockname(sock, (struct sockaddr *) &add, (int *)&size); getsockname(sock, (struct sockaddr *) &add, (socklen_t *)&size);
s=accept(sock, (struct sockaddr *) &add, (int *)&size); s=accept(sock, (struct sockaddr *) &add, (socklen_t *)&size);
sclose(sock); /* close the first socket */ sclose(sock); /* close the first socket */
@@ -199,7 +133,7 @@ static CURLcode AllowServerConnect(struct UrlData *data,
} }
infof(data, "Connection accepted from server\n"); infof(data, "Connection accepted from server\n");
data->secondarysocket = s; conn->secondarysocket = s;
} }
break; break;
} }
@@ -362,23 +296,28 @@ CURLcode Curl_ftp_connect(struct connectdata *conn)
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
memset(ftp, 0, sizeof(struct FTP)); memset(ftp, 0, sizeof(struct FTP));
data->proto.ftp = ftp; conn->proto.ftp = ftp;
/* We always support persistant connections on ftp */
conn->bits.close = FALSE;
/* get some initial data into the ftp struct */ /* get some initial data into the ftp struct */
ftp->bytecountp = &conn->bytecount; ftp->bytecountp = &conn->bytecount;
ftp->user = data->user;
ftp->passwd = data->passwd; /* duplicate to keep them even when the data struct changes */
ftp->user = strdup(data->user);
ftp->passwd = strdup(data->passwd);
if (data->bits.tunnel_thru_httpproxy) { if (data->bits.tunnel_thru_httpproxy) {
/* We want "seamless" FTP operations through HTTP proxy tunnel */ /* We want "seamless" FTP operations through HTTP proxy tunnel */
result = Curl_ConnectHTTPProxyTunnel(conn, data->firstsocket, result = Curl_ConnectHTTPProxyTunnel(conn, conn->firstsocket,
data->hostname, data->remote_port); conn->hostname, conn->remote_port);
if(CURLE_OK != result) if(CURLE_OK != result)
return result; return result;
} }
/* The first thing we do is wait for the "220*" line: */ /* The first thing we do is wait for the "220*" line: */
nread = Curl_GetFTPResponse(data->firstsocket, buf, conn, &ftpcode); nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if(nread < 0) if(nread < 0)
return CURLE_OPERATION_TIMEOUTED; return CURLE_OPERATION_TIMEOUTED;
@@ -398,7 +337,7 @@ CURLcode Curl_ftp_connect(struct connectdata *conn)
set a valid level */ set a valid level */
sec_request_prot(conn, data->krb4_level); sec_request_prot(conn, data->krb4_level);
data->cmdchannel = fdopen(data->firstsocket, "w"); data->cmdchannel = fdopen(conn->firstsocket, "w");
if(sec_login(conn) != 0) if(sec_login(conn) != 0)
infof(data, "Logging in with password in cleartext!\n"); infof(data, "Logging in with password in cleartext!\n");
@@ -408,10 +347,10 @@ CURLcode Curl_ftp_connect(struct connectdata *conn)
#endif #endif
/* send USER */ /* send USER */
ftpsendf(data->firstsocket, conn, "USER %s", ftp->user); ftpsendf(conn->firstsocket, conn, "USER %s", ftp->user);
/* wait for feedback */ /* wait for feedback */
nread = Curl_GetFTPResponse(data->firstsocket, buf, conn, &ftpcode); nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if(nread < 0) if(nread < 0)
return CURLE_OPERATION_TIMEOUTED; return CURLE_OPERATION_TIMEOUTED;
@@ -424,8 +363,8 @@ CURLcode Curl_ftp_connect(struct connectdata *conn)
else if(ftpcode == 331) { else if(ftpcode == 331) {
/* 331 Password required for ... /* 331 Password required for ...
(the server requires to send the user's password too) */ (the server requires to send the user's password too) */
ftpsendf(data->firstsocket, conn, "PASS %s", ftp->passwd); ftpsendf(conn->firstsocket, conn, "PASS %s", ftp->passwd);
nread = Curl_GetFTPResponse(data->firstsocket, buf, conn, &ftpcode); nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if(nread < 0) if(nread < 0)
return CURLE_OPERATION_TIMEOUTED; return CURLE_OPERATION_TIMEOUTED;
@@ -469,6 +408,58 @@ CURLcode Curl_ftp_connect(struct connectdata *conn)
return CURLE_FTP_WEIRD_USER_REPLY; return CURLE_FTP_WEIRD_USER_REPLY;
} }
/* send PWD to discover our entry point */
ftpsendf(conn->firstsocket, conn, "PWD");
/* wait for feedback */
nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if(nread < 0)
return CURLE_OPERATION_TIMEOUTED;
if(ftpcode == 257) {
char *dir = (char *)malloc(nread+1);
char *store=dir;
char *ptr=&buf[4]; /* start on the first letter */
/* Reply format is like
257<space>"<directory-name>"<space><commentary> and the RFC959 says
The directory name can contain any character; embedded double-quotes
should be escaped by double-quotes (the "quote-doubling" convention).
*/
if('\"' == *ptr) {
/* it started good */
ptr++;
while(ptr && *ptr) {
if('\"' == *ptr) {
if('\"' == ptr[1]) {
/* "quote-doubling" */
*store = ptr[1];
ptr++;
}
else {
/* end of path */
*store = '\0'; /* zero terminate */
break; /* get out of this loop */
}
}
else
*store = *ptr;
store++;
ptr++;
}
ftp->entrypath =dir; /* remember this */
infof(data, "Entry path is '%s'\n", ftp->entrypath);
}
else {
/* couldn't get the path */
}
}
else {
/* We couldn't read the PWD response! */
}
return CURLE_OK; return CURLE_OK;
} }
@@ -477,7 +468,7 @@ CURLcode Curl_ftp_connect(struct connectdata *conn)
CURLcode Curl_ftp_done(struct connectdata *conn) CURLcode Curl_ftp_done(struct connectdata *conn)
{ {
struct UrlData *data = conn->data; struct UrlData *data = conn->data;
struct FTP *ftp = data->proto.ftp; struct FTP *ftp = conn->proto.ftp;
size_t nread; size_t nread;
char *buf = data->buffer; /* this is our buffer */ char *buf = data->buffer; /* this is our buffer */
struct curl_slist *qitem; /* QUOTE item */ struct curl_slist *qitem; /* QUOTE item */
@@ -492,7 +483,7 @@ CURLcode Curl_ftp_done(struct connectdata *conn)
} }
else { else {
if((-1 != conn->size) && (conn->size != *ftp->bytecountp) && if((-1 != conn->size) && (conn->size != *ftp->bytecountp) &&
(data->maxdownload != *ftp->bytecountp)) { (conn->maxdownload != *ftp->bytecountp)) {
failf(data, "Received only partial file"); failf(data, "Received only partial file");
return CURLE_PARTIAL_FILE; return CURLE_PARTIAL_FILE;
} }
@@ -502,16 +493,16 @@ CURLcode Curl_ftp_done(struct connectdata *conn)
} }
} }
#ifdef KRB4 #ifdef KRB4
sec_fflush_fd(conn, data->secondarysocket); sec_fflush_fd(conn, conn->secondarysocket);
#endif #endif
/* shut down the socket to inform the server we're done */ /* shut down the socket to inform the server we're done */
sclose(data->secondarysocket); sclose(conn->secondarysocket);
data->secondarysocket = -1; conn->secondarysocket = -1;
if(!data->bits.no_body) { if(!data->bits.no_body) {
/* now let's see what the server says about the transfer we /* now let's see what the server says about the transfer we
just performed: */ just performed: */
nread = Curl_GetFTPResponse(data->firstsocket, buf, conn, &ftpcode); nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if(nread < 0) if(nread < 0)
return CURLE_OPERATION_TIMEOUTED; return CURLE_OPERATION_TIMEOUTED;
@@ -529,9 +520,9 @@ CURLcode Curl_ftp_done(struct connectdata *conn)
while (qitem) { while (qitem) {
/* Send string */ /* Send string */
if (qitem->data) { if (qitem->data) {
ftpsendf(data->firstsocket, conn, "%s", qitem->data); ftpsendf(conn->firstsocket, conn, "%s", qitem->data);
nread = Curl_GetFTPResponse(data->firstsocket, buf, conn, &ftpcode); nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if(nread < 0) if(nread < 0)
return CURLE_OPERATION_TIMEOUTED; return CURLE_OPERATION_TIMEOUTED;
@@ -560,18 +551,19 @@ CURLcode _ftp(struct connectdata *conn)
char *buf = data->buffer; /* this is our buffer */ char *buf = data->buffer; /* this is our buffer */
/* for the ftp PORT mode */ /* for the ftp PORT mode */
int portsock=-1; int portsock=-1;
struct sockaddr_in serv_addr;
char hostent_buf[8192];
#if defined (HAVE_INET_NTOA_R) #if defined (HAVE_INET_NTOA_R)
char ntoa_buf[64]; char ntoa_buf[64];
#endif #endif
#ifdef ENABLE_IPV6 #ifdef ENABLE_IPV6
struct addrinfo *ai; struct addrinfo *ai;
#else
struct sockaddr_in serv_addr;
char hostent_buf[8192];
#endif #endif
struct curl_slist *qitem; /* QUOTE item */ struct curl_slist *qitem; /* QUOTE item */
/* the ftp struct is already inited in ftp_connect() */ /* the ftp struct is already inited in ftp_connect() */
struct FTP *ftp = data->proto.ftp; struct FTP *ftp = conn->proto.ftp;
long *bytecountp = ftp->bytecountp; long *bytecountp = ftp->bytecountp;
int ftpcode; /* for ftp status */ int ftpcode; /* for ftp status */
@@ -583,9 +575,9 @@ CURLcode _ftp(struct connectdata *conn)
while (qitem) { while (qitem) {
/* Send string */ /* Send string */
if (qitem->data) { if (qitem->data) {
ftpsendf(data->firstsocket, conn, "%s", qitem->data); ftpsendf(conn->firstsocket, conn, "%s", qitem->data);
nread = Curl_GetFTPResponse(data->firstsocket, buf, conn, &ftpcode); nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if(nread < 0) if(nread < 0)
return CURLE_OPERATION_TIMEOUTED; return CURLE_OPERATION_TIMEOUTED;
@@ -599,10 +591,27 @@ CURLcode _ftp(struct connectdata *conn)
} }
} }
if(conn->bits.reuse) {
/* This is a re-used connection. Since we change directory to where the
transfer is taking place, we must now get back to the original dir
where we ended up after login: */
ftpsendf(conn->firstsocket, conn, "CWD %s", ftp->entrypath);
nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if(nread < 0)
return CURLE_OPERATION_TIMEOUTED;
if(ftpcode != 250) {
failf(data, "Couldn't change back to directory %s", ftp->entrypath);
return CURLE_FTP_ACCESS_DENIED;
}
}
/* change directory first! */ /* change directory first! */
if(ftp->dir && ftp->dir[0]) { if(ftp->dir && ftp->dir[0]) {
ftpsendf(data->firstsocket, conn, "CWD %s", ftp->dir); ftpsendf(conn->firstsocket, conn, "CWD %s", ftp->dir);
nread = Curl_GetFTPResponse(data->firstsocket, buf, conn, &ftpcode); nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if(nread < 0) if(nread < 0)
return CURLE_OPERATION_TIMEOUTED; return CURLE_OPERATION_TIMEOUTED;
@@ -615,9 +624,9 @@ CURLcode _ftp(struct connectdata *conn)
if(data->bits.get_filetime && ftp->file) { if(data->bits.get_filetime && ftp->file) {
/* we have requested to get the modified-time of the file, this is yet /* we have requested to get the modified-time of the file, this is yet
again a grey area as the MDTM is not kosher RFC959 */ again a grey area as the MDTM is not kosher RFC959 */
ftpsendf(data->firstsocket, conn, "MDTM %s", ftp->file); ftpsendf(conn->firstsocket, conn, "MDTM %s", ftp->file);
nread = Curl_GetFTPResponse(data->firstsocket, buf, conn, &ftpcode); nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if(nread < 0) if(nread < 0)
return CURLE_OPERATION_TIMEOUTED; return CURLE_OPERATION_TIMEOUTED;
@@ -651,10 +660,10 @@ CURLcode _ftp(struct connectdata *conn)
/* Some servers return different sizes for different modes, and thus we /* Some servers return different sizes for different modes, and thus we
must set the proper type before we check the size */ must set the proper type before we check the size */
ftpsendf(data->firstsocket, conn, "TYPE %s", ftpsendf(conn->firstsocket, conn, "TYPE %s",
(data->bits.ftp_ascii)?"A":"I"); (data->bits.ftp_ascii)?"A":"I");
nread = Curl_GetFTPResponse(data->firstsocket, buf, conn, &ftpcode); nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if(nread < 0) if(nread < 0)
return CURLE_OPERATION_TIMEOUTED; return CURLE_OPERATION_TIMEOUTED;
@@ -665,9 +674,9 @@ CURLcode _ftp(struct connectdata *conn)
CURLE_FTP_COULDNT_SET_BINARY; CURLE_FTP_COULDNT_SET_BINARY;
} }
ftpsendf(data->firstsocket, conn, "SIZE %s", ftp->file); ftpsendf(conn->firstsocket, conn, "SIZE %s", ftp->file);
nread = Curl_GetFTPResponse(data->firstsocket, buf, conn, &ftpcode); nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if(nread < 0) if(nread < 0)
return CURLE_OPERATION_TIMEOUTED; return CURLE_OPERATION_TIMEOUTED;
@@ -709,20 +718,20 @@ CURLcode _ftp(struct connectdata *conn)
#ifdef ENABLE_IPV6 #ifdef ENABLE_IPV6
struct addrinfo hints, *res, *ai; struct addrinfo hints, *res, *ai;
struct sockaddr_storage ss; struct sockaddr_storage ss;
int sslen; socklen_t sslen;
char hbuf[NI_MAXHOST]; char hbuf[NI_MAXHOST];
char *localaddr;
struct sockaddr *sa=(struct sockaddr *)&ss; struct sockaddr *sa=(struct sockaddr *)&ss;
#ifdef NI_WITHSCOPEID #ifdef NI_WITHSCOPEID
const int niflags = NI_NUMERICHOST | NI_NUMERICSERV | NI_WITHSCOPEID; const int niflags = NI_NUMERICHOST | NI_NUMERICSERV | NI_WITHSCOPEID;
#else #else
const int niflags = NI_NUMERICHOST | NI_NUMERICSERV; const int niflags = NI_NUMERICHOST | NI_NUMERICSERV;
#endif #endif
unsigned char *ap; char *ap;
unsigned char *pp; char *pp;
int alen, plen; int alen, plen;
char portmsgbuf[4096], tmp[4096]; char portmsgbuf[4096], tmp[4096];
char *p;
char *mode[] = { "EPRT", "LPRT", "PORT", NULL }; char *mode[] = { "EPRT", "LPRT", "PORT", NULL };
char **modep; char **modep;
@@ -731,7 +740,7 @@ CURLcode _ftp(struct connectdata *conn)
* I believe we should use the same address as the control connection. * I believe we should use the same address as the control connection.
*/ */
sslen = sizeof(ss); sslen = sizeof(ss);
if (getsockname(data->firstsocket, (struct sockaddr *)&ss, &sslen) < 0) if (getsockname(conn->firstsocket, (struct sockaddr *)&ss, &sslen) < 0)
return CURLE_FTP_PORT_FAILED; return CURLE_FTP_PORT_FAILED;
if (getnameinfo((struct sockaddr *)&ss, sslen, hbuf, sizeof(hbuf), NULL, 0, if (getnameinfo((struct sockaddr *)&ss, sslen, hbuf, sizeof(hbuf), NULL, 0,
@@ -755,13 +764,13 @@ CURLcode _ftp(struct connectdata *conn)
continue; continue;
if (bind(portsock, ai->ai_addr, ai->ai_addrlen) < 0) { if (bind(portsock, ai->ai_addr, ai->ai_addrlen) < 0) {
close(portsock); sclose(portsock);
portsock = -1; portsock = -1;
continue; continue;
} }
if (listen(portsock, 1) < 0) { if (listen(portsock, 1) < 0) {
close(portsock); sclose(portsock);
portsock = -1; portsock = -1;
continue; continue;
} }
@@ -819,7 +828,7 @@ CURLcode _ftp(struct connectdata *conn)
if (q) if (q)
*q = '\0'; *q = '\0';
} }
ftpsendf(data->firstsocket, conn, "%s |%d|%s|%s|", *modep, eprtaf, ftpsendf(conn->firstsocket, conn, "%s |%d|%s|%s|", *modep, eprtaf,
portmsgbuf, tmp); portmsgbuf, tmp);
} else if (strcmp(*modep, "LPRT") == 0 || strcmp(*modep, "PORT") == 0) { } else if (strcmp(*modep, "LPRT") == 0 || strcmp(*modep, "PORT") == 0) {
int i; int i;
@@ -856,10 +865,10 @@ CURLcode _ftp(struct connectdata *conn)
goto again; goto again;
} }
} }
ftpsendf(data->firstsocket, conn, "%s %s", *modep, portmsgbuf); ftpsendf(conn->firstsocket, conn, "%s %s", *modep, portmsgbuf);
} }
nread = Curl_GetFTPResponse(data->firstsocket, buf, conn, &ftpcode); nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if (nread < 0) if (nread < 0)
return CURLE_OPERATION_TIMEOUTED; return CURLE_OPERATION_TIMEOUTED;
@@ -872,7 +881,7 @@ again:;
} }
if (!*modep) { if (!*modep) {
close(portsock); sclose(portsock);
freeaddrinfo(res); freeaddrinfo(res);
return CURLE_FTP_PORT_FAILED; return CURLE_FTP_PORT_FAILED;
} }
@@ -909,7 +918,7 @@ again:;
/* we set the secondary socket variable to this for now, it /* we set the secondary socket variable to this for now, it
is only so that the cleanup function will close it in case is only so that the cleanup function will close it in case
we fail before the true secondary stuff is made */ we fail before the true secondary stuff is made */
data->secondarysocket = portsock; conn->secondarysocket = portsock;
memset((char *)&sa, 0, sizeof(sa)); memset((char *)&sa, 0, sizeof(sa));
memcpy((char *)&sa.sin_addr, memcpy((char *)&sa.sin_addr,
@@ -926,7 +935,7 @@ again:;
size = sizeof(add); size = sizeof(add);
if(getsockname(portsock, (struct sockaddr *) &add, if(getsockname(portsock, (struct sockaddr *) &add,
(int *)&size)<0) { (socklen_t *)&size)<0) {
failf(data, "getsockname() failed"); failf(data, "getsockname() failed");
return CURLE_FTP_PORT_FAILED; return CURLE_FTP_PORT_FAILED;
} }
@@ -971,13 +980,13 @@ again:;
sscanf( inet_ntoa(in), "%hu.%hu.%hu.%hu", sscanf( inet_ntoa(in), "%hu.%hu.%hu.%hu",
&ip[0], &ip[1], &ip[2], &ip[3]); &ip[0], &ip[1], &ip[2], &ip[3]);
#endif #endif
ftpsendf(data->firstsocket, conn, "PORT %d,%d,%d,%d,%d,%d", ftpsendf(conn->firstsocket, conn, "PORT %d,%d,%d,%d,%d,%d",
ip[0], ip[1], ip[2], ip[3], ip[0], ip[1], ip[2], ip[3],
porttouse >> 8, porttouse >> 8,
porttouse & 255); porttouse & 255);
} }
nread = Curl_GetFTPResponse(data->firstsocket, buf, conn, &ftpcode); nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if(nread < 0) if(nread < 0)
return CURLE_OPERATION_TIMEOUTED; return CURLE_OPERATION_TIMEOUTED;
@@ -998,8 +1007,8 @@ again:;
int modeoff; int modeoff;
for (modeoff = 0; mode[modeoff]; modeoff++) { for (modeoff = 0; mode[modeoff]; modeoff++) {
ftpsendf(data->firstsocket, conn, mode[modeoff]); ftpsendf(conn->firstsocket, conn, mode[modeoff]);
nread = Curl_GetFTPResponse(data->firstsocket, buf, conn, &ftpcode); nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if(nread < 0) if(nread < 0)
return CURLE_OPERATION_TIMEOUTED; return CURLE_OPERATION_TIMEOUTED;
@@ -1021,9 +1030,10 @@ again:;
struct addrinfo *res; struct addrinfo *res;
#else #else
struct hostent *he; struct hostent *he;
#endif
char *str=buf,*ip_addr;
char *hostdataptr=NULL; char *hostdataptr=NULL;
char *ip_addr;
#endif
char *str=buf;
/* /*
* New 227-parser June 3rd 1999. * New 227-parser June 3rd 1999.
@@ -1057,12 +1067,12 @@ again:;
* previous lookup. * previous lookup.
*/ */
#ifdef ENABLE_IPV6 #ifdef ENABLE_IPV6
res = conn->res; res = conn->hp;
#else #else
he = conn->hp; he = conn->hp;
#endif #endif
connectport = connectport =
(unsigned short)data->port; /* we connect to the proxy's port */ (unsigned short)conn->port; /* we connect to the proxy's port */
} }
else { else {
/* normal, direct, ftp connection */ /* normal, direct, ftp connection */
@@ -1081,15 +1091,15 @@ again:;
} }
#ifdef ENABLE_IPV6 #ifdef ENABLE_IPV6
data->secondarysocket = -1; conn->secondarysocket = -1;
for (ai = res; ai; ai = ai->ai_next) { for (ai = res; ai; ai = ai->ai_next) {
/* XXX for now, we can do IPv4 only */ /* XXX for now, we can do IPv4 only */
if (ai->ai_family != AF_INET) if (ai->ai_family != AF_INET)
continue; continue;
data->secondarysocket = socket(ai->ai_family, ai->ai_socktype, conn->secondarysocket = socket(ai->ai_family, ai->ai_socktype,
ai->ai_protocol); ai->ai_protocol);
if (data->secondarysocket < 0) if (conn->secondarysocket < 0)
continue; continue;
if(data->bits.verbose) { if(data->bits.verbose) {
@@ -1114,21 +1124,21 @@ again:;
} }
} }
if (connect(data->secondarysocket, ai->ai_addr, ai->ai_addrlen) < 0) { if (connect(conn->secondarysocket, ai->ai_addr, ai->ai_addrlen) < 0) {
close(data->secondarysocket); close(conn->secondarysocket);
data->secondarysocket = -1; conn->secondarysocket = -1;
continue; continue;
} }
break; break;
} }
if (data->secondarysocket < 0) { if (conn->secondarysocket < 0) {
failf(data, strerror(errno)); failf(data, strerror(errno));
return CURLE_FTP_CANT_RECONNECT; return CURLE_FTP_CANT_RECONNECT;
} }
#else #else
data->secondarysocket = socket(AF_INET, SOCK_STREAM, 0); conn->secondarysocket = socket(AF_INET, SOCK_STREAM, 0);
memset((char *) &serv_addr, '\0', sizeof(serv_addr)); memset((char *) &serv_addr, '\0', sizeof(serv_addr));
memcpy((char *)&(serv_addr.sin_addr), he->h_addr, he->h_length); memcpy((char *)&(serv_addr.sin_addr), he->h_addr, he->h_length);
@@ -1202,7 +1212,7 @@ again:;
if(hostdataptr) if(hostdataptr)
free(hostdataptr); free(hostdataptr);
if (connect(data->secondarysocket, (struct sockaddr *) &serv_addr, if (connect(conn->secondarysocket, (struct sockaddr *) &serv_addr,
sizeof(serv_addr)) < 0) { sizeof(serv_addr)) < 0) {
switch(errno) { switch(errno) {
#ifdef ECONNREFUSED #ifdef ECONNREFUSED
@@ -1213,7 +1223,7 @@ again:;
#endif #endif
#ifdef EINTR #ifdef EINTR
case EINTR: case EINTR:
failf(data, "Connection timeouted to ftp server"); failf(data, "Connection timed out to ftp server");
break; break;
#endif #endif
default: default:
@@ -1226,7 +1236,7 @@ again:;
if (data->bits.tunnel_thru_httpproxy) { if (data->bits.tunnel_thru_httpproxy) {
/* We want "seamless" FTP operations through HTTP proxy tunnel */ /* We want "seamless" FTP operations through HTTP proxy tunnel */
result = Curl_ConnectHTTPProxyTunnel(conn, data->secondarysocket, result = Curl_ConnectHTTPProxyTunnel(conn, conn->secondarysocket,
newhost, newport); newhost, newport);
if(CURLE_OK != result) if(CURLE_OK != result)
return result; return result;
@@ -1241,10 +1251,10 @@ again:;
if(data->bits.upload) { if(data->bits.upload) {
/* Set type to binary (unless specified ASCII) */ /* Set type to binary (unless specified ASCII) */
ftpsendf(data->firstsocket, conn, "TYPE %s", ftpsendf(conn->firstsocket, conn, "TYPE %s",
(data->bits.ftp_ascii)?"A":"I"); (data->bits.ftp_ascii)?"A":"I");
nread = Curl_GetFTPResponse(data->firstsocket, buf, conn, &ftpcode); nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if(nread < 0) if(nread < 0)
return CURLE_OPERATION_TIMEOUTED; return CURLE_OPERATION_TIMEOUTED;
@@ -1273,9 +1283,9 @@ again:;
/* we could've got a specified offset from the command line, /* we could've got a specified offset from the command line,
but now we know we didn't */ but now we know we didn't */
ftpsendf(data->firstsocket, conn, "SIZE %s", ftp->file); ftpsendf(conn->firstsocket, conn, "SIZE %s", ftp->file);
nread = Curl_GetFTPResponse(data->firstsocket, buf, conn, &ftpcode); nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if(nread < 0) if(nread < 0)
return CURLE_OPERATION_TIMEOUTED; return CURLE_OPERATION_TIMEOUTED;
@@ -1332,11 +1342,11 @@ again:;
/* Send everything on data->in to the socket */ /* Send everything on data->in to the socket */
if(data->bits.ftp_append) if(data->bits.ftp_append)
/* we append onto the file instead of rewriting it */ /* we append onto the file instead of rewriting it */
ftpsendf(data->firstsocket, conn, "APPE %s", ftp->file); ftpsendf(conn->firstsocket, conn, "APPE %s", ftp->file);
else else
ftpsendf(data->firstsocket, conn, "STOR %s", ftp->file); ftpsendf(conn->firstsocket, conn, "STOR %s", ftp->file);
nread = Curl_GetFTPResponse(data->firstsocket, buf, conn, &ftpcode); nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if(nread < 0) if(nread < 0)
return CURLE_OPERATION_TIMEOUTED; return CURLE_OPERATION_TIMEOUTED;
@@ -1347,7 +1357,7 @@ again:;
} }
if(data->bits.ftp_use_port) { if(data->bits.ftp_use_port) {
result = AllowServerConnect(data, portsock); result = AllowServerConnect(data, conn, portsock);
if( result ) if( result )
return result; return result;
} }
@@ -1360,7 +1370,7 @@ again:;
Curl_pgrsSetUploadSize(data, data->infilesize); Curl_pgrsSetUploadSize(data, data->infilesize);
result = Curl_Transfer(conn, -1, -1, FALSE, NULL, /* no download */ result = Curl_Transfer(conn, -1, -1, FALSE, NULL, /* no download */
data->secondarysocket, bytecountp); conn->secondarysocket, bytecountp);
if(result) if(result)
return result; return result;
@@ -1392,16 +1402,16 @@ again:;
else if(from < 0) { else if(from < 0) {
/* -Y */ /* -Y */
totalsize = -from; totalsize = -from;
data->maxdownload = -from; conn->maxdownload = -from;
data->resume_from = from; data->resume_from = from;
infof(data, "FTP RANGE the last %d bytes\n", totalsize); infof(data, "FTP RANGE the last %d bytes\n", totalsize);
} }
else { else {
/* X-Y */ /* X-Y */
totalsize = to-from; totalsize = to-from;
data->maxdownload = totalsize+1; /* include the last mentioned byte */ conn->maxdownload = totalsize+1; /* include the last mentioned byte */
data->resume_from = from; data->resume_from = from;
infof(data, "FTP RANGE from %d getting %d bytes\n", from, data->maxdownload); infof(data, "FTP RANGE from %d getting %d bytes\n", from, conn->maxdownload);
} }
infof(data, "range-download from %d to %d, totally %d bytes\n", infof(data, "range-download from %d to %d, totally %d bytes\n",
from, to, totalsize); from, to, totalsize);
@@ -1414,9 +1424,9 @@ again:;
dirlist = TRUE; dirlist = TRUE;
/* Set type to ASCII */ /* Set type to ASCII */
ftpsendf(data->firstsocket, conn, "TYPE A"); ftpsendf(conn->firstsocket, conn, "TYPE A");
nread = Curl_GetFTPResponse(data->firstsocket, buf, conn, &ftpcode); nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if(nread < 0) if(nread < 0)
return CURLE_OPERATION_TIMEOUTED; return CURLE_OPERATION_TIMEOUTED;
@@ -1429,16 +1439,16 @@ again:;
better used since the LIST command output is not specified or better used since the LIST command output is not specified or
standard in any way */ standard in any way */
ftpsendf(data->firstsocket, conn, "%s", ftpsendf(conn->firstsocket, conn, "%s",
data->customrequest?data->customrequest: data->customrequest?data->customrequest:
(data->bits.ftp_list_only?"NLST":"LIST")); (data->bits.ftp_list_only?"NLST":"LIST"));
} }
else { else {
/* Set type to binary (unless specified ASCII) */ /* Set type to binary (unless specified ASCII) */
ftpsendf(data->firstsocket, conn, "TYPE %s", ftpsendf(conn->firstsocket, conn, "TYPE %s",
(data->bits.ftp_ascii)?"A":"I"); (data->bits.ftp_ascii)?"A":"I");
nread = Curl_GetFTPResponse(data->firstsocket, buf, conn, &ftpcode); nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if(nread < 0) if(nread < 0)
return CURLE_OPERATION_TIMEOUTED; return CURLE_OPERATION_TIMEOUTED;
@@ -1457,9 +1467,9 @@ again:;
* of the file we're gonna get. If we can get the size, this is by far * of the file we're gonna get. If we can get the size, this is by far
* the best way to know if we're trying to resume beyond the EOF. */ * the best way to know if we're trying to resume beyond the EOF. */
ftpsendf(data->firstsocket, conn, "SIZE %s", ftp->file); ftpsendf(conn->firstsocket, conn, "SIZE %s", ftp->file);
nread = Curl_GetFTPResponse(data->firstsocket, buf, conn, &ftpcode); nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if(nread < 0) if(nread < 0)
return CURLE_OPERATION_TIMEOUTED; return CURLE_OPERATION_TIMEOUTED;
@@ -1501,9 +1511,9 @@ again:;
infof(data, "Instructs server to resume from offset %d\n", infof(data, "Instructs server to resume from offset %d\n",
data->resume_from); data->resume_from);
ftpsendf(data->firstsocket, conn, "REST %d", data->resume_from); ftpsendf(conn->firstsocket, conn, "REST %d", data->resume_from);
nread = Curl_GetFTPResponse(data->firstsocket, buf, conn, &ftpcode); nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if(nread < 0) if(nread < 0)
return CURLE_OPERATION_TIMEOUTED; return CURLE_OPERATION_TIMEOUTED;
@@ -1513,10 +1523,10 @@ again:;
} }
} }
ftpsendf(data->firstsocket, conn, "RETR %s", ftp->file); ftpsendf(conn->firstsocket, conn, "RETR %s", ftp->file);
} }
nread = Curl_GetFTPResponse(data->firstsocket, buf, conn, &ftpcode); nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if(nread < 0) if(nread < 0)
return CURLE_OPERATION_TIMEOUTED; return CURLE_OPERATION_TIMEOUTED;
@@ -1580,7 +1590,7 @@ again:;
size = downloadsize; size = downloadsize;
if(data->bits.ftp_use_port) { if(data->bits.ftp_use_port) {
result = AllowServerConnect(data, portsock); result = AllowServerConnect(data, conn, portsock);
if( result ) if( result )
return result; return result;
} }
@@ -1588,7 +1598,7 @@ again:;
infof(data, "Getting file with size: %d\n", size); infof(data, "Getting file with size: %d\n", size);
/* FTP download: */ /* FTP download: */
result=Curl_Transfer(conn, data->secondarysocket, size, FALSE, result=Curl_Transfer(conn, conn->secondarysocket, size, FALSE,
bytecountp, bytecountp,
-1, NULL); /* no upload here */ -1, NULL); /* no upload here */
if(result) if(result)
@@ -1617,7 +1627,7 @@ CURLcode Curl_ftp(struct connectdata *conn)
int dirlength=0; /* 0 forces strlen() */ int dirlength=0; /* 0 forces strlen() */
/* the ftp struct is already inited in ftp_connect() */ /* the ftp struct is already inited in ftp_connect() */
ftp = data->proto.ftp; ftp = conn->proto.ftp;
/* We split the path into dir and file parts *before* we URLdecode /* We split the path into dir and file parts *before* we URLdecode
it */ it */
@@ -1706,3 +1716,16 @@ size_t Curl_ftpsendf(int fd, struct connectdata *conn, char *fmt, ...)
} }
CURLcode Curl_ftp_disconnect(struct connectdata *conn)
{
struct FTP *ftp= conn->proto.ftp;
if(ftp->user)
free(ftp->user);
if(ftp->passwd)
free(ftp->passwd);
if(ftp->entrypath)
free(ftp->entrypath);
return CURLE_OK;
}

View File

@@ -26,12 +26,10 @@
CURLcode Curl_ftp(struct connectdata *conn); CURLcode Curl_ftp(struct connectdata *conn);
CURLcode Curl_ftp_done(struct connectdata *conn); 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);
size_t Curl_ftpsendf(int fd, struct connectdata *, char *fmt, ...); size_t Curl_ftpsendf(int fd, struct connectdata *, char *fmt, ...);
struct curl_slist *curl_slist_append(struct curl_slist *list, char *data);
void curl_slist_free_all(struct curl_slist *list);
/* The kerberos stuff needs this: */ /* The kerberos stuff needs this: */
int Curl_GetFTPResponse(int sockfd, char *buf, int Curl_GetFTPResponse(int sockfd, char *buf,
struct connectdata *conn, struct connectdata *conn,

View File

@@ -104,6 +104,11 @@
# include <string.h> # include <string.h>
#endif #endif
/* The last #include file should be: */
#ifdef MALLOCDEBUG
#include "memdebug.h"
#endif
#if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7) #if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7)
# define __attribute__(x) # define __attribute__(x)
#endif #endif
@@ -222,7 +227,7 @@ static int yyRelSeconds;
static int yyRelYear; static int yyRelYear;
#line 205 "getdate.y" #line 210 "getdate.y"
typedef union { typedef union {
int Number; int Number;
enum _MERIDIAN Meridian; enum _MERIDIAN Meridian;
@@ -305,11 +310,11 @@ static const short yyrhs[] = { -1,
#if YYDEBUG != 0 #if YYDEBUG != 0
static const short yyrline[] = { 0, static const short yyrline[] = { 0,
221, 222, 225, 228, 231, 234, 237, 240, 243, 249, 226, 227, 230, 233, 236, 239, 242, 245, 248, 254,
255, 264, 270, 282, 285, 288, 294, 298, 302, 308, 260, 269, 275, 287, 290, 293, 299, 303, 307, 313,
312, 330, 336, 342, 346, 351, 355, 362, 370, 373, 317, 335, 341, 347, 351, 356, 360, 367, 375, 378,
376, 379, 382, 385, 388, 391, 394, 397, 400, 403, 381, 384, 387, 390, 393, 396, 399, 402, 405, 408,
406, 409, 412, 415, 418, 421, 424, 429, 462, 466 411, 414, 417, 420, 423, 426, 429, 434, 467, 471
}; };
#endif #endif
@@ -390,7 +395,7 @@ static const short yycheck[] = { 0,
56 56
}; };
/* -*-C-*- Note some compilers choke on comments on `#line' lines. */ /* -*-C-*- Note some compilers choke on comments on `#line' lines. */
#line 3 "/usr/local/share/bison.simple" #line 3 "/usr/lib/bison.simple"
/* This file comes from bison-1.28. */ /* This file comes from bison-1.28. */
/* Skeleton output parser for bison, /* Skeleton output parser for bison,
@@ -604,7 +609,7 @@ __yy_memcpy (char *to, char *from, unsigned int count)
#endif #endif
#endif #endif
#line 217 "/usr/local/share/bison.simple" #line 217 "/usr/lib/bison.simple"
/* The user can define YYPARSE_PARAM as the name of an argument to be passed /* The user can define YYPARSE_PARAM as the name of an argument to be passed
into yyparse. The argument should have type void *. into yyparse. The argument should have type void *.
@@ -933,37 +938,37 @@ yyreduce:
switch (yyn) { switch (yyn) {
case 3: case 3:
#line 225 "getdate.y" #line 230 "getdate.y"
{ {
yyHaveTime++; yyHaveTime++;
; ;
break;} break;}
case 4: case 4:
#line 228 "getdate.y" #line 233 "getdate.y"
{ {
yyHaveZone++; yyHaveZone++;
; ;
break;} break;}
case 5: case 5:
#line 231 "getdate.y" #line 236 "getdate.y"
{ {
yyHaveDate++; yyHaveDate++;
; ;
break;} break;}
case 6: case 6:
#line 234 "getdate.y" #line 239 "getdate.y"
{ {
yyHaveDay++; yyHaveDay++;
; ;
break;} break;}
case 7: case 7:
#line 237 "getdate.y" #line 242 "getdate.y"
{ {
yyHaveRel++; yyHaveRel++;
; ;
break;} break;}
case 9: case 9:
#line 243 "getdate.y" #line 248 "getdate.y"
{ {
yyHour = yyvsp[-1].Number; yyHour = yyvsp[-1].Number;
yyMinutes = 0; yyMinutes = 0;
@@ -972,7 +977,7 @@ case 9:
; ;
break;} break;}
case 10: case 10:
#line 249 "getdate.y" #line 254 "getdate.y"
{ {
yyHour = yyvsp[-3].Number; yyHour = yyvsp[-3].Number;
yyMinutes = yyvsp[-1].Number; yyMinutes = yyvsp[-1].Number;
@@ -981,7 +986,7 @@ case 10:
; ;
break;} break;}
case 11: case 11:
#line 255 "getdate.y" #line 260 "getdate.y"
{ {
yyHour = yyvsp[-3].Number; yyHour = yyvsp[-3].Number;
yyMinutes = yyvsp[-1].Number; yyMinutes = yyvsp[-1].Number;
@@ -993,7 +998,7 @@ case 11:
; ;
break;} break;}
case 12: case 12:
#line 264 "getdate.y" #line 269 "getdate.y"
{ {
yyHour = yyvsp[-5].Number; yyHour = yyvsp[-5].Number;
yyMinutes = yyvsp[-3].Number; yyMinutes = yyvsp[-3].Number;
@@ -1002,7 +1007,7 @@ case 12:
; ;
break;} break;}
case 13: case 13:
#line 270 "getdate.y" #line 275 "getdate.y"
{ {
yyHour = yyvsp[-5].Number; yyHour = yyvsp[-5].Number;
yyMinutes = yyvsp[-3].Number; yyMinutes = yyvsp[-3].Number;
@@ -1015,53 +1020,53 @@ case 13:
; ;
break;} break;}
case 14: case 14:
#line 282 "getdate.y" #line 287 "getdate.y"
{ {
yyTimezone = yyvsp[0].Number; yyTimezone = yyvsp[0].Number;
; ;
break;} break;}
case 15: case 15:
#line 285 "getdate.y" #line 290 "getdate.y"
{ {
yyTimezone = yyvsp[0].Number - 60; yyTimezone = yyvsp[0].Number - 60;
; ;
break;} break;}
case 16: case 16:
#line 289 "getdate.y" #line 294 "getdate.y"
{ {
yyTimezone = yyvsp[-1].Number - 60; yyTimezone = yyvsp[-1].Number - 60;
; ;
break;} break;}
case 17: case 17:
#line 294 "getdate.y" #line 299 "getdate.y"
{ {
yyDayOrdinal = 1; yyDayOrdinal = 1;
yyDayNumber = yyvsp[0].Number; yyDayNumber = yyvsp[0].Number;
; ;
break;} break;}
case 18: case 18:
#line 298 "getdate.y" #line 303 "getdate.y"
{ {
yyDayOrdinal = 1; yyDayOrdinal = 1;
yyDayNumber = yyvsp[-1].Number; yyDayNumber = yyvsp[-1].Number;
; ;
break;} break;}
case 19: case 19:
#line 302 "getdate.y" #line 307 "getdate.y"
{ {
yyDayOrdinal = yyvsp[-1].Number; yyDayOrdinal = yyvsp[-1].Number;
yyDayNumber = yyvsp[0].Number; yyDayNumber = yyvsp[0].Number;
; ;
break;} break;}
case 20: case 20:
#line 308 "getdate.y" #line 313 "getdate.y"
{ {
yyMonth = yyvsp[-2].Number; yyMonth = yyvsp[-2].Number;
yyDay = yyvsp[0].Number; yyDay = yyvsp[0].Number;
; ;
break;} break;}
case 21: case 21:
#line 312 "getdate.y" #line 317 "getdate.y"
{ {
/* Interpret as YYYY/MM/DD if $1 >= 1000, otherwise as MM/DD/YY. /* Interpret as YYYY/MM/DD if $1 >= 1000, otherwise as MM/DD/YY.
The goal in recognizing YYYY/MM/DD is solely to support legacy The goal in recognizing YYYY/MM/DD is solely to support legacy
@@ -1082,7 +1087,7 @@ case 21:
; ;
break;} break;}
case 22: case 22:
#line 330 "getdate.y" #line 335 "getdate.y"
{ {
/* ISO 8601 format. yyyy-mm-dd. */ /* ISO 8601 format. yyyy-mm-dd. */
yyYear = yyvsp[-2].Number; yyYear = yyvsp[-2].Number;
@@ -1091,7 +1096,7 @@ case 22:
; ;
break;} break;}
case 23: case 23:
#line 336 "getdate.y" #line 341 "getdate.y"
{ {
/* e.g. 17-JUN-1992. */ /* e.g. 17-JUN-1992. */
yyDay = yyvsp[-2].Number; yyDay = yyvsp[-2].Number;
@@ -1100,14 +1105,14 @@ case 23:
; ;
break;} break;}
case 24: case 24:
#line 342 "getdate.y" #line 347 "getdate.y"
{ {
yyMonth = yyvsp[-1].Number; yyMonth = yyvsp[-1].Number;
yyDay = yyvsp[0].Number; yyDay = yyvsp[0].Number;
; ;
break;} break;}
case 25: case 25:
#line 346 "getdate.y" #line 351 "getdate.y"
{ {
yyMonth = yyvsp[-3].Number; yyMonth = yyvsp[-3].Number;
yyDay = yyvsp[-2].Number; yyDay = yyvsp[-2].Number;
@@ -1115,14 +1120,14 @@ case 25:
; ;
break;} break;}
case 26: case 26:
#line 351 "getdate.y" #line 356 "getdate.y"
{ {
yyMonth = yyvsp[0].Number; yyMonth = yyvsp[0].Number;
yyDay = yyvsp[-1].Number; yyDay = yyvsp[-1].Number;
; ;
break;} break;}
case 27: case 27:
#line 355 "getdate.y" #line 360 "getdate.y"
{ {
yyMonth = yyvsp[-1].Number; yyMonth = yyvsp[-1].Number;
yyDay = yyvsp[-2].Number; yyDay = yyvsp[-2].Number;
@@ -1130,7 +1135,7 @@ case 27:
; ;
break;} break;}
case 28: case 28:
#line 362 "getdate.y" #line 367 "getdate.y"
{ {
yyRelSeconds = -yyRelSeconds; yyRelSeconds = -yyRelSeconds;
yyRelMinutes = -yyRelMinutes; yyRelMinutes = -yyRelMinutes;
@@ -1141,115 +1146,115 @@ case 28:
; ;
break;} break;}
case 30: case 30:
#line 373 "getdate.y" #line 378 "getdate.y"
{ {
yyRelYear += yyvsp[-1].Number * yyvsp[0].Number; yyRelYear += yyvsp[-1].Number * yyvsp[0].Number;
; ;
break;} break;}
case 31: case 31:
#line 376 "getdate.y" #line 381 "getdate.y"
{ {
yyRelYear += yyvsp[-1].Number * yyvsp[0].Number; yyRelYear += yyvsp[-1].Number * yyvsp[0].Number;
; ;
break;} break;}
case 32: case 32:
#line 379 "getdate.y" #line 384 "getdate.y"
{ {
yyRelYear += yyvsp[0].Number; yyRelYear += yyvsp[0].Number;
; ;
break;} break;}
case 33: case 33:
#line 382 "getdate.y" #line 387 "getdate.y"
{ {
yyRelMonth += yyvsp[-1].Number * yyvsp[0].Number; yyRelMonth += yyvsp[-1].Number * yyvsp[0].Number;
; ;
break;} break;}
case 34: case 34:
#line 385 "getdate.y" #line 390 "getdate.y"
{ {
yyRelMonth += yyvsp[-1].Number * yyvsp[0].Number; yyRelMonth += yyvsp[-1].Number * yyvsp[0].Number;
; ;
break;} break;}
case 35: case 35:
#line 388 "getdate.y" #line 393 "getdate.y"
{ {
yyRelMonth += yyvsp[0].Number; yyRelMonth += yyvsp[0].Number;
; ;
break;} break;}
case 36: case 36:
#line 391 "getdate.y" #line 396 "getdate.y"
{ {
yyRelDay += yyvsp[-1].Number * yyvsp[0].Number; yyRelDay += yyvsp[-1].Number * yyvsp[0].Number;
; ;
break;} break;}
case 37: case 37:
#line 394 "getdate.y" #line 399 "getdate.y"
{ {
yyRelDay += yyvsp[-1].Number * yyvsp[0].Number; yyRelDay += yyvsp[-1].Number * yyvsp[0].Number;
; ;
break;} break;}
case 38: case 38:
#line 397 "getdate.y" #line 402 "getdate.y"
{ {
yyRelDay += yyvsp[0].Number; yyRelDay += yyvsp[0].Number;
; ;
break;} break;}
case 39: case 39:
#line 400 "getdate.y" #line 405 "getdate.y"
{ {
yyRelHour += yyvsp[-1].Number * yyvsp[0].Number; yyRelHour += yyvsp[-1].Number * yyvsp[0].Number;
; ;
break;} break;}
case 40: case 40:
#line 403 "getdate.y" #line 408 "getdate.y"
{ {
yyRelHour += yyvsp[-1].Number * yyvsp[0].Number; yyRelHour += yyvsp[-1].Number * yyvsp[0].Number;
; ;
break;} break;}
case 41: case 41:
#line 406 "getdate.y" #line 411 "getdate.y"
{ {
yyRelHour += yyvsp[0].Number; yyRelHour += yyvsp[0].Number;
; ;
break;} break;}
case 42: case 42:
#line 409 "getdate.y" #line 414 "getdate.y"
{ {
yyRelMinutes += yyvsp[-1].Number * yyvsp[0].Number; yyRelMinutes += yyvsp[-1].Number * yyvsp[0].Number;
; ;
break;} break;}
case 43: case 43:
#line 412 "getdate.y" #line 417 "getdate.y"
{ {
yyRelMinutes += yyvsp[-1].Number * yyvsp[0].Number; yyRelMinutes += yyvsp[-1].Number * yyvsp[0].Number;
; ;
break;} break;}
case 44: case 44:
#line 415 "getdate.y" #line 420 "getdate.y"
{ {
yyRelMinutes += yyvsp[0].Number; yyRelMinutes += yyvsp[0].Number;
; ;
break;} break;}
case 45: case 45:
#line 418 "getdate.y" #line 423 "getdate.y"
{ {
yyRelSeconds += yyvsp[-1].Number * yyvsp[0].Number; yyRelSeconds += yyvsp[-1].Number * yyvsp[0].Number;
; ;
break;} break;}
case 46: case 46:
#line 421 "getdate.y" #line 426 "getdate.y"
{ {
yyRelSeconds += yyvsp[-1].Number * yyvsp[0].Number; yyRelSeconds += yyvsp[-1].Number * yyvsp[0].Number;
; ;
break;} break;}
case 47: case 47:
#line 424 "getdate.y" #line 429 "getdate.y"
{ {
yyRelSeconds += yyvsp[0].Number; yyRelSeconds += yyvsp[0].Number;
; ;
break;} break;}
case 48: case 48:
#line 430 "getdate.y" #line 435 "getdate.y"
{ {
if (yyHaveTime && yyHaveDate && !yyHaveRel) if (yyHaveTime && yyHaveDate && !yyHaveRel)
yyYear = yyvsp[0].Number; yyYear = yyvsp[0].Number;
@@ -1282,20 +1287,20 @@ case 48:
; ;
break;} break;}
case 49: case 49:
#line 463 "getdate.y" #line 468 "getdate.y"
{ {
yyval.Meridian = MER24; yyval.Meridian = MER24;
; ;
break;} break;}
case 50: case 50:
#line 467 "getdate.y" #line 472 "getdate.y"
{ {
yyval.Meridian = yyvsp[0].Meridian; yyval.Meridian = yyvsp[0].Meridian;
; ;
break;} break;}
} }
/* the action file gets copied in in place of this dollarsign */ /* the action file gets copied in in place of this dollarsign */
#line 543 "/usr/local/share/bison.simple" #line 543 "/usr/lib/bison.simple"
yyvsp -= yylen; yyvsp -= yylen;
yyssp -= yylen; yyssp -= yylen;
@@ -1515,7 +1520,7 @@ yyerrhandle:
} }
return 1; return 1;
} }
#line 472 "getdate.y" #line 477 "getdate.y"
/* Include this file down here because bison inserts code above which /* Include this file down here because bison inserts code above which

View File

@@ -80,6 +80,11 @@
# include <string.h> # include <string.h>
#endif #endif
/* The last #include file should be: */
#ifdef MALLOCDEBUG
#include "memdebug.h"
#endif
#if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7) #if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7)
# define __attribute__(x) # define __attribute__(x)
#endif #endif

View File

@@ -31,7 +31,7 @@
#include <string.h> #include <string.h>
#include <stdarg.h> #include <stdarg.h>
CURLcode curl_getinfo(CURL *curl, CURLINFO info, ...) CURLcode Curl_getinfo(CURL *curl, CURLINFO info, ...)
{ {
va_list arg; va_list arg;
long *param_longp; long *param_longp;

View File

@@ -66,6 +66,11 @@
# endif # endif
#endif #endif
/* The last #include file should be: */
#ifdef MALLOCDEBUG
#include "memdebug.h"
#endif
/* no perror? make an fprintf! */ /* no perror? make an fprintf! */
#ifndef HAVE_PERROR #ifndef HAVE_PERROR
# define perror(x) fprintf(stderr, "Error in: %s\n", x) # define perror(x) fprintf(stderr, "Error in: %s\n", x)

View File

@@ -104,6 +104,7 @@
#include "memdebug.h" #include "memdebug.h"
#endif #endif
/* ------------------------------------------------------------------------- */
/* /*
* The add_buffer series of functions are used to build one large memory chunk * The add_buffer series of functions are used to build one large memory chunk
* from repeated function invokes. Used so that the entire HTTP request can * from repeated function invokes. Used so that the entire HTTP request can
@@ -205,7 +206,7 @@ CURLcode add_buffer(send_buffer *in, void *inptr, size_t size)
} }
/* end of the add_buffer functions */ /* end of the add_buffer functions */
/*****************************************************************************/ /* ------------------------------------------------------------------------- */
/* /*
* Read everything until a newline. * Read everything until a newline.
@@ -282,8 +283,8 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn,
"%s" "%s"
"\r\n", "\r\n",
hostname, remote_port, hostname, remote_port,
(data->bits.proxy_user_passwd)?data->ptr_proxyuserpwd:"", (conn->bits.proxy_user_passwd)?conn->allocptr.proxyuserpwd:"",
(data->useragent?data->ptr_uagent:"") (data->useragent?conn->allocptr.uagent:"")
); );
/* 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 */
@@ -309,6 +310,9 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn,
return CURLE_OK; return CURLE_OK;
} }
/*
* HTTP stuff to do at connect-time.
*/
CURLcode Curl_http_connect(struct connectdata *conn) CURLcode Curl_http_connect(struct connectdata *conn)
{ {
struct UrlData *data; struct UrlData *data;
@@ -325,21 +329,21 @@ CURLcode Curl_http_connect(struct connectdata *conn)
if (conn->protocol & PROT_HTTPS) { if (conn->protocol & PROT_HTTPS) {
if (data->bits.httpproxy) { if (data->bits.httpproxy) {
/* 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, data->firstsocket, result = Curl_ConnectHTTPProxyTunnel(conn, conn->firstsocket,
data->hostname, data->remote_port); conn->hostname, conn->remote_port);
if(CURLE_OK != result) if(CURLE_OK != result)
return result; return result;
} }
/* now, perform the SSL initialization for this socket */ /* now, perform the SSL initialization for this socket */
if(Curl_SSLConnect(data)) if(Curl_SSLConnect(conn))
return CURLE_SSL_CONNECT_ERROR; return CURLE_SSL_CONNECT_ERROR;
} }
if(data->bits.user_passwd && !data->bits.this_is_a_follow) { if(conn->bits.user_passwd && !data->bits.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(data->hostname); data->auth_host = strdup(conn->hostname);
} }
return CURLE_OK; return CURLE_OK;
@@ -361,7 +365,7 @@ CURLcode Curl_http_done(struct connectdata *conn)
struct HTTP *http; struct HTTP *http;
data=conn->data; data=conn->data;
http=data->proto.http; http=conn->proto.http;
if(data->bits.http_formpost) { if(data->bits.http_formpost) {
*bytecount = http->readbytecount + http->writebytecount; *bytecount = http->readbytecount + http->writebytecount;
@@ -390,11 +394,20 @@ CURLcode Curl_http(struct connectdata *conn)
char *host = conn->name; char *host = conn->name;
long *bytecount = &conn->bytecount; long *bytecount = &conn->bytecount;
http = (struct HTTP *)malloc(sizeof(struct HTTP)); if(!conn->proto.http) {
if(!http) /* Only allocate this struct if we don't already have it! */
return CURLE_OUT_OF_MEMORY;
memset(http, 0, sizeof(struct HTTP)); http = (struct HTTP *)malloc(sizeof(struct HTTP));
data->proto.http = http; if(!http)
return CURLE_OUT_OF_MEMORY;
memset(http, 0, sizeof(struct HTTP));
conn->proto.http = http;
}
else
http = conn->proto.http;
/* We default to persistant connections */
conn->bits.close = FALSE;
if ( (conn->protocol&(PROT_HTTP|PROT_FTP)) && if ( (conn->protocol&(PROT_HTTP|PROT_FTP)) &&
data->bits.upload) { data->bits.upload) {
@@ -405,33 +418,39 @@ CURLcode Curl_http(struct connectdata *conn)
have been used in the proxy connect, but if we have got a header with have been used in the proxy connect, but if we have got a header with
the user-agent string specified, we erase the previously made string the user-agent string specified, we erase the previously made string
here. */ here. */
if(checkheaders(data, "User-Agent:") && data->ptr_uagent) { if(checkheaders(data, "User-Agent:") && conn->allocptr.uagent) {
free(data->ptr_uagent); free(conn->allocptr.uagent);
data->ptr_uagent=NULL; conn->allocptr.uagent=NULL;
} }
if((data->bits.user_passwd) && !checkheaders(data, "Authorization:")) { if((conn->bits.user_passwd) && !checkheaders(data, "Authorization:")) {
char *authorization; char *authorization;
/* 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->bits.this_is_a_follow ||
!data->auth_host || !data->auth_host ||
strequal(data->auth_host, data->hostname)) { strequal(data->auth_host, conn->hostname)) {
sprintf(data->buffer, "%s:%s", data->user, data->passwd); sprintf(data->buffer, "%s:%s", data->user, data->passwd);
if(Curl_base64_encode(data->buffer, strlen(data->buffer), if(Curl_base64_encode(data->buffer, strlen(data->buffer),
&authorization) >= 0) { &authorization) >= 0) {
data->ptr_userpwd = aprintf( "Authorization: Basic %s\015\012", if(conn->allocptr.userpwd)
free(conn->allocptr.userpwd);
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->bits.http_set_referer) && !checkheaders(data, "Referer:")) {
data->ptr_ref = aprintf("Referer: %s\015\012", data->referer); if(conn->allocptr.ref)
free(conn->allocptr.ref);
conn->allocptr.ref = aprintf("Referer: %s\015\012", data->referer);
} }
if(data->cookie && !checkheaders(data, "Cookie:")) { if(data->cookie && !checkheaders(data, "Cookie:")) {
data->ptr_cookie = aprintf("Cookie: %s\015\012", data->cookie); if(conn->allocptr.cookie)
free(conn->allocptr.cookie);
conn->allocptr.cookie = aprintf("Cookie: %s\015\012", data->cookie);
} }
if(data->cookies) { if(data->cookies) {
@@ -451,13 +470,22 @@ CURLcode Curl_http(struct connectdata *conn)
} }
if(!checkheaders(data, "Host:")) { if(!checkheaders(data, "Host:")) {
if(((conn->protocol&PROT_HTTPS) && (data->remote_port == PORT_HTTPS)) || /* if ptr_host is already set, it is almost OK since we only re-use
(!(conn->protocol&PROT_HTTPS) && (data->remote_port == PORT_HTTP)) ) connections to the very same host and port, but when we use a HTTP
proxy we have a persistant connect and yet we must change the Host:
header! */
if(conn->allocptr.host)
free(conn->allocptr.host);
if(((conn->protocol&PROT_HTTPS) && (conn->remote_port == PORT_HTTPS)) ||
(!(conn->protocol&PROT_HTTPS) && (conn->remote_port == PORT_HTTP)) )
/* If (HTTPS on port 443) OR (non-HTTPS on port 80) then don't include /* If (HTTPS on port 443) OR (non-HTTPS on port 80) then don't include
the port number in the host string */ the port number in the host string */
data->ptr_host = aprintf("Host: %s\r\n", host); conn->allocptr.host = aprintf("Host: %s\r\n", host);
else else
data->ptr_host = aprintf("Host: %s:%d\r\n", host, data->remote_port); conn->allocptr.host = aprintf("Host: %s:%d\r\n", host,
conn->remote_port);
} }
if(!checkheaders(data, "Pragma:")) if(!checkheaders(data, "Pragma:"))
@@ -531,7 +559,7 @@ CURLcode Curl_http(struct connectdata *conn)
*/ */
if((data->httpreq == HTTPREQ_GET) && if((data->httpreq == HTTPREQ_GET) &&
!checkheaders(data, "Range:")) { !checkheaders(data, "Range:")) {
data->ptr_rangeline = aprintf("Range: bytes=%s\r\n", data->range); conn->allocptr.rangeline = aprintf("Range: bytes=%s\r\n", data->range);
} }
else if((data->httpreq != HTTPREQ_GET) && else if((data->httpreq != HTTPREQ_GET) &&
!checkheaders(data, "Content-Range:")) { !checkheaders(data, "Content-Range:")) {
@@ -539,14 +567,14 @@ CURLcode Curl_http(struct connectdata *conn)
if(data->resume_from) { if(data->resume_from) {
/* This is because "resume" was selected */ /* This is because "resume" was selected */
long total_expected_size= data->resume_from + data->infilesize; long total_expected_size= data->resume_from + data->infilesize;
data->ptr_rangeline = aprintf("Content-Range: bytes %s%ld/%ld\r\n", conn->allocptr.rangeline = aprintf("Content-Range: bytes %s%ld/%ld\r\n",
data->range, total_expected_size-1, data->range, total_expected_size-1,
total_expected_size); total_expected_size);
} }
else { else {
/* 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 */
data->ptr_rangeline = aprintf("Content-Range: bytes %s/%d\r\n", conn->allocptr.rangeline = aprintf("Content-Range: bytes %s/%d\r\n",
data->range, data->infilesize); data->range, data->infilesize);
} }
} }
@@ -562,7 +590,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.0\r\n" /* path */ "%s HTTP/1.1\r\n" /* path */
"%s" /* proxyuserpwd */ "%s" /* proxyuserpwd */
"%s" /* userpwd */ "%s" /* userpwd */
"%s" /* range */ "%s" /* range */
@@ -578,15 +606,19 @@ CURLcode Curl_http(struct connectdata *conn)
(data->bits.http_post || data->bits.http_formpost)?"POST": (data->bits.http_post || data->bits.http_formpost)?"POST":
(data->bits.http_put)?"PUT":"GET"), (data->bits.http_put)?"PUT":"GET"),
ppath, ppath,
(data->bits.proxy_user_passwd && data->ptr_proxyuserpwd)?data->ptr_proxyuserpwd:"", (conn->bits.proxy_user_passwd &&
(data->bits.user_passwd && data->ptr_userpwd)?data->ptr_userpwd:"", conn->allocptr.proxyuserpwd)?conn->allocptr.proxyuserpwd:"",
(data->bits.set_range && data->ptr_rangeline)?data->ptr_rangeline:"", (conn->bits.user_passwd && conn->allocptr.userpwd)?
(data->useragent && *data->useragent && data->ptr_uagent)?data->ptr_uagent:"", conn->allocptr.userpwd:"",
(data->ptr_cookie?data->ptr_cookie:""), /* Cookie: <data> */ (data->bits.set_range && conn->allocptr.rangeline)?
(data->ptr_host?data->ptr_host:""), /* Host: host */ conn->allocptr.rangeline:"",
(data->useragent && *data->useragent && conn->allocptr.uagent)?
conn->allocptr.uagent:"",
(conn->allocptr.cookie?conn->allocptr.cookie:""), /* Cookie: <data> */
(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 && data->ptr_ref)?data->ptr_ref:"" /* Referer: <data> <CRLF> */ (data->bits.http_set_referer && conn->allocptr.ref)?conn->allocptr.ref:"" /* Referer: <data> <CRLF> */
); );
if(co) { if(co) {
@@ -690,10 +722,10 @@ CURLcode Curl_http(struct connectdata *conn)
Curl_pgrsSetUploadSize(data, http->postsize); Curl_pgrsSetUploadSize(data, http->postsize);
data->request_size = data->request_size =
add_buffer_send(data->firstsocket, conn, req_buffer); add_buffer_send(conn->firstsocket, conn, req_buffer);
result = Curl_Transfer(conn, data->firstsocket, -1, TRUE, result = Curl_Transfer(conn, conn->firstsocket, -1, TRUE,
&http->readbytecount, &http->readbytecount,
data->firstsocket, conn->firstsocket,
&http->writebytecount); &http->writebytecount);
if(result) { if(result) {
Curl_FormFree(http->sendit); /* free that whole lot */ Curl_FormFree(http->sendit); /* free that whole lot */
@@ -716,12 +748,12 @@ CURLcode Curl_http(struct connectdata *conn)
/* this sends the buffer and frees all the buffer resources */ /* this sends the buffer and frees all the buffer resources */
data->request_size = data->request_size =
add_buffer_send(data->firstsocket, conn, req_buffer); add_buffer_send(conn->firstsocket, conn, req_buffer);
/* prepare for transfer */ /* prepare for transfer */
result = Curl_Transfer(conn, data->firstsocket, -1, TRUE, result = Curl_Transfer(conn, conn->firstsocket, -1, TRUE,
&http->readbytecount, &http->readbytecount,
data->firstsocket, conn->firstsocket,
&http->writebytecount); &http->writebytecount);
if(result) if(result)
return result; return result;
@@ -762,10 +794,10 @@ CURLcode Curl_http(struct connectdata *conn)
/* issue the request */ /* issue the request */
data->request_size = data->request_size =
add_buffer_send(data->firstsocket, conn, req_buffer); add_buffer_send(conn->firstsocket, conn, req_buffer);
/* HTTP GET/HEAD download: */ /* HTTP GET/HEAD download: */
result = Curl_Transfer(conn, data->firstsocket, -1, TRUE, bytecount, result = Curl_Transfer(conn, conn->firstsocket, -1, TRUE, bytecount,
-1, NULL); /* nothing to upload */ -1, NULL); /* nothing to upload */
} }
if(result) if(result)

View File

@@ -35,4 +35,9 @@ 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); CURLcode Curl_http_close(struct connectdata *conn);
/* The following functions are defined in http_chunks.c */
void Curl_httpchunk_init(struct connectdata *conn);
CHUNKcode Curl_httpchunk_read(struct connectdata *conn, char *datap,
ssize_t length, ssize_t *wrote);
#endif #endif

222
lib/http_chunks.c Normal file
View File

@@ -0,0 +1,222 @@
/*****************************************************************************
* _ _ ____ _
* 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"
/* -- WIN32 approved -- */
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <stdlib.h>
#include <ctype.h>
#include "urldata.h" /* it includes http_chunks.h */
#include "sendf.h" /* for the client write stuff */
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
/* The last #include file should be: */
#ifdef MALLOCDEBUG
#include "memdebug.h"
#endif
/*
* Chunk format (simplified):
*
* <HEX SIZE>[ chunk extension ] CRLF
* <DATA>
*
* Highlights from RFC2616 section 3.6 say:
The chunked encoding modifies the body of a message in order to
transfer it as a series of chunks, each with its own size indicator,
followed by an OPTIONAL trailer containing entity-header fields. This
allows dynamically produced content to be transferred along with the
information necessary for the recipient to verify that it has
received the full message.
Chunked-Body = *chunk
last-chunk
trailer
CRLF
chunk = chunk-size [ chunk-extension ] CRLF
chunk-data CRLF
chunk-size = 1*HEX
last-chunk = 1*("0") [ chunk-extension ] CRLF
chunk-extension= *( ";" chunk-ext-name [ "=" chunk-ext-val ] )
chunk-ext-name = token
chunk-ext-val = token | quoted-string
chunk-data = chunk-size(OCTET)
trailer = *(entity-header CRLF)
The chunk-size field is a string of hex digits indicating the size of
the chunk. The chunked encoding is ended by any chunk whose size is
zero, followed by the trailer, which is terminated by an empty line.
*/
void Curl_httpchunk_init(struct connectdata *conn)
{
struct Curl_chunker *chunk = &conn->proto.http->chunk;
chunk->hexindex=0; /* start at 0 */
chunk->dataleft=0; /* no data left yet! */
chunk->state = CHUNK_HEX; /* we get hex first! */
}
/*
* chunk_read() returns a OK for normal operations, or a positive return code
* for errors. STOP means this sequence of chunks is complete. The 'wrote'
* argument is set to tell the caller how many bytes we actually passed to the
* client (for byte-counting and whatever).
*
* The states and the state-machine is further explained in the header file.
*/
CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
char *datap,
ssize_t length,
ssize_t *wrote)
{
CURLcode result;
struct Curl_chunker *ch = &conn->proto.http->chunk;
int piece;
*wrote = 0; /* nothing yet */
while(length) {
switch(ch->state) {
case CHUNK_HEX:
if(isxdigit((int)*datap)) {
if(ch->hexindex < MAXNUM_SIZE) {
ch->hexbuffer[ch->hexindex] = *datap;
datap++;
length--;
ch->hexindex++;
}
else {
return CHUNKE_TOO_LONG_HEX; /* longer hex than we support */
}
}
else {
if(0 == ch->hexindex) {
/* This is illegal data, we received junk where we expected
a hexadecimal digit. */
return CHUNKE_ILLEGAL_HEX;
}
/* length and datap are unmodified */
ch->hexbuffer[ch->hexindex]=0;
ch->datasize=strtoul(ch->hexbuffer, NULL, 16);
ch->state = CHUNK_POSTHEX;
}
break;
case CHUNK_POSTHEX:
/* In this state, we're waiting for CRLF to arrive. We support
this to allow so called chunk-extensions to show up here
before the CRLF comes. */
if(*datap == '\r')
ch->state = CHUNK_CR;
length--;
datap++;
break;
case CHUNK_CR:
/* waiting for the LF */
if(*datap == '\n') {
/* we're now expecting data to come, unless size was zero! */
if(0 == ch->datasize) {
ch->state = CHUNK_STOP; /* stop reading! */
if(1 == length) {
/* This was the final byte, return right now */
return CHUNKE_STOP;
}
}
else
ch->state = CHUNK_DATA;
}
else
/* previously we got a fake CR, go back to CR waiting! */
ch->state = CHUNK_CR;
datap++;
length--;
break;
case CHUNK_DATA:
/* we get pure and fine data
We expect another 'datasize' of data. We have 'length' right now,
it can be more or less than 'datasize'. Get the smallest piece.
*/
piece = (ch->datasize >= length)?length:ch->datasize;
/* Write the data portion available */
result = Curl_client_write(conn->data, CLIENTWRITE_BODY, datap, piece);
if(result)
return CHUNKE_WRITE_ERROR;
*wrote += piece;
ch->datasize -= piece; /* decrease amount left to expect */
datap += piece; /* move read pointer forward */
length -= piece; /* decrease space left in this round */
if(0 == ch->datasize)
/* end of data this round, we now expect a trailing CRLF */
ch->state = CHUNK_POSTCR;
break;
case CHUNK_POSTCR:
if(*datap == '\r') {
ch->state = CHUNK_POSTLF;
datap++;
length--;
}
else
return CHUNKE_BAD_CHUNK;
break;
case CHUNK_POSTLF:
if(*datap == '\n') {
/*
* The last one before we go back to hex state and start all
* over.
*/
Curl_httpchunk_init(conn);
datap++;
length--;
}
else
return CHUNKE_BAD_CHUNK;
break;
case CHUNK_STOP:
/* If we arrive here, there is data left in the end of the buffer
even if there's no more chunks to read */
ch->dataleft = length;
return CHUNKE_STOP; /* return stop */
default:
return CHUNKE_STATE_ERROR;
}
}
return CHUNKE_OK;
}

87
lib/http_chunks.h Normal file
View File

@@ -0,0 +1,87 @@
#ifndef __HTTP_CHUNKS_H
#define __HTTP_CHUNKS_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$
*****************************************************************************/
/*
* The longest possible hexadecimal number we support in a chunked transfer.
* Weird enough, RFC2616 doesn't set a maximum size! Since we use strtoul()
* to convert it, we "only" support 2^32 bytes chunk data.
*/
#define MAXNUM_SIZE 16
typedef enum {
CHUNK_FIRST, /* never use */
/* In this we await and buffer all hexadecimal digits until we get one
that isn't a hexadecimal digit. When done, we go POSTHEX */
CHUNK_HEX,
/* We have received the hexadecimal digit and we eat all characters until
we get a CRLF pair. When we see a CR we go to the CR state. */
CHUNK_POSTHEX,
/* A single CR has been found and we should get a LF right away in this
state or we go back to POSTHEX. When LF is received, we go to DATA.
If the size given was zero, we set state to STOP and return. */
CHUNK_CR,
/* We eat the amount of data specified. When done, we move on to the
POST_CR state. */
CHUNK_DATA,
/* POSTCR should get a CR and nothing else, then move to POSTLF */
CHUNK_POSTCR,
/* POSTLF should get a LF and nothing else, then move back to HEX as
the CRLF combination marks the end of a chunk */
CHUNK_POSTLF,
/* This is mainly used to really mark that we're out of the game.
NOTE: that there's a 'dataleft' field in the struct that will tell how
many bytes that were not passed to the client in the end of the last
buffer! */
CHUNK_STOP,
CHUNK_LAST /* never use */
} ChunkyState;
typedef enum {
CHUNKE_STOP = -1,
CHUNKE_OK = 0,
CHUNKE_TOO_LONG_HEX = 1,
CHUNKE_ILLEGAL_HEX,
CHUNKE_BAD_CHUNK,
CHUNKE_WRITE_ERROR,
CHUNKE_STATE_ERROR,
CHUNKE_LAST
} CHUNKcode;
struct Curl_chunker {
char hexbuffer[ MAXNUM_SIZE + 1];
int hexindex;
ChunkyState state;
size_t datasize;
size_t dataleft; /* untouched data amount at the end of the last buffer */
};
#endif

View File

@@ -70,6 +70,11 @@
#include "inet_ntoa_r.h" #include "inet_ntoa_r.h"
#endif #endif
/* The last #include file should be: */
#ifdef MALLOCDEBUG
#include "memdebug.h"
#endif
#define SYS_ERROR -1 #define SYS_ERROR -1
char *Curl_if2ip(char *interface, char *buf, int buf_size) char *Curl_if2ip(char *interface, char *buf, int buf_size)
@@ -90,6 +95,7 @@ char *Curl_if2ip(char *interface, char *buf, int buf_size)
strcpy(req.ifr_name, interface); strcpy(req.ifr_name, interface);
req.ifr_addr.sa_family = AF_INET; req.ifr_addr.sa_family = AF_INET;
if (SYS_ERROR == ioctl(dummy, SIOCGIFADDR, &req, sizeof(req))) { if (SYS_ERROR == ioctl(dummy, SIOCGIFADDR, &req, sizeof(req))) {
sclose(dummy);
return NULL; return NULL;
} }
else { else {
@@ -104,7 +110,7 @@ char *Curl_if2ip(char *interface, char *buf, int buf_size)
ip[buf_size - 1] = 0; ip[buf_size - 1] = 0;
#endif #endif
} }
close(dummy); sclose(dummy);
} }
return ip; return ip;
} }

View File

@@ -290,7 +290,7 @@ krb4_auth(void *app_data, struct connectdata *conn)
size_t nread; size_t nread;
int l = sizeof(local_addr); int l = sizeof(local_addr);
if(getsockname(conn->data->firstsocket, if(getsockname(conn->firstsocket,
(struct sockaddr *)LOCAL_ADDR, &l) < 0) (struct sockaddr *)LOCAL_ADDR, &l) < 0)
perror("getsockname()"); perror("getsockname()");
@@ -339,9 +339,9 @@ krb4_auth(void *app_data, struct connectdata *conn)
return AUTH_CONTINUE; return AUTH_CONTINUE;
} }
/*ret = command("ADAT %s", p)*/ /*ret = command("ADAT %s", p)*/
Curl_ftpsendf(conn->data->firstsocket, conn, "ADAT %s", p); Curl_ftpsendf(conn->firstsocket, conn, "ADAT %s", p);
/* wait for feedback */ /* wait for feedback */
nread = Curl_GetFTPResponse(conn->data->firstsocket, nread = Curl_GetFTPResponse(conn->firstsocket,
conn->data->buffer, conn, NULL); conn->data->buffer, conn, NULL);
if(nread < 0) if(nread < 0)
return /*CURLE_OPERATION_TIMEOUTED*/-1; return /*CURLE_OPERATION_TIMEOUTED*/-1;
@@ -409,10 +409,10 @@ void krb_kauth(struct connectdata *conn)
save = set_command_prot(conn, prot_private); save = set_command_prot(conn, prot_private);
/*ret = command("SITE KAUTH %s", name);***/ /*ret = command("SITE KAUTH %s", name);***/
Curl_ftpsendf(conn->data->firstsocket, conn, Curl_ftpsendf(conn->firstsocket, conn,
"SITE KAUTH %s", conn->data->user); "SITE KAUTH %s", conn->data->user);
/* wait for feedback */ /* wait for feedback */
nread = Curl_GetFTPResponse(conn->data->firstsocket, conn->data->buffer, nread = Curl_GetFTPResponse(conn->firstsocket, conn->data->buffer,
conn, NULL); conn, NULL);
if(nread < 0) if(nread < 0)
return /*CURLE_OPERATION_TIMEOUTED*/; return /*CURLE_OPERATION_TIMEOUTED*/;
@@ -486,10 +486,10 @@ void krb_kauth(struct connectdata *conn)
} }
memset (tktcopy.dat, 0, tktcopy.length); memset (tktcopy.dat, 0, tktcopy.length);
/*ret = command("SITE KAUTH %s %s", name, p);***/ /*ret = command("SITE KAUTH %s %s", name, p);***/
Curl_ftpsendf(conn->data->firstsocket, conn, Curl_ftpsendf(conn->firstsocket, conn,
"SITE KAUTH %s %s", name, p); "SITE KAUTH %s %s", name, p);
/* wait for feedback */ /* wait for feedback */
nread = Curl_GetFTPResponse(conn->data->firstsocket, conn->data->buffer, nread = Curl_GetFTPResponse(conn->firstsocket, conn->data->buffer,
conn, NULL); conn, NULL);
if(nread < 0) if(nread < 0)
return /*CURLE_OPERATION_TIMEOUTED*/; return /*CURLE_OPERATION_TIMEOUTED*/;

View File

@@ -171,10 +171,10 @@ CURLcode Curl_ldap(struct connectdata *conn)
DYNA_GET_FUNCTION(int (*)(void *, char *, void *, void *, char **, char **, int (*)(void *, char *, int), void *, char *, int, unsigned long), ldap_entry2text); DYNA_GET_FUNCTION(int (*)(void *, char *, void *, void *, char **, char **, int (*)(void *, char *, int), void *, char *, int, unsigned long), ldap_entry2text);
DYNA_GET_FUNCTION(int (*)(void *, char *, void *, void *, char **, char **, int (*)(void *, char *, int), void *, char *, int, unsigned long, char *, char *), ldap_entry2html); DYNA_GET_FUNCTION(int (*)(void *, char *, void *, void *, char **, char **, int (*)(void *, char *, int), void *, char *, int, unsigned long, char *, char *), ldap_entry2html);
server = ldap_open(data->hostname, data->port); server = ldap_open(conn->hostname, conn->port);
if (server == NULL) { if (server == NULL) {
failf(data, "LDAP: Cannot connect to %s:%d", failf(data, "LDAP: Cannot connect to %s:%d",
data->hostname, data->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->user, data->passwd);

View File

@@ -7,36 +7,25 @@ LIBRARY LIBCURL
DESCRIPTION 'curl libcurl - http://curl.haxx.se' DESCRIPTION 'curl libcurl - http://curl.haxx.se'
EXPORTS EXPORTS
curl_close @ 1 ; curl_easy_cleanup @ 1 ;
curl_connect @ 2 ; curl_easy_getinfo @ 2 ;
curl_disconnect @ 3 ; curl_easy_init @ 3 ;
curl_do @ 4 ; curl_easy_perform @ 4 ;
curl_done @ 5 ; curl_easy_setopt @ 5 ;
curl_easy_cleanup @ 6 ; curl_escape @ 6 ;
curl_easy_getinfo @ 7 ; curl_formparse @ 7 ;
curl_easy_init @ 8 ; curl_formfree @ 8 ;
curl_easy_perform @ 9 ; curl_getdate @ 9 ;
curl_easy_setopt @ 10 ; curl_getenv @ 10 ;
curl_escape @ 11 ; curl_slist_append @ 11 ;
curl_formparse @ 12 ; curl_slist_free_all @ 12 ;
curl_free @ 13 ; curl_unescape @ 13 ;
curl_getdate @ 14 ; curl_version @ 14 ;
curl_getenv @ 15 ; curl_maprintf @ 15 ;
curl_init @ 16 ; curl_mfprintf @ 16 ;
curl_open @ 17 ; curl_mprintf @ 17 ;
curl_read @ 18 ; curl_msprintf @ 18 ;
curl_setopt @ 19 ; curl_msnprintf @ 19 ;
curl_slist_append @ 20 ; curl_mvfprintf @ 20 ;
curl_slist_free_all @ 21 ; curl_strequal @ 21 ;
curl_transfer @ 22 ; curl_strnequal @ 22 ;
curl_unescape @ 23 ;
curl_version @ 24 ;
curl_write @ 25 ;
maprintf @ 26 ;
mfprintf @ 27 ;
mprintf @ 28 ;
msprintf @ 29 ;
msnprintf @ 30 ;
mvfprintf @ 31 ;
strequal @ 32 ;
strnequal @ 33 ;

View File

@@ -72,7 +72,7 @@ void *curl_domalloc(size_t size, int line, char *source)
return mem; return mem;
} }
char *curl_dostrdup(char *str, int line, char *source) char *curl_dostrdup(const char *str, int line, char *source)
{ {
char *mem; char *mem;
size_t len; size_t len;
@@ -120,7 +120,7 @@ int curl_socket(int domain, int type, int protocol, int line, char *source)
return sockfd; return sockfd;
} }
int curl_accept(int s, struct sockaddr *addr, int *addrlen, int curl_accept(int s, struct sockaddr *addr, socklen_t *addrlen,
int line, char *source) int line, char *source)
{ {
int sockfd=(accept)(s, addr, addrlen); int sockfd=(accept)(s, addr, addrlen);

View File

@@ -7,13 +7,13 @@
void *curl_domalloc(size_t size, int line, char *source); void *curl_domalloc(size_t size, int line, char *source);
void *curl_dorealloc(void *ptr, size_t size, int line, char *source); void *curl_dorealloc(void *ptr, size_t size, int line, char *source);
void curl_dofree(void *ptr, int line, char *source); void curl_dofree(void *ptr, int line, char *source);
char *curl_dostrdup(char *str, int line, char *source); char *curl_dostrdup(const char *str, int line, char *source);
void curl_memdebug(char *logname); void curl_memdebug(char *logname);
/* file descriptor manipulators */ /* file descriptor manipulators */
int curl_socket(int domain, int type, int protocol, int, char *); int curl_socket(int domain, int type, int protocol, int, char *);
int curl_sclose(int sockfd, int, char *); int curl_sclose(int sockfd, int, char *);
int curl_accept(int s, struct sockaddr *addr, int *addrlen, int curl_accept(int s, struct sockaddr *addr, socklen_t *addrlen,
int line, char *source); int line, char *source);
/* FILE functions */ /* FILE functions */

View File

@@ -27,10 +27,26 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAVE_PWD_H
#include <pwd.h>
#endif
#include <curl/curl.h> #include <curl/curl.h>
#include "strequal.h" #include "strequal.h"
/* The last #include file should be: */
#ifdef MALLOCDEBUG
#include "memdebug.h"
#endif
/* Debug this single source file with: /* Debug this single source file with:
'make netrc' then run './netrc'! 'make netrc' then run './netrc'!
@@ -60,7 +76,7 @@ int Curl_parsenetrc(char *host,
char netrcbuffer[256]; char netrcbuffer[256];
int retcode=1; int retcode=1;
char *home = curl_getenv("HOME"); /* portable environment reader */ char *home = NULL;
int state=NOTHING; int state=NOTHING;
char state_login=0; char state_login=0;
@@ -68,11 +84,25 @@ int Curl_parsenetrc(char *host,
#define NETRC DOT_CHAR "netrc" #define NETRC DOT_CHAR "netrc"
if(!home) #if defined(HAVE_GETPWUID) && defined(HAVE_GETEUID)
return -1; struct passwd *pw;
pw= getpwuid(geteuid());
if (pw)
home = pw->pw_dir;
#else
void *pw=NULL;
#endif
if(NULL == pw) {
home = curl_getenv("HOME"); /* portable environment reader */
if(!home) {
return -1;
}
}
if(strlen(home)>(sizeof(netrcbuffer)-strlen(NETRC))) { if(strlen(home)>(sizeof(netrcbuffer)-strlen(NETRC))) {
free(home); if(NULL==pw)
free(home);
return -1; return -1;
} }
@@ -140,7 +170,8 @@ int Curl_parsenetrc(char *host,
fclose(file); fclose(file);
} }
free(home); if(NULL==pw)
free(home);
return retcode; return retcode;
} }

View File

@@ -482,10 +482,10 @@ sec_prot_internal(struct connectdata *conn, int level)
} }
if(level){ if(level){
Curl_ftpsendf(conn->data->firstsocket, conn, Curl_ftpsendf(conn->firstsocket, conn,
"PBSZ %u", s); "PBSZ %u", s);
/* wait for feedback */ /* wait for feedback */
nread = Curl_GetFTPResponse(conn->data->firstsocket, nread = Curl_GetFTPResponse(conn->firstsocket,
conn->data->buffer, conn, NULL); conn->data->buffer, conn, NULL);
if(nread < 0) if(nread < 0)
return /*CURLE_OPERATION_TIMEOUTED*/-1; return /*CURLE_OPERATION_TIMEOUTED*/-1;
@@ -501,10 +501,10 @@ sec_prot_internal(struct connectdata *conn, int level)
conn->buffer_size = s; conn->buffer_size = s;
} }
Curl_ftpsendf(conn->data->firstsocket, conn, Curl_ftpsendf(conn->firstsocket, conn,
"PROT %c", level["CSEP"]); "PROT %c", level["CSEP"]);
/* wait for feedback */ /* wait for feedback */
nread = Curl_GetFTPResponse(conn->data->firstsocket, nread = Curl_GetFTPResponse(conn->firstsocket,
conn->data->buffer, conn, NULL); conn->data->buffer, conn, NULL);
if(nread < 0) if(nread < 0)
return /*CURLE_OPERATION_TIMEOUTED*/-1; return /*CURLE_OPERATION_TIMEOUTED*/-1;
@@ -610,10 +610,10 @@ sec_login(struct connectdata *conn)
} }
infof(data, "Trying %s...\n", (*m)->name); infof(data, "Trying %s...\n", (*m)->name);
/*ret = command("AUTH %s", (*m)->name);***/ /*ret = command("AUTH %s", (*m)->name);***/
Curl_ftpsendf(conn->data->firstsocket, conn, Curl_ftpsendf(conn->firstsocket, conn,
"AUTH %s", (*m)->name); "AUTH %s", (*m)->name);
/* wait for feedback */ /* wait for feedback */
nread = Curl_GetFTPResponse(conn->data->firstsocket, nread = Curl_GetFTPResponse(conn->firstsocket,
conn->data->buffer, conn, NULL); conn->data->buffer, conn, NULL);
if(nread < 0) if(nread < 0)
return /*CURLE_OPERATION_TIMEOUTED*/-1; return /*CURLE_OPERATION_TIMEOUTED*/-1;

View File

@@ -50,7 +50,77 @@
#include "memdebug.h" #include "memdebug.h"
#endif #endif
/* infof() is for info message along the way */ /* returns last node in linked list */
static struct curl_slist *slist_get_last(struct curl_slist *list)
{
struct curl_slist *item;
/* if caller passed us a NULL, return now */
if (!list)
return NULL;
/* loop through to find the last item */
item = list;
while (item->next) {
item = item->next;
}
return item;
}
/* append a struct to the linked list. It always retunrs the address of the
* first record, so that you can sure this function as an initialization
* function as well as an append function. If you find this bothersome,
* then simply create a separate _init function and call it appropriately from
* within the proram. */
struct curl_slist *curl_slist_append(struct curl_slist *list,
const char *data)
{
struct curl_slist *last;
struct curl_slist *new_item;
new_item = (struct curl_slist *) malloc(sizeof(struct curl_slist));
if (new_item) {
new_item->next = NULL;
new_item->data = strdup(data);
}
else {
fprintf(stderr, "Cannot allocate memory for QUOTE list.\n");
return NULL;
}
if (list) {
last = slist_get_last(list);
last->next = new_item;
return list;
}
/* if this is the first item, then new_item *is* the list */
return new_item;
}
/* be nice and clean up resources */
void curl_slist_free_all(struct curl_slist *list)
{
struct curl_slist *next;
struct curl_slist *item;
if (!list)
return;
item = list;
do {
next = item->next;
if (item->data) {
free(item->data);
}
free(item);
item = next;
} while (next);
}
/* Curl_infof() is for info message along the way */
void Curl_infof(struct UrlData *data, char *fmt, ...) void Curl_infof(struct UrlData *data, char *fmt, ...)
{ {
@@ -63,7 +133,7 @@ void Curl_infof(struct UrlData *data, char *fmt, ...)
} }
} }
/* 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, char *fmt, ...) void Curl_failf(struct UrlData *data, char *fmt, ...)
@@ -72,8 +142,11 @@ void Curl_failf(struct UrlData *data, char *fmt, ...)
va_start(ap, fmt); va_start(ap, fmt);
if(data->errorbuffer) if(data->errorbuffer)
vsnprintf(data->errorbuffer, CURL_ERROR_SIZE, fmt, ap); vsnprintf(data->errorbuffer, CURL_ERROR_SIZE, fmt, ap);
else /* no errorbuffer receives this, write to data->err instead */ else if(!data->bits.mute) {
/* no errorbuffer receives this, write to data->err instead */
vfprintf(data->err, fmt, ap); vfprintf(data->err, fmt, ap);
fprintf(data->err, "\n");
}
va_end(ap); va_end(ap);
} }
@@ -111,15 +184,14 @@ CURLcode Curl_write(struct connectdata *conn, int sockfd,
size_t *written) size_t *written)
{ {
size_t bytes_written; size_t bytes_written;
struct UrlData *data=conn->data; /* conn knows data, not vice versa */
#ifdef USE_SSLEAY #ifdef USE_SSLEAY
if (data->ssl.use) { if (conn->ssl.use) {
int loop=100; /* just a precaution to never loop endlessly */ int loop=100; /* just a precaution to never loop endlessly */
while(loop--) { while(loop--) {
bytes_written = SSL_write(data->ssl.handle, mem, len); bytes_written = SSL_write(conn->ssl.handle, mem, len);
if((-1 != bytes_written) || if((-1 != bytes_written) ||
(SSL_ERROR_WANT_WRITE != SSL_get_error(data->ssl.handle, (SSL_ERROR_WANT_WRITE != SSL_get_error(conn->ssl.handle,
bytes_written) )) bytes_written) ))
break; break;
} }
@@ -141,23 +213,6 @@ CURLcode Curl_write(struct connectdata *conn, int sockfd,
return CURLE_OK; return CURLE_OK;
} }
/*
* External write-function, writes to the data-socket.
* Takes care of plain sockets, SSL or kerberos transparently.
*/
CURLcode curl_write(CURLconnect *c_conn, char *buf, size_t amount,
size_t *n)
{
struct connectdata *conn = (struct connectdata *)c_conn;
if(!n || !conn || (conn->handle != STRUCT_CONNECT))
return CURLE_FAILED_INIT;
return Curl_write(conn, conn->sockfd, buf, amount, n);
}
/* client_write() sends data to the write callback(s) /* client_write() sends data to the write callback(s)
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.
@@ -200,16 +255,15 @@ CURLcode Curl_read(struct connectdata *conn, int sockfd,
char *buf, size_t buffersize, char *buf, size_t buffersize,
ssize_t *n) ssize_t *n)
{ {
struct UrlData *data = conn->data;
ssize_t nread; ssize_t nread;
#ifdef USE_SSLEAY #ifdef USE_SSLEAY
if (data->ssl.use) { if (conn->ssl.use) {
int loop=100; /* just a precaution to never loop endlessly */ int loop=100; /* just a precaution to never loop endlessly */
while(loop--) { while(loop--) {
nread = SSL_read(data->ssl.handle, buf, buffersize); nread = SSL_read(conn->ssl.handle, buf, buffersize);
if((-1 != nread) || if((-1 != nread) ||
(SSL_ERROR_WANT_READ != SSL_get_error(data->ssl.handle, nread) )) (SSL_ERROR_WANT_READ != SSL_get_error(conn->ssl.handle, nread) ))
break; break;
} }
} }
@@ -228,19 +282,3 @@ CURLcode Curl_read(struct connectdata *conn, int sockfd,
return CURLE_OK; return CURLE_OK;
} }
/*
* The public read function reads from the 'sockfd' file descriptor only.
* Use the Curl_read() internally when you want to specify fd.
*/
CURLcode curl_read(CURLconnect *c_conn, char *buf, size_t buffersize,
ssize_t *n)
{
struct connectdata *conn = (struct connectdata *)c_conn;
if(!n || !conn || (conn->handle != STRUCT_CONNECT))
return CURLE_FAILED_INIT;
return Curl_read(conn, conn->sockfd, buf, buffersize, n);
}

View File

@@ -24,6 +24,7 @@
#include "setup.h" #include "setup.h"
#include <stdio.h> #include <stdio.h>
#include <string.h>
#if defined(__MINGW32__) #if defined(__MINGW32__)
#include <winsock.h> #include <winsock.h>
#endif #endif

View File

@@ -35,6 +35,7 @@
#include "formdata.h" /* for the boundary function */ #include "formdata.h" /* for the boundary function */
#ifdef USE_SSLEAY #ifdef USE_SSLEAY
#include <openssl/rand.h>
static char global_passwd[64]; static char global_passwd[64];
@@ -58,15 +59,108 @@ static int passwd_callback(char *buf, int num, int verify
return 0; return 0;
} }
/* This function is *highly* inspired by (and parts are directly stolen static
* from) source from the SSLeay package written by Eric Young bool seed_enough(struct connectdata *conn, /* unused for now */
* (eay@cryptsoft.com). */ int nread)
{
#ifdef HAVE_RAND_STATUS
/* only available in OpenSSL 0.9.5a and later */
if(RAND_status())
return TRUE;
#else
if(nread > 500)
/* this is a very silly decision to make */
return TRUE;
#endif
return FALSE; /* not enough */
}
static static
int cert_stuff(struct UrlData *data, int random_the_seed(struct connectdata *conn)
{
char *buf = conn->data->buffer; /* point to the big buffer */
int nread=0;
struct UrlData *data=conn->data;
/* Q: should we add support for a random file name as a libcurl option?
A: Yes, it is here */
#ifndef RANDOM_FILE
/* if RANDOM_FILE isn't defined, we only perform this if an option tells
us to! */
if(data->ssl.random_file)
#define RANDOM_FILE "" /* doesn't matter won't be used */
#endif
{
/* let the option override the define */
nread += RAND_load_file((data->ssl.random_file?
data->ssl.random_file:RANDOM_FILE),
16384);
if(seed_enough(conn, nread))
return nread;
}
#if defined(HAVE_RAND_EGD)
/* only available in OpenSSL 0.9.5 and later */
/* EGD_SOCKET is set at configure time or not at all */
#ifndef EGD_SOCKET
/* If we don't have the define set, we only do this if the egd-option
is set */
if(data->ssl.egdsocket)
#define EGD_SOCKET "" /* doesn't matter won't be used */
#endif
{
/* If there's an option and a define, the option overrides the
define */
int ret = RAND_egd(data->ssl.egdsocket?data->ssl.egdsocket:EGD_SOCKET);
if(-1 != ret) {
nread += ret;
if(seed_enough(conn, nread))
return nread;
}
}
#endif
/* If we get here, it means we need to seed the PRNG using a "silly"
approach! */
#ifdef HAVE_RAND_SCREEN
/* This one gets a random value by reading the currently shown screen */
RAND_screen();
nread = 100; /* just a value */
#else
{
int len;
char *area = Curl_FormBoundary();
if(!area)
return 3; /* out of memory */
len = strlen(area);
RAND_seed(area, len);
free(area); /* now remove the random junk */
}
#endif
/* generates a default path for the random seed file */
buf[0]=0; /* blank it first */
RAND_file_name(buf, BUFSIZE);
if ( buf[0] ) {
/* we got a file name to try */
nread += RAND_load_file(buf, 16384);
if(seed_enough(conn, nread))
return nread;
}
infof(conn->data, "Your connection is using a weak random seed!\n");
return nread;
}
static
int cert_stuff(struct connectdata *conn,
char *cert_file, char *cert_file,
char *key_file) char *key_file)
{ {
struct UrlData *data = conn->data;
if (cert_file != NULL) { if (cert_file != NULL) {
SSL *ssl; SSL *ssl;
X509 *x509; X509 *x509;
@@ -78,10 +172,10 @@ int cert_stuff(struct UrlData *data,
*/ */
strcpy(global_passwd, data->cert_passwd); strcpy(global_passwd, data->cert_passwd);
/* Set passwd callback: */ /* Set passwd callback: */
SSL_CTX_set_default_passwd_cb(data->ssl.ctx, passwd_callback); SSL_CTX_set_default_passwd_cb(conn->ssl.ctx, passwd_callback);
} }
if (SSL_CTX_use_certificate_file(data->ssl.ctx, if (SSL_CTX_use_certificate_file(conn->ssl.ctx,
cert_file, cert_file,
SSL_FILETYPE_PEM) <= 0) { SSL_FILETYPE_PEM) <= 0) {
failf(data, "unable to set certificate file (wrong password?)\n"); failf(data, "unable to set certificate file (wrong password?)\n");
@@ -90,14 +184,14 @@ int cert_stuff(struct UrlData *data,
if (key_file == NULL) if (key_file == NULL)
key_file=cert_file; key_file=cert_file;
if (SSL_CTX_use_PrivateKey_file(data->ssl.ctx, if (SSL_CTX_use_PrivateKey_file(conn->ssl.ctx,
key_file, key_file,
SSL_FILETYPE_PEM) <= 0) { SSL_FILETYPE_PEM) <= 0) {
failf(data, "unable to set public key file\n"); failf(data, "unable to set public key file\n");
return(0); return(0);
} }
ssl=SSL_new(data->ssl.ctx); ssl=SSL_new(conn->ssl.ctx);
x509=SSL_get_certificate(ssl); x509=SSL_get_certificate(ssl);
if (x509 != NULL) if (x509 != NULL)
@@ -111,7 +205,7 @@ int cert_stuff(struct UrlData *data,
/* Now we know that a key and cert have been set against /* Now we know that a key and cert have been set against
* the SSL context */ * the SSL context */
if (!SSL_CTX_check_private_key(data->ssl.ctx)) { if (!SSL_CTX_check_private_key(conn->ssl.ctx)) {
failf(data, "Private key does not match the certificate public key\n"); failf(data, "Private key does not match the certificate public key\n");
return(0); return(0);
} }
@@ -122,9 +216,6 @@ int cert_stuff(struct UrlData *data,
return(1); return(1);
} }
#endif
#ifdef USE_SSLEAY
static static
int cert_verify_callback(int ok, X509_STORE_CTX *ctx) int cert_verify_callback(int ok, X509_STORE_CTX *ctx)
{ {
@@ -141,152 +232,133 @@ int cert_verify_callback(int ok, X509_STORE_CTX *ctx)
/* ====================================================== */ /* ====================================================== */
int int
Curl_SSLConnect (struct UrlData *data) Curl_SSLConnect(struct connectdata *conn)
{ {
#ifdef USE_SSLEAY #ifdef USE_SSLEAY
int err; struct UrlData *data = conn->data;
char * str; int err;
SSL_METHOD *req_method; char * str;
SSL_METHOD *req_method;
/* mark this is being ssl enabled from here on out. */ /* mark this is being ssl enabled from here on out. */
data->ssl.use = TRUE; conn->ssl.use = TRUE;
/* Lets get nice error messages */ /* Lets get nice error messages */
SSL_load_error_strings(); SSL_load_error_strings();
#ifdef HAVE_RAND_STATUS /* Make funny stuff to get random input */
/* RAND_status() was introduced in OpenSSL 0.9.5 */ random_the_seed(conn);
if(0 == RAND_status())
#endif
{
/* We need to seed the PRNG properly! */
#ifdef HAVE_RAND_SCREEN
/* This one gets a random value by reading the currently shown screen */
RAND_screen();
#else
int len;
char *area = Curl_FormBoundary();
if(!area)
return 3; /* out of memory */
len = strlen(area);
RAND_seed(area, len);
free(area); /* now remove the random junk */
#endif
}
/* Setup all the global SSL stuff */ /* Setup all the global SSL stuff */
SSLeay_add_ssl_algorithms(); SSLeay_add_ssl_algorithms();
switch(data->ssl.version) { switch(data->ssl.version) {
default: default:
req_method = SSLv23_client_method(); req_method = SSLv23_client_method();
break; break;
case 2: case 2:
req_method = SSLv2_client_method(); req_method = SSLv2_client_method();
break; break;
case 3: case 3:
req_method = SSLv3_client_method(); req_method = SSLv3_client_method();
break; break;
} }
data->ssl.ctx = SSL_CTX_new(req_method); conn->ssl.ctx = SSL_CTX_new(req_method);
if(!data->ssl.ctx) { if(!conn->ssl.ctx) {
failf(data, "SSL: couldn't create a context!"); failf(data, "SSL: couldn't create a context!");
return 1; return 1;
} }
if(data->cert) { if(data->cert) {
if (!cert_stuff(data, data->cert, data->cert)) { if (!cert_stuff(conn, data->cert, data->cert)) {
failf(data, "couldn't use certificate!\n"); failf(data, "couldn't use certificate!\n");
return 2; return 2;
}
} }
}
if(data->ssl.verifypeer){ if(data->ssl.verifypeer){
SSL_CTX_set_verify(data->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(data->ssl.ctx, if (!SSL_CTX_load_verify_locations(conn->ssl.ctx,
data->ssl.CAfile, data->ssl.CAfile,
data->ssl.CApath)) { data->ssl.CApath)) {
failf(data,"error setting cerficate verify locations\n"); failf(data,"error setting cerficate verify locations\n");
return 2; return 2;
}
} }
else }
SSL_CTX_set_verify(data->ssl.ctx, SSL_VERIFY_NONE, cert_verify_callback); else
SSL_CTX_set_verify(conn->ssl.ctx, SSL_VERIFY_NONE, cert_verify_callback);
/* Lets make an SSL structure */ /* Lets make an SSL structure */
data->ssl.handle = SSL_new (data->ssl.ctx); conn->ssl.handle = SSL_new (conn->ssl.ctx);
SSL_set_connect_state (data->ssl.handle); SSL_set_connect_state (conn->ssl.handle);
data->ssl.server_cert = 0x0; conn->ssl.server_cert = 0x0;
/* pass the raw socket into the SSL layers */ /* pass the raw socket into the SSL layers */
SSL_set_fd (data->ssl.handle, data->firstsocket); SSL_set_fd (conn->ssl.handle, conn->firstsocket);
err = SSL_connect (data->ssl.handle); err = SSL_connect (conn->ssl.handle);
if (-1 == err) { if (-1 == err) {
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 10; return 10;
} }
/* Informational message */ /* Informational message */
infof (data, "SSL connection using %s\n", infof (data, "SSL connection using %s\n",
SSL_get_cipher(data->ssl.handle)); SSL_get_cipher(conn->ssl.handle));
/* 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
* to authenticate the server; otherwise we risk man-in-the-middle * to authenticate the server; otherwise we risk man-in-the-middle
* attack * attack
*/ */
data->ssl.server_cert = SSL_get_peer_certificate (data->ssl.handle); conn->ssl.server_cert = SSL_get_peer_certificate (conn->ssl.handle);
if(!data->ssl.server_cert) { if(!conn->ssl.server_cert) {
failf(data, "SSL: couldn't get peer certificate!"); failf(data, "SSL: couldn't get peer certificate!");
return 3; return 3;
} }
infof (data, "Server certificate:\n"); infof (data, "Server certificate:\n");
str = X509_NAME_oneline (X509_get_subject_name (data->ssl.server_cert), str = X509_NAME_oneline (X509_get_subject_name (conn->ssl.server_cert),
NULL, 0); NULL, 0);
if(!str) { if(!str) {
failf(data, "SSL: couldn't get X509-subject!"); failf(data, "SSL: couldn't get X509-subject!");
return 4; return 4;
} }
infof(data, "\t subject: %s\n", str); infof(data, "\t subject: %s\n", str);
CRYPTO_free(str); CRYPTO_free(str);
str = X509_NAME_oneline (X509_get_issuer_name (data->ssl.server_cert), str = X509_NAME_oneline (X509_get_issuer_name (conn->ssl.server_cert),
NULL, 0); NULL, 0);
if(!str) { if(!str) {
failf(data, "SSL: couldn't get X509-issuer name!"); failf(data, "SSL: couldn't get X509-issuer name!");
return 5; return 5;
} }
infof(data, "\t issuer: %s\n", str); infof(data, "\t issuer: %s\n", str);
CRYPTO_free(str); CRYPTO_free(str);
/* 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->ssl.verifypeer) {
data->ssl.certverifyresult=SSL_get_verify_result(data->ssl.handle); data->ssl.certverifyresult=SSL_get_verify_result(conn->ssl.handle);
infof(data, "Verify result: %d\n", data->ssl.certverifyresult); infof(data, "Verify result: %d\n", data->ssl.certverifyresult);
} }
else else
data->ssl.certverifyresult=0; data->ssl.certverifyresult=0;
X509_free(data->ssl.server_cert); X509_free(conn->ssl.server_cert);
#else /* USE_SSLEAY */ #else /* USE_SSLEAY */
/* this is for "-ansi -Wall -pedantic" to stop complaining! (rabe) */ /* this is for "-ansi -Wall -pedantic" to stop complaining! (rabe) */
(void) data; (void) conn;
#endif #endif
return 0; return 0;
} }

View File

@@ -22,5 +22,6 @@
* *
* $Id$ * $Id$
*****************************************************************************/ *****************************************************************************/
int Curl_SSLConnect (struct UrlData *data); #include "urldata.h"
int Curl_SSLConnect(struct connectdata *conn);
#endif #endif

View File

@@ -25,7 +25,7 @@
#include <string.h> #include <string.h>
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);
@@ -45,7 +45,7 @@ int Curl_strequal(const char *first, const char *second)
#endif #endif
} }
int Curl_strnequal(const char *first, const char *second, size_t max) int curl_strnequal(const char *first, const char *second, size_t max)
{ {
#if defined(HAVE_STRCASECMP) #if defined(HAVE_STRCASECMP)
return !strncasecmp(first, second, max); return !strncasecmp(first, second, max);

View File

@@ -22,10 +22,14 @@
* *
* $Id$ * $Id$
*****************************************************************************/ *****************************************************************************/
int Curl_strequal(const char *first, const char *second);
int Curl_strnequal(const char *first, const char *second, size_t max);
#define strequal(a,b) Curl_strequal(a,b) /*
#define strnequal(a,b,c) Curl_strnequal(a,b,c) * These two actually are public functions.
*/
int curl_strequal(const char *first, const char *second);
int curl_strnequal(const char *first, const char *second, size_t max);
#define strequal(a,b) curl_strequal(a,b)
#define strnequal(a,b,c) curl_strnequal(a,b,c)
#endif #endif

File diff suppressed because it is too large Load Diff

View File

@@ -53,7 +53,7 @@ gettimeofday (struct timeval *tp, void *nothing)
#endif #endif
#endif #endif
struct timeval Curl_tvnow () struct timeval Curl_tvnow (void)
{ {
struct timeval now; struct timeval now;
#ifdef HAVE_GETTIMEOFDAY #ifdef HAVE_GETTIMEOFDAY

View File

@@ -89,6 +89,7 @@
#include "getpass.h" #include "getpass.h"
#include "progress.h" #include "progress.h"
#include "getdate.h" #include "getdate.h"
#include "http.h"
#define _MPRINTF_REPLACE /* use our functions only */ #define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h> #include <curl/mprintf.h>
@@ -106,7 +107,7 @@
<butlerm@xmission.com>. */ <butlerm@xmission.com>. */
CURLcode static CURLcode static
_Transfer(struct connectdata *c_conn) Transfer(struct connectdata *c_conn)
{ {
ssize_t nread; /* number of bytes read */ ssize_t nread; /* number of bytes read */
int bytecount = 0; /* total number of bytes read */ int bytecount = 0; /* total number of bytes read */
@@ -126,7 +127,8 @@ _Transfer(struct connectdata *c_conn)
bool content_range = FALSE; /* set TRUE if Content-Range: was found */ bool content_range = FALSE; /* set TRUE if Content-Range: was found */
int offset = 0; /* possible resume offset read from the int offset = 0; /* possible resume offset read from the
Content-Range: header */ Content-Range: header */
int code = 0; /* error code from the 'HTTP/1.? XXX' line */ int httpcode = 0; /* error code from the 'HTTP/1.? XXX' line */
int httpversion = -1; /* the last digit in the HTTP/1.1 string */
/* for the low speed checks: */ /* for the low speed checks: */
CURLcode urg; CURLcode urg;
@@ -140,9 +142,6 @@ _Transfer(struct connectdata *c_conn)
char *buf; char *buf;
int maxfd; int maxfd;
if(!conn || (conn->handle != STRUCT_CONNECT))
return CURLE_BAD_FUNCTION_ARGUMENT;
data = conn->data; /* there's the root struct */ data = conn->data; /* there's the root struct */
buf = data->buffer; buf = data->buffer;
maxfd = (conn->sockfd>conn->writesockfd?conn->sockfd:conn->writesockfd)+1; maxfd = (conn->sockfd>conn->writesockfd?conn->sockfd:conn->writesockfd)+1;
@@ -182,7 +181,7 @@ _Transfer(struct connectdata *c_conn)
int keepon=0; int keepon=0;
/* timeout every X second /* timeout every X second
- makes a better progressmeter (i.e even when no data is read, the - makes a better progress meter (i.e even when no data is read, the
meter can be updated and reflect reality) meter can be updated and reflect reality)
- allows removal of the alarm() crap - allows removal of the alarm() crap
- variable timeout is easier - variable timeout is easier
@@ -311,18 +310,34 @@ _Transfer(struct connectdata *c_conn)
/* we now have a full line that p points to */ /* we now have a full line that p points to */
if (('\n' == *p) || ('\r' == *p)) { if (('\n' == *p) || ('\r' == *p)) {
/* Zero-length line means end of header! */ /* Zero-length line means end of header! */
#if 0
if (-1 != conn->size) /* if known */ if (-1 != conn->size) /* if known */
conn->size += bytecount; /* we append the already read size */ conn->size += bytecount; /* we append the already read
size */
#endif
if ('\r' == *p) if ('\r' == *p)
p++; /* pass the \r byte */ p++; /* pass the \r byte */
if ('\n' == *p) if ('\n' == *p)
p++; /* pass the \n byte */ p++; /* pass the \n byte */
#if 0 /* headers are not included in the size */
Curl_pgrsSetDownloadSize(data, conn->size); Curl_pgrsSetDownloadSize(data, conn->size);
#endif
header = FALSE; /* no more header to parse! */ if(100 == httpcode) {
/*
* we have made a HTTP PUT or POST and this is 1.1-lingo
* that tells us that the server is OK with this and ready
* to receive our stuff.
* However, we'll get more headers now so we must get
* back into the header-parsing state!
*/
header = TRUE;
headerline = 0; /* we restart the header line counter */
}
else
header = FALSE; /* no more header to parse! */
/* now, only output this if the header AND body are requested: /* now, only output this if the header AND body are requested:
*/ */
@@ -336,18 +351,39 @@ _Transfer(struct connectdata *c_conn)
return urg; return urg;
data->header_size += p - data->headerbuff; data->header_size += p - data->headerbuff;
break; /* exit header line loop */
if(!header) {
/*
* end-of-headers.
*
* If we requested a "no body" and this isn't a "close"
* connection, this is a good time to get out and return
* home.
*/
if(!conn->bits.close && data->bits.no_body)
return CURLE_OK;
break; /* exit header line loop */
}
/* We continue reading headers, so reset the line-based
header parsing variables hbufp && hbuflen */
hbufp = data->headerbuff;
hbuflen = 0;
continue;
} }
if (!headerline++) { if (!headerline++) {
/* This is the first header, it MUST be the error code line /* This is the first header, it MUST be the error code line
or else we consiser this to be the body right away! */ or else we consiser this to be the body right away! */
if (sscanf (p, " HTTP/1.%*c %3d", &code)) { if (2 == sscanf (p, " HTTP/1.%d %3d", &httpversion,
&httpcode)) {
/* 404 -> URL not found! */ /* 404 -> URL not found! */
if ( if (
( ((data->bits.http_follow_location) && (code >= 400)) ( ((data->bits.http_follow_location) &&
(httpcode >= 400))
|| ||
(!data->bits.http_follow_location && (code >= 300))) (!data->bits.http_follow_location &&
(httpcode >= 300)))
&& (data->bits.http_fail_on_error)) { && (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: */
@@ -355,7 +391,13 @@ _Transfer(struct connectdata *c_conn)
failf (data, "The requested file was not found"); failf (data, "The requested file was not found");
return CURLE_HTTP_NOT_FOUND; return CURLE_HTTP_NOT_FOUND;
} }
data->progress.httpcode = code; data->progress.httpcode = httpcode;
data->progress.httpversion = httpversion;
if(httpversion == 0)
/* Default action for HTTP/1.0 must be to close, unless
we get one of those fancy headers that tell us the
server keeps it open for us! */
conn->bits.close = TRUE;
} }
else { else {
header = FALSE; /* this is not a header line */ header = FALSE; /* this is not a header line */
@@ -364,12 +406,52 @@ _Transfer(struct connectdata *c_conn)
} }
/* check for Content-Length: header lines to get size */ /* check for Content-Length: header lines to get size */
if (strnequal("Content-Length", p, 14) && if (strnequal("Content-Length", p, 14) &&
sscanf (p+14, ": %ld", &contentlength)) sscanf (p+14, ": %ld", &contentlength)) {
conn->size = contentlength; conn->size = contentlength;
Curl_pgrsSetDownloadSize(data, contentlength);
}
else if((httpversion == 0) &&
conn->bits.httpproxy &&
strnequal("Proxy-Connection: keep-alive", p,
strlen("Proxy-Connection: keep-alive"))) {
/*
* When a HTTP/1.0 reply comes when using a proxy, the
* 'Proxy-Connection: keep-alive' line tells us the
* connection will be kept alive for our pleasure.
* Default action for 1.0 is to close.
*/
conn->bits.close = FALSE; /* don't close when done */
infof(data, "HTTP/1.0 proxy connection set to keep alive!\n");
}
else if (strnequal("Connection: close", p,
strlen("Connection: close"))) {
/*
* [RFC 2616, section 8.1.2.1]
* "Connection: close" is HTTP/1.1 language and means that
* the connection will close when this request has been
* served.
*/
conn->bits.close = TRUE; /* close when done */
}
else if (strnequal("Transfer-Encoding: chunked", p,
strlen("Transfer-Encoding: chunked"))) {
/*
* [RFC 2616, section 3.6.1] A 'chunked' transfer encoding
* means that the server will send a series of "chunks". Each
* chunk starts with line with info (including size of the
* coming block) (terminated with CRLF), then a block of data
* with the previously mentioned size. There can be any amount
* of chunks, and a chunk-data set to zero signals the
* end-of-chunks. */
conn->bits.chunk = TRUE; /* chunks coming our way */
/* init our chunky engine */
Curl_httpchunk_init(conn);
}
else if (strnequal("Content-Range", p, 13)) { else if (strnequal("Content-Range", p, 13)) {
if (sscanf (p+13, ": bytes %d-", &offset) || if (sscanf (p+13, ": bytes %d-", &offset) ||
sscanf (p+13, ": bytes: %d-", &offset)) { sscanf (p+13, ": bytes: %d-", &offset)) {
/* This second format was added August 1st by Igor /* This second format was added August 1st 2000 by Igor
Khristophorov since Sun's webserver JavaWebServer/1.1.1 Khristophorov since Sun's webserver JavaWebServer/1.1.1
obviously sends the header this way! :-( */ obviously sends the header this way! :-( */
if (data->resume_from == offset) { if (data->resume_from == offset) {
@@ -390,7 +472,7 @@ _Transfer(struct connectdata *c_conn)
if(data->bits.get_filetime) if(data->bits.get_filetime)
data->progress.filetime = timeofdoc; data->progress.filetime = timeofdoc;
} }
else if ((code >= 300 && code < 400) && else if ((httpcode >= 300 && httpcode < 400) &&
(data->bits.http_follow_location) && (data->bits.http_follow_location) &&
strnequal("Location: ", p, 10)) { strnequal("Location: ", p, 10)) {
/* this is the URL that the server advices us to get instead */ /* this is the URL that the server advices us to get instead */
@@ -405,7 +487,7 @@ _Transfer(struct connectdata *c_conn)
ptr++; ptr++;
backup = *ptr; /* store the ending letter */ backup = *ptr; /* store the ending letter */
*ptr = '\0'; /* zero terminate */ *ptr = '\0'; /* zero terminate */
data->newurl = strdup(start); /* clone string */ conn->newurl = strdup(start); /* clone string */
*ptr = backup; /* restore ending letter */ *ptr = backup; /* restore ending letter */
} }
@@ -446,12 +528,12 @@ _Transfer(struct connectdata *c_conn)
if(0 == bodywrites) { if(0 == bodywrites) {
/* These checks are only made the first time we are about to /* These checks are only made the first time we are about to
write a chunk of the body */ write a piece of the body */
if(conn->protocol&PROT_HTTP) { if(conn->protocol&PROT_HTTP) {
/* HTTP-only checks */ /* HTTP-only checks */
if (data->newurl) { if (conn->newurl) {
/* abort after the headers if "follow Location" is set */ /* abort after the headers if "follow Location" is set */
infof (data, "Follow to new URL: %s\n", data->newurl); infof (data, "Follow to new URL: %s\n", conn->newurl);
return CURLE_OK; return CURLE_OK;
} }
else if (data->resume_from && else if (data->resume_from &&
@@ -489,13 +571,49 @@ _Transfer(struct connectdata *c_conn)
} /* switch */ } /* switch */
} /* two valid time strings */ } /* two valid time strings */
} /* we have a time condition */ } /* we have a time condition */
if(!conn->bits.close) {
/* If this is not the last request before a close, we must
set the maximum download size to the size of the expected
document or else, we won't know when to stop reading! */
if(-1 != conn->size)
conn->maxdownload = conn->size;
/* What to do if the size is *not* known? */
}
} /* this is HTTP */ } /* this is HTTP */
} /* this is the first time we write a body part */ } /* this is the first time we write a body part */
bodywrites++; bodywrites++;
if(data->maxdownload && if(conn->bits.chunk) {
(bytecount + nread > data->maxdownload)) { /*
nread = data->maxdownload - bytecount; * Bless me father for I have sinned. Here comes a chunked
* transfer flying and we need to decode this properly. While
* the name says read, this function both reads and writes away
* the data. The returned 'nread' holds the number of actual
* data it wrote to the client. */
CHUNKcode res =
Curl_httpchunk_read(conn, str, nread, &nread);
if(CHUNKE_OK < res) {
failf(data, "Receeived problem in the chunky parser");
return CURLE_READ_ERROR;
}
else if(CHUNKE_STOP == res) {
/* we're done reading chunks! */
keepon &= ~KEEP_READ; /* read no more */
/* There are now possibly N number of bytes at the end of the
str buffer that weren't written to the client, but we don't
care about them right now. */
}
/* If it returned OK, we just keep going */
}
if(conn->maxdownload &&
(bytecount + nread >= conn->maxdownload)) {
nread = conn->maxdownload - bytecount;
if((signed int)nread < 0 ) /* this should be unusual */ if((signed int)nread < 0 ) /* this should be unusual */
nread = 0; nread = 0;
keepon &= ~KEEP_READ; /* we're done reading */ keepon &= ~KEEP_READ; /* we're done reading */
@@ -505,9 +623,12 @@ _Transfer(struct connectdata *c_conn)
Curl_pgrsSetDownloadCounter(data, (double)bytecount); Curl_pgrsSetDownloadCounter(data, (double)bytecount);
urg = Curl_client_write(data, CLIENTWRITE_BODY, str, nread); if(! conn->bits.chunk) {
if(urg) /* If this is chunky transfer, it was already written */
return urg; urg = Curl_client_write(data, CLIENTWRITE_BODY, str, nread);
if(urg)
return urg;
}
} /* if (! header and data to read ) */ } /* if (! header and data to read ) */
} /* if( read from socket ) */ } /* if( read from socket ) */
@@ -593,6 +714,11 @@ _Transfer(struct connectdata *c_conn)
contentlength-bytecount); contentlength-bytecount);
return CURLE_PARTIAL_FILE; return CURLE_PARTIAL_FILE;
} }
else if(conn->bits.chunk && conn->proto.http->chunk.datasize) {
failf(data, "transfer closed with at least %d bytes remaining",
conn->proto.http->chunk.datasize);
return CURLE_PARTIAL_FILE;
}
if(Curl_pgrsUpdate(data)) if(Curl_pgrsUpdate(data))
return CURLE_ABORTED_BY_CALLBACK; return CURLE_ABORTED_BY_CALLBACK;
@@ -604,28 +730,27 @@ _Transfer(struct connectdata *c_conn)
return CURLE_OK; return CURLE_OK;
} }
typedef int (*func_T)(void); CURLcode Curl_perform(CURL *curl)
CURLcode curl_transfer(CURL *curl)
{ {
CURLcode res; CURLcode res;
struct UrlData *data = curl; struct UrlData *data = (struct UrlData *)curl;
struct connectdata *c_connect=NULL; struct connectdata *conn=NULL;
bool port=TRUE; /* allow data->use_port to set port to use */
Curl_pgrsStartNow(data); Curl_pgrsStartNow(data);
do { do {
Curl_pgrsTime(data, TIMER_STARTSINGLE); Curl_pgrsTime(data, TIMER_STARTSINGLE);
res = curl_connect(curl, (CURLconnect **)&c_connect); res = Curl_connect(data, &conn, port);
if(res == CURLE_OK) { if(res == CURLE_OK) {
res = curl_do(c_connect); res = Curl_do(conn);
if(res == CURLE_OK) { if(res == CURLE_OK) {
res = _Transfer(c_connect); /* now fetch that URL please */ res = Transfer(conn); /* now fetch that URL please */
if(res == CURLE_OK) if(res == CURLE_OK)
res = curl_done(c_connect); res = Curl_done(conn);
} }
if((res == CURLE_OK) && data->newurl) { if((res == CURLE_OK) && conn->newurl) {
/* Location: redirect /* Location: redirect
This is assumed to happen for HTTP(S) only! This is assumed to happen for HTTP(S) only!
@@ -633,9 +758,14 @@ CURLcode curl_transfer(CURL *curl)
char prot[16]; /* URL protocol string storage */ char prot[16]; /* URL protocol string storage */
char letter; /* used for a silly sscanf */ char letter; /* used for a silly sscanf */
port=TRUE; /* by default we use the user set port number even after
a Location: */
if (data->maxredirs && (data->followlocation >= data->maxredirs)) { if (data->maxredirs && (data->followlocation >= data->maxredirs)) {
failf(data,"Maximum (%d) redirects followed", data->maxredirs); failf(data,"Maximum (%d) redirects followed", data->maxredirs);
#ifdef USE_OLD_DISCONNECT
curl_disconnect(c_connect); curl_disconnect(c_connect);
#endif
res=CURLE_TOO_MANY_REDIRECTS; res=CURLE_TOO_MANY_REDIRECTS;
break; break;
} }
@@ -660,7 +790,7 @@ CURLcode curl_transfer(CURL *curl)
data->bits.http_set_referer = TRUE; /* might have been false */ data->bits.http_set_referer = TRUE; /* might have been false */
} }
if(2 != sscanf(data->newurl, "%15[^:]://%c", prot, &letter)) { if(2 != sscanf(conn->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!
@@ -678,13 +808,14 @@ CURLcode curl_transfer(CURL *curl)
if(!protsep) if(!protsep)
protsep=data->url; protsep=data->url;
else { else {
/* TBD: set the port with curl_setopt() */ port=FALSE; /* we got a full URL and thus we should not obey the
data->port=0; /* we got a full URL and then we should reset the port number that might have been set by the user
port number here to re-initiate it later */ in data->use_port */
protsep+=2; /* pass the slashes */ protsep+=2; /* pass the slashes */
} }
if('/' != data->newurl[0]) { if('/' != conn->newurl[0]) {
/* First we need to find out if there's a ?-letter in the URL, /* First we need to find out if there's a ?-letter in the URL,
and cut it and the right-side of that off */ and cut it and the right-side of that off */
pathsep = strrchr(protsep, '?'); pathsep = strrchr(protsep, '?');
@@ -707,27 +838,26 @@ CURLcode curl_transfer(CURL *curl)
newest=(char *)malloc( strlen(data->url) + newest=(char *)malloc( strlen(data->url) +
1 + /* possible slash */ 1 + /* possible slash */
strlen(data->newurl) + 1/* zero byte */); strlen(conn->newurl) + 1/* zero byte */);
if(!newest) if(!newest)
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
sprintf(newest, "%s%s%s", data->url, ('/' == data->newurl[0])?"":"/", sprintf(newest, "%s%s%s", data->url, ('/' == conn->newurl[0])?"":"/",
data->newurl); conn->newurl);
free(data->newurl); free(conn->newurl);
data->newurl = newest; conn->newurl = newest;
} }
else { else {
/* This was an absolute URL, clear the port number! */ /* This is an absolute URL, don't use the custom port number */
/* TBD: set the port with curl_setopt() */ port = FALSE;
data->port = 0;
} }
if(data->bits.urlstringalloc) if(data->bits.urlstringalloc)
free(data->url); free(data->url);
/* TBD: set the URL with curl_setopt() */ /* TBD: set the URL with curl_setopt() */
data->url = data->newurl; data->url = conn->newurl;
data->newurl = NULL; /* don't show! */ conn->newurl = NULL; /* don't show! */
data->bits.urlstringalloc = TRUE; /* the URL is allocated */ data->bits.urlstringalloc = TRUE; /* the URL is allocated */
infof(data, "Follows Location: to new URL: '%s'\n", data->url); infof(data, "Follows Location: to new URL: '%s'\n", data->url);
@@ -772,18 +902,24 @@ CURLcode curl_transfer(CURL *curl)
*/ */
break; break;
} }
#ifdef USE_OLD_DISCONNECT
curl_disconnect(c_connect); curl_disconnect(c_connect);
#endif
continue; continue;
} }
#ifdef USE_OLD_DISCONNECT
curl_disconnect(c_connect); curl_disconnect(c_connect);
#endif
} }
break; /* it only reaches here when this shouldn't loop */ break; /* it only reaches here when this shouldn't loop */
} while(1); /* loop if Location: */ } while(1); /* loop if Location: */
if(data->newurl) if(conn->newurl) {
free(data->newurl); free(conn->newurl);
conn->newurl = NULL;
}
return res; return res;
} }

View File

@@ -22,8 +22,9 @@
* *
* $Id$ * $Id$
*****************************************************************************/ *****************************************************************************/
CURLcode curl_transfer(CURL *curl); CURLcode Curl_perform(CURL *curl);
/* This sets up a forthcoming transfer */
CURLcode CURLcode
Curl_Transfer (struct connectdata *data, Curl_Transfer (struct connectdata *data,
int sockfd, /* socket to read from or -1 */ int sockfd, /* socket to read from or -1 */

2304
lib/url.c

File diff suppressed because it is too large Load Diff

View File

@@ -79,6 +79,8 @@
#include <curl/curl.h> #include <curl/curl.h>
#include "http_chunks.h" /* for the structs and enum stuff */
/* Download buffer size, keep it fairly big for speed reasons */ /* Download buffer size, keep it fairly big for speed reasons */
#define BUFSIZE (1024*50) #define BUFSIZE (1024*50)
@@ -96,27 +98,6 @@
#define MAX(x,y) ((x)>(y)?(x):(y)) #define MAX(x,y) ((x)>(y)?(x):(y))
#endif #endif
/* Type of handle. All publicly returned 'handles' in the curl interface
have a handle first in the struct that describes what kind of handle it
is. Used to detect bad handle usage. */
typedef enum {
STRUCT_NONE,
STRUCT_OPEN,
STRUCT_CONNECT,
STRUCT_LAST
} Handle;
/* Connecting to a remote server using the curl interface is moving through
a state machine, this type is used to store the current state */
typedef enum {
CONN_NONE, /* illegal state */
CONN_INIT, /* curl_connect() has been called */
CONN_DO, /* curl_do() has been called successfully */
CONN_DONE, /* curl_done() has been called successfully */
CONN_ERROR, /* and error has occurred */
CONN_LAST /* illegal state */
} ConnState;
#ifdef KRB4 #ifdef KRB4
/* Types needed for krb4-ftp connections */ /* Types needed for krb4-ftp connections */
struct krb4buffer { struct krb4buffer {
@@ -133,20 +114,88 @@ enum protection_level {
}; };
#endif #endif
/* struct for data related to SSL and SSL connections */
struct ssl_connect_data {
bool use; /* use ssl encrypted communications TRUE/FALSE */
#ifdef USE_SSLEAY
/* these ones requires specific SSL-types */
SSL_CTX* ctx;
SSL* handle;
X509* server_cert;
#endif /* USE_SSLEAY */
};
struct ssl_config_data {
long version; /* what version the client wants to use */
long certverifyresult; /* result from the certificate verification */
long verifypeer; /* set TRUE if this is desired */
char *CApath; /* DOES NOT WORK ON WINDOWS */
char *CAfile; /* cerficate to verify peer against */
char *random_file; /* path to file containing "random" data */
char *egdsocket; /* path to file containing the EGD daemon socket */
};
/****************************************************************************
* HTTP unique setup
***************************************************************************/
struct HTTP {
struct FormData *sendit;
int postsize;
char *p_pragma; /* Pragma: string */
char *p_accept; /* Accept: string */
long readbytecount;
long writebytecount;
/* For FORM posting */
struct Form form;
size_t (*storefread)(char *, size_t , size_t , FILE *);
FILE *in;
struct Curl_chunker chunk;
};
/****************************************************************************
* FTP unique setup
***************************************************************************/
struct FTP {
long *bytecountp;
char *user; /* user name string */
char *passwd; /* password string */
char *urlpath; /* the originally given path part of the URL */
char *dir; /* decoded directory */
char *file; /* decoded file */
char *entrypath; /* the PWD reply when we logged on */
};
/****************************************************************************
* FILE unique setup
***************************************************************************/
struct FILE {
int fd; /* open file descriptor to read from! */
};
/*
* Boolean values that concerns this connection.
*/
struct ConnectBits {
bool close; /* if set, we close the connection after this request */
bool reuse; /* if set, this is a re-used connection */
bool chunk; /* if set, this is a chunked transfer-encoding */
bool httpproxy; /* if set, this transfer is done through a http proxy */
bool user_passwd; /* do we use user+password for this connection? */
bool proxy_user_passwd; /* user+password for the proxy? */
};
/* /*
* The connectdata struct contains all fields and variables that should be * The connectdata struct contains all fields and variables that should be
* unique for an entire connection. * unique for an entire connection.
*/ */
struct connectdata { struct connectdata {
/**** Fields set when inited and not modified again */ /**** Fields set when inited and not modified again */
/* To better see what kind of struct that is passed as input, *ALL* publicly
returned handles MUST have this initial 'Handle'. */
Handle handle; /* struct identifier */
struct UrlData *data; /* link to the root CURL struct */ struct UrlData *data; /* link to the root CURL struct */
int connectindex; /* what index in the connects index this particular
/**** curl_connect() phase fields */ struct has */
ConnState state; /* for state dependent actions */
long protocol; /* PROT_* flags concerning the protocol set */ long protocol; /* PROT_* flags concerning the protocol set */
#define PROT_MISSING (1<<0) #define PROT_MISSING (1<<0)
@@ -160,23 +209,41 @@ struct connectdata {
#define PROT_FILE (1<<8) #define PROT_FILE (1<<8)
#ifdef ENABLE_IPV6 #ifdef ENABLE_IPV6
struct addrinfo *res; struct addrinfo *hp; /* host info pointer list */
struct addrinfo *ai; /* the particular host we use */
#else #else
char *hostent_buf; /* pointer to allocated memory for name info */ char *hostent_buf; /* pointer to allocated memory for name info */
struct hostent *hp; struct hostent *hp;
struct sockaddr_in serv_addr; struct sockaddr_in serv_addr;
#endif #endif
char proto[64]; /* store the protocol string in this buffer */ char protostr[64]; /* store the protocol string in this buffer */
char gname[257]; /* store the hostname in this buffer */ char gname[257]; /* store the hostname in this buffer */
char *name; /* host name pointer to fool around with */ char *name; /* host name pointer to fool around with */
char *path; /* allocated buffer to store the URL's path part in */ char *path; /* allocated buffer to store the URL's path part in */
char *hostname; /* hostname to connect, as parsed from url */
long port; /* which port to use locally */
unsigned short remote_port; /* what remote port to connect to,
not the proxy port! */
char *ppath; char *ppath;
long bytecount; long bytecount;
struct timeval now; /* current time */
char *proxyhost; /* name of the http proxy host */
struct timeval now; /* "current" time */
struct timeval created; /* creation time */
int firstsocket; /* the main socket to use */
int secondarysocket; /* for i.e ftp transfers */
long upload_bufsize; /* adjust as you see fit, never bigger than BUFSIZE long upload_bufsize; /* adjust as you see fit, never bigger than BUFSIZE
never smaller than UPLOAD_BUFSIZE */ never smaller than UPLOAD_BUFSIZE */
long maxdownload; /* in bytes, the maximum amount of data to fetch, 0
means unlimited */
struct ssl_connect_data ssl; /* this is for ssl-stuff */
struct ConnectBits bits; /* various state-flags for this connection */
/* These two functions MUST be set by the curl_connect() function to be /* These two functions MUST be set by the curl_connect() function to be
be protocol dependent */ be protocol dependent */
CURLcode (*curl_do)(struct connectdata *connect); CURLcode (*curl_do)(struct connectdata *connect);
@@ -187,6 +254,11 @@ struct connectdata {
*/ */
CURLcode (*curl_connect)(struct connectdata *connect); CURLcode (*curl_connect)(struct connectdata *connect);
/* This function *MAY* be set to a protocol-dependent function that is run
* by the curl_disconnect(), as a step in the disconnection.
*/
CURLcode (*curl_disconnect)(struct connectdata *connect);
/* This function *MAY* be set to a protocol-dependent function that is run /* This function *MAY* be set to a protocol-dependent function that is run
* in the curl_close() function if protocol-specific cleanups are required. * in the curl_close() function if protocol-specific cleanups are required.
*/ */
@@ -205,6 +277,21 @@ struct connectdata {
the same we read from. -1 disables */ the same we read from. -1 disables */
long *writebytecountp; /* return number of bytes written or NULL */ long *writebytecountp; /* return number of bytes written or NULL */
/** Dynamicly allocated strings, may need to be freed before this **/
/** struct is killed. **/
struct dynamically_allocated_data {
char *proxyuserpwd; /* free later if not NULL! */
char *uagent; /* free later if not NULL! */
char *userpwd; /* free later if not NULL! */
char *rangeline; /* free later if not NULL! */
char *ref; /* free later if not NULL! */
char *cookie; /* free later if not NULL! */
char *host; /* free later if not NULL */
} allocptr;
char *newurl; /* This can only be set if a Location: was in the
document headers */
#ifdef KRB4 #ifdef KRB4
enum protection_level command_prot; enum protection_level command_prot;
@@ -218,6 +305,24 @@ struct connectdata {
void *app_data; void *app_data;
#endif #endif
/*************** Request - specific items ************/
/* previously this was in the urldata struct */
union {
struct HTTP *http;
struct HTTP *gopher; /* alias, just for the sake of being more readable */
struct HTTP *https; /* alias, just for the sake of being more readable */
struct FTP *ftp;
struct FILE *file;
void *telnet; /* private for telnet.c-eyes only */
#if 0 /* no need for special ones for these: */
struct LDAP *ldap;
struct DICT *dict;
#endif
void *generic;
} proto;
}; };
struct Progress { struct Progress {
@@ -244,6 +349,7 @@ struct Progress {
double t_connect; double t_connect;
double t_pretransfer; double t_pretransfer;
int httpcode; int httpcode;
int httpversion;
time_t filetime; /* If requested, this is might get set. It may be 0 if time_t filetime; /* If requested, this is might get set. It may be 0 if
the time was unretrievable */ the time was unretrievable */
@@ -253,35 +359,6 @@ struct Progress {
int speeder_c; int speeder_c;
}; };
/****************************************************************************
* HTTP unique setup
***************************************************************************/
struct HTTP {
struct FormData *sendit;
int postsize;
char *p_pragma; /* Pragma: string */
char *p_accept; /* Accept: string */
long readbytecount;
long writebytecount;
/* For FORM posting */
struct Form form;
size_t (*storefread)(char *, size_t , size_t , FILE *);
FILE *in;
};
/****************************************************************************
* FTP unique setup
***************************************************************************/
struct FTP {
long *bytecountp;
char *user; /* user name string */
char *passwd; /* password string */
char *urlpath; /* the originally given path part of the URL */
char *dir; /* decoded directory */
char *file; /* decoded file */
};
typedef enum { typedef enum {
HTTPREQ_NONE, /* first in list */ HTTPREQ_NONE, /* first in list */
HTTPREQ_GET, HTTPREQ_GET,
@@ -316,42 +393,20 @@ struct Configbits {
bool httpproxy; bool httpproxy;
bool mute; bool mute;
bool no_body; bool no_body;
bool proxy_user_passwd;
bool set_port; bool set_port;
bool set_range; bool set_range;
bool upload; bool upload;
bool use_netrc; bool use_netrc;
bool user_passwd;
bool verbose; bool verbose;
bool this_is_a_follow; /* this is a followed Location: request */ bool this_is_a_follow; /* this is a followed Location: request */
bool krb4; /* kerberos4 connection requested */ bool krb4; /* kerberos4 connection requested */
bool proxystringalloc; /* the http proxy string is malloc()'ed */ bool proxystringalloc; /* the http proxy string is malloc()'ed */
bool rangestringalloc; /* the range string is malloc()'ed */ bool rangestringalloc; /* the range string is malloc()'ed */
bool urlstringalloc; /* the URL string is malloc()'ed */ bool urlstringalloc; /* the URL string is malloc()'ed */
}; bool reuse_forbid; /* if this is forbidden to be reused, close
after use */
/* What type of interface that intiated this struct */ bool reuse_fresh; /* do not re-use an existing connection for this
typedef enum { transfer */
CURLI_NONE,
CURLI_EASY,
CURLI_NORMAL,
CURLI_LAST
} CurlInterface;
/* struct for data related to SSL and SSL connections */
struct ssldata {
bool use; /* use ssl encrypted communications TRUE/FALSE */
long version; /* what version the client wants to use */
long certverifyresult; /* result from the certificate verification */
long verifypeer; /* set TRUE if this is desired */
char *CApath; /* DOES NOT WORK ON WINDOWS */
char *CAfile; /* cerficate to verify peer against */
#ifdef USE_SSLEAY
/* these ones requires specific SSL-types */
SSL_CTX* ctx;
SSL* handle;
X509* server_cert;
#endif /* USE_SSLEAY */
}; };
/* /*
@@ -368,20 +423,24 @@ struct ssldata {
* *
* (Request) * (Request)
* 3 - Request-specific. Variables that are of interest for this particular * 3 - Request-specific. Variables that are of interest for this particular
* transfer being made right now. * transfer being made right now. THIS IS WRONG STRUCT FOR THOSE.
* *
* In Febrary 2001, this is being done stricter. The 'connectdata' struct
* MUST have all the connection oriented stuff as we may now have several
* simultaneous connections and connection structs in memory.
*
* From now on, the 'UrlData' must only contain data that is set once to go
* for many (perhaps) independent connections. Values that are generated or
* calculated internally MUST NOT be a part of this struct.
*/ */
struct UrlData { struct UrlData {
Handle handle; /* struct identifier */
CurlInterface interf; /* created by WHAT interface? */
/*************** Global - specific items ************/ /*************** Global - specific items ************/
FILE *err; /* the stderr writes goes here */ FILE *err; /* the stderr writes goes here */
char *errorbuffer; /* store failure messages in here */ char *errorbuffer; /* store failure messages in here */
/*************** Session - specific items ************/ /*************** Session - specific items ************/
char *proxy; /* if proxy, set it here, set CONF_PROXY to use this */ char *proxy; /* if proxy, set it here */
char *proxyuserpwd; /* Proxy <user:password>, if used */ char *proxyuserpwd; /* Proxy <user:password>, if used */
long proxyport; /* If non-zero, use this port number by default. If the long proxyport; /* If non-zero, use this port number by default. If the
proxy string features a ":[port]" that one will override proxy string features a ":[port]" that one will override
@@ -391,33 +450,14 @@ struct UrlData {
long header_size; /* size of read header(s) in bytes */ long header_size; /* size of read header(s) in bytes */
long request_size; /* the amount of bytes sent in the request(s) */ long request_size; /* the amount of bytes sent in the request(s) */
/*************** Request - specific items ************/
union {
struct HTTP *http;
struct HTTP *gopher; /* alias, just for the sake of being more readable */
struct HTTP *https; /* alias, just for the sake of being more readable */
struct FTP *ftp;
#if 0 /* no need for special ones for these: */
struct TELNET *telnet;
struct FILE *file;
struct LDAP *ldap;
struct DICT *dict;
#endif
void *generic;
} proto;
FILE *out; /* the fetched file goes here */ FILE *out; /* the fetched file goes here */
FILE *in; /* the uploaded file is read from here */ FILE *in; /* the uploaded file is read from here */
FILE *writeheader; /* write the header to this is non-NULL */ FILE *writeheader; /* write the header to this is non-NULL */
char *url; /* what to get */ char *url; /* what to get */
char *freethis; /* if non-NULL, an allocated string for the URL */ char *freethis; /* if non-NULL, an allocated string for the URL */
char *hostname; /* hostname to connect, as parsed from url */ long use_port; /* which port to use (when not using default) */
long port; /* which port to use (if non-protocol bind) set
CONF_PORT to use this */
unsigned short remote_port; /* what remote port to connect to, not the proxy
port! */
struct Configbits bits; /* new-style (v7) flag data */ struct Configbits bits; /* new-style (v7) flag data */
struct ssl_config_data ssl; /* this is for ssl-stuff */
char *userpwd; /* <user:password>, if used */ char *userpwd; /* <user:password>, if used */
char *range; /* range, if used. See README for detailed specification on char *range; /* range, if used. See README for detailed specification on
@@ -456,15 +496,9 @@ struct UrlData {
curl_passwd_callback fpasswd; curl_passwd_callback fpasswd;
void *passwd_client; /* pointer to pass to the passwd callback */ void *passwd_client; /* pointer to pass to the passwd callback */
long timeout; /* in seconds, 0 means no timeout */ long timeout; /* in seconds, 0 means no timeout */
long infilesize; /* size of file to upload, -1 means unknown */ long connecttimeout; /* in seconds, 0 means no timeout */
long infilesize; /* size of file to upload, -1 means unknown */
long maxdownload; /* in bytes, the maximum amount of data to fetch, 0
means unlimited */
/* fields only set and used within _urlget() */
int firstsocket; /* the main socket to use */
int secondarysocket; /* for i.e ftp transfers */
char buffer[BUFSIZE+1]; /* buffer with size BUFSIZE */ char buffer[BUFSIZE+1]; /* buffer with size BUFSIZE */
@@ -477,9 +511,6 @@ struct UrlData {
char *cookie; /* HTTP cookie string to send */ char *cookie; /* HTTP cookie string to send */
char *newurl; /* This can only be set if a Location: was in the
document headers */
struct curl_slist *headers; /* linked list of extra headers */ struct curl_slist *headers; /* linked list of extra headers */
struct HttpPost *httppost; /* linked list of POST data */ struct HttpPost *httppost; /* linked list of POST data */
@@ -488,12 +519,13 @@ struct UrlData {
struct CookieInfo *cookies; struct CookieInfo *cookies;
struct ssldata ssl; /* this is for ssl-stuff */
long crlf; long crlf;
struct curl_slist *quote; /* before the transfer */ struct curl_slist *quote; /* before the transfer */
struct curl_slist *postquote; /* after the transfer */ struct curl_slist *postquote; /* after the transfer */
/* Telnet negotiation options */
struct curl_slist *telnet_options; /* linked list of telnet options */
TimeCond timecondition; /* kind of comparison */ TimeCond timecondition; /* kind of comparison */
time_t timevalue; /* what time to compare with */ time_t timevalue; /* what time to compare with */
@@ -504,12 +536,6 @@ struct UrlData {
char *headerbuff; /* allocated buffer to store headers in */ char *headerbuff; /* allocated buffer to store headers in */
int headersize; /* size of the allocation */ int headersize; /* size of the allocation */
#if 0
/* this was removed in libcurl 7.4 */
char *writeinfo; /* if non-NULL describes what to output on a successful
completion */
#endif
struct Progress progress; /* for all the progress meter data */ struct Progress progress; /* for all the progress meter data */
#define MAX_CURL_USER_LENGTH 128 #define MAX_CURL_USER_LENGTH 128
@@ -526,25 +552,44 @@ struct UrlData {
char proxyuser[MAX_CURL_USER_LENGTH]; char proxyuser[MAX_CURL_USER_LENGTH];
char proxypasswd[MAX_CURL_PASSWORD_LENGTH]; char proxypasswd[MAX_CURL_PASSWORD_LENGTH];
/**** Dynamicly allocated strings, may need to be freed on return ****/
char *ptr_proxyuserpwd; /* free later if not NULL! */
char *ptr_uagent; /* free later if not NULL! */
char *ptr_userpwd; /* free later if not NULL! */
char *ptr_rangeline; /* free later if not NULL! */
char *ptr_ref; /* free later if not NULL! */
char *ptr_cookie; /* free later if not NULL! */
char *ptr_host; /* free later if not NULL */
char *krb4_level; /* what security level */ char *krb4_level; /* what security level */
#ifdef KRB4 #ifdef KRB4
FILE *cmdchannel; FILE *cmdchannel;
#endif #endif
struct timeval keeps_speed; /* this should be request-specific */ struct timeval keeps_speed; /* this should be request-specific */
/* 'connects' will be an allocated array with pointers. If the pointer is
set, it holds an allocated connection. */
struct connectdata **connects;
size_t numconnects; /* size of the 'connects' array */
curl_closepolicy closepolicy;
}; };
#define LIBCURL_NAME "libcurl" #define LIBCURL_NAME "libcurl"
#define LIBCURL_ID LIBCURL_NAME " " LIBCURL_VERSION " " SSL_ID #define LIBCURL_ID LIBCURL_NAME " " LIBCURL_VERSION " " SSL_ID
CURLcode Curl_getinfo(CURL *curl, CURLINFO info, ...);
/*
* Here follows function prototypes from what we used to plan to call
* the "low level" interface. It is no longer prioritized and it is not likely
* to ever be supported to external users.
*
* I removed all the comments to them as well, as they were no longer accurate
* and they're not meant for "public use" anymore.
*/
CURLcode Curl_open(CURL **curl, char *url);
CURLcode Curl_setopt(CURL *handle, CURLoption option, ...);
CURLcode Curl_close(CURL *curl); /* the opposite of curl_open() */
CURLcode Curl_connect(struct UrlData *,
struct connectdata **,
bool allow_port);
CURLcode Curl_do(struct connectdata *);
CURLcode Curl_done(struct connectdata *);
CURLcode Curl_disconnect(struct connectdata *);
#endif #endif

View File

@@ -11,7 +11,7 @@ libversion="$version"
# Now we have a section to get the major, minor and patch number from the # Now we have a section to get the major, minor and patch number from the
# full version string. We create a single hexadecimal number from it '0xMMmmpp' # full version string. We create a single hexadecimal number from it '0xMMmmpp'
# #
perl='$a=<STDIN>;@p=split("\\.",$a);for(0..2){printf STDOUT ("%02x",$p[0+$_]);}'; perl='$a=<STDIN>;@p=split("[\\.-]",$a);for(0..2){printf STDOUT ("%02x",$p[0+$_]);}';
numeric=`echo $libversion | perl -e "$perl"` numeric=`echo $libversion | perl -e "$perl"`

View File

@@ -145,7 +145,7 @@ if($totalmem) {
for(keys %sizeataddr) { for(keys %sizeataddr) {
$addr = $_; $addr = $_;
$size = $sizeataddr{$addr}; $size = $sizeataddr{$addr};
if($size) { if($size > 0) {
print "At $addr, there's $size bytes.\n"; print "At $addr, there's $size bytes.\n";
print " allocated by ".$getmem{$addr}."\n"; print " allocated by ".$getmem{$addr}."\n";
} }

View File

@@ -1 +1,3 @@
SUBDIRS = Win32 Linux SUBDIRS = Win32 Linux
EXTRA_DIST = README

35
perl/Curl_easy/Changes Normal file
View File

@@ -0,0 +1,35 @@
Revision history for Perl extension Curl::easy.
Check out the file README for more info.
1.0.2 Tue Oct 10 2000:
- runs with libcurl 7.4
- modified curl_easy_getinfo(). It now calls curl_getinfo() that has
been added to libcurl in version 7.4.
1.0.1 Tue Oct 10 2000:
- Added some missing features of curl_easy_setopt():
- CURLOPT_ERRORBUFFER now works by passing the name of a perl
variable that shall be crated and the errormessage (if any)
be stored to.
- Passing filehandles (Options FILE, INFILE and WRITEHEADER) now works.
Have a look at test.pl to see how it works...
- Added a new function, curl_easy_getinfo(), that for now always
returns the number of bytes that where written to disk during the last
download. If the curl_easy_getinfo() function is included in libcurl,
(as promised by Daniel ;-)) i will turn this into just a call to this
function.
1.0 Thu Oct 5 2000:
- first released version
- runs with libcurl 7.3
- some features of curl_easy_setopt() are still missing:
- passing function pointers doesn't work (options WRITEFUNCTION,
READFUNCTION and PROGRESSFUNCTION).
- passing FILE * pointers doesn't work (options FILE, INFILE and
WRITEHEADER).
- passing linked lists doesn't work (options HTTPHEADER and
HTTPPOST).
- setting the buffer where to store error messages in doesn't work
(option ERRORBUFFER).

6
perl/Curl_easy/MANIFEST Normal file
View File

@@ -0,0 +1,6 @@
Changes
MANIFEST
Makefile.PL
easy.pm
easy.xs
test.pl

View File

@@ -0,0 +1,14 @@
# Makefile.PL for Perl extension Curl::easy.
# Check out the file README for more info.
use ExtUtils::MakeMaker;
# See lib/ExtUtils/MakeMaker.pm for details of how to influence
# the contents of the Makefile that is written.
WriteMakefile(
'NAME' => 'Curl::easy',
'VERSION_FROM' => 'easy.pm', # finds $VERSION
'LIBS' => ['-lcurl '], # e.g., '-lm'
'DEFINE' => '', # e.g., '-DHAVE_SOMETHING'
'INC' => '', # e.g., '-I/usr/include/other'
'clean' => {FILES => "head.out body.out"}
);

View File

@@ -0,0 +1 @@
EXTRA_DIST = Changes easy.pm easy.xs Makefile.PL MANIFEST README test.pl

27
perl/Curl_easy/README Normal file
View File

@@ -0,0 +1,27 @@
README for Perl extension Curl::easy.
The perl module Curl::easy provides an interface to the cURL library "libcurl".
See http://curl.haxx.se/ for more information on cURL and libcurl.
This module requires libcurl and the corresponding headerfiles to be
installed. You then may install this module via the usual way:
perl Makefile.PL
make
make test
make install
The module provides the same functionality as libcurl provides to C programs,
please refer to the documentation of libcurl.
A short example how to use the module may be found in test.pl.
This Software is distributed AS IS, WITHOUT WARRANTY OF ANY KIND,
either express or implied. Send praise, patches, money, beer and
pizza to the author. Send complaints to /dev/null. ;-)
The author of this module is Georg Horn <horn@koblenz-net.de>
The latest version of this module can be dowloaded from
http://koblenz-net.de/~horn/export/

139
perl/Curl_easy/easy.pm Normal file
View File

@@ -0,0 +1,139 @@
# Perl interface for libcurl. Check out the file README for more info.
package Curl::easy;
use strict;
use Carp;
use vars qw($VERSION @ISA @EXPORT @EXPORT_OK $AUTOLOAD);
require Exporter;
require DynaLoader;
require AutoLoader;
@ISA = qw(Exporter DynaLoader);
# Items to export into callers namespace by default. Note: do not export
# names by default without a very good reason. Use EXPORT_OK instead.
# Do not simply export all your public functions/methods/constants.
@EXPORT = qw(
CURLOPT_AUTOREFERER
CURLOPT_COOKIE
CURLOPT_COOKIEFILE
CURLOPT_CRLF
CURLOPT_CUSTOMREQUEST
CURLOPT_ERRORBUFFER
CURLOPT_FAILONERROR
CURLOPT_FILE
CURLOPT_FOLLOWLOCATION
CURLOPT_FTPAPPEND
CURLOPT_FTPASCII
CURLOPT_FTPLISTONLY
CURLOPT_FTPPORT
CURLOPT_HEADER
CURLOPT_HTTPHEADER
CURLOPT_HTTPPOST
CURLOPT_HTTPPROXYTUNNEL
CURLOPT_HTTPREQUEST
CURLOPT_INFILE
CURLOPT_INFILESIZE
CURLOPT_INTERFACE
CURLOPT_KRB4LEVEL
CURLOPT_LOW_SPEED_LIMIT
CURLOPT_LOW_SPEED_TIME
CURLOPT_MUTE
CURLOPT_NETRC
CURLOPT_NOBODY
CURLOPT_NOPROGRESS
CURLOPT_NOTHING
CURLOPT_PORT
CURLOPT_POST
CURLOPT_POSTFIELDS
CURLOPT_POSTFIELDSIZE
CURLOPT_POSTQUOTE
CURLOPT_PROGRESSDATA
CURLOPT_PROGRESSFUNCTION
CURLOPT_PROXY
CURLOPT_PROXYPORT
CURLOPT_PROXYUSERPWD
CURLOPT_PUT
CURLOPT_QUOTE
CURLOPT_RANGE
CURLOPT_READFUNCTION
CURLOPT_REFERER
CURLOPT_RESUME_FROM
CURLOPT_SSLCERT
CURLOPT_SSLCERTPASSWD
CURLOPT_SSLVERSION
CURLOPT_STDERR
CURLOPT_TIMECONDITION
CURLOPT_TIMEOUT
CURLOPT_TIMEVALUE
CURLOPT_TRANSFERTEXT
CURLOPT_UPLOAD
CURLOPT_URL
CURLOPT_USERAGENT
CURLOPT_USERPWD
CURLOPT_VERBOSE
CURLOPT_WRITEFUNCTION
CURLOPT_WRITEHEADER
CURLINFO_EFFECTIVE_URL
CURLINFO_HTTP_CODE
CURLINFO_TOTAL_TIME
CURLINFO_NAMELOOKUP_TIME
CURLINFO_CONNECT_TIME
CURLINFO_PRETRANSFER_TIME
CURLINFO_SIZE_UPLOAD
CURLINFO_SIZE_DOWNLOAD
CURLINFO_SPEED_DOWNLOAD
CURLINFO_SPEED_UPLOAD
CURLINFO_HEADER_SIZE
CURLINFO_REQUEST_SIZE
);
$VERSION = '1.0.1';
sub AUTOLOAD {
# This AUTOLOAD is used to 'autoload' constants from the constant()
# XS function.
(my $constname = $AUTOLOAD) =~ s/.*:://;
return constant($constname, 0);
}
bootstrap Curl::easy $VERSION;
# Preloaded methods go here.
# Autoload methods go after =cut, and are processed by the autosplit program.
1;
__END__
# Below is the stub of documentation for your module. You better edit it!
=head1 NAME
Curl::easy - Perl extension for libcurl
=head1 SYNOPSIS
use Curl::easy;
$CURL = curl_easy_init();
$CURLcode = curl_easy_setopt($CURL, CURLoption, Value);
$CURLcode = curl_easy_perform($CURL);
curl_easy_cleanup($CURL);
=head1 DESCRIPTION
This perl module provides an interface to the libcurl C library. See
http://curl.haxx.se/ for more information on cURL and libcurl.
=head1 AUTHOR
Georg Horn <horn@koblenz-net.de>
=head1 SEE ALSO
http://curl.haxx.se/
=cut

290
perl/Curl_easy/easy.xs Normal file
View File

@@ -0,0 +1,290 @@
/* Perl interface for libcurl. Check out the file README for more info. */
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#include <curl/curl.h>
#include <curl/easy.h>
/* Buffer and varname for option CURLOPT_ERRORBUFFER */
static char errbuf[CURL_ERROR_SIZE];
static char *errbufvarname = NULL;
static int
constant(char *name, int arg)
{
errno = 0;
if (strncmp(name, "CURLINFO_", 9) == 0) {
name += 9;
switch (*name) {
case 'A':
case 'B':
case 'C':
case 'D':
if (strEQ(name, "CONNECT_TIME")) return CURLINFO_CONNECT_TIME;
break;
case 'E':
case 'F':
if (strEQ(name, "EFFECTIVE_URL")) return CURLINFO_EFFECTIVE_URL;
break;
case 'G':
case 'H':
if (strEQ(name, "HEADER_SIZE")) return CURLINFO_HEADER_SIZE;
if (strEQ(name, "HTTP_CODE")) return CURLINFO_HTTP_CODE;
break;
case 'I':
case 'J':
case 'K':
case 'L':
case 'M':
case 'N':
if (strEQ(name, "NAMELOOKUP_TIME")) return CURLINFO_NAMELOOKUP_TIME;
break;
case 'O':
case 'P':
if (strEQ(name, "PRETRANSFER_TIME")) return CURLINFO_PRETRANSFER_TIME;
break;
case 'Q':
case 'R':
if (strEQ(name, "REQUEST_SIZE")) return CURLINFO_REQUEST_SIZE;
break;
case 'S':
case 'T':
if (strEQ(name, "SIZE_DOWNLOAD")) return CURLINFO_SIZE_DOWNLOAD;
if (strEQ(name, "SIZE_UPLOAD")) return CURLINFO_SIZE_UPLOAD;
if (strEQ(name, "SPEED_DOWNLOAD")) return CURLINFO_SPEED_DOWNLOAD;
if (strEQ(name, "SPEED_UPLOAD")) return CURLINFO_SPEED_UPLOAD;
if (strEQ(name, "TOTAL_TIME")) return CURLINFO_TOTAL_TIME;
break;
case 'U':
case 'V':
case 'W':
case 'X':
case 'Y':
case 'Z':
break;
}
}
if (strncmp(name, "CURLOPT_", 8) == 0) {
name += 8;
switch (*name) {
case 'A':
case 'B':
if (strEQ(name, "AUTOREFERER")) return CURLOPT_AUTOREFERER;
break;
case 'C':
case 'D':
if (strEQ(name, "COOKIE")) return CURLOPT_COOKIE;
if (strEQ(name, "COOKIEFILE")) return CURLOPT_COOKIEFILE;
if (strEQ(name, "CRLF")) return CURLOPT_CRLF;
if (strEQ(name, "CUSTOMREQUEST")) return CURLOPT_CUSTOMREQUEST;
break;
case 'E':
case 'F':
if (strEQ(name, "ERRORBUFFER")) return CURLOPT_ERRORBUFFER;
if (strEQ(name, "FAILONERROR")) return CURLOPT_FAILONERROR;
if (strEQ(name, "FILE")) return CURLOPT_FILE;
if (strEQ(name, "FOLLOWLOCATION")) return CURLOPT_FOLLOWLOCATION;
if (strEQ(name, "FTPAPPEND")) return CURLOPT_FTPAPPEND;
if (strEQ(name, "FTPASCII")) return CURLOPT_FTPASCII;
if (strEQ(name, "FTPLISTONLY")) return CURLOPT_FTPLISTONLY;
if (strEQ(name, "FTPPORT")) return CURLOPT_FTPPORT;
break;
case 'G':
case 'H':
if (strEQ(name, "HEADER")) return CURLOPT_HEADER;
if (strEQ(name, "HTTPHEADER")) return CURLOPT_HTTPHEADER;
if (strEQ(name, "HTTPPOST")) return CURLOPT_HTTPPOST;
if (strEQ(name, "HTTPPROXYTUNNEL")) return CURLOPT_HTTPPROXYTUNNEL;
if (strEQ(name, "HTTPREQUEST")) return CURLOPT_HTTPREQUEST;
break;
case 'I':
case 'J':
if (strEQ(name, "INFILE")) return CURLOPT_INFILE;
if (strEQ(name, "INFILESIZE")) return CURLOPT_INFILESIZE;
if (strEQ(name, "INTERFACE")) return CURLOPT_INTERFACE;
break;
case 'K':
case 'L':
if (strEQ(name, "KRB4LEVEL")) return CURLOPT_KRB4LEVEL;
if (strEQ(name, "LOW_SPEED_LIMIT")) return CURLOPT_LOW_SPEED_LIMIT;
if (strEQ(name, "LOW_SPEED_TIME")) return CURLOPT_LOW_SPEED_TIME;
break;
case 'M':
case 'N':
if (strEQ(name, "MUTE")) return CURLOPT_MUTE;
if (strEQ(name, "NETRC")) return CURLOPT_NETRC;
if (strEQ(name, "NOBODY")) return CURLOPT_NOBODY;
if (strEQ(name, "NOPROGRESS")) return CURLOPT_NOPROGRESS;
if (strEQ(name, "NOTHING")) return CURLOPT_NOTHING;
break;
case 'O':
case 'P':
if (strEQ(name, "PORT")) return CURLOPT_PORT;
if (strEQ(name, "POST")) return CURLOPT_POST;
if (strEQ(name, "POSTFIELDS")) return CURLOPT_POSTFIELDS;
if (strEQ(name, "POSTFIELDSIZE")) return CURLOPT_POSTFIELDSIZE;
if (strEQ(name, "POSTQUOTE")) return CURLOPT_POSTQUOTE;
if (strEQ(name, "PROGRESSDATA")) return CURLOPT_PROGRESSDATA;
if (strEQ(name, "PROGRESSFUNCTION")) return CURLOPT_PROGRESSFUNCTION;
if (strEQ(name, "PROXY")) return CURLOPT_PROXY;
if (strEQ(name, "PROXYPORT")) return CURLOPT_PROXYPORT;
if (strEQ(name, "PROXYUSERPWD")) return CURLOPT_PROXYUSERPWD;
if (strEQ(name, "PUT")) return CURLOPT_PUT;
break;
case 'Q':
case 'R':
if (strEQ(name, "QUOTE")) return CURLOPT_QUOTE;
if (strEQ(name, "RANGE")) return CURLOPT_RANGE;
if (strEQ(name, "READFUNCTION")) return CURLOPT_READFUNCTION;
if (strEQ(name, "REFERER")) return CURLOPT_REFERER;
if (strEQ(name, "RESUME_FROM")) return CURLOPT_RESUME_FROM;
break;
case 'S':
case 'T':
if (strEQ(name, "SSLCERT")) return CURLOPT_SSLCERT;
if (strEQ(name, "SSLCERTPASSWD")) return CURLOPT_SSLCERTPASSWD;
if (strEQ(name, "SSLVERSION")) return CURLOPT_SSLVERSION;
if (strEQ(name, "STDERR")) return CURLOPT_STDERR;
if (strEQ(name, "TIMECONDITION")) return CURLOPT_TIMECONDITION;
if (strEQ(name, "TIMEOUT")) return CURLOPT_TIMEOUT;
if (strEQ(name, "TIMEVALUE")) return CURLOPT_TIMEVALUE;
if (strEQ(name, "TRANSFERTEXT")) return CURLOPT_TRANSFERTEXT;
break;
case 'U':
case 'V':
if (strEQ(name, "UPLOAD")) return CURLOPT_UPLOAD;
if (strEQ(name, "URL")) return CURLOPT_URL;
if (strEQ(name, "USERAGENT")) return CURLOPT_USERAGENT;
if (strEQ(name, "USERPWD")) return CURLOPT_USERPWD;
if (strEQ(name, "VERBOSE")) return CURLOPT_VERBOSE;
break;
case 'W':
case 'X':
case 'Y':
case 'Z':
if (strEQ(name, "WRITEFUNCTION")) return CURLOPT_WRITEFUNCTION;
if (strEQ(name, "WRITEHEADER")) return CURLOPT_WRITEHEADER;
if (strEQ(name, "WRITEINFO")) return CURLOPT_WRITEINFO;
break;
}
}
errno = EINVAL;
return 0;
}
MODULE = Curl::easy PACKAGE = Curl::easy
int
constant(name,arg)
char * name
int arg
void *
curl_easy_init()
CODE:
if (errbufvarname) free(errbufvarname);
errbufvarname = NULL;
RETVAL = curl_easy_init();
OUTPUT:
RETVAL
int
curl_easy_setopt(curl, option, value)
void * curl
int option
char * value
CODE:
if (option < CURLOPTTYPE_OBJECTPOINT) {
/* This is an option specifying an integer value: */
long value = (long)SvIV(ST(2));
RETVAL = curl_setopt(curl, option, value);
} else if (option == CURLOPT_FILE || option == CURLOPT_INFILE ||
option == CURLOPT_WRITEHEADER) {
/* This is an option specifying a FILE * value: */
FILE * value = IoIFP(sv_2io(ST(2)));
RETVAL = curl_setopt(curl, option, value);
} else if (option == CURLOPT_ERRORBUFFER) {
SV *sv;
RETVAL = curl_setopt(curl, option, errbuf);
if (errbufvarname) free(errbufvarname);
errbufvarname = strdup(value);
sv = perl_get_sv(errbufvarname, TRUE | GV_ADDMULTI);
} else if (option == CURLOPT_WRITEFUNCTION || option ==
CURLOPT_READFUNCTION || option == CURLOPT_PROGRESSFUNCTION) {
/* This is an option specifying a callback function */
/* not yet implemented */
RETVAL = -1;
} else {
/* default, option specifying a char * value: */
RETVAL = curl_setopt(curl, option, value);
}
OUTPUT:
RETVAL
int
curl_easy_perform(curl)
void * curl
CODE:
RETVAL = curl_easy_perform(curl);
if (RETVAL && errbufvarname) {
SV *sv = perl_get_sv(errbufvarname, TRUE | GV_ADDMULTI);
sv_setpv(sv, errbuf);
}
OUTPUT:
RETVAL
int
curl_easy_getinfo(curl, option, value)
void * curl
int option
double value
CODE:
switch (option & CURLINFO_TYPEMASK) {
case CURLINFO_STRING: {
char * value = (char *)SvPV(ST(2), PL_na);
RETVAL = curl_getinfo(curl, option, &value);
sv_setpv(ST(2), value);
break;
}
case CURLINFO_LONG: {
long value = (long)SvIV(ST(2));
RETVAL = curl_getinfo(curl, option, &value);
sv_setiv(ST(2), value);
break;
}
case CURLINFO_DOUBLE: {
double value = (double)SvNV(ST(2));
RETVAL = curl_getinfo(curl, option, &value);
sv_setnv(ST(2), value);
break;
}
default: {
RETVAL = CURLE_BAD_FUNCTION_ARGUMENT;
break;
}
}
OUTPUT:
RETVAL
int
curl_easy_cleanup(curl)
void * curl
CODE:
curl_easy_cleanup(curl);
if (errbufvarname) free(errbufvarname);
errbufvarname = NULL;
RETVAL = 0;
OUTPUT:
RETVAL

101
perl/Curl_easy/test.pl Normal file
View File

@@ -0,0 +1,101 @@
# Test script for Perl extension Curl::easy.
# Check out the file README for more info.
# Before `make install' is performed this script should be runnable with
# `make test'. After `make install' it should work as `perl test.pl'
######################### We start with some black magic to print on failure.
# Change 1..1 below to 1..last_test_to_print .
# (It may become useful if the test is moved to ./t subdirectory.)
BEGIN { $| = 1; print "1..5\n"; }
END {print "not ok 1\n" unless $loaded;}
use Curl::easy;
$loaded = 1;
print "ok 1\n";
######################### End of black magic.
# Insert your test code below (better if it prints "ok 13"
# (correspondingly "not ok 13") depending on the success of chunk 13
# of the test code):
# Read URL to get
$defurl = "http://www/";
$url = "";
print "Please enter an URL to fetch [$defurl]: ";
$url = <STDIN>;
if ($url =~ /^\s*\n/) {
$url = $defurl;
}
# Use this for simple benchmarking
#for ($i=0; $i<1000; $i++) {
# Init the curl session
if (($curl = Curl::easy::curl_easy_init()) != 0) {
print "ok 2\n";
} else {
print "ko 2\n";
}
# Set URL to get
if (Curl::easy::curl_easy_setopt($curl, Curl::easy::CURLOPT_URL, $url) == 0) {
print "ok 3\n";
} else {
print "ko 3\n";
}
# No progress meter please
Curl::easy::curl_easy_setopt($curl, Curl::easy::CURLOPT_NOPROGRESS, 1);
# Shut up completely
Curl::easy::curl_easy_setopt($curl, Curl::easy::CURLOPT_MUTE, 1);
# Follow location headers
Curl::easy::curl_easy_setopt($curl, Curl::easy::CURLOPT_FOLLOWLOCATION, 1);
# Set timeout
Curl::easy::curl_easy_setopt($curl, Curl::easy::CURLOPT_TIMEOUT, 30);
# Set file where to read cookies from
Curl::easy::curl_easy_setopt($curl, Curl::easy::CURLOPT_COOKIEFILE, "cookies");
# Set file where to store the header
open HEAD, ">head.out";
Curl::easy::curl_easy_setopt($curl, Curl::easy::CURLOPT_WRITEHEADER, HEAD);
# Set file where to store the body
open BODY, ">body.out";
Curl::easy::curl_easy_setopt($curl, Curl::easy::CURLOPT_FILE, BODY);
# Store error messages in variable $errbuf
# NOTE: The name of the variable is passed as a string!
# curl_easy_setopt() creates a perl variable with that name, and
# curl_easy_perform() stores the errormessage into it if an error occurs.
Curl::easy::curl_easy_setopt($curl, Curl::easy::CURLOPT_ERRORBUFFER, "errbuf");
# Go get it
if (Curl::easy::curl_easy_perform($curl) == 0) {
Curl::easy::curl_easy_getinfo($curl, Curl::easy::CURLINFO_SIZE_DOWNLOAD, $bytes);
print "ok 4: $bytes bytes read\n";
print "check out the files head.out and body.out\n";
print "for the headers and content of the URL you just fetched...\n";
Curl::easy::curl_easy_getinfo($curl, Curl::easy::CURLINFO_EFFECTIVE_URL, $realurl);
Curl::easy::curl_easy_getinfo($curl, Curl::easy::CURLINFO_HTTP_CODE, $httpcode);
print "effective fetched url (http code: $httpcode) was: $url\n";
} else {
# We can acces the error message in $errbuf here
print "ko 4: '$errbuf'\n";
}
# Cleanup
close HEAD;
close BODY;
Curl::easy::curl_easy_cleanup($curl);
print "ok 5\n";
# Use this for simple benchmarking
#}

3
perl/Makefile.am Normal file
View File

@@ -0,0 +1,3 @@
SUBDIRS = Curl_easy
EXTRA_DIST = README

View File

@@ -1,33 +1,17 @@
This is just a small collection of perl scripts that use curl to do _ _ ____ _
their jobs. ___| | | | _ \| |
/ __| | | | |_) | |
| (__| |_| | _ <| |___
\___|\___/|_| \_\_____|
If you need a proxy configuration in order to get HTTP or FTP Perl
documents, do edit your .curlrc file in your HOME dir to contain:
-x <proxy host>:<proxy port>
These scripts are all written by Daniel Stenberg. Perl's a great script language, not the least for quick prototyping. Curl is
elegantly used from within it. You can either invoke external curl command
line or use the curl interface.
checklinks.pl Georg Horn's Perl interface to curl is available in the Curl_easy/
============= subdirectory.
This script fetches an HTML page, extracts all links and references to
other documents and then goes through them to check that they work.
Reports progress in a format intended for machine-parsing.
getlinks.pl Unfortunately, we don't have any examples nor any documentation for it at
=========== this point.
You ever wanted to download a bunch of programs a certain HTML page has
links to? This program extracts all links and references from a web page
and then compares them to the regex you supply. All matches will be
downloaded in the target directory of your choice.
recursiveftpget.pl
==================
This script recursively downloads all files from a directory on an ftp site
and all subdirectories it has. Optional depth-level.
formfind.pl
===========
Downloads an HTML page (or reads stdin) and reports a human readable report
about the FORM(s) present. What method, what URL, which input or select
field, what default values they have and what submit buttons there are. It
is useful if you intend to use curl to properly fake a form submission.

View File

0
perl/getlinks.pl.in → perl/contrib/getlinks.pl.in Executable file → Normal file
View File

104
perl/contrib/mirror.pl Normal file
View File

@@ -0,0 +1,104 @@
#!/usr/bin/perl
#
# Author: Daniel Stenberg <daniel@haxx.se>
# Version: 0.1
# Date: October 10, 2000
#
# This is public domain. Feel free to do whatever you please with this script.
# There are no warranties whatsoever! It might work, it might ruin your hard
# disk. Use this on your own risk.
#
# PURPOSE
#
# This script uses a local directory to maintain a "mirror" of the curl
# packages listed in the remote curl web sites package list. Files present in
# the local directory that aren't present in the remote list will be removed.
# Files that are present in the remote list but not in the local directory
# will be downloaded and put there. Files present at both places will not
# be touched.
#
# WARNING: don't put other files in the mirror directory, they will be removed
# when this script runs if they don't exist in the remote package list!
#
# this is the directory to keep all the mirrored curl files in:
$some_dir = $ARGV[0];
if( ! -d $some_dir ) {
print "$some_dir is not a dir!\n";
exit;
}
# path to the curl binary
$curl = "/home/danste/bin/curl";
# this is the remote file list
$filelist = "http://curl.haxx.se/download/curldist.txt";
# prepend URL:
$prepend = "http://curl.haxx.se/download";
opendir(DIR, $some_dir) || die "can't opendir $some_dir: $!";
@existing = grep { /^[^\.]/ } readdir(DIR);
closedir DIR;
$LOCAL_FILE = 1;
$REMOTE_FILE = 2;
# create a hash array
for(@existing) {
$allfiles{$_} |= $LOCAL_FILE;
}
# get remote file list
print "Getting file list from $filelist\n";
@remotefiles=`$curl -s $filelist`;
# fill in the hash array
for(@remotefiles) {
chomp;
$allfiles{$_} |= $REMOTE_FILE;
$remote++;
}
if($remote < 10) {
print "There's something wrong. The remote file list seems too smallish!\n";
exit;
}
@sfiles = sort { $a cmp $b } keys %allfiles;
$leftalone = $downloaded = $removed = 0;
for(@sfiles) {
$file = $_;
$info = $allfiles{$file};
if($info == ($REMOTE_FILE|$LOCAL_FILE)) {
print "$file is LOCAL and REMOTE, left alone\n";
$leftalone++;
}
elsif($info == $REMOTE_FILE) {
print "$file is only REMOTE, getting it...\n";
system("$curl $prepend/$file -o $some_dir/$file");
$downloaded++;
}
elsif($info == $LOCAL_FILE) {
print "$file is only LOCAL, removing it...\n";
system("rm $some_dir/$file");
$removed++;
}
else {
print "Problem, file $file was marked $info\n";
}
$loops++;
}
if(!$loops) {
print "No remote or local files were found!\n";
exit;
}
print "$leftalone files were already present\n",
"$downloaded files were added\n",
"$removed files were removed\n";

View File

2
php/Makefile.am Normal file
View File

@@ -0,0 +1,2 @@
SUBDIRS = examples
EXTRA_DIST = README

15
php/README Normal file
View File

@@ -0,0 +1,15 @@
_ _ ____ _
___| | | | _ \| |
/ __| | | | |_) | |
| (__| |_| | _ <| |___
\___|\___/|_| \_\_____|
PHP
There's an excellent interface to curl written for PHP by Sterling Hughes. See
the subdirectory examples/ for some examples on how to program with it.
Unfortunately, we don't have much more information about the interface
included here yet, but there's a detailed online manual for it over at:
http://www.php.net/manual/ref.curl.php

1
php/examples/Makefile.am Normal file
View File

@@ -0,0 +1 @@
EXTRA_DIST = README getpageinvar.php simpleget.php simplepost.php

16
php/examples/README Normal file
View File

@@ -0,0 +1,16 @@
_ _ ____ _
___| | | | _ \| |
/ __| | | | |_) | |
| (__| |_| | _ <| |___
\___|\___/|_| \_\_____|
PHP program examples
getpageinvar.php
- Fetch a single URL and return in a variable
simpleget.php
- A very simple example that gets a HTTP page
simplepost.php
- Example that sends a HTTP POST to a remote site

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