Compare commits

...

326 Commits

Author SHA1 Message Date
Daniel Stenberg
bdb5e5a250 7.10.6 2003-07-28 12:13:48 +00:00
Daniel Stenberg
48a580e609 clear http->send_buffer when we have freed the memory it pointed to 2003-07-28 10:21:57 +00:00
Daniel Stenberg
1361fc69b9 updated to the new ftp dir parsing code that allows a preceeding double
slash
2003-07-28 09:02:15 +00:00
Daniel Stenberg
93352e56d8 As noticed by Kevin Roth, we shall not speak of root dir when it isn't
necessarily the root...
2003-07-28 08:53:12 +00:00
Daniel Stenberg
d9246ff24d Franois Pons brought a patch that once again made curl deal with ftp and
"double slash" as indicating the root directory. In the RFC1738-fix of April
30, that ability was removed (since it is not the "right" way).
2003-07-28 08:50:02 +00:00
Daniel Stenberg
9301bc3444 use the correct 'test71' file name for the temp file 2003-07-28 08:23:46 +00:00
Daniel Stenberg
76352c4e2d got a bug report on -F in config files, so I wrote up this test to verify
that is works... and it did! ;-)
2003-07-28 08:21:07 +00:00
Daniel Stenberg
428f41bd12 having it in CVS causes us problems *grrr* 2003-07-25 09:46:07 +00:00
Daniel Stenberg
99c32e460f Andrs Garca updated with the added files etc 2003-07-25 08:59:55 +00:00
Daniel Stenberg
83f249cf65 With an unknown CA path, we undef the variable. To build properly without
SSL/CA.
2003-07-25 08:47:34 +00:00
Daniel Stenberg
2c2baa93ea only check for CA bundle path if build with SSL support
set a conditional for the makefile if we know the CA path or not
2003-07-25 08:47:10 +00:00
Daniel Stenberg
f0278ca114 Removed #include <sys/resource.h>, as pointed out by Henry Bland we don't
need it.
2003-07-25 08:30:58 +00:00
Daniel Stenberg
297b1b5013 the test compared numericly if though it could contain a string, and I
lowered the number of retries to 10
2003-07-23 17:28:36 +00:00
Daniel Stenberg
e9f63bf4e8 When we re-use an existing connection we must make sure that we don't
accidentally re-use the connect_addr field, as that might no longer be
around. Fix verified by Tracy Boehrer who basicly debugged and tracked down
this problem.
2003-07-23 17:06:21 +00:00
Daniel Stenberg
556ce1c6a1 minor code style fix 2003-07-23 12:55:24 +00:00
Daniel Stenberg
cc4ff62681 Split out the changes from the year 2002 into a separate file, named
CHANGES.2002.
2003-07-23 11:59:20 +00:00
Daniel Stenberg
0423fd9b55 SSLCERTS was moved into the docs/ directory 2003-07-23 11:39:05 +00:00
Daniel Stenberg
789ab20bf7 moved SSLCERTS into the docs/ directory 2003-07-23 11:38:19 +00:00
Daniel Stenberg
b47462bd68 Daniel Kouril's fix to make the GSS-Negotiate work fine. 2003-07-23 11:28:59 +00:00
Daniel Stenberg
1a94fee42d Juan F. Codagnone's fixes to build properly on Windows again 2003-07-23 08:21:21 +00:00
Daniel Stenberg
a91ce6a5d6 Plain default version of this file, to allow users to build easier from
CVS. This will be updated by the configure script, and a default is placed
here by the maketgz script.
2003-07-23 08:11:28 +00:00
Daniel Stenberg
981ffd9fce reversed the check for GSSAPI when request that auth 2003-07-22 11:15:46 +00:00
Daniel Stenberg
e76c960624 CURLDEBUG, not MALLOCDEBUG 2003-07-22 10:00:37 +00:00
Daniel Stenberg
416c92cc6f More support for NTLM on proxies, now proxy state and nonce is stored in
a separate struct properly.
2003-07-22 09:59:36 +00:00
Daniel Stenberg
fb731eb3e7 The NTLM functions now take a 'proxy' argument as well. 2003-07-22 09:58:57 +00:00
Daniel Stenberg
6f2a4d290f Added a separate struct for the proxyntlm data, as it will/can be different
than the remote server's. That is, both the server and the proxy can in
fact require NTLM auth.
2003-07-22 09:58:18 +00:00
Daniel Stenberg
cefc8ba938 CURLDEBUG is the symbol now 2003-07-22 09:57:09 +00:00
Daniel Stenberg
d0bd644eef Don't depend on the TIME_WITH_SYS_TIME define. win32 doesn't have sys/time.h
and I don't think we need it.
2003-07-22 08:23:16 +00:00
Daniel Stenberg
071c95128e moved the proxyuser and proxypasswd fields from the sessionhandle to the
connectdata to work as expected
2003-07-21 13:16:30 +00:00
Daniel Stenberg
1a192c489b adjusted to support NTLM for proxies 2003-07-21 13:16:01 +00:00
Daniel Stenberg
56014e74a0 krb4-fixes for the moved user+password fields within the structs 2003-07-21 09:19:48 +00:00
Daniel Stenberg
172271498d pre4-commit 2003-07-21 08:25:31 +00:00
Daniel Stenberg
f2882cb88c pre4 2003-07-21 08:25:21 +00:00
Daniel Stenberg
152f1fee40 the CWD-null bug fix 2003-07-21 07:54:20 +00:00
Daniel Stenberg
968234e6ae the fixed skip-blanks in the FTP CWD code called for this adjustment 2003-07-20 00:19:44 +00:00
Daniel Stenberg
5e133e2dff David Gardner pointed out in bug report 770755 that using the FTP command CWD
with a blank argument is a bad idea. Now skip blanks.
2003-07-20 00:18:11 +00:00
Daniel Stenberg
0049c09fc3 If NTLM is requested, only re-use connections that have the exact same
credentials.
2003-07-20 00:02:47 +00:00
Daniel Stenberg
a2a63c27f4 explains my fixes just committed 2003-07-19 23:58:21 +00:00
Daniel Stenberg
c50a601f1a modified to work fine with the new persistant connection working test suite
HTTP server
2003-07-19 23:57:08 +00:00
Daniel Stenberg
bc0fd6db71 swsclose added 2003-07-19 23:56:44 +00:00
Daniel Stenberg
52b631fade Access the user and passwd fields from the connectdata struct now instead
of the sessionhandle struct, as that was not good.
2003-07-19 23:56:33 +00:00
Daniel Stenberg
2f0bc9d1f7 No longer stores user+password in the sessionhandle, now doing that in the
connectdata struct instead. Each being an allocated pointer.

The passwdgiven field was turned into a local variable in the only
function it was being used.
2003-07-19 23:55:15 +00:00
Daniel Stenberg
5ef6520d4e fixed the CONNECT thing again 2003-07-19 23:54:15 +00:00
Daniel Stenberg
2c1925161e If the data contents contains the word 'swsclose', then this server will
disconnect the client after the response have been sent. This also happens
if the respons is zero byte long.

In all other cases (unless an error happens), it will now maintain the
connection to allow proper persistant connection testing. This was required
for the NTLM testing to work so I finally had to fix this. Of course most of
the existing HTTP tests will be adjusted to work with this new rule of test
file syntax for HTTP tests.

Also fixed the log function to deal with varargs for better logging.
2003-07-19 23:44:22 +00:00
Daniel Stenberg
0529b349d5 recent changes 2003-07-16 00:04:45 +00:00
Daniel Stenberg
b4620364a2 more fixes from Doug Kaufman for DJGPP builds for DOS 2003-07-15 23:47:25 +00:00
Daniel Stenberg
634aef3895 updated to work with Dan Winship's NTLM domain stuff fix 2003-07-15 23:38:06 +00:00
Daniel Stenberg
06c86d1a8c Moved the NTLM credentials to the connectdata struct instead, as NTLM
authenticates connections and not single requests. This should make it work
better when we mix requests from multiple hosts. Problem pointed out by
Cris Bailiff.
2003-07-15 23:36:50 +00:00
Daniel Stenberg
79749f8eb4 Fix to the endless loop of bad Basic authentication as reported in Cris
Bailiff's bug report 768275.
2003-07-15 23:06:02 +00:00
Daniel Stenberg
b036986b3e Dan Winship's patch added that makes use of DOMAIN\USER or DOMAIN/USER
for the user field. I changed it slightly to stay with strchr() only instead
of strpbrk() for portability reasons.
2003-07-15 22:58:36 +00:00
Daniel Stenberg
938f1d1da7 Dan Winship's fix to make the new auth stuff such as NTLM to work with
the multi interface
2003-07-15 22:46:01 +00:00
Daniel Stenberg
58b6b3df06 Dan Winship pointed out this flaw 2003-07-15 22:44:48 +00:00
Daniel Stenberg
f9c3347f7c re-use existing variable instead of declaring a new local one 2003-07-05 13:27:02 +00:00
Daniel Stenberg
5b72eb0b03 Some of Doug Kaufman's changes for the DOS port 2003-07-05 13:13:49 +00:00
Daniel Stenberg
6dd4c13bc0 the latest changes 2003-07-04 18:18:17 +00:00
Daniel Stenberg
e4e7db551f HAVE_SETVBUF removed, no longer used 2003-07-04 18:17:58 +00:00
Daniel Stenberg
ebfde8da56 removed 2003-07-04 18:15:53 +00:00
Daniel Stenberg
756bc0f4b7 Dan Grayson pointed out that we set the CURL_CA_BUNDLE variable wrongly in
the configure script. We set it differently now and generate the
lib/ca-bundle.h file entirely.
2003-07-04 18:15:25 +00:00
Daniel Stenberg
269d491b6a remove the usage of setvbuf() and use fflush() instead if no buffering should
be done on the output
2003-07-04 17:16:34 +00:00
Daniel Stenberg
449e5bc2ad CURLDEBUG not MALLOCDEBUG anymore 2003-07-04 16:37:16 +00:00
Daniel Stenberg
8736c11d84 adjusted to the NTLM updates 2003-07-04 16:36:31 +00:00
Daniel Stenberg
45fc760985 Peter Sylvester's patch was applied that introduces the following:
CURLOPT_SSL_CTX_FUNCTION to set a callback that gets called with the
   OpenSSL's ssl_ctx pointer passed in and allow a callback to act on it. If
   anything but CURLE_OK is returned, that will also be returned by libcurl
   all the way back. If this function changes the CURLOPT_URL, libcurl will
   detect this and instead go use the new URL.

   CURLOPT_SSL_CTX_DATA is a pointer you set to get passed to the callback set
   with CURLOPT_SSL_CTX_FUNCTION.
2003-07-04 16:29:23 +00:00
Daniel Stenberg
7968e3c2de David Byron's patch that allows a client to make the server quit with a
magic url.
2003-07-01 15:21:42 +00:00
Daniel Stenberg
964a41c75c new CVS info 2003-07-01 12:12:10 +00:00
Daniel Stenberg
5931d53637 Gisle Vanem found a lib handle leak in the ldap code 2003-07-01 10:12:52 +00:00
Daniel Stenberg
3ed3ae5bcf When I introduced the DIST_SUBDIRS usage, I broken the 'make install' for
include files and docs, so now I've added a custom install hook to run
make install for docs and install when data is installed at the top-level.
2003-06-27 14:37:38 +00:00
Sterling Hughes
6519cc70c5 revert out my bogus commit. ;-) 2003-06-26 21:30:48 +00:00
Sterling Hughes
505a4f27fa test commit 2003-06-26 21:17:29 +00:00
Daniel Stenberg
79144eba99 new tests 2003-06-26 11:45:04 +00:00
Daniel Stenberg
26e17d89c9 produce a skip-report at the end of all tests, and thus record and count
them properly
2003-06-26 11:44:01 +00:00
Daniel Stenberg
4322c1106f beautified and added comments all over 2003-06-26 11:42:54 +00:00
Daniel Stenberg
73071dfd4f mention the new flag bits we support 2003-06-26 11:41:24 +00:00
Daniel Stenberg
b7c14b3c27 mention that it copies the string you add 2003-06-26 11:41:08 +00:00
Daniel Stenberg
3130b44535 added lots, mostly the new auth-related option(s) 2003-06-26 11:40:44 +00:00
Daniel Stenberg
a2bd73334f added lots of auth stuff and updated other things too 2003-06-26 11:40:04 +00:00
Daniel Stenberg
1a393f5625 mention COOKIES, removed added entries, corrected the FPL-SSL link/reference 2003-06-26 11:38:53 +00:00
Daniel Stenberg
d4951e837e mention the other formats the docs come in 2003-06-26 11:37:13 +00:00
Daniel Stenberg
26f6365e93 adjusted to recent changes 2003-06-26 11:36:32 +00:00
Daniel Stenberg
3a552b1e63 we do support NTLM now... 2003-06-26 11:35:48 +00:00
Daniel Stenberg
69eb1790da CURLDEBUG is the symbol to use, no longer MALLOCDEBUG 2003-06-26 11:34:36 +00:00
Daniel Stenberg
a1af6f3614 adjusted the compressed generation to be more helpful in comments etc 2003-06-26 11:34:07 +00:00
Daniel Stenberg
3aced61465 support for the new auth stuff
more output on --version/-V
mention --manual on the help output text
2003-06-26 11:33:29 +00:00
Daniel Stenberg
6f02ddfce8 new httpauth support, changed filetime variable kind 2003-06-26 11:31:50 +00:00
Daniel Stenberg
c2faa39b62 added CURLOPT_HTTPAUTH support 2003-06-26 11:30:59 +00:00
Daniel Stenberg
2d3734b8b5 Adjusted to work properly with the new authentication stuff
Added code to deal with white spaces in relocation headers.
2003-06-26 11:30:26 +00:00
Daniel Stenberg
ed908b7f89 use CURLDEBUG instead of MALLOCDEBUG 2003-06-26 11:28:26 +00:00
Daniel Stenberg
f7d795a364 use CURLDEBUG 2003-06-26 11:27:38 +00:00
Daniel Stenberg
8919b39d54 adjusted to use the same API as the OpenSSL version of the MD5 functions 2003-06-26 11:27:22 +00:00
Daniel Stenberg
84cedc094e added ntlm flag bits 2003-06-26 11:26:50 +00:00
Daniel Stenberg
3b2b2496d7 Many fixes, most of them based on comments by Eric Glass 2003-06-26 11:26:26 +00:00
Daniel Stenberg
445684c409 new proto for Curl_input_negotiate 2003-06-26 11:25:42 +00:00
Daniel Stenberg
898e067ccc kill warnings 2003-06-26 11:25:23 +00:00
Daniel Stenberg
12859e345f major adjustments to the new authentication support 2003-06-26 11:24:55 +00:00
Daniel Stenberg
89f4af695e include GSS in the debug string if available, support a few new flag
booleans
2003-06-26 11:22:48 +00:00
Daniel Stenberg
308bc9d919 use CURLDEBUG instead of MALLOCDEBUG for preprocessor conditions 2003-06-26 11:22:12 +00:00
Daniel Stenberg
db566c54ae use CURLDEBUG instead of MALLOCDEBUG 2003-06-26 11:16:37 +00:00
Daniel Stenberg
81d403e207 one typecast less for the localtime(), use CURLDEBUG instead of MALLOCDEBUG 2003-06-26 06:52:48 +00:00
Daniel Stenberg
2bd71d70ff use CURLDEBUG instead of MALLOCDEBUG 2003-06-26 06:50:32 +00:00
Daniel Stenberg
1eef6f44ba CURLDEBUG instead of MALLOCDEBUG 2003-06-26 06:47:20 +00:00
Daniel Stenberg
204f03912f We noe use CURLDEBUG instead of MALLOCDEBUG 2003-06-26 06:45:15 +00:00
Daniel Stenberg
f8c3b3aa18 moved from former CVS 2003-06-26 06:21:29 +00:00
Daniel Stenberg
d4df981463 Added time_t 2003-06-26 06:19:37 +00:00
Daniel Stenberg
497c6d516d up to date with the actual situation 2003-06-25 23:40:48 +00:00
Daniel Stenberg
8288862b7e Cris Bailiff's patch that should make us do NTLM correctly. When we've
authenticated our connection, we can continue without any Authorization:
headers as long as our connection is maintained.
2003-06-13 10:15:55 +00:00
Daniel Stenberg
9aae16c236 stdout is good enough 2003-06-13 09:09:04 +00:00
Daniel Stenberg
80c194a70a work more on pids, less on pidfiles to be able to do better kills at the
end of the test where the pidfiles aren't found, but "our" server is running
2003-06-13 09:04:08 +00:00
Daniel Stenberg
c832b2db5b fixed NTLM test 67, added test 68 for bad NTLM name/password 2003-06-13 08:03:45 +00:00
Daniel Stenberg
27018882ec Cris Bailiff's bugfix 2003-06-13 07:56:38 +00:00
Daniel Stenberg
caf6e9c540 use more curlish strings, these should be able to change... 2003-06-13 07:14:46 +00:00
Daniel Stenberg
e727fb82f2 Marty Kuhrt's #include fixes for VMS 2003-06-13 06:48:04 +00:00
Daniel Stenberg
c78df56801 get and use only the first line of the curl --version output 2003-06-12 23:05:12 +00:00
Daniel Stenberg
d13202f43b modified 2003-06-12 23:03:08 +00:00
Daniel Stenberg
9d139a6b35 Make the HTTP auth stuff work, Dan Fandrich made --version output a list
of all supported protocols.
2003-06-12 23:02:36 +00:00
Daniel Stenberg
d2abe44e6f remove the dumpit file after use 2003-06-12 19:17:08 +00:00
Daniel Stenberg
bc67228576 corrected a comment 2003-06-12 17:40:56 +00:00
Daniel Stenberg
ecf32c964a CURLHTTP* renamed to CURLAUTH* and NEGOTIATE is now GSSNEGOTIATE as there's
a "plain" Negotiate as well.
2003-06-12 17:34:27 +00:00
Daniel Stenberg
e58f30b82a NTLM test case 2003-06-12 16:39:35 +00:00
Daniel Stenberg
654e3f1101 require the netrc_debug feature the same way we now can require SSL
present client-side
2003-06-12 16:38:14 +00:00
Daniel Stenberg
86689dc524 now test cases can be set to be dependent on the presence of "SSL" in the
client/library
2003-06-12 16:22:52 +00:00
Daniel Stenberg
5f62a0c1ca make it build with older OpenSSL 2003-06-12 13:55:40 +00:00
Daniel Stenberg
ad1bf0f389 attempt to make older OpenSSL versions work with the DES stuff 2003-06-12 13:18:10 +00:00
Daniel Stenberg
9c7703ace1 Based on Dan Fandrich's patch and gzip unpack function, we now compress
the 'hugehelp' text if libz and gzip are available at build time.
2003-06-12 12:54:34 +00:00
Daniel Stenberg
4a8155b53c store HAVE_LIBZ as an automake conditional 2003-06-12 12:53:38 +00:00
Daniel Stenberg
80d6d5c5c4 fixing details for NTLM 2003-06-11 16:14:45 +00:00
Daniel Stenberg
c624be8388 more how I envision it _should_ work, but it still doesn't... 2003-06-11 15:33:09 +00:00
Daniel Stenberg
09df1cd41e to support "redirects" after the full body is transfered 2003-06-11 15:31:40 +00:00
Daniel Stenberg
52c5b57200 made a nicer output for the decode test, as it served as a nice tool for me ;-) 2003-06-11 15:31:06 +00:00
Daniel Stenberg
5ea04a852e when we get the auth headers, we still need to read out the full body response
as otherwise we can re-send requests on the same connection nicely
2003-06-11 15:30:30 +00:00
Daniel Stenberg
a2eef05198 correct mistakes 2003-06-11 14:05:13 +00:00
Daniel Stenberg
55f75af353 describe the NTLM mechanism too 2003-06-11 13:44:58 +00:00
Daniel Stenberg
fb6a51b8fd basic NTLM support 2003-06-11 13:44:31 +00:00
Daniel Stenberg
252cc2213e ntlm added 2003-06-11 13:42:53 +00:00
Daniel Stenberg
73c5f24fa4 Initial take at NTLM authentication. It doesn't really work at this point
but the infrastructure is there.
2003-06-11 13:38:55 +00:00
Daniel Stenberg
4c80e103a0 clarify the CUSTOMREQUEST and HTTPHEADER options slightly 2003-06-10 13:06:38 +00:00
Daniel Stenberg
39ea557360 CURLOPT_HTTPAUTH docu 2003-06-10 12:58:40 +00:00
Daniel Stenberg
d0cc92a01a Set auth type differently, we use one CURLOPT_HTTPAUTH instead as we plan
to add more method in the future.
2003-06-10 12:49:16 +00:00
Daniel Stenberg
d7980c1a45 Daniel Kouril for the HTTP negotiate stuff 2003-06-10 12:25:01 +00:00
Daniel Stenberg
e56ae1426c Daniel Kouril's patch that adds HTTP negotiation support to libcurl was
added.
2003-06-10 12:22:19 +00:00
Daniel Stenberg
696843c020 we fix more 2003-06-10 12:07:10 +00:00
Daniel Stenberg
6ff5621dd7 more generic 2003-06-10 12:05:12 +00:00
Daniel Stenberg
e7fb72a732 Pass the error stream pointer to the URL globber, so that it can report
errors correctly to the user, if need be.

Also fixed so that a missing ] in the globbing process no longer leads
to core dump.
2003-06-10 09:42:22 +00:00
Daniel Stenberg
8d30d34e0c When doing very big GET requests over HTTPS, we need to add some extra
funky logic in order to make re-tries work fine with OpenSSL. This corrects
the problem David Orrell noticed.
2003-06-06 14:58:26 +00:00
Daniel Stenberg
bc7fe85f8a Just moved around some logic in Curl_write() to make it easier to debug. 2003-06-06 14:56:50 +00:00
Daniel Stenberg
89352d92c5 spellfix 2003-06-06 06:44:05 +00:00
Daniel Stenberg
c32390d84c Reversed the logic to only include the <sys/select.h> header on systems
known to really NEED it as another system that doesn't have it came up:
very old Linux libc5-based systems (as addition to all HPUX versions).

The only known system at this point is AIX.
2003-06-05 14:04:44 +00:00
Daniel Stenberg
45ca866a2d LDAP problem added as mention in bug report #735752 2003-06-03 08:10:53 +00:00
Daniel Stenberg
ceef206c21 include the time headers just like we used to do in the curl/curl.h header
once upon the time
2003-06-03 08:07:06 +00:00
Daniel Stenberg
7c6424f0a9 we want the time defines too 2003-06-03 08:06:23 +00:00
Daniel Stenberg
bc942de6f1 Content-Length: now overrides other means of knowing when the stream has
ended.
2003-06-03 07:53:18 +00:00
Daniel Stenberg
06984df5cb Make the Content-Length info override the Connection: close header, so that
libcurl will stop reading when the number of bytes have arrived and not wait
for a closed socket.
2003-06-02 14:57:08 +00:00
Daniel Stenberg
4f136a3a76 the 500-599 test case range 2003-06-02 14:48:27 +00:00
Daniel Stenberg
363bf3ba30 ignore more 2003-06-02 13:55:40 +00:00
Daniel Stenberg
acb895956a ignore 2003-06-02 13:53:13 +00:00
Daniel Stenberg
21e87b9bb3 David Byron's fix to get the progress-bar use the local size too when
doing a resumed download.
2003-06-02 13:42:42 +00:00
Daniel Stenberg
c896ebcf12 makefile fiddle
changed how http requests are sent - now in one chunk more often
HPUX include fix in the external headers
better SSL work-arounds for bad SSL servers
modified error message when CURLE_HTTP_RETURNED_ERROR is returned
2003-06-02 13:31:25 +00:00
Daniel Stenberg
d288222e80 work-around SSL implementation flaws better, pointed out in bug report
#745122.
2003-06-02 13:27:03 +00:00
Daniel Stenberg
4eb2a6c9a3 make a more descriptive error message when CURLE_HTTP_RETURNED_ERROR is
returned
2003-06-02 13:14:57 +00:00
Daniel Stenberg
2563731c4d haven't updates this in a loooong time 2003-05-28 10:24:20 +00:00
Daniel Stenberg
4e410111db Posting static data using POST and chunked encoded now also appends the
data to the initial request buffer, if the total post data is less than
100K.
2003-05-28 07:54:33 +00:00
Daniel Stenberg
5670563a26 include sys/time.h, we didn't have a time() proto anymore. Did one of the
changes in curl/curl.h make this occur?
2003-05-27 22:56:01 +00:00
Daniel Stenberg
6caa656d01 Documented which rules the public headers must follow when we write
preprocessor checks for condititions.
2003-05-27 12:51:46 +00:00
Daniel Stenberg
c12af7aed1 oops, removed a # too many 2003-05-27 12:51:15 +00:00
Daniel Stenberg
dcb6d1c01d remove usage of HAVE_* defines, we cannot and shall not depend on any such
defines in the public external header files
2003-05-27 12:45:51 +00:00
Daniel Stenberg
18234cbdac sys/select.h is not present on HPUX, avoid including it 2003-05-27 12:34:48 +00:00
Daniel Stenberg
06bf988dc1 made it work ;-) 2003-05-27 12:18:00 +00:00
Daniel Stenberg
55ff4c3f08 if cvs update fails, attempt again after 5 seconds and retry 50 times
before giving up
2003-05-27 12:03:24 +00:00
Daniel Stenberg
4915002168 Only build in lib and src by default, make the others dist-subdirs.
Make the test stuff get built when we run 'make test' instead.
2003-05-27 08:51:09 +00:00
Daniel Stenberg
5bd8d60e41 Rudy Koento experienced problems with curl's recent habit of POSTing data in
two separate send() calls, first the headers and then the data. I've now made
a fix that for static and known content that isn't to be chunked-encoded,
everything is now sent in one single system call again. This is also better
for network performance reasons.
2003-05-27 08:33:08 +00:00
Daniel Stenberg
fc872808c5 runs on DOS now 2003-05-27 07:37:34 +00:00
Daniel Stenberg
0f4feda382 include file flaw and yet another socks5-fix 2003-05-27 06:41:06 +00:00
Daniel Stenberg
90b0f38316 Another socks5-fix. Make sure that when we use a socks-proxy, it is not the
same as using a httpproxy so we must make sure to better check for http
proxies before we do HTTP proxy stuff. This included authorization and
URI usage in the request etc.
2003-05-27 06:28:25 +00:00
Daniel Stenberg
18f630ab21 CURLOPT_HTTPDIGEST is added 2003-05-27 06:25:56 +00:00
Daniel Stenberg
e97fd44151 language 2003-05-26 12:32:22 +00:00
Daniel Stenberg
b75679778f ftp ASCII transfers in general need fixing 2003-05-26 08:19:06 +00:00
Daniel Stenberg
35a84ad576 Chris Lewis mentioned that he doesn't get WIN32 defined, only _WIN32 so we
make an adjustment to catch this.
2003-05-26 07:57:53 +00:00
Daniel Stenberg
4ed28be75a even more 2003-05-23 11:24:39 +00:00
Daniel Stenberg
e2f4656a86 Ricardo Cadime found a socket leak when listing directories without
contents. Test cases 144 and 145 were added to verify the fix.

Now we deal with return code 450 properly and other codes also do proper
cleanup.
2003-05-23 11:14:09 +00:00
Daniel Stenberg
1e14da5c60 more ftp testing using NLST and no contents and bad return code 2003-05-23 11:10:35 +00:00
Daniel Stenberg
b2ef79ef3d Rudy Koento's problem fixed, test case 66 verifies this. 2003-05-23 09:47:57 +00:00
Daniel Stenberg
f488874ff5 test 66 returns one line of data with no header (HTTP) 2003-05-23 09:46:19 +00:00
Daniel Stenberg
23258648da --digest added, --compressed rephrased 2003-05-23 08:06:31 +00:00
Daniel Stenberg
6b84ebe501 include digest.h for proto 2003-05-23 06:44:24 +00:00
Daniel Stenberg
07dd067f73 DJGPP fix by Gisle Vanem 2003-05-23 06:43:14 +00:00
Daniel Stenberg
420744d048 more more more 2003-05-22 22:47:48 +00:00
Daniel Stenberg
01108e3a63 warning-free is better 2003-05-22 22:45:38 +00:00
Daniel Stenberg
8026b1e194 Introducing --digest 2003-05-22 22:40:01 +00:00
Daniel Stenberg
a39d77227f Better Digest stuff 2003-05-22 22:39:38 +00:00
Daniel Stenberg
9f69deec7d Added CURLOPT_HTTPDIGEST support
SOCKS5 fix as suggested by Jis in bugreport #741841.
2003-05-22 22:38:46 +00:00
Daniel Stenberg
e912f772e0 Document the <dataNUM> thing we use, 2003-05-22 22:37:00 +00:00
Daniel Stenberg
0102726aeb Digest support added 2003-05-22 22:36:39 +00:00
Daniel Stenberg
1e7aa04040 Digest testing added 2003-05-22 22:36:22 +00:00
Daniel Stenberg
00a7c6fe6b proper header added 2003-05-22 16:23:27 +00:00
Daniel Stenberg
87f8c0d471 hush the compiler 2003-05-22 16:12:30 +00:00
Daniel Stenberg
334d78cd18 Initial Digest support. At least partly working. 2003-05-22 16:09:54 +00:00
Daniel Stenberg
2356325592 David Balazic pointed out the lack of checks for a valid %XX code when
we unescape a string. We now check and decode only valid %XX strings.
2003-05-21 15:53:59 +00:00
Daniel Stenberg
d78ec593fa fix the makefile in packages/DOS too 2003-05-21 08:12:52 +00:00
Daniel Stenberg
d5043133e6 Gisle Vanem made curl build with djgpp on DOS. 2003-05-21 08:08:48 +00:00
Daniel Stenberg
509f69a457 Gisle Vanem's fix to make the 'curl -M' output nicer 2003-05-21 07:21:44 +00:00
Daniel Stenberg
662c659220 missing semicolon, by Gisle Vanem 2003-05-20 12:44:55 +00:00
Daniel Stenberg
9a6566e774 Gisle Vanem's code for not trusting h_aliases to always be non-NULL 2003-05-20 09:41:39 +00:00
Daniel Stenberg
4da0428d9e Remind about the gpg command lines 2003-05-20 06:33:13 +00:00
Daniel Stenberg
8ee1177206 support user name and password in proxy environment variables 2003-05-19 13:14:26 +00:00
Daniel Stenberg
e9154b2549 the proxy environment variables now may contain user name and password 2003-05-19 13:09:41 +00:00
Daniel Stenberg
d398a0dd58 remove debug output 2003-05-19 13:08:48 +00:00
Daniel Stenberg
7723a24297 setenv support added to allow test cases to require a set of environment
variables
2003-05-19 13:06:10 +00:00
Daniel Stenberg
95a4b8db68 7.10.5 commit 2003-05-19 11:45:10 +00:00
Daniel Stenberg
663c1898a3 known AIX ipv6 problems 2003-05-16 10:57:53 +00:00
Daniel Stenberg
465de793e8 Skip any preceeding dots from the domain name of cookies when we keep them
in memory, only add it when we save the cookie. This makes all tailmatching
and domain string matching internally a lot easier.

This was also the reason for a remaining bug I introduced in my overhaul.
2003-05-15 22:28:19 +00:00
Daniel Stenberg
de9b76cef0 change the order of the in_addr_t tests, so that 'unsigned long' is tested
for first, as it seems to be what many systems use
2003-05-15 21:13:36 +00:00
Daniel Stenberg
1747a8d3d9 1. George Comninos' progress meter fix
2. I also added the pre-releases and dates to the log
2003-05-15 08:13:19 +00:00
Daniel Stenberg
1094e79749 documented CURLOPT_FTP_USE_EPRT 2003-05-14 09:03:51 +00:00
Daniel Stenberg
22569681bc George Comninos provided a fix that calls the progress meter when waiting
for FTP command responses take >1 second.
2003-05-14 06:31:00 +00:00
Daniel Stenberg
e615d117a0 Setup and use CURL_INADDR_NONE all over instead of INADDR_NONE. We setup
the define accordingly in the hostip.h header to work nicely all over.
2003-05-13 12:12:17 +00:00
Daniel Stenberg
a51258b6bb before using if2ip(), check if the address is an ip address and skip it if
it is.
2003-05-13 12:11:31 +00:00
Daniel Stenberg
8894bd07b6 libtool 1.4.2 is enough 2003-05-13 09:38:09 +00:00
Daniel Stenberg
ec45a9e825 fix comment 2003-05-13 09:37:45 +00:00
Daniel Stenberg
871358a6e5 before checking for network interfaces using if2ip(), check that the given
name isn't an ip address
2003-05-12 13:06:48 +00:00
Daniel Stenberg
2e2e0fba60 no more complaining when I have 1.5 and it tests for 1.4.2 2003-05-12 13:05:11 +00:00
Daniel Stenberg
4a5139e3f4 fixes from the last week+ 2003-05-12 12:49:22 +00:00
Daniel Stenberg
8f85933d7c Dan F clarified the CURLOPT_ENCODING description after his changes to
allow "" to enable all support formats.
2003-05-12 12:47:35 +00:00
Daniel Stenberg
246f3a63f6 Dan Fandrich added --compressed docu 2003-05-12 12:46:45 +00:00
Daniel Stenberg
e99eff4eb0 setting ENCODING to "" means enable-all-you-support 2003-05-12 12:45:57 +00:00
Daniel Stenberg
c0197f19cf Dan Fandrich changed CURLOPT_ENCODING to select all supported encodings if
set to "".  This frees the application from having to know which encodings
 the library supports.
2003-05-12 12:45:14 +00:00
Daniel Stenberg
3994d67eea Dan Fandrich lowered the libtool requirement 2003-05-12 12:38:52 +00:00
Daniel Stenberg
9ead79c9d4 when we have accepted the server's connection in a PORT sequence, we set
the new socket to non-blocking
2003-05-12 12:37:35 +00:00
Daniel Stenberg
9371aed46c avoid the write loop 2003-05-12 12:37:05 +00:00
Daniel Stenberg
940707ad66 incoming proxy headers shall be sent to the debug function has HEADERs not
DATA
2003-05-12 12:29:00 +00:00
Daniel Stenberg
e6c267fb4c oops, run libtoolize as the first tool 2003-05-09 08:17:41 +00:00
Daniel Stenberg
93538fccd6 run libtoolize too 2003-05-09 08:13:02 +00:00
Daniel Stenberg
83a7fad308 run libtoolize to generate these files 2003-05-09 08:12:46 +00:00
Daniel Stenberg
3c7e33388e CURLOPT_FTP_USE_EPRT added 2003-05-09 07:42:47 +00:00
Daniel Stenberg
7b0f35edb6 --disable-eprt added 2003-05-09 07:39:50 +00:00
Daniel Stenberg
94a157d0b0 support for CURLOPT_FTP_USE_EPRT added 2003-05-09 07:39:29 +00:00
Daniel Stenberg
ca04620253 AIX wants sys/select.h 2003-05-09 07:37:27 +00:00
Daniel Stenberg
073ef0b36a clarify on the curl name issue and that there may be other libcurl-based
tools that provide GUI
2003-05-09 07:07:13 +00:00
Daniel Stenberg
c41c05d4f4 Kevin Delafield reported another case where we didn't correctly check for
EAGAIN but only EWOULDBLOCK, which caused badness on HPUX. We also check for
 and act the same on EINTR errors as well now.
2003-05-06 08:19:36 +00:00
Daniel Stenberg
f1ea54e07a fixed the required tools' version numbers 2003-05-05 14:19:54 +00:00
Daniel Stenberg
a139ce901a the writable argv check now should not exit when building a cross-compiled
curl
2003-05-04 16:07:19 +00:00
Daniel Stenberg
7431957113 put back the libtool test, now for 1.5
require autoconf 2.57
require automake 1.7
2003-05-03 16:25:49 +00:00
Daniel Stenberg
1752d80915 If there is a custom Host: header specified, we use that host name to
extract the correct set of cookies to send. This functionality is verified
by test case 62.
2003-05-02 09:13:19 +00:00
Daniel Stenberg
aa7420e109 send correct cookies when using a custom Host: 2003-05-02 09:12:26 +00:00
Daniel Stenberg
a290d4b9db fixed the format slightly 2003-05-02 09:11:53 +00:00
Daniel Stenberg
19a4314e7f corrected a comment about gzip not being supported 2003-05-01 17:49:47 +00:00
Daniel Stenberg
d166e85e0a FTP URL with type=a 2003-05-01 17:48:59 +00:00
Daniel Stenberg
f213e857ab Andy Cedilnik fixed some compiler warnings 2003-05-01 13:37:36 +00:00
Daniel Stenberg
eb6130baa7 ourerrno became Curl_ourerrno() and is now available to all libcurl 2003-05-01 13:37:05 +00:00
Daniel Stenberg
f69ea2c68a Use the proper Curl_ourerrno() function instead of plain errno, for better
portability. Also use Andy Cedilnik's compiler warning fixes.
2003-05-01 13:36:28 +00:00
Daniel Stenberg
078441d477 the test numbers are now only for human readability, the numbers no longer
enforces protocol/server
2003-04-30 20:29:31 +00:00
Daniel Stenberg
95f6b15a67 no longer assume that the test number implies servers to run 2003-04-30 20:28:49 +00:00
Daniel Stenberg
ee29dbdb8f Each test case now specifies which server(s) it needs, without relying on the
test number.
2003-04-30 20:25:39 +00:00
Daniel Stenberg
15f3f4c93f we say welcome to test 142 2003-04-30 20:08:01 +00:00
Daniel Stenberg
6932e94e0e verify that curl fails fine when an FTP URL with a too deep dir hierarchy
is used
2003-04-30 20:07:37 +00:00
Daniel Stenberg
3ef06d7efe when making up the list of path parts, save the last entry pointing to NULL
as otherwise we'll go nuts
2003-04-30 20:04:17 +00:00
Daniel Stenberg
fb012b48e9 recent action 2003-04-30 20:01:22 +00:00
Daniel Stenberg
bc77bf217f if there's a cookiehost allocated, free that too 2003-04-30 19:58:36 +00:00
Daniel Stenberg
37d1e9351e ok, make the test run ok too 2003-04-30 19:56:53 +00:00
Daniel Stenberg
4494c0dee0 various new cookie tests with a custom Host: header set 2003-04-30 19:49:51 +00:00
Daniel Stenberg
26afc604ac modified to work with modified code 2003-04-30 17:16:25 +00:00
Daniel Stenberg
9aefcada19 modified to produce nicer output when a single test fails 2003-04-30 17:15:38 +00:00
Daniel Stenberg
69fc363760 make the diffs with 'diff -u' to make them nicer and easier to read 2003-04-30 17:15:00 +00:00
Daniel Stenberg
bea02ddebe stop parsing Host: host names at colons too 2003-04-30 17:12:29 +00:00
Daniel Stenberg
3fb257c39c modified to the new cookie function proto 2003-04-30 17:05:19 +00:00
Daniel Stenberg
7c96c5a39b extract host name from custom Host: headers to use for cookies 2003-04-30 17:04:53 +00:00
Daniel Stenberg
efd836d971 Many cookie fixes:
o Save domains in jars like Mozilla does. It means all domains set in
    Set-Cookie: headers are dot-prefixed.
  o Save and use the 'tailmatch' field in the Mozilla/Netscape cookie jars (the
    second column).
  o Reject cookies using illegal domains in the Set-Cookie: line. Concerns
    both domains with too few dots or domains that are outside the currently
    operating server host's domain.
  o Set the path part by default to the one used in the request, if none was
    set in the Set-Cookie line.
2003-04-30 17:03:43 +00:00
Daniel Stenberg
836aaa1647 changes need for the new ftp path treatment and the new cookie code 2003-04-30 17:01:00 +00:00
Daniel Stenberg
bf2b3dbf3e David Balazic's patch to make the FTP operations "do right" according to
RFC1738, which means it'll use one CWD for each pathpart.
2003-04-30 16:59:42 +00:00
Daniel Stenberg
b4fa2ff995 two more platforms Rich Gray built curl on 2003-04-30 07:32:43 +00:00
Daniel Stenberg
2f9cabc30b Peter Kovacs provided a patch that makes the CURLINFO_CONNECT_TIME work fine
when using the multi interface (too).
2003-04-29 18:03:30 +00:00
Daniel Stenberg
63593f5597 mention configure --help 2003-04-29 16:55:17 +00:00
Daniel Stenberg
c0acaa5d2c CURLOPT_FTPPORT could support port number too 2003-04-28 17:29:32 +00:00
Daniel Stenberg
2e46f8d0a6 corrected the comment which wasn't correct 2003-04-28 13:48:16 +00:00
Daniel Stenberg
51da6aaa07 RSAglue.lib is no longer needed with recent OpenSSL versions 2003-04-25 15:08:46 +00:00
Daniel Stenberg
c8b79e36db Dan Fandrich added support for the gzip Content-Encoding for --compressed 2003-04-24 06:34:31 +00:00
Daniel Stenberg
208374bcc9 Bryan Kemp's reported problems with curl and PUT from stdin and a faked
content-length made me add test case 60, that does exactly this, but it
seems to run fine...
2003-04-23 12:09:58 +00:00
Daniel Stenberg
7f0a6e7203 last 10 days or so 2003-04-22 23:30:04 +00:00
Daniel Stenberg
54ebb9cfd4 libtool 1.5 stuff 2003-04-22 23:29:27 +00:00
Daniel Stenberg
49e9c1495b stop checking for libtool, we don't run that in this script 2003-04-22 23:26:00 +00:00
Daniel Stenberg
a84b0fbd52 Dan Fandrich corrected the error messages on "bad encoding". 2003-04-22 22:33:39 +00:00
Daniel Stenberg
c95814c04d Dan Fandrich's gzip bugfix 2003-04-22 22:32:02 +00:00
Daniel Stenberg
9f8123f1b8 Dan Fandrich's fix 2003-04-22 22:31:02 +00:00
Daniel Stenberg
8b23db4f4d Peter Sylvester pointed out that curl_easy_setopt() will always (wrongly)
return CURLE_OK no matter what happens.
2003-04-22 21:42:39 +00:00
Daniel Stenberg
d77cc13374 two dashes is enough 2003-04-16 12:46:20 +00:00
Daniel Stenberg
9a12db1aa2 typecast the setting of the size, as it might be an off_t which is bigger
than long and libcurl expects a long...
2003-04-15 14:18:37 +00:00
Daniel Stenberg
eb54d34bec If MALLOCDEBUG, include the lib's setup.h here so that the proper defines
are set before all system headers, as otherwise we get compiler warnings
on my Solaris at least.
2003-04-15 14:01:57 +00:00
Daniel Stenberg
4b1203d4c9 include config.h before all system headers, so that _FILE_OFFSET_BITS and
similar is set properly by us first
2003-04-15 13:32:26 +00:00
Daniel Stenberg
183a9c6244 extended the -F section 2003-04-15 09:58:27 +00:00
Daniel Stenberg
1f2294d585 treat uploaded .html files as text/html by default 2003-04-15 09:29:39 +00:00
Daniel Stenberg
0b839c4f77 return the same error for the sslv2 "certificate verify failed" code 2003-04-14 22:00:36 +00:00
Daniel Stenberg
1d4fd1fcae new wording by Kevin Roth 2003-04-14 14:54:18 +00:00
Daniel Stenberg
b1d8d72c16 ignore all stamp-h* 2003-04-14 13:09:44 +00:00
Daniel Stenberg
bafb68b844 With the recent fix of libcurl, it shall now return CURLE_SSL_CACERT when
it had problems withe CA cert and thus we offer a huge blurb of verbose
help to explain to the poor user why this happens.
2003-04-14 13:09:09 +00:00
Daniel Stenberg
21873b52e9 Restored the SSL error codes since they was broken in the 7.10.4 release,
also now attempt to detect and return the specific CACERT error code.
2003-04-14 12:53:29 +00:00
Daniel Stenberg
0aa8b82871 FTP CWD response fixed
gzip content-encoding added
chunked content-encoding fixed
2003-04-14 07:13:08 +00:00
Daniel Stenberg
f9781afafd clarified the CURLINFO_SIZE_DOWNLOAD somewhat on Juan F. Codagnone's
suggestion
2003-04-11 16:52:30 +00:00
Daniel Stenberg
fece361a55 Nic fixed so that Curl_client_write() must not be called with 0 lenth data.
I edited somewhat and removed trailing whitespaces.
2003-04-11 16:31:18 +00:00
Daniel Stenberg
7b51b2f128 Nic Hines fixed this bug when deflate or gzip contents were downloaded using
chunked encoding.
2003-04-11 16:23:43 +00:00
Daniel Stenberg
22d88fb28e ah, move the zero byte too or havoc will occur 2003-04-11 16:23:06 +00:00
Daniel Stenberg
f7c5b28e76 verify the new url parser fix 2003-04-11 16:22:27 +00:00
Daniel Stenberg
5760f2a307 support ? as separator instead of / even if not protocol was given 2003-04-11 16:08:41 +00:00
Daniel Stenberg
ee46efb5a5 these guys deserve a mentioning here as well 2003-04-11 08:57:19 +00:00
Daniel Stenberg
eb6ffebfc7 Dan the man on the list 2003-04-11 08:55:08 +00:00
Daniel Stenberg
c06c44f286 Dan Fandrich's added gzip support documented. 2003-04-11 08:51:24 +00:00
Daniel Stenberg
019c4088cf Dan Fandrich's gzip patch applied 2003-04-11 08:49:20 +00:00
Daniel Stenberg
0b0a88b78d when saving a cookie jar fails, you don't get an error code or anything,
just a warning in the verbose output stream
2003-04-11 08:19:06 +00:00
Daniel Stenberg
028e9cc56f According to RFC959, CWD is supposed to return 250 on success, but
there seem to be non-compliant FTP servers out there that return 200,
 so we accept any '2xy' response now.
2003-04-11 08:10:54 +00:00
Daniel Stenberg
e0d8615ece show a verbose warning message in case cookie-saving fails, after
Ralph Mitchell's notification.
2003-04-11 07:39:16 +00:00
Daniel Stenberg
c8ecbda40b new ftp tests 2003-04-10 11:43:47 +00:00
Daniel Stenberg
2324c10d43 another week has passed 2003-04-10 11:36:56 +00:00
Daniel Stenberg
89cfa76291 Vlad Krupin's URL parsing patch to fix the URL parsing when the URL has no
slash after the host name, but still a ? and following "parameters".
2003-04-10 09:44:39 +00:00
Daniel Stenberg
072070a22c oops, committed test code not meant to be here 2003-04-09 12:02:06 +00:00
Daniel Stenberg
3c3ad134ea the default debugfunction shows incoming headers as well 2003-04-09 11:57:06 +00:00
Daniel Stenberg
a4ffcfd4d5 timecond support added
made the Last-Modified (faked) header look correct using GMT always
2003-04-09 11:56:31 +00:00
Daniel Stenberg
136670c58a three new ftp tests 2003-04-09 11:55:24 +00:00
Daniel Stenberg
28169725fa <mdtm> added 2003-04-09 11:53:09 +00:00
Daniel Stenberg
5b13106f54 MDTM support added 2003-04-09 11:52:24 +00:00
Daniel Stenberg
1a2db0dfb1 James Bursa fixed a flaw in the content-type extracting code that could
miss the first letter
2003-04-08 14:48:38 +00:00
Daniel Stenberg
696f95bb0a share.c added 2003-04-08 10:35:35 +00:00
Daniel Stenberg
acec588fe3 --disable-eprt perhaps? 2003-04-07 06:41:24 +00:00
Daniel Stenberg
6ed0da8e98 Ryan Weaver's fix to prevent the ca bundle to get installed even when
building curl without SSL support!
2003-04-06 12:29:45 +00:00
Daniel Stenberg
7fd91d70bd adjusted the formpost testcases to the new boundary string construction 2003-04-04 12:30:35 +00:00
Daniel Stenberg
61788a0389 Changed how boundary strings are generated. This new way uses 28 dashes
and 12 following hexadecimal letters, which seems to be what IE uses.
This makes curl work smoother with more stupidly written server apps.

Worked this out together with Martijn Broenland.
2003-04-04 12:24:01 +00:00
Daniel Stenberg
0821447b5b spell fix 2003-04-03 16:11:47 +00:00
Daniel Stenberg
3cba274ba6 kill a compiler warning on cygwin 2003-04-03 14:16:15 +00:00
Daniel Stenberg
df7bbcfd21 Added log output for when the writing of the input HTTP request is successful
or unsuccessful. Used to track down the recent cygwin test suite problems.
2003-04-03 13:43:15 +00:00
Daniel Stenberg
021d406f0c Modified how we log data to server.input, as we can't keep the file open
very much as it makes it troublesome on certain operating systems.
2003-04-03 13:42:06 +00:00
Daniel Stenberg
294569c502 new 2003-04-03 13:39:36 +00:00
258 changed files with 9328 additions and 10701 deletions

View File

@@ -9,3 +9,6 @@ config.status
curl-config curl-config
autom4te.cache autom4te.cache
depcomp depcomp
config.guess
config.sub
ltmain.sh

1967
CHANGES

File diff suppressed because it is too large Load Diff

1504
CHANGES.2002 Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -16,8 +16,8 @@ Compile and build instructions follow below.
CHANGES.$year contains changes for the particular year. CHANGES.$year contains changes for the particular year.
tests/memanalyze.pl tests/memanalyze.pl
is for analyzing the output generated by curl if -DMALLOCDEBUG is for analyzing the output generated by curl if -DCURLDEBUG
is used when compiling is used when compiling (run configure with --enable-debug)
buildconf builds the makefiles and configure stuff buildconf builds the makefiles and configure stuff
@@ -40,9 +40,9 @@ REQUIREMENTS
You need the following software installed: You need the following software installed:
o autoconf 2.50 (or later) o autoconf 2.57 (or later)
o automake 1.5 (or later) o automake 1.7 (or later)
o libtool 1.4 (or later) o libtool 1.4.2 (or later)
o GNU m4 (required by autoconf) o GNU m4 (required by autoconf)
o nroff + perl o nroff + perl

View File

@@ -4,12 +4,13 @@
AUTOMAKE_OPTIONS = foreign AUTOMAKE_OPTIONS = foreign
EXTRA_DIST = CHANGES COPYING maketgz SSLCERTS reconf Makefile.dist \ EXTRA_DIST = CHANGES COPYING maketgz reconf Makefile.dist \
curl-config.in build_vms.com curl-style.el sample.emacs testcurl.sh curl-config.in build_vms.com curl-style.el sample.emacs testcurl.sh
bin_SCRIPTS = curl-config bin_SCRIPTS = curl-config
SUBDIRS = docs lib src include tests packages SUBDIRS = lib src
DIST_SUBDIRS = $(SUBDIRS) tests include packages docs
# create a root makefile in the distribution: # create a root makefile in the distribution:
dist-hook: dist-hook:
@@ -25,10 +26,10 @@ pdf:
check: test check: test
test: test:
@(cd tests; $(MAKE) quiet-test) @(cd tests; $(MAKE) all quiet-test)
test-full: test-full:
@(cd tests; $(MAKE) full-test) @(cd tests; $(MAKE) all full-test)
# #
# Build source and binary rpms. For rpm-3.0 and above, the ~/.rpmmacros # Build source and binary rpms. For rpm-3.0 and above, the ~/.rpmmacros
@@ -77,3 +78,8 @@ pkgadd:
# resulting .tar.bz2 file will end up at packages/Win32/cygwin # resulting .tar.bz2 file will end up at packages/Win32/cygwin
cygwinbin: cygwinbin:
$(MAKE) -C packages/Win32/cygwin cygwinbin $(MAKE) -C packages/Win32/cygwin cygwinbin
# We extend the standard install with a custom hook:
install-data-hook:
cd include && $(MAKE) install
cd docs && $(MAKE) install

View File

@@ -59,6 +59,10 @@ vc-ssl-dll:
cd ..\src cd ..\src
nmake -f Makefile.vc6 nmake -f Makefile.vc6
djgpp:
make -C lib -f Makefile.dj
make -C src -f Makefile.dj
cygwin: cygwin:
./configure ./configure
make make

8
README
View File

@@ -49,15 +49,15 @@ CVS
To download the very latest source off the CVS server do this: To download the very latest source off the CVS server do this:
cvs -d :pserver:anonymous@cvs.curl.sourceforge.net:/cvsroot/curl login cvs -d :pserver:cvsread@cvs.php.net:/repository login
(just press enter when asked for password) (enter "phpfi" when asked for password)
cvs -d :pserver:anonymous@cvs.curl.sourceforge.net:/cvsroot/curl co curl cvs -d :pserver:cvsread@cvs.php.net:/repository co curl
(you'll get a directory named curl created, filled with the source code) (you'll get a directory named curl created, filled with the source code)
cvs -d :pserver:anonymous@cvs.curl.sourceforge.net:/cvsroot/curl logout cvs -d :pserver:cvsread@cvs.php.net:/repository logout
(you're off the hook!) (you're off the hook!)

View File

@@ -152,10 +152,8 @@ AC_DEFUN([TYPE_IN_ADDR_T],
AC_MSG_CHECKING([for in_addr_t equivalent]) AC_MSG_CHECKING([for in_addr_t equivalent])
AC_CACHE_VAL([curl_cv_in_addr_t_equiv], AC_CACHE_VAL([curl_cv_in_addr_t_equiv],
[ [
# Systems have either "struct sockaddr *" or
# "void *" as the second argument to getpeername
curl_cv_in_addr_t_equiv= curl_cv_in_addr_t_equiv=
for t in int size_t unsigned long "unsigned long"; do for t in "unsigned long" int size_t unsigned long; do
AC_TRY_COMPILE([ AC_TRY_COMPILE([
#include <sys/types.h> #include <sys/types.h>
#include <sys/socket.h> #include <sys/socket.h>

View File

@@ -6,18 +6,19 @@ die(){
} }
#-------------------------------------------------------------------------- #--------------------------------------------------------------------------
# autoconf 2.50 or newer # autoconf 2.57 or newer
# #
need_autoconf="2.57"
ac_version=`${AUTOCONF:-autoconf} --version 2>/dev/null|head -1| sed -e 's/^[^0-9]*//' -e 's/[a-z]* *$//'` ac_version=`${AUTOCONF:-autoconf} --version 2>/dev/null|head -1| sed -e 's/^[^0-9]*//' -e 's/[a-z]* *$//'`
if test -z "$ac_version"; then if test -z "$ac_version"; then
echo "buildconf: autoconf not found." echo "buildconf: autoconf not found."
echo " You need autoconf version 2.50 or newer installed." echo " You need autoconf version $need_autoconf or newer installed."
exit 1 exit 1
fi fi
IFS=.; set $ac_version; IFS=' ' IFS=.; set $ac_version; IFS=' '
if test "$1" = "2" -a "$2" -lt "50" || test "$1" -lt "2"; then if test "$1" = "2" -a "$2" -lt "57" || test "$1" -lt "2"; then
echo "buildconf: autoconf version $ac_version found." echo "buildconf: autoconf version $ac_version found."
echo " You need autoconf version 2.50 or newer installed." echo " You need autoconf version $need_autoconf or newer installed."
echo " If you have a sufficient autoconf installed, but it" echo " If you have a sufficient autoconf installed, but it"
echo " is not named 'autoconf', then try setting the" echo " is not named 'autoconf', then try setting the"
echo " AUTOCONF environment variable." echo " AUTOCONF environment variable."
@@ -48,18 +49,19 @@ fi
echo "buildconf: autoheader version $ah_version (ok)" echo "buildconf: autoheader version $ah_version (ok)"
#-------------------------------------------------------------------------- #--------------------------------------------------------------------------
# automake 1.5 or newer # automake 1.7 or newer
# #
am_version=`${AUTOMAKE:-automake} --version 2>/dev/null|head -1| sed -e 's/^[^0-9]*//' -e 's/[a-z]* *$//'` need_automake="1.7"
am_version=`${AUTOMAKE:-automake} --version 2>/dev/null|head -1| sed -e 's/^.* \([0-9]\)/\1/' -e 's/[a-z]* *$//'`
if test -z "$am_version"; then if test -z "$am_version"; then
echo "buildconf: automake not found." echo "buildconf: automake not found."
echo " You need automake version 1.5 or newer installed." echo " You need automake version $need_automake or newer installed."
exit 1 exit 1
fi fi
IFS=.; set $am_version; IFS=' ' IFS=.; set $am_version; IFS=' '
if test "$1" = "1" -a "$2" -lt "5" || test "$1" -lt "1"; then if test "$1" = "1" -a "$2" -lt "7" || test "$1" -lt "1"; then
echo "buildconf: automake version $am_version found." echo "buildconf: automake version $am_version found."
echo " You need automake version 1.5 or newer installed." echo " You need automake version $need_automake or newer installed."
echo " If you have a sufficient automake installed, but it" echo " If you have a sufficient automake installed, but it"
echo " is not named 'autommake', then try setting the" echo " is not named 'autommake', then try setting the"
echo " AUTOMAKE environment variable." echo " AUTOMAKE environment variable."
@@ -68,33 +70,37 @@ fi
echo "buildconf: automake version $am_version (ok)" echo "buildconf: automake version $am_version (ok)"
#-------------------------------------------------------------------------- #--------------------------------------------------------------------------
# libtool 1.4 or newer # libtool check
# #
LIBTOOL_WANTED_MAJOR=1 LIBTOOL_WANTED_MAJOR=1
LIBTOOL_WANTED_MINOR=4 LIBTOOL_WANTED_MINOR=4
LIBTOOL_WANTED_PATCH= LIBTOOL_WANTED_PATCH=2
LIBTOOL_WANTED_VERSION=1.4 LIBTOOL_WANTED_VERSION=1.4.2
libtool=`which glibtool 2>/dev/null` libtool=`which glibtool 2>/dev/null`
if test ! -x "$libtool"; then if test ! -x "$libtool"; then
libtool=`which libtool` libtool=`which libtool`
fi fi
lt_pversion=`$libtool --version 2>/dev/null|sed -e 's/^[^0-9]*//' -e 's/[- ].*//'` #lt_pversion=`${LIBTOOL:-$libtool} --version 2>/dev/null|head -1| sed -e 's/^.* \([0-9]\)/\1/' -e 's/[a-z]* *$//'`
lt_pversion=`$libtool --version 2>/dev/null|head -1|sed -e 's/^[^0-9]*//g' -e 's/[- ].*//'`
if test -z "$lt_pversion"; then if test -z "$lt_pversion"; then
echo "buildconf: libtool not found." echo "buildconf: libtool not found."
echo " You need libtool version $LIBTOOL_WANTED_VERSION or newer installed" echo " You need libtool version $LIBTOOL_WANTED_VERSION or newer installed"
exit 1 exit 1
fi fi
lt_version=`echo $lt_pversion|sed -e 's/\([a-z]*\)$/.\1/'` lt_version=`echo $lt_pversion` #|sed -e 's/\([a-z]*\)$/.\1/'`
IFS=.; set $lt_version; IFS=' ' IFS=.; set $lt_version; IFS=' '
lt_status="good" lt_status="good"
if test "$1" = "$LIBTOOL_WANTED_MAJOR"; then if test "$1" = "$LIBTOOL_WANTED_MAJOR"; then
if test "$2" -lt "$LIBTOOL_WANTED_MINOR"; then if test "$2" -lt "$LIBTOOL_WANTED_MINOR"; then
lt_status="bad" lt_status="bad"
elif test ! -z "$LIBTOOL_WANTED_PATCH"; then elif test ! -z "$LIBTOOL_WANTED_PATCH"; then
if test "$3" -lt "$LIBTOOL_WANTED_PATCH"; then if test -n "$3"; then
lt_status="bad" if test "$3" -lt "$LIBTOOL_WANTED_PATCH"; then
lt_status="bad"
fi
fi fi
fi fi
fi fi
@@ -104,15 +110,20 @@ if test $lt_status != "good"; then
exit 1 exit 1
fi fi
echo "buildconf: libtool version $lt_pversion (ok)" echo "buildconf: libtool version $lt_version (ok)"
# ------------------------------------------------------------
# run the correct scripts now
echo "buildconf: running libtoolize"
${LIBTOOLIZE:-libtoolize} --copy --automake || die "The command '${LIBTOOLIZE:-libtoolize} --copy --automake' failed"
echo "buildconf: running aclocal" echo "buildconf: running aclocal"
aclocal || die "The command 'aclocal' failed" ${ACLOCAL:-aclocal} || die "The command '${AUTOHEADER:-aclocal}' failed"
echo "buildconf: running autoheader" echo "buildconf: running autoheader"
autoheader || die "The command 'autoheader' failed" ${AUTOHEADER:-autoheader} || die "The command '${AUTOHEADER:-autoheader}' failed"
echo "buildconf: running autoconf" echo "buildconf: running autoconf"
autoconf || die "The command 'autoconf' failed" ${AUTOCONF:-autoconf} || die "The command '${AUTOCONF:-autoconf}' failed"
echo "buildconf: running automake" echo "buildconf: running automake"
automake -a || die "The command 'automake -a' failed" ${AUTOMAKE:-automake} -a || die "The command '${AUTOMAKE:-automake} -a' failed"
exit 0 exit 0

1363
config.guess vendored

File diff suppressed because it is too large Load Diff

1470
config.sub vendored

File diff suppressed because it is too large Load Diff

View File

@@ -14,7 +14,7 @@ This configure script may be copied, distributed and modified under the
terms of the curl license; see COPYING for more details]) terms of the curl license; see COPYING for more details])
AC_CONFIG_SRCDIR([lib/urldata.h]) AC_CONFIG_SRCDIR([lib/urldata.h])
AM_CONFIG_HEADER(lib/config.h src/config.h tests/server/config.h lib/ca-bundle.h) AM_CONFIG_HEADER(lib/config.h src/config.h tests/server/config.h )
AM_MAINTAINER_MODE AM_MAINTAINER_MODE
AC_PATH_PROG( SED, sed, , $PATH:/usr/bin:/usr/local/bin) AC_PATH_PROG( SED, sed, , $PATH:/usr/bin:/usr/local/bin)
@@ -349,15 +349,17 @@ dnl Check if the operating system allows programs to write to their own argv[]
dnl ********************************************************************** dnl **********************************************************************
AC_MSG_CHECKING([if argv can be written to]) AC_MSG_CHECKING([if argv can be written to])
AC_TRY_RUN([ AC_RUN_IFELSE([[
int main(int argc, char ** argv) { int main(int argc, char ** argv) {
argv[0][0] = ' '; argv[0][0] = ' ';
return (argv[0][0] == ' ')?0:1; return (argv[0][0] == ' ')?0:1;
} }
], ]],
AC_DEFINE(HAVE_WRITABLE_ARGV, 1, [Define this symbol if your OS supports changing the contents of argv]) AC_DEFINE(HAVE_WRITABLE_ARGV, 1, [Define this symbol if your OS supports changing the contents of argv])
AC_MSG_RESULT(yes), AC_MSG_RESULT(yes),
AC_MSG_RESULT(no) AC_MSG_RESULT(no),
AC_MSG_RESULT(no)
AC_MSG_WARN([the previous check could not be made default was used])
) )
dnl ********************************************************************** dnl **********************************************************************
@@ -452,6 +454,63 @@ else
AC_MSG_RESULT(no) AC_MSG_RESULT(no)
fi fi
dnl **********************************************************************
dnl Check for GSS-API libraries
dnl **********************************************************************
AC_ARG_WITH(gssapi-includes,
AC_HELP_STRING([--with-gssapi-includes=DIR],
[Specify location of GSSAPI header]),
[ GSSAPI_INCS="-I$withval"
want_gss="yes" ]
)
AC_ARG_WITH(gssapi-libs,
AC_HELP_STRING([--with-gssapi-libs=DIR],
[Specify location of GSSAPI libs]),
[ GSSAPI_LIBS="-L$withval -lgssapi"
want_gss="yes" ]
)
AC_ARG_WITH(gssapi,
AC_HELP_STRING([--with-gssapi=DIR],
[Where to look for GSSAPI]),
[ GSSAPI_ROOT="$withval"
want_gss="yes" ]
)
AC_MSG_CHECKING([if GSSAPI support is requested])
if test x"$want_gss" = xyes; then
if test -z "$GSSAPI_INCS"; then
if test -f "$GSSAPI_ROOT/bin/krb5-config"; then
gss_cppflags=`$GSSAPI_ROOT/bin/krb5-config --cflags gssapi`
CPPFLAGS="$CPPFLAGS $gss_cppflags"
else
CPPFLAGS="$GSSAPI_ROOT/include"
fi
else
CPPFLAGS="$CPPFLAGS $GSSAPI_INCS"
fi
if test -z "$GSSAPI_LIB_DIR"; then
if test -f "$GSSAPI_ROOT/bin/krb5-config"; then
gss_ldflags=`$GSSAPI_ROOT/bin/krb5-config --libs gssapi`
LDFLAGS="$LDFLAGS $gss_ldflags"
else
LDFLAGS="$LDFLAGS $GSSAPI_ROOT/lib -lgssapi"
fi
else
LDFLAGS="$LDFLAGS $GSSAPI_LIB_DIR"
fi
AC_MSG_RESULT(yes)
AC_DEFINE(GSSAPI, 1, [if you have the gssapi libraries])
else
AC_MSG_RESULT(no)
fi
dnl Detect the pkg-config tool, as it may have extra info about the dnl Detect the pkg-config tool, as it may have extra info about the
dnl openssl installation we can use. I *believe* this is what we are dnl openssl installation we can use. I *believe* this is what we are
dnl expected to do on really recent Redhat Linux hosts. dnl expected to do on really recent Redhat Linux hosts.
@@ -484,6 +543,8 @@ dnl **********************************************************************
dnl Default to compiler & linker defaults for SSL files & libraries. dnl Default to compiler & linker defaults for SSL files & libraries.
OPT_SSL=off OPT_SSL=off
dnl Default to no CA bundle
ca="no"
AC_ARG_WITH(ssl,dnl AC_ARG_WITH(ssl,dnl
AC_HELP_STRING([--with-ssl=PATH],[where to look for SSL, PATH points to the SSL installation (default: /usr/local/ssl)]) AC_HELP_STRING([--with-ssl=PATH],[where to look for SSL, PATH points to the SSL installation (default: /usr/local/ssl)])
AC_HELP_STRING([--without-ssl], [disable SSL]), AC_HELP_STRING([--without-ssl], [disable SSL]),
@@ -567,6 +628,36 @@ else
AC_SUBST(OPENSSL_ENABLED) AC_SUBST(OPENSSL_ENABLED)
AC_MSG_CHECKING([CA cert bundle install path])
AC_ARG_WITH(ca-bundle,
AC_HELP_STRING([--with-ca-bundle=FILE], [File name to install the CA bundle as])
AC_HELP_STRING([--without-ca-bundle], [Don't install the CA bundle]),
[ ca="$withval" ],
[
if test "x$prefix" != xNONE; then
ca="\${prefix}/share/curl/curl-ca-bundle.crt"
else
ca="$ac_default_prefix/share/curl/curl-ca-bundle.crt"
fi
] )
if test X"$OPT_SSL" = Xno; then
ca="no"
fi
if test "x$ca" != "xno"; then
CURL_CA_BUNDLE='"'$ca'"'
AC_SUBST(CURL_CA_BUNDLE)
fi
AC_MSG_RESULT([$ca])
dnl these can only exist if openssl exists
AC_CHECK_FUNCS( RAND_status \
RAND_screen \
RAND_egd )
fi fi
if test X"$OPT_SSL" != Xoff && if test X"$OPT_SSL" != Xoff &&
@@ -574,15 +665,10 @@ else
AC_MSG_ERROR([OpenSSL libs and/or directories were not found where specified!]) AC_MSG_ERROR([OpenSSL libs and/or directories were not found where specified!])
fi fi
dnl these can only exist if openssl exists
AC_CHECK_FUNCS( RAND_status \
RAND_screen \
RAND_egd )
fi fi
AM_CONDITIONAL(CABUNDLE, test x$ca != xno)
dnl ********************************************************************** dnl **********************************************************************
dnl Check for the presence of ZLIB libraries and headers dnl Check for the presence of ZLIB libraries and headers
dnl ********************************************************************** dnl **********************************************************************
@@ -625,6 +711,9 @@ case "$OPT_ZLIB" in
;; ;;
esac esac
dnl set variable for use in automakefile(s)
AM_CONDITIONAL(HAVE_LIBZ, test x"$HAVE_LIBZ" = x1)
dnl Default is to try the thread-safe versions of a few functions dnl Default is to try the thread-safe versions of a few functions
OPT_THREAD=on OPT_THREAD=on
@@ -772,7 +861,6 @@ AC_CHECK_FUNCS( socket \
tcgetattr \ tcgetattr \
perror \ perror \
closesocket \ closesocket \
setvbuf \
sigaction \ sigaction \
signal \ signal \
getpass_r \ getpass_r \
@@ -820,31 +908,6 @@ AC_PATH_PROGS( NROFF, gnroff nroff, ,
$PATH:/usr/bin/:/usr/local/bin ) $PATH:/usr/bin/:/usr/local/bin )
AC_SUBST(NROFF) AC_SUBST(NROFF)
AC_MSG_CHECKING([CA cert bundle install path])
AC_ARG_WITH(ca-bundle,
AC_HELP_STRING([--with-ca-bundle=FILE], [File name to install the CA bundle as])
AC_HELP_STRING([--without-ca-bundle], [Don't install the CA bundle]),
[ ca="$withval" ],
[
if test "x$prefix" != xNONE; then
ca="$prefix/share/curl/curl-ca-bundle.crt"
else
ca="$ac_default_prefix/share/curl/curl-ca-bundle.crt"
fi
] )
if test "x$ca" = "xno"; then
dnl let's not keep "no" as path name, blank it instead
ca=""
else
AC_DEFINE_UNQUOTED(CURL_CA_BUNDLE, "$ca", [CA bundle full path name])
fi
CURL_CA_BUNDLE="$ca"
AC_SUBST(CURL_CA_BUNDLE)
AC_MSG_RESULT([$ca])
AC_PROG_YACC AC_PROG_YACC
dnl AC_PATH_PROG( RANLIB, ranlib, /usr/bin/ranlib, dnl AC_PATH_PROG( RANLIB, ranlib, /usr/bin/ranlib,
@@ -864,7 +927,7 @@ AC_HELP_STRING([--disable-debug],[Disable debug options]),
;; ;;
*) AC_MSG_RESULT(yes) *) AC_MSG_RESULT(yes)
CPPFLAGS="$CPPFLAGS -DMALLOCDEBUG" CPPFLAGS="$CPPFLAGS -DCURLDEBUG"
CFLAGS="$CFLAGS -g" CFLAGS="$CFLAGS -g"
if test "$GCC" = "yes"; then if test "$GCC" = "yes"; then
CFLAGS="$CFLAGS -W -Wall -Wwrite-strings -pedantic -Wundef -Wpointer-arith -Wnested-externs" CFLAGS="$CFLAGS -W -Wall -Wwrite-strings -pedantic -Wundef -Wpointer-arith -Wnested-externs"
@@ -907,6 +970,7 @@ AC_CONFIG_FILES([Makefile \
packages/Linux/RPM/curl.spec \ packages/Linux/RPM/curl.spec \
packages/Linux/RPM/curl-ssl.spec \ packages/Linux/RPM/curl-ssl.spec \
packages/Solaris/Makefile \ packages/Solaris/Makefile \
packages/DOS/Makefile \
packages/EPM/curl.list \ packages/EPM/curl.list \
packages/EPM/Makefile \ packages/EPM/Makefile \
curl-config curl-config

View File

@@ -37,7 +37,7 @@
(setq tab-width 8 (setq tab-width 8
indent-tabs-mode nil ; Use spaces. Not tabs. indent-tabs-mode nil ; Use spaces. Not tabs.
comment-column 40 comment-column 40
c-font-lock-extra-types (append '("bool" "CURL" "CURLcode" "ssize_t" "size_t" "socklen_t" "fd_set")) c-font-lock-extra-types (append '("bool" "CURL" "CURLcode" "ssize_t" "size_t" "socklen_t" "fd_set" "time_t"))
) )
;; keybindings for C, C++, and Objective-C. We can put these in ;; keybindings for C, C++, and Objective-C. We can put these in
;; c-mode-base-map because of inheritance ... ;; c-mode-base-map because of inheritance ...

View File

@@ -1,4 +1,4 @@
Updated: February 25, 2003 (http://curl.haxx.se/docs/faq.html) Updated: June 17, 2003 (http://curl.haxx.se/docs/faq.html)
_ _ ____ _ _ _ ____ _
___| | | | _ \| | ___| | | | _ \| |
/ __| | | | |_) | | / __| | | | |_) | |
@@ -97,6 +97,12 @@ FAQ
We spell it cURL or just curl. We pronounce it with an initial k sound: We spell it cURL or just curl. We pronounce it with an initial k sound:
[kurl]. [kurl].
NOTE: there are numerous sub-projects and related projects that also use the
word curl in the project names in various combinations, but you should take
notice that this FAQ is directed at the command-line tool named curl (and
libcurl the library), and may therefore not be valid for other curl
projects.
1.2 What is libcurl? 1.2 What is libcurl?
libcurl is a reliable and portable library which provides you with an easy libcurl is a reliable and portable library which provides you with an easy
@@ -132,11 +138,9 @@ FAQ
better. We 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:
* Curl is to remain a command line tool. If you want GUIs or fancy scripting * Curl -- the command line tool -- is to remain a non-graphical command line
capabilities, you're free to write another tool that uses libcurl and that tool. If you want GUIs or fancy scripting capabilities, you should look
offers this. There's no point in having a single tool that does every for another tool that uses libcurl.
imaginable thing. That's also one of the great advantages of having the
core of curl as a library.
* We 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
@@ -589,9 +593,11 @@ FAQ
4.9. Curl can't authenticate to the server that requires NTLM? 4.9. Curl can't authenticate to the server that requires NTLM?
NTLM is a Microsoft proprietary protocol. Unfortunately, curl does not This is supported in curl 7.10.6 or later. No earlier curl version knows
currently support that. Proprietary formats are evil. You should not use of this magic.
such ones.
NTLM is a Microsoft proprietary protocol. Proprietary formats are evil. You
should not use such ones.
4.10 My HTTP request using HEAD, PUT or DELETE doesn't work! 4.10 My HTTP request using HEAD, PUT or DELETE doesn't work!
@@ -772,6 +778,5 @@ FAQ
discussions and a large amount of people have contributed with source code discussions and a large amount of people have contributed with source code
knowing that this is the license we use. This license puts the restrictions knowing that this is the license we use. This license puts the restrictions
we want on curl/libcurl and it does not spread to other programs or we want on curl/libcurl and it does not spread to other programs or
libraries that use it. The recent dual license modification should make it libraries that use it. It should be possible for everyone to use libcurl or
possible for everyone to use libcurl or curl in their projects, no matter curl in their projects, no matter what license they already have in use.
what license they already have in use.

View File

@@ -17,27 +17,30 @@ 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 (reported built on 29 operating systems) - compiles on win32 (reported builds on 40+ operating systems)
- redirectable stderr - redirectable stderr
- use selected network interface for outgoing traffic - selectable network interface for outgoing traffic
- IPv6 support - IPv6 support
- persistant connections - persistant connections
- socks5 support
- supports user name + password in proxy environment variables
- operations through proxy "tunnel" (using CONNECT)
HTTP HTTP
- HTTP/1.1 compliant - HTTP/1.1 compliant (optionally uses 1.0)
- GET - GET
- PUT - PUT
- HEAD - HEAD
- POST - POST
- multipart POST - multipart formpost (RFC1867-style)
- authentication - authentication (Basic, Digest, NTLM(*1), GSS-Negotiate(*3))
- resume (both GET and PUT) - 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
- cookie get/send fully parsed - cookie get/send fully parsed
- understands the netscape cookie file format - reads/writes the netscape cookie file format
- custom headers (that can replace/remove internally generated headers) - custom headers (replace/remove internally generated headers)
- custom user-agent string - custom user-agent string
- custom referer string - custom referer string
- range - range
@@ -45,12 +48,16 @@ HTTP
- time conditions - time conditions
- via http-proxy - via http-proxy
- retrieve file modification date - retrieve file modification date
- Content-Encoding support for deflate and gzip
- "Transfer-Encoding: chunked" support for "uploads"
HTTPS (*1) HTTPS (*1)
- (all the HTTP features) - (all the HTTP features)
- using certificates - using certificates
- verify server certificate - verify server certificate
- via http-proxy - via http-proxy
- select desired encryption
- force usage of a specific SSL version (SSLv2, SSLv3 or TLSv1)
FTP FTP
- download - download
@@ -90,5 +97,6 @@ GOPHER
FILE FILE
- URL support - URL support
*1 = requires OpenSSL *1 = requires OpenSSL
*2 = requires OpenLDAP *2 = requires OpenLDAP
*3 = requires a GSSAPI-compliant library, such as Heimdal or similar.

View File

@@ -31,6 +31,10 @@ UNIX
If you have checked out the sources from the CVS repository, read the If you have checked out the sources from the CVS repository, read the
CVS-INFO on how to proceed. CVS-INFO on how to proceed.
Get a full listing of all available configure options by invoking it like:
./configure --help
If you want to install curl in a different file hierarchy than /usr/local, If you want to install curl in a different file hierarchy than /usr/local,
you need to specify that already when running configure: you need to specify that already when running configure:
@@ -444,6 +448,7 @@ PORTS
- StrongARM NetBSD 1.4.1 - StrongARM NetBSD 1.4.1
- Ultrix 4.3a - Ultrix 4.3a
- i386 BeOS - i386 BeOS
- i386 DOS
- i386 FreeBSD - i386 FreeBSD
- i386 HURD - i386 HURD
- i386 Linux 1.3, 2.0, 2.2, 2.3, 2.4 - i386 Linux 1.3, 2.0, 2.2, 2.3, 2.4
@@ -454,10 +459,12 @@ PORTS
- i386 Solaris 2.7 - i386 Solaris 2.7
- i386 Windows 95, 98, ME, NT, 2000 - i386 Windows 95, 98, ME, NT, 2000
- i386 QNX 6 - i386 QNX 6
- i486 ncr-sysv4.3.03 (NCR MP-RAS)
- ia64 Linux 2.3.99 - ia64 Linux 2.3.99
- m68k AmigaOS 3 - m68k AmigaOS 3
- m68k Linux - m68k Linux
- m68k OpenBSD - m68k OpenBSD
- m88k dg-dgux5.4R3.00
- s390 Linux - s390 Linux
- XScale/PXA250 Linux 2.4 - XScale/PXA250 Linux 2.4

View File

@@ -3,6 +3,15 @@ join in and help us correct one or more of these! Also be sure to check the
changelog of the current development status, as one or more of these problems changelog of the current development status, as one or more of these problems
may have been fixed since this was written! may have been fixed since this was written!
* LDAP output is garbled. Hardly anyone seems to care about LDAP functionality
in curl/libcurl why this report has been closed and set to be solved later.
If you feel this is something you want fixed, get in touch and we'll start
working.
http://sourceforge.net/tracker/index.php?func=detail&aid=735752&group_id=976&atid=100976
* IPv6 support on AIX 4.3.3 doesn't work due to a missing sockaddr_storage
struct. It has been reported to work on AIX 5.1 though.
* Running 'make test' on Mac OS X gives 4 errors. This seems to be related * Running 'make test' on Mac OS X gives 4 errors. This seems to be related
to some kind of libtool problem: to some kind of libtool problem:
http://curl.haxx.se/mail/archive-2002-03/0029.html and http://curl.haxx.se/mail/archive-2002-03/0029.html and

View File

@@ -11,7 +11,7 @@ SIMPLE USAGE
curl http://www.netscape.com/ curl http://www.netscape.com/
Get the root README file from funet's ftp-server: Get the README file the user's home directory at funet's ftp-server:
curl ftp://ftp.funet.fi/README curl ftp://ftp.funet.fi/README
@@ -19,7 +19,7 @@ SIMPLE USAGE
curl http://www.weirdserver.com:8000/ curl http://www.weirdserver.com:8000/
Get a list of the root directory of an FTP site: Get a list of a directory of an FTP site:
curl ftp://cool.haxx.se/ curl ftp://cool.haxx.se/

View File

@@ -19,7 +19,7 @@ PDFPAGES = \
SUBDIRS = examples libcurl SUBDIRS = examples libcurl
EXTRA_DIST = MANUAL BUGS CONTRIBUTE FAQ FEATURES INTERNALS \ EXTRA_DIST = MANUAL BUGS CONTRIBUTE FAQ FEATURES INTERNALS SSLCERTS \
README.win32 RESOURCES TODO TheArtOfHttpScripting THANKS \ README.win32 RESOURCES TODO TheArtOfHttpScripting THANKS \
VERSIONS KNOWN_BUGS BINDINGS $(man_MANS) $(HTMLPAGES) \ VERSIONS KNOWN_BUGS BINDINGS $(man_MANS) $(HTMLPAGES) \
HISTORY INSTALL libcurl-the-guide $(PDFPAGES) HISTORY INSTALL libcurl-the-guide $(PDFPAGES)

View File

@@ -13,8 +13,8 @@ README.win32
are win32-based. are win32-based.
The unix-style man pages are tricky to read on windows, so therefore are all The unix-style man pages are tricky to read on windows, so therefore are all
those pages also converted to HTML and those are also included in the those pages converted to HTML as well as pdf, and included in the release
release archives. archives.
The main curl.1 man page is also "built-in" in the command line tool. Use a The main curl.1 man page is also "built-in" in the command line tool. Use a
command line similar to this in order to extract a separate text file: command line similar to this in order to extract a separate text file:

View File

@@ -87,3 +87,7 @@ that have contributed with non-trivial parts:
- Miklos Nemeth <mnemeth@kfkisystems.com> - Miklos Nemeth <mnemeth@kfkisystems.com>
- Kevin Roth <kproth@users.sourceforge.net> - Kevin Roth <kproth@users.sourceforge.net>
- Ralph Mitchell <rmitchell@eds.com> - Ralph Mitchell <rmitchell@eds.com>
- Dan Fandrich <dan@coneharvesters.com>
- Jean-Philippe Barrette-LaPierre <jpb@rrette.com>
- Richard Bramante <RBramante@on.com>
- Daniel Kouril <kouril@ics.muni.cz>

View File

@@ -16,7 +16,7 @@ TODO
know what cookies that are received. Pushing interface that calls a know what cookies that are received. Pushing interface that calls a
callback on each received cookie? Querying interface that asks about callback on each received cookie? Querying interface that asks about
existing cookies? We probably need both. Enable applications to modify existing cookies? We probably need both. Enable applications to modify
existing cookies as well. existing cookies as well. http://curl.haxx.se/dev/COOKIES
* Make content encoding/decoding internally be made using a filter system. * Make content encoding/decoding internally be made using a filter system.
@@ -50,10 +50,6 @@ TODO
requested. That is, the download should not even begin but be aborted requested. That is, the download should not even begin but be aborted
immediately. immediately.
* Allow the http_proxy (and other) environment variables to contain user and
password as well in the style: http://proxyuser:proxypasswd@proxy:port
Berend Reitsma suggested.
LIBCURL - multi interface LIBCURL - multi interface
* Make sure we don't ever loop because of non-blocking sockets return * Make sure we don't ever loop because of non-blocking sockets return
@@ -73,52 +69,24 @@ TODO
FTP FTP
* FTP ASCII upload does not follow RFC959 section 3.1.1.1: "The sender * Make CURLOPT_FTPPORT support an additional port number on the IP/if/name,
converts the data from an internal character representation to the standard like "blabla:[port]" or possibly even "blabla:[portfirst]-[portsecond]".
8-bit NVT-ASCII representation (see the Telnet specification). The
receiver will convert the data from the standard form to his own internal * FTP ASCII transfers do not follow RFC959. They don't convert the data
form." accordingly.
* Since USERPWD always override the user and password specified in URLs, we * Since USERPWD always override the user and password specified in URLs, we
might need another way to specify user+password for anonymous ftp logins. might need another way to specify user+password for anonymous ftp logins.
* An option to only download remote FTP files if they're newer than the local
one is a good idea, and it would fit right into the same syntax as the
already working http dito works. It of course requires that 'MDTM' works,
and it isn't a standard FTP command.
* Add FTPS support with SSL for the data connection too. This should be made * Add FTPS support with SSL for the data connection too. This should be made
according to the specs written in draft-murray-auth-ftp-ssl-08.txt, according to the specs written in draft-murray-auth-ftp-ssl-11.txt,
"Securing FTP with TLS" "Securing FTP with TLS", valid until September 27th 2003.
http://curl.haxx.se/rfc/draft-murray-auth-ftp-ssl-11.txt
HTTP HTTP
* If the "body" of the POST is < MSS it really aught to be sent along with * Digest, NTLM and GSS-Negotiate support for HTTP proxies. They all work
the headers. More generally, if the last chunk of the POST body is < MSS, on direct-connections to the server.
it should be sent with the previous chunk (which may be the POST headers).
So long as any one send is larger than MSS (or there is only one send when
< MSS :), the Nagle Algorithm will not be a problem on any stack where
Nagle is implemented correctly. (pointed out by Rick Jones)
* Authentication: NTLM. Support for that MS crap called NTLM
authentication. MS proxies and servers sometime require that. Since that
protocol is a proprietary one, it involves reverse engineering and network
sniffing. This should however be a library-based functionality. There are a
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
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" A valid test page seem
to exist at: http://hopf.math.nwu.edu/testpage/digest/ And some friendly
person's server source code is available at
http://hopf.math.nwu.edu/digestauth/index.html 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 a lot better
authentication method than the more common "Basic". Basic sends the
password in cleartext over the network, this "Digest" method uses a
challange-response protocol which increases security quite a lot.
* Pipelining. Sending multiple requests before the previous one(s) are done. * Pipelining. Sending multiple requests before the previous one(s) are done.
This could possibly be implemented using the multi interface to queue This could possibly be implemented using the multi interface to queue

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 "14 Feb 2003" "Curl 7.10.3" "Curl Manual" .TH curl 1 "18 June 2003" "Curl 7.10.6" "Curl Manual"
.SH NAME .SH NAME
curl \- transfer a URL curl \- transfer a URL
.SH SYNOPSIS .SH SYNOPSIS
@@ -10,14 +10,18 @@ curl \- transfer a URL
.I [URL...] .I [URL...]
.SH DESCRIPTION .SH DESCRIPTION
.B curl .B curl
is a client to get documents/files from or send documents to a server, using is a tool to transfer data from or to a server, using one of the supported
any of the supported protocols (HTTP, HTTPS, FTP, GOPHER, DICT, TELNET, LDAP protocols (HTTP, HTTPS, FTP, FTPS, GOPHER, DICT, TELNET, LDAP or FILE). The
or FILE). The command is designed to work without user interaction or any kind command is designed to work without user interaction.
of interactivity.
curl offers a busload of useful tricks like proxy support, user curl offers a busload of useful tricks like proxy support, user
authentication, ftp upload, HTTP post, SSL (https:) connections, cookies, file authentication, ftp upload, HTTP post, SSL (https:) connections, cookies, file
transfer resume and more. transfer resume and more. As you will see below, the amount of features will
make your head spin!
curl is powered by libcurl for all transfer-related features. See
.BR libcurl (3)
for details.
.SH URL .SH URL
The URL syntax is protocol dependent. You'll find a detailed description in The URL syntax is protocol dependent. You'll find a detailed description in
RFC 2396. RFC 2396.
@@ -48,10 +52,8 @@ specified on a single command line and cannot be used between separate curl
invokes. invokes.
.SH OPTIONS .SH OPTIONS
.IP "-a/--append" .IP "-a/--append"
(FTP) (FTP) When used in an FTP upload, this will tell curl to append to the target
When used in a ftp upload, this will tell curl to append to the target file instead of overwriting it. If the file doesn't exist, it will be created.
file instead of overwriting it. If the file doesn't exist, it will
be created.
If this option is used twice, the second one will disable append mode again. If this option is used twice, the second one will disable append mode again.
.IP "-A/--user-agent <agent string>" .IP "-A/--user-agent <agent string>"
@@ -63,6 +65,16 @@ surround the string with single quote marks. This can also be set with the
If this option is set more than once, the last one will be the one that's If this option is set more than once, the last one will be the one that's
used. used.
.IP "--anyauth"
(HTTP) Tells curl to figure out authentication method by itself, and use the
most secure one the remote site claims it supports. This is done by first
doing a request and checking the response-headers, thus inducing an extra
network round-trip. This is used instead of setting a specific authentication
method, which you can do with \fI--digest\fP, \fI--ntlm\fP, and
\fI--negotiate\fP. (Added in 7.10.6)
If this option is used several times, the following occurrences make no
difference.
.IP "-b/--cookie <name=data>" .IP "-b/--cookie <name=data>"
(HTTP) (HTTP)
Pass the data to the HTTP server as a cookie. It is supposedly the Pass the data to the HTTP server as a cookie. It is supposedly the
@@ -90,12 +102,26 @@ 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 "--basic"
(HTTP) Tells curl to use HTTP Basic authentication. This is the default and
this option is usually pointless, unless you use it to override a previously
set option that sets a different authentication method (such as \fI--ntlm\fP,
\fI--digest\fP and \fI--negotiate\fP). (Added in 7.10.6)
If this option is used several times, the following occurrences make no
difference.
.IP "--ciphers <list of ciphers>" .IP "--ciphers <list of ciphers>"
(SSL) Specifies which ciphers to use in the connection. The list of ciphers (SSL) Specifies which ciphers to use in the connection. The list of ciphers
must be using valid ciphers. Read up on SSL cipher list details on this URL: must be using valid ciphers. Read up on SSL cipher list details on this URL:
.I http://www.openssl.org/docs/apps/ciphers.html (Option added in curl 7.9) .I http://www.openssl.org/docs/apps/ciphers.html (Option added in curl 7.9)
If this option is used several times, the last one will override the others. If this option is used several times, the last one will override the others.
.IP "--compressed"
(HTTP) Request a compressed response using one of the algorithms libcurl
supports, and return the uncompressed document. If this option is used and
the server sends an unsupported encoding, Curl will report an error.
If this option is used several times, each occurrence will toggle it on/off.
.IP "--connect-timeout <seconds>" .IP "--connect-timeout <seconds>"
Maximum time in seconds that you allow the connection to the server to take. Maximum time in seconds that you allow the connection to the server to take.
This only limits the connection phase, once curl has connected this option is This only limits the connection phase, once curl has connected this option is
@@ -110,6 +136,12 @@ no file will be written. The file will be written using the Netscape cookie
file format. If you set the file name to a single dash, "-", the cookies will file format. If you set the file name to a single dash, "-", the cookies will
be written to stdout. (Option added in curl 7.9) be written to stdout. (Option added in curl 7.9)
.B NOTE
If the cookie jar can't be created or written to, the whole curl operation
won't fail or even report an error clearly. Using -v will get a warning
displayed, but that is the only visible feedback you get about this possibly
lethal situation.
If this option is used several times, the last specfied file name will be If this option is used several times, the last specfied file name will be
used. used.
.IP "-C/--continue-at <offset>" .IP "-C/--continue-at <offset>"
@@ -122,7 +154,7 @@ Use "-C -" to tell curl to automatically find out where/how to resume the
transfer. It then uses the given output/input files to figure that out. transfer. It then uses the given output/input files to figure that out.
If this option is used several times, the last one will be used. If this option is used several times, the last one will be used.
.IP "---create-dirs" .IP "--create-dirs"
When used in conjunction with the -o option, curl will create the necessary When used in conjunction with the -o option, curl will create the necessary
local directory hierarchy as needed. local directory hierarchy as needed.
.IP "--crlf" .IP "--crlf"
@@ -166,9 +198,27 @@ want to post a binary file without the strip-newlines feature of the
If this option is used several times, the ones following the first will If this option is used several times, the ones following the first will
append data. append data.
.IP "--digest"
(HTTP) Enables HTTP Digest authentication. This is a authentication that
prevents the password from being sent over the wire in clear text. Use this in
combination with the normal -u/--user option to set user name and
password. See also \fI--ntlm\fP, \fP--negotiate\fI and \fI--anyauth\fP for
related options. (Added in curl 7.10.6)
If this option is used several times, the following occurrences make no
difference.
.IP "--disable-eprt"
(FTP) Tell curl to disable the use of the EPRT and LPRT commands when doing
active FTP transfers. Curl will normally always first attempt to use EPRT,
then LPRT before using PORT, but with this option, it will use PORT right
away. EPRT and LPRT are extensions to the original FTP protocol, may not work
on all servers but enable more functionality in a better way than the
traditional PORT command. (Aded in 7.10.5)
If this option is used several times, each occurrence will toggle this on/off.
.IP "--disable-epsv" .IP "--disable-epsv"
(FTP) Tell curl to disable the use of the EPSV command when doing passive FTP (FTP) Tell curl to disable the use of the EPSV command when doing passive FTP
downloads. Curl will normally always first attempt to use EPSV before PASV, transfers. Curl will normally always first attempt to use EPSV before PASV,
but with this option, it will not try using EPSV. but with this option, it will not try using EPSV.
If this option is used several times, each occurrence will toggle this on/off. If this option is used several times, each occurrence will toggle this on/off.
@@ -256,12 +306,18 @@ Example, to send your password file to the server, where
\&'password' is the name of the form-field to which /etc/passwd will be the \&'password' is the name of the form-field to which /etc/passwd will be the
input: input:
.B curl \fBcurl\fP -F password=@/etc/passwd www.mypasswords.com
-F password=@/etc/passwd www.mypasswords.com
To read the file's content from stdin insted of a file, use - where the file To read the file's content from stdin insted of a file, use - where the file
name should've been. This goes for both @ and < constructs. name should've been. This goes for both @ and < constructs.
You can also tell curl what Content-Type to use for the file upload part, by
using 'type=', in a manner similar to:
\fBcurl\fP -F "web=@index.html;type=text/html" url.com
See further examples and details in the MANUAL.
This option can be used multiple times. This option can be used multiple times.
.IP "-g/--globoff" .IP "-g/--globoff"
This option switches off the "URL globbing parser". When you set this option, This option switches off the "URL globbing parser". When you set this option,
@@ -381,9 +437,18 @@ If this option is used twice, the second will again disable list only.
(HTTP/HTTPS) If the server reports that the requested page has a different (HTTP/HTTPS) If the server reports that the requested page has a different
location (indicated with the header line Location:) this flag will let curl location (indicated with the header line Location:) this flag will let curl
attempt to reattempt the get on the new place. If used together with -i or -I, attempt to reattempt the get on the new place. If used together with -i or -I,
headers from all requested pages will be shown. If this flag is used when headers from all requested pages will be shown. If authentication is used,
making a HTTP POST, curl will automatically switch to GET after the initial curl will only send its credentials to the initial host, so if a redirect
POST has been done. takes curl to a different host, it won't intercept the user+password. See also
\fI--location-trusted\fP on how to change this.
If this option is used twice, the second will again disable location following.
.IP "--location-trusted"
(HTTP/HTTPS) Like \fI--location\fP, but will allow sending the name + password
to all hosts that the site may redirect to. This may or may not introduce a
security breach if the site redirects you do a site to which you'll send your
authentication info (which is plaintext in the case of HTTP Basic
authentication).
If this option is used twice, the second will again disable location following. If this option is used twice, the second will again disable location following.
.IP "-m/--max-time <seconds>" .IP "-m/--max-time <seconds>"
@@ -417,6 +482,19 @@ to allow curl to ftp to the machine host.domain.com with user name
.B "machine host.domain.com login myself password secret" .B "machine host.domain.com login myself password secret"
If this option is used twice, the second will again disable netrc usage. If this option is used twice, the second will again disable netrc usage.
.IP "--negotiate"
(HTTP) Enables GSS-Negotiate authentication. The GSS-Negotiate method was
designed by Microsoft and is used in their web aplications. It is primarily
meant as a support for Kerberos5 authentication but may be also used along
with another authentication methods. For more information see IETF draft
draft-brezak-spnego-http-04.txt. (Added in 7.10.6)
\fBNOTE\fP that this option requiures that the library was built with GSSAPI
support. This is not very common. Use \fIcurl --version\fP to see if your
version supports GSS-Negotiate.
If this option is used several times, the following occurrences make no
difference.
.IP "-N/--no-buffer" .IP "-N/--no-buffer"
Disables the buffering of the output stream. In normal work situations, curl Disables the buffering of the output stream. In normal work situations, curl
will use a standard buffered output stream that will have the effect that it will use a standard buffered output stream that will have the effect that it
@@ -424,6 +502,19 @@ will output the data in chunks, not necessarily exactly when the data arrives.
Using this option will disable that buffering. Using this option will disable that buffering.
If this option is used twice, the second will again switch on buffering. If this option is used twice, the second will again switch on buffering.
.IP "--ntlm"
(HTTP) Enables NTLM authentication. The NTLM authentication method was
designed by Microsoft and is used by IIS web servers. It is a proprietary
protocol, reversed engineered by clever people and implemented in curl based
on their efforts. This kind of behavior should not be endorsed, you should
encourage everyone who uses NTLM to switch to a public and documented
authentication method instead. Such as Digest. (Added in 7.10.6)
\fBNOTE\fP that this option requiures that the library was built with SSL
support. Use \fIcurl --version\fP to see if your version supports NTLM.
If this option is used several times, the following occurrences make no
difference.
.IP "-o/--output <file>" .IP "-o/--output <file>"
Write output to <file> instead of stdout. If you are using {} or [] to fetch Write output to <file> instead of stdout. If you are using {} or [] to fetch
multiple documents, you can use '#' followed by a number in the <file> multiple documents, you can use '#' followed by a number in the <file>
@@ -440,8 +531,8 @@ You may use this option as many times as you have number of URLs.
See also the --create-dirs option to create the local directories dynamically. See also the --create-dirs option to create the local directories dynamically.
.IP "-O/--remote-name" .IP "-O/--remote-name"
Write output to a local file named like the remote file we get. (Only Write output to a local file named like the remote file we get. (Only the file
the file part of the remote file is used, the path is cut off.) part of the remote file is used, the path is cut off.)
You may use this option as many times as you have number of URLs. You may use this option as many times as you have number of URLs.
.IP "-p/--proxytunnel" .IP "-p/--proxytunnel"
@@ -580,7 +671,7 @@ descriptive information, to the given output file. Use "-" as filename to have
the output sent to stdout. the output sent to stdout.
If this option is used several times, the last one will be used. (Added in If this option is used several times, the last one will be used. (Added in
curl 7.9.7) 7.9.7)
.IP "--trace-ascii <file>" .IP "--trace-ascii <file>"
Enables a full trace dump of all incoming and outgoing data, including Enables a full trace dump of all incoming and outgoing data, including
descriptive information, to the given output file. Use "-" as filename to have descriptive information, to the given output file. Use "-" as filename to have
@@ -591,12 +682,15 @@ the ASCII part of the dump. It makes smaller output that might be easier to
read for untrained humans. read for untrained humans.
If this option is used several times, the last one will be used. (Added in If this option is used several times, the last one will be used. (Added in
curl 7.9.7) 7.9.7)
.IP "-u/--user <user:password>" .IP "-u/--user <user:password>"
Specify user and password to use when fetching. Read the MANUAL for detailed Specify user and password to use when fetching. Read the MANUAL for detailed
examples of how to use this. If no password is specified, curl will ask for it examples of how to use this. If no password is specified, curl will ask for it
interactively. interactively.
You can also use the --digest option to enable Digest authentication when
communicating with HTTP 1.1 servers.
If this option is used several times, the last one will be used. If this option is used several times, the last one will be used.
.IP "-U/--proxy-user <user:password>" .IP "-U/--proxy-user <user:password>"
Specify user and password to use for Proxy authentication. If no Specify user and password to use for Proxy authentication. If no
@@ -626,8 +720,17 @@ If you think this option still doesn't give you enough details, consider using
If this option is used twice, the second will again disable verbose. If this option is used twice, the second will again disable verbose.
.IP "-V/--version" .IP "-V/--version"
Displays the full version of curl, libcurl and other 3rd party libraries Displays information about curl and the libcurl version it uses.
linked with the executable.
The first line includes the full version of curl, libcurl and other 3rd party
libraries linked with the executable.
The second line (starts with "Protocols:") shows all protocols that libcurl
reports to support.
The third line (starts with "Features:") shows specific features libcurl
reports to offer.
.IP "-w/--write-out <format>" .IP "-w/--write-out <format>"
Defines what to display after a completed and successful operation. The format Defines what to display after a completed and successful operation. The format
is a string that may contain plain text mixed with any number of variables. The is a string that may contain plain text mixed with any number of variables. The

View File

@@ -9,7 +9,7 @@ EXTRA_DIST = README curlgtk.c sepheaders.c simple.c postit2.c \
multithread.c getinmemory.c ftpupload.c httpput.c \ multithread.c getinmemory.c ftpupload.c httpput.c \
simplessl.c ftpgetresp.c http-post.c post-callback.c \ simplessl.c ftpgetresp.c http-post.c post-callback.c \
multi-app.c multi-double.c multi-single.c multi-post.c \ multi-app.c multi-double.c multi-single.c multi-post.c \
fopen.c simplepost.c fopen.c simplepost.c makefile.dj
all: all:
@echo "done" @echo "done"

31
docs/examples/makefile.dj Normal file
View File

@@ -0,0 +1,31 @@
#
# Adapted for djgpp / Watt-32 / DOS by
# Gisle Vanem <giva@bgnett.no>
#
include ../../packages/DOS/common.dj
CFLAGS += -I../../include
LIBS = ../../lib/libcurl.a
ifeq ($(USE_SSL),1)
LIBS += $(OPENSSL_ROOT)/lib/libssl.a $(OPENSSL_ROOT)/lib/libcrypt.a
endif
LIBS += $(WATT32_ROOT)/lib/libwatt.a $(ZLIB_ROOT)/libz.a
PROGRAMS = fopen.exe ftpget.exe ftpgetre.exe ftpuploa.exe getinmem.exe \
http-pos.exe httpput.exe multi-ap.exe multi-do.exe \
multi-po.exe multi-si.exe persista.exe post-cal.exe \
postit2.exe sepheade.exe simple.exe simpless.exe
all: $(PROGRAMS)
.c.exe:
$(CC) $(CFLAGS) -o $@ $^ $(LIBS)
@echo
clean:
rm -f $(PROGRAMS)

View File

@@ -40,7 +40,7 @@ int main(int argc, char **argv)
FILE *headerfile; FILE *headerfile;
const char *pCertFile = "testcert.pem"; const char *pCertFile = "testcert.pem";
const char *pCACertFile="cacert.pem" const char *pCACertFile="cacert.pem";
const char *pKeyName; const char *pKeyName;
const char *pKeyType; const char *pKeyType;

View File

@@ -78,7 +78,8 @@ uploaded.
.TP .TP
.B CURLINFO_SIZE_DOWNLOAD .B CURLINFO_SIZE_DOWNLOAD
Pass a pointer to a double to receive the total amount of bytes that were Pass a pointer to a double to receive the total amount of bytes that were
downloaded. downloaded. The amount is only for the latest transfer and will be reset again
for each new transfer.
.TP .TP
.B CURLINFO_SPEED_DOWNLOAD .B CURLINFO_SPEED_DOWNLOAD
Pass a pointer to a double to receive the average download speed that curl Pass a pointer to a double to receive the average download speed that curl

View File

@@ -1,7 +1,7 @@
.\" nroff -man [file] .\" nroff -man [file]
.\" $Id$ .\" $Id$
.\" .\"
.TH curl_easy_setopt 3 "3 Dec 2002" "libcurl 7.10.3" "libcurl Manual" .TH curl_easy_setopt 3 "10 Jun 2003" "libcurl 7.10.6" "libcurl Manual"
.SH NAME .SH NAME
curl_easy_setopt - set options for a curl easy handle curl_easy_setopt - set options for a curl easy handle
.SH SYNOPSIS .SH SYNOPSIS
@@ -272,7 +272,7 @@ The main point of this would be that the write callback gets called more often
and with smaller chunks. This is just treated as a request, not an order. You and with smaller chunks. This is just treated as a request, not an order. You
cannot be guaranteed to actually get the given size. (Added in 7.10) cannot be guaranteed to actually get the given size. (Added in 7.10)
.PP .PP
.SH NAMES and PASSWORDS OPTIONS .SH NAMES and PASSWORDS OPTIONS (Authentication)
.TP 0.4i .TP 0.4i
.B CURLOPT_NETRC .B CURLOPT_NETRC
This parameter controls the preference of libcurl between using user names and This parameter controls the preference of libcurl between using user names and
@@ -322,23 +322,76 @@ prompt function.
When using HTTP and CURLOPT_FOLLOWLOCATION, libcurl might perform several When using HTTP and CURLOPT_FOLLOWLOCATION, libcurl might perform several
requests to possibly different hosts. libcurl will only send this user and requests to possibly different hosts. libcurl will only send this user and
password information to hosts using the initial host name, so if libcurl password information to hosts using the initial host name (unless
follows locations to other hosts it will not send the user and password to CURLOPT_UNRESTRICTED_AUTH is set), so if libcurl follows locations to other
those. This is enforced to prevent accidental information leakage. hosts it will not send the user and password to those. This is enforced to
prevent accidental information leakage.
.TP .TP
.B CURLOPT_PROXYUSERPWD .B CURLOPT_PROXYUSERPWD
Pass a char * as parameter, which should be [user name]:[password] to use for Pass a char * as parameter, which should be [user name]:[password] to use for
the connection to the HTTP proxy. If the password is left out, you will be the connection to the HTTP proxy. If the password is left out, you will be
prompted for it. \fICURLOPT_PASSWDFUNCTION\fP can be used to set your own prompted for it. \fICURLOPT_PASSWDFUNCTION\fP can be used to set your own
prompt function. prompt function.
.TP
.B CURLOPT_HTTPAUTH
Pass a long as parameter, which is set to a bitmask, to tell libcurl what
authentication method(s) you want it to use. The available bits are listed
below. If more than one bit is set, libcurl will first query the site to see
what authentication methods it supports and then pick the best one you allow
it to use. Note that for some methods, this will induce an extra network
round-trip. Set the actual name and password with the \fICURLOPT_USERPWD\fP
option. (Added in 7.10.6)
.RS
.TP 5
.B CURLAUTH_BASIC
HTTP Basic authentication. This is the default choice, and the only method
that is in wide-spread use and supported virtually everywhere. This is sending
the user name and password over the network in plain text, easily captured by
others.
.TP
.B CURLAUTH_DIGEST
HTTP Digest authentication. Digest authentication is defined in RFC2617 and
is a more secure way to do authentication over public networks than the
regular old-fashioned Basic method.
.TP
.B CURLAUTH_GSSNEGOTIATE
HTTP GSS-Negotiate authentication. The GSS-Negotiate method was designed by
Microsoft and is used in their web aplications. It is primarily meant as a
support for Kerberos5 authentication but may be also used along with another
authentication methods. For more information see IETF draft
draft-brezak-spnego-http-04.txt.
.TP
.B CURLAUTH_NTLM
HTTP NTLM authentication. A proprietary protocol invented and used by
Microsoft. It uses a challenge-response and hash concept similar to Digest to
prevent the password from being evesdropped.
.TP
.B CURLAUTH_ANY
This is a convenience macro that sets all bits and thus makes libcurl pick any
it finds suitable. libcurl will automaticly select the one it finds most
secure.
.TP
.B CURLAUTH_ANYSAFE
This is a convenience macro that sets all bits except Basic and thus makes
libcurl pick any it finds suitable. libcurl will automaticly select the one it
finds most secure.
.RE
.PP .PP
.SH HTTP OPTIONS .SH HTTP OPTIONS
.TP 0.4i .TP 0.4i
.B CURLOPT_ENCODING .B CURLOPT_ENCODING
Two encodings are supported \fIdentity\fP, which does nothing, and Sets the contents of the Accept-Encoding: header sent in an HTTP
\fIdeflate\fP to request the server to compress its reponse using the request, and enables decoding of a response when a Content-Encoding:
zlib algorithm. This is not an order, the server may or may not do it. header is received. Three encodings are supported: \fIidentity\fP,
See the special file lib/README.encoding for details. which does nothing, \fIdeflate\fP which requests the server to
compress its response using the zlib algorithm, and \fIgzip\fP which
requests the gzip algorithm. If a zero-length string is set, then an
Accept-Encoding: header containing all supported encodings is sent.
This is a request, not an order; the server may or may not do it. This
option must be set (to any non-NULL value) or else any unsolicited
encoding done by the server is ignored. See the special file
lib/README.encoding for details.
.TP .TP
.B CURLOPT_FOLLOWLOCATION .B CURLOPT_FOLLOWLOCATION
A non-zero parameter tells the library to follow any Location: header that the A non-zero parameter tells the library to follow any Location: header that the
@@ -429,6 +482,10 @@ curl adds CRLF after each header item. Failure to comply with this will
result in strange bugs because the server will most likely ignore part result in strange bugs because the server will most likely ignore part
of the headers you specified. of the headers you specified.
The first line in a request (usually containing a GET or POST) is not a header
and cannot be replaced using this option. Only the lines following the
request-line are headers.
\fBNOTE:\fPThe most commonly replaced headers have "shortcuts" in the options \fBNOTE:\fPThe most commonly replaced headers have "shortcuts" in the options
CURLOPT_COOKIE, CURLOPT_USERAGENT and CURLOPT_REFERER. CURLOPT_COOKIE, CURLOPT_USERAGENT and CURLOPT_REFERER.
.TP .TP
@@ -478,6 +535,13 @@ is called. If no cookies are known, no file will be created. Specify "-" to
instead have the cookies written to stdout. Using this option also enables instead have the cookies written to stdout. Using this option also enables
cookies for this session, so if you for example follow a location it will make cookies for this session, so if you for example follow a location it will make
matching cookies get sent accordingly. (Added in 7.9) matching cookies get sent accordingly. (Added in 7.9)
.B NOTE
If the cookie jar file can't be created or written to (when the
curl_easy_cleanup() is called), libcurl will not and cannot report an error
for this. Using CURLOPT_VERBOSE or CURLOPT_DEBUGFUNCTION will get a warning to
display, but that is the only visible feedback you get about this possibly
lethal situation.
.TP .TP
.B CURLOPT_TIMECONDITION .B CURLOPT_TIMECONDITION
Pass a long as parameter. This defines how the CURLOPT_TIMEVALUE time value is Pass a long as parameter. This defines how the CURLOPT_TIMEVALUE time value is
@@ -560,6 +624,13 @@ and symbolic links.
A non-zero parameter tells the library to append to the remote file instead of A non-zero parameter tells the library to append to the remote file instead of
overwrite it. This is only useful when uploading to a ftp site. overwrite it. This is only useful when uploading to a ftp site.
.TP .TP
.B CURLOPT_FTP_USE_EPRT
Pass a long. If the value is non-zero, it tells curl to use the EPRT (and
LPRT) command when doing active FTP downloads (which is enabled by
CURLOPT_FTPPORT). Using EPRT means that it will first attempt to use EPRT and
then LPRT before using PORT, but if you pass FALSE (zero) to this option, it
will not try using EPRT or LPRT, only plain PORT. (Added in 7.10.5)
.TP
.B CURLOPT_FTP_USE_EPSV .B CURLOPT_FTP_USE_EPSV
Pass a long. If the value is non-zero, it tells curl to use the EPSV command Pass a long. If the value is non-zero, it tells curl to use the EPSV command
when doing passive FTP downloads (which it always does by default). Using EPSV when doing passive FTP downloads (which it always does by default). Using EPSV
@@ -593,9 +664,18 @@ want the transfer to start from.
.TP .TP
.B CURLOPT_CUSTOMREQUEST .B CURLOPT_CUSTOMREQUEST
Pass a pointer to a zero terminated string as parameter. It will be user Pass a pointer to a zero terminated string as parameter. It will be user
instead of GET or HEAD when doing the HTTP request. This is useful for doing instead of GET or HEAD when doing a HTTP request, or instead of LIST or NLST
DELETE or other more or less obscure HTTP requests. Don't do this at will, when doing an ftp directory listing. This is useful for doing DELETE or other
make sure your server supports the command first. more or less obscure HTTP requests. Don't do this at will, make sure your
server supports the command first.
NOTE: many people have wrongly used this option to replace the entire request
with their own, including multiple headers and POST contents. While that might
work in many cases, it will cause libcurl to send invalid requests and it
could possibly confuse the remote server badly. Use \fICURLOPT_POST\fP and
\fICURLOPT_POSTFIELDS\fP to set POST data. Use \fICURLOPT_HTTPHEADER\fP to
replace or extend the set of headers sent by libcurl. Use
\fICURLOPT_HTTP_VERSION\fP to change HTTP version.
.TP .TP
.B CURLOPT_FILETIME .B CURLOPT_FILETIME
Pass a long. If it is a non-zero value, libcurl will attempt to get the Pass a long. If it is a non-zero value, libcurl will attempt to get the

View File

@@ -2,7 +2,7 @@
.\" nroff -man [file] .\" nroff -man [file]
.\" $Id$ .\" $Id$
.\" .\"
.TH curl_slist_append 3 "21 Feb 2003" "libcurl 7.10.4" "libcurl Manual" .TH curl_slist_append 3 "19 Jun 2003" "libcurl 7.10.4" "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
@@ -15,7 +15,8 @@ curl_slist_append - add a string to an slist
curl_slist_append() appends a specified string to a linked list of curl_slist_append() appends a specified string to a linked list of
strings. The existing \fIlist\fP should be passed as the first argument while strings. The existing \fIlist\fP should be passed as the first argument while
the new list is returned from this function. The specified \fIstring\fP has the new list is returned from this function. The specified \fIstring\fP has
been appended when this function returns. been appended when this function returns. curl_slist_append() copies the
string.
The list should be freed again (after usage) with \fBcurl_slist_free_all()\fP. The list should be freed again (after usage) with \fBcurl_slist_free_all()\fP.
.SH RETURN VALUE .SH RETURN VALUE

View File

@@ -2,7 +2,7 @@
.\" nroff -man [file] .\" nroff -man [file]
.\" $Id$ .\" $Id$
.\" .\"
.TH curl_version_info 3 "30 Sep 2002" "libcurl 7.10" "libcurl Manual" .TH curl_version_info 3 "17 Jun 2003" "libcurl 7.10.6" "libcurl Manual"
.SH NAME .SH NAME
curl_version_info - returns run-time libcurl version info curl_version_info - returns run-time libcurl version info
.SH SYNOPSIS .SH SYNOPSIS
@@ -69,6 +69,16 @@ supports SSL (HTTPS/FTPS)
.TP .TP
.B CURL_VERSION_LIBZ .B CURL_VERSION_LIBZ
supports HTTP deflate using libz supports HTTP deflate using libz
.TP
.B CURL_VERSION_NTLM
supports HTTP NTLM (added in 7.10.6)
.TP
.B CURL_VERSION_GSSNEGOTIATE
supports HTTP GSS-Negotiate (added in 7.10.6)
.TP
.B CURL_VERSION_DEBUG
libcurl was built with extra debug capabilities built-in. This is mainly of
interest for libcurl hackers. (added in 7.10.6)
.PP .PP
\fIssl_version\fP is an ascii string for the OpenSSL version used. If libcurl \fIssl_version\fP is an ascii string for the OpenSSL version used. If libcurl
has no SSL support, this is NULL. has no SSL support, this is NULL.
@@ -83,8 +93,6 @@ libcurl has no libz support, this is NULL.
names protocols that libcurl supports (using lowercase letters). The protocol names protocols that libcurl supports (using lowercase letters). The protocol
names are the same as would be used in URLs. The array is terminated by a NULL names are the same as would be used in URLs. The array is terminated by a NULL
entry. entry.
.SH RETURN VALUE .SH RETURN VALUE
A pointer to a curl_version_info_data struct. A pointer to a curl_version_info_data struct.
.SH "SEE ALSO" .SH "SEE ALSO"

View File

@@ -13,3 +13,26 @@ of environment. You should include files from here using...
... style and point the compiler's include path to the directory holding the ... style and point the compiler's include path to the directory holding the
curl subdirectory. It makes it more likely to survive future modifications. curl subdirectory. It makes it more likely to survive future modifications.
NOTE FOR LIBCURL HACKERS
All the include files in this tree are written and intended to be installed on
a system that may serve multiple platforms and multiple applications, all
using libcurl (possibly even different libcurl installations using different
versions). Therefore, all header files in here must obey these rules:
* They cannot depend on or use configure-generated results from libcurl's or
curl's directories. Other applications may not run configure as (lib)curl
does, and using platform dependent info here may break other platforms.
* We cannot assume anything else but very basic compiler features being
present. While libcurl requires an ANSI C compiler to build, some of the
earlier ANSI compilers clearly can't deal with some preprocessor operators.
* Newlines must remain unix-style for older compilers' sake.
* Comments must be written in the old-style /* unnested C-fashion */
To figure out how to do good and portable checks for features, operating
systems or specific hardwarare, a very good resource is Bjorn Reese's
collection at http://predef.sf.net/

View File

@@ -23,23 +23,39 @@
* $Id$ * $Id$
***************************************************************************/ ***************************************************************************/
/* If you have problems, all libcurl docs and details are found here:
http://curl.haxx.se/libcurl/
*/
/* This is the version number of the libcurl package from which this header
file origins: */
#define LIBCURL_VERSION "7.10.6"
/* This is the numeric version of the libcurl version number, meant for easier
parsing and comparions by programs. The LIBCURL_VERSION_NUM define will
always follow this syntax:
0xXXYYZZ
Where XX, YY and ZZ are the main version, release and patch numbers in
hexadecimal. All three numbers are always represented using two digits. 1.2
would appear as "0x010200" while version 9.11.7 appears as "0x090b07".
This 6-digit hexadecimal number does not show pre-release number, and it is
always a greater number in a more recent release. It makes comparisons with
greater than and less than work.
*/
#define LIBCURL_VERSION_NUM 0x070a06
#include <stdio.h> #include <stdio.h>
/* The include stuff here is mainly for time_t! */
/* The include stuff here below is mainly for time_t! */
#ifdef vms #ifdef vms
# include <types.h> # include <types.h>
# include <time.h> # include <time.h>
#else #else
# include <sys/types.h> # include <sys/types.h>
# ifdef TIME_WITH_SYS_TIME # include <time.h>
# include <sys/time.h>
# include <time.h>
# else
# ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
# else
# include <time.h>
# endif
# endif
#endif /* defined (vms) */ #endif /* defined (vms) */
#ifndef TRUE #ifndef TRUE
@@ -55,39 +71,36 @@
extern "C" { extern "C" {
#endif #endif
/* stupid #define trick to preserve functionality with older code, but /* silly trick to preserve functionality with older code, but making it use
making it use our name space for the future */ our name space for the future */
#define HttpPost curl_httppost #define HttpPost curl_httppost
struct curl_httppost { struct curl_httppost {
struct curl_httppost *next; /* next entry in the list */ struct curl_httppost *next; /* next entry in the list */
char *name; /* pointer to allocated name */ char *name; /* pointer to allocated name */
long namelength; /* length of name length */ long namelength; /* length of name length */
char *contents; /* pointer to allocated data contents */ char *contents; /* pointer to allocated data contents */
long contentslength; /* length of contents field */ long contentslength; /* length of contents field */
char *buffer; /* pointer to allocated buffer contents */
/* CMC: Added support for buffer uploads */ long bufferlength; /* length of buffer field */
char *buffer; /* pointer to allocated buffer contents */ char *contenttype; /* Content-Type */
long bufferlength; /* length of buffer field */
char *contenttype; /* Content-Type */
struct curl_slist* contentheader; /* list of extra headers for this form */ struct curl_slist* contentheader; /* list of extra headers for this form */
struct curl_httppost *more; /* if one field name has more than one file, this struct curl_httppost *more; /* if one field name has more than one
link should link to following files */ file, this link should link to following
long flags; /* as defined below */ files */
#define HTTPPOST_FILENAME (1<<0) /* specified content is a file name */ long flags; /* as defined below */
#define HTTPPOST_READFILE (1<<1) /* specified content is a file name */ #define HTTPPOST_FILENAME (1<<0) /* specified content is a file name */
#define HTTPPOST_PTRNAME (1<<2) /* name is only stored pointer #define HTTPPOST_READFILE (1<<1) /* specified content is a file name */
do not free in formfree */ #define HTTPPOST_PTRNAME (1<<2) /* name is only stored pointer
do not free in formfree */
#define HTTPPOST_PTRCONTENTS (1<<3) /* contents is only stored pointer #define HTTPPOST_PTRCONTENTS (1<<3) /* contents is only stored pointer
do not free in formfree */ do not free in formfree */
#define HTTPPOST_BUFFER (1<<4) /* upload file from buffer */
#define HTTPPOST_PTRBUFFER (1<<5) /* upload file from pointer contents */
/* CMC: Added support for buffer uploads */ char *showfilename; /* The file name to show. If not set, the
#define HTTPPOST_BUFFER (1<<4) /* upload file from buffer */ actual file name will be used (if this
#define HTTPPOST_PTRBUFFER (1<<5) /* upload file from pointer contents */ is a file part) */
char *showfilename; /* The file name to show. If not set, the actual
file name will be used (if this is a file part) */
}; };
typedef int (*curl_progress_callback)(void *clientp, typedef int (*curl_progress_callback)(void *clientp,
@@ -130,7 +143,7 @@ typedef int (*curl_debug_callback)
curl_infotype type, /* what kind of data */ curl_infotype type, /* what kind of data */
char *data, /* points to the data */ char *data, /* points to the data */
size_t size, /* size of the data pointed to */ size_t size, /* size of the data pointed to */
void *userp); /* whatever the user please */ void *userptr); /* whatever the user please */
/* All possible error codes from all sorts of curl functions. Future versions /* All possible error codes from all sorts of curl functions. Future versions
may return other values, stay prepared. may return other values, stay prepared.
@@ -207,6 +220,11 @@ typedef enum {
CURL_LAST /* never use! */ CURL_LAST /* never use! */
} CURLcode; } CURLcode;
typedef CURLcode (*curl_ssl_ctx_callback)(CURL *curl, /* easy handle */
void *ssl_ctx, /* actually an
OpenSSL SSL_CTX */
void *userptr);
/* Make a spelling correction for the operation timed-out define */ /* Make a spelling correction for the operation timed-out define */
#define CURLE_OPERATION_TIMEDOUT CURLE_OPERATION_TIMEOUTED #define CURLE_OPERATION_TIMEDOUT CURLE_OPERATION_TIMEOUTED
#define CURLE_HTTP_NOT_FOUND CURLE_HTTP_RETURNED_ERROR #define CURLE_HTTP_NOT_FOUND CURLE_HTTP_RETURNED_ERROR
@@ -217,6 +235,14 @@ typedef enum {
CURLPROXY_SOCKS5 = 5 CURLPROXY_SOCKS5 = 5
} curl_proxytype; } curl_proxytype;
#define CURLAUTH_NONE 0 /* nothing */
#define CURLAUTH_BASIC (1<<0) /* Basic (default) */
#define CURLAUTH_DIGEST (1<<1) /* Digest */
#define CURLAUTH_GSSNEGOTIATE (1<<2) /* GSS-Negotiate */
#define CURLAUTH_NTLM (1<<3) /* NTLM */
#define CURLAUTH_ANY ~0 /* all types set */
#define CURLAUTH_ANYSAFE (~CURLAUTH_BASIC)
/* this was the error code 50 in 7.7.3 and a few earlier versions, this /* this was the error code 50 in 7.7.3 and a few earlier versions, this
is no longer used by libcurl but is instead #defined here only to not is no longer used by libcurl but is instead #defined here only to not
make programs break */ make programs break */
@@ -266,6 +292,12 @@ typedef enum {
#define CINIT(name,type,number) CURLOPT_/**/name = type + number #define CINIT(name,type,number) CURLOPT_/**/name = type + number
#endif #endif
/*
* This macro-mania below setups the CURLOPT_[what] enum, to be used with
* curl_easy_setopt(). The first argument in the CINIT() macro is the [what]
* word.
*/
typedef enum { typedef enum {
CINIT(NOTHING, LONG, 0), /********* the first one is unused ************/ CINIT(NOTHING, LONG, 0), /********* the first one is unused ************/
@@ -275,24 +307,19 @@ typedef enum {
/* The full URL to get/put */ /* The full URL to get/put */
CINIT(URL, OBJECTPOINT, 2), CINIT(URL, OBJECTPOINT, 2),
/* Port number to connect to, if other than default. Specify the CONF_PORT /* Port number to connect to, if other than default. */
flag in the CURLOPT_FLAGS to activate this */
CINIT(PORT, LONG, 3), CINIT(PORT, LONG, 3),
/* Name of proxy to use. Specify the CONF_PROXY flag in the CURLOPT_FLAGS to /* Name of proxy to use. */
activate this */
CINIT(PROXY, OBJECTPOINT, 4), CINIT(PROXY, OBJECTPOINT, 4),
/* Name and password to use when fetching. Specify the CONF_USERPWD flag in /* "name:password" to use when fetching. */
the CURLOPT_FLAGS to activate this */
CINIT(USERPWD, OBJECTPOINT, 5), CINIT(USERPWD, OBJECTPOINT, 5),
/* Name and password to use with Proxy. Specify the CONF_PROXYUSERPWD /* "name:password" to use with proxy. */
flag in the CURLOPT_FLAGS to activate this */
CINIT(PROXYUSERPWD, OBJECTPOINT, 6), CINIT(PROXYUSERPWD, OBJECTPOINT, 6),
/* Range to get, specified as an ASCII string. Specify the CONF_RANGE flag /* Range to get, specified as an ASCII string. */
in the CURLOPT_FLAGS to activate this */
CINIT(RANGE, OBJECTPOINT, 7), CINIT(RANGE, OBJECTPOINT, 7),
/* not used */ /* not used */
@@ -413,7 +440,6 @@ typedef enum {
as described elsewhere. */ as described elsewhere. */
CINIT(WRITEINFO, OBJECTPOINT, 40), CINIT(WRITEINFO, OBJECTPOINT, 40),
/* Previous FLAG bits */
CINIT(VERBOSE, LONG, 41), /* talk a lot */ CINIT(VERBOSE, LONG, 41), /* talk a lot */
CINIT(HEADER, LONG, 42), /* throw the header out too */ CINIT(HEADER, LONG, 42), /* throw the header out too */
CINIT(NOPROGRESS, LONG, 43), /* shut off the progress meter */ CINIT(NOPROGRESS, LONG, 43), /* shut off the progress meter */
@@ -624,6 +650,25 @@ typedef enum {
and password to whatever host the server decides. */ and password to whatever host the server decides. */
CINIT(UNRESTRICTED_AUTH, LONG, 105), CINIT(UNRESTRICTED_AUTH, LONG, 105),
/* Specificly switch on or off the FTP engine's use of the EPRT command ( it
also disables the LPRT attempt). By default, those ones will always be
attempted before the good old traditional PORT command. */
CINIT(FTP_USE_EPRT, LONG, 106),
/* Set this to a bitmask value to enable the particular authentications
methods you like. Use this in combination with CURLOPT_USERPWD.
Note that setting multiple bits may cause extra network round-trips. */
CINIT(HTTPAUTH, LONG, 107),
/* Set the ssl context callback function, currently only for OpenSSL ssl_ctx
in second argument. The function must be matching the
curl_ssl_ctx_callback proto. */
CINIT(SSL_CTX_FUNCTION, FUNCTIONPOINT, 108),
/* Set the userdata for the ssl context callback function's third
argument */
CINIT(SSL_CTX_DATA, OBJECTPOINT, 109),
CURLOPT_LASTENTRY /* the last unused */ CURLOPT_LASTENTRY /* the last unused */
} CURLoption; } CURLoption;
@@ -692,9 +737,9 @@ typedef enum {
#endif #endif
/* These functions are in the libcurl, they're here for portable reasons and /* These functions are in libcurl, they're here for portable reasons and they
they are used by the 'curl' client. They really should be moved to some kind are used by the 'curl' client. They really should be moved to some kind of
of "portability library" since it has nothing to do with file transfers and "portability library" since it has nothing to do with file transfers and
might be usable to other programs... might be usable to other programs...
NOTE: they return TRUE if the strings match *case insensitively*. NOTE: they return TRUE if the strings match *case insensitively*.
@@ -702,9 +747,12 @@ typedef enum {
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);
/* DEPRECATED function to build formdata */ #ifdef CURL_OLDSTYLE
/* DEPRECATED function to build formdata. Stop using this, it will cease
to exist. */
int curl_formparse(char *, struct curl_httppost **, int curl_formparse(char *, struct curl_httppost **,
struct curl_httppost **_post); struct curl_httppost **_post);
#endif
/* name is uppercase CURLFORM_<name> */ /* name is uppercase CURLFORM_<name> */
#ifdef CFINIT #ifdef CFINIT
@@ -783,47 +831,122 @@ typedef enum {
CURL_FORMADD_LAST /* last */ CURL_FORMADD_LAST /* last */
} CURLFORMcode; } CURLFORMcode;
/*
* NAME curl_formadd()
*
* DESCRIPTION
*
* Pretty advanved function for building multi-part formposts. Each invoke
* adds one part that together construct a full post. Then use
* CURLOPT_HTTPPOST to send it off to libcurl.
*/
CURLFORMcode curl_formadd(struct curl_httppost **httppost, CURLFORMcode curl_formadd(struct curl_httppost **httppost,
struct curl_httppost **last_post, struct curl_httppost **last_post,
...); ...);
/* cleanup a form: */ /*
* NAME curl_formfree()
*
* DESCRIPTION
*
* Free a multipart formpost previously built with curl_formadd().
*/
void curl_formfree(struct curl_httppost *form); void curl_formfree(struct curl_httppost *form);
/* Unix and Win32 getenv function call, this returns a malloc()'ed string that /*
MUST be free()ed after usage is complete. */ * NAME curl_getenv()
*
* DESCRIPTION
*
* Returns a malloc()'ed string that MUST be curl_free()ed after usage is
* complete.
*/
char *curl_getenv(const char *variable); char *curl_getenv(const char *variable);
/* Returns a static ascii string of the libcurl version. */ /*
* NAME curl_version()
*
* DESCRIPTION
*
* Returns a static ascii string of the libcurl version.
*/
char *curl_version(void); char *curl_version(void);
/* Escape and unescape URL encoding in strings. The functions return a new /*
* allocated string or NULL if an error occurred. */ * NAME curl_escape()
*
* DESCRIPTION
*
* Escapes URL strings (converts all letters consider illegal in URLs to their
* %XX versions). This function returns a new allocated string or NULL if an
* error occurred.
*/
char *curl_escape(const char *string, int length); char *curl_escape(const char *string, int length);
/*
* NAME curl_unescape()
*
* DESCRIPTION
*
* Unescapes URL encoding in strings (converts all %XX codes to their 8bit
* versions). This function returns a new allocated string or NULL if an error
* occurred.
*/
char *curl_unescape(const char *string, int length); char *curl_unescape(const char *string, int length);
/* 20020912 WJM. Provide for a de-allocation in the same translation unit
that did the allocation. Added in libcurl 7.10 */ /*
* NAME curl_free()
*
* DESCRIPTION
*
* Provided for de-allocation in the same translation unit that did the
* allocation. Added in libcurl 7.10
*/
void curl_free(void *p); void curl_free(void *p);
/* curl_global_init() should be invoked exactly once for each application that /*
uses libcurl */ * NAME curl_global_init()
*
* DESCRIPTION
*
* curl_global_init() should be invoked exactly once for each application that
* uses libcurl
*/
CURLcode curl_global_init(long flags); CURLcode curl_global_init(long flags);
/* curl_global_cleanup() should be invoked exactly once for each application /*
that uses libcurl */ * NAME curl_global_cleanup()
*
* DESCRIPTION
*
* curl_global_cleanup() should be invoked exactly once for each application
* that uses libcurl
*/
void curl_global_cleanup(void); void curl_global_cleanup(void);
/* This is the version number */
#define LIBCURL_VERSION "7.10.4"
#define LIBCURL_VERSION_NUM 0x070a04
/* 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 {
char *data; char *data;
struct curl_slist *next; struct curl_slist *next;
}; };
/*
* NAME curl_slist_append()
*
* DESCRIPTION
*
* Appends a string to a linked list. If no list exists, it will be created
* first. Returns the new list, after appending.
*/
struct curl_slist *curl_slist_append(struct curl_slist *, const char *); struct curl_slist *curl_slist_append(struct curl_slist *, const char *);
/*
* NAME curl_slist_free_all()
*
* DESCRIPTION
*
* free a previously built curl_slist.
*/
void curl_slist_free_all(struct curl_slist *); void curl_slist_free_all(struct curl_slist *);
/* /*
@@ -991,8 +1114,18 @@ typedef struct {
#define CURL_VERSION_KERBEROS4 (1<<1) #define CURL_VERSION_KERBEROS4 (1<<1)
#define CURL_VERSION_SSL (1<<2) #define CURL_VERSION_SSL (1<<2)
#define CURL_VERSION_LIBZ (1<<3) #define CURL_VERSION_LIBZ (1<<3)
#define CURL_VERSION_NTLM (1<<4)
#define CURL_VERSION_GSSNEGOTIATE (1<<5)
#define CURL_VERSION_DEBUG (1<<6) /* built with debug capabilities */
/* returns a pointer to a static copy of the version info struct */ /*
* NAME curl_version_info()
*
* DESCRIPTION
*
* This function returns a pointer to a static copy of the version info
* struct. See above.
*/
curl_version_info_data *curl_version_info(CURLversion); curl_version_info_data *curl_version_info(CURLversion);
#ifdef __cplusplus #ifdef __cplusplus

View File

@@ -45,10 +45,23 @@
file descriptors simultaneous easily. file descriptors simultaneous easily.
*/ */
#if defined(_WIN32) && !defined(WIN32)
/* Chris Lewis mentioned that he doesn't get WIN32 defined, only _WIN32 so we
make this adjustment to catch this. */
#define WIN32 1
#endif
#if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__) #if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__)
#include <winsock.h> #include <winsock.h>
#else #else
#ifdef _AIX
/* HP-UX systems version 9, 10 and 11 lack sys/select.h and so does oldish
libc5-based Linux systems. Only include it on system that are known to
require it! */
#include <sys/select.h>
#endif
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/time.h> #include <sys/time.h>
#include <sys/types.h> #include <sys/types.h>

View File

@@ -23,9 +23,7 @@
* $Id$ * $Id$
***************************************************************************/ ***************************************************************************/
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h> #include <sys/types.h>
#endif
size_t fread (void *, size_t, size_t, FILE *); size_t fread (void *, size_t, size_t, FILE *);
size_t fwrite (const void *, size_t, size_t, FILE *); size_t fwrite (const void *, size_t, size_t, FILE *);

View File

@@ -7,7 +7,8 @@ AUTOMAKE_OPTIONS = foreign nostdinc
EXTRA_DIST = getdate.y Makefile.b32 Makefile.b32.resp Makefile.m32 \ EXTRA_DIST = getdate.y Makefile.b32 Makefile.b32.resp Makefile.m32 \
Makefile.vc6 Makefile.riscos libcurl.def curllib.dsp \ Makefile.vc6 Makefile.riscos libcurl.def curllib.dsp \
curllib.dsw config-vms.h config-win32.h config-riscos.h config-mac.h \ curllib.dsw config-vms.h config-win32.h config-riscos.h config-mac.h \
config.h.in ca-bundle.crt README.encoding README.memoryleak config.h.in ca-bundle.crt README.encoding README.memoryleak \
makefile.dj config.dj
lib_LTLIBRARIES = libcurl.la lib_LTLIBRARIES = libcurl.la
@@ -66,16 +67,29 @@ getpass.c netrc.c telnet.h getinfo.c getinfo.h transfer.c strequal.c \
strequal.h easy.c security.h security.c krb4.c krb4.h memdebug.c \ strequal.h easy.c security.h security.c krb4.c krb4.h memdebug.c \
memdebug.h inet_ntoa_r.h http_chunks.c http_chunks.h strtok.c strtok.h \ memdebug.h inet_ntoa_r.h http_chunks.c http_chunks.h strtok.c strtok.h \
connect.c connect.h llist.c llist.h hash.c hash.h multi.c \ connect.c connect.h llist.c llist.h hash.c hash.h multi.c \
content_encoding.c content_encoding.h share.c share.h content_encoding.c content_encoding.h share.c share.h http_digest.c \
md5.c md5.h http_digest.h http_negotiate.c http_negotiate.h \
http_ntlm.c http_ntlm.h ca-bundle.h
noinst_HEADERS = setup.h transfer.h noinst_HEADERS = setup.h transfer.h
BUILT_SOURCES = $(srcdir)/getdate.c $(srcdir)/ca-bundle.h
# Say $(srcdir), so GNU make does not report an ambiguity with the .y.c rule. # Say $(srcdir), so GNU make does not report an ambiguity with the .y.c rule.
$(srcdir)/getdate.c: getdate.y $(srcdir)/getdate.c: getdate.y
cd $(srcdir) && \ cd $(srcdir) && \
$(YACC) $(YFLAGS) getdate.y; \ $(YACC) $(YFLAGS) getdate.y; \
mv -f y.tab.c getdate.c mv -f y.tab.c getdate.c
$(srcdir)/ca-bundle.h: Makefile.in Makefile
cd $(srcdir) && \
echo "/* The file is generated automaticly */" > $@
if CABUNDLE
echo '#define CURL_CA_BUNDLE @CURL_CA_BUNDLE@' >> $@
else
echo '#undef CURL_CA_BUNDLE /* unknown */' >> $@
endif
install-data-hook: install-data-hook:
@if test -n "@CURL_CA_BUNDLE@"; then \ @if test -n "@CURL_CA_BUNDLE@"; then \
$(mkinstalldirs) `dirname $(DESTDIR)@CURL_CA_BUNDLE@`; \ $(mkinstalldirs) `dirname $(DESTDIR)@CURL_CA_BUNDLE@`; \
@@ -85,4 +99,4 @@ install-data-hook:
# this hook is mainly for non-unix systems to build even if configure # this hook is mainly for non-unix systems to build even if configure
# isn't run # isn't run
dist-hook: dist-hook:
cp $(srcdir)/ca-bundle.h.in $(distdir)/ca-bundle.h echo "/* ca bundle path set in here*/" > $(distdir)/ca-bundle.h

View File

@@ -26,24 +26,28 @@ ifdef SSL
DLL_LIBS = -L$(OPENSSL_PATH)/out -leay32 -lssl32 DLL_LIBS = -L$(OPENSSL_PATH)/out -leay32 -lssl32
endif endif
ifdef ZLIB ifdef ZLIB
INCLUDES += -I"$(ZLIB_PATH)" INCLUDES += -I"$(ZLIB_PATH)"
CFLAGS += -DHAVE_LIBZ -DHAVE_ZLIB_H CFLAGS += -DHAVE_LIBZ -DHAVE_ZLIB_H
DLL_LIBS += -L$(ZLIB_PATH) -lz DLL_LIBS += -L$(ZLIB_PATH) -lz
endif endif
COMPILE = $(CC) $(INCLUDES) $(CFLAGS) COMPILE = $(CC) $(INCLUDES) $(CFLAGS)
libcurl_a_LIBRARIES = libcurl.a libcurl_a_LIBRARIES = libcurl.a
libcurl_a_SOURCES = arpa_telnet.h file.c getpass.h netrc.h timeval.c base64.c \ libcurl_a_SOURCES = arpa_telnet.h file.c getpass.h netrc.h timeval.c base64.c \
file.h hostip.c progress.c timeval.h base64.h formdata.c hostip.h progress.h \ file.h hostip.c progress.c timeval.h base64.h formdata.c hostip.h \
cookie.c formdata.h http.c sendf.c cookie.h ftp.c http.h sendf.h url.c dict.c \ progress.h cookie.c formdata.h http.c sendf.c cookie.h ftp.c \
ftp.h if2ip.c speedcheck.c url.h dict.h getdate.c if2ip.h speedcheck.h \ http.h sendf.h url.c dict.c ftp.h if2ip.c speedcheck.c url.h \
urldata.h transfer.c getdate.h ldap.c ssluse.c version.c transfer.h getenv.c \ dict.h getdate.c if2ip.h speedcheck.h urldata.h transfer.c getdate.h \
ldap.h ssluse.h escape.c getenv.h mprintf.c telnet.c escape.h getpass.c netrc.c \ ldap.c ssluse.c version.c transfer.h getenv.c \
telnet.h getinfo.c strequal.c strequal.h easy.c security.h \ ldap.h ssluse.h escape.c getenv.h mprintf.c telnet.c escape.h \
security.c krb4.h krb4.c memdebug.h memdebug.c inet_ntoa_r.h http_chunks.h http_chunks.c \ getpass.c netrc.c telnet.h getinfo.c strequal.c strequal.h easy.c \
strtok.c connect.c hash.c llist.c multi.c share.c share.h\ security.h security.c krb4.h krb4.c memdebug.h memdebug.c \
content_encoding.h content_encoding.c inet_ntoa_r.h http_chunks.h http_chunks.c \
strtok.c connect.c hash.c llist.c multi.c share.c share.h \
content_encoding.h content_encoding.c http_digest.h http_digest.c \
http_negotiate.c http_negotiate.h http_ntlm.c http_ntlm.h md5.h \
md5.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 \
@@ -51,7 +55,7 @@ libcurl_a_OBJECTS = file.o timeval.o base64.o hostip.o progress.o \
getenv.o escape.o mprintf.o telnet.o getpass.o netrc.o getinfo.o \ getenv.o escape.o mprintf.o telnet.o getpass.o netrc.o getinfo.o \
strequal.o easy.o security.o krb4.o memdebug.o http_chunks.o \ strequal.o easy.o security.o krb4.o memdebug.o http_chunks.o \
strtok.o connect.o hash.o llist.o multi.o share.o \ strtok.o connect.o hash.o llist.o multi.o share.o \
content_encoding.o content_encoding.o http_digest.o http_negotiate.o http_ntlm.o md5.o
LIBRARIES = $(libcurl_a_LIBRARIES) LIBRARIES = $(libcurl_a_LIBRARIES)
SOURCES = $(libcurl_a_SOURCES) SOURCES = $(libcurl_a_SOURCES)

View File

@@ -33,7 +33,7 @@
LIB_NAME = libcurl LIB_NAME = libcurl
LIB_NAME_DEBUG = libcurld LIB_NAME_DEBUG = libcurld
!IFNDEF OPENSSL_PATH !IFNDEF OPENSSL_PATH
OPENSSL_PATH = ../../openssl-0.9.6 OPENSSL_PATH = ../../openssl-0.9.7a
!ENDIF !ENDIF
############################################################# #############################################################
@@ -48,7 +48,8 @@ LNKDLL = link.exe /DLL /def:libcurl.def
LNKLIB = link.exe -lib LNKLIB = link.exe -lib
LFLAGS = /nologo LFLAGS = /nologo
LINKLIBS = ws2_32.lib winmm.lib LINKLIBS = ws2_32.lib winmm.lib
SSLLIBS = libeay32.lib ssleay32.lib RSAglue.lib SSLLIBS = libeay32.lib ssleay32.lib
# RSAglue.lib was formerly needed in the SSLLIBS
CFGSET = FALSE CFGSET = FALSE
###################### ######################
@@ -201,7 +202,9 @@ X_OBJS= \
$(DIROBJ)\hash.obj \ $(DIROBJ)\hash.obj \
$(DIROBJ)\llist.obj \ $(DIROBJ)\llist.obj \
$(DIROBJ)\share.obj \ $(DIROBJ)\share.obj \
$(DIROBJ)\multi.obj $(DIROBJ)\multi.obj \
$(DIROBJ)\http_digest.obj \
$(DIROBJ)\md5.obj
all : $(TARGET) all : $(TARGET)
@@ -223,3 +226,6 @@ clean:
-@erase $(DIROBJ)\*.obj -@erase $(DIROBJ)\*.obj
-@erase vc60.idb -@erase vc60.idb
-@erase vc60.pch -@erase vc60.pch
getdate.c: getdate.c.cvs
copy getdate.c.cvs getdate.c

View File

@@ -5,15 +5,15 @@
HTTP/1.1 [RFC 2616] specifies that a client may request that a server encode HTTP/1.1 [RFC 2616] specifies that a client may request that a server encode
its response. This is usually used to compress a response using one of a set its response. This is usually used to compress a response using one of a set
of commonly available compression techniques. These schemes are `deflate' of commonly available compression techniques. These schemes are `deflate' (the
(the zlib algorithm), `gzip' and `compress' [sec 3.5, RFC 2616]. A client zlib algorithm), `gzip' and `compress' [sec 3.5, RFC 2616]. A client requests
requests that the sever perform an encoding by including an Accept-Encoding that the sever perform an encoding by including an Accept-Encoding header in
header in the request document. The value of the header should be one of the the request document. The value of the header should be one of the recognized
recognized tokens `deflate', ... (there's a way to register new tokens `deflate', ... (there's a way to register new schemes/tokens, see sec
schemes/tokens, see sec 3.5 of the spec). A server MAY honor the client's 3.5 of the spec). A server MAY honor the client's encoding request. When a
encoding request. When a response is encoded, the server includes a response is encoded, the server includes a Content-Encoding header in the
Content-Encoding header in the response. The value of the Content-Encoding response. The value of the Content-Encoding header indicates which scheme was
header indicates which scheme was used to encode the data. used to encode the data.
A client may tell a server that it can understand several different encoding A client may tell a server that it can understand several different encoding
schemes. In this case the server may choose any one of those and use it to schemes. In this case the server may choose any one of those and use it to
@@ -24,11 +24,10 @@ information on the Accept-Encoding header.
* Current support for content encoding: * Current support for content encoding:
I added support for the 'deflate' content encoding to both libcurl and curl. Support for the 'deflate' and 'gzip' content encoding are supported by
Both regular and chunked transfers should work although I've tested only the libcurl. Both regular and chunked transfers should work fine. The library
former. The library zlib is required for this feature. Places where I zlib is required for this feature. 'deflate' support was added by James
modified the source code are commented and typically include my initials and Gallagher, and support for the 'gzip' encoding was added by Dan Fandrich.
the date (e.g., 08/29/02 jhrg).
* The libcurl interface: * The libcurl interface:
@@ -39,15 +38,23 @@ To cause libcurl to request a content encoding use:
where <string> is the intended value of the Accept-Encoding header. where <string> is the intended value of the Accept-Encoding header.
Currently, libcurl only understands how to process responses that use the Currently, libcurl only understands how to process responses that use the
`deflate' Content-Encoding, so the only value for CURLOPT_ENCODING that will "deflate" or "gzip" Content-Encoding, so the only values for CURLOPT_ENCODING
work (besides "identity," which does nothing) is "deflate." If a response is that will work (besides "identity," which does nothing) are "deflate" and
encoded using either the `gzip' or `compress' methods, libcurl will return an "gzip" If a response is encoded using the "compress" or methods, libcurl will
error indicating that the response could not be decoded. If <string> is null return an error indicating that the response could not be decoded. If
or empty no Accept-Encoding header is generated. <string> is NULL no Accept-Encoding header is generated. If <string> is a
zero-length string, then an Accept-Encoding header containing all supported
encodings will be generated.
The CURLOPT_ENCODING must be set to any non-NULL value for content to be
automatically decoded. If it is not set and the server still sends encoded
content (despite not having been asked), the data is returned in its raw form
and the Content-Encoding type is not checked.
* The curl interface: * The curl interface:
Use the --compressed option with curl to cause it to ask servers to compress Use the --compressed option with curl to cause it to ask servers to compress
responses using deflate. responses using deflate.
James Gallagher <jgallagher@gso.uri.edu> James Gallagher <jgallagher@gso.uri.edu>
Dan Fandrich <dan@coneharvesters.com>

View File

@@ -17,7 +17,7 @@ Single-threaded
Build Build
Rebuild libcurl with -DMALLOCDEBUG (usually, rerunning configure with Rebuild libcurl with -DCURLDEBUG (usually, rerunning configure with
--enable-debug fixes this). 'make clean' first, then 'make' so that all --enable-debug fixes this). 'make clean' first, then 'make' so that all
files actually are rebuilt properly. It will also make sense to build files actually are rebuilt properly. It will also make sense to build
libcurl with the debug option (usually -g to the compiler) so that debugging libcurl with the debug option (usually -g to the compiler) so that debugging

View File

@@ -42,7 +42,7 @@
#include "base64.h" #include "base64.h"
#ifdef MALLOCDEBUG #ifdef CURLDEBUG
#include "memdebug.h" #include "memdebug.h"
#endif #endif
@@ -220,6 +220,8 @@ int main(int argc, char **argv, char **envp)
#ifdef TEST_DECODE #ifdef TEST_DECODE
/* decoding test harness. Read in a base64 string from stdin and write out the /* decoding test harness. Read in a base64 string from stdin and write out the
* length returned by Curl_base64_decode, followed by the decoded data itself * length returned by Curl_base64_decode, followed by the decoded data itself
*
* gcc -DTEST_DECODE base64.c -o base64 mprintf.o memdebug.o
*/ */
#include <stdio.h> #include <stdio.h>
@@ -232,13 +234,31 @@ int main(int argc, char **argv, char **envp)
int base64Len; int base64Len;
unsigned char *data; unsigned char *data;
int dataLen; int dataLen;
int i, j;
base64 = (char *)suck(&base64Len); base64 = (char *)suck(&base64Len);
data = (unsigned char *)malloc(base64Len * 3/4 + 8); data = (unsigned char *)malloc(base64Len * 3/4 + 8);
dataLen = Curl_base64_decode(base64, data); dataLen = Curl_base64_decode(base64, data);
fprintf(stderr, "%d\n", dataLen); fprintf(stderr, "%d\n", dataLen);
fwrite(data,1,dataLen,stdout);
for(i=0; i < dataLen; i+=0x10) {
printf("0x%02x: ", i);
for(j=0; j < 0x10; j++)
if((j+i) < dataLen)
printf("%02x ", data[i+j]);
else
printf(" ");
printf(" | ");
for(j=0; j < 0x10; j++)
if((j+i) < dataLen)
printf("%c", isgraph(data[i+j])?data[i+j]:'.');
else
break;
puts("");
}
free(base64); free(data); free(base64); free(data);
return 0; return 0;

92
lib/config.dj Normal file
View File

@@ -0,0 +1,92 @@
#ifndef _CURL_CONFIG_DJGPP_H
#define _CURL_CONFIG_DJGPP_H
#define OS "djgpp"
#define PACKAGE "curl"
#define CURL_CA_BUNDLE "/dev/env/CURL_CA_BUNDLE"
#if (DJGPP_MINOR >= 4)
/* #define HAVE_DLOPEN 1 maybe not (DXE3) */
#endif
#if 1 /* use ioctlsocket() via fsext'ed fcntl() */
#define HAVE_O_NONBLOCK 1
#else
#define HAVE_IOCTLSOCKET 1
#endif
#define HAVE_ALARM 1
#define HAVE_ARPA_INET_H 1
#define HAVE_CLOSESOCKET 1
#define HAVE_FCNTL_H 1
#define HAVE_GETHOSTBYADDR 1
#define HAVE_GETHOSTNAME 1
#define HAVE_GETPASS 1
#define HAVE_GETSERVBYNAME 1
#define HAVE_GETTIMEOFDAY 1
#define HAVE_INET_ADDR 1
#define HAVE_INET_NTOA 1
#define HAVE_IO_H 1
#define HAVE_MALLOC_H 1
#define HAVE_MEMORY_H 1
#define HAVE_NETDB_H 1
#define HAVE_NETINET_IN_H 1
#define HAVE_NET_IF_H 1
#define HAVE_PERROR 1
#define HAVE_SELECT 1
#define HAVE_SETJMP_H 1
#define HAVE_SETVBUF 1
#define HAVE_SIGNAL 1
#define HAVE_SIGACTION 1
#define HAVE_SIGSETJMP 1
#define HAVE_SOCKET 1
#define HAVE_STRCASECMP 1
#define HAVE_STRDUP 1
#define HAVE_STRFTIME 1
#define HAVE_STRICMP 1
#define HAVE_STRSTR 1
#define HAVE_SYS_SOCKET_H 1
#define HAVE_SYS_STAT_H 1
#define HAVE_SYS_TYPES_H 1
#define HAVE_TERMIOS_H 1
#define HAVE_TIME_H 1
#define HAVE_UNAME 1
#define HAVE_UNISTD_H 1
#define HAVE_VPRINTF 1
#define RETSIGTYPE void
#define SIZEOF_LONG_DOUBLE 16
#define SIZEOF_LONG_LONG 8
#define STDC_HEADERS 1
#define TIME_WITH_SYS_TIME 1
#define BSD
#define USE_ZLIB
/* #define MALLOCDEBUG */
#ifdef HAVE_OPENSSL_ENGINE_H /* on cmd-line */
#define HAVE_OPENSSL_X509_H 1
#define HAVE_OPENSSL_SSL_H 1
#define HAVE_OPENSSL_RSA_H 1
#define HAVE_OPENSSL_PEM_H 1
#define HAVE_OPENSSL_ERR_H 1
#define HAVE_OPENSSL_CRYPTO_H 1
#define HAVE_LIBSSL 1
#define HAVE_LIBCRYPTO 1
#define OPENSSL_NO_KRB5 1
#endif
#define in_addr_t u_long
#define socklen_t int
#define ssize_t int
#include <stdlib.h>
#include <string.h>
#include <tcp.h> /* Watt-32 API */
#undef word
#endif /* _CURL_CONFIG_DJGPP_H */

View File

@@ -77,12 +77,11 @@
#include "if2ip.h" #include "if2ip.h"
/* The last #include file should be: */ /* The last #include file should be: */
#ifdef MALLOCDEBUG #ifdef CURLDEBUG
#include "memdebug.h" #include "memdebug.h"
#endif #endif
static int Curl_ourerrno(void)
int ourerrno(void)
{ {
#ifdef WIN32 #ifdef WIN32
return (int)GetLastError(); return (int)GetLastError();
@@ -198,10 +197,6 @@ static CURLcode bindlocal(struct connectdata *conn,
#ifdef HAVE_INET_NTOA #ifdef HAVE_INET_NTOA
#ifndef INADDR_NONE
#define INADDR_NONE (in_addr_t) ~0
#endif
struct SessionHandle *data = conn->data; struct SessionHandle *data = conn->data;
/************************************************************* /*************************************************************
@@ -214,7 +209,11 @@ static CURLcode bindlocal(struct connectdata *conn,
char myhost[256] = ""; char myhost[256] = "";
in_addr_t in; in_addr_t in;
if(Curl_if2ip(data->set.device, myhost, sizeof(myhost))) { /* First check if the given name is an IP address */
in=inet_addr(data->set.device);
if((in == CURL_INADDR_NONE) &&
Curl_if2ip(data->set.device, myhost, sizeof(myhost))) {
/* /*
* We now have the numerical IPv4-style x.y.z.w in the 'myhost' buffer * We now have the numerical IPv4-style x.y.z.w in the 'myhost' buffer
*/ */
@@ -247,7 +246,7 @@ static CURLcode bindlocal(struct connectdata *conn,
infof(data, "We bind local end to %s\n", myhost); infof(data, "We bind local end to %s\n", myhost);
in=inet_addr(myhost); in=inet_addr(myhost);
if (INADDR_NONE != in) { if (CURL_INADDR_NONE != in) {
if ( h ) { if ( h ) {
Curl_addrinfo *addr = h->addr; Curl_addrinfo *addr = h->addr;
@@ -350,7 +349,7 @@ int socketerror(int sockfd)
if( -1 == getsockopt(sockfd, SOL_SOCKET, SO_ERROR, if( -1 == getsockopt(sockfd, SOL_SOCKET, SO_ERROR,
(void *)&err, &errSize)) (void *)&err, &errSize))
err = ourerrno(); err = Curl_ourerrno();
return err; return err;
} }
@@ -414,7 +413,7 @@ CURLcode Curl_is_connected(struct connectdata *conn,
return CURLE_COULDNT_CONNECT; return CURLE_COULDNT_CONNECT;
} }
else if(1 != rc) { else if(1 != rc) {
int error = ourerrno(); int error = Curl_ourerrno();
failf(data, "Failed connect to %s:%d, errno: %d", failf(data, "Failed connect to %s:%d, errno: %d",
conn->hostname, conn->port, error); conn->hostname, conn->port, error);
return CURLE_COULDNT_CONNECT; return CURLE_COULDNT_CONNECT;
@@ -526,7 +525,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */
rc = connect(sockfd, ai->ai_addr, ai->ai_addrlen); rc = connect(sockfd, ai->ai_addr, ai->ai_addrlen);
if(-1 == rc) { if(-1 == rc) {
int error=ourerrno(); int error=Curl_ourerrno();
switch (error) { switch (error) {
case EINPROGRESS: case EINPROGRESS:
@@ -645,7 +644,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */
sizeof(serv_addr)); sizeof(serv_addr));
if(-1 == rc) { if(-1 == rc) {
int error=ourerrno(); int error=Curl_ourerrno();
switch (error) { switch (error) {
case EINPROGRESS: case EINPROGRESS:

View File

@@ -37,4 +37,6 @@ CURLcode Curl_connecthost(struct connectdata *conn,
Curl_ipconnect **addr, /* the one we used */ Curl_ipconnect **addr, /* the one we used */
bool *connected /* truly connected? */ bool *connected /* truly connected? */
); );
int Curl_ourerrno(void);
#endif #endif

View File

@@ -1,8 +1,8 @@
/*************************************************************************** /***************************************************************************
* _ _ ____ _ * _ _ ____ _
* Project ___| | | | _ \| | * Project ___| | | | _ \| |
* / __| | | | |_) | | * / __| | | | |_) | |
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2003, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 1998 - 2003, Daniel Stenberg, <daniel@haxx.se>, et al.
@@ -10,7 +10,7 @@
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
* are also available at http://curl.haxx.se/docs/copyright.html. * are also available at http://curl.haxx.se/docs/copyright.html.
* *
* You may opt to use, copy, modify, merge, publish, distribute and/or sell * 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 * copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file. * furnished to do so, under the terms of the COPYING file.
@@ -25,13 +25,26 @@
#ifdef HAVE_LIBZ #ifdef HAVE_LIBZ
#include <stdlib.h>
#include <string.h>
#include "urldata.h" #include "urldata.h"
#include <curl/curl.h> #include <curl/curl.h>
#include <curl/types.h> #include <curl/types.h>
#include "sendf.h" #include "sendf.h"
#define DSIZ 4096 /* buffer size for decompressed data */ #define DSIZ 0x10000 /* buffer size for decompressed data */
#define GZIP_MAGIC_0 0x1f
#define GZIP_MAGIC_1 0x8b
/* gzip flag byte */
#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */
#define HEAD_CRC 0x02 /* bit 1 set: header CRC present */
#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
#define ORIG_NAME 0x08 /* bit 3 set: original file name present */
#define COMMENT 0x10 /* bit 4 set: file comment present */
#define RESERVED 0xE0 /* bits 5..7: reserved */
static CURLcode static CURLcode
process_zlib_error(struct SessionHandle *data, z_stream *z) process_zlib_error(struct SessionHandle *data, z_stream *z)
@@ -55,7 +68,7 @@ exit_zlib(z_stream *z, bool *zlib_init, CURLcode result)
} }
CURLcode CURLcode
Curl_unencode_deflate_write(struct SessionHandle *data, Curl_unencode_deflate_write(struct SessionHandle *data,
struct Curl_transfer_keeper *k, struct Curl_transfer_keeper *k,
ssize_t nread) ssize_t nread)
{ {
@@ -63,7 +76,7 @@ Curl_unencode_deflate_write(struct SessionHandle *data,
int result; /* Curl_client_write status */ int result; /* Curl_client_write status */
char decomp[DSIZ]; /* Put the decompressed data here. */ char decomp[DSIZ]; /* Put the decompressed data here. */
z_stream *z = &k->z; /* zlib state structure */ z_stream *z = &k->z; /* zlib state structure */
/* Initialize zlib? */ /* Initialize zlib? */
if (!k->zlib_init) { if (!k->zlib_init) {
z->zalloc = (alloc_func)Z_NULL; z->zalloc = (alloc_func)Z_NULL;
@@ -74,7 +87,7 @@ Curl_unencode_deflate_write(struct SessionHandle *data,
k->zlib_init = 1; k->zlib_init = 1;
} }
/* Set the compressed input when this fucntion is called */ /* Set the compressed input when this function is called */
z->next_in = (Bytef *)k->str; z->next_in = (Bytef *)k->str;
z->avail_in = nread; z->avail_in = nread;
@@ -87,11 +100,12 @@ Curl_unencode_deflate_write(struct SessionHandle *data,
status = inflate(z, Z_SYNC_FLUSH); status = inflate(z, Z_SYNC_FLUSH);
if (status == Z_OK || status == Z_STREAM_END) { if (status == Z_OK || status == Z_STREAM_END) {
result = Curl_client_write(data, CLIENTWRITE_BODY, decomp, if (DSIZ - z->avail_out) {
DSIZ - z->avail_out); result = Curl_client_write(data, CLIENTWRITE_BODY, decomp,
/* if !CURLE_OK, clean up, return */ DSIZ - z->avail_out);
if (result) { /* if !CURLE_OK, clean up, return */
return exit_zlib(z, &k->zlib_init, result); if (result)
return exit_zlib(z, &k->zlib_init, result);
} }
/* Done?; clean up, return */ /* Done?; clean up, return */
@@ -103,7 +117,233 @@ Curl_unencode_deflate_write(struct SessionHandle *data,
} }
/* Done with these bytes, exit */ /* Done with these bytes, exit */
if (status == Z_OK && z->avail_in == 0 && z->avail_out > 0) if (status == Z_OK && z->avail_in == 0 && z->avail_out > 0)
return result;
}
else { /* Error; exit loop, handle below */
return exit_zlib(z, &k->zlib_init, process_zlib_error(data, z));
}
}
}
/* Skip over the gzip header */
static enum {
GZIP_OK,
GZIP_BAD,
GZIP_UNDERFLOW
} check_gzip_header(unsigned char const *data, ssize_t len, ssize_t *headerlen)
{
int method, flags;
const ssize_t totallen = len;
/* The shortest header is 10 bytes */
if (len < 10)
return GZIP_UNDERFLOW;
if ((data[0] != GZIP_MAGIC_0) || (data[1] != GZIP_MAGIC_1))
return GZIP_BAD;
method = data[2];
flags = data[3];
if (method != Z_DEFLATED || (flags & RESERVED) != 0) {
/* Can't handle this compression method or unknown flag */
return GZIP_BAD;
}
/* Skip over time, xflags, OS code and all previous bytes */
len -= 10;
data += 10;
if (flags & EXTRA_FIELD) {
ssize_t extra_len;
if (len < 2)
return GZIP_UNDERFLOW;
extra_len = (data[1] << 8) | data[0];
if (len < (extra_len+2))
return GZIP_UNDERFLOW;
len -= (extra_len + 2);
}
if (flags & ORIG_NAME) {
/* Skip over NUL-terminated file name */
while (len && *data) {
--len;
++data;
}
if (!len || *data)
return GZIP_UNDERFLOW;
/* Skip over the NUL */
--len;
++data;
}
if (flags & COMMENT) {
/* Skip over NUL-terminated comment */
while (len && *data) {
--len;
++data;
}
if (!len || *data)
return GZIP_UNDERFLOW;
/* Skip over the NUL */
--len;
++data;
}
if (flags & HEAD_CRC) {
if (len < 2)
return GZIP_UNDERFLOW;
len -= 2;
data += 2;
}
*headerlen = totallen - len;
return GZIP_OK;
}
CURLcode
Curl_unencode_gzip_write(struct SessionHandle *data,
struct Curl_transfer_keeper *k,
ssize_t nread)
{
int status; /* zlib status */
int result; /* Curl_client_write status */
char decomp[DSIZ]; /* Put the decompressed data here. */
z_stream *z = &k->z; /* zlib state structure */
/* Initialize zlib? */
if (!k->zlib_init) {
z->zalloc = (alloc_func)Z_NULL;
z->zfree = (free_func)Z_NULL;
z->opaque = 0; /* of dubious use 08/27/02 jhrg */
if (inflateInit2(z, -MAX_WBITS) != Z_OK)
return process_zlib_error(data, z);
k->zlib_init = 1; /* Initial call state */
}
/* This next mess is to get around the potential case where there isn't
enough data passed in to skip over the gzip header. If that happens,
we malloc a block and copy what we have then wait for the next call. If
there still isn't enough (this is definitely a worst-case scenario), we
make the block bigger, copy the next part in and keep waiting. */
/* Skip over gzip header? */
if (k->zlib_init == 1) {
/* Initial call state */
ssize_t hlen;
switch (check_gzip_header((unsigned char *)k->str, nread, &hlen)) {
case GZIP_OK:
z->next_in = (Bytef *)k->str + hlen;
z->avail_in = nread - hlen;
k->zlib_init = 3; /* Inflating stream state */
break;
case GZIP_UNDERFLOW:
/* We need more data so we can find the end of the gzip header.
It's possible that the memory block we malloc here will never be
freed if the transfer abruptly aborts after this point. Since it's
unlikely that circumstances will be right for this code path to be
followed in the first place, and it's even more unlikely for a transfer
to fail immediately afterwards, it should seldom be a problem. */
z->avail_in = nread;
z->next_in = malloc(z->avail_in);
if (z->next_in == NULL) {
return exit_zlib(z, &k->zlib_init, CURLE_OUT_OF_MEMORY);
}
memcpy(z->next_in, k->str, z->avail_in);
k->zlib_init = 2; /* Need more gzip header data state */
/* We don't have any data to inflate yet */
return CURLE_OK;
case GZIP_BAD:
default:
return exit_zlib(z, &k->zlib_init, process_zlib_error(data, z));
}
}
else if (k->zlib_init == 2) {
/* Need more gzip header data state */
ssize_t hlen;
unsigned char *oldblock = z->next_in;
z->avail_in += nread;
z->next_in = realloc(z->next_in, z->avail_in);
if (z->next_in == NULL) {
free(oldblock);
return exit_zlib(z, &k->zlib_init, CURLE_OUT_OF_MEMORY);
}
/* Append the new block of data to the previous one */
memcpy(z->next_in + z->avail_in - nread, k->str, nread);
switch (check_gzip_header(z->next_in, z->avail_in, &hlen)) {
case GZIP_OK:
/* This is the zlib stream data */
free(z->next_in);
/* Don't point into the malloced block since we just freed it */
z->next_in = (Bytef *)k->str + hlen + nread - z->avail_in;
z->avail_in = z->avail_in - hlen;
k->zlib_init = 3; /* Inflating stream state */
break;
case GZIP_UNDERFLOW:
/* We still don't have any data to inflate! */
return CURLE_OK;
case GZIP_BAD:
default:
free(z->next_in);
return exit_zlib(z, &k->zlib_init, process_zlib_error(data, z));
}
}
else {
/* Inflating stream state */
z->next_in = (Bytef *)k->str;
z->avail_in = nread;
}
if (z->avail_in == 0) {
/* We don't have any data to inflate; wait until next time */
return CURLE_OK;
}
/* because the buffer size is fixed, iteratively decompress
and transfer to the client via client_write. */
for (;;) {
/* (re)set buffer for decompressed output for every iteration */
z->next_out = (Bytef *)&decomp[0];
z->avail_out = DSIZ;
status = inflate(z, Z_SYNC_FLUSH);
if (status == Z_OK || status == Z_STREAM_END) {
if(DSIZ - z->avail_out) {
result = Curl_client_write(data, CLIENTWRITE_BODY, decomp,
DSIZ - z->avail_out);
/* if !CURLE_OK, clean up, return */
if (result)
return exit_zlib(z, &k->zlib_init, result);
}
/* Done?; clean up, return */
/* We should really check the gzip CRC here */
if (status == Z_STREAM_END) {
if (inflateEnd(z) == Z_OK)
return exit_zlib(z, &k->zlib_init, result);
else
return exit_zlib(z, &k->zlib_init, process_zlib_error(data, z));
}
/* Done with these bytes, exit */
if (status == Z_OK && z->avail_in == 0 && z->avail_out > 0)
return result; return result;
} }
else { /* Error; exit loop, handle below */ else { /* Error; exit loop, handle below */

View File

@@ -20,7 +20,22 @@
* *
* $Id$ * $Id$
***************************************************************************/ ***************************************************************************/
#include "setup.h"
/*
* Comma-separated list all supported Content-Encodings ('identity' is implied)
*/
#ifdef HAVE_LIBZ
#define ALL_CONTENT_ENCODINGS "deflate, gzip"
#else
#define ALL_CONTENT_ENCODINGS "identity"
#endif
CURLcode Curl_unencode_deflate_write(struct SessionHandle *data, CURLcode Curl_unencode_deflate_write(struct SessionHandle *data,
struct Curl_transfer_keeper *k, struct Curl_transfer_keeper *k,
ssize_t nread); ssize_t nread);
CURLcode
Curl_unencode_gzip_write(struct SessionHandle *data,
struct Curl_transfer_keeper *k,
ssize_t nread);

View File

@@ -92,7 +92,7 @@ Example set of cookies:
#include "strtok.h" #include "strtok.h"
/* The last #include file should be: */ /* The last #include file should be: */
#ifdef MALLOCDEBUG #ifdef CURLDEBUG
#include "memdebug.h" #include "memdebug.h"
#endif #endif
@@ -111,6 +111,17 @@ free_cookiemess(struct Cookie *co)
free(co); free(co);
} }
static bool tailmatch(const char *little, const char *bigone)
{
unsigned int littlelen = strlen(little);
unsigned int biglen = strlen(bigone);
if(littlelen > biglen)
return FALSE;
return strequal(little, bigone+biglen-littlelen);
}
/**************************************************************************** /****************************************************************************
* *
* Curl_cookie_add() * Curl_cookie_add()
@@ -123,7 +134,10 @@ struct Cookie *
Curl_cookie_add(struct CookieInfo *c, Curl_cookie_add(struct CookieInfo *c,
bool httpheader, /* TRUE if HTTP header-style line */ bool httpheader, /* TRUE if HTTP header-style line */
char *lineptr, /* first character of the line */ char *lineptr, /* first character of the line */
char *domain) /* default domain */ char *domain, /* default domain */
char *path) /* full path used when this cookie is set,
used to get default path for the cookie
unless set */
{ {
struct Cookie *clist; struct Cookie *clist;
char what[MAX_COOKIE_LINE]; char what[MAX_COOKIE_LINE];
@@ -134,6 +148,7 @@ Curl_cookie_add(struct CookieInfo *c,
struct Cookie *lastc=NULL; struct Cookie *lastc=NULL;
time_t now = time(NULL); time_t now = time(NULL);
bool replace_old = FALSE; bool replace_old = FALSE;
bool badcookie = FALSE; /* cookies are good by default. mmmmm yummy */
/* First, alloc and init a new struct for it */ /* First, alloc and init a new struct for it */
co = (struct Cookie *)malloc(sizeof(struct Cookie)); co = (struct Cookie *)malloc(sizeof(struct Cookie));
@@ -186,8 +201,63 @@ Curl_cookie_add(struct CookieInfo *c,
co->path=strdup(whatptr); co->path=strdup(whatptr);
} }
else if(strequal("domain", name)) { else if(strequal("domain", name)) {
co->domain=strdup(whatptr); /* note that this name may or may not have a preceeding dot, but
co->field1= (whatptr[0]=='.')?2:1; we don't care about that, we treat the names the same anyway */
char *ptr=whatptr;
int dotcount=1;
unsigned int i;
static const char *seventhree[]= {
"com", "edu", "net", "org", "gov", "mil", "int"
};
/* Count the dots, we need to make sure that there are THREE dots
in the normal domains, or TWO in the seventhree-domains. */
if('.' == whatptr[0])
/* don't count the initial dot, assume it */
ptr++;
do {
ptr = strchr(ptr, '.');
if(ptr) {
ptr++;
dotcount++;
}
} while(ptr);
for(i=0;
i<sizeof(seventhree)/sizeof(seventhree[0]); i++) {
if(tailmatch(seventhree[i], whatptr)) {
dotcount++; /* we allow one dot less for these */
break;
}
}
if(dotcount < 3) {
/* Received and skipped a cookie with a domain using too few
dots. */
badcookie=TRUE; /* mark this as a bad cookie */
}
else {
/* Now, we make sure that our host is within the given domain,
or the given domain is not valid and thus cannot be set. */
if(!domain || tailmatch(whatptr, domain)) {
char *ptr=whatptr;
if(ptr[0] == '.')
ptr++;
co->domain=strdup(ptr); /* dont prefix with dots internally */
co->tailmatch=TRUE; /* we always do that if the domain name was
given */
}
else {
/* we did not get a tailmatch and then the attempted set domain
is not a domain to which the current host belongs. Mark as
bad. */
badcookie=TRUE;
}
}
} }
else if(strequal("version", name)) { else if(strequal("version", name)) {
co->version=strdup(whatptr); co->version=strdup(whatptr);
@@ -249,8 +319,11 @@ Curl_cookie_add(struct CookieInfo *c,
semiptr=strchr(ptr, '\0'); semiptr=strchr(ptr, '\0');
} while(semiptr); } while(semiptr);
if(NULL == co->name) { if(badcookie || (NULL == co->name)) {
/* we didn't get a cookie name, this is an illegal line, bail out */ /* we didn't get a cookie name or a bad one,
this is an illegal line, bail out */
if(co->expirestr)
free(co->expirestr);
if(co->domain) if(co->domain)
free(co->domain); free(co->domain);
if(co->path) if(co->path)
@@ -264,8 +337,20 @@ Curl_cookie_add(struct CookieInfo *c,
} }
if(NULL == co->domain) if(NULL == co->domain)
/* no domain given in the header line, set the default now */ /* no domain was given in the header line, set the default now */
co->domain=domain?strdup(domain):NULL; co->domain=domain?strdup(domain):NULL;
if((NULL == co->path) && path) {
/* no path was given in the header line, set the default now */
char *endslash = strrchr(path, '/');
if(endslash) {
int pathlen = endslash-path+1; /* include the ending slash */
co->path=malloc(pathlen+1); /* one extra for the zero byte */
if(co->path) {
memcpy(co->path, path, pathlen);
co->path[pathlen]=0; /* zero terminate */
}
}
}
} }
else { else {
/* This line is NOT a HTTP header style line, we do offer support for /* This line is NOT a HTTP header style line, we do offer support for
@@ -297,9 +382,12 @@ Curl_cookie_add(struct CookieInfo *c,
/* Now loop through the fields and init the struct we already have /* Now loop through the fields and init the struct we already have
allocated */ allocated */
for(ptr=firstptr, fields=0; ptr; ptr=strtok_r(NULL, "\t", &tok_buf), fields++) { for(ptr=firstptr, fields=0; ptr;
ptr=strtok_r(NULL, "\t", &tok_buf), fields++) {
switch(fields) { switch(fields) {
case 0: case 0:
if(ptr[0]=='.') /* skip preceeding dots */
ptr++;
co->domain = strdup(ptr); co->domain = strdup(ptr);
break; break;
case 1: case 1:
@@ -312,10 +400,8 @@ Curl_cookie_add(struct CookieInfo *c,
As far as I can see, it is set to true when the cookie says As far as I can see, it is set to true when the cookie says
.domain.com and to false when the domain is complete www.domain.com .domain.com and to false when the domain is complete www.domain.com
We don't currently take advantage of this knowledge.
*/ */
co->field1=strequal(ptr, "TRUE")+1; /* store information */ co->tailmatch=strequal(ptr, "TRUE"); /* store information */
break; break;
case 2: case 2:
/* It turns out, that sometimes the file format allows the path /* It turns out, that sometimes the file format allows the path
@@ -374,13 +460,8 @@ Curl_cookie_add(struct CookieInfo *c,
/* the names are identical */ /* the names are identical */
if(clist->domain && co->domain) { if(clist->domain && co->domain) {
if(strequal(clist->domain, co->domain) || if(strequal(clist->domain, co->domain))
(clist->domain[0]=='.' && /* The domains are identical */
strequal(&(clist->domain[1]), co->domain)) ||
(co->domain[0]=='.' &&
strequal(clist->domain, &(co->domain[1]))) )
/* The domains are identical, or at least identical if you skip the
preceeding dot */
replace_old=TRUE; replace_old=TRUE;
} }
else if(!clist->domain && !co->domain) else if(!clist->domain && !co->domain)
@@ -470,7 +551,6 @@ Curl_cookie_add(struct CookieInfo *c,
} }
c->numcookies++; /* one more cookie in the jar */ c->numcookies++; /* one more cookie in the jar */
return co; return co;
} }
@@ -532,7 +612,7 @@ struct CookieInfo *Curl_cookie_init(char *file,
while(*lineptr && isspace((int)*lineptr)) while(*lineptr && isspace((int)*lineptr))
lineptr++; lineptr++;
Curl_cookie_add(c, headerline, lineptr, NULL); Curl_cookie_add(c, headerline, lineptr, NULL, NULL);
} }
if(fromfile) if(fromfile)
fclose(fp); fclose(fp);
@@ -561,9 +641,6 @@ struct Cookie *Curl_cookie_getlist(struct CookieInfo *c,
struct Cookie *newco; struct Cookie *newco;
struct Cookie *co; struct Cookie *co;
time_t now = time(NULL); time_t now = time(NULL);
int hostlen=strlen(host);
int domlen;
struct Cookie *mainco=NULL; struct Cookie *mainco=NULL;
if(!c || !c->cookies) if(!c || !c->cookies)
@@ -572,43 +649,42 @@ struct Cookie *Curl_cookie_getlist(struct CookieInfo *c,
co = c->cookies; co = c->cookies;
while(co) { while(co) {
/* only process this cookie if it is not expired or had no expire /* only process this cookie if it is not expired or had no expire
date AND that if the cookie requires we're secure we must only date AND that if the cookie requires we're secure we must only
continue if we are! */ continue if we are! */
if( (co->expires<=0 || (co->expires> now)) && if( (co->expires<=0 || (co->expires> now)) &&
(co->secure?secure:TRUE) ) { (co->secure?secure:TRUE) ) {
/* now check if the domain is correct */
if(!co->domain ||
(co->tailmatch && tailmatch(co->domain, host)) ||
(!co->tailmatch && strequal(host, co->domain)) ) {
/* the right part of the host matches the domain stuff in the
cookie data */
/* now check the left part of the path with the cookies path
requirement */
if(!co->path ||
checkprefix(co->path, path) ) {
/* now check if the domain is correct */ /* and now, we know this is a match and we should create an
domlen=co->domain?strlen(co->domain):0; entry for the return-linked-list */
if(!co->domain ||
((domlen<=hostlen) && newco = (struct Cookie *)malloc(sizeof(struct Cookie));
strequal(host+(hostlen-domlen), co->domain)) ) { if(newco) {
/* the right part of the host matches the domain stuff in the /* first, copy the whole source cookie: */
cookie data */ memcpy(newco, co, sizeof(struct Cookie));
/* now check the left part of the path with the cookies path /* then modify our next */
requirement */ newco->next = mainco;
if(!co->path ||
checkprefix(co->path, path) ) { /* point the main to us */
mainco = newco;
/* and now, we know this is a match and we should create an }
entry for the return-linked-list */ }
}
newco = (struct Cookie *)malloc(sizeof(struct Cookie)); }
if(newco) { co = co->next;
/* first, copy the whole source cookie: */
memcpy(newco, co, sizeof(struct Cookie));
/* then modify our next */
newco->next = mainco;
/* point the main to us */
mainco = newco;
}
}
}
}
co = co->next;
} }
return mainco; /* return the new list */ return mainco; /* return the new list */
@@ -716,15 +792,19 @@ int Curl_cookie_output(struct CookieInfo *c, char *dumphere)
while(co) { while(co) {
fprintf(out, fprintf(out,
"%s\t" /* domain */ "%s%s\t" /* domain */
"%s\t" /* field1 */ "%s\t" /* tailmatch */
"%s\t" /* path */ "%s\t" /* path */
"%s\t" /* secure */ "%s\t" /* secure */
"%u\t" /* expires */ "%u\t" /* expires */
"%s\t" /* name */ "%s\t" /* name */
"%s\n", /* value */ "%s\n", /* value */
/* Make sure all domains are prefixed with a dot if they allow
tailmatching. This is Mozilla-style. */
(co->tailmatch && co->domain && co->domain[0] != '.')? ".":"",
co->domain?co->domain:"unknown", co->domain?co->domain:"unknown",
co->field1==2?"TRUE":"FALSE", co->tailmatch?"TRUE":"FALSE",
co->path?co->path:"/", co->path?co->path:"/",
co->secure?"TRUE":"FALSE", co->secure?"TRUE":"FALSE",
(unsigned int)co->expires, (unsigned int)co->expires,

View File

@@ -40,8 +40,7 @@ struct Cookie {
char *domain; /* domain = <this> */ char *domain; /* domain = <this> */
long expires; /* expires = <this> */ long expires; /* expires = <this> */
char *expirestr; /* the plain text version */ char *expirestr; /* the plain text version */
bool tailmatch; /* weather we do tail-matchning of the domain name */
char field1; /* read from a cookie file, 1 => FALSE, 2=> TRUE */
/* RFC 2109 keywords. Version=1 means 2109-compliant cookie sending */ /* RFC 2109 keywords. Version=1 means 2109-compliant cookie sending */
char *version; /* Version = <value> */ char *version; /* Version = <value> */
@@ -70,11 +69,11 @@ struct CookieInfo {
#define MAX_NAME_TXT "255" #define MAX_NAME_TXT "255"
/* /*
* Add a cookie to the internal list of cookies. The domain argument is only * Add a cookie to the internal list of cookies. The domain and path arguments
* used if the header boolean is TRUE. * are only used if the header boolean is TRUE.
*/ */
struct Cookie *Curl_cookie_add(struct CookieInfo *, bool header, char *line, struct Cookie *Curl_cookie_add(struct CookieInfo *, bool header, char *line,
char *domain); char *domain, char *path);
struct CookieInfo *Curl_cookie_init(char *, struct CookieInfo *, bool); struct CookieInfo *Curl_cookie_init(char *, struct CookieInfo *, bool);
struct Cookie *Curl_cookie_getlist(struct CookieInfo *, char *, char *, bool); struct Cookie *Curl_cookie_getlist(struct CookieInfo *, char *, char *, bool);

View File

@@ -243,6 +243,10 @@ SOURCE=.\url.c
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=.\share.c
# End Source File
# Begin Source File
SOURCE=.\version.c SOURCE=.\version.c
# End Source File # End Source File
# End Group # End Group
@@ -385,6 +389,22 @@ SOURCE=.\url.h
SOURCE=.\urldata.h SOURCE=.\urldata.h
# End Source File # End Source File
# Begin Source File
SOURCE=.\http_digest.c
# End Source File
# Begin Source File
SOURCE=.\md5.c
# End Source File
# Begin Source File
SOURCE=.\http_digest.h
# End Source File
# Begin Source File
SOURCE=.\md5.h
# End Source File
# End Group # End Group
# Begin Group "Resource Files" # Begin Group "Resource Files"

View File

@@ -44,7 +44,6 @@
#endif #endif
#include <netinet/in.h> #include <netinet/in.h>
#include <sys/time.h> #include <sys/time.h>
#include <sys/resource.h>
#ifdef HAVE_UNISTD_H #ifdef HAVE_UNISTD_H
#include <unistd.h> #include <unistd.h>
#endif #endif

View File

@@ -46,7 +46,6 @@
#endif #endif
#include <netinet/in.h> #include <netinet/in.h>
#include <sys/time.h> #include <sys/time.h>
#include <sys/resource.h>
#ifdef HAVE_UNISTD_H #ifdef HAVE_UNISTD_H
#include <unistd.h> #include <unistd.h>
#endif #endif
@@ -200,6 +199,7 @@ CURLcode curl_easy_setopt(CURL *curl, CURLoption tag, ...)
long param_long = 0; long param_long = 0;
void *param_obj = NULL; void *param_obj = NULL;
struct SessionHandle *data = curl; struct SessionHandle *data = curl;
CURLcode ret=CURLE_FAILED_INIT;
va_start(arg, tag); va_start(arg, tag);
@@ -213,20 +213,20 @@ 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); ret = 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); ret = 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); ret = Curl_setopt(data, tag, param_func);
} }
va_end(arg); va_end(arg);
return CURLE_OK; return ret;
} }
CURLcode curl_easy_perform(CURL *curl) CURLcode curl_easy_perform(CURL *curl)

View File

@@ -33,7 +33,7 @@
#include <string.h> #include <string.h>
/* The last #include file should be: */ /* The last #include file should be: */
#ifdef MALLOCDEBUG #ifdef CURLDEBUG
#include "memdebug.h" #include "memdebug.h"
#endif #endif
@@ -79,6 +79,10 @@ char *curl_escape(const char *string, int length)
return ns; return ns;
} }
#define ishex(in) ((in >= 'a' && in <= 'f') || \
(in >= 'A' && in <= 'F') || \
(in >= '0' && in <= '9'))
char *curl_unescape(const char *string, int length) char *curl_unescape(const char *string, int length)
{ {
int alloc = (length?length:(int)strlen(string))+1; int alloc = (length?length:(int)strlen(string))+1;
@@ -93,13 +97,19 @@ char *curl_unescape(const char *string, int length)
while(--alloc > 0) { while(--alloc > 0) {
in = *string; in = *string;
if('%' == in) { if(('%' == in) && ishex(string[1]) && ishex(string[2])) {
/* encoded part */ /* this is two hexadecimal digits following a '%' */
if(sscanf(string+1, "%02X", &hex)) { char hexstr[3];
in = hex; char *ptr;
string+=2; hexstr[0] = string[1];
alloc-=2; hexstr[1] = string[2];
} hexstr[2] = 0;
hex = strtol(hexstr, &ptr, 16);
in = hex;
string+=2;
alloc-=2;
} }
ns[index++] = in; ns[index++] = in;
@@ -109,6 +119,9 @@ char *curl_unescape(const char *string, int length)
return ns; return ns;
} }
/* For operating systems/environments that use different malloc/free
ssystems for the app and for this library, we provide a free that uses
the library's memory system */
void curl_free(void *p) void curl_free(void *p)
{ {
free(p); free(p);

View File

@@ -48,7 +48,6 @@
#include <netinet/in.h> #include <netinet/in.h>
#endif #endif
#include <sys/time.h> #include <sys/time.h>
#include <sys/resource.h>
#ifdef HAVE_UNISTD_H #ifdef HAVE_UNISTD_H
#include <unistd.h> #include <unistd.h>
#endif #endif
@@ -88,7 +87,7 @@
#include <curl/mprintf.h> #include <curl/mprintf.h>
/* The last #include file should be: */ /* The last #include file should be: */
#ifdef MALLOCDEBUG #ifdef CURLDEBUG
#include "memdebug.h" #include "memdebug.h"
#endif #endif

View File

@@ -124,15 +124,12 @@ Content-Disposition: form-data; name="FILECONTENT"
#include "strequal.h" #include "strequal.h"
/* The last #include file should be: */ /* The last #include file should be: */
#ifdef MALLOCDEBUG #ifdef CURLDEBUG
#include "memdebug.h" #include "memdebug.h"
#endif #endif
/* Length of the random boundary string. The risk of this being used /* Length of the random boundary string. */
in binary data is very close to zero, 64^32 makes #define BOUNDARY_LENGTH 40
6277101735386680763835789423207666416102355444464034512896
combinations... */
#define BOUNDARY_LENGTH 32
/* What kind of Content-Type to use on un-specified files with unrecognized /* What kind of Content-Type to use on un-specified files with unrecognized
extensions. */ extensions. */
@@ -520,7 +517,7 @@ static const char * ContentTypeForFilename (const char *filename,
{".jpg", "image/jpeg"}, {".jpg", "image/jpeg"},
{".jpeg", "image/jpeg"}, {".jpeg", "image/jpeg"},
{".txt", "text/plain"}, {".txt", "text/plain"},
{".html", "text/plain"} {".html", "text/html"}
}; };
if(prevtype) if(prevtype)
@@ -1049,22 +1046,23 @@ char *Curl_FormBoundary(void)
the same form won't be identical */ the same form won't be identical */
int i; int i;
static char table62[]= static char table16[]="abcdef0123456789";
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
retstring = (char *)malloc(BOUNDARY_LENGTH); retstring = (char *)malloc(BOUNDARY_LENGTH+1);
if(!retstring) if(!retstring)
return NULL; /* failed */ return NULL; /* failed */
srand(time(NULL)+randomizer++); /* seed */ srand(time(NULL)+randomizer++); /* seed */
strcpy(retstring, "curl"); /* bonus commercials 8*) */ strcpy(retstring, "----------------------------");
for(i=4; i<(BOUNDARY_LENGTH-1); i++) { for(i=strlen(retstring); i<BOUNDARY_LENGTH; i++)
retstring[i] = table62[rand()%62]; retstring[i] = table16[rand()%16];
}
retstring[BOUNDARY_LENGTH-1]=0; /* zero terminate */ /* 28 dashes and 12 hexadecimal digits makes 12^16 (184884258895036416)
combinations */
retstring[BOUNDARY_LENGTH]=0; /* zero terminate */
return retstring; return retstring;
} }

205
lib/ftp.c
View File

@@ -94,7 +94,7 @@
#include <curl/mprintf.h> #include <curl/mprintf.h>
/* The last #include file should be: */ /* The last #include file should be: */
#ifdef MALLOCDEBUG #ifdef CURLDEBUG
#include "memdebug.h" #include "memdebug.h"
#endif #endif
@@ -158,6 +158,7 @@ static CURLcode AllowServerConnect(struct SessionHandle *data,
infof(data, "Connection accepted from server\n"); infof(data, "Connection accepted from server\n");
conn->secondarysocket = s; conn->secondarysocket = s;
Curl_nonblock(s, TRUE); /* enable non-blocking */
} }
break; break;
} }
@@ -237,7 +238,7 @@ CURLcode Curl_GetFTPResponse(ssize_t *nreadp, /* return number of bytes read */
if(!ftp->cache) { if(!ftp->cache) {
readfd = rkeepfd; /* set every lap */ readfd = rkeepfd; /* set every lap */
interval.tv_sec = timeout; interval.tv_sec = 1; /* use 1 second timeout intervals */
interval.tv_usec = 0; interval.tv_usec = 0;
switch (select (sockfd+1, &readfd, NULL, NULL, &interval)) { switch (select (sockfd+1, &readfd, NULL, NULL, &interval)) {
@@ -246,9 +247,10 @@ CURLcode Curl_GetFTPResponse(ssize_t *nreadp, /* return number of bytes read */
failf(data, "Transfer aborted due to select() error: %d", errno); failf(data, "Transfer aborted due to select() error: %d", errno);
break; break;
case 0: /* timeout */ case 0: /* timeout */
result = CURLE_OPERATION_TIMEDOUT; if(Curl_pgrsUpdate(conn))
failf(data, "Transfer aborted due to timeout"); return CURLE_ABORTED_BY_CALLBACK;
break; continue; /* just continue in our loop for the timeout duration */
default: default:
break; break;
} }
@@ -407,9 +409,9 @@ CURLcode Curl_ftp_connect(struct connectdata *conn)
/* get some initial data into the ftp struct */ /* get some initial data into the ftp struct */
ftp->bytecountp = &conn->bytecount; ftp->bytecountp = &conn->bytecount;
/* no need to duplicate them, the data struct won't change */ /* no need to duplicate them, this connectdata struct won't change */
ftp->user = data->state.user; ftp->user = conn->user;
ftp->passwd = data->state.passwd; ftp->passwd = conn->passwd;
ftp->response_time = 3600; /* set default response time-out */ ftp->response_time = 3600; /* set default response time-out */
if (data->set.tunnel_thru_httpproxy) { if (data->set.tunnel_thru_httpproxy) {
@@ -510,7 +512,7 @@ CURLcode Curl_ftp_connect(struct connectdata *conn)
/* we may need to issue a KAUTH here to have access to the files /* we may need to issue a KAUTH here to have access to the files
* do it if user supplied a password * do it if user supplied a password
*/ */
if(data->state.passwd && *data->state.passwd) { if(conn->passwd && *conn->passwd) {
result = Curl_krb_kauth(conn); result = Curl_krb_kauth(conn);
if(result) if(result)
return result; return result;
@@ -726,7 +728,10 @@ CURLcode ftp_cwd(struct connectdata *conn, char *path)
if (result) if (result)
return result; return result;
if (ftpcode != 250) { /* According to RFC959, CWD is supposed to return 250 on success, but
there seem to be non-compliant FTP servers out there that return 200,
so we accept any '2xy' code here. */
if (ftpcode/100 != 2) {
failf(conn->data, "Couldn't cd to %s", path); failf(conn->data, "Couldn't cd to %s", path);
return CURLE_FTP_ACCESS_DENIED; return CURLE_FTP_ACCESS_DENIED;
} }
@@ -933,6 +938,7 @@ ftp_pasv_verbose(struct connectdata *conn,
# endif # endif
# else # else
(void)hostent_buf; /* avoid compiler warning */
answer = gethostbyaddr((char *) &address, sizeof(address), AF_INET); answer = gethostbyaddr((char *) &address, sizeof(address), AF_INET);
# endif # endif
#else #else
@@ -961,7 +967,7 @@ ftp_pasv_verbose(struct connectdata *conn,
#else #else
const int niflags = NI_NUMERICHOST | NI_NUMERICSERV; const int niflags = NI_NUMERICHOST | NI_NUMERICSERV;
#endif #endif
port = 0; /* unused, prevent warning */ (void)port; /* prevent compiler warning */
if (getnameinfo(addr->ai_addr, addr->ai_addrlen, if (getnameinfo(addr->ai_addr, addr->ai_addrlen,
nbuf, sizeof(nbuf), sbuf, sizeof(sbuf), niflags)) { nbuf, sizeof(nbuf), sbuf, sizeof(sbuf), niflags)) {
snprintf(nbuf, sizeof(nbuf), "?"); snprintf(nbuf, sizeof(nbuf), "?");
@@ -1076,7 +1082,8 @@ CURLcode ftp_use_port(struct connectdata *conn)
return CURLE_FTP_PORT_FAILED; return CURLE_FTP_PORT_FAILED;
} }
for (modep = (char **)mode; modep && *modep; modep++) { for (modep = (char **)(data->set.ftp_use_eprt?&mode[0]:&mode[2]);
modep && *modep; modep++) {
int lprtaf, eprtaf; int lprtaf, eprtaf;
int alen=0, plen=0; int alen=0, plen=0;
@@ -1177,7 +1184,6 @@ CURLcode ftp_use_port(struct connectdata *conn)
return result; return result;
if (ftpcode != 200) { if (ftpcode != 200) {
failf(data, "Server does not grok %s", *modep);
continue; continue;
} }
else else
@@ -1186,6 +1192,7 @@ CURLcode ftp_use_port(struct connectdata *conn)
if (!*modep) { if (!*modep) {
sclose(portsock); sclose(portsock);
failf(data, "PORT command attempts failed");
return CURLE_FTP_PORT_FAILED; return CURLE_FTP_PORT_FAILED;
} }
/* we set the secondary socket variable to this for now, it /* we set the secondary socket variable to this for now, it
@@ -1206,7 +1213,13 @@ CURLcode ftp_use_port(struct connectdata *conn)
bool sa_filled_in = FALSE; bool sa_filled_in = FALSE;
if(data->set.ftpport) { if(data->set.ftpport) {
if(Curl_if2ip(data->set.ftpport, myhost, sizeof(myhost))) { in_addr_t in;
/* First check if the given name is an IP address */
in=inet_addr(data->set.ftpport);
if((in == CURL_INADDR_NONE) &&
Curl_if2ip(data->set.ftpport, myhost, sizeof(myhost))) {
h = Curl_resolv(data, myhost, 0); h = Curl_resolv(data, myhost, 0);
} }
else { else {
@@ -1918,8 +1931,14 @@ CURLcode Curl_ftp_nextconnect(struct connectdata *conn)
return result; return result;
} }
else { else {
failf(data, "%s", buf+4); if(dirlist && (ftpcode == 450)) {
return CURLE_FTP_COULDNT_RETR_FILE; /* simply no matching files */
ftp->no_transfer = TRUE; /* don't think we should download anything */
}
else {
failf(data, "%s", buf+4);
return CURLE_FTP_COULDNT_RETR_FILE;
}
} }
} }
@@ -1963,17 +1982,46 @@ CURLcode ftp_perform(struct connectdata *conn,
return result; return result;
} }
/* change directory first! */ {
if(ftp->dir && ftp->dir[0]) { int i; /* counter for loop */
if ((result = ftp_cwd(conn, ftp->dir)) != CURLE_OK) for (i=0; ftp->dirs[i]; i++) {
/* RFC 1738 says empty components should be respected too */
if ((result = ftp_cwd(conn, ftp->dirs[i])) != CURLE_OK)
return result; return result;
}
} }
/* Requested time of file? */ /* Requested time of file or time-depended transfer? */
if(data->set.get_filetime && ftp->file) { if((data->set.get_filetime || data->set.timecondition) &&
ftp->file) {
result = ftp_getfiletime(conn, ftp->file); result = ftp_getfiletime(conn, ftp->file);
if(result) if(result)
return result; return result;
if(data->set.timecondition) {
if((data->info.filetime > 0) && (data->set.timevalue > 0)) {
switch(data->set.timecondition) {
case TIMECOND_IFMODSINCE:
default:
if(data->info.filetime < data->set.timevalue) {
infof(data, "The requested document is not new enough\n");
ftp->no_transfer = TRUE; /* mark this to not transfer data */
return CURLE_OK;
}
break;
case TIMECOND_IFUNMODSINCE:
if(data->info.filetime > data->set.timevalue) {
infof(data, "The requested document is not old enough\n");
ftp->no_transfer = TRUE; /* mark this to not transfer data */
return CURLE_OK;
}
break;
} /* switch */
}
else {
infof(data, "Skipping time comparison\n");
}
}
} }
/* If we have selected NOBODY and HEADER, it means that we only want file /* If we have selected NOBODY and HEADER, it means that we only want file
@@ -2013,10 +2061,10 @@ CURLcode ftp_perform(struct connectdata *conn,
struct tm buffer; struct tm buffer;
tm = (struct tm *)localtime_r(&data->info.filetime, &buffer); tm = (struct tm *)localtime_r(&data->info.filetime, &buffer);
#else #else
tm = localtime((unsigned long *)&data->info.filetime); tm = localtime(&data->info.filetime);
#endif #endif
/* format: "Tue, 15 Nov 1994 12:45:26 GMT" */ /* format: "Tue, 15 Nov 1994 12:45:26 GMT" */
strftime(buf, BUFSIZE-1, "Last-Modified: %a, %d %b %Y %H:%M:%S %Z\r\n", strftime(buf, BUFSIZE-1, "Last-Modified: %a, %d %b %Y %H:%M:%S GMT\r\n",
tm); tm);
result = Curl_client_write(data, CLIENTWRITE_BOTH, buf, 0); result = Curl_client_write(data, CLIENTWRITE_BOTH, buf, 0);
if(result) if(result)
@@ -2061,34 +2109,81 @@ CURLcode ftp_perform(struct connectdata *conn,
*/ */
CURLcode Curl_ftp(struct connectdata *conn) CURLcode Curl_ftp(struct connectdata *conn)
{ {
CURLcode retcode; CURLcode retcode=CURLE_OK;
bool connected; bool connected=0;
struct SessionHandle *data = conn->data; struct SessionHandle *data = conn->data;
struct FTP *ftp; struct FTP *ftp;
int dirlength=0; /* 0 forces strlen() */
char *slash_pos; /* position of the first '/' char in curpos */
char *cur_pos=conn->ppath; /* current position in ppath. point at the begin
of next path component */
int path_part=0;/* current path component */
/* the ftp struct is already inited in ftp_connect() */ /* the ftp struct is already inited in ftp_connect() */
ftp = conn->proto.ftp; ftp = conn->proto.ftp;
conn->size = -1; /* make sure this is unknown at this point */ conn->size = -1; /* make sure this is unknown at this point */
/* We split the path into dir and file parts *before* we URLdecode Curl_pgrsSetUploadCounter(data, 0);
it */ Curl_pgrsSetDownloadCounter(data, 0);
ftp->file = strrchr(conn->ppath, '/'); Curl_pgrsSetUploadSize(data, 0);
if(ftp->file) { Curl_pgrsSetDownloadSize(data, 0);
if(ftp->file != conn->ppath)
dirlength=ftp->file-conn->ppath; /* don't count the traling slash */
ftp->file++; /* point to the first letter in the file name part or /* fixed : initialize ftp->dirs[xxx] to NULL !
remain NULL */ is done in Curl_ftp_connect() */
}
else { /* parse the URL path into separate path components */
ftp->file = conn->ppath; /* there's only a file part */ while((slash_pos=strchr(cur_pos, '/'))) {
/* 1 or 0 to indicate absolute directory */
bool absolute_dir = (cur_pos - conn->ppath > 0) && (path_part == 0);
/* seek out the next path component */
if (slash_pos-cur_pos) {
/* we skip empty path components, like "x//y" since the FTP command CWD
requires a parameter and a non-existant parameter a) doesn't work on
many servers and b) has no effect on the others. */
ftp->dirs[path_part] = curl_unescape(cur_pos - absolute_dir,
slash_pos - cur_pos + absolute_dir);
if (!ftp->dirs[path_part]) { /* run out of memory ... */
failf(data, "no memory");
retcode = CURLE_OUT_OF_MEMORY;
}
}
else {
cur_pos = slash_pos + 1; /* jump to the rest of the string */
continue;
}
if(!retcode) {
cur_pos = slash_pos + 1; /* jump to the rest of the string */
if(++path_part >= (CURL_MAX_FTP_DIRDEPTH-1)) {
/* too deep, we need the last entry to be kept NULL at all
times to signal end of list */
failf(data, "too deep dir hierarchy");
retcode = CURLE_URL_MALFORMAT;
}
}
if (retcode) {
int i;
for (i=0;i<path_part;i++) { /* free previous parts */
free(ftp->dirs[i]);
ftp->dirs[i]=NULL;
}
return retcode; /* failure */
}
} }
ftp->file = cur_pos; /* the rest is the file name */
if(*ftp->file) { if(*ftp->file) {
ftp->file = curl_unescape(ftp->file, 0); ftp->file = curl_unescape(ftp->file, 0);
if(NULL == ftp->file) { if(NULL == ftp->file) {
int i;
for (i=0;i<path_part;i++){
free(ftp->dirs[i]);
ftp->dirs[i]=NULL;
}
failf(data, "no memory"); failf(data, "no memory");
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
} }
@@ -2096,26 +2191,23 @@ CURLcode Curl_ftp(struct connectdata *conn)
else else
ftp->file=NULL; /* instead of point to a zero byte, we make it a NULL ftp->file=NULL; /* instead of point to a zero byte, we make it a NULL
pointer */ pointer */
ftp->urlpath = conn->ppath;
if(dirlength) {
ftp->dir = curl_unescape(ftp->urlpath, dirlength);
if(NULL == ftp->dir) {
if(ftp->file)
free(ftp->file);
failf(data, "no memory");
return CURLE_OUT_OF_MEMORY; /* failure */
}
}
else
ftp->dir = NULL;
retcode = ftp_perform(conn, &connected); retcode = ftp_perform(conn, &connected);
if(CURLE_OK == retcode) { if(CURLE_OK == retcode) {
if(connected) if(connected)
retcode = Curl_ftp_nextconnect(conn); retcode = Curl_ftp_nextconnect(conn);
else
if(retcode && (conn->secondarysocket >= 0)) {
/* Failure detected, close the second socket if it was created already */
sclose(conn->secondarysocket);
conn->secondarysocket = -1;
}
if(ftp->no_transfer)
/* no data to transfer */
retcode=Curl_Transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
else if(!connected)
/* since we didn't connect now, we want do_more to get called */ /* since we didn't connect now, we want do_more to get called */
conn->bits.do_more = TRUE; conn->bits.do_more = TRUE;
} }
@@ -2182,6 +2274,7 @@ CURLcode Curl_ftpsendf(struct connectdata *conn,
CURLcode Curl_ftp_disconnect(struct connectdata *conn) CURLcode Curl_ftp_disconnect(struct connectdata *conn)
{ {
struct FTP *ftp= conn->proto.ftp; struct FTP *ftp= conn->proto.ftp;
int i;
/* The FTP session may or may not have been allocated/setup at this point! */ /* The FTP session may or may not have been allocated/setup at this point! */
if(ftp) { if(ftp) {
@@ -2191,10 +2284,12 @@ CURLcode Curl_ftp_disconnect(struct connectdata *conn)
free(ftp->cache); free(ftp->cache);
if(ftp->file) if(ftp->file)
free(ftp->file); free(ftp->file);
if(ftp->dir) for (i=0;ftp->dirs[i];i++){
free(ftp->dir); free(ftp->dirs[i]);
ftp->dirs[i]=NULL;
}
ftp->file = ftp->dir = NULL; /* zero */ ftp->file = NULL; /* zero */
} }
return CURLE_OK; return CURLE_OK;
} }

View File

@@ -35,7 +35,7 @@
#include <unixlib.h> #include <unixlib.h>
#endif #endif
#ifdef MALLOCDEBUG #ifdef CURLDEBUG
#include "memdebug.h" #include "memdebug.h"
#endif #endif

View File

@@ -36,8 +36,10 @@
#endif #endif
/* Make this the last #include */ /* Make this the last #include */
#ifdef MALLOCDEBUG #ifdef CURLDEBUG
#include "memdebug.h" #include "memdebug.h"
#else
#include <stdlib.h>
#endif #endif
/* /*

View File

@@ -89,7 +89,7 @@ char *getpass_r(const char *prompt, char *buffer, size_t buflen)
#endif #endif
/* The last #include file should be: */ /* The last #include file should be: */
#ifdef MALLOCDEBUG #ifdef CURLDEBUG
#include "memdebug.h" #include "memdebug.h"
#endif #endif
@@ -99,7 +99,7 @@ char *getpass_r(const char *prompt, char *buffer, size_t buflen)
char infp_fclose = 0; char infp_fclose = 0;
FILE *outfp; FILE *outfp;
RETSIGTYPE (*sigint)(); RETSIGTYPE (*sigint)();
#ifndef __EMX__ #ifdef SIGTSTP
RETSIGTYPE (*sigtstp)(); RETSIGTYPE (*sigtstp)();
#endif #endif
size_t bytes_read; size_t bytes_read;
@@ -117,9 +117,7 @@ char *getpass_r(const char *prompt, char *buffer, size_t buflen)
#endif #endif
sigint = signal(SIGINT, SIG_IGN); sigint = signal(SIGINT, SIG_IGN);
/* 20000318 mgs #ifdef SIGTSTP
* this is needed by the emx system, SIGTSTP is not a supported signal */
#ifndef __EMX__
sigtstp = signal(SIGTSTP, SIG_IGN); sigtstp = signal(SIGTSTP, SIG_IGN);
#endif #endif
@@ -181,7 +179,7 @@ char *getpass_r(const char *prompt, char *buffer, size_t buflen)
#endif #endif
signal(SIGINT, sigint); signal(SIGINT, sigint);
#ifndef __EMX__ #ifdef SIGTSTP
signal(SIGTSTP, sigtstp); signal(SIGTSTP, sigtstp);
#endif #endif

View File

@@ -29,7 +29,7 @@
#include "hash.h" #include "hash.h"
#include "llist.h" #include "llist.h"
#ifdef MALLOCDEBUG #ifdef CURLDEBUG
/* this must be the last include file */ /* this must be the last include file */
#include "memdebug.h" #include "memdebug.h"
#endif #endif

View File

@@ -74,7 +74,7 @@
#endif #endif
/* The last #include file should be: */ /* The last #include file should be: */
#ifdef MALLOCDEBUG #ifdef CURLDEBUG
#include "memdebug.h" #include "memdebug.h"
#endif #endif
@@ -192,7 +192,7 @@ hostcache_prune(curl_hash *hostcache, int cache_timeout, int now)
hostcache_timestamp_remove); hostcache_timestamp_remove);
} }
#if defined(MALLOCDEBUG) && defined(AGGRESIVE_TEST) #if defined(CURLDEBUG) && defined(AGGRESIVE_TEST)
/* Called from Curl_done() to check that there's no DNS cache entry with /* Called from Curl_done() to check that there's no DNS cache entry with
a non-zero counter left. */ a non-zero counter left. */
void Curl_scan_cache_used(void *user, void *ptr) void Curl_scan_cache_used(void *user, void *ptr)
@@ -239,7 +239,7 @@ struct Curl_dns_entry *Curl_resolv(struct SessionHandle *data,
will generate a signal and we will siglongjmp() from that here */ will generate a signal and we will siglongjmp() from that here */
if(!data->set.no_signal && sigsetjmp(curl_jmpenv, 1)) { if(!data->set.no_signal && sigsetjmp(curl_jmpenv, 1)) {
/* this is coming from a siglongjmp() */ /* this is coming from a siglongjmp() */
failf(data, "name lookup time-outed"); failf(data, "name lookup timed out");
return NULL; return NULL;
} }
#endif #endif
@@ -252,9 +252,7 @@ struct Curl_dns_entry *Curl_resolv(struct SessionHandle *data,
return NULL; return NULL;
if(data->share) if(data->share)
{
Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE); Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
}
/* See if its already in our dns cache */ /* See if its already in our dns cache */
dns = Curl_hash_pick(data->hostcache, entry_id, entry_len+1); dns = Curl_hash_pick(data->hostcache, entry_id, entry_len+1);
@@ -282,7 +280,7 @@ struct Curl_dns_entry *Curl_resolv(struct SessionHandle *data,
dns->timestamp = now; dns->timestamp = now;
dns->inuse++; /* mark entry as in-use */ dns->inuse++; /* mark entry as in-use */
#ifdef MALLOCDEBUG #ifdef CURLDEBUG
dns->entry_id = entry_id; dns->entry_id = entry_id;
#endif #endif
@@ -297,14 +295,13 @@ struct Curl_dns_entry *Curl_resolv(struct SessionHandle *data,
void Curl_resolv_unlock(struct SessionHandle *data, struct Curl_dns_entry *dns) void Curl_resolv_unlock(struct SessionHandle *data, struct Curl_dns_entry *dns)
{ {
if(data->share) if(data->share)
{
Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE); Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
}
dns->inuse--; dns->inuse--;
if(data->share) if(data->share)
{
Curl_share_unlock(data, CURL_LOCK_DATA_DNS); Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
}
} }
/* /*
@@ -337,7 +334,7 @@ void Curl_freednsinfo(void *freethis)
#ifdef ENABLE_IPV6 #ifdef ENABLE_IPV6
#ifdef MALLOCDEBUG #ifdef CURLDEBUG
/* These two are strictly for memory tracing and are using the same /* These two are strictly for memory tracing and are using the same
* style as the family otherwise present in memdebug.c. I put these ones * style as the family otherwise present in memdebug.c. I put these ones
* here since they require a bunch of struct types I didn't wanna include * here since they require a bunch of struct types I didn't wanna include
@@ -455,18 +452,22 @@ static struct hostent* pack_hostent(char** buf, struct hostent* orig)
copy->h_aliases = (char**)bufptr; copy->h_aliases = (char**)bufptr;
/* Figure out how many aliases there are */ /* Figure out how many aliases there are */
for (i = 0; orig->h_aliases[i] != NULL; ++i); for (i = 0; orig->h_aliases && orig->h_aliases[i]; ++i);
/* Reserve room for the array */ /* Reserve room for the array */
bufptr += (i + 1) * sizeof(char*); bufptr += (i + 1) * sizeof(char*);
/* Clone all known aliases */ /* Clone all known aliases */
for(i = 0; (str = orig->h_aliases[i]); i++) { if(orig->h_aliases) {
len = strlen(str) + 1; for(i = 0; (str = orig->h_aliases[i]); i++) {
strncpy(bufptr, str, len); len = strlen(str) + 1;
copy->h_aliases[i] = bufptr; strncpy(bufptr, str, len);
bufptr += len; copy->h_aliases[i] = bufptr;
bufptr += len;
}
} }
/* if(!orig->h_aliases) i was already set to 0 */
/* Terminate the alias list with a NULL */ /* Terminate the alias list with a NULL */
copy->h_aliases[i] = NULL; copy->h_aliases[i] = NULL;
@@ -532,10 +533,6 @@ static char *MakeIP(unsigned long num, char *addr, int addr_len)
return (addr); return (addr);
} }
#ifndef INADDR_NONE
#define INADDR_NONE (in_addr_t) ~0
#endif
static void hostcache_fixoffset(struct hostent *h, int offset) static void hostcache_fixoffset(struct hostent *h, int offset)
{ {
int i=0; int i=0;
@@ -573,7 +570,8 @@ static Curl_addrinfo *my_getaddrinfo(struct SessionHandle *data,
port=0; /* unused in IPv4 code */ port=0; /* unused in IPv4 code */
ret = 0; /* to prevent the compiler warning */ ret = 0; /* to prevent the compiler warning */
if ( (in=inet_addr(hostname)) != INADDR_NONE ) { in=inet_addr(hostname);
if (in != CURL_INADDR_NONE) {
struct in_addr *addrentry; struct in_addr *addrentry;
struct namebuf { struct namebuf {
struct hostent hostentry; struct hostent hostentry;
@@ -630,7 +628,7 @@ static Curl_addrinfo *my_getaddrinfo(struct SessionHandle *data,
step_size+=200; step_size+=200;
} }
#ifdef MALLOCDEBUG #ifdef CURLDEBUG
infof(data, "gethostbyname_r() uses %d bytes\n", step_size); infof(data, "gethostbyname_r() uses %d bytes\n", step_size);
#endif #endif
@@ -680,7 +678,7 @@ static Curl_addrinfo *my_getaddrinfo(struct SessionHandle *data,
if(!h) /* failure */ if(!h) /* failure */
res=1; res=1;
#ifdef MALLOCDEBUG #ifdef CURLDEBUG
infof(data, "gethostbyname_r() uses %d bytes\n", step_size); infof(data, "gethostbyname_r() uses %d bytes\n", step_size);
#endif #endif
if(!res) { if(!res) {

View File

@@ -41,7 +41,7 @@ struct Curl_dns_entry {
time_t timestamp; time_t timestamp;
long inuse; /* use-counter, make very sure you decrease this long inuse; /* use-counter, make very sure you decrease this
when you're done using the address you received */ when you're done using the address you received */
#ifdef MALLOCDEBUG #ifdef CURLDEBUG
char *entry_id; char *entry_id;
#endif #endif
}; };
@@ -70,7 +70,7 @@ void Curl_freeaddrinfo(Curl_addrinfo *freeaddr);
/* free cached name info */ /* free cached name info */
void Curl_freednsinfo(void *freethis); void Curl_freednsinfo(void *freethis);
#ifdef MALLOCDEBUG #ifdef CURLDEBUG
void curl_freeaddrinfo(struct addrinfo *freethis, void curl_freeaddrinfo(struct addrinfo *freethis,
int line, const char *source); int line, const char *source);
int curl_getaddrinfo(char *hostname, char *service, int curl_getaddrinfo(char *hostname, char *service,
@@ -79,4 +79,11 @@ int curl_getaddrinfo(char *hostname, char *service,
int line, const char *source); int line, const char *source);
#endif #endif
#ifndef INADDR_NONE
#define CURL_INADDR_NONE (in_addr_t) ~0
#else
#define CURL_INADDR_NONE INADDR_NONE
#endif
#endif #endif

View File

@@ -54,7 +54,6 @@
#endif #endif
#endif #endif
#include <sys/resource.h>
#ifdef HAVE_UNISTD_H #ifdef HAVE_UNISTD_H
#include <unistd.h> #include <unistd.h>
#endif #endif
@@ -89,12 +88,15 @@
#include "cookie.h" #include "cookie.h"
#include "strequal.h" #include "strequal.h"
#include "ssluse.h" #include "ssluse.h"
#include "http_digest.h"
#include "http_ntlm.h"
#include "http_negotiate.h"
#define _MPRINTF_REPLACE /* use our functions only */ #define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h> #include <curl/mprintf.h>
/* The last #include file should be: */ /* The last #include file should be: */
#ifdef MALLOCDEBUG #ifdef CURLDEBUG
#include "memdebug.h" #include "memdebug.h"
#endif #endif
@@ -190,6 +192,7 @@ CURLcode add_buffer_send(send_buffer *in,
char *ptr; char *ptr;
int size; int size;
struct HTTP *http = conn->proto.http; struct HTTP *http = conn->proto.http;
int sendsize;
/* The looping below is required since we use non-blocking sockets, but due /* The looping below is required since we use non-blocking sockets, but due
to the circumstances we will just loop and try again and again etc */ to the circumstances we will just loop and try again and again etc */
@@ -197,7 +200,28 @@ CURLcode add_buffer_send(send_buffer *in,
ptr = in->buffer; ptr = in->buffer;
size = in->size_used; size = in->size_used;
res = Curl_write(conn, sockfd, ptr, size, &amount); if(conn->protocol & PROT_HTTPS) {
/* We never send more than CURL_MAX_WRITE_SIZE bytes in one single chunk
when we speak HTTPS, as if only a fraction of it is sent now, this data
needs to fit into the normal read-callback buffer later on and that
buffer is using this size.
*/
sendsize= (size > CURL_MAX_WRITE_SIZE)?CURL_MAX_WRITE_SIZE:size;
/* OpenSSL is very picky and we must send the SAME buffer pointer to the
library when we attempt to re-send this buffer. Sending the same data
is not enough, we must use the exact same address. For this reason, we
must copy the data to the uploadbuffer first, since that is the buffer
we will be using if this send is retried later.
*/
memcpy(conn->data->state.uploadbuffer, ptr, sendsize);
ptr = conn->data->state.uploadbuffer;
}
else
sendsize = size;
res = Curl_write(conn, sockfd, ptr, sendsize, &amount);
if(CURLE_OK == res) { if(CURLE_OK == res) {
@@ -213,7 +237,8 @@ CURLcode add_buffer_send(send_buffer *in,
and wait until it might work again. */ and wait until it might work again. */
size -= amount; size -= amount;
ptr += amount;
ptr = in->buffer + amount;
/* backup the currently set pointers */ /* backup the currently set pointers */
http->backup.fread = conn->fread; http->backup.fread = conn->fread;
@@ -491,16 +516,16 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn,
/* a newline is CRLF in ftp-talk, so the CR is ignored as /* a newline is CRLF in ftp-talk, so the CR is ignored as
the line isn't really terminated until the LF comes */ the line isn't really terminated until the LF comes */
/* output debug output if that is requested */
if(data->set.verbose)
Curl_debug(data, CURLINFO_DATA_IN, line_start, perline);
if('\r' == line_start[0]) { if('\r' == line_start[0]) {
/* end of headers */ /* end of headers */
keepon=FALSE; keepon=FALSE;
break; /* breaks out of loop, not switch */ break; /* breaks out of loop, not switch */
} }
/* output debug output if that is requested */
if(data->set.verbose)
Curl_debug(data, CURLINFO_HEADER_IN, line_start, perline);
if(2 == sscanf(line_start, "HTTP/1.%d %d", if(2 == sscanf(line_start, "HTTP/1.%d %d",
&subversion, &subversion,
&httperror)) { &httperror)) {
@@ -591,11 +616,15 @@ CURLcode Curl_http_done(struct connectdata *conn)
conn->fread = data->set.fread; /* restore */ conn->fread = data->set.fread; /* restore */
conn->fread_in = data->set.in; /* restore */ conn->fread_in = data->set.in; /* restore */
if (http == NULL)
return CURLE_OK;
if(http->send_buffer) { if(http->send_buffer) {
send_buffer *buff = http->send_buffer; send_buffer *buff = http->send_buffer;
free(buff->buffer); free(buff->buffer);
free(buff); free(buff);
http->send_buffer = NULL; /* cleaer the pointer */
} }
if(HTTPREQ_POST_FORM == data->set.httpreq) { if(HTTPREQ_POST_FORM == data->set.httpreq) {
@@ -616,6 +645,25 @@ CURLcode Curl_http_done(struct connectdata *conn)
return CURLE_OK; return CURLE_OK;
} }
static CURLcode Curl_output_basic(struct connectdata *conn)
{
char *authorization;
struct SessionHandle *data=conn->data;
sprintf(data->state.buffer, "%s:%s", conn->user, conn->passwd);
if(Curl_base64_encode(data->state.buffer, strlen(data->state.buffer),
&authorization) >= 0) {
if(conn->allocptr.userpwd)
free(conn->allocptr.userpwd);
conn->allocptr.userpwd = aprintf( "Authorization: Basic %s\015\012",
authorization);
free(authorization);
}
else
return CURLE_OUT_OF_MEMORY;
return CURLE_OK;
}
CURLcode Curl_http(struct connectdata *conn) CURLcode Curl_http(struct connectdata *conn)
{ {
struct SessionHandle *data=conn->data; struct SessionHandle *data=conn->data;
@@ -626,6 +674,8 @@ CURLcode Curl_http(struct connectdata *conn)
char *ppath = conn->ppath; /* three previous function arguments */ char *ppath = conn->ppath; /* three previous function arguments */
char *host = conn->name; char *host = conn->name;
const char *te = ""; /* tranfer-encoding */ const char *te = ""; /* tranfer-encoding */
char *ptr;
char *request;
if(!conn->proto.http) { if(!conn->proto.http) {
/* Only allocate this struct if we don't already have it! */ /* Only allocate this struct if we don't already have it! */
@@ -646,6 +696,13 @@ CURLcode Curl_http(struct connectdata *conn)
data->set.upload) { data->set.upload) {
data->set.httpreq = HTTPREQ_PUT; data->set.httpreq = HTTPREQ_PUT;
} }
request = data->set.customrequest?
data->set.customrequest:
(data->set.no_body?(char *)"HEAD":
((HTTPREQ_POST == data->set.httpreq) ||
(HTTPREQ_POST_FORM == data->set.httpreq))?(char *)"POST":
(HTTPREQ_PUT == data->set.httpreq)?(char *)"PUT":(char *)"GET");
/* The User-Agent string has been built in url.c already, because it might /* The User-Agent string has been built in url.c already, because it might
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
@@ -656,27 +713,50 @@ CURLcode Curl_http(struct connectdata *conn)
conn->allocptr.uagent=NULL; conn->allocptr.uagent=NULL;
} }
if((conn->bits.user_passwd) && !checkheaders(data, "Authorization:")) { /* To prevent the user+password to get sent to other than the original
char *authorization; host due to a location-follow, we do some weirdo checks here */
if(!data->state.this_is_a_follow ||
!data->state.auth_host ||
curl_strequal(data->state.auth_host, conn->hostname) ||
data->set.http_disable_hostname_check_before_authentication) {
/* To prevent the user+password to get sent to other than the original #ifdef GSSAPI
host due to a location-follow, we do some weirdo checks here */ if((data->state.authwant == CURLAUTH_GSSNEGOTIATE) &&
if(!data->state.this_is_a_follow || data->state.negotiate.context &&
!data->state.auth_host || !GSS_ERROR(data->state.negotiate.status)) {
curl_strequal(data->state.auth_host, conn->hostname) || result = Curl_output_negotiate(conn);
data->set.http_disable_hostname_check_before_authentication) { if (result)
sprintf(data->state.buffer, "%s:%s", return result;
data->state.user, data->state.passwd); }
if(Curl_base64_encode(data->state.buffer, strlen(data->state.buffer), else
&authorization) >= 0) { #endif
if(conn->allocptr.userpwd) #ifdef USE_SSLEAY
free(conn->allocptr.userpwd); if(data->state.authwant == CURLAUTH_NTLM) {
conn->allocptr.userpwd = aprintf( "Authorization: Basic %s\015\012", result = Curl_output_ntlm(conn, FALSE);
authorization); if(result)
free(authorization); return result;
}
else
#endif
{
if((data->state.authwant == CURLAUTH_DIGEST) &&
data->state.digest.nonce) {
result = Curl_output_digest(conn,
(unsigned char *)request,
(unsigned char *)ppath);
if(result)
return result;
}
else if((data->state.authwant == CURLAUTH_BASIC) && /* Basic */
conn->bits.user_passwd &&
!checkheaders(data, "Authorization:")) {
result = Curl_output_basic(conn);
if(result)
return result;
} }
} }
} }
if((data->change.referer) && !checkheaders(data, "Referer:")) { if((data->change.referer) && !checkheaders(data, "Referer:")) {
if(conn->allocptr.ref) if(conn->allocptr.ref)
free(conn->allocptr.ref); free(conn->allocptr.ref);
@@ -714,30 +794,30 @@ CURLcode Curl_http(struct connectdata *conn)
} }
} }
if(data->cookies) { ptr = checkheaders(data, "Host:");
co = Curl_cookie_getlist(data->cookies, if(ptr) {
host, ppath, /* If we have a given custom Host: header, we extract the host name
(bool)(conn->protocol&PROT_HTTPS?TRUE:FALSE)); in order to possibly use it for cookie reasons later on. */
} char *start = ptr+strlen("Host:");
if (data->change.proxy && *data->change.proxy && char *ptr;
!data->set.tunnel_thru_httpproxy && while(*start && isspace((int)*start ))
!(conn->protocol&PROT_HTTPS)) { start++;
/* The path sent to the proxy is in fact the entire URL */ ptr = start; /* start host-scanning here */
ppath = data->change.url;
}
if(HTTPREQ_POST_FORM == data->set.httpreq) {
/* we must build the whole darned post sequence first, so that we have
a size of the whole shebang before we start to send it */
result = Curl_getFormData(&http->sendit, data->set.httppost,
&http->postsize);
if(CURLE_OK != result) {
/* Curl_getFormData() doesn't use failf() */
failf(data, "failed creating formpost data");
return result;
}
}
if(!checkheaders(data, "Host:")) { /* scan through the string to find the end (space or colon) */
while(*ptr && !isspace((int)*ptr) && !(':'==*ptr))
ptr++;
if(ptr != start) {
int len=ptr-start;
conn->allocptr.cookiehost = malloc(len+1);
if(!conn->allocptr.cookiehost)
return CURLE_OUT_OF_MEMORY;
memcpy(conn->allocptr.cookiehost, start, len);
conn->allocptr.cookiehost[len]=0;
}
}
else {
/* if ptr_host is already set, it is almost OK since we only re-use /* if ptr_host is already set, it is almost OK since we only re-use
connections to the very same host and port, but when we use a 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: proxy we have a persistant connect and yet we must change the Host:
@@ -765,6 +845,32 @@ CURLcode Curl_http(struct connectdata *conn)
conn->remote_port); conn->remote_port);
} }
if(data->cookies) {
co = Curl_cookie_getlist(data->cookies,
conn->allocptr.cookiehost?
conn->allocptr.cookiehost:host, ppath,
(bool)(conn->protocol&PROT_HTTPS?TRUE:FALSE));
}
if (conn->bits.httpproxy &&
!data->set.tunnel_thru_httpproxy &&
!(conn->protocol&PROT_HTTPS)) {
/* The path sent to the proxy is in fact the entire URL */
ppath = data->change.url;
}
if(HTTPREQ_POST_FORM == data->set.httpreq) {
/* we must build the whole darned post sequence first, so that we have
a size of the whole shebang before we start to send it */
result = Curl_getFormData(&http->sendit, data->set.httppost,
&http->postsize);
if(CURLE_OK != result) {
/* Curl_getFormData() doesn't use failf() */
failf(data, "failed creating formpost data");
return result;
}
}
if(!checkheaders(data, "Pragma:")) if(!checkheaders(data, "Pragma:"))
http->p_pragma = "Pragma: no-cache\r\n"; http->p_pragma = "Pragma: no-cache\r\n";
@@ -861,13 +967,14 @@ CURLcode Curl_http(struct connectdata *conn)
} }
} }
do { {
/* Use 1.1 unless the use specificly asked for 1.0 */ /* Use 1.1 unless the use specificly asked for 1.0 */
const char *httpstring= const char *httpstring=
data->set.httpversion==CURL_HTTP_VERSION_1_0?"1.0":"1.1"; data->set.httpversion==CURL_HTTP_VERSION_1_0?"1.0":"1.1";
send_buffer *req_buffer; send_buffer *req_buffer;
struct curl_slist *headers=data->set.headers; struct curl_slist *headers=data->set.headers;
size_t postsize;
/* initialize a dynamic send-buffer */ /* initialize a dynamic send-buffer */
req_buffer = add_buffer_init(); req_buffer = add_buffer_init();
@@ -875,7 +982,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/%s\r\n" /* path */ "%s HTTP/%s\r\n" /* path + HTTP version */
"%s" /* proxyuserpwd */ "%s" /* proxyuserpwd */
"%s" /* userpwd */ "%s" /* userpwd */
"%s" /* range */ "%s" /* range */
@@ -888,16 +995,12 @@ CURLcode Curl_http(struct connectdata *conn)
"%s" /* referer */ "%s" /* referer */
"%s",/* transfer-encoding */ "%s",/* transfer-encoding */
data->set.customrequest?data->set.customrequest: request,
(data->set.no_body?"HEAD": ppath,
((HTTPREQ_POST == data->set.httpreq) || httpstring,
(HTTPREQ_POST_FORM == data->set.httpreq))?"POST": (conn->bits.httpproxy && conn->allocptr.proxyuserpwd)?
(HTTPREQ_PUT == data->set.httpreq)?"PUT":"GET"), conn->allocptr.proxyuserpwd:"",
ppath, httpstring, conn->allocptr.userpwd?conn->allocptr.userpwd:"",
(conn->bits.proxy_user_passwd &&
conn->allocptr.proxyuserpwd)?conn->allocptr.proxyuserpwd:"",
(conn->bits.user_passwd && conn->allocptr.userpwd)?
conn->allocptr.userpwd:"",
(conn->bits.use_range && conn->allocptr.rangeline)? (conn->bits.use_range && conn->allocptr.rangeline)?
conn->allocptr.rangeline:"", conn->allocptr.rangeline:"",
(data->set.useragent && *data->set.useragent && conn->allocptr.uagent)? (data->set.useragent && *data->set.useragent && conn->allocptr.uagent)?
@@ -1105,6 +1208,11 @@ CURLcode Curl_http(struct connectdata *conn)
case HTTPREQ_POST: case HTTPREQ_POST:
/* this is the simple POST, using x-www-form-urlencoded style */ /* this is the simple POST, using x-www-form-urlencoded style */
/* store the size of the postfields */
postsize = data->set.postfieldsize?
data->set.postfieldsize:
(data->set.postfields?strlen(data->set.postfields):0);
if(!conn->bits.upload_chunky) { if(!conn->bits.upload_chunky) {
/* We only set Content-Length and allow a custom Content-Length if /* We only set Content-Length and allow a custom Content-Length if
we don't upload data chunked, as RFC2616 forbids us to set both we don't upload data chunked, as RFC2616 forbids us to set both
@@ -1113,11 +1221,7 @@ CURLcode Curl_http(struct connectdata *conn)
if(!checkheaders(data, "Content-Length:")) if(!checkheaders(data, "Content-Length:"))
/* we allow replacing this header, although it isn't very wise to /* we allow replacing this header, although it isn't very wise to
actually set your own */ actually set your own */
add_bufferf(req_buffer, add_bufferf(req_buffer, "Content-Length: %d\r\n", postsize);
"Content-Length: %d\r\n",
data->set.postfieldsize?
data->set.postfieldsize:
(data->set.postfields?strlen(data->set.postfields):0) );
} }
if(!checkheaders(data, "Content-Type:")) if(!checkheaders(data, "Content-Type:"))
@@ -1126,21 +1230,38 @@ CURLcode Curl_http(struct connectdata *conn)
add_buffer(req_buffer, "\r\n", 2); add_buffer(req_buffer, "\r\n", 2);
/* and here we setup the pointers to the actual data */
if(data->set.postfields) { if(data->set.postfields) {
if(data->set.postfieldsize)
http->postsize = data->set.postfieldsize;
else
http->postsize = strlen(data->set.postfields);
http->postdata = data->set.postfields;
http->sending = HTTPSEND_BODY; if(postsize < (100*1024)) {
/* The post data is less than 100K, then append it to the header.
This limit is no magic limit but only set to prevent really huge
POSTs to get the data duplicated with malloc() and family. */
conn->fread = (curl_read_callback)readmoredata; if(!conn->bits.upload_chunky)
conn->fread_in = (void *)conn; /* We're not sending it 'chunked', append it to the request
already now to reduce the number if send() calls */
add_buffer(req_buffer, data->set.postfields, postsize);
else {
/* Append the POST data chunky-style */
add_bufferf(req_buffer, "%x\r\n", postsize);
add_buffer(req_buffer, data->set.postfields, postsize);
add_buffer(req_buffer, "\r\n0\r\n", 5); /* end of a chunked
transfer stream */
}
}
else {
/* A huge POST coming up, do data separate from the request */
http->postsize = postsize;
http->postdata = data->set.postfields;
/* set the upload size to the progress meter */ http->sending = HTTPSEND_BODY;
Curl_pgrsSetUploadSize(data, http->postsize);
conn->fread = (curl_read_callback)readmoredata;
conn->fread_in = (void *)conn;
/* set the upload size to the progress meter */
Curl_pgrsSetUploadSize(data, http->postsize);
}
} }
else else
/* set the upload size to the progress meter */ /* set the upload size to the progress meter */
@@ -1156,8 +1277,8 @@ CURLcode Curl_http(struct connectdata *conn)
result = result =
Curl_Transfer(conn, conn->firstsocket, -1, TRUE, Curl_Transfer(conn, conn->firstsocket, -1, TRUE,
&http->readbytecount, &http->readbytecount,
conn->firstsocket, http->postdata?conn->firstsocket:-1,
&http->writebytecount); http->postdata?&http->writebytecount:NULL);
break; break;
default: default:
@@ -1178,8 +1299,7 @@ CURLcode Curl_http(struct connectdata *conn)
} }
if(result) if(result)
return result; return result;
} while (0); /* this is just a left-over from the multiple document download }
attempts */
return CURLE_OK; return CURLE_OK;
} }

View File

@@ -39,7 +39,7 @@
#include <curl/mprintf.h> #include <curl/mprintf.h>
/* The last #include file should be: */ /* The last #include file should be: */
#ifdef MALLOCDEBUG #ifdef CURLDEBUG
#include "memdebug.h" #include "memdebug.h"
#endif #endif
@@ -186,15 +186,22 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
break; break;
case DEFLATE: case DEFLATE:
/* update conn->keep.str to point to the chunk data. */
conn->keep.str = datap;
result = Curl_unencode_deflate_write(conn->data, &conn->keep, piece); result = Curl_unencode_deflate_write(conn->data, &conn->keep, piece);
break; break;
case GZIP: case GZIP:
/* update conn->keep.str to point to the chunk data. */
conn->keep.str = datap;
result = Curl_unencode_gzip_write(conn->data, &conn->keep, piece);
break;
case COMPRESS: case COMPRESS:
default: default:
failf (conn->data, failf (conn->data,
"Unrecognized content encoding type. " "Unrecognized content encoding type. "
"libcurl understands `identity' and `deflate' " "libcurl understands `identity', `deflate' and `gzip' "
"content encodings."); "content encodings.");
return CHUNKE_BAD_ENCODING; return CHUNKE_BAD_ENCODING;
} }

231
lib/http_digest.c Normal file
View File

@@ -0,0 +1,231 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2003, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at http://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* $Id$
***************************************************************************/
#include "setup.h"
#ifndef CURL_DISABLE_HTTP
/* -- WIN32 approved -- */
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <stdlib.h>
#include <ctype.h>
#include "urldata.h"
#include "sendf.h"
#include "strequal.h"
#include "md5.h"
#include "http_digest.h"
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
/* The last #include file should be: */
#ifdef CURLDEBUG
#include "memdebug.h"
#endif
/* Test example header:
WWW-Authenticate: Digest realm="testrealm", nonce="1053604598"
*/
CURLdigest Curl_input_digest(struct connectdata *conn,
char *header) /* rest of the www-authenticate:
header */
{
bool more = TRUE;
struct SessionHandle *data=conn->data;
/* skip initial whitespaces */
while(*header && isspace((int)*header))
header++;
if(checkprefix("Digest", header)) {
header += strlen("Digest");
/* clear off any former leftovers and init to defaults */
Curl_digest_cleanup(data);
while(more) {
char value[32];
char content[128];
int totlen=0;
while(*header && isspace((int)*header))
header++;
/* how big can these strings be? */
if(2 == sscanf(header, "%31[^=]=\"%127[^\"]\"",
value, content)) {
if(strequal(value, "nonce")) {
data->state.digest.nonce = strdup(content);
}
else if(strequal(value, "cnonce")) {
data->state.digest.cnonce = strdup(content);
}
else if(strequal(value, "realm")) {
data->state.digest.realm = strdup(content);
}
else if(strequal(value, "algorithm")) {
if(strequal(content, "MD5-sess"))
data->state.digest.algo = CURLDIGESTALGO_MD5SESS;
/* else, remain using the default md5 */
}
else {
/* unknown specifier, ignore it! */
}
totlen = strlen(value)+strlen(content)+3;
}
else
break; /* we're done here */
header += totlen;
if(',' == *header)
/* allow the list to be comma-separated */
header++;
}
if(!data->state.digest.nonce)
return CURLDIGEST_BAD;
}
else
/* else not a digest, get out */
return CURLDIGEST_NONE;
return CURLDIGEST_FINE;
}
/* convert md5 chunk to RFC2617 (section 3.1.3) -suitable ascii string*/
static void md5_to_ascii(unsigned char *source, /* 16 bytes */
unsigned char *dest) /* 33 bytes */
{
int i;
for(i=0; i<16; i++)
sprintf((char *)&dest[i*2], "%02x", source[i]);
}
CURLcode Curl_output_digest(struct connectdata *conn,
unsigned char *request,
unsigned char *uripath)
{
/* We have a Digest setup for this, use it!
Now, to get all the details for this sorted out, I must urge you dear friend
to read up on the RFC2617 section 3.2.2, */
unsigned char md5buf[16]; /* 16 bytes/128 bits */
unsigned char ha1[33]; /* 32 digits and 1 zero byte */
unsigned char ha2[33];
unsigned char request_digest[33];
unsigned char *md5this;
struct SessionHandle *data = conn->data;
/*
if the algorithm is "MD5" or unspecified (which then defaults to MD5):
A1 = unq(username-value) ":" unq(realm-value) ":" passwd
if the algorithm is "MD5-sess" then:
A1 = H( unq(username-value) ":" unq(realm-value) ":" passwd )
":" unq(nonce-value) ":" unq(cnonce-value)
*/
if(data->state.digest.algo == CURLDIGESTALGO_MD5SESS) {
md5this = (unsigned char *)
aprintf("%s:%s:%s:%s:%s",
conn->user,
data->state.digest.realm,
conn->passwd,
data->state.digest.nonce,
data->state.digest.cnonce);
}
else {
md5this = (unsigned char *)
aprintf("%s:%s:%s",
conn->user,
data->state.digest.realm,
conn->passwd);
}
Curl_md5it(md5buf, md5this);
free(md5this); /* free this again */
md5_to_ascii(md5buf, ha1);
/*
A2 = Method ":" digest-uri-value
(The "Method" value is the HTTP request method as specified in section
5.1.1 of RFC 2616)
*/
md5this = (unsigned char *)aprintf("%s:%s", request, uripath);
Curl_md5it(md5buf, md5this);
free(md5this); /* free this again */
md5_to_ascii(md5buf, ha2);
md5this = (unsigned char *)aprintf("%s:%s:%s", ha1, data->state.digest.nonce,
ha2);
Curl_md5it(md5buf, md5this);
free(md5this); /* free this again */
md5_to_ascii(md5buf, request_digest);
/* for test case 64 (snooped from a Mozilla 1.3a request)
Authorization: Digest username="testuser", realm="testrealm", \
nonce="1053604145", uri="/64", response="c55f7f30d83d774a3d2dcacf725abaca"
*/
conn->allocptr.userpwd =
aprintf( "Authorization: Digest "
"username=\"%s\", "
"realm=\"%s\", "
"nonce=\"%s\", "
"uri=\"%s\", "
"response=\"%s\"\r\n",
conn->user,
data->state.digest.realm,
data->state.digest.nonce,
uripath, /* this is the PATH part of the URL */
request_digest );
return CURLE_OK;
}
void Curl_digest_cleanup(struct SessionHandle *data)
{
if(data->state.digest.nonce)
free(data->state.digest.nonce);
data->state.digest.nonce = NULL;
if(data->state.digest.cnonce)
free(data->state.digest.cnonce);
data->state.digest.cnonce = NULL;
if(data->state.digest.realm)
free(data->state.digest.realm);
data->state.digest.realm = NULL;
data->state.digest.algo = CURLDIGESTALGO_MD5; /* default algorithm */
}
#endif

48
lib/http_digest.h Normal file
View File

@@ -0,0 +1,48 @@
#ifndef __HTTP_DIGEST_H
#define __HTTP_DIGEST_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2003, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at http://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* $Id$
***************************************************************************/
typedef enum {
CURLDIGEST_NONE, /* not a digest */
CURLDIGEST_BAD, /* a digest, but one we don't like */
CURLDIGEST_FINE, /* a digest we act on */
CURLDIGEST_LAST /* last entry in this enum, don't use */
} CURLdigest;
enum {
CURLDIGESTALGO_MD5,
CURLDIGESTALGO_MD5SESS
};
/* this is for digest header input */
CURLdigest Curl_input_digest(struct connectdata *conn, char *header);
/* this is for creating digest header output */
CURLcode Curl_output_digest(struct connectdata *conn,
unsigned char *request,
unsigned char *uripath);
void Curl_digest_cleanup(struct SessionHandle *data);
#endif

216
lib/http_negotiate.c Normal file
View File

@@ -0,0 +1,216 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2003, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at http://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* $Id$
***************************************************************************/
#include "setup.h"
#ifdef GSSAPI
#ifndef CURL_DISABLE_HTTP
/* -- WIN32 approved -- */
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <stdlib.h>
#include <ctype.h>
#include <errno.h>
#include "urldata.h"
#include "sendf.h"
#include "strequal.h"
#include "base64.h"
#include "http_negotiate.h"
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
/* The last #include file should be: */
#ifdef CURLDEBUG
#include "memdebug.h"
#endif
static int
get_gss_name(struct connectdata *conn, gss_name_t *server)
{
OM_uint32 major_status, minor_status;
gss_buffer_desc token = GSS_C_EMPTY_BUFFER;
char name[2048];
/* GSSAPI implementation by Globus (known as GSI) requires the name to be
of form "<service>/<fqdn>" instead of <service>@<fqdn> (ie. slash instead
of at-sign). Also GSI servers are often identified as 'host' not 'khttp'.
Change following lines if you want to use GSI */
token.length = strlen("khttp@") + strlen(conn->hostname) + 1;
if (token.length + 1 > sizeof(name))
return EMSGSIZE;
sprintf(name, "khttp@%s", conn->hostname);
token.value = (void *) name;
major_status = gss_import_name(&minor_status,
&token,
GSS_C_NT_HOSTBASED_SERVICE,
server);
return GSS_ERROR(major_status) ? -1 : 0;
}
static void
log_gss_error(struct connectdata *conn, OM_uint32 error_status, char *prefix)
{
OM_uint32 maj_stat, min_stat;
OM_uint32 msg_ctx = 0;
gss_buffer_desc status_string;
char buf[1024];
size_t len;
snprintf(buf, sizeof(buf), "%s", prefix);
len = strlen(buf);
do {
maj_stat = gss_display_status (&min_stat,
error_status,
GSS_C_MECH_CODE,
GSS_C_NO_OID,
&msg_ctx,
&status_string);
if (sizeof(buf) > len + status_string.length + 1) {
sprintf(buf + len, ": %s", (char*) status_string.value);
len += status_string.length;
}
gss_release_buffer(&min_stat, &status_string);
} while (!GSS_ERROR(maj_stat) && msg_ctx != 0);
infof(conn->data, buf);
}
int Curl_input_negotiate(struct connectdata *conn, char *header)
{
struct negotiatedata *neg_ctx = &conn->data->state.negotiate;
OM_uint32 major_status, minor_status, minor_status2;
gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER;
gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER;
int ret;
size_t len;
while(*header && isspace((int)*header))
header++;
if(!checkprefix("GSS-Negotiate", header))
return -1;
if (neg_ctx->context && neg_ctx->status == GSS_S_COMPLETE) {
/* We finished succesfully our part of authentication, but server
* rejected it (since we're again here). Exit with an error since we
* can't invent anything better */
Curl_cleanup_negotiate(conn->data);
return -1;
}
if (neg_ctx->server_name == NULL &&
(ret = get_gss_name(conn, &neg_ctx->server_name)))
return ret;
header += strlen("GSS-Negotiate");
while(*header && isspace((int)*header))
header++;
len = strlen(header);
if (len > 0) {
int rawlen;
input_token.length = (len+3)/4 * 3;
input_token.value = malloc(input_token.length);
if (input_token.value == NULL)
return ENOMEM;
rawlen = Curl_base64_decode(header, input_token.value);
if (rawlen < 0)
return -1;
input_token.length = rawlen;
}
major_status = gss_init_sec_context(&minor_status,
GSS_C_NO_CREDENTIAL,
&neg_ctx->context,
neg_ctx->server_name,
GSS_C_NO_OID,
GSS_C_DELEG_FLAG,
0,
GSS_C_NO_CHANNEL_BINDINGS,
&input_token,
NULL,
&output_token,
NULL,
NULL);
if (input_token.length > 0)
gss_release_buffer(&minor_status2, &input_token);
neg_ctx->status = major_status;
if (GSS_ERROR(major_status)) {
/* Curl_cleanup_negotiate(conn->data) ??? */
log_gss_error(conn, minor_status,
(char *)"gss_init_sec_context() failed: ");
return -1;
}
if (output_token.length == 0) {
return -1;
}
neg_ctx->output_token = output_token;
/* conn->bits.close = FALSE; */
return 0;
}
CURLcode Curl_output_negotiate(struct connectdata *conn)
{
struct negotiatedata *neg_ctx = &conn->data->state.negotiate;
OM_uint32 minor_status;
char *encoded = NULL;
int len = Curl_base64_encode(neg_ctx->output_token.value,
neg_ctx->output_token.length,
&encoded);
if (len < 0)
return CURLE_OUT_OF_MEMORY;
conn->allocptr.userpwd =
aprintf("Authorization: GSS-Negotiate %s\r\n", encoded);
free(encoded);
gss_release_buffer(&minor_status, &neg_ctx->output_token);
return (conn->allocptr.userpwd == NULL) ? CURLE_OUT_OF_MEMORY : CURLE_OK;
}
void Curl_cleanup_negotiate(struct SessionHandle *data)
{
OM_uint32 minor_status;
struct negotiatedata *neg_ctx = &data->state.negotiate;
if (neg_ctx->context != GSS_C_NO_CONTEXT)
gss_delete_sec_context(&minor_status, &neg_ctx->context, GSS_C_NO_BUFFER);
if (neg_ctx->output_token.length != 0)
gss_release_buffer(&minor_status, &neg_ctx->output_token);
if (neg_ctx->server_name != GSS_C_NO_NAME)
gss_release_name(&minor_status, &neg_ctx->server_name);
memset(neg_ctx, 0, sizeof(*neg_ctx));
}
#endif
#endif

39
lib/http_negotiate.h Normal file
View File

@@ -0,0 +1,39 @@
#ifndef __HTTP_NEGOTIATE_H
#define __HTTP_NEGOTIATE_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2003, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at http://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* $Id$
***************************************************************************/
#ifdef GSSAPI
/* this is for Negotiate header input */
int Curl_input_negotiate(struct connectdata *conn, char *header);
/* this is for creating Negotiate header output */
CURLcode Curl_output_negotiate(struct connectdata *conn);
void Curl_cleanup_negotiate(struct SessionHandle *data);
#endif
#endif

571
lib/http_ntlm.c Normal file
View File

@@ -0,0 +1,571 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2003, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at http://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* $Id$
***************************************************************************/
#include "setup.h"
/* NTLM details:
http://davenport.sourceforge.net/ntlm.html
http://www.innovation.ch/java/ntlm.html
*/
#ifndef CURL_DISABLE_HTTP
#ifdef USE_SSLEAY
/* We need OpenSSL for the crypto lib to provide us with MD4 and DES */
/* -- WIN32 approved -- */
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <stdlib.h>
#include <ctype.h>
#include "urldata.h"
#include "sendf.h"
#include "strequal.h"
#include "base64.h"
#include "http_ntlm.h"
#include "url.h"
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
#include <openssl/des.h>
#include <openssl/md4.h>
#include <openssl/ssl.h>
#if OPENSSL_VERSION_NUMBER < 0x00907001L
#define DES_key_schedule des_key_schedule
#define DES_cblock des_cblock
#define DES_set_odd_parity des_set_odd_parity
#define DES_set_key des_set_key
#define DES_ecb_encrypt des_ecb_encrypt
/* This is how things were done in the old days */#define DESKEY(x) x
#define DESKEY(x) x
#define DESKEYARG(x) x
#else
/* Modern version */
#define DESKEYARG(x) *x
#define DESKEY(x) &x
#endif
/* The last #include file should be: */
#ifdef CURLDEBUG
#include "memdebug.h"
#endif
/* Define this to make the type-3 message include the NT response message */
#undef USE_NTRESPONSES
/*
(*) = A "security buffer" is a triplet consisting of two shorts and one
long:
1. a 'short' containing the length of the buffer in bytes
2. a 'short' containing the allocated space for the buffer in bytes
3. a 'long' containing the offset to the start of the buffer from the
beginning of the NTLM message, in bytes.
*/
CURLntlm Curl_input_ntlm(struct connectdata *conn,
bool proxy, /* if proxy or not */
char *header) /* rest of the www-authenticate:
header */
{
/* point to the correct struct with this */
struct ntlmdata *ntlm;
ntlm = proxy?&conn->proxyntlm:&conn->ntlm;
/* skip initial whitespaces */
while(*header && isspace((int)*header))
header++;
if(checkprefix("NTLM", header)) {
unsigned char buffer[256];
header += strlen("NTLM");
while(*header && isspace((int)*header))
header++;
if(*header) {
/* We got a type-2 message here:
Index Description Content
0 NTLMSSP Signature Null-terminated ASCII "NTLMSSP"
(0x4e544c4d53535000)
8 NTLM Message Type long (0x02000000)
12 Target Name security buffer(*)
20 Flags long
24 Challenge 8 bytes
(32) Context (optional) 8 bytes (two consecutive longs)
(40) Target Information (optional) security buffer(*)
32 (48) start of data block
*/
int size = Curl_base64_decode(header, buffer);
ntlm->state = NTLMSTATE_TYPE2; /* we got a type-2 */
if(size >= 48)
/* the nonce of interest is index [24 .. 31], 8 bytes */
memcpy(ntlm->nonce, &buffer[24], 8);
/* at index decimal 20, there's a 32bit NTLM flag field */
}
else {
if(ntlm->state >= NTLMSTATE_TYPE1)
return CURLNTLM_BAD;
ntlm->state = NTLMSTATE_TYPE1; /* we should sent away a type-1 */
}
}
return CURLNTLM_FINE;
}
/*
* Turns a 56 bit key into the 64 bit, odd parity key and sets the key. The
* key schedule ks is also set.
*/
static void setup_des_key(unsigned char *key_56,
DES_key_schedule DESKEYARG(ks))
{
DES_cblock key;
key[0] = key_56[0];
key[1] = ((key_56[0] << 7) & 0xFF) | (key_56[1] >> 1);
key[2] = ((key_56[1] << 6) & 0xFF) | (key_56[2] >> 2);
key[3] = ((key_56[2] << 5) & 0xFF) | (key_56[3] >> 3);
key[4] = ((key_56[3] << 4) & 0xFF) | (key_56[4] >> 4);
key[5] = ((key_56[4] << 3) & 0xFF) | (key_56[5] >> 5);
key[6] = ((key_56[5] << 2) & 0xFF) | (key_56[6] >> 6);
key[7] = (key_56[6] << 1) & 0xFF;
DES_set_odd_parity(&key);
DES_set_key(&key, ks);
}
/*
* takes a 21 byte array and treats it as 3 56-bit DES keys. The
* 8 byte plaintext is encrypted with each key and the resulting 24
* bytes are stored in the results array.
*/
static void calc_resp(unsigned char *keys,
unsigned char *plaintext,
unsigned char *results)
{
DES_key_schedule ks;
setup_des_key(keys, DESKEY(ks));
DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) results,
DESKEY(ks), DES_ENCRYPT);
setup_des_key(keys+7, DESKEY(ks));
DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) (results+8),
DESKEY(ks), DES_ENCRYPT);
setup_des_key(keys+14, DESKEY(ks));
DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) (results+16),
DESKEY(ks), DES_ENCRYPT);
}
/*
* Set up lanmanager and nt hashed passwords
*/
static void mkhash(char *password,
unsigned char *nonce, /* 8 bytes */
unsigned char *lmresp /* must fit 0x18 bytes */
#ifdef USE_NTRESPONSES
, unsigned char *ntresp /* must fit 0x18 bytes */
#endif
)
{
unsigned char lmbuffer[21];
#ifdef USE_NTRESPONSES
unsigned char ntbuffer[21];
#endif
unsigned char *pw;
static const unsigned char magic[] = {
0x4B, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25
};
int i;
int len = strlen(password);
/* make it fit at least 14 bytes */
pw = malloc(len<7?14:len*2);
if(!pw)
return; /* this will lead to a badly generated package */
if (len > 14)
len = 14;
for (i=0; i<len; i++)
pw[i] = toupper(password[i]);
for (; i<14; i++)
pw[i] = 0;
{
/* create LanManager hashed password */
DES_key_schedule ks;
setup_des_key(pw, DESKEY(ks));
DES_ecb_encrypt((DES_cblock *)magic, (DES_cblock *)lmbuffer,
DESKEY(ks), DES_ENCRYPT);
setup_des_key(pw+7, DESKEY(ks));
DES_ecb_encrypt((DES_cblock *)magic, (DES_cblock *)(lmbuffer+8),
DESKEY(ks), DES_ENCRYPT);
memset(lmbuffer+16, 0, 5);
}
/* create LM responses */
calc_resp(lmbuffer, nonce, lmresp);
#ifdef USE_NTRESPONSES
{
/* create NT hashed password */
MD4_CTX MD4;
len = strlen(password);
for (i=0; i<len; i++) {
pw[2*i] = password[i];
pw[2*i+1] = 0;
}
MD4_Init(&MD4);
MD4_Update(&MD4, pw, 2*len);
MD4_Final(ntbuffer, &MD4);
memset(ntbuffer+16, 0, 8);
}
calc_resp(ntbuffer, nonce, ntresp);
#endif
free(pw);
}
#define SHORTPAIR(x) ((x) & 0xff), ((x) >> 8)
#define LONGQUARTET(x) ((x) & 0xff), (((x) >> 8)&0xff), \
(((x) >>16)&0xff), ((x)>>24)
/* this is for creating ntlm header output */
CURLcode Curl_output_ntlm(struct connectdata *conn,
bool proxy)
{
const char *domain=""; /* empty */
const char *host=""; /* empty */
int domlen=strlen(domain);
int hostlen = strlen(host);
int hostoff; /* host name offset */
int domoff; /* domain name offset */
int size;
char *base64=NULL;
unsigned char ntlmbuf[256]; /* enough, unless the host/domain is very long */
/* point to the address of the pointer that holds the string to sent to the
server, which is for a plain host or for a HTTP proxy */
char **allocuserpwd;
/* point to the name and password for this */
char *userp;
char *passwdp;
/* point to the correct struct with this */
struct ntlmdata *ntlm;
if(proxy) {
allocuserpwd = &conn->allocptr.proxyuserpwd;
userp = conn->proxyuser;
passwdp = conn->proxypasswd;
ntlm = &conn->proxyntlm;
}
else {
allocuserpwd = &conn->allocptr.userpwd;
userp = conn->user;
passwdp = conn->passwd;
ntlm = &conn->ntlm;
}
switch(ntlm->state) {
case NTLMSTATE_TYPE1:
default: /* for the weird cases we (re)start here */
hostoff = 32;
domoff = hostoff + hostlen;
/* Create and send a type-1 message:
Index Description Content
0 NTLMSSP Signature Null-terminated ASCII "NTLMSSP"
(0x4e544c4d53535000)
8 NTLM Message Type long (0x01000000)
12 Flags long
16 Supplied Domain security buffer(*)
24 Supplied Workstation security buffer(*)
32 start of data block
*/
snprintf((char *)ntlmbuf, sizeof(ntlmbuf), "NTLMSSP%c"
"\x01%c%c%c" /* 32-bit type = 1 */
"%c%c%c%c" /* 32-bit NTLM flag field */
"%c%c" /* domain length */
"%c%c" /* domain allocated space */
"%c%c" /* domain name offset */
"%c%c" /* 2 zeroes */
"%c%c" /* host length */
"%c%c" /* host allocated space */
"%c%c" /* host name offset */
"%c%c" /* 2 zeroes */
"%s" /* host name */
"%s", /* domain string */
0, /* trailing zero */
0,0,0, /* part of type-1 long */
LONGQUARTET(
NTLMFLAG_NEGOTIATE_OEM| /* 2 */
NTLMFLAG_NEGOTIATE_NTLM_KEY /* 200 */
/* equals 0x0202 */
),
SHORTPAIR(domlen),
SHORTPAIR(domlen),
SHORTPAIR(domoff),
0,0,
SHORTPAIR(hostlen),
SHORTPAIR(hostlen),
SHORTPAIR(hostoff),
0,0,
host, domain);
/* initial packet length */
size = 32 + hostlen + domlen;
/* now keeper of the base64 encoded package size */
size = Curl_base64_encode(ntlmbuf, size, &base64);
if(size >0 ) {
Curl_safefree(*allocuserpwd);
*allocuserpwd = aprintf("%sAuthorization: NTLM %s\r\n",
proxy?"Proxy-":"",
base64);
free(base64);
}
else
return CURLE_OUT_OF_MEMORY; /* FIX TODO */
break;
case NTLMSTATE_TYPE2:
/* We received the type-2 already, create a type-3 message:
Index Description Content
0 NTLMSSP Signature Null-terminated ASCII "NTLMSSP"
(0x4e544c4d53535000)
8 NTLM Message Type long (0x03000000)
12 LM/LMv2 Response security buffer(*)
20 NTLM/NTLMv2 Response security buffer(*)
28 Domain Name security buffer(*)
36 User Name security buffer(*)
44 Workstation Name security buffer(*)
(52) Session Key (optional) security buffer(*)
(60) Flags (optional) long
52 (64) start of data block
*/
{
int lmrespoff;
int ntrespoff;
int useroff;
unsigned char lmresp[0x18]; /* fixed-size */
#ifdef USE_NTRESPONSES
unsigned char ntresp[0x18]; /* fixed-size */
#endif
const char *user;
int userlen;
user = strchr(userp, '\\');
if(!user)
user = strchr(userp, '/');
if (user) {
domain = userp;
domlen = user - domain;
user++;
}
else
user = userp;
userlen = strlen(user);
mkhash(passwdp, &ntlm->nonce[0], lmresp
#ifdef USE_NTRESPONSES
, ntresp
#endif
);
domoff = 64; /* always */
useroff = domoff + domlen;
hostoff = useroff + userlen;
lmrespoff = hostoff + hostlen;
ntrespoff = lmrespoff + 0x18;
/* Create the big type-3 message binary blob */
size = snprintf((char *)ntlmbuf, sizeof(ntlmbuf),
"NTLMSSP%c"
"\x03%c%c%c" /* type-3, 32 bits */
"%c%c%c%c" /* LanManager length + allocated space */
"%c%c" /* LanManager offset */
"%c%c" /* 2 zeroes */
"%c%c" /* NT-response length */
"%c%c" /* NT-response allocated space */
"%c%c" /* NT-response offset */
"%c%c" /* 2 zeroes */
"%c%c" /* domain length */
"%c%c" /* domain allocated space */
"%c%c" /* domain name offset */
"%c%c" /* 2 zeroes */
"%c%c" /* user length */
"%c%c" /* user allocated space */
"%c%c" /* user offset */
"%c%c" /* 2 zeroes */
"%c%c" /* host length */
"%c%c" /* host allocated space */
"%c%c" /* host offset */
"%c%c%c%c%c%c" /* 6 zeroes */
"\xff\xff" /* message length */
"%c%c" /* 2 zeroes */
"\x01\x82" /* flags */
"%c%c" /* 2 zeroes */
/* domain string */
/* user string */
/* host string */
/* LanManager response */
/* NT response */
,
0, /* zero termination */
0,0,0, /* type-3 long, the 24 upper bits */
SHORTPAIR(0x18), /* LanManager response length, twice */
SHORTPAIR(0x18),
SHORTPAIR(lmrespoff),
0x0, 0x0,
#ifdef USE_NTRESPONSES
SHORTPAIR(0x18), /* NT-response length, twice */
SHORTPAIR(0x18),
#else
0x0, 0x0,
0x0, 0x0,
#endif
SHORTPAIR(ntrespoff),
0x0, 0x0,
SHORTPAIR(domlen),
SHORTPAIR(domlen),
SHORTPAIR(domoff),
0x0, 0x0,
SHORTPAIR(userlen),
SHORTPAIR(userlen),
SHORTPAIR(useroff),
0x0, 0x0,
SHORTPAIR(hostlen),
SHORTPAIR(hostlen),
SHORTPAIR(hostoff),
0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0,
0x0, 0x0);
/* size is now 64 */
size=64;
ntlmbuf[62]=ntlmbuf[63]=0;
memcpy(&ntlmbuf[size], domain, domlen);
size += domlen;
memcpy(&ntlmbuf[size], user, userlen);
size += userlen;
/* we append the binary hashes to the end of the blob */
if(size < ((int)sizeof(ntlmbuf) - 0x18)) {
memcpy(&ntlmbuf[size], lmresp, 0x18);
size += 0x18;
}
#ifdef USE_NTRESPONSES
if(size < ((int)sizeof(ntlmbuf) - 0x18)) {
memcpy(&ntlmbuf[size], ntresp, 0x18);
size += 0x18;
}
#endif
ntlmbuf[56] = size & 0xff;
ntlmbuf[57] = size >> 8;
/* convert the binary blob into base64 */
size = Curl_base64_encode(ntlmbuf, size, &base64);
if(size >0 ) {
Curl_safefree(*allocuserpwd);
*allocuserpwd = aprintf("%sAuthorization: NTLM %s\r\n",
proxy?"Proxy-":"",
base64);
free(base64);
}
else
return CURLE_OUT_OF_MEMORY; /* FIX TODO */
ntlm->state = NTLMSTATE_TYPE3; /* we sent a type-3 */
}
break;
case NTLMSTATE_TYPE3:
/* connection is already authenticated,
* don't send a header in future requests */
if(*allocuserpwd) {
free(*allocuserpwd);
*allocuserpwd=NULL;
}
break;
}
return CURLE_OK;
}
#endif /* USE_SSLEAY */
#endif /* !CURL_DISABLE_HTTP */

143
lib/http_ntlm.h Normal file
View File

@@ -0,0 +1,143 @@
#ifndef __HTTP_NTLM_H
#define __HTTP_NTLM_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2003, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at http://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* $Id$
***************************************************************************/
typedef enum {
CURLNTLM_NONE, /* not a ntlm */
CURLNTLM_BAD, /* an ntlm, but one we don't like */
CURLNTLM_FIRST, /* the first 401-reply we got with NTLM */
CURLNTLM_FINE, /* an ntlm we act on */
CURLNTLM_LAST /* last entry in this enum, don't use */
} CURLntlm;
/* this is for ntlm header input */
CURLntlm Curl_input_ntlm(struct connectdata *conn, bool proxy, char *header);
/* this is for creating ntlm header output */
CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy);
void Curl_ntlm_cleanup(struct SessionHandle *data);
/* Flag bits definitions based on http://davenport.sourceforge.net/ntlm.html */
#define NTLMFLAG_NEGOTIATE_UNICODE (1<<0)
/* Indicates that Unicode strings are supported for use in security buffer
data. */
#define NTLMFLAG_NEGOTIATE_OEM (1<<1)
/* Indicates that OEM strings are supported for use in security buffer data. */
#define NTLMFLAG_REQUEST_TARGET (1<<2)
/* Requests that the server's authentication realm be included in the Type 2
message. */
/* unknown (1<<3) */
#define NTLMFLAG_NEGOTIATE_SIGN (1<<4)
/* Specifies that authenticated communication between the client and server
should carry a digital signature (message integrity). */
#define NTLMFLAG_NEGOTIATE_SEAL (1<<5)
/* Specifies that authenticated communication between the client and server
should be encrypted (message confidentiality). */
#define NTLMFLAG_NEGOTIATE_DATAGRAM_STYLE (1<<6)
/* unknown purpose */
#define NTLMFLAG_NEGOTIATE_LM_KEY (1<<7)
/* Indicates that the LAN Manager session key should be used for signing and
sealing authenticated communications. */
#define NTLMFLAG_NEGOTIATE_NETWARE (1<<8)
/* unknown purpose */
#define NTLMFLAG_NEGOTIATE_NTLM_KEY (1<<9)
/* Indicates that NTLM authentication is being used. */
/* unknown (1<<10) */
/* unknown (1<<11) */
#define NTLMFLAG_NEGOTIATE_DOMAIN_SUPPLIED (1<<12)
/* Sent by the client in the Type 1 message to indicate that a desired
authentication realm is included in the message. */
#define NTLMFLAG_NEGOTIATE_WORKSTATION_SUPPLIED (1<<13)
/* Sent by the client in the Type 1 message to indicate that the client
workstation's name is included in the message. */
#define NTLMFLAG_NEGOTIATE_LOCAL_CALL (1<<14)
/* Sent by the server to indicate that the server and client are on the same
machine. Implies that the client may use a pre-established local security
context rather than responding to the challenge. */
#define NTLMFLAG_NEGOTIATE_ALWAYS_SIGN (1<<15)
/* Indicates that authenticated communication between the client and server
should be signed with a "dummy" signature. */
#define NTLMFLAG_TARGET_TYPE_DOMAIN (1<<16)
/* Sent by the server in the Type 2 message to indicate that the target
authentication realm is a domain. */
#define NTLMFLAG_TARGET_TYPE_SERVER (1<<17)
/* Sent by the server in the Type 2 message to indicate that the target
authentication realm is a server. */
#define NTLMFLAG_TARGET_TYPE_SHARE (1<<18)
/* Sent by the server in the Type 2 message to indicate that the target
authentication realm is a share. Presumably, this is for share-level
authentication. Usage is unclear. */
#define NTLMFLAG_NEGOTIATE_NTLM2_KEY (1<<19)
/* Indicates that the NTLM2 signing and sealing scheme should be used for
protecting authenticated communications. */
#define NTLMFLAG_REQUEST_INIT_RESPONSE (1<<20)
/* unknown purpose */
#define NTLMFLAG_REQUEST_ACCEPT_RESPONSE (1<<21)
/* unknown purpose */
#define NTLMFLAG_REQUEST_NONNT_SESSION_KEY (1<<22)
/* unknown purpose */
#define NTLMFLAG_NEGOTIATE_TARGET_INFO (1<<23)
/* Sent by the server in the Type 2 message to indicate that it is including a
Target Information block in the message. */
/* unknown (1<24) */
/* unknown (1<25) */
/* unknown (1<26) */
/* unknown (1<27) */
/* unknown (1<28) */
#define NTLMFLAG_NEGOTIATE_128 (1<<29)
/* Indicates that 128-bit encryption is supported. */
#define NTLMFLAG_NEGOTIATE_KEY_EXCHANGE (1<<30)
/* unknown purpose */
#define NTLMFLAG_NEGOTIATE_56 (1<<31)
/* Indicates that 56-bit encryption is supported. */
#endif

View File

@@ -73,10 +73,14 @@
#endif #endif
/* The last #include file should be: */ /* The last #include file should be: */
#ifdef MALLOCDEBUG #ifdef CURLDEBUG
#include "memdebug.h" #include "memdebug.h"
#endif #endif
#ifdef DJGPP
#define IOCTL_3_ARGS
#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)

View File

@@ -64,7 +64,7 @@
#endif #endif
/* The last #include file should be: */ /* The last #include file should be: */
#ifdef MALLOCDEBUG #ifdef CURLDEBUG
#include "memdebug.h" #include "memdebug.h"
#endif #endif
@@ -322,7 +322,7 @@ CURLcode Curl_krb_kauth(struct connectdata *conn)
save = Curl_set_command_prot(conn, prot_private); save = Curl_set_command_prot(conn, prot_private);
result = Curl_ftpsendf(conn, "SITE KAUTH %s", conn->data->state.user); result = Curl_ftpsendf(conn, "SITE KAUTH %s", conn->user);
if(result) if(result)
return result; return result;
@@ -363,7 +363,7 @@ CURLcode Curl_krb_kauth(struct connectdata *conn)
for(; *p && *p != ' ' && *p != '\r' && *p != '\n'; p++); for(; *p && *p != ' ' && *p != '\r' && *p != '\n'; p++);
*p = 0; *p = 0;
des_string_to_key (conn->data->state.passwd, &key); des_string_to_key (conn->passwd, &key);
des_key_sched(&key, schedule); des_key_sched(&key, schedule);
des_pcbc_encrypt((void *)tkt.dat, (void *)tktcopy.dat, des_pcbc_encrypt((void *)tkt.dat, (void *)tktcopy.dat,

View File

@@ -74,7 +74,7 @@ static void DynaOpen(void)
* liblber.so automatically, but since it does not we will * liblber.so automatically, but since it does not we will
* handle it here by opening liblber.so as global. * handle it here by opening liblber.so as global.
*/ */
dlopen("liblber.so", liblber = dlopen("liblber.so",
#ifdef RTLD_LAZY_GLOBAL /* It turns out some systems use this: */ #ifdef RTLD_LAZY_GLOBAL /* It turns out some systems use this: */
RTLD_LAZY_GLOBAL RTLD_LAZY_GLOBAL
#else #else
@@ -178,8 +178,8 @@ CURLcode Curl_ldap(struct connectdata *conn)
status = CURLE_COULDNT_CONNECT; status = CURLE_COULDNT_CONNECT;
} else { } else {
rc = ldap_simple_bind_s(server, rc = ldap_simple_bind_s(server,
conn->bits.user_passwd?data->state.user:NULL, conn->bits.user_passwd?conn->user:NULL,
conn->bits.user_passwd?data->state.passwd:NULL); conn->bits.user_passwd?conn->passwd:NULL);
if (rc != 0) { if (rc != 0) {
failf(data, "LDAP: %s", ldap_err2string(rc)); failf(data, "LDAP: %s", ldap_err2string(rc));
status = CURLE_LDAP_CANNOT_BIND; status = CURLE_LDAP_CANNOT_BIND;

View File

@@ -28,7 +28,7 @@
#include "llist.h" #include "llist.h"
#ifdef MALLOCDEBUG #ifdef CURLDEBUG
/* this must be the last include file */ /* this must be the last include file */
#include "memdebug.h" #include "memdebug.h"
#endif #endif

157
lib/makefile.dj Normal file
View File

@@ -0,0 +1,157 @@
#
# Adapted for djgpp2 / Watt-32 / DOS by
# Gisle Vanem <giva@bgnett.no>
#
DEPEND_PREREQ = config.h getdate.c
include ../packages/DOS/common.dj
ifeq ($(USE_SSL),1)
CFLAGS += -I$(OPENSSL_ROOT)
endif
SOURCES = base64.c connect.c content_.c cookie.c dict.c \
easy.c escape.c file.c formdata.c ftp.c \
getdate.c getenv.c getinfo.c getpass.c hash.c \
hostip.c http.c http_chu.c if2ip.c krb4.c \
ldap.c llist.c memdebug.c mprintf.c multi.c \
netrc.c progress.c security.c sendf.c share.c \
speedche.c ssluse.c strequal.c strtok.c telnet.c \
timeval.c transfer.c url.c version.c
OBJECTS = $(SOURCES:.c=.o)
CURL_LIB = libcurl.a
all: config.h $(CURL_LIB)
$(CURL_LIB): $(OBJECTS)
ar rs $@ $?
config.h: config.dj
@echo '#include "./config.dj"' > $@
getdate.c: getdate.y
$(YACC) -o $@ $^
clean:
- rm -f $(OBJECTS) $(CURL_LIB) Makefile.bak config.h getdate.c
# DO NOT DELETE THIS LINE
base64.o: base64.c setup.h config.h config.dj ../include/curl/mprintf.h \
base64.h
connect.o: connect.c setup.h config.h config.dj urldata.h cookie.h \
../include/curl/curl.h ../include/curl/types.h ../include/curl/easy.h \
../include/curl/multi.h formdata.h timeval.h http_chunks.h hostip.h \
hash.h llist.h sendf.h if2ip.h
content_.o: content_.c setup.h config.h config.dj
cookie.o: cookie.c setup.h config.h config.dj cookie.h \
../include/curl/curl.h ../include/curl/types.h ../include/curl/easy.h \
../include/curl/multi.h getdate.h strequal.h strtok.h
dict.o: dict.c setup.h config.h config.dj urldata.h cookie.h \
../include/curl/curl.h ../include/curl/types.h ../include/curl/easy.h \
../include/curl/multi.h formdata.h timeval.h http_chunks.h hostip.h \
hash.h llist.h transfer.h sendf.h progress.h strequal.h \
../include/curl/mprintf.h
easy.o: easy.c setup.h config.h config.dj strequal.h urldata.h cookie.h \
../include/curl/curl.h ../include/curl/types.h ../include/curl/easy.h \
../include/curl/multi.h formdata.h timeval.h http_chunks.h hostip.h \
hash.h llist.h transfer.h ssluse.h url.h getinfo.h \
../include/curl/mprintf.h
escape.o: escape.c setup.h config.h config.dj ../include/curl/curl.h \
../include/curl/types.h ../include/curl/easy.h ../include/curl/multi.h
file.o: file.c setup.h config.h config.dj urldata.h cookie.h \
../include/curl/curl.h ../include/curl/types.h ../include/curl/easy.h \
../include/curl/multi.h formdata.h timeval.h http_chunks.h hostip.h \
hash.h llist.h progress.h sendf.h escape.h ../include/curl/mprintf.h
formdata.o: formdata.c setup.h config.h config.dj ../include/curl/curl.h \
../include/curl/types.h ../include/curl/easy.h ../include/curl/multi.h \
formdata.h strequal.h
ftp.o: ftp.c setup.h config.h config.dj ../include/curl/curl.h \
../include/curl/types.h ../include/curl/easy.h ../include/curl/multi.h \
urldata.h cookie.h formdata.h timeval.h http_chunks.h hostip.h hash.h \
llist.h sendf.h if2ip.h progress.h transfer.h escape.h http.h ftp.h \
strequal.h ssluse.h connect.h ../include/curl/mprintf.h
getdate.o: getdate.c setup.h config.h config.dj getdate.h
getenv.o: getenv.c setup.h config.h config.dj
getinfo.o: getinfo.c setup.h config.h config.dj ../include/curl/curl.h \
../include/curl/types.h ../include/curl/easy.h ../include/curl/multi.h \
urldata.h cookie.h formdata.h timeval.h http_chunks.h hostip.h hash.h \
llist.h
getpass.o: getpass.c setup.h config.h config.dj
hash.o: hash.c setup.h config.h config.dj hash.h llist.h
hostip.o: hostip.c setup.h config.h config.dj urldata.h cookie.h \
../include/curl/curl.h ../include/curl/types.h ../include/curl/easy.h \
../include/curl/multi.h formdata.h timeval.h http_chunks.h hostip.h \
hash.h llist.h sendf.h share.h ../include/curl/mprintf.h
http.o: http.c setup.h config.h config.dj urldata.h cookie.h \
../include/curl/curl.h ../include/curl/types.h ../include/curl/easy.h \
../include/curl/multi.h formdata.h timeval.h http_chunks.h hostip.h \
hash.h llist.h transfer.h sendf.h progress.h base64.h strequal.h \
ssluse.h ../include/curl/mprintf.h
http_chu.o: http_chu.c setup.h config.h config.dj urldata.h cookie.h \
../include/curl/curl.h ../include/curl/types.h ../include/curl/easy.h \
../include/curl/multi.h formdata.h timeval.h http_chunks.h hostip.h \
hash.h llist.h sendf.h content_encoding.h ../include/curl/mprintf.h
if2ip.o: if2ip.c setup.h config.h config.dj
krb4.o: krb4.c setup.h config.h config.dj
ldap.o: ldap.c setup.h config.h config.dj urldata.h cookie.h \
../include/curl/curl.h ../include/curl/types.h ../include/curl/easy.h \
../include/curl/multi.h formdata.h timeval.h http_chunks.h hostip.h \
hash.h llist.h sendf.h escape.h transfer.h ../include/curl/mprintf.h
llist.o: llist.c setup.h config.h config.dj llist.h
memdebug.o: memdebug.c
mprintf.o: mprintf.c setup.h config.h config.dj
multi.o: multi.c setup.h config.h config.dj ../include/curl/curl.h \
../include/curl/types.h ../include/curl/easy.h ../include/curl/multi.h \
urldata.h cookie.h formdata.h timeval.h http_chunks.h hostip.h hash.h \
llist.h transfer.h url.h connect.h progress.h
netrc.o: netrc.c setup.h config.h config.dj ../include/curl/curl.h \
../include/curl/types.h ../include/curl/easy.h ../include/curl/multi.h \
strequal.h strtok.h
progress.o: progress.c setup.h config.h config.dj ../include/curl/curl.h \
../include/curl/types.h ../include/curl/easy.h ../include/curl/multi.h \
urldata.h cookie.h formdata.h timeval.h http_chunks.h hostip.h hash.h \
llist.h sendf.h progress.h ../include/curl/mprintf.h
security.o: security.c setup.h config.h config.dj
sendf.o: sendf.c setup.h config.h config.dj ../include/curl/curl.h \
../include/curl/types.h ../include/curl/easy.h ../include/curl/multi.h \
urldata.h cookie.h formdata.h timeval.h http_chunks.h hostip.h hash.h \
llist.h sendf.h connect.h ../include/curl/mprintf.h
share.o: share.c setup.h config.h config.dj ../include/curl/curl.h \
../include/curl/types.h ../include/curl/easy.h ../include/curl/multi.h \
urldata.h cookie.h formdata.h timeval.h http_chunks.h hostip.h hash.h \
llist.h share.h
speedche.o: speedche.c setup.h config.h config.dj ../include/curl/curl.h \
../include/curl/types.h ../include/curl/easy.h ../include/curl/multi.h \
urldata.h cookie.h formdata.h timeval.h http_chunks.h hostip.h hash.h \
llist.h sendf.h speedcheck.h
ssluse.o: ssluse.c setup.h config.h config.dj urldata.h cookie.h \
../include/curl/curl.h ../include/curl/types.h ../include/curl/easy.h \
../include/curl/multi.h formdata.h timeval.h http_chunks.h hostip.h \
hash.h llist.h sendf.h url.h
strequal.o: strequal.c setup.h config.h config.dj
strtok.o: strtok.c setup.h config.h config.dj
telnet.o: telnet.c setup.h config.h config.dj urldata.h cookie.h \
../include/curl/curl.h ../include/curl/types.h ../include/curl/easy.h \
../include/curl/multi.h formdata.h timeval.h http_chunks.h hostip.h \
hash.h llist.h transfer.h sendf.h ../include/curl/mprintf.h \
arpa_telnet.h
timeval.o: timeval.c timeval.h setup.h config.h config.dj
transfer.o: transfer.c setup.h config.h config.dj strequal.h urldata.h \
cookie.h ../include/curl/curl.h ../include/curl/types.h \
../include/curl/easy.h ../include/curl/multi.h formdata.h timeval.h \
http_chunks.h hostip.h hash.h llist.h netrc.h content_encoding.h \
transfer.h sendf.h speedcheck.h getpass.h progress.h getdate.h http.h \
url.h getinfo.h ssluse.h ../include/curl/mprintf.h
url.o: url.c setup.h config.h config.dj urldata.h cookie.h \
../include/curl/curl.h ../include/curl/types.h ../include/curl/easy.h \
../include/curl/multi.h formdata.h timeval.h http_chunks.h hostip.h \
hash.h llist.h netrc.h base64.h ssluse.h if2ip.h transfer.h sendf.h \
getpass.h progress.h strequal.h escape.h strtok.h share.h \
content_encoding.h ftp.h dict.h telnet.h http.h file.h ldap.h url.h \
connect.h ca-bundle.h ../include/curl/mprintf.h
version.o: version.c setup.h config.h config.dj ../include/curl/curl.h \
../include/curl/types.h ../include/curl/easy.h ../include/curl/multi.h \
urldata.h cookie.h formdata.h timeval.h http_chunks.h hostip.h hash.h \
llist.h

356
lib/md5.c Normal file
View File

@@ -0,0 +1,356 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2003, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at http://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* $Id$
***************************************************************************/
#include "setup.h"
#ifndef USE_SSLEAY
/* This code segment is only used if OpenSSL is not provided, as if it is
we use the MD5-function provided there instead. No good duplicating
code! */
/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
rights reserved.
License to copy and use this software is granted provided that it
is identified as the "RSA Data Security, Inc. MD5 Message-Digest
Algorithm" in all material mentioning or referencing this software
or this function.
License is also granted to make and use derivative works provided
that such works are identified as "derived from the RSA Data
Security, Inc. MD5 Message-Digest Algorithm" in all material
mentioning or referencing the derived work.
RSA Data Security, Inc. makes no representations concerning either
the merchantability of this software or the suitability of this
software for any particular purpose. It is provided "as is"
without express or implied warranty of any kind.
These notices must be retained in any copies of any part of this
documentation and/or software.
*/
#include <string.h>
/* UINT4 defines a four byte word */
typedef unsigned long int UINT4;
/* MD5 context. */
struct md5_ctx {
UINT4 state[4]; /* state (ABCD) */
UINT4 count[2]; /* number of bits, modulo 2^64 (lsb first) */
unsigned char buffer[64]; /* input buffer */
};
typedef struct md5_ctx MD5_CTX;
static void MD5_Init(struct md5_ctx *);
static void MD5_Update(struct md5_ctx *, unsigned char *, unsigned int);
static void MD5_Final(unsigned char [16], struct md5_ctx *);
/* Constants for MD5Transform routine.
*/
#define S11 7
#define S12 12
#define S13 17
#define S14 22
#define S21 5
#define S22 9
#define S23 14
#define S24 20
#define S31 4
#define S32 11
#define S33 16
#define S34 23
#define S41 6
#define S42 10
#define S43 15
#define S44 21
static void MD5Transform(UINT4 [4], unsigned char [64]);
static void Encode(unsigned char *, UINT4 *, unsigned int);
static void Decode(UINT4 *, unsigned char *, unsigned int);
#define MD5_memcpy(dst,src,len) memcpy(dst,src,len)
#define MD5_memset(dst,val,len) memset(dst,val,len)
static unsigned char PADDING[64] = {
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
/* F, G, H and I are basic MD5 functions.
*/
#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
#define H(x, y, z) ((x) ^ (y) ^ (z))
#define I(x, y, z) ((y) ^ ((x) | (~z)))
/* ROTATE_LEFT rotates x left n bits.
*/
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
Rotation is separate from addition to prevent recomputation.
*/
#define FF(a, b, c, d, x, s, ac) { \
(a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
#define GG(a, b, c, d, x, s, ac) { \
(a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
#define HH(a, b, c, d, x, s, ac) { \
(a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
#define II(a, b, c, d, x, s, ac) { \
(a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
/* MD5 initialization. Begins an MD5 operation, writing a new context.
*/
static void MD5_Init (context)
struct md5_ctx *context; /* context */
{
context->count[0] = context->count[1] = 0;
/* Load magic initialization constants.
*/
context->state[0] = 0x67452301;
context->state[1] = 0xefcdab89;
context->state[2] = 0x98badcfe;
context->state[3] = 0x10325476;
}
/* MD5 block update operation. Continues an MD5 message-digest
operation, processing another message block, and updating the
context.
*/
static void MD5_Update (context, input, inputLen)
struct md5_ctx *context; /* context */
unsigned char *input; /* input block */
unsigned int inputLen; /* length of input block */
{
unsigned int i, index, partLen;
/* Compute number of bytes mod 64 */
index = (unsigned int)((context->count[0] >> 3) & 0x3F);
/* Update number of bits */
if ((context->count[0] += ((UINT4)inputLen << 3))
< ((UINT4)inputLen << 3))
context->count[1]++;
context->count[1] += ((UINT4)inputLen >> 29);
partLen = 64 - index;
/* Transform as many times as possible. */
if (inputLen >= partLen) {
MD5_memcpy((void *)&context->buffer[index], (void *)input, partLen);
MD5Transform(context->state, context->buffer);
for (i = partLen; i + 63 < inputLen; i += 64)
MD5Transform(context->state, &input[i]);
index = 0;
}
else
i = 0;
/* Buffer remaining input */
MD5_memcpy((void *)&context->buffer[index], (void *)&input[i],
inputLen-i);
}
/* MD5 finalization. Ends an MD5 message-digest operation, writing the
the message digest and zeroizing the context.
*/
static void MD5_Final (digest, context)
unsigned char digest[16]; /* message digest */
struct md5_ctx *context; /* context */
{
unsigned char bits[8];
unsigned int index, padLen;
/* Save number of bits */
Encode (bits, context->count, 8);
/* Pad out to 56 mod 64. */
index = (unsigned int)((context->count[0] >> 3) & 0x3f);
padLen = (index < 56) ? (56 - index) : (120 - index);
MD5_Update (context, PADDING, padLen);
/* Append length (before padding) */
MD5_Update (context, bits, 8);
/* Store state in digest */
Encode (digest, context->state, 16);
/* Zeroize sensitive information. */
MD5_memset ((void *)context, 0, sizeof (*context));
}
/* MD5 basic transformation. Transforms state based on block. */
static void MD5Transform (state, block)
UINT4 state[4];
unsigned char block[64];
{
UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
Decode (x, block, 64);
/* Round 1 */
FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
/* Round 2 */
GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */
GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
/* Round 3 */
HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */
HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
/* Round 4 */
II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
state[0] += a;
state[1] += b;
state[2] += c;
state[3] += d;
/* Zeroize sensitive information. */
MD5_memset ((void *)x, 0, sizeof (x));
}
/* Encodes input (UINT4) into output (unsigned char). Assumes len is
a multiple of 4.
*/
static void Encode (unsigned char *output,
UINT4 *input,
unsigned int len)
{
unsigned int i, j;
for (i = 0, j = 0; j < len; i++, j += 4) {
output[j] = (unsigned char)(input[i] & 0xff);
output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
}
}
/* Decodes input (unsigned char) into output (UINT4). Assumes len is
a multiple of 4.
*/
static void Decode (UINT4 *output,
unsigned char *input,
unsigned int len)
{
unsigned int i, j;
for (i = 0, j = 0; j < len; i++, j += 4)
output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) |
(((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24);
}
#else
/* If OpenSSL is present */
#include <openssl/md5.h>
#include <string.h>
#endif
void Curl_md5it(unsigned char *outbuffer, /* 16 bytes */
unsigned char *input)
{
MD5_CTX ctx;
MD5_Init(&ctx);
MD5_Update(&ctx, input, strlen((char *)input));
MD5_Final(outbuffer, &ctx);
}

View File

@@ -1,31 +1,29 @@
#ifndef __CA_BUNDLE_H #ifndef __MD5_H
#define __CA_BUNDLE_H #define __MD5_H
/***************************************************************************** /***************************************************************************
* _ _ ____ _ * _ _ ____ _
* Project ___| | | | _ \| | * Project ___| | | | _ \| |
* / __| | | | |_) | | * / __| | | | |_) | |
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 1998 - 2003, 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.
* *
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at http://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell * 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 * 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 * furnished to do so, under the terms of the COPYING file.
* licenses. You may pick one of these licenses.
* *
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied. * KIND, either express or implied.
* *
* $Id$ * $Id$
*****************************************************************************/ ***************************************************************************/
void Curl_md5it(unsigned char *output,
unsigned char *input);
#ifndef CURL_CA_BUNDLE
/* Set this to the full path file name of the ca cert bundle */
#undef CURL_CA_BUNDLE
#endif #endif
#endif /* __CA_BUNDLE_H */

View File

@@ -1,4 +1,4 @@
#ifdef MALLOCDEBUG #ifdef CURLDEBUG
/*************************************************************************** /***************************************************************************
* _ _ ____ _ * _ _ ____ _
* Project ___| | | | _ \| | * Project ___| | | | _ \| |
@@ -220,4 +220,4 @@ int curl_fclose(FILE *file, int line, const char *source)
#ifdef VMS #ifdef VMS
int VOID_VAR_MEMDEBUG; int VOID_VAR_MEMDEBUG;
#endif #endif
#endif /* MALLOCDEBUG */ #endif /* CURLDEBUG */

View File

@@ -1,4 +1,4 @@
#ifdef MALLOCDEBUG #ifdef CURLDEBUG
/*************************************************************************** /***************************************************************************
* _ _ ____ _ * _ _ ____ _
* Project ___| | | | _ \| | * Project ___| | | | _ \| |

View File

@@ -48,7 +48,7 @@
/* The last #include file should be: */ /* The last #include file should be: */
#ifdef MALLOCDEBUG #ifdef CURLDEBUG
#include "memdebug.h" #include "memdebug.h"
#endif #endif

View File

@@ -31,6 +31,9 @@
#ifdef HAVE_SYS_SOCKET_H #ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h> #include <sys/socket.h>
#endif #endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <curl/curl.h> #include <curl/curl.h>
@@ -38,9 +41,10 @@
#include "transfer.h" #include "transfer.h"
#include "url.h" #include "url.h"
#include "connect.h" #include "connect.h"
#include "progress.h"
/* The last #include file should be: */ /* The last #include file should be: */
#ifdef MALLOCDEBUG #ifdef CURLDEBUG
#include "memdebug.h" #include "memdebug.h"
#endif #endif
@@ -298,7 +302,7 @@ CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
easy=multi->easy.next; easy=multi->easy.next;
while(easy) { while(easy) {
#ifdef MALLOCDEBUG #ifdef CURLDEBUG
fprintf(stderr, "HANDLE %p: State: %x\n", fprintf(stderr, "HANDLE %p: State: %x\n",
(char *)easy, easy->state); (char *)easy, easy->state);
#endif #endif
@@ -328,6 +332,7 @@ CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
} }
/* Connect. We get a connection identifier filled in. */ /* Connect. We get a connection identifier filled in. */
Curl_pgrsTime(easy->easy_handle, TIMER_STARTSINGLE);
easy->result = Curl_connect(easy->easy_handle, &easy->easy_conn); easy->result = Curl_connect(easy->easy_handle, &easy->easy_conn);
/* after the connect has been sent off, go WAITCONNECT */ /* after the connect has been sent off, go WAITCONNECT */
@@ -435,8 +440,9 @@ CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
/* When we follow redirects, must to go back to the CONNECT state */ /* When we follow redirects, must to go back to the CONNECT state */
if(easy->easy_conn->newurl) { if(easy->easy_conn->newurl) {
easy->result = Curl_follow(easy->easy_handle, char *newurl = easy->easy_conn->newurl;
strdup(easy->easy_conn->newurl)); easy->easy_conn->newurl = NULL;
easy->result = Curl_follow(easy->easy_handle, newurl);
if(CURLE_OK == easy->result) { if(CURLE_OK == easy->result) {
easy->state = CURLM_STATE_CONNECT; easy->state = CURLM_STATE_CONNECT;
result = CURLM_CALL_MULTI_PERFORM; result = CURLM_CALL_MULTI_PERFORM;
@@ -468,11 +474,12 @@ CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
} }
if(CURLM_STATE_COMPLETED != easy->state) { if(CURLM_STATE_COMPLETED != easy->state) {
if(CURLE_OK != easy->result) if(CURLE_OK != easy->result) {
/* /*
* If an error was returned, and we aren't in completed state now, * If an error was returned, and we aren't in completed state now,
* then we go to completed and consider this transfer aborted. */ * then we go to completed and consider this transfer aborted. */
easy->state = CURLM_STATE_COMPLETED; easy->state = CURLM_STATE_COMPLETED;
}
else else
/* this one still lives! */ /* this one still lives! */
(*running_handles)++; (*running_handles)++;

View File

@@ -46,7 +46,7 @@
#include "strtok.h" #include "strtok.h"
/* The last #include file should be: */ /* The last #include file should be: */
#ifdef MALLOCDEBUG #ifdef CURLDEBUG
#include "memdebug.h" #include "memdebug.h"
#endif #endif
@@ -119,7 +119,7 @@ int Curl_parsenetrc(char *host,
sprintf(netrcbuffer, "%s%s%s", home, DIR_CHAR, NETRC); sprintf(netrcbuffer, "%s%s%s", home, DIR_CHAR, NETRC);
#ifdef MALLOCDEBUG #ifdef CURLDEBUG
{ {
/* This is a hack to allow testing. /* This is a hack to allow testing.
* If compiled with --enable-debug and CURL_DEBUG_NETRC is defined, * If compiled with --enable-debug and CURL_DEBUG_NETRC is defined,
@@ -141,7 +141,7 @@ int Curl_parsenetrc(char *host,
free(override); free(override);
} }
} }
#endif /* MALLOCDEBUG */ #endif /* CURLDEBUG */
file = fopen(netrcbuffer, "r"); file = fopen(netrcbuffer, "r");
if(file) { if(file) {

View File

@@ -172,18 +172,20 @@ void Curl_pgrsSetUploadCounter(struct SessionHandle *data, double size)
void Curl_pgrsSetDownloadSize(struct SessionHandle *data, double size) void Curl_pgrsSetDownloadSize(struct SessionHandle *data, double size)
{ {
if(size > 0) { data->progress.size_dl = size;
data->progress.size_dl = size; if(size > 0)
data->progress.flags |= PGRS_DL_SIZE_KNOWN; data->progress.flags |= PGRS_DL_SIZE_KNOWN;
} else
data->progress.flags &= ~PGRS_DL_SIZE_KNOWN;
} }
void Curl_pgrsSetUploadSize(struct SessionHandle *data, double size) void Curl_pgrsSetUploadSize(struct SessionHandle *data, double size)
{ {
if(size > 0) { data->progress.size_ul = size;
data->progress.size_ul = size; if(size > 0)
data->progress.flags |= PGRS_UL_SIZE_KNOWN; data->progress.flags |= PGRS_UL_SIZE_KNOWN;
} else
data->progress.flags &= ~PGRS_UL_SIZE_KNOWN;
} }
/* EXAMPLE OUTPUT to follow: /* EXAMPLE OUTPUT to follow:

View File

@@ -60,7 +60,7 @@
#include "ftp.h" #include "ftp.h"
/* The last #include file should be: */ /* The last #include file should be: */
#ifdef MALLOCDEBUG #ifdef CURLDEBUG
#include "memdebug.h" #include "memdebug.h"
#endif #endif

View File

@@ -46,6 +46,7 @@
#include <curl/curl.h> #include <curl/curl.h>
#include "urldata.h" #include "urldata.h"
#include "sendf.h" #include "sendf.h"
#include "connect.h" /* for the Curl_ourerrno() proto */
#define _MPRINTF_REPLACE /* use the internal *printf() functions */ #define _MPRINTF_REPLACE /* use the internal *printf() functions */
#include <curl/mprintf.h> #include <curl/mprintf.h>
@@ -55,7 +56,7 @@
#endif #endif
#include <string.h> #include <string.h>
/* The last #include file should be: */ /* The last #include file should be: */
#ifdef MALLOCDEBUG #ifdef CURLDEBUG
#include "memdebug.h" #include "memdebug.h"
#endif #endif
@@ -93,7 +94,6 @@ struct curl_slist *curl_slist_append(struct curl_slist *list,
new_item->data = strdup(data); new_item->data = strdup(data);
} }
if (new_item == NULL || new_item->data == NULL) { if (new_item == NULL || new_item->data == NULL) {
fprintf(stderr, "Cannot allocate memory for QUOTE list.\n");
return NULL; return NULL;
} }
@@ -228,6 +228,8 @@ CURLcode Curl_write(struct connectdata *conn, int sockfd,
ssize_t *written) ssize_t *written)
{ {
ssize_t bytes_written; ssize_t bytes_written;
CURLcode retcode;
(void)conn;
#ifdef USE_SSLEAY #ifdef USE_SSLEAY
/* SSL_write() is said to return 'int' while write() and send() returns /* SSL_write() is said to return 'int' while write() and send() returns
@@ -242,12 +244,28 @@ CURLcode Curl_write(struct connectdata *conn, int sockfd,
switch(err) { switch(err) {
case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_READ:
case SSL_ERROR_WANT_WRITE: case SSL_ERROR_WANT_WRITE:
/* this is basicly the EWOULDBLOCK equivalent */ /* The operation did not complete; the same TLS/SSL I/O function
should be called again later. This is basicly an EWOULDBLOCK
equivalent. */
*written = 0; *written = 0;
return CURLE_OK; return CURLE_OK;
case SSL_ERROR_SYSCALL: case SSL_ERROR_SYSCALL:
failf(conn->data, "SSL_write() returned SYSCALL, errno = %d\n", errno); failf(conn->data, "SSL_write() returned SYSCALL, errno = %d\n",
Curl_ourerrno());
return CURLE_SEND_ERROR; return CURLE_SEND_ERROR;
case SSL_ERROR_SSL:
{
/* A failure in the SSL library occurred, usually a
protocol error. The OpenSSL error queue contains more
information on the error. */
char error_buffer[120]; /* OpenSSL documents that this must be at least
120 bytes long. */
int sslerror = ERR_get_error();
failf(conn->data, "SSL_write() error: %s\n",
ERR_error_string(sslerror, error_buffer));
return CURLE_SEND_ERROR;
}
break;
} }
/* a true error */ /* a true error */
failf(conn->data, "SSL_write() return error %d\n", err); failf(conn->data, "SSL_write() return error %d\n", err);
@@ -267,27 +285,31 @@ CURLcode Curl_write(struct connectdata *conn, int sockfd,
bytes_written = swrite(sockfd, mem, len); bytes_written = swrite(sockfd, mem, len);
} }
if(-1 == bytes_written) { if(-1 == bytes_written) {
#ifdef WIN32 int err = Curl_ourerrno();
if(WSAEWOULDBLOCK == GetLastError())
if(
#ifdef WSAEWOULDBLOCK
/* This is how Windows does it */
(WSAEWOULDBLOCK == err)
#else #else
/* As pointed out by Christophe Demory on March 11 2003, errno /* As pointed out by Christophe Demory on March 11 2003, errno
may be EWOULDBLOCK or on some systems EAGAIN when it returned may be EWOULDBLOCK or on some systems EAGAIN when it returned
due to its inability to send off data without blocking. We due to its inability to send off data without blocking. We
therefor treat both error codes the same here */ therefor treat both error codes the same here */
if((EWOULDBLOCK == errno) || (EAGAIN == errno)) (EWOULDBLOCK == err) || (EAGAIN == err) || (EINTR == err)
#endif #endif
{ )
/* this is just a case of EWOULDBLOCK */ /* this is just a case of EWOULDBLOCK */
*written=0; bytes_written=0;
return CURLE_OK;
}
} }
#ifdef USE_SSLEAY #ifdef USE_SSLEAY
} }
#endif #endif
*written = bytes_written; *written = bytes_written;
return (-1 != bytes_written)?CURLE_OK:CURLE_SEND_ERROR; retcode = (-1 != bytes_written)?CURLE_OK:CURLE_SEND_ERROR;
return retcode;
} }
/* client_write() sends data to the write callback(s) /* client_write() sends data to the write callback(s)
@@ -345,6 +367,7 @@ int Curl_read(struct connectdata *conn,
ssize_t *n) ssize_t *n)
{ {
ssize_t nread; ssize_t nread;
(void)conn;
*n=0; /* reset amount to zero */ *n=0; /* reset amount to zero */
#ifdef USE_SSLEAY #ifdef USE_SSLEAY
@@ -363,6 +386,17 @@ int Curl_read(struct connectdata *conn,
case SSL_ERROR_WANT_WRITE: case SSL_ERROR_WANT_WRITE:
/* there's data pending, re-invoke SSL_read() */ /* there's data pending, re-invoke SSL_read() */
return -1; /* basicly EWOULDBLOCK */ return -1; /* basicly EWOULDBLOCK */
case SSL_ERROR_SYSCALL:
/* openssl/ssl.h says "look at error stack/return value/errno" */
{
char error_buffer[120]; /* OpenSSL documents that this must be at least
120 bytes long. */
int sslerror = ERR_get_error();
failf(conn->data, "SSL read: %s, errno %d",
ERR_error_string(sslerror, error_buffer),
Curl_ourerrno() );
}
return CURLE_RECV_ERROR;
default: default:
failf(conn->data, "SSL read error: %d", err); failf(conn->data, "SSL read error: %d", err);
return CURLE_RECV_ERROR; return CURLE_RECV_ERROR;
@@ -379,10 +413,11 @@ int Curl_read(struct connectdata *conn,
nread = sread (sockfd, buf, buffersize); nread = sread (sockfd, buf, buffersize);
if(-1 == nread) { if(-1 == nread) {
int err = Curl_ourerrno();
#ifdef WIN32 #ifdef WIN32
if(WSAEWOULDBLOCK == GetLastError()) if(WSAEWOULDBLOCK == err)
#else #else
if(EWOULDBLOCK == errno) if((EWOULDBLOCK == err) || (EAGAIN == err) || (EINTR == err))
#endif #endif
return -1; return -1;
} }
@@ -408,6 +443,7 @@ int Curl_debug(struct SessionHandle *data, curl_infotype type,
switch(type) { switch(type) {
case CURLINFO_TEXT: case CURLINFO_TEXT:
case CURLINFO_HEADER_OUT: case CURLINFO_HEADER_OUT:
case CURLINFO_HEADER_IN:
fwrite(s_infotype[type], 2, 1, data->set.err); fwrite(s_infotype[type], 2, 1, data->set.err);
fwrite(ptr, size, 1, data->set.err); fwrite(ptr, size, 1, data->set.err);
break; break;

View File

@@ -135,20 +135,40 @@ defined(HAVE_LIBSSL) && defined(HAVE_LIBCRYPTO)
#define HAVE_ALARM #define HAVE_ALARM
#endif #endif
#define PATH_CHAR ";"
#define DIR_CHAR "\\" #define DIR_CHAR "\\"
#define DOT_CHAR "_" #define DOT_CHAR "_"
#else #else
#ifdef DJGPP
#define sclose(x) close_s(x)
#define sread(x,y,z) read_s(x,y,z)
#define swrite(x,y,z) write_s(x,y,z)
#define select(n,r,w,x,t) select_s(n,r,w,x,t)
#define ioctl(x,y,z) ioctlsocket(x,y,(char *)(z))
#define IOCTL_3_ARGS
#include <tcp.h>
#ifdef word
#undef word
#endif
#else
#define sclose(x) close(x) #define sclose(x) close(x)
#define sread(x,y,z) recv(x,y,z,0) #define sread(x,y,z) recv(x,y,z,0)
#define swrite(x,y,z) send(x,y,z,0) #define swrite(x,y,z) send(x,y,z,0)
#define HAVE_ALARM #define HAVE_ALARM
#define PATH_CHAR ":" #endif
#define DIR_CHAR "/" #define DIR_CHAR "/"
#define DOT_CHAR "." #define DOT_CHAR "."
#ifdef DJGPP
#undef DOT_CHAR
#define DOT_CHAR "_"
#endif
#ifdef HAVE_STRCASECMP #ifdef HAVE_STRCASECMP
/* this is for "-ansi -Wall -pedantic" to stop complaining! */ /* this is for "-ansi -Wall -pedantic" to stop complaining! */
extern int (strcasecmp)(const char *s1, const char *s2); extern int (strcasecmp)(const char *s1, const char *s2);

View File

@@ -24,12 +24,13 @@
#include "setup.h" #include "setup.h"
#include <stdarg.h> #include <stdarg.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h>
#include <curl/curl.h> #include <curl/curl.h>
#include "urldata.h" #include "urldata.h"
#include "share.h" #include "share.h"
/* The last #include file should be: */ /* The last #include file should be: */
#ifdef MALLOCDEBUG #ifdef CURLDEBUG
#include "memdebug.h" #include "memdebug.h"
#endif #endif

View File

@@ -46,7 +46,7 @@
#include <openssl/rand.h> #include <openssl/rand.h>
/* The last #include file should be: */ /* The last #include file should be: */
#ifdef MALLOCDEBUG #ifdef CURLDEBUG
#include "memdebug.h" #include "memdebug.h"
#endif #endif
@@ -697,6 +697,7 @@ static int Curl_ASN1_UTCTIME_output(struct connectdata *conn,
#endif #endif
/* ====================================================== */ /* ====================================================== */
#ifdef USE_SSLEAY
static int static int
cert_hostcheck(const char *certname, const char *hostname) cert_hostcheck(const char *certname, const char *hostname)
{ {
@@ -733,6 +734,7 @@ cert_hostcheck(const char *certname, const char *hostname)
} }
return 0; return 0;
} }
#endif
/* ====================================================== */ /* ====================================================== */
CURLcode CURLcode
@@ -783,6 +785,16 @@ Curl_SSLConnect(struct connectdata *conn)
failf(data, "SSL: couldn't create a context!"); failf(data, "SSL: couldn't create a context!");
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
} }
/* OpenSSL contains code to work-around lots of bugs and flaws in various
SSL-implementations. SSL_CTX_set_options() is used to enabled those
work-arounds. The man page for this option states that SSL_OP_ALL enables
ll the work-arounds and that "It is usually safe to use SSL_OP_ALL to
enable the bug workaround options if compatibility with somewhat broken
implementations is desired."
*/
SSL_CTX_set_options(conn->ssl.ctx, SSL_OP_ALL);
if(data->set.cert) { if(data->set.cert) {
if (!cert_stuff(conn, if (!cert_stuff(conn,
@@ -803,7 +815,7 @@ Curl_SSLConnect(struct connectdata *conn)
} }
} }
if(data->set.ssl.verifypeer){ if(data->set.ssl.verifypeer) {
SSL_CTX_set_verify(conn->ssl.ctx, SSL_CTX_set_verify(conn->ssl.ctx,
SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT| SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT|
SSL_VERIFY_CLIENT_ONCE, SSL_VERIFY_CLIENT_ONCE,
@@ -819,6 +831,15 @@ Curl_SSLConnect(struct connectdata *conn)
else else
SSL_CTX_set_verify(conn->ssl.ctx, SSL_VERIFY_NONE, cert_verify_callback); SSL_CTX_set_verify(conn->ssl.ctx, SSL_VERIFY_NONE, cert_verify_callback);
/* give application a chance to interfere with SSL set up. */
if (data->set.ssl.fsslctx) {
retcode = (*data->set.ssl.fsslctx)(data, conn->ssl.ctx,
data->set.ssl.fsslctxp);
if (retcode) {
failf(data,"error signaled by ssl ctx callback");
return retcode;
}
}
/* Lets make an SSL structure */ /* Lets make an SSL structure */
conn->ssl.handle = SSL_new (conn->ssl.ctx); conn->ssl.handle = SSL_new (conn->ssl.ctx);
@@ -900,14 +921,34 @@ Curl_SSLConnect(struct connectdata *conn)
/* untreated error */ /* untreated error */
char error_buffer[120]; /* OpenSSL documents that this must be at least char error_buffer[120]; /* OpenSSL documents that this must be at least
120 bytes long. */ 120 bytes long. */
/* detail is already set to the SSL error above */
failf(data, "SSL: %s", ERR_error_string(detail, error_buffer));
/* OpenSSL 0.9.6 and later has a function named detail = ERR_get_error(); /* Gets the earliest error code from the
ERRO_error_string_n() that takes the size of the buffer as a third thread's error queue and removes the
argument, and we should possibly switch to using that one in the entry. */
future. */
return CURLE_SSL_CONNECT_ERROR; switch(detail) {
case 0x1407E086:
/* 1407E086:
SSL routines:
SSL2_SET_CERTIFICATE:
certificate verify failed */
case 0x14090086:
/* 14090086:
SSL routines:
SSL3_GET_SERVER_CERTIFICATE:
certificate verify failed */
failf(data,
"SSL certificate problem, verify that the CA cert is OK");
return CURLE_SSL_CACERT;
default:
/* detail is already set to the SSL error above */
failf(data, "SSL: %s", ERR_error_string(detail, error_buffer));
/* OpenSSL 0.9.6 and later has a function named
ERRO_error_string_n() that takes the size of the buffer as a third
argument, and we should possibly switch to using that one in the
future. */
return CURLE_SSL_CONNECT_ERROR;
}
} }
} }
else else

View File

@@ -45,7 +45,6 @@
#endif #endif
#include <netinet/in.h> #include <netinet/in.h>
#include <sys/time.h> #include <sys/time.h>
#include <sys/resource.h>
#ifdef HAVE_UNISTD_H #ifdef HAVE_UNISTD_H
#include <unistd.h> #include <unistd.h>
#endif #endif
@@ -84,7 +83,7 @@
#include "arpa_telnet.h" #include "arpa_telnet.h"
/* The last #include file should be: */ /* The last #include file should be: */
#ifdef MALLOCDEBUG #ifdef CURLDEBUG
#include "memdebug.h" #include "memdebug.h"
#endif #endif
@@ -756,7 +755,7 @@ static int check_telnet_options(struct connectdata *conn)
if(conn->bits.user_passwd) if(conn->bits.user_passwd)
{ {
char *buf = malloc(256); char *buf = malloc(256);
sprintf(buf, "USER,%s", data->state.user); sprintf(buf, "USER,%s", conn->user);
tn->telnet_vars = curl_slist_append(tn->telnet_vars, buf); tn->telnet_vars = curl_slist_append(tn->telnet_vars, buf);
tn->us_preferred[CURL_TELOPT_NEW_ENVIRON] = CURL_YES; tn->us_preferred[CURL_TELOPT_NEW_ENVIRON] = CURL_YES;

View File

@@ -46,7 +46,6 @@
#endif #endif
#include <netinet/in.h> #include <netinet/in.h>
#include <sys/time.h> #include <sys/time.h>
#include <sys/resource.h>
#ifdef HAVE_UNISTD_H #ifdef HAVE_UNISTD_H
#include <unistd.h> #include <unistd.h>
#endif #endif
@@ -95,12 +94,15 @@
#include "url.h" #include "url.h"
#include "getinfo.h" #include "getinfo.h"
#include "ssluse.h" #include "ssluse.h"
#include "http_digest.h"
#include "http_ntlm.h"
#include "http_negotiate.h"
#define _MPRINTF_REPLACE /* use our functions only */ #define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h> #include <curl/mprintf.h>
/* The last #include file should be: */ /* The last #include file should be: */
#ifdef MALLOCDEBUG #ifdef CURLDEBUG
#include "memdebug.h" #include "memdebug.h"
#endif #endif
@@ -284,6 +286,9 @@ CURLcode Curl_readwrite(struct connectdata *conn,
/* header line within buffer loop */ /* header line within buffer loop */
do { do {
int hbufp_index; int hbufp_index;
int rest_length;
int full_length;
int writetype;
/* str_start is start of line within buf */ /* str_start is start of line within buf */
k->str_start = k->str; k->str_start = k->str;
@@ -325,22 +330,24 @@ CURLcode Curl_readwrite(struct connectdata *conn,
break; /* read more and try again */ break; /* read more and try again */
} }
/* decrease the size of the remaining buffer */ /* decrease the size of the remaining (supposed) header line */
nread -= (k->end_ptr - k->str)+1; rest_length = (k->end_ptr - k->str)+1;
nread -= rest_length;
k->str = k->end_ptr + 1; /* move past new line */ k->str = k->end_ptr + 1; /* move past new line */
full_length = k->str - k->str_start;
/* /*
* We're about to copy a chunk of data to the end of the * We're about to copy a chunk of data to the end of the
* already received header. We make sure that the full string * already received header. We make sure that the full string
* fit in the allocated header buffer, or else we enlarge * fit in the allocated header buffer, or else we enlarge
* it. * it.
*/ */
if (k->hbuflen + (k->str - k->str_start) >= if (k->hbuflen + full_length >=
data->state.headersize) { data->state.headersize) {
char *newbuff; char *newbuff;
long newsize=MAX((k->hbuflen+ long newsize=MAX((k->hbuflen+full_length)*3/2,
(k->str-k->str_start))*3/2,
data->state.headersize*2); data->state.headersize*2);
hbufp_index = k->hbufp - data->state.headerbuff; hbufp_index = k->hbufp - data->state.headerbuff;
newbuff = (char *)realloc(data->state.headerbuff, newsize); newbuff = (char *)realloc(data->state.headerbuff, newsize);
@@ -354,10 +361,11 @@ CURLcode Curl_readwrite(struct connectdata *conn,
} }
/* copy to end of line */ /* copy to end of line */
strncpy (k->hbufp, k->str_start, k->str - k->str_start); strncpy (k->hbufp, k->str_start, full_length);
k->hbufp += k->str - k->str_start; k->hbufp += full_length;
k->hbuflen += k->str - k->str_start; k->hbuflen += full_length;
*k->hbufp = 0; *k->hbufp = 0;
k->end_ptr = k->hbufp;
k->p = data->state.headerbuff; k->p = data->state.headerbuff;
@@ -371,7 +379,14 @@ CURLcode Curl_readwrite(struct connectdata *conn,
!checkhttpprefix(data, data->state.headerbuff)) { !checkhttpprefix(data, data->state.headerbuff)) {
/* this is not the beginning of a HTTP first header line */ /* this is not the beginning of a HTTP first header line */
k->header = FALSE; k->header = FALSE;
k->badheader = HEADER_PARTHEADER; if(nread)
/* since there's more, this is a partial bad header */
k->badheader = HEADER_PARTHEADER;
else {
/* this was all we read so its all a bad header */
k->badheader = HEADER_ALLBAD;
nread = rest_length;
}
break; break;
} }
} }
@@ -421,13 +436,13 @@ CURLcode Curl_readwrite(struct connectdata *conn,
/* now, only output this if the header AND body are requested: /* now, only output this if the header AND body are requested:
*/ */
k->writetype = CLIENTWRITE_HEADER; writetype = CLIENTWRITE_HEADER;
if (data->set.http_include_header) if (data->set.http_include_header)
k->writetype |= CLIENTWRITE_BODY; writetype |= CLIENTWRITE_BODY;
headerlen = k->p - data->state.headerbuff; headerlen = k->p - data->state.headerbuff;
result = Curl_client_write(data, k->writetype, result = Curl_client_write(data, writetype,
data->state.headerbuff, data->state.headerbuff,
headerlen); headerlen);
if(result) if(result)
@@ -445,11 +460,16 @@ CURLcode Curl_readwrite(struct connectdata *conn,
*/ */
if(data->set.no_body) if(data->set.no_body)
stop_reading = TRUE; stop_reading = TRUE;
else if(!conn->bits.close) { else {
/* If this is not the last request before a close, we must /* If we know the expected size of this document, we set the
set the maximum download size to the size of the maximum download size to the size of the expected
expected document or else, we won't know when to stop document or else, we won't know when to stop reading!
reading! */
Note that we set the download maximum even if we read a
"Connection: close" header, to make sure that
"Content-Length: 0" still prevents us from attempting to
read the (missing) response-body.
*/
if(-1 != conn->size) if(-1 != conn->size)
conn->maxdownload = conn->size; conn->maxdownload = conn->size;
} }
@@ -519,7 +539,8 @@ CURLcode Curl_readwrite(struct connectdata *conn,
/* If we have been told to fail hard on HTTP-errors, /* If we have been told to fail hard on HTTP-errors,
here is the check for that: */ here is the check for that: */
/* serious error, go home! */ /* serious error, go home! */
failf (data, "The requested file was not found"); failf (data, "The requested URL returned error: %d",
k->httpcode);
return CURLE_HTTP_RETURNED_ERROR; return CURLE_HTTP_RETURNED_ERROR;
} }
@@ -568,7 +589,7 @@ CURLcode Curl_readwrite(struct connectdata *conn,
int len; int len;
/* Find the first non-space letter */ /* Find the first non-space letter */
for(start=k->p+14; for(start=k->p+13;
*start && isspace((int)*start); *start && isspace((int)*start);
start++); start++);
@@ -647,12 +668,12 @@ CURLcode Curl_readwrite(struct connectdata *conn,
else if (checkprefix("Content-Encoding:", k->p) && else if (checkprefix("Content-Encoding:", k->p) &&
data->set.encoding) { data->set.encoding) {
/* /*
* Process Content-Encoding. Look for the values: identity, gzip, * Process Content-Encoding. Look for the values: identity,
* defalte, compress, x-gzip and x-compress. x-gzip and * gzip, deflate, compress, x-gzip and x-compress. x-gzip and
* x-compress are the same as gzip and compress. (Sec 3.5 RFC * x-compress are the same as gzip and compress. (Sec 3.5 RFC
* 2616). zlib cannot handle compress, and gzip is not currently * 2616). zlib cannot handle compress. However, errors are
* implemented. However, errors are handled further down when the * handled further down when the response body is processed
* response body is processed 08/27/02 jhrg */ */
char *start; char *start;
/* Find the first non-space letter */ /* Find the first non-space letter */
@@ -686,7 +707,12 @@ CURLcode Curl_readwrite(struct connectdata *conn,
} }
else if(data->cookies && else if(data->cookies &&
checkprefix("Set-Cookie:", k->p)) { checkprefix("Set-Cookie:", k->p)) {
Curl_cookie_add(data->cookies, TRUE, k->p+11, conn->name); Curl_cookie_add(data->cookies, TRUE, k->p+11,
/* If there is a custom-set Host: name, use it
here, or else use real peer host name. */
conn->allocptr.cookiehost?
conn->allocptr.cookiehost:conn->name,
conn->ppath);
} }
else if(checkprefix("Last-Modified:", k->p) && else if(checkprefix("Last-Modified:", k->p) &&
(data->set.timecondition || data->set.get_filetime) ) { (data->set.timecondition || data->set.get_filetime) ) {
@@ -696,47 +722,144 @@ CURLcode Curl_readwrite(struct connectdata *conn,
if(data->set.get_filetime) if(data->set.get_filetime)
data->info.filetime = k->timeofdoc; data->info.filetime = k->timeofdoc;
} }
else if ((k->httpcode >= 300 && k->httpcode < 400) && else if(checkprefix("WWW-Authenticate:", k->p) &&
(data->set.http_follow_location) && (401 == k->httpcode)) {
checkprefix("Location:", k->p)) { /*
/* this is the URL that the server advices us to get instead */ * This page requires authentication
char *ptr; */
char *start=k->p; char *start = k->p+strlen("WWW-Authenticate:");
char backup;
start += 9; /* pass "Location:" */ /* pass all white spaces */
while(*start && isspace((int)*start))
/* Skip spaces and tabs. We do this to support multiple
white spaces after the "Location:" keyword. */
while(*start && isspace((int)*start ))
start++; start++;
ptr = start; /* start scanning here */
/* scan through the string to find the end */ #ifdef GSSAPI
while(*ptr && !isspace((int)*ptr)) if (checkprefix("GSS-Negotiate", start)) {
ptr++; if(data->state.authwant == CURLAUTH_GSSNEGOTIATE) {
backup = *ptr; /* store the ending letter */ /* if exactly this is wanted, go */
if(ptr != start) { int neg = Curl_input_negotiate(conn, start);
*ptr = '\0'; /* zero terminate */ if (neg == 0)
conn->newurl = strdup(start); /* clone string */ conn->newurl = strdup(data->change.url);
*ptr = backup; /* restore ending letter */ }
else
if(data->state.authwant & CURLAUTH_GSSNEGOTIATE)
data->state.authavail |= CURLAUTH_GSSNEGOTIATE;
} }
else
#endif
#ifdef USE_SSLEAY
/* NTLM support requires the SSL crypto libs */
if(checkprefix("NTLM", start)) {
if(data->state.authwant == CURLAUTH_NTLM) {
/* NTLM authentication is activated */
CURLntlm ntlm =
Curl_input_ntlm(conn, FALSE, start);
if(CURLNTLM_BAD != ntlm)
conn->newurl = strdup(data->change.url); /* clone string */
else
infof(data, "Authentication problem. Ignoring this.\n");
}
else
if(data->state.authwant & CURLAUTH_NTLM)
data->state.authavail |= CURLAUTH_NTLM;
}
else
#endif
if(checkprefix("Digest", start)) {
if(data->state.authwant == CURLAUTH_DIGEST) {
/* Digest authentication is activated */
CURLdigest dig = CURLDIGEST_BAD;
if(data->state.digest.nonce)
infof(data, "Authentication problem. Ignoring this.\n");
else
dig = Curl_input_digest(conn, start);
if(CURLDIGEST_FINE == dig)
/* We act on it. Store our new url, which happens to be
the same one we already use! */
conn->newurl = strdup(data->change.url); /* clone string */
}
else
if(data->state.authwant & CURLAUTH_DIGEST) {
/* We don't know if Digest is what we're gonna use, but we
call this function anyway to store the digest data that
is provided on this line, to skip the extra round-trip
we need to do otherwise. We must sure to free this
data! */
Curl_input_digest(conn, start);
data->state.authavail |= CURLAUTH_DIGEST;
}
}
else if(checkprefix("Basic", start)) {
if((data->state.authwant == CURLAUTH_BASIC) &&
(k->httpcode == 401)) {
/* We asked for Basic authentication but got a 401 back
anyway, which basicly means our name+password isn't
valid. */
data->state.authavail = CURLAUTH_NONE;
infof(data, "Authentication problem. Ignoring this.\n");
}
else if(data->state.authwant & CURLAUTH_BASIC) {
data->state.authavail |= CURLAUTH_BASIC;
}
}
}
else if ((k->httpcode >= 300 && k->httpcode < 400) &&
checkprefix("Location:", k->p)) {
if(data->set.http_follow_location) {
/* this is the URL that the server advices us to get instead */
char *ptr;
char *start=k->p;
char backup;
start += 9; /* pass "Location:" */
/* Skip spaces and tabs. We do this to support multiple
white spaces after the "Location:" keyword. */
while(*start && isspace((int)*start ))
start++;
/* Scan through the string from the end to find the last
non-space. k->end_ptr points to the actual terminating zero
letter, move pointer one letter back and start from
there. This logic strips off trailing whitespace, but keeps
any embedded whitespace. */
ptr = k->end_ptr-1;
while((ptr>=start) && isspace((int)*ptr))
ptr--;
ptr++;
backup = *ptr; /* store the ending letter */
if(ptr != start) {
*ptr = '\0'; /* zero terminate */
conn->newurl = strdup(start); /* clone string */
*ptr = backup; /* restore ending letter */
}
}
#if 0 /* for consideration */
else {
/* This is a Location: but we have not been instructed to
follow it */
infof(data, "We ignore this location header as instructed\n");
}
#endif
} }
/* /*
* End of header-checks. Write them to the client. * End of header-checks. Write them to the client.
*/ */
k->writetype = CLIENTWRITE_HEADER; writetype = CLIENTWRITE_HEADER;
if (data->set.http_include_header) if (data->set.http_include_header)
k->writetype |= CLIENTWRITE_BODY; writetype |= CLIENTWRITE_BODY;
if(data->set.verbose) if(data->set.verbose)
Curl_debug(data, CURLINFO_HEADER_IN, Curl_debug(data, CURLINFO_HEADER_IN,
k->p, k->hbuflen); k->p, k->hbuflen);
result = Curl_client_write(data, k->writetype, k->p, result = Curl_client_write(data, writetype, k->p, k->hbuflen);
k->hbuflen);
if(result) if(result)
return result; return result;
@@ -769,15 +892,41 @@ CURLcode Curl_readwrite(struct connectdata *conn,
write a piece 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 (conn->newurl) {
/* abort after the headers if "follow Location" is set */ if(data->state.authavail) {
infof (data, "Follow to new URL: %s\n", conn->newurl); if(data->state.authavail & CURLAUTH_GSSNEGOTIATE)
k->keepon &= ~KEEP_READ; data->state.authwant = CURLAUTH_GSSNEGOTIATE;
FD_ZERO(&k->rkeepfd); else if(data->state.authavail & CURLAUTH_DIGEST)
*done = TRUE; data->state.authwant = CURLAUTH_DIGEST;
return CURLE_OK; else if(data->state.authavail & CURLAUTH_NTLM)
data->state.authwant = CURLAUTH_NTLM;
else if(data->state.authavail & CURLAUTH_BASIC)
data->state.authwant = CURLAUTH_BASIC;
else
data->state.authwant = CURLAUTH_NONE; /* none */
if(data->state.authwant)
conn->newurl = strdup(data->change.url); /* clone string */
data->state.authavail = CURLAUTH_NONE; /* clear it here */
} }
else if (conn->resume_from &&
if (conn->newurl) {
if(conn->bits.close) {
/* Abort after the headers if "follow Location" is set
and we're set to close anyway. */
k->keepon &= ~KEEP_READ;
FD_ZERO(&k->rkeepfd);
*done = TRUE;
return CURLE_OK;
}
/* We have a new url to load, but since we want to be able
to re-use this connection properly, we read the full
response in "ignore more" */
k->ignorebody = TRUE;
infof(data, "Ignoring the response-body\n");
}
if (conn->resume_from &&
!k->content_range && !k->content_range &&
(data->set.httpreq==HTTPREQ_GET)) { (data->set.httpreq==HTTPREQ_GET)) {
/* we wanted to resume a download, although the server /* we wanted to resume a download, although the server
@@ -878,7 +1027,7 @@ CURLcode Curl_readwrite(struct connectdata *conn,
if(!conn->bits.chunk && (nread || k->badheader)) { if(!conn->bits.chunk && (nread || k->badheader)) {
/* If this is chunky transfer, it was already written */ /* If this is chunky transfer, it was already written */
if(k->badheader) { if(k->badheader && !k->ignorebody) {
/* we parsed a piece of data wrongly assuming it was a header /* we parsed a piece of data wrongly assuming it was a header
and now we output it as body instead */ and now we output it as body instead */
result = Curl_client_write(data, CLIENTWRITE_BODY, result = Curl_client_write(data, CLIENTWRITE_BODY,
@@ -888,7 +1037,9 @@ CURLcode Curl_readwrite(struct connectdata *conn,
if(k->badheader < HEADER_ALLBAD) { if(k->badheader < HEADER_ALLBAD) {
/* This switch handles various content encodings. If there's an /* This switch handles various content encodings. If there's an
error here, be sure to check over the almost identical code error here, be sure to check over the almost identical code
in http_chunk.c. 08/29/02 jhrg */ in http_chunks.c. 08/29/02 jhrg
Make sure that ALL_CONTENT_ENCODINGS contains all the
encodings handled here. */
#ifdef HAVE_LIBZ #ifdef HAVE_LIBZ
switch (k->content_encoding) { switch (k->content_encoding) {
case IDENTITY: case IDENTITY:
@@ -897,8 +1048,9 @@ CURLcode Curl_readwrite(struct connectdata *conn,
Content-Encoding header. See Curl_readwrite_init; the Content-Encoding header. See Curl_readwrite_init; the
memset() call initializes k->content_encoding to zero. memset() call initializes k->content_encoding to zero.
08/28/02 jhrg */ 08/28/02 jhrg */
result = Curl_client_write(data, CLIENTWRITE_BODY, k->str, if(!k->ignorebody)
nread); result = Curl_client_write(data, CLIENTWRITE_BODY, k->str,
nread);
#ifdef HAVE_LIBZ #ifdef HAVE_LIBZ
break; break;
@@ -907,11 +1059,15 @@ CURLcode Curl_readwrite(struct connectdata *conn,
result = Curl_unencode_deflate_write(data, k, nread); result = Curl_unencode_deflate_write(data, k, nread);
break; break;
case GZIP: /* FIXME 08/27/02 jhrg */ case GZIP:
case COMPRESS: /* Assume CLIENTWRITE_BODY; headers are not encoded. */
result = Curl_unencode_gzip_write(data, k, nread);
break;
case COMPRESS: /* FIXME 08/27/02 jhrg */
default: default:
failf (data, "Unrecognized content encoding type. " failf (data, "Unrecognized content encoding type. "
"libcurl understands `identity' and `deflate' " "libcurl understands `identity', `deflate' and `gzip' "
"content encodings."); "content encodings.");
result = CURLE_BAD_CONTENT_ENCODING; result = CURLE_BAD_CONTENT_ENCODING;
break; break;
@@ -940,7 +1096,7 @@ CURLcode Curl_readwrite(struct connectdata *conn,
int i, si; int i, si;
ssize_t bytes_written; ssize_t bytes_written;
bool writedone=FALSE; bool writedone=TRUE;
if ((k->bytecount == 0) && (k->writebytecount == 0)) if ((k->bytecount == 0) && (k->writebytecount == 0))
Curl_pgrsTime(data, TIMER_STARTTRANSFER); Curl_pgrsTime(data, TIMER_STARTTRANSFER);
@@ -1175,6 +1331,7 @@ CURLcode Curl_readwrite_init(struct connectdata *conn)
k->maxfd = (conn->sockfd>conn->writesockfd? k->maxfd = (conn->sockfd>conn->writesockfd?
conn->sockfd:conn->writesockfd)+1; conn->sockfd:conn->writesockfd)+1;
k->hbufp = data->state.headerbuff; k->hbufp = data->state.headerbuff;
k->ignorebody=FALSE;
Curl_pgrsTime(data, TIMER_PRETRANSFER); Curl_pgrsTime(data, TIMER_PRETRANSFER);
Curl_speedinit(data); Curl_speedinit(data);
@@ -1344,6 +1501,10 @@ CURLcode Curl_pretransfer(struct SessionHandle *data)
data->state.this_is_a_follow = FALSE; /* reset this */ data->state.this_is_a_follow = FALSE; /* reset this */
data->state.errorbuf = FALSE; /* no error has occurred */ data->state.errorbuf = FALSE; /* no error has occurred */
/* set preferred authentication, default to basic */
data->state.authwant = data->set.httpauth?data->set.httpauth:CURLAUTH_BASIC;
data->state.authavail = CURLAUTH_NONE; /* nothing so far */
/* If there was a list of cookie files to read and we haven't done it before, /* If there was a list of cookie files to read and we haven't done it before,
do it now! */ do it now! */
if(data->change.cookielist) { if(data->change.cookielist) {
@@ -1390,6 +1551,60 @@ CURLcode Curl_posttransfer(struct SessionHandle *data)
return CURLE_OK; return CURLE_OK;
} }
static int strlen_url(char *url)
{
char *ptr;
int newlen=0;
bool left=TRUE; /* left side of the ? */
for(ptr=url; *ptr; ptr++) {
switch(*ptr) {
case '?':
left=FALSE;
default:
newlen++;
break;
case ' ':
if(left)
newlen+=3;
else
newlen++;
break;
}
}
return newlen;
}
static void strcpy_url(char *output, char *url)
{
/* we must add this with whitespace-replacing */
bool left=TRUE;
char *iptr;
char *optr = output;
for(iptr = url; /* read from here */
*iptr; /* until zero byte */
iptr++) {
switch(*iptr) {
case '?':
left=FALSE;
default:
*optr++=*iptr;
break;
case ' ':
if(left) {
*optr++='%'; /* add a '%' */
*optr++='2'; /* add a '2' */
*optr++='0'; /* add a '0' */
}
else
*optr++='+'; /* add a '+' here */
break;
}
}
*optr=0; /* zero terminate output buffer */
}
CURLcode Curl_follow(struct SessionHandle *data, CURLcode Curl_follow(struct SessionHandle *data,
char *newurl) /* this 'newurl' is the Location: string, char *newurl) /* this 'newurl' is the Location: string,
and it must be malloc()ed before passed and it must be malloc()ed before passed
@@ -1398,6 +1613,8 @@ CURLcode Curl_follow(struct SessionHandle *data,
/* Location: redirect */ /* Location: redirect */
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 */
int newlen;
char *newest;
if (data->set.maxredirs && if (data->set.maxredirs &&
(data->set.followlocation >= data->set.maxredirs)) { (data->set.followlocation >= data->set.maxredirs)) {
@@ -1434,9 +1651,9 @@ CURLcode Curl_follow(struct SessionHandle *data,
*/ */
char *protsep; char *protsep;
char *pathsep; char *pathsep;
char *newest;
char *useurl = newurl; char *useurl = newurl;
int urllen;
/* we must make our own copy of the URL to play with, as it may /* we must make our own copy of the URL to play with, as it may
point to read-only data */ point to read-only data */
@@ -1509,42 +1726,79 @@ CURLcode Curl_follow(struct SessionHandle *data,
*pathsep=0; *pathsep=0;
} }
newest=(char *)malloc( strlen(url_clone) + /* If the new part contains a space, this is a mighty stupid redirect
1 + /* possible slash */ but we still make an effort to do "right". To the left of a '?'
strlen(useurl) + 1/* zero byte */); letter we replace each space with %20 while it is replaced with '+'
on the right side of the '?' letter.
*/
newlen = strlen_url(useurl);
urllen = strlen(url_clone);
newest=(char *)malloc( urllen + 1 + /* possible slash */
newlen + 1 /* zero byte */);
if(!newest) if(!newest)
return CURLE_OUT_OF_MEMORY; /* go out from this */ return CURLE_OUT_OF_MEMORY; /* go out from this */
sprintf(newest, "%s%s%s", url_clone, /* copy over the root url part */
(('/' == useurl[0]) || (protsep && !*protsep))?"":"/", memcpy(newest, url_clone, urllen);
useurl);
/* check if we need to append a slash */
if(('/' == useurl[0]) || (protsep && !*protsep))
;
else
newest[urllen++]='/';
/* then append the new piece on the right side */
strcpy_url(&newest[urllen], useurl);
free(newurl); /* newurl is the allocated pointer */ free(newurl); /* newurl is the allocated pointer */
free(url_clone); free(url_clone);
newurl = newest; newurl = newest;
} }
else else {
/* This is an absolute URL, don't allow the custom port number */ /* This is an absolute URL, don't allow the custom port number */
data->state.allow_port = FALSE; data->state.allow_port = FALSE;
if(strchr(newurl, ' ')) {
/* This new URL contains at least one space, this is a mighty stupid
redirect but we still make an effort to do "right". */
newlen = strlen_url(newurl);
newest = malloc(newlen+1); /* get memory for this */
if(newest) {
strcpy_url(newest, newurl); /* create a space-free URL */
free(newurl); /* that was no good */
newurl = newest; /* use this instead now */
}
}
}
if(data->change.url_alloc) if(data->change.url_alloc)
free(data->change.url); free(data->change.url);
else else
data->change.url_alloc = TRUE; /* the URL is allocated */ data->change.url_alloc = TRUE; /* the URL is allocated */
/* TBD: set the URL with curl_setopt() */
data->change.url = newurl; data->change.url = newurl;
newurl = NULL; /* don't free! */ newurl = NULL; /* don't free! */
infof(data, "Follows Location: to new URL: '%s'\n", data->change.url); infof(data, "Issue another request to this URL: '%s'\n", data->change.url);
/* /*
* We get here when the HTTP code is 300-399. We need to perform * We get here when the HTTP code is 300-399 (and 401). We need to perform
* differently based on exactly what return code there was. * differently based on exactly what return code there was.
* Discussed on the curl mailing list and posted about on the 26th *
* of January 2001. * News from 7.10.6: we can also get here on a 401, in case we act on a
* HTTP authentication scheme other than Basic.
*/ */
switch(data->info.httpcode) { switch(data->info.httpcode) {
case 401:
/* Act on an authentication, we keep on moving and do the Authorization:
XXXX header in the HTTP request code snippet */
break;
case 300: /* Multiple Choices */ case 300: /* Multiple Choices */
case 306: /* Not used */ case 306: /* Not used */
case 307: /* Temporary Redirect */ case 307: /* Temporary Redirect */
@@ -1642,9 +1896,29 @@ CURLcode Curl_perform(struct SessionHandle *data)
* performed after this do-while loop. * performed after this do-while loop.
*/ */
do { do {
Curl_pgrsTime(data, TIMER_STARTSINGLE); int urlchanged = FALSE;
res = Curl_connect(data, &conn); do {
Curl_pgrsTime(data, TIMER_STARTSINGLE);
data->change.url_changed = FALSE;
res = Curl_connect(data, &conn);
/* If a callback (or something) has altered the URL we should use within
the Curl_connect(), we detect it here and act as if we are redirected
to the new URL */
urlchanged = data->change.url_changed;
if ((CURLE_OK == res) && urlchanged) {
char *newurl;
res = Curl_done(conn);
if(CURLE_OK == res) {
newurl = strdup(data->change.url);
res = Curl_follow(data, newurl);
if(res)
free(newurl);
}
}
} while (urlchanged && res == CURLE_OK) ;
if(res == CURLE_OK) { if(res == CURLE_OK) {
res = Curl_do(&conn); res = Curl_do(&conn);

300
lib/url.c
View File

@@ -45,7 +45,6 @@
#endif #endif
#include <netinet/in.h> #include <netinet/in.h>
#include <sys/time.h> #include <sys/time.h>
#include <sys/resource.h>
#ifdef HAVE_UNISTD_H #ifdef HAVE_UNISTD_H
#include <unistd.h> #include <unistd.h>
#endif #endif
@@ -106,6 +105,9 @@
#include "escape.h" #include "escape.h"
#include "strtok.h" #include "strtok.h"
#include "share.h" #include "share.h"
#include "content_encoding.h"
#include "http_digest.h"
#include "http_negotiate.h"
/* And now for the protocols */ /* And now for the protocols */
#include "ftp.h" #include "ftp.h"
@@ -132,7 +134,7 @@
#endif #endif
/* The last #include file should be: */ /* The last #include file should be: */
#ifdef MALLOCDEBUG #ifdef CURLDEBUG
#include "memdebug.h" #include "memdebug.h"
#endif #endif
@@ -164,6 +166,11 @@ RETSIGTYPE alarmfunc(int signal)
} }
#endif #endif
void Curl_safefree(void *ptr)
{
if(ptr)
free(ptr);
}
/* /*
* This is the internal function curl_easy_cleanup() calls. This should * This is the internal function curl_easy_cleanup() calls. This should
@@ -191,11 +198,8 @@ CURLcode Curl_close(struct SessionHandle *data)
if(data->change.cookielist) /* clean up list if any */ if(data->change.cookielist) /* clean up list if any */
curl_slist_free_all(data->change.cookielist); curl_slist_free_all(data->change.cookielist);
if(data->state.auth_host) Curl_safefree(data->state.auth_host);
free(data->state.auth_host); Curl_safefree(data->state.scratch);
if(data->state.scratch)
free(data->state.scratch);
if(data->change.proxy_alloc) if(data->change.proxy_alloc)
free(data->change.proxy); free(data->change.proxy);
@@ -206,13 +210,14 @@ CURLcode Curl_close(struct SessionHandle *data)
if(data->change.url_alloc) if(data->change.url_alloc)
free(data->change.url); free(data->change.url);
if(data->state.headerbuff) Curl_safefree(data->state.headerbuff);
free(data->state.headerbuff);
#ifndef CURL_DISABLE_HTTP #ifndef CURL_DISABLE_HTTP
if(data->set.cookiejar) if(data->set.cookiejar) {
/* we have a "destination" for all the cookies to get dumped to */ /* we have a "destination" for all the cookies to get dumped to */
Curl_cookie_output(data->cookies, data->set.cookiejar); if(Curl_cookie_output(data->cookies, data->set.cookiejar))
infof(data, "WARNING: failed to save cookies in given jar\n");
}
Curl_cookie_cleanup(data->cookies); Curl_cookie_cleanup(data->cookies);
#endif #endif
@@ -220,8 +225,9 @@ CURLcode Curl_close(struct SessionHandle *data)
/* free the connection cache */ /* free the connection cache */
free(data->state.connects); free(data->state.connects);
if(data->info.contenttype) Curl_safefree(data->info.contenttype);
free(data->info.contenttype);
Curl_digest_cleanup(data);
free(data); free(data);
return CURLE_OK; return CURLE_OK;
@@ -282,6 +288,7 @@ CURLcode Curl_open(struct SessionHandle **curl)
data->set.httpreq = HTTPREQ_GET; /* Default HTTP request */ data->set.httpreq = HTTPREQ_GET; /* Default HTTP request */
data->set.ftp_use_epsv = TRUE; /* FTP defaults to EPSV operations */ data->set.ftp_use_epsv = TRUE; /* FTP defaults to EPSV operations */
data->set.ftp_use_eprt = TRUE; /* FTP defaults to EPRT operations */
data->set.dns_cache_timeout = 60; /* Timeout every 60 seconds by default */ data->set.dns_cache_timeout = 60; /* Timeout every 60 seconds by default */
@@ -632,10 +639,14 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, ...)
data->set.ftp_use_port = data->set.ftpport?1:0; data->set.ftp_use_port = data->set.ftpport?1:0;
break; break;
case CURLOPT_FTP_USE_EPRT:
data->set.ftp_use_eprt = va_arg(param, long)?TRUE:FALSE;
break;
case CURLOPT_FTP_USE_EPSV: case CURLOPT_FTP_USE_EPSV:
data->set.ftp_use_epsv = va_arg(param, long)?TRUE:FALSE; data->set.ftp_use_epsv = va_arg(param, long)?TRUE:FALSE;
break; break;
case CURLOPT_HTTPHEADER: case CURLOPT_HTTPHEADER:
/* /*
* Set a list with HTTP headers to use (or replace internals with) * Set a list with HTTP headers to use (or replace internals with)
@@ -711,6 +722,7 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, ...)
} }
data->set.set_url = va_arg(param, char *); data->set.set_url = va_arg(param, char *);
data->change.url = data->set.set_url; data->change.url = data->set.set_url;
data->change.url_changed = TRUE;
break; break;
case CURLOPT_PORT: case CURLOPT_PORT:
/* /*
@@ -818,10 +830,38 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, ...)
case CURLOPT_ENCODING: case CURLOPT_ENCODING:
/* /*
* String to use at the value of Accept-Encoding header. 08/28/02 jhrg * String to use at the value of Accept-Encoding header. 08/28/02 jhrg
*
* If the encoding is set to "" we use an Accept-Encoding header that
* encompasses all the encodings we support.
* If the encoding is set to NULL we don't send an Accept-Encoding header
* and ignore an received Content-Encoding header.
*
*/ */
data->set.encoding = va_arg(param, char *); data->set.encoding = va_arg(param, char *);
if(data->set.encoding && !*data->set.encoding)
data->set.encoding = (char*)ALL_CONTENT_ENCODINGS;
break; break;
case CURLOPT_HTTPAUTH:
/*
* Set HTTP Authentication type BITMASK.
*/
{
long auth = va_arg(param, long);
/* switch off bits we can't support */
#ifndef USE_SSLEAY
auth &= ~CURLAUTH_NTLM; /* no NTLM without SSL */
#endif
#ifndef GSSAPI
auth &= ~CURLAUTH_GSSNEGOTIATE; /* no GSS-Negotiate without GSSAPI */
#endif
if(!auth)
return CURLE_FAILED_INIT; /* no supported types left! */
data->set.httpauth = auth;
}
break;
case CURLOPT_USERPWD: case CURLOPT_USERPWD:
/* /*
* user:password to use in the operation * user:password to use in the operation
@@ -1051,6 +1091,18 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, ...)
*/ */
data->set.ssl.verifyhost = va_arg(param, long); data->set.ssl.verifyhost = va_arg(param, long);
break; break;
case CURLOPT_SSL_CTX_FUNCTION:
/*
* Set a SSL_CTX callback
*/
data->set.ssl.fsslctx = va_arg(param, curl_ssl_ctx_callback);
break;
case CURLOPT_SSL_CTX_DATA:
/*
* Set a SSL_CTX callback parameter pointer
*/
data->set.ssl.fsslctxp = va_arg(param, void *);
break;
case CURLOPT_CAINFO: case CURLOPT_CAINFO:
/* /*
* Set CA info for SSL connection. Specify file name of the CA certificate * Set CA info for SSL connection. Specify file name of the CA certificate
@@ -1180,14 +1232,9 @@ CURLcode Curl_disconnect(struct connectdata *conn)
/* This is set if protocol-specific cleanups should be made */ /* This is set if protocol-specific cleanups should be made */
conn->curl_disconnect(conn); conn->curl_disconnect(conn);
if(conn->proto.generic) Curl_safefree(conn->proto.generic);
free(conn->proto.generic); Curl_safefree(conn->newurl);
Curl_safefree(conn->path); /* the URL path part */
if(conn->newurl)
free(conn->newurl);
if(conn->path) /* the URL path part */
free(conn->path);
#ifdef USE_SSLEAY #ifdef USE_SSLEAY
Curl_SSL_Close(conn); Curl_SSL_Close(conn);
@@ -1199,25 +1246,20 @@ CURLcode Curl_disconnect(struct connectdata *conn)
if(-1 != conn->firstsocket) if(-1 != conn->firstsocket)
sclose(conn->firstsocket); sclose(conn->firstsocket);
if(conn->allocptr.proxyuserpwd) Curl_safefree(conn->user);
free(conn->allocptr.proxyuserpwd); Curl_safefree(conn->passwd);
if(conn->allocptr.uagent) Curl_safefree(conn->proxyuser);
free(conn->allocptr.uagent); Curl_safefree(conn->proxypasswd);
if(conn->allocptr.userpwd) Curl_safefree(conn->allocptr.proxyuserpwd);
free(conn->allocptr.userpwd); Curl_safefree(conn->allocptr.uagent);
if(conn->allocptr.accept_encoding) Curl_safefree(conn->allocptr.userpwd);
free(conn->allocptr.accept_encoding); Curl_safefree(conn->allocptr.accept_encoding);
if(conn->allocptr.rangeline) Curl_safefree(conn->allocptr.rangeline);
free(conn->allocptr.rangeline); Curl_safefree(conn->allocptr.ref);
if(conn->allocptr.ref) Curl_safefree(conn->allocptr.cookie);
free(conn->allocptr.ref); Curl_safefree(conn->allocptr.host);
if(conn->allocptr.cookie) Curl_safefree(conn->allocptr.cookiehost);
free(conn->allocptr.cookie); Curl_safefree(conn->proxyhost);
if(conn->allocptr.host)
free(conn->allocptr.host);
if(conn->proxyhost)
free(conn->proxyhost);
Curl_free_ssl_config(&conn->ssl_config); Curl_free_ssl_config(&conn->ssl_config);
@@ -1300,11 +1342,13 @@ ConnectionExists(struct SessionHandle *data,
continue; continue;
} }
} }
if(needle->protocol & PROT_FTP) { if((needle->protocol & PROT_FTP) ||
/* This is FTP, verify that we're using the same name and ((needle->protocol & PROT_HTTP) &&
password as well */ (needle->data->state.authwant==CURLAUTH_NTLM))) {
if(!strequal(needle->data->state.user, check->proto.ftp->user) || /* This is FTP or HTTP+NTLM, verify that we're using the same name
!strequal(needle->data->state.passwd, check->proto.ftp->passwd)) { and password as well */
if(!strequal(needle->user, check->user) ||
!strequal(needle->passwd, check->passwd)) {
/* one of them was different */ /* one of them was different */
continue; continue;
} }
@@ -1517,7 +1561,7 @@ static int handleSock5Proxy(
return 1; return 1;
} }
if ((socksreq[0] != 5) || /* version */ if ((socksreq[0] != 1) || /* version */
(socksreq[1] != 0)) { /* status */ (socksreq[1] != 0)) { /* status */
failf(conn->data, "User was rejected by the SOCKS5 server (%d %d).", failf(conn->data, "User was rejected by the SOCKS5 server (%d %d).",
socksreq[0], socksreq[1]); socksreq[0], socksreq[1]);
@@ -1660,8 +1704,8 @@ static CURLcode ConnectPlease(struct connectdata *conn,
#endif #endif
if (conn->data->set.proxytype == CURLPROXY_SOCKS5) { if (conn->data->set.proxytype == CURLPROXY_SOCKS5) {
return handleSock5Proxy(conn->data->state.proxyuser, return handleSock5Proxy(conn->proxyuser,
conn->data->state.proxypasswd, conn->proxypasswd,
conn, conn,
conn->firstsocket) ? conn->firstsocket) ?
CURLE_COULDNT_CONNECT : CURLE_OK; CURLE_COULDNT_CONNECT : CURLE_OK;
@@ -1775,7 +1819,6 @@ static CURLcode CreateConnection(struct SessionHandle *data,
struct connectdata **in_connect) struct connectdata **in_connect)
{ {
char *tmp; char *tmp;
char *buf;
CURLcode result=CURLE_OK; CURLcode result=CURLE_OK;
char resumerange[40]=""; char resumerange[40]="";
struct connectdata *conn; struct connectdata *conn;
@@ -1786,6 +1829,11 @@ static CURLcode CreateConnection(struct SessionHandle *data,
unsigned int prev_alarm=0; unsigned int prev_alarm=0;
#endif #endif
char endbracket; char endbracket;
char user[MAX_CURL_USER_LENGTH];
char passwd[MAX_CURL_PASSWORD_LENGTH];
bool passwdgiven=FALSE; /* set TRUE if an application-provided password has
been set */
#ifdef HAVE_SIGACTION #ifdef HAVE_SIGACTION
struct sigaction keep_sigact; /* store the old struct here */ struct sigaction keep_sigact; /* store the old struct here */
@@ -1921,16 +1969,20 @@ static CURLcode CreateConnection(struct SessionHandle *data,
/* Set default host and default path */ /* Set default host and default path */
strcpy(conn->gname, "curl.haxx.se"); strcpy(conn->gname, "curl.haxx.se");
strcpy(conn->path, "/"); strcpy(conn->path, "/");
/* We need to search for '/' OR '?' - whichever comes first after host
* name but before the path. We need to change that to handle things like
* http://example.com?param= (notice the missing '/'). Later we'll insert
* that missing slash at the beginning of the path.
*/
if (2 > sscanf(data->change.url, if (2 > sscanf(data->change.url,
"%64[^\n:]://%512[^\n/]%[^\n]", "%64[^\n:]://%512[^\n/?]%[^\n]",
conn->protostr, conn->gname, conn->path)) { conn->protostr, conn->gname, conn->path)) {
/* /*
* The URL was badly formatted, let's try the browser-style _without_ * The URL was badly formatted, let's try the browser-style _without_
* protocol specified like 'http://'. * protocol specified like 'http://'.
*/ */
if((1 > sscanf(data->change.url, "%512[^\n/]%[^\n]", if((1 > sscanf(data->change.url, "%512[^\n/?]%[^\n]",
conn->gname, conn->path)) ) { conn->gname, conn->path)) ) {
/* /*
* We couldn't even get this format. * We couldn't even get this format.
@@ -1972,7 +2024,17 @@ static CURLcode CreateConnection(struct SessionHandle *data,
} }
} }
buf = data->state.buffer; /* this is our buffer */ /* If the URL is malformatted (missing a '/' after hostname before path) we
* insert a slash here. The only letter except '/' we accept to start a path
* is '?'.
*/
if(conn->path[0] == '?') {
/* We need this function to deal with overlapping memory areas. We know
that the memory area 'path' points to is 'urllen' bytes big and that
is bigger than the path. Use +1 to move the zero byte too. */
memmove(&conn->path[1], conn->path, strlen(conn->path)+1);
conn->path[0] = '/';
}
/* /*
* So if the URL was A://B/C, * So if the URL was A://B/C,
@@ -1985,29 +2047,36 @@ static CURLcode CreateConnection(struct SessionHandle *data,
* Take care of proxy authentication stuff * Take care of proxy authentication stuff
*************************************************************/ *************************************************************/
if(conn->bits.proxy_user_passwd) { if(conn->bits.proxy_user_passwd) {
data->state.proxyuser[0] =0; char proxyuser[MAX_CURL_USER_LENGTH]="";
data->state.proxypasswd[0]=0; char proxypasswd[MAX_CURL_PASSWORD_LENGTH]="";
if(*data->set.proxyuserpwd != ':') { if(*data->set.proxyuserpwd != ':') {
/* the name is given, get user+password */ /* the name is given, get user+password */
sscanf(data->set.proxyuserpwd, "%127[^:]:%127[^\n]", sscanf(data->set.proxyuserpwd, "%127[^:]:%127[^\n]",
data->state.proxyuser, data->state.proxypasswd); proxyuser, proxypasswd);
} }
else else
/* no name given, get the password only */ /* no name given, get the password only */
sscanf(data->set.proxyuserpwd+1, "%127[^\n]", data->state.proxypasswd); sscanf(data->set.proxyuserpwd+1, "%127[^\n]", proxypasswd);
/* check for password, if no ask for one */ /* check for password, if no ask for one */
if( !data->state.proxypasswd[0] ) { if( !proxypasswd[0] ) {
if(data->set.fpasswd( data->set.passwd_client, if(data->set.fpasswd( data->set.passwd_client,
"proxy password:", "proxy password:",
data->state.proxypasswd, proxypasswd,
sizeof(data->state.proxypasswd))) { sizeof(proxypasswd))) {
failf(data, "Bad password from password callback"); failf(data, "Bad password from password callback");
return CURLE_BAD_PASSWORD_ENTERED; return CURLE_BAD_PASSWORD_ENTERED;
} }
} }
conn->proxyuser = strdup(proxyuser);
if(!conn->proxyuser)
return CURLE_OUT_OF_MEMORY;
conn->proxypasswd = strdup(proxypasswd);
if(!conn->proxypasswd)
return CURLE_OUT_OF_MEMORY;
} }
/************************************************************* /*************************************************************
@@ -2017,7 +2086,6 @@ static CURLcode CreateConnection(struct SessionHandle *data,
conn->ppath = conn->path; conn->ppath = conn->path;
conn->hostname = conn->name; conn->hostname = conn->name;
/************************************************************* /*************************************************************
* Detect what (if any) proxy to use * Detect what (if any) proxy to use
*************************************************************/ *************************************************************/
@@ -2118,6 +2186,45 @@ static CURLcode CreateConnection(struct SessionHandle *data,
if(proxy && *proxy) { if(proxy && *proxy) {
/* we have a proxy here to set */ /* we have a proxy here to set */
char *ptr;
char user[MAX_CURL_USER_LENGTH];
char passwd[MAX_CURL_PASSWORD_LENGTH];
/* skip the possible protocol piece */
ptr=strstr(proxy, "://");
if(ptr)
ptr += 3;
else
ptr = proxy;
/* check for an @-letter */
ptr = strchr(ptr, '@');
if(ptr && (2 == sscanf(proxy, "%" MAX_CURL_USER_LENGTH_TXT"[^:]:"
"%" MAX_CURL_PASSWORD_LENGTH_TXT "[^@]",
user, passwd))) {
/* found user and password, rip them out */
if(conn->proxyuser)
free(conn->proxyuser);
conn->proxyuser = strdup(user);
if(!conn->proxyuser)
return CURLE_OUT_OF_MEMORY;
if(conn->proxypasswd)
free(conn->proxypasswd);
conn->proxypasswd = strdup(passwd);
if(!conn->proxypasswd)
return CURLE_OUT_OF_MEMORY;
conn->bits.proxy_user_passwd = TRUE; /* enable it */
ptr = strdup(ptr+1);
free(proxy); /* free the former data */
proxy = ptr; /* now use this instead */
}
data->change.proxy = proxy; data->change.proxy = proxy;
data->change.proxy_alloc=TRUE; /* this needs to be freed later */ data->change.proxy_alloc=TRUE; /* this needs to be freed later */
conn->bits.httpproxy = TRUE; conn->bits.httpproxy = TRUE;
@@ -2495,8 +2602,8 @@ static CURLcode CreateConnection(struct SessionHandle *data,
* *
* Outputs: (almost :- all currently undefined) * Outputs: (almost :- all currently undefined)
* conn->bits.user_passwd - non-zero if non-default passwords exist * conn->bits.user_passwd - non-zero if non-default passwords exist
* conn->state.user - non-zero length if defined * conn->user - non-zero length if defined
* conn->state.passwd - ditto * conn->passwd - ditto
* conn->hostname - remove user name and password * conn->hostname - remove user name and password
*/ */
@@ -2507,8 +2614,8 @@ static CURLcode CreateConnection(struct SessionHandle *data,
* We need somewhere to put the embedded details, so do that first. * We need somewhere to put the embedded details, so do that first.
*/ */
data->state.user[0] =0; /* to make everything well-defined */ user[0] =0; /* to make everything well-defined */
data->state.passwd[0]=0; passwd[0]=0;
if (conn->protocol & (PROT_FTP|PROT_HTTP)) { if (conn->protocol & (PROT_FTP|PROT_HTTP)) {
/* This is a FTP or HTTP URL, we will now try to extract the possible /* This is a FTP or HTTP URL, we will now try to extract the possible
@@ -2535,31 +2642,31 @@ static CURLcode CreateConnection(struct SessionHandle *data,
if(*userpass != ':') { if(*userpass != ':') {
/* the name is given, get user+password */ /* the name is given, get user+password */
sscanf(userpass, "%127[^:@]:%127[^@]", sscanf(userpass, "%127[^:@]:%127[^@]",
data->state.user, data->state.passwd); user, passwd);
} }
else else
/* no name given, get the password only */ /* no name given, get the password only */
sscanf(userpass, ":%127[^@]", data->state.passwd); sscanf(userpass, ":%127[^@]", passwd);
if(data->state.user[0]) { if(user[0]) {
char *newname=curl_unescape(data->state.user, 0); char *newname=curl_unescape(user, 0);
if(strlen(newname) < sizeof(data->state.user)) { if(strlen(newname) < sizeof(user)) {
strcpy(data->state.user, newname); strcpy(user, newname);
} }
/* if the new name is longer than accepted, then just use /* if the new name is longer than accepted, then just use
the unconverted name, it'll be wrong but what the heck */ the unconverted name, it'll be wrong but what the heck */
free(newname); free(newname);
} }
if (data->state.passwd[0]) { if (passwd[0]) {
/* we have a password found in the URL, decode it! */ /* we have a password found in the URL, decode it! */
char *newpasswd=curl_unescape(data->state.passwd, 0); char *newpasswd=curl_unescape(passwd, 0);
if(strlen(newpasswd) < sizeof(data->state.passwd)) { if(strlen(newpasswd) < sizeof(passwd)) {
strcpy(data->state.passwd, newpasswd); strcpy(passwd, newpasswd);
} }
free(newpasswd); free(newpasswd);
/* we have set the password */ /* we have set the password */
data->state.passwdgiven = TRUE; passwdgiven = TRUE;
} }
} }
} }
@@ -2578,35 +2685,35 @@ static CURLcode CreateConnection(struct SessionHandle *data,
if(*data->set.userpwd != ':') { if(*data->set.userpwd != ':') {
/* the name is given, get user+password */ /* the name is given, get user+password */
sscanf(data->set.userpwd, "%127[^:]:%127[^\n]", sscanf(data->set.userpwd, "%127[^:]:%127[^\n]",
data->state.user, data->state.passwd); user, passwd);
if(strchr(data->set.userpwd, ':')) if(strchr(data->set.userpwd, ':'))
/* a colon means the password was given, even if blank */ /* a colon means the password was given, even if blank */
data->state.passwdgiven = TRUE; passwdgiven = TRUE;
} }
else else
/* no name given, starts with a colon, get the password only */ /* no name given, starts with a colon, get the password only */
sscanf(data->set.userpwd+1, "%127[^\n]", data->state.passwd); sscanf(data->set.userpwd+1, "%127[^\n]", passwd);
} }
if ((data->set.use_netrc != CURL_NETRC_IGNORED) && if ((data->set.use_netrc != CURL_NETRC_IGNORED) &&
!data->state.passwdgiven) { /* need passwd */ !passwdgiven) { /* need passwd */
if(Curl_parsenetrc(conn->hostname, if(Curl_parsenetrc(conn->hostname,
data->state.user, user,
data->state.passwd)) { passwd)) {
infof(data, "Couldn't find host %s in the .netrc file, using defaults", infof(data, "Couldn't find host %s in the .netrc file, using defaults",
conn->hostname); conn->hostname);
} }
else { else {
conn->bits.user_passwd = 1; /* enable user+password */ conn->bits.user_passwd = 1; /* enable user+password */
data->state.passwdgiven = TRUE; passwdgiven = TRUE;
} }
} }
/* if we have a user but no password, ask for one */ /* if we have a user but no password, ask for one */
if(conn->bits.user_passwd && !data->state.passwdgiven ) { if(conn->bits.user_passwd && !passwdgiven ) {
if(data->set.fpasswd(data->set.passwd_client, if(data->set.fpasswd(data->set.passwd_client,
"password:", data->state.passwd, "password:", passwd,
sizeof(data->state.passwd))) sizeof(passwd)))
return CURLE_BAD_PASSWORD_ENTERED; return CURLE_BAD_PASSWORD_ENTERED;
} }
@@ -2615,14 +2722,18 @@ static CURLcode CreateConnection(struct SessionHandle *data,
/* If our protocol needs a password and we have none, use the defaults */ /* If our protocol needs a password and we have none, use the defaults */
if ( (conn->protocol & (PROT_FTP|PROT_HTTP)) && if ( (conn->protocol & (PROT_FTP|PROT_HTTP)) &&
!conn->bits.user_passwd && !conn->bits.user_passwd &&
!data->state.passwdgiven) { !passwdgiven) {
strcpy(data->state.user, CURL_DEFAULT_USER); strcpy(user, CURL_DEFAULT_USER);
strcpy(data->state.passwd, CURL_DEFAULT_PASSWORD); strcpy(passwd, CURL_DEFAULT_PASSWORD);
/* This is the default password, so DON'T set conn->bits.user_passwd */ /* This is the default password, so DON'T set conn->bits.user_passwd */
} }
/* store user + password */
conn->user = strdup(user);
conn->passwd = strdup(passwd);
/************************************************************* /*************************************************************
* Check the current list of connections to see if we can * Check the current list of connections to see if we can
* re-use an already existing one or if we have to create a * re-use an already existing one or if we have to create a
@@ -2682,6 +2793,9 @@ static CURLcode CreateConnection(struct SessionHandle *data,
otherwise */ otherwise */
conn->maxdownload = -1; /* might have been used previously! */ conn->maxdownload = -1; /* might have been used previously! */
free(old_conn->user);
free(old_conn->passwd);
free(old_conn); /* we don't need this anymore */ free(old_conn); /* we don't need this anymore */
/* /*
@@ -2786,6 +2900,8 @@ static CURLcode CreateConnection(struct SessionHandle *data,
if(conn->bits.reuse) { if(conn->bits.reuse) {
/* re-used connection, no resolving is necessary */ /* re-used connection, no resolving is necessary */
hostaddr = NULL; hostaddr = NULL;
conn->connect_addr = NULL; /* we don't connect now so we don't have any
fresh connect_addr struct to point to */
} }
else if(!data->change.proxy || !*data->change.proxy) { else if(!data->change.proxy || !*data->change.proxy) {
/* If not connecting via a proxy, extract the port from the URL, if it is /* If not connecting via a proxy, extract the port from the URL, if it is
@@ -2862,7 +2978,7 @@ static CURLcode CreateConnection(struct SessionHandle *data,
if(conn->bits.proxy_user_passwd) { if(conn->bits.proxy_user_passwd) {
char *authorization; char *authorization;
snprintf(data->state.buffer, BUFSIZE, "%s:%s", snprintf(data->state.buffer, BUFSIZE, "%s:%s",
data->state.proxyuser, data->state.proxypasswd); conn->proxyuser, conn->proxypasswd);
if(Curl_base64_encode(data->state.buffer, strlen(data->state.buffer), if(Curl_base64_encode(data->state.buffer, strlen(data->state.buffer),
&authorization) >= 0) { &authorization) >= 0) {
if(conn->allocptr.proxyuserpwd) if(conn->allocptr.proxyuserpwd)
@@ -2982,7 +3098,7 @@ CURLcode Curl_done(struct connectdata *conn)
if(conn->connect_addr) if(conn->connect_addr)
Curl_resolv_unlock(conn->data, conn->connect_addr); /* done with this */ Curl_resolv_unlock(conn->data, conn->connect_addr); /* done with this */
#if defined(MALLOCDEBUG) && defined(AGGRESIVE_TEST) #if defined(CURLDEBUG) && defined(AGGRESIVE_TEST)
/* scan for DNS cache entries still marked as in use */ /* scan for DNS cache entries still marked as in use */
Curl_hash_apply(data->hostcache, Curl_hash_apply(data->hostcache,
NULL, Curl_scan_cache_used); NULL, Curl_scan_cache_used);

View File

@@ -42,4 +42,5 @@ bool Curl_ssl_config_matches(struct ssl_config_data* data,
bool Curl_clone_ssl_config(struct ssl_config_data* source, bool Curl_clone_ssl_config(struct ssl_config_data* source,
struct ssl_config_data* dest); struct ssl_config_data* dest);
void Curl_free_ssl_config(struct ssl_config_data* sslc); void Curl_free_ssl_config(struct ssl_config_data* sslc);
void Curl_safefree(void *ptr);
#endif #endif

View File

@@ -83,7 +83,11 @@
#include "hash.h" #include "hash.h"
#ifdef HAVE_ZLIB_H #ifdef HAVE_ZLIB_H
#include <zlib.h> /* for content-encoding 08/28/02 jhrg */ #include <zlib.h> /* for content-encoding */
#endif
#ifdef GSSAPI
#include <gssapi.h>
#endif #endif
/* Download buffer size, keep it fairly big for speed reasons */ /* Download buffer size, keep it fairly big for speed reasons */
@@ -93,6 +97,9 @@
of need. */ of need. */
#define HEADERSIZE 256 #define HEADERSIZE 256
/* Maximum number of dirs supported by libcurl in a FTP dir hierarchy */
#define CURL_MAX_FTP_DIRDEPTH 100
/* Just a convenience macro to get the larger value out of two given */ /* Just a convenience macro to get the larger value out of two given */
#ifndef MAX #ifndef MAX
#define MAX(x,y) ((x)>(y)?(x):(y)) #define MAX(x,y) ((x)>(y)?(x):(y))
@@ -138,6 +145,8 @@ struct ssl_config_data {
char *egdsocket; /* path to file containing the EGD daemon socket */ char *egdsocket; /* path to file containing the EGD daemon socket */
char *cipher_list; /* list of ciphers to use */ char *cipher_list; /* list of ciphers to use */
long numsessions; /* SSL session id cache size */ long numsessions; /* SSL session id cache size */
curl_ssl_ctx_callback fsslctx; /* function to initialize ssl ctx */
void *fsslctxp; /*parameter for call back */
}; };
/* information stored about one single SSL session */ /* information stored about one single SSL session */
@@ -149,6 +158,36 @@ struct curl_ssl_session {
struct ssl_config_data ssl_config; /* setup for this session */ struct ssl_config_data ssl_config; /* setup for this session */
}; };
/* Struct used for Digest challenge-response authentication */
struct digestdata {
char *nonce;
char *cnonce;
char *realm;
int algo;
};
typedef enum {
NTLMSTATE_NONE,
NTLMSTATE_TYPE1,
NTLMSTATE_TYPE2,
NTLMSTATE_TYPE3,
NTLMSTATE_LAST
} curlntlm;
/* Struct used for Digest challenge-response authentication */
struct ntlmdata {
curlntlm state;
unsigned char nonce[8];
};
#ifdef GSSAPI
struct negotiatedata {
OM_uint32 status;
gss_ctx_id_t context;
gss_name_t server_name;
gss_buffer_desc output_token;
};
#endif
/**************************************************************************** /****************************************************************************
* HTTP unique setup * HTTP unique setup
@@ -193,7 +232,7 @@ struct FTP {
char *user; /* user name string */ char *user; /* user name string */
char *passwd; /* password string */ char *passwd; /* password string */
char *urlpath; /* the originally given path part of the URL */ char *urlpath; /* the originally given path part of the URL */
char *dir; /* decoded directory */ char *dirs[CURL_MAX_FTP_DIRDEPTH]; /* path components */
char *file; /* decoded file */ char *file; /* decoded file */
char *entrypath; /* the PWD reply when we logged on */ char *entrypath; /* the PWD reply when we logged on */
@@ -296,14 +335,13 @@ struct Curl_transfer_keeper {
#ifdef HAVE_LIBZ #ifdef HAVE_LIBZ
bool zlib_init; /* True if zlib already initialized; bool zlib_init; /* True if zlib already initialized;
undefined if Content-Encdoing header. */ undefined if Content-Encoding header. */
z_stream z; /* State structure for zlib. */ z_stream z; /* State structure for zlib. */
#endif #endif
/* for the low speed checks: */ /* for the low speed checks: */
time_t timeofdoc; time_t timeofdoc;
long bodywrites; long bodywrites;
int writetype;
char *buf; char *buf;
char *uploadbuf; char *uploadbuf;
@@ -322,8 +360,9 @@ struct Curl_transfer_keeper {
bool upload_done; /* set to TRUE when doing chunked transfer-encoding upload bool upload_done; /* set to TRUE when doing chunked transfer-encoding upload
and we're uploading the last chunk */ and we're uploading the last chunk */
};
bool ignorebody; /* we read a response-body but we ignore it! */
};
/* /*
* The connectdata struct contains all fields and variables that should be * The connectdata struct contains all fields and variables that should be
@@ -374,6 +413,12 @@ struct connectdata {
char *proxyhost; /* name of the http proxy host */ char *proxyhost; /* name of the http proxy host */
char *user; /* user name string, allocated */
char *passwd; /* password string, allocated */
char *proxyuser; /* proxy user name string, allocated */
char *proxypasswd; /* proxy password string, allocated */
struct timeval now; /* "current" time */ struct timeval now; /* "current" time */
struct timeval created; /* creation time */ struct timeval created; /* creation time */
int firstsocket; /* the main socket to use */ int firstsocket; /* the main socket to use */
@@ -429,12 +474,13 @@ struct connectdata {
struct dynamically_allocated_data { struct dynamically_allocated_data {
char *proxyuserpwd; /* free later if not NULL! */ char *proxyuserpwd; /* free later if not NULL! */
char *uagent; /* free later if not NULL! */ char *uagent; /* free later if not NULL! */
char *accept_encoding; /* free later if not NULL! 08/28/02 jhrg */ char *accept_encoding; /* free later if not NULL! */
char *userpwd; /* free later if not NULL! */ char *userpwd; /* free later if not NULL! */
char *rangeline; /* free later if not NULL! */ char *rangeline; /* free later if not NULL! */
char *ref; /* free later if not NULL! */ char *ref; /* free later if not NULL! */
char *cookie; /* free later if not NULL! */ char *cookie; /* free later if not NULL! */
char *host; /* free later if not NULL */ char *host; /* free later if not NULL */
char *cookiehost; /* free later if not NULL */
} allocptr; } allocptr;
char *newurl; /* This can only be set if a Location: was in the char *newurl; /* This can only be set if a Location: was in the
@@ -487,9 +533,14 @@ struct connectdata {
curl_read_callback fread; /* function that reads the input */ curl_read_callback fread; /* function that reads the input */
void *fread_in; /* pointer to pass to the fread() above */ void *fread_in; /* pointer to pass to the fread() above */
struct ntlmdata ntlm; /* NTLM differs from other authentication schemes
because it authenticates connections, not
single requests! */
struct ntlmdata proxyntlm; /* NTLM data for proxy */
}; };
/* The end of connectdata. 08/27/02 jhrg */ /* The end of connectdata. */
/* /*
* Struct to keep statistical and informational data. * Struct to keep statistical and informational data.
@@ -497,8 +548,8 @@ struct connectdata {
struct PureInfo { struct PureInfo {
int httpcode; int httpcode;
int httpversion; int httpversion;
long filetime; /* If requested, this is might get set. Set to -1 if time_t filetime; /* If requested, this is might get set. Set to -1 if
the time was unretrievable */ the time was unretrievable */
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) */
@@ -560,6 +611,8 @@ typedef enum {
* Session-data MUST be put in the connectdata struct and here. */ * Session-data MUST be put in the connectdata struct and here. */
#define MAX_CURL_USER_LENGTH 256 #define MAX_CURL_USER_LENGTH 256
#define MAX_CURL_PASSWORD_LENGTH 256 #define MAX_CURL_PASSWORD_LENGTH 256
#define MAX_CURL_USER_LENGTH_TXT "255"
#define MAX_CURL_PASSWORD_LENGTH_TXT "255"
struct UrlState { struct UrlState {
enum { enum {
@@ -569,14 +622,6 @@ struct UrlState {
} used_interface; } used_interface;
/* buffers to store authentication data in, as parsed from input options */ /* buffers to store authentication data in, as parsed from input options */
char user[MAX_CURL_USER_LENGTH];
char passwd[MAX_CURL_PASSWORD_LENGTH];
char proxyuser[MAX_CURL_USER_LENGTH];
char proxypasswd[MAX_CURL_PASSWORD_LENGTH];
bool passwdgiven; /* set TRUE if an application-provided password has been
set */
struct timeval keeps_speed; /* for the progress meter really */ struct timeval keeps_speed; /* for the progress meter really */
/* 'connects' will be an allocated array with pointers. If the pointer is /* 'connects' will be an allocated array with pointers. If the pointer is
@@ -613,6 +658,15 @@ struct UrlState {
#endif #endif
bool allow_port; /* Is set.use_port allowed to take effect or not. This bool allow_port; /* Is set.use_port allowed to take effect or not. This
is always set TRUE when curl_easy_perform() is called. */ is always set TRUE when curl_easy_perform() is called. */
struct digestdata digest;
#ifdef GSSAPI
struct negotiatedata negotiate;
#endif
long authwant; /* inherited from what the user set with CURLOPT_HTTPAUTH */
long authavail; /* what the server reports */
}; };
@@ -626,6 +680,10 @@ struct UrlState {
struct DynamicStatic { struct DynamicStatic {
char *url; /* work URL, copied from UserDefined */ char *url; /* work URL, copied from UserDefined */
bool url_alloc; /* URL string is malloc()'ed */ bool url_alloc; /* URL string is malloc()'ed */
bool url_changed; /* set on CURL_OPT_URL, used to detect if the URL was
changed after the connect phase, as we allow callback
to change it and if so, we reconnect to use the new
URL instead */
char *proxy; /* work proxy, copied from UserDefined */ char *proxy; /* work proxy, copied from UserDefined */
bool proxy_alloc; /* http proxy string is malloc()'ed */ bool proxy_alloc; /* http proxy string is malloc()'ed */
char *referer; /* referer string */ char *referer; /* referer string */
@@ -657,6 +715,7 @@ struct UserDefined {
char *set_proxy; /* proxy to use */ char *set_proxy; /* proxy to use */
long use_port; /* which port to use (when not using default) */ long use_port; /* which port to use (when not using default) */
char *userpwd; /* <user:password>, if used */ char *userpwd; /* <user:password>, if used */
long httpauth; /* what kind of HTTP authentication to use (bitmask) */
char *set_range; /* range, if used. See README for detailed specification char *set_range; /* range, if used. See README for detailed specification
on this syntax. */ on this syntax. */
long followlocation; /* as in HTTP Location: */ long followlocation; /* as in HTTP Location: */
@@ -755,6 +814,7 @@ struct UserDefined {
bool reuse_fresh; /* do not re-use an existing connection */ bool reuse_fresh; /* do not re-use an existing connection */
bool expect100header; /* TRUE if we added Expect: 100-continue */ bool expect100header; /* TRUE if we added Expect: 100-continue */
bool ftp_use_epsv; /* if EPSV is to be attempted or not */ bool ftp_use_epsv; /* if EPSV is to be attempted or not */
bool ftp_use_eprt; /* if EPRT is to be attempted or not */
bool no_signal; /* do not use any signal/alarm handler */ bool no_signal; /* do not use any signal/alarm handler */
bool global_dns_cache; bool global_dns_cache;

View File

@@ -114,6 +114,10 @@ char *curl_version(void)
sprintf(ptr, " zlib/%s", zlibVersion()); sprintf(ptr, " zlib/%s", zlibVersion());
ptr += strlen(ptr); ptr += strlen(ptr);
#endif #endif
#ifdef GSSAPI
sprintf(ptr, " GSS");
ptr += strlen(ptr);
#endif
return version; return version;
} }
@@ -168,9 +172,16 @@ static curl_version_info_data version_info = {
#endif #endif
#ifdef USE_SSLEAY #ifdef USE_SSLEAY
| CURL_VERSION_SSL | CURL_VERSION_SSL
| CURL_VERSION_NTLM /* since this requires OpenSSL */
#endif #endif
#ifdef HAVE_LIBZ #ifdef HAVE_LIBZ
| CURL_VERSION_LIBZ | CURL_VERSION_LIBZ
#endif
#ifdef GSSAPI
| CURL_VERSION_GSSNEGOTIATE
#endif
#ifdef CURLDEBUG
| CURL_VERSION_DEBUG
#endif #endif
, ,
NULL, /* ssl_version */ NULL, /* ssl_version */

4998
ltmain.sh

File diff suppressed because it is too large Load Diff

View File

@@ -134,3 +134,8 @@ echo ""
ls -l $targz $bzip2 $zip ls -l $targz $bzip2 $zip
md5sum $targz $bzip2 $zip md5sum $targz $bzip2 $zip
echo "Run these commands:"
echo "gpg -b -a $targz"
echo "gpg -b -a $bzip2"
echo "gpg -b -a $zip"

2
packages/DOS/.cvsignore Normal file
View File

@@ -0,0 +1,2 @@
Makefile
Makefile.in

1
packages/DOS/Makefile.am Normal file
View File

@@ -0,0 +1 @@
EXTRA_DIST = README common.dj

4
packages/DOS/README Normal file
View File

@@ -0,0 +1,4 @@
Gisle Vanem made curl build fine on DOS (and MingW) with djgpp, OpenSSL and his
Watt-32 stack.
'make djgpp' in the root curl dir should build it fine.

56
packages/DOS/common.dj Normal file
View File

@@ -0,0 +1,56 @@
#
# Common defines for curl (djgpp/Watt-32)
#
# Assumes you've unpacked cURL with short-file names
# I.e use "set LFN=n" before untaring on Win9x/XP.
# Requires sed, yacc, rm and the usual stuff.
#
.SUFFIXES: .exe .y
MAKEFILE = Makefile.dj
#
# OpenSSL is available from www.openssl.org and builds okay
# with djgpp/Watt-32. Set to 0 if you don't need https URLs
# (reduces curl.exe with approx 700 kB)
#
USE_SSL = 1
default: all
#
# Root directory for Waterloo tcp/ip. WATT_ROOT should be set
# during Watt-32 install.
#
WATT32_ROOT = $(subst \,/,$(WATT_ROOT))
OPENSSL_ROOT = /net/openssl.098
ZLIB_ROOT = $(DJDIR)/contrib/zlib
CC = gcc
YACC = bison -y
CFLAGS = -g -O2 -I. -I../include -Wall -DHAVE_CONFIG_H
ifeq ($(USE_SSL),1)
CFLAGS += -DUSE_SSLEAY -DHAVE_OPENSSL_ENGINE_H
endif
#
# Generated dependencies; Due to some hacks in gcc 2.95+ and djgpp 2.03
# we must prevent "$(DJDIR)/bin/../include/sys/version.h" from beeing
# included in dependency output (or else this makefile cannot be used on
# another machine). We therefore use a special 'specs' file during
# pre-processing.
#
MM_SPECS = $(TMPDIR)/specs
depend: $(DEPEND_PREREQ)
@echo Generating dependencies..
@copy $(MAKEFILE) Makefile.bak
@echo "*cpp: %(cpp_cpu) %{posix:-D_POSIX_SOURCE} -remap" > $(MM_SPECS)
sed -e "/^# DO NOT DELETE THIS LINE/,$$d" < Makefile.bak > $(MAKEFILE)
echo "# DO NOT DELETE THIS LINE" >> $(MAKEFILE)
$(CC) -MM -specs=$(MM_SPECS) $(CFLAGS) $(SOURCES) >> $(MAKEFILE)
rm -f $(MM_SPECS)

View File

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

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