Compare commits

...

148 Commits

Author SHA1 Message Date
Daniel Stenberg
67273eed9b 7.9.8 commit 2002-06-13 14:37:15 +00:00
Daniel Stenberg
3c63e1d8d9 Added 'dont_check' to be set during an FTP operation if the final status
message is supposed to be ignored.
2002-06-13 09:21:08 +00:00
Daniel Stenberg
cae555c977 when no FTP transfer was done, don't attempt to read the download transfer
thing. The 'resumed' flag is also causing confusions. I'll deal with that
tomorrow.
2002-06-12 22:05:28 +00:00
Daniel Stenberg
407583e8e2 Moved the secondarysocket cleanup. The 'conn' struct may have been cleared
already at that other place.
2002-06-12 22:04:25 +00:00
Daniel Stenberg
131645dc31 Chris Combes added CURLFORM_BUFFER, CURLFORM_BUFFERPTR, CURLFORM_BUFFERLENGTH 2002-06-12 21:40:59 +00:00
Daniel Stenberg
dafd644fe7 fixing builds, patching bugs, adding curl_formadd() options 2002-06-12 21:40:30 +00:00
Daniel Stenberg
73cc1742af HAVE_SIGSETJMP 2002-06-12 17:56:22 +00:00
Daniel Stenberg
87afd7686f added a connect failure error message that might get empty otherwise 2002-06-12 09:48:26 +00:00
Daniel Stenberg
8ce10b5dfa Jrn fixes for 7.9.8 build 2002-06-12 09:18:37 +00:00
Daniel Stenberg
943e31b35c CURLOPT_MAXFILESIZE 2002-06-12 08:16:59 +00:00
Daniel Stenberg
20f85b94df kris@freebsd.org fixed a bad format string 2002-06-12 07:45:11 +00:00
Daniel Stenberg
17b784381e kris@freebsd.org fixed a few bad format strings 2002-06-12 07:44:22 +00:00
Daniel Stenberg
e3031fddb9 Add QNX 2002-06-12 07:26:13 +00:00
Daniel Stenberg
38c994a7ae put #ifdefs around the sigjmp_buf declaration too, as it should be 2002-06-11 15:47:01 +00:00
Daniel Stenberg
85e2e96fb6 corrected the signal handler 2002-06-11 15:44:27 +00:00
Daniel Stenberg
be35b3ad03 7.9.8-pre3 commit 2002-06-11 15:28:50 +00:00
Daniel Stenberg
dbbd871ea1 the disable protocol stuff is now added 2002-06-11 15:24:47 +00:00
Daniel Stenberg
813911db59 more nonewline support 2002-06-11 15:11:41 +00:00
Daniel Stenberg
3c49b405de Now uses sigsetjmp() and siglongjmp() to bail out from slow name lookups in
case a timeout is set. This seems to work. God knows if it is good enough
or what kind of side-effects we introduce here and now.

I'll close my eyes and cross my fingers. Hard.
2002-06-11 15:10:18 +00:00
Daniel Stenberg
4cfffd6c4a cut up the string in more pieces for <512 bytes strings 2002-06-11 15:09:02 +00:00
Daniel Stenberg
e9f1c12f0f removed accidentally added debug-code! 2002-06-11 14:10:32 +00:00
Daniel Stenberg
4fe252847c ftp range downloads make us ignore the final status message as the server
will most likely treat the download as failed as we might abort it
pre-maturely
2002-06-11 12:35:03 +00:00
Daniel Stenberg
109cbbe9c5 added test135 ftp byte-range download 2002-06-11 12:25:46 +00:00
Daniel Stenberg
fd3881eaa6 added --disable-[protocol] support 2002-06-11 11:13:29 +00:00
Daniel Stenberg
08ef208fb7 added disable-[protocol] support, largely provided by Miklos Nemeth 2002-06-11 11:13:01 +00:00
Daniel Stenberg
8c45e2a641 Added disable-defines 2002-06-11 11:12:27 +00:00
Daniel Stenberg
25dc520163 added multi.obj 2002-06-11 11:11:06 +00:00
Daniel Stenberg
fc37ef9e4b make sure data->set.postfields is non-NULL before doing strlen() on the
pointer. Bugs item #566835.
2002-06-11 07:20:21 +00:00
Daniel Stenberg
11ba367fc9 getaddrinfo() failures now show port number too in informational output 2002-06-10 13:26:02 +00:00
Daniel Stenberg
78473f71eb added a missing failf() for certain connect failures 2002-06-10 13:25:03 +00:00
Daniel Stenberg
8b77f40f99 This fix MIGHT make us build nicely with OpenSSL 0.9.7. This fix is based
on a patch from Jacob Meuser, input from Gtz Babin-Ebell and my own
browsing of the latest include files.
2002-06-10 12:38:10 +00:00
Daniel Stenberg
d866716565 Gautam Mani found a socket descriptor leak that happened when FTP transfers
failed and you reinvoked curl_easy_perform().
2002-06-10 12:34:04 +00:00
Daniel Stenberg
307d0effe2 Added HAVE_SYS_TYPES_H 2002-06-07 06:17:05 +00:00
Daniel Stenberg
b47b053e54 Gustaf Hui fixed curl_multi_remove_handle() to prevent a potential crash 2002-06-05 21:29:20 +00:00
Daniel Stenberg
b79f01caf3 set HAVE_RAND_STATUS too 2002-06-05 14:14:54 +00:00
Daniel Stenberg
0db227f55e hostcache_fixoffset() is now corrected to work on 64bit architectures
Bug report #564585.
2002-06-05 13:41:33 +00:00
Daniel Stenberg
ac48b38842 more stuff since pre1 2002-06-04 11:53:31 +00:00
Daniel Stenberg
0cbb9365c6 indent like the other ones 2002-06-03 13:37:09 +00:00
Daniel Stenberg
798b8c522b Christophe Espern wrote another binding! 2002-06-03 13:20:23 +00:00
Daniel Stenberg
15bc7e19f9 updated header 2002-06-03 13:04:35 +00:00
Daniel Stenberg
0be3f1a063 T. Bharath's updates since curl now uses the winmm lib for higher resolution
timer
2002-06-03 12:48:31 +00:00
Daniel Stenberg
c0257c6721 T. Bharath made the request size add up as it is documented to do. 2002-06-03 12:47:08 +00:00
Daniel Stenberg
9aec0fc7de T. Bharath fixed higher resolution time for windows builds 2002-06-03 12:46:32 +00:00
Daniel Stenberg
bce5e0d82c T. Bharath fixed the TIMER_REDIRECT. 2002-06-03 12:46:04 +00:00
Daniel Stenberg
62032ee248 Getting an empty FTP file no longer makes us return error 19. An empty file
is fine to get.
2002-05-28 22:33:30 +00:00
Daniel Stenberg
775645f29b Gustaf Hui provided new code that changes how curl_multi_info_read()
messages are stored, so that they don't have to be kept around for the multi
 handle's entire life time. He also made it return failure codes properly
 which it didn't do before.

 I made the messages only get stored per easy-handle so that they can be
 independently killed easier without ruining the "master list". It makes
 the info_read() function slightly less beautiful as it has to scan for
 messages to return, but it makes removing individual handles a lot easier
 and less error prone.
2002-05-28 14:45:50 +00:00
Daniel Stenberg
99c0456872 Adjusted to make curl_multi_perform() work properly even when
curl_multi_fdset() is not used.
2002-05-28 14:18:36 +00:00
Daniel Stenberg
0236bee5de I trimmed the --help output slightly to better fit within 80 cols 2002-05-28 09:31:48 +00:00
Daniel Stenberg
59c11b82d5 Cris Bailiff's CAPATH support added 2002-05-28 09:21:29 +00:00
Daniel Stenberg
98871d1e9e new url, spell checked 2002-05-22 22:14:03 +00:00
Daniel Stenberg
b40dc5d742 since 7.9.7 2002-05-22 11:08:19 +00:00
Daniel Stenberg
17b0723713 James Cone's little work-around for the strict error 2002-05-21 22:39:09 +00:00
Daniel Stenberg
ec585e8907 When re-using a connection, make sure that we use the current host name as
we might actually re-use a connection to a different host, when using proxies!

This was what bug report #558888 was all about.
2002-05-21 22:24:56 +00:00
Daniel Stenberg
0aeb25ff3b James Cone added the new CURL_NETRC_OPTION enum 2002-05-21 22:22:28 +00:00
Daniel Stenberg
a928f2c4aa test suite mods for the netrc testing stuff 2002-05-21 22:20:52 +00:00
Daniel Stenberg
51fcee6f81 James Cone added CURLOPT_NETRC / --netrc / --netrc-optional descriptions 2002-05-21 22:20:16 +00:00
Daniel Stenberg
654be65590 Use the new CURLOPT_NETRC option and adds --netrc-optional, by James Cone 2002-05-21 22:18:34 +00:00
Daniel Stenberg
105ec79b2b James Cone's efforts to add another netrc parsing "mode" 2002-05-21 22:17:19 +00:00
Daniel Stenberg
c759d8427a five new test cases for the netrc parsing 2002-05-21 22:14:08 +00:00
Daniel Stenberg
c7b03d6479 maprintf() and vmaprintf() now work better when printfing "%s" with an
empty string
2002-05-21 17:59:57 +00:00
Daniel Stenberg
2080738883 corrected see also 2002-05-21 14:00:55 +00:00
Daniel Stenberg
48bc73c271 3.14 added, javascript support 2002-05-21 13:53:32 +00:00
Daniel Stenberg
3d0969d1d1 Added source header and made it clear that this code was originally donated
to us by Juergen Wilke.
2002-05-21 08:22:00 +00:00
Daniel Stenberg
323f195036 ASN1 files don't work for the *chain_file(), make them use the previous
version
2002-05-21 08:15:42 +00:00
Daniel Stenberg
c3c392fc98 return type CURLFORMcode instead of plain int 2002-05-21 07:47:09 +00:00
Daniel Stenberg
5d2944c211 curl_formadd() now returns 'CURLFORMcode' instead of int, to better enable
checking for particular errors. curl/curl.h defines the errros
2002-05-21 07:44:27 +00:00
Daniel Stenberg
fe3ba1dd11 Roland Zimmermann's hint, we use SSL_CTX_use_certificate_chain_file() instead
of the previous one that used SSL_CTX_use_certificate_file()
2002-05-20 14:25:35 +00:00
Daniel Stenberg
0c00eb93a0 removed compiler warnings 2002-05-17 08:15:33 +00:00
Daniel Stenberg
baa77ec13b FreeBSD needs sys/types.h before we include sys/select.h that was included
mainly for AIX in the first place...! As reported in bug report #556869
2002-05-17 07:57:13 +00:00
Daniel Stenberg
9263652c6d Fixes bug report #556930 - we need to make sure that the data is all right
after we've realloc() the packed hostent struct.
2002-05-17 07:49:28 +00:00
Daniel Stenberg
bc74375543 Added item 4.10 after talks with Russ Freeman 2002-05-15 21:40:29 +00:00
Daniel Stenberg
edb1756050 7.9.7 commit 2002-05-13 09:40:16 +00:00
Daniel Stenberg
5215f6f654 we don't need win32sockets.c anymore, we support this internally 2002-05-13 07:29:22 +00:00
Daniel Stenberg
1913b4eeed fopen.c added, a fopen() style emulation for URL reading 2002-05-13 07:28:10 +00:00
Daniel Stenberg
b44a4da5df Friday's fixes 2002-05-12 16:10:12 +00:00
Daniel Stenberg
919878fbb2 AIX 5.1 2002-05-10 16:01:24 +00:00
Daniel Stenberg
06bdf83419 Kein Roth made --trace-ascii look even better, and make OD 0A occurances
get output as plain newlines.
2002-05-10 15:59:42 +00:00
Daniel Stenberg
2ff2810a92 AIX wants sys/select.h for the fd_set stuff in curl/multi.h, and even though
it is a bit ugly work-around to add this here, it is still a working work-
around! ;-)
2002-05-10 14:37:39 +00:00
Daniel Stenberg
20d9c1b30d Patrick Smith's contributed docs improvements for when NLST is used by
curl...
2002-05-07 23:36:53 +00:00
Daniel Stenberg
bbe10cb0cb 7.9.7-pre2 2002-05-07 21:52:38 +00:00
Daniel Stenberg
daba8f3a70 Added --trace-ascii support 2002-05-07 13:13:17 +00:00
Daniel Stenberg
1458c3668d --trace-ascii and --junk-session-cookies were added 2002-05-07 13:12:12 +00:00
Daniel Stenberg
980a47b42b support for ingoring session cookies added 2002-05-07 09:58:13 +00:00
Daniel Stenberg
f7ca561b06 the code for case CURLOPT_DEBUGDATA code broke the CURLOPT_STDERR one! 2002-05-06 18:30:17 +00:00
Daniel Stenberg
cacd756efd recent fiddling 2002-05-06 13:44:00 +00:00
Daniel Stenberg
8539e76cb9 CURLOPT_FILE and CURLOPT_INFILE have better aliases now:
CURLOPT_WRITEDATA and CURLOPT_READDATA
2002-05-06 13:43:35 +00:00
Daniel Stenberg
3bbf694d5a Added multi-post.c, based on the source file posted by Gustaf Hui 2002-05-06 13:38:28 +00:00
Daniel Stenberg
44debdde62 Better support for being used with the multi interface without the *fd_set()
and proper select()ing have been made.
2002-05-05 12:11:03 +00:00
Daniel Stenberg
c6cf2b8e93 --trace is a 7.9.7 function 2002-05-05 09:09:17 +00:00
Daniel Stenberg
69c5452b25 added -Z/--max-redirs and --trace
changed order of a few others to keep the a-z order
2002-05-05 09:08:26 +00:00
Daniel Stenberg
d321056e8d made VERBOSE output more like it used to be, HEADER_IN is thus also ignored
by the internal debugfunction callback
2002-05-04 15:36:07 +00:00
Daniel Stenberg
d9a1a59f22 CURL_MAX_WRITE_SIZE is a new exported define that informs about the biggest
sized buffer that may be passed to a write callback
2002-05-03 14:50:29 +00:00
Daniel Stenberg
0b898b5a8a fixed return code 2002-05-03 12:40:37 +00:00
Daniel Stenberg
a9e0885be0 another week of changes 2002-05-03 12:21:07 +00:00
Daniel Stenberg
57ff28c9b7 - Added "--trace [file]" to the command line tool. It makes a very detailed
trace dump get stored, with a full protocol dump that includes all received
  and transmitted data. This could be a very effective tool for debugging what
  goes wrong. This dump includes every byte the way it is sent to/received
  from the server. The dump is the plain-text version, so SSL transfers will
  still be readable.
2002-05-03 12:14:09 +00:00
Daniel Stenberg
86cc34c0de made the DEBUGFUNCTION get called properly on a few more places, especially
for DATA_IN and DATA_OUT.
2002-05-03 12:07:32 +00:00
Daniel Stenberg
39028f1bd4 make sure our own printf() clones are used 2002-05-03 12:06:04 +00:00
Daniel Stenberg
71f4c05665 -D now stores all headers to the same file if multiple URLs are given on the
command line!
2002-05-03 09:47:25 +00:00
Daniel Stenberg
9ef9797998 clarified that you must keep the variables that you point to! 2002-05-02 22:34:31 +00:00
Daniel Stenberg
ab9374de57 spell 2002-05-02 22:15:21 +00:00
Daniel Stenberg
913e997061 use and set the fd_set pointers instead of the actual values, as then we
work properly with the multi interface when the user has provided the
fd_sets!
2002-05-02 22:14:31 +00:00
Daniel Stenberg
8e50d6b6f3 added two pointers to the fd_set variables to read/write from, as sometimes
we need to point to user-provided fd_sets
2002-05-02 22:13:35 +00:00
Daniel Stenberg
2db0744a7b return CURLM_CALL_MULTI_PERFORM in one more case, and check return code
from malloc()
2002-05-02 22:12:14 +00:00
Daniel Stenberg
2de0028349 make sure the dns cache pointers in the easy handles are NULLed 2002-05-02 18:07:38 +00:00
Daniel Stenberg
35d04c5398 Hanno Kranzhoff noticed we didn't properly reset the download/upload counters
before transfers, when doing multiple ones on the same handle.
2002-05-02 08:52:09 +00:00
Daniel Stenberg
b1becd0ed5 Jacky Lam's fix to make the realloc() of the hostent data work properly
even when the realloc() actually gets a new memory block
2002-05-01 11:36:13 +00:00
Daniel Stenberg
bd9650bc81 how to set more than one cookie 2002-04-30 07:37:02 +00:00
Daniel Stenberg
969a25d1b2 implemented curl_multi_info_read() which I had forgotten before! 2002-04-27 22:21:51 +00:00
Daniel Stenberg
f144f77ba7 updated some docs 2002-04-27 20:19:55 +00:00
Daniel Stenberg
abea1f8910 clarified 2002-04-27 18:31:49 +00:00
Daniel Stenberg
8eaa7fec76 one added, one edited 2002-04-27 18:12:26 +00:00
Daniel Stenberg
fdace647e8 shorter introduction 2002-04-27 18:01:54 +00:00
Daniel Stenberg
d7531c18fc updated 2002-04-27 18:00:10 +00:00
Daniel Stenberg
ef3f978784 Added BINDINGS, lists all available libcurl bindings as of this date. 2002-04-27 17:02:38 +00:00
Daniel Stenberg
e410860e0e fixes on rainy saturday in the end of April, 2002 2002-04-27 13:26:32 +00:00
Daniel Stenberg
c64fca1b0c Fixed the FTP response reader to deal with timeouts better. Previously it
would reset the timeout for each incoming data, which would make veeery
slow responses be allowed to take even more time since the timeout would only
be reached if the time between two received data chunks was longer than the
set timeout value...
2002-04-27 13:24:06 +00:00
Daniel Stenberg
15b2a3af91 (Curl_GetFTPResponse) moved some code to only get performed when actually
needed
2002-04-27 13:09:37 +00:00
Daniel Stenberg
8358505b6d Now uses Curl_ as prefix for internal global symbols. curl_ should only be
used for "exported" globals.
2002-04-27 13:07:51 +00:00
Daniel Stenberg
1c42779845 DNC cache prune crash removed, made the name spacing follow the general
rule: "Curl_" prefix for library-wide private symbols, "curl_" is for
exported symbols.
2002-04-27 13:06:40 +00:00
Daniel Stenberg
32823f17e0 openbsd on Alpha was no problemos 2002-04-26 12:58:07 +00:00
Daniel Stenberg
e1c2e3f5e9 test suite portability fix 2002-04-26 12:57:49 +00:00
Daniel Stenberg
044755b30f handles much larger POSTs, replaced snprintf() with sprintf() since this
needs to be more portable and in the test server we can skip the extra
safety
2002-04-26 07:48:05 +00:00
Daniel Stenberg
9aa22399a8 another week of changes 2002-04-26 07:45:39 +00:00
Daniel Stenberg
f564905ac4 adjusted to the new Curl_resolv() proto 2002-04-25 19:26:29 +00:00
Daniel Stenberg
00e4f81446 prevent persistant connections to do name resolves 2002-04-25 19:18:19 +00:00
Daniel Stenberg
8927ddec16 In order to not get problems with DNS cache pruning, we no longer store
any name resolved data in any curl handle struct. That way, we won't mind
if the cache entries are pruned for the next time we need them. We'll just
resolve them again instead.

This changes the Curl_resolv() proto. It modifies the SessionHandle struct
but perhaps most importantly, it'll make the internals somewhat dependent
on the DNS cache not being disabled as that will cripple operations somewhat.
Especially for persistant connections.
2002-04-25 19:00:57 +00:00
Daniel Stenberg
f6525ae200 the TOTAL_TIME is not really total, as it excludes the connect time... 2002-04-25 16:45:15 +00:00
Daniel Stenberg
0be7944d66 use the hostname pointer instead of using IPv4-only info from a struct 2002-04-25 15:50:49 +00:00
Daniel Stenberg
47819ea86e clarified a bit with the timecondition stuff 2002-04-24 10:16:46 +00:00
Daniel Stenberg
96ce3461ad no, this doesn't look like it bugs 2002-04-24 10:16:00 +00:00
Daniel Stenberg
8b6d555421 NetBSD alpha works, also tried a newer FreeBSD on alpha 2002-04-24 10:15:37 +00:00
Daniel Stenberg
3b9ef8dfc8 removed warning about signed/unsigned comparison 2002-04-23 14:57:37 +00:00
Daniel Stenberg
db6d4bcf47 the 80 column police narrowed this source code! B-] 2002-04-23 14:56:21 +00:00
Daniel Stenberg
471f1d694f fixes bug report #547484, no_proxy doesn't properly strip off port numbers
from the host names before comparing
2002-04-23 13:34:28 +00:00
Daniel Stenberg
495f6f6bd3 use new timecond defines 2002-04-23 00:05:21 +00:00
Daniel Stenberg
36e35b6f60 allow binding the local end of a connection even when using IPv6, thus we
now have --interface working properly
2002-04-22 23:56:13 +00:00
Daniel Stenberg
192606bc4b use double where it is supposed to 2002-04-22 23:54:43 +00:00
Daniel Stenberg
53a9fdf078 use sclose() to close sockets 2002-04-22 23:53:49 +00:00
Daniel Stenberg
ef436bdbe8 renamed the TIMECOND defines to be CURL_ prefixed 2002-04-22 23:53:15 +00:00
Daniel Stenberg
72d722b07b The timecond stuff now have CURL_ prefixes 2002-04-22 13:33:56 +00:00
Daniel Stenberg
21fc402c01 Jacky Lam's adjust resolve-buffer size patch applied. Slightly edited
by Daniel.
2002-04-22 13:31:16 +00:00
Daniel Stenberg
381f77756d pack_hostent does not handle 64 bit pointers correctly.
A Bjrn Reese patch.
2002-04-19 11:00:26 +00:00
Sterling Hughes
a386562d9a Prune old hostcache entries with each call...
This can be optimized a tidbit, but this is a start.
2002-04-17 20:13:55 +00:00
Daniel Stenberg
2bc84fb163 Dirk Manske's two new infos 2002-04-17 07:21:17 +00:00
Daniel Stenberg
08f8917acb Dirk Manske's fix for HTTP response code 301, that now behaves more like
browsers do. Which thus *breaks* the RFC 2616...
2002-04-17 07:16:49 +00:00
Daniel Stenberg
62d205a2ec Dirk Manske brought the patch that introduces two new CURLINFO_* values:
CURLINFO_REDIRECT_TIME and CURLINFO_REDIRECT_COUNT.
2002-04-16 07:59:20 +00:00
Daniel Stenberg
29e873b12d Jonatan Lander fixed the "Disables POST, goes with GET" output to be more
connected with reality! ;-)
2002-04-15 13:47:06 +00:00
Daniel Stenberg
95f78080ab This makes formposting with a specified file missing fail. curl_easy_perform
will then return CURLE_READ_ERROR.
2002-04-15 11:19:03 +00:00
90 changed files with 3735 additions and 1280 deletions

285
CHANGES
View File

@@ -6,6 +6,291 @@
History of Changes
Version 7.9.8
Daniel (13 Jun 2002)
- Time to let this baby go.
Daniel (12 Jun 2002)
- Chris Combes added three new options for curl_formadd(): CURLFORM_BUFFER,
CURLFORM_BUFFERPTR, CURLFORM_BUFFERLENGTH. They are used to create a
multipart that appears as a regular file upload, but the data is provided
with a pointer and length.
- Nico Baggus made the VMS version use sigsetjmp() too.
- J<>rn Hartroth fixed the mingw32 build using the mm lib.
- Applied patches by Kris Kennaway that correct format string problems in
lib/ftp.c and lib/ldap.c.
Version 7.9.8-pre3
Daniel (11 Jun 2002)
- James Cone brought the idea of using sigsetjmp() in the signal handler to
make the time-out of name lookups to work, even when the underlying name
resolver library traps EINTR. The use of sigsetjmp() and siglongjmp() for
this may be a bit drastic, and also not likely to exist on all platforms. I
added careful checking for this in the configure script, even checks for it
being a macro (which seems to be the case in for example Linux).
sigsetjmp() seems to be mentioned in the Single Unix specification.
- Miklos Nemeth brought a patch that allows libcurl to get built with specific
protocols disabled. This is done by running ./configure
--disable-[protocol].
- FTP range downloads could make CURLE_FTP_WRITE_ERROR get returned. We now
make precautions to not return this for range downloads.
Added test case 135 that makes an ftp range download. Had to tweak the
runtests.pl script a bit too.
- Bug report #566835 identified a strlen() on a NULL pointer. Added additional
check to prevent this.
Daniel (10 Jun 2002)
- Found and corrected a connect failure problem that didn't create a human
error text.
- Added code to compile with OpenSSL 0.9.7. Based on patch from Jacob Meuser
and comments from G<>tz Babin-Ebell.
- Gautam Mani found a socket descriptor leak that happened when FTP transfers
failed and you reinvoked curl_easy_perform().
Daniel (5 Jun 2002)
- Gustaf Hui corrected curl_multi_remove_handle() so that it won't crash no
matter when you decide to remove the CURL handle.
- HAVE_RAND_STATUS was added to lib/config-win32.h by Andreas Olsson, as it
makes windows builds stop complaining about "weak seeding" when it in fact
isn't.
- Another 64bit architecture crash that was introduced in 7.9.7 was now
removed, as bug report #564585 clarified. This happened due to our attempts
to only allocate only as much memory as is actually needed for name
resolving (using realloc) which called for a function that could 'move' a
hostent struct in memory.
Version 7.9.8-pre2
Daniel (3 Jun 2002)
- T. Bharath fixed the CURLINFO_REDIRECT_TIME to return a correct time and
made the CURLINFO_REQUEST_SIZE return the correct total request size. He
also made the win32 timers use higher resolution than before.
Daniel (29 May 2002)
- Renaud Chaillat made me aware of the fact that libcurl returned an error if
you tried to get an empty FTP file. This seemed like a wrong thing to do, so
now it no longer does that! I just hope that no one built anything fancy
upon this unexpected behavior...
Daniel (28 May 2002)
- Cris Bailiff brought CURLOPT_CAPATH that works like CURLOPT_CAINFO but
specifies a path to a directory with certificates rather than a single file
with them all concatenated. --capath was added to the command line tool
for the same function.
Windows users need to pay attention that the directory should be setup with
the c_rehash tool of the OpenSSL package, and that creates symlinks by
default that need to be replaced with actual copies to work on Windows.
- Gustaf Hui provided new code that changes how curl_multi_info_read()
messages are stored, so that they don't have to be kept around for the multi
handle's entire life time. He also made it return failure codes properly
which it didn't do before.
Daniel (27 May 2002)
- Gustaf Hui pointed out that running curl_multi_perform() without doing
curl_multi_fdset() first was not really a working combo. I added an internal
check for this and have some extra select() code without timeout to make the
library internals work identically nevertheless. We might need to somehow
either document that once you've used the *_fdset() you should remain using
them in select() or you should blank them somehow so that libcurl won't go
crazy.
Version 7.9.8-pre1
Daniel (22 May 2002)
- James Cone brought an excellent patch, including several tests and docs!
CURLOPT_NETRC now takes an enum as argument instead of the previous boolean.
--netrc-optional was introduced as an addition to --netrc to allow the
command line client to take use of all that new netrc stuff.
- Bug report #558888 showed a case where libcurl re-used the previous host
name when a connection over a proxy was re-used but to a different target
host.
Daniel (21 May 2002)
- Edin Kadribasic helped me sort out a problem to made libcurl crash when
trying to HTTP POST an empty string.
- Clarified that Juergen Wilke donated the original tests/server/sws.c code.
- Jean-Philippe Barrette-LaPierre made curl_formadd() return a typedef named
CURLFORMcode instead of the previous 'int', and the various return codes are
now globally exported. It allows applications to better figure out what goes
wrong when curl_formadd() returns errors.
Daniel (20 May 2002)
- Roland Zimmermann pointed out that SSL_CTX_use_certificate_chain_file()
is prefered to SSL_CTX_use_certificate_file().
Daniel (17 May 2002)
- Bug report #556869 pointed out that src/writeout.c didn't compile on freebsd
after my AIX fixes the other week.
- Bug report #556930 pointed out a FreeBSD core dump introduced in 7.9.7 in
the DNS struct realloc stuff. Actually, this crash could happen on all
systems that made the pack_hostent() function get invoked.
- I removed several compiler warnings in the test suite's HTTP server.
Version 7.9.7
Daniel (10 May 2002)
- Kevin Roth adjusted the --trace-ascii output slightly.
- Paul Harrington found out that src/writeout.c needed an additional header
file included for AIX builds
Version 7.9.7-pre2
Daniel (7 May 2002)
- Updated the man page with --trace-ascii and -j/--junk-session-cookies.
- Made --trace-ascii do pretty much the same as --trace but without the hex
part in the output.
- Added CURLOPT_COOKIESESSION that when enabled makes libcurl ignore session
cookies read from a file. This option is enforced by the curl command line
tool using the new -j/--junk-session-cookies option. After discussions with
Kevin Roth. This makes it easier to use curl to fully emulate a browser's
behavior, even when it comes to "session cookies". Session cookies are
cookies that a normal browser discards when the browser is shut
down. They're identified by not having any expire date/time.
- When CURLOPT_DEBUGDATA was set, it ruined the CURLOPT_STDERR setting and
this was discovered when --trace was made to crash.
- Using -v and --trace at the same time confused matters. -v is now pretty
much ignored when --trace or --trace-ascii is used.
- Made --trace (and --trace-ascii) support - as file name to pass output to
stdout instead. It makes it consistent with how other options work.
Version 7.9.7-pre1
Daniel (6 May 2002)
- Added multi-post.c to the examples directory. I got the basic source for
this from Gustaf Hui.
Daniel (3 May 2002)
- CURL_MAX_WRITE_SIZE is now an exported #define in the curl/curl.h header and
can be used to figure out the maximum buffer size your write callback can
get.
- CURLOPT_READDATA is now an alias for CURLOPT_INFILE and CURLOPT_WRITEDATE is
an alias for CURLOPT_FILE. These two were added for conformity. Most other
callback function's userdata are provided with options using a similar name-
scheme.
- Added "--trace [file]" to the command line tool. It makes a very detailed
trace dump get stored, with a full protocol dump that includes all received
and transmitted data. This could be a very effective tool for debugging what
goes wrong. This dump includes every byte the way it is sent to/received
from the server. The dump is the plain-text version, so SSL transfers will
still be readable.
- I found out that the DEBUGFUNCTION was not called properly everywhere as we
wanted it to. I fixed it.
- -D now stores all headers to the same file if multiple URLs are given on the
command line! Kevin Roth made me aware of that it didn't already do this!
- Gustaf Hui wrote an excellent formpost example that used the multi
interface. Unfortunately, it didn't work due to several bugs in how
transfers were made when the multi interface was used.
Daniel (2 May 2002)
- Hanno Kranzhoff found out that when doing multiple transfers on the same
easy handle, the progress meter would show a bad "currently downloaded
value" when the transfer starts.
Daniel (1 May 2002)
- Applied another patch by Jacky Lam to make the name resolve info realloc()
stuff work properly.
Daniel (28 April 2002)
- curl_multi_info_read() is now implemented!
Daniel (27 April 2002)
- Updated BUGS, TODO, FAQ, INSTALL and added BINDINGS.
- I think I fixed the DNS cache prune crach Jacky Lam found and reported.
- I cleaned up the name prefix stuff in the hash and llist modules.
- FTP responses should now be better on timing out properly. The timeout value
is maximum timeout for the entire request operation, but before this, the
timeout was used as a maximum allowed time between two reads...
Daniel (26 April 2002)
- Fixed the test suite http server to not use snprintf() anymore due to better
portability.
Daniel (25 April 2002)
- With Sterling Hughes' new DNS pruning, Jacky Lam asked if this wouldn't
cause problems since the pruning is only checking the entry time, and it
sure could cause problems. Therefor, I've now added and changed code so that
this should not be a problem. Nowhere in the code will be store name
resolved information around so that a sunsequent DNS cache prune should
cause a problem. This of course called for some mild internal changes.
Daniel (23 April 2002)
- Improved the 'no_proxy' check, as using port numbers in the URL confused it
previously. Reported by Erwan Legrand in bug report #547484.
- The --interface option now works even on IPv6 enabled builds. Reported by
'thor'.
Daniel (22 April 2002)
- The #defines names starting with TIMECOND now has CURL_ prefixes. (The old
names are still #defined too.) Pointed out by Robert Olson.
- Jacky Lam brought code that lets the name resolve function only use as much
memory as it actually needs. This only works on certain operating systems,
but is totally transparant to all users.
Daniel (19 April 2002)
- Bjorn Reese fixed pack_hostent to work properly with 64 bit pointers.
Daniel (18 April 2002)
- Sterling Hughes added code to prune old DNS cache entries, since Jacky Lam
experienced very big caches.
Daniel (17 April 2002)
- Dirk Manske patched the 301 response to work against the RFC but more like
common browsers do. If a POST get a 301 back, it'll switch to GET in the
next request (if location-following is enabled).
Daniel (16 April 2002)
- Dirk Manske posted a patch originally written by Ingo Wilken that introduced
two new CURLINFO_* values: CURLINFO_REDIRECT_TIME and
CURLINFO_REDIRECT_COUNT.
Daniel (15 April 2002)
- Jonatan Lander patched the verbose text 'Disables POST, goes with GET' to
reflect reality better, like when the first request isn't POST and when
the second isn't GET... :-)
- Craig Davison pointed out that when curl_formadd()ing a file that doesn't
exist, libcurl doesn't return error. Now, curl_easy_perform() will return
CURLE_READ_ERROR if that is the case. Test 41 was added to verify this.
Version 7.9.6
Daniel (14 April 2002)
- Dirk Manske brought a fix that makes libcurl strip off white spaces from the
beginning of cookie contents.

View File

@@ -64,3 +64,24 @@
/* Define this to 'int' if in_addr_t is not an available typedefed type */
#undef in_addr_t
/* Define to disable DICT */
#undef CURL_DISABLE_DICT
/* Define to disable FILE */
#undef CURL_DISABLE_FILE
/* Define to disable FTP */
#undef CURL_DISABLE_FTP
/* Define to disable GOPHER */
#undef CURL_DISABLE_GOPHER
/* Define to disable HTTP */
#undef CURL_DISABLE_HTTP
/* Define to disable LDAP */
#undef CURL_DISABLE_LDAP
/* Define to disable TELNET */
#undef CURL_DISABLE_TELNET

View File

@@ -56,24 +56,117 @@ dnl AC_PROG_INSTALL
AC_PROG_MAKE_SET
dnl ************************************************************
dnl lame option to switch on debug options
dnl switch off particular protocols
dnl
AC_MSG_CHECKING([whether to enable debug options])
AC_ARG_ENABLE(debug,
[ --enable-debug Enable pedantic debug options
--disable-debug Disable debug options],
AC_MSG_CHECKING([whether to support http])
AC_ARG_ENABLE(http,
[ --enable-http Enable HTTP support
--disable-http Disable HTTP support],
[ case "$enableval" in
no)
AC_MSG_RESULT(no)
AC_DEFINE(CURL_DISABLE_HTTP)
AC_MSG_WARN([disable HTTP disables FTP over proxy and GOPHER too])
AC_DEFINE(CURL_DISABLE_GOPHER)
AC_SUBST(CURL_DISABLE_HTTP)
AC_SUBST(CURL_DISABLE_GOPHER)
;;
*) AC_MSG_RESULT(yes)
CPPFLAGS="$CPPFLAGS -DMALLOCDEBUG"
CFLAGS="-W -Wall -Wwrite-strings -pedantic -Wundef -Wpointer-arith -Wcast-align -Wnested-externs -g"
;;
esac ],
AC_MSG_RESULT(no)
AC_MSG_RESULT(yes)
)
AC_MSG_CHECKING([whether to support ftp])
AC_ARG_ENABLE(ftp,
[ --enable-ftp Enable FTP support
--disable-ftp Disable FTP support],
[ case "$enableval" in
no)
AC_MSG_RESULT(no)
AC_DEFINE(CURL_DISABLE_FTP)
AC_SUBST(CURL_DISABLE_FTP)
;;
*) AC_MSG_RESULT(yes)
;;
esac ],
AC_MSG_RESULT(yes)
)
AC_MSG_CHECKING([whether to support gopher])
AC_ARG_ENABLE(gopher,
[ --enable-gopher Enable GOPHER support
--disable-gopher Disable GOPHER support],
[ case "$enableval" in
no)
AC_MSG_RESULT(no)
AC_DEFINE(CURL_DISABLE_GOPHER)
AC_SUBST(CURL_DISABLE_GOPHER)
;;
*) AC_MSG_RESULT(yes)
;;
esac ],
AC_MSG_RESULT(yes)
)
AC_MSG_CHECKING([whether to support file])
AC_ARG_ENABLE(file,
[ --enable-file Enable FILE support
--disable-file Disable FILE support],
[ case "$enableval" in
no)
AC_MSG_RESULT(no)
AC_DEFINE(CURL_DISABLE_FILE)
AC_SUBST(CURL_DISABLE_FILE)
;;
*) AC_MSG_RESULT(yes)
;;
esac ],
AC_MSG_RESULT(yes)
)
AC_MSG_CHECKING([whether to support ldap])
AC_ARG_ENABLE(ldap,
[ --enable-ldap Enable LDAP support
--disable-ldap Disable LDAP support],
[ case "$enableval" in
no)
AC_MSG_RESULT(no)
AC_DEFINE(CURL_DISABLE_LDAP)
AC_SUBST(CURL_DISABLE_LDAP)
;;
*) AC_MSG_RESULT(yes)
;;
esac ],
AC_MSG_RESULT(yes)
)
AC_MSG_CHECKING([whether to support dict])
AC_ARG_ENABLE(dict,
[ --enable-dict Enable DICT support
--disable-dict Disable DICT support],
[ case "$enableval" in
no)
AC_MSG_RESULT(no)
AC_DEFINE(CURL_DISABLE_DICT)
AC_SUBST(CURL_DISABLE_DICT)
;;
*) AC_MSG_RESULT(yes)
;;
esac ],
AC_MSG_RESULT(yes)
)
AC_MSG_CHECKING([whether to support telnet])
AC_ARG_ENABLE(telnet,
[ --enable-telnet Enable TELNET support
--disable-telnet Disable TELNET support],
[ case "$enableval" in
no)
AC_MSG_RESULT(no)
AC_DEFINE(CURL_DISABLE_TELNET)
AC_SUBST(CURL_DISABLE_TELNET)
;;
*) AC_MSG_RESULT(yes)
;;
esac ],
AC_MSG_RESULT(yes)
)
dnl **********************************************************************
dnl Checks for IPv6
@@ -510,7 +603,8 @@ AC_CHECK_HEADERS( \
io.h \
pwd.h \
utime.h \
sys/utime.h
sys/utime.h \
setjmp.h
)
dnl Check for libz header
@@ -565,9 +659,23 @@ AC_CHECK_FUNCS( socket \
getpwuid \
geteuid \
dlopen \
utime
utime \
sigsetjmp
)
dnl sigsetjmp() might be a macro and no function so if it isn't found already
dnl we make an extra check here!
if test "$ac_cv_func_sigsetjmp" != "yes"; then
AC_MSG_CHECKING([for sigsetjmp defined as macro])
AC_TRY_LINK( [#include <setjmp.h>],
[sigjmp_buf jmpenv;
sigsetjmp(jmpenv, 1);],
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_SIGSETJMP),
AC_MSG_RESULT(no)
)
fi
dnl removed 'getpass' check on October 26, 2000
if test "$ac_cv_func_select" != "yes"; then
@@ -591,6 +699,26 @@ dnl AC_PATH_PROG( RANLIB, ranlib, /usr/bin/ranlib,
dnl $PATH:/usr/bin/:/usr/local/bin )
dnl AC_SUBST(RANLIB)
dnl ************************************************************
dnl lame option to switch on debug options
dnl
AC_MSG_CHECKING([whether to enable debug options])
AC_ARG_ENABLE(debug,
[ --enable-debug Enable pedantic debug options
--disable-debug Disable debug options],
[ case "$enableval" in
no)
AC_MSG_RESULT(no)
;;
*) AC_MSG_RESULT(yes)
CPPFLAGS="$CPPFLAGS -DMALLOCDEBUG"
CFLAGS="-W -Wall -Wwrite-strings -pedantic -Wundef -Wpointer-arith -Wcast-align -Wnested-externs -g"
;;
esac ],
AC_MSG_RESULT(no)
)
AC_CONFIG_FILES([Makefile \
docs/Makefile \
docs/examples/Makefile \

View File

@@ -61,6 +61,27 @@ while test $# -gt 0; do
if test "@IPV6_ENABLED@" = "1"; then
echo "IPv6"
fi
if test "@CURL_DISABLE_HTTP@" = "1"; then
echo "HTTP-disabled"
fi
if test "@CURL_DISABLE_FTP@" = "1"; then
echo "FTP-disabled"
fi
if test "@CURL_DISABLE_GOPHER@" = "1"; then
echo "GOPHER-disabled"
fi
if test "@CURL_DISABLE_FILE@" = "1"; then
echo "FILE-disabled"
fi
if test "@CURL_DISABLE_TELNET@" = "1"; then
echo "TELNET-disabled"
fi
if test "@CURL_DISABLE_LDAP@" = "1"; then
echo "LDAP-disabled"
fi
if test "@CURL_DISABLE_DICT@" = "1"; then
echo "DICT-disabled"
fi
;;
--version)

96
docs/BINDINGS Normal file
View File

@@ -0,0 +1,96 @@
_ _ ____ _
___| | | | _ \| |
/ __| | | | |_) | |
| (__| |_| | _ <| |___
\___|\___/|_| \_\_____|
libcurl bindings
Creative people have written particular bindings or interfaces for various
environments and programming languages. Using one of these allows you to take
advantage of curl powers from within your favourite language or system.
This is a list of all known interfaces as of this writing.
The bindings listed below are not part of the curl/libcurl distribution
archives, but must be downloaded and installed separately.
Basic
ScriptBasic bindings to libcurl. Writtten by Peter Verhas.
http://scriptbasic.com/
C++
Maintained by Jean-Philippe Barrette-LaPierre.
http://curl.haxx.se/libcurl/cplusplus/
Cocoa
Written by Dan Wood.
http://curlhandle.sourceforge.net/
Dylan
Written by Chris Double.
http://dylanlibs.sourceforge.net/
Java
Written by Daniel Stenberg.
http://curl.haxx.se/libcurl/java/
Lua
Written by Steve Dekorte.
http://curl.haxx.se/libcurl/lua/
Object-Pascal
Free Pascal, Delphi and Kylix binding written by Christophe Espern.
http://www.tekool.com/opcurl
Pascal
Free Pascal, Delphi and Kylix binding written by Jeffrey Pohlmeyer.
http://houston.quik.com/jkp/curlpas/
Perl
Maintained by Cris Bailiff.
http://curl.haxx.se/libcurl/perl/
PHP
Written by Sterling Hughes.
http://curl.haxx.se/libcurl/php/
PostgreSQL
Written by Gian Paolo Ciceri.
http://gborg.postgresql.org/project/pgcurl/projdisplay.php
Python
Written by Kjetil Jacobsen.
http://pycurl.sourceforge.net/
Rexx
Written Mark Hessling.
http://rexxcurl.sourceforge.net/
Ruby
Written by Hirotaka Matsuyuki.
http://www.d1.dion.ne.jp/~matuyuki/ruby.html
Scheme
Bigloo binding written by Kirill Lisovsky.
http://curl.haxx.se/libcurl/scheme/
Tcl
Written by Andr<64>s Garc<72>a.
http://personal1.iddeo.es/andresgarci/tclcurl/english/docs.html

View File

@@ -8,28 +8,44 @@ $Id$
BUGS
Curl and libcurl have grown substantially since the beginning. At the time
of writing (mid March 2001), there are 23000 lines of source code, and by
of writing (end of April 2002), there are 32000 lines of source code, and by
the time you read this it has probably grown even more.
Of course there are lots of bugs left. And lots of misfeatures.
To help us make curl the stable and solid product we want it to be, we need
bug reports and bug fixes. If you can't fix a bug yourself and submit a fix
for it, try to report an as detailed report as possible to the curl mailing
list to allow one of us to have a go at a solution. You should also post
your bug/problem at curl's bug tracking system over at
bug reports and bug fixes.
WHERE TO REPORT
If you can't fix a bug yourself and submit a fix for it, try to report an as
detailed report as possible to the curl mailing list to allow one of us to
have a go at a solution. You should also post your bug/problem at curl's bug
tracking system over at
http://sourceforge.net/bugs/?group_id=976
When reporting a bug, you should include information that will help us
understand what's wrong, what you expected to happen and how to repeat the
bad behavior. You therefore need to supply your operating system's name and
version number (uname -a under a unix is fine), what version of curl you're
using (curl -V is fine), what URL you were working with and anything else
you think matters.
(but please read the section below first before doing that)
Since curl deals with networks, it often helps us a lot if you include a
protocol debug dump with your bug report. The output you get by using the -v
WHAT TO REPORT
When reporting a bug, you should include information that will help us
understand what's wrong what you expected to happen and how to repeat the
bad behavior. You therefore need to tell us:
- your operating system's name and version number (uname -a under a unix
is fine)
- what version of curl you're using (curl -V is fine)
- what URL you were working with (if possible), at least which protocol
and anything and everything else you think matters. Tell us what you
expected to happen, tell use what did happen, tell us how you could make it
work another way. Dig around, try out, test. Then include all the tiny bits
and pieces in your report. You will benefit from this yourself, as it will
enable us to help you quicker and more accurately.
Since curl deals with networks, it often helps us if you include a protocol
debug dump with your bug report. The output you get by using the -v
flag. Usually, you also get more info by using -i so that is likely to be
useful when reporting bugs as well.

View File

@@ -1,4 +1,4 @@
Updated: March 11, 2002 (http://curl.haxx.se/docs/faq.shtml)
Updated: May 23, 2002 (http://curl.haxx.se/docs/faq.html)
_ _ ____ _
___| | | | _ \| |
/ __| | | | |_) | |
@@ -15,6 +15,7 @@ FAQ
1.5 Who makes cURL?
1.6 What do you get for making cURL?
1.7 What about CURL from curl.com?
1.8 I have a problem who do I mail?
2. Install Related Problems
2.1 configure doesn't find OpenSSL even when it is installed
@@ -30,14 +31,15 @@ FAQ
3.3 Why doesn't my posting using -F work?
3.4 How do I tell curl to run custom FTP commands?
3.5 How can I disable the Pragma: nocache header?
3.6 Does curl support javascript, ASP, XML, XHTML or HTML version Y?
3.6 Does curl support ASP, XML, XHTML or HTML version Y?
3.7 Can I use curl to delete/rename a file through FTP?
3.8 How do I tell curl to follow HTTP redirects?
3.9 How do I use curl in my favourite programming language?
3.9 How do I use curl in my favorite programming language?
3.10 What about SOAP, WebDAV, XML-RPC or similar protocols over HTTP?
3.11 How do I POST with a different Content-Type?
3.12 Why do FTP specific features over HTTP proxy fail?
3.13 Why does my single/double quotes fail?
3.14 Does curl support javascript or pac (automated proxy config)?
4. Running Problems
4.1 Problems connecting to SSL servers.
@@ -55,6 +57,7 @@ FAQ
4.7 How do I keep user names and passwords secret in Curl command lines?
4.8 I found a bug!
4.9 Curl can't authenticate to the server that requires NTLM?
4.10 My HTTP request using HEAD, PUT or DELETE doesn't work!
5. libcurl Issues
5.1 Is libcurl thread-safe?
@@ -193,6 +196,21 @@ FAQ
We recognize that we will be living in parallel with curl.com and wish them
every success.
1.8 I have a problem who do I mail?
Please do not attempt to mail any single individual unless you really need
to. Keep curl-related questions on a suitable mailing list. All available
mailing lists are listed in the MANUAL document and online at
http://curl.haxx.se/mail/
Keeping curl-related questions and discussions on mailing lists allows others
to join in and help, to share their ideas, contribute their suggestions and
spread their wisdom. Keeping discussions on public mailing lists also allows
for others to learn from this (both current and future users thanks to the
web based archives of the mailing lists), thus saving us from having to
repeat ourselves even more. Thanks for respecting this.
2. Install Related Problems
2.1. configure doesn't find OpenSSL even when it is installed
@@ -308,16 +326,14 @@ FAQ
the -H/--header option. By adding a header with empty contents you safely
disable that one. Use -H "Pragma:" to disable that specific header.
3.6. Does curl support javascript, ASP, XML, XHTML or HTML version Y?
3.6. Does curl support ASP, XML, XHTML or HTML version Y?
To curl, all contents are alike. It doesn't matter how the page was
generated. It may be ASP, PHP, Perl, shell-script, SSI or plain
HTML-files. There's no difference to curl and it doesn't even know what kind
of language that generated the page.
Javascript is slightly different since that is code embedded in the HTML
that is sent for the client to interpret and curl has no javascript
interpreter.
See also item 3.14 regarding javascript.
3.7. Can I use curl to delete/rename a file through FTP?
@@ -335,7 +351,7 @@ FAQ
curl -L http://redirector.com
3.9 How do I use curl in my favourite programming language?
3.9 How do I use curl in my favorite programming language?
There exist many language interfaces/bindings for curl that integrates it
better with various languages. If you are fluid in a script language, you
@@ -372,7 +388,7 @@ FAQ
Because when you use a HTTP proxy, the protocol spoken on the network will
be HTTP, even if you specify a FTP URL. This effectively means that you
normally can't use FTP specific features such as ftp upload and ftp quote
normally can't use FTP specific features such as FTP upload and FTP quote
etc.
There is one exception to this rule, and that is if you can "tunnel through"
@@ -392,17 +408,41 @@ FAQ
curl -d ' with spaces ' url.com
Exactly what kind of quotes and how to do this is entirely up to the shell
or command line interepreter that you are using. For most unix shells, you
or command line interpreter that you are using. For most unix shells, you
can more or less pick either single (') or double (") quotes. For
Windows/DOS prompts I believe you're forced to use double (") quotes.
Please study the documentaion for your particular environment. Examples in
Please study the documentation for your particular environment. Examples in
the curl docs will use a mix of both these ones as shown above. You must
adjust them to work in your environment.
Remember that curl works and runs on more operating systems than most single
individuals have ever tried.
3.14 Does curl support javascript or pac (automated proxy config)?
Many web pages do magic stuff using embedded javascript. Curl and libcurl
have no built-in support for that, so it will be treated just like any other
contents.
.pac files are a netscape invention and are sometimes used by organizations
to allow them to differentiate which proxies to use. The .pac contents is
just a javascript program that gets invoked by the browser and that returns
the name of the proxy to connect to. Since curl doesn't support javascript,
it can't support .pac proxy configuration either.
Some work-arounds usually suggested to overcome this javascript dependency:
- Depending on the javascript complexity, write up a script that
translates it to another language and execute that.
- Read the javascript code and rewrite the same logic in another language.
- Implement a javascript interpreted, people have successfully used the
Mozilla javascript engine in the past.
- Ask your admins to stop this, for a static proxy setup or similar.
4. Running Problems
@@ -495,7 +535,7 @@ FAQ
4.5.6 "301 Moved Permanently"
If you get this return code and an HTML outpt similar to this:
If you get this return code and an HTML output similar to this:
<H1>Moved Permanently</H1> The document has moved <A
HREF="http://same_url_now_with_a_trailing_slash/">here</A>.
@@ -537,12 +577,8 @@ FAQ
particular platform, try contacting the person who built the package/archive
you have.
If there is a bug, post a bug report in the Curl Bug Track System over at
http://sourceforge.net/bugs/?group_id=976
Always include as many details you can think of, including curl version,
operating system name and version and complete instructions how to repeat
the bug.
If there is a bug, read the BUGS document first. Then report it as described
in there.
4.9. Curl can't authenticate to the server that requires NTLM?
@@ -550,6 +586,18 @@ FAQ
currently support that. Proprietary formats are evil. You should not use
such ones.
4.10 My HTTP request using HEAD, PUT or DELETE doesn't work!
Many web servers allow or demand that the administrator configures the
server properly for these requests to work on the web server.
Some servers seem to support HEAD only on certain kinds of URLs.
To fully grasp this, try the documentation for the particular server
software you're trying to interact with. This is not anything curl can do
anything about.
5. libcurl Issues
5.1. Is libcurl thread-safe?

View File

@@ -395,13 +395,15 @@ CROSS COMPILE
PORTS
=====
This is a probably incomplete list of known hardware and operating systems
that curl has been compiled for. If you know one system curl compiles and
that curl has been compiled for. If you know a system curl compiles and
runs on, that isn't listed, please let us know!
- Alpha DEC OSF 4
- Alpha Digital UNIX v3.2
- Alpha FreeBSD 4.1
- Alpha Linux 2.2.16
- Alpha FreeBSD 4.1, 4.5
- Alpha Linux 2.2, 2.4
- Alpha NetBSD 1.5.2
- Alpha OpenBSD 3.0
- Alpha OpenVMS V7.1-1H2
- Alpha Tru64 v5.0 5.1
- HP-PA HP-UX 9.X 10.X 11.X
@@ -409,7 +411,7 @@ PORTS
- MIPS IRIX 6.2, 6.5
- MIPS Linux
- Pocket PC/Win CE 3.0
- Power AIX 4.2, 4.3.1, 4.3.2
- Power AIX 4.2, 4.3.1, 4.3.2, 5.1
- PowerPC Darwin 1.0
- PowerPC Linux
- PowerPC Mac OS 9
@@ -432,6 +434,7 @@ PORTS
- i386 SCO unix
- i386 Solaris 2.7
- i386 Windows 95, 98, ME, NT, 2000
- i386 QNX 6
- ia64 Linux 2.3.99
- m68k AmigaOS 3
- m68k Linux

View File

@@ -3,9 +3,6 @@ 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
may have been fixed since this was written!
* curl_formadd() fails on OSF1. Why? Fix! Need help from OSF1 dudes.
https://sourceforge.net/tracker/index.php?func=detail&aid=524433&group_id=976&atid=100976
* Running 'make test' on Mac OS X gives 4 errors. This seems to be related
to some kind of libtool problem:
http://curl.haxx.se/mail/archive-2002-03/0029.html and

View File

@@ -716,9 +716,9 @@ NETRC
passwords, so therefor most unix programs won't read this file unless it is
only readable by yourself (curl doesn't care though).
Curl supports .netrc files if told so (using the -n/--netrc option). This is
not restricted to only ftp, but curl can use it for all protocols where
authentication is used.
Curl supports .netrc files if told so (using the -n/--netrc and
--netrc-optional options). This is not restricted to only ftp,
but curl can use it for all protocols where authentication is used.
A very simple .netrc file could look something like:

View File

@@ -16,7 +16,7 @@ SUBDIRS = examples libcurl
EXTRA_DIST = MANUAL BUGS CONTRIBUTE FAQ FEATURES INTERNALS \
README.win32 RESOURCES TODO TheArtOfHttpScripting THANKS \
VERSIONS KNOWN_BUGS $(man_MANS) $(HTMLPAGES)
VERSIONS KNOWN_BUGS BINDINGS $(man_MANS) $(HTMLPAGES)
MAN2HTML= gnroff -man $< | man2html >$@

View File

@@ -5,10 +5,9 @@
\___|\___/|_| \_\_____|
This document has been introduced in order to let you find documents that
specify standards used by curl, software that extends curl, web pages with
"competing" utilities and information pages that describe some of the tools
that we use to build/compile/develop curl.
This document lists documents that specify standards used by curl, software
that extends curl, web pages with similar utilities and information pages that
describe some of the tools that we use to build/compile/develop curl.
Standards
---------

View File

@@ -17,16 +17,10 @@ TODO
* Make content encoding/decoding internally be made using a filter system.
* Test the 'multi' interface more.
* Introduce another callback interface for upload/download that makes one
less copy of data and thus a faster operation.
[http://curl.haxx.se/dev/no_copy_callbacks.txt]
* Add configure options that disables certain protocols in libcurl to
decrease footprint. '--disable-[protocol]' where protocol is http, ftp,
telnet, ldap, dict or file.
* Add asynchronous name resolving. http://curl.haxx.se/dev/async-resolver.txt
This should be made to work on most of the supported platforms, or
otherwise it isn't really interesting.
@@ -53,16 +47,18 @@ TODO
especially regular HTTP POST), the FTP command sending etc.
* Go through the code and verify that libcurl deals with big files >2GB and
>4GB all over. Bug reports indicate that it doesn't currently work
properly.
>4GB all over. Bug reports (and source reviews) indicate that it doesn't
currently work properly.
* Make the built-in progress meter use its own dedicated output stream, and
make it possible to set it. Use stderr by default.
* CURLOPT_MAXFILESIZE. Prevent downloads that are larger than the specified
size. CURLE_FILESIZE_EXCEEDED would then be returned. Gautam Mani
requested.
DOCUMENTATION
* Include documentation in the main archive about all the various libcurl
bindings.
FTP
@@ -77,7 +73,9 @@ TODO
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.
* 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,
"Securing FTP with TLS"
HTTP

View File

@@ -2,7 +2,7 @@
.\" nroff -man curl.1
.\" Written by Daniel Stenberg
.\"
.TH curl 1 "10 Apr 2002" "Curl 7.9.5" "Curl Manual"
.TH curl 1 "7 May 2002" "Curl 7.9.7" "Curl Manual"
.SH NAME
curl \- transfer a URL
.SH SYNOPSIS
@@ -99,10 +99,7 @@ If this option is used severl times, the last one will override the others.
.IP "--connect-timeout <seconds>"
Maximum time in seconds that you allow the connection to the server to take.
This only limits the connection phase, once curl has connected this option is
of no more use. This option didn't work in win32 systems until 7.7.2. See
also the
.I "--max-time"
option.
of no more use. See also the \fI--max-time\fP option.
If this option is used several times, the last one will be used.
.IP "-c/--cookie-jar <file name>"
@@ -125,6 +122,10 @@ 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.
If this option is used several times, the last one will be used.
.IP "--crlf"
(FTP) Convert LF to CRLF in upload. Useful for MVS (OS/390).
If this option is used twice, the second will again disable crlf converting.
.IP "-d/--data <data>"
(HTTP) Sends the specified data in a POST request to the HTTP server, in a way
that can emulate as if a user has filled in a HTML form and pressed the submit
@@ -167,16 +168,17 @@ append data.
downloads. Curl will normally always first attempt to use EPSV before PASV,
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.
.IP "-D/--dump-header <file>"
(HTTP/FTP)
Write the HTTP headers to this file. Write the FTP file info to this
file if -I/--head is used.
Write the protocol headers to the specified file.
This option is handy to use when you want to store the cookies that a HTTP
site sends to you. The cookies could then be read in a second curl invoke by
using the -b/--cookie option!
When used on FTP, the ftp server response lines are considered being "headers"
and thus are saved there.
If this option is used several times, the last one will be used.
.IP "-e/--referer <URL>"
(HTTP) Sends the "Referer Page" information to the HTTP server. This can also
@@ -187,6 +189,12 @@ previous URL when it follows a Location: header. The ";auto" string can be
used alone, even if you don't set an initial referer.
If this option is used several times, the last one will be used.
.IP "--environment"
(RISC OS ONLY) Sets a range of environment variables, using the names the -w
option supports, to easier allow extraction of useful information after having
run curl.
If this option is used several times, each occurrence will toggle this on/off.
.IP "--egd-file <file>"
(HTTPS) Specify the path name to the Entropy Gathering Daemon socket. The
socket is used to seed the random engine for SSL connections. See also the
@@ -203,17 +211,25 @@ certificate concatenated!
If this option is used several times, the last one will be used.
.IP "--cacert <CA certificate>"
(HTTPS) Tells curl to use the specified certificate file to verify the
peer. The certificate must be in PEM format.
peer. The file may contain multiple CA certificates. The certificate(s) must
be in PEM format.
If this option is used several times, the last one will be used.
.IP "--capath <CA certificate directory>"
(HTTPS) Tells curl to use the specified certificate directory to verify the
peer. The certificates must be in PEM format, and the directory must have been
processed using the c_rehash utility supplied with openssl. Certificate directories
are not supported under Windows (because c_rehash uses symbolink links to
create them). Using --capath can allow curl to make https connections much
more efficiently than using --cacert if the --cacert file contains many CA certificates.
If this option is used several times, the last one will be used.
.IP "-f/--fail"
(HTTP)
Fail silently (no output at all) on server errors. This is mostly done
like this to better enable scripts etc to better deal with failed
attempts. In normal cases when a HTTP server fails to deliver a
document, it returns a HTML document stating so (which often also
describes why and more). This flag will prevent curl from
outputting that and fail silently instead.
(HTTP) Fail silently (no output at all) on server errors. This is mostly done
like this to better enable scripts etc to better deal with failed attempts. In
normal cases when a HTTP server fails to deliver a document, it returns a HTML
document stating so (which often also describes why and more). This flag will
prevent curl from outputting that and fail silently instead.
If this option is used twice, the second will again disable silent failure.
.IP "-F/--form <name=content>"
@@ -241,13 +257,17 @@ This option can be used multiple times.
This option switches off the "URL globbing parser". When you set this option,
you can specify URLs that contain the letters {}[] without having them being
interpreted by curl itself. Note that these letters are not normal legal URL
contents but they should be encoded according to the URI standard. (Option
added in curl 7.6)
contents but they should be encoded according to the URI standard.
.IP "-G/--get"
When used, this option will make all data specified with -d/--data or
--data-binary to be used in a HTTP GET request instead of the POST request
that otherwise would be used. The data will be appended to the URL with a '?'
separator. (Option added in curl 7.9)
If used in combination with -I, the POST data will instead be appended to the
URL with a HEAD request.
If used multiple times, nothing special happens.
.IP "-h/--help"
Usage help.
.IP "-H/--header <header>"
@@ -260,7 +280,7 @@ set headers without knowing perfectly well what you're doing. Replacing an
internal header with one without content on the right side of the colon will
prevent that header from appearing.
This option can be used multiple times.
This option can be used multiple times to add/replace/remove multiple headers.
.IP "-i/--include"
(HTTP)
Include the HTTP-header in the output. The HTTP-header includes things
@@ -281,6 +301,13 @@ which this uses to get nothing but the header of a document. When used
on a FTP file, curl displays the file size only.
If this option is used twice, the second will again disable header only.
.IP "-j/--junk-session-cookies"
(HTTP) When curl is told to read cookies from a given file, this option will
make it discard all "session cookies". This will basicly have the same effect
as if a new session is started. Typical browsers always discard session
cookies when they're closed down. (Added in 7.9.7)
If this option is used several times, each occurrence will toggle this on/off.
.IP "--krb4 <level>"
(FTP) Enable kerberos4 authentication and use. The level must be entered and
should be one of 'clear', 'safe', 'confidential' or 'private'. Should you use
@@ -312,6 +339,10 @@ Especially useful if you want to machine-parse the contents of an FTP
directory since the normal directory view doesn't use a standard look
or format.
This option causes an FTP NLST command to be sent. Some FTP servers
list only files in their response to NLST; they do not include
subdirectories and symbolic links.
If this option is used twice, the second will again disable list only.
.IP "-L/--location"
(HTTP/HTTPS) If the server reports that the requested page has a different
@@ -325,10 +356,8 @@ If this option is used twice, the second will again disable location following.
.IP "-m/--max-time <seconds>"
Maximum time in seconds that you allow the whole operation to take. This is
useful for preventing your batch jobs from hanging for hours due to slow
networks or links going down. This doesn't work fully in win32 systems.
See also the
.I "--connect-timeout"
option.
networks or links going down. This doesn't work fully in win32 systems. See
also the \fI--connect-timeout\fP option.
If this option is used several times, the last one will be used.
.IP "-M/--manual"
@@ -485,6 +514,12 @@ If this option is used twice, the second will again disable mute.
When used with -s it makes curl show error message if it fails.
If this option is used twice, the second will again disable show error.
.IP "--stderr <file>"
Redirect all writes to stderr to the specified file instead. If the file name
is a plain '-', it is instead written to stdout. This option has no point when
you're using a shell with decent redirecting capabilities.
If this option is used several times, the last one will be used.
.IP "-t/--telnet-option <OPT=val>"
Pass options to the telnet protocol. Supported options are:
@@ -504,6 +539,24 @@ this is used on a http(s) server, the PUT command will be used.
Use the file name "-" (a single dash) to use stdin instead of a given file.
If this option is used several times, the last one will be used.
.IP "--trace <file>"
Enables a full trace dump of all incoming and outgoing data, including
descriptive information, to the given output file. Use "-" as filename to have
the output sent to stdout.
If this option is used several times, the last one will be used. (Added in
curl 7.9.7)
.IP "--trace-ascii <file>"
Enables a full trace dump of all incoming and outgoing data, including
descriptive information, to the given output file. Use "-" as filename to have
the output sent to stdout.
This is very similar to --trace, but leaves out the hex part and only shows
the ASCII part of the dump. It makes smaller output that might be easier to
read for untrained humans.
If this option is used several times, the last one will be used. (Added in
curl 7.9.7)
.IP "-u/--user <user:password>"
Specify user and password to use when fetching. See README.curl for detailed
examples of how to use this. If no password is specified, curl will
@@ -654,6 +707,12 @@ Start the date expression with a dash (-) to make it request for a document
that is older than the given date/time, default is a document that is newer
than the specified date/time.
If this option is used several times, the last one will be used.
.IP "-Z/--max-redirs <num>"
Set maximum number of redirection-followings allowed. If -L/--location is
used, this option can be used to prevent curl from following redirections "in
absurdum".
If this option is used several times, the last one will be used.
.IP "-3/--sslv3"
(HTTPS)
@@ -669,16 +728,6 @@ Make curl display progress information as a progress bar instead of the
default statistics.
If this option is used twice, the second will again disable the progress bar.
.IP "--crlf"
(FTP) Convert LF to CRLF in upload. Useful for MVS (OS/390).
If this option is used twice, the second will again disable crlf converting.
.IP "--stderr <file>"
Redirect all writes to stderr to the specified file instead. If the file name
is a plain '-', it is instead written to stdout. This option has no point when
you're using a shell with decent redirecting capabilities.
If this option is used several times, the last one will be used.
.SH FILES
.I ~/.curlrc
.RS

View File

@@ -5,10 +5,11 @@
AUTOMAKE_OPTIONS = foreign no-dependencies
EXTRA_DIST = README curlgtk.c sepheaders.c simple.c postit2.c \
win32sockets.c persistant.c ftpget.c Makefile.example \
persistant.c ftpget.c Makefile.example \
multithread.c getinmemory.c ftpupload.c httpput.c \
simplessl.c ftpgetresp.c http-post.c post-callback.c \
multi-app.c multi-double.c multi-single.c
multi-app.c multi-double.c multi-single.c multi-post.c \
fopen.c
all:
@echo "done"

222
docs/examples/fopen.c Normal file
View File

@@ -0,0 +1,222 @@
/*****************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* $Id$
*
* This example source code introduces an fopen()/fread()/fclose() emulation
* for URL reads. Using an approach similar to this, you could replace your
* program's fopen() with this url_fopen() and fread() with url_fread() and
* it should be possible to read remote streams instead of (only) local files.
*
* See the main() function at the bottom that shows a tiny app in action.
*
* This source code is a proof of concept. It will need further attention to
* become production-use useful and solid.
*
* This example requires libcurl 7.9.7 or later.
*/
#include <stdio.h>
#include <string.h>
#include <sys/time.h>
#include <curl/curl.h>
#include <curl/types.h>
#include <curl/easy.h>
struct data {
int type;
union {
CURL *curl;
FILE *file;
} handle;
/* TODO: We should perhaps document the biggest possible buffer chunk we can
get from libcurl in one single callback... */
char buffer[CURL_MAX_WRITE_SIZE];
char *readptr; /* read from here */
int bytes; /* bytes available from read pointer */
CURLMcode m; /* stored from a previous url_fread() */
};
typedef struct data URL_FILE;
/* we use a global one for convenience */
CURLM *multi_handle;
static
size_t write_callback(char *buffer,
size_t size,
size_t nitems,
void *userp)
{
URL_FILE *url = (URL_FILE *)userp;
size *= nitems;
memcpy(url->readptr, buffer, size);
url->readptr += size;
url->bytes += size;
return size;
}
URL_FILE *url_fopen(char *url, char *operation)
{
/* this code could check for URLs or types in the 'url' and
basicly use the real fopen() for standard files */
URL_FILE *file;
int still_running;
file = (URL_FILE *)malloc(sizeof(URL_FILE));
if(!file)
return NULL;
memset(file, 0, sizeof(URL_FILE));
file->type = 1; /* marked as URL, use 0 for plain file */
file->handle.curl = curl_easy_init();
curl_easy_setopt(file->handle.curl, CURLOPT_URL, url);
curl_easy_setopt(file->handle.curl, CURLOPT_FILE, file);
curl_easy_setopt(file->handle.curl, CURLOPT_VERBOSE, FALSE);
curl_easy_setopt(file->handle.curl, CURLOPT_WRITEFUNCTION, write_callback);
if(!multi_handle)
multi_handle = curl_multi_init();
curl_multi_add_handle(multi_handle, file->handle.curl);
while(CURLM_CALL_MULTI_PERFORM ==
curl_multi_perform(multi_handle, &still_running));
/* if still_running would be 0 now, we should return NULL */
return file;
}
void url_fclose(URL_FILE *file)
{
/* make sure the easy handle is not in the multi handle anymore */
curl_multi_remove_handle(multi_handle, file->handle.curl);
/* cleanup */
curl_easy_cleanup(file->handle.curl);
}
size_t url_fread(void *ptr, size_t size, size_t nmemb, URL_FILE *file)
{
fd_set fdread;
fd_set fdwrite;
fd_set fdexcep;
int maxfd;
struct timeval timeout;
int rc;
int still_running = 0;
if(!file->bytes) { /* no data available at this point */
file->readptr = file->buffer; /* reset read pointer */
if(CURLM_CALL_MULTI_PERFORM == file->m) {
while(CURLM_CALL_MULTI_PERFORM ==
curl_multi_perform(multi_handle, &still_running)) {
if(file->bytes) {
printf("(fread) WOAH! THis happened!\n");
break;
}
}
if(!still_running) {
printf("NO MORE RUNNING AROUND!\n");
return 0;
}
}
FD_ZERO(&fdread);
FD_ZERO(&fdwrite);
FD_ZERO(&fdexcep);
/* set a suitable timeout to fail on */
timeout.tv_sec = 500; /* 5 minutes */
timeout.tv_usec = 0;
/* get file descriptors from the transfers */
curl_multi_fdset(multi_handle, &fdread, &fdwrite, &fdexcep, &maxfd);
rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
switch(rc) {
case -1:
/* select error */
break;
case 0:
break;
default:
/* timeout or readable/writable sockets */
do {
file->m = curl_multi_perform(multi_handle, &still_running);
if(file->bytes)
/* we have received data, return that now */
break;
} while(CURLM_CALL_MULTI_PERFORM == file->m);
if(!still_running)
printf("NO MORE RUNNING AROUND!\n");
break;
}
}
else
printf("(fread) Skip network read\n");
if(file->bytes) {
/* data already available, return that */
int want = size * nmemb;
if(file->bytes < want)
want = file->bytes;
memcpy(ptr, file->readptr, want);
file->readptr += want;
file->bytes -= want;
printf("(fread) return %d bytes\n", want);
return want;
}
return 0; /* no data available to return */
}
int main(int argc, char *argv[])
{
URL_FILE *handle;
int nread;
char buffer[256];
handle = url_fopen("http://www.haxx.se", "r");
if(!handle) {
printf("couldn't url_fopen()\n");
}
do {
nread = url_fread(buffer, sizeof(buffer), 1, handle);
printf("We got: %d bytes\n", nread);
} while(nread);
url_fclose(handle);
return 0;
}

126
docs/examples/multi-post.c Normal file
View File

@@ -0,0 +1,126 @@
/*****************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* $Id$
*
* This is an example application source code using the multi interface
* to do a multipart formpost without "blocking".
*/
#include <stdio.h>
#include <string.h>
#include <sys/time.h>
#include <curl/curl.h>
int main(int argc, char *argv[])
{
CURL *curl;
CURLcode res;
CURLM *multi_handle;
int still_running;
struct HttpPost *formpost=NULL;
struct HttpPost *lastptr=NULL;
struct curl_slist *headerlist=NULL;
char buf[] = "Expect:";
/* Fill in the file upload field */
curl_formadd(&formpost,
&lastptr,
CURLFORM_COPYNAME, "sendfile",
CURLFORM_FILE, "postit2.c",
CURLFORM_END);
/* Fill in the filename field */
curl_formadd(&formpost,
&lastptr,
CURLFORM_COPYNAME, "filename",
CURLFORM_COPYCONTENTS, "postit2.c",
CURLFORM_END);
/* Fill in the submit field too, even if this is rarely needed */
curl_formadd(&formpost,
&lastptr,
CURLFORM_COPYNAME, "submit",
CURLFORM_COPYCONTENTS, "send",
CURLFORM_END);
curl = curl_easy_init();
multi_handle = curl_multi_init();
/* initalize custom header list (stating that Expect: 100-continue is not
wanted */
headerlist = curl_slist_append(headerlist, buf);
if(curl && multi_handle) {
int perform=0;
/* what URL that receives this POST */
curl_easy_setopt(curl, CURLOPT_URL,
"http://www.fillinyoururl.com/upload.cgi");
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerlist);
curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);
curl_multi_add_handle(multi_handle, curl);
while(CURLM_CALL_MULTI_PERFORM ==
curl_multi_perform(multi_handle, &still_running));
while(still_running) {
struct timeval timeout;
int rc; /* select() return code */
fd_set fdread;
fd_set fdwrite;
fd_set fdexcep;
int maxfd;
FD_ZERO(&fdread);
FD_ZERO(&fdwrite);
FD_ZERO(&fdexcep);
/* set a suitable timeout to play around with */
timeout.tv_sec = 1;
timeout.tv_usec = 0;
/* get file descriptors from the transfers */
curl_multi_fdset(multi_handle, &fdread, &fdwrite, &fdexcep, &maxfd);
rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
switch(rc) {
case -1:
/* select error */
break;
case 0:
printf("timeout!\n");
default:
/* timeout or readable/writable sockets */
printf("perform!\n");
while(CURLM_CALL_MULTI_PERFORM ==
curl_multi_perform(multi_handle, &still_running));
printf("running: %d!\n", still_running);
break;
}
}
curl_multi_cleanup(multi_handle);
/* always cleanup */
curl_easy_cleanup(curl);
/* then cleanup the formpost chain */
curl_formfree(formpost);
/* free slist */
curl_slist_free_all (headerlist);
}
return 0;
}

View File

@@ -1,49 +0,0 @@
/*
* Note: This is only required if you use curl 7.8 or lower, later
* versions provide an option to curl_global_init() that does the
* win32 initialization for you.
*/
/*
* These are example functions doing socket init that Windows
* require. If you don't use windows, you can safely ignore this crap.
*/
#include <windows.h>
void win32_cleanup(void)
{
WSACleanup();
}
int win32_init(void)
{
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD(1, 1);
err = WSAStartup(wVersionRequested, &wsaData);
if (err != 0)
/* Tell the user that we couldn't find a useable */
/* winsock.dll. */
return 1;
/* Confirm that the Windows Sockets DLL supports 1.1.*/
/* Note that if the DLL supports versions greater */
/* than 1.1 in addition to 1.1, it will still return */
/* 1.1 in wVersion since that is the version we */
/* requested. */
if ( LOBYTE( wsaData.wVersion ) != 1 ||
HIBYTE( wsaData.wVersion ) != 1 ) {
/* Tell the user that we couldn't find a useable */
/* winsock.dll. */
WSACleanup();
return 1;
}
return 0; /* 0 is ok */
}

View File

@@ -949,11 +949,11 @@ Security Considerations
.netrc is a pretty handy file/feature that allows you to login quickly and
automaticly to frequently visited sites. The file contains passwords in
clear text and is a real security risk. In some cases, your .netrc is also
stored in a home directory that is NFS mounter or used on another network
stored in a home directory that is NFS mounted or used on another network
based file system, so the clear text password will fly through your
network every time anyone reads that file!
To avoid this problem, don't use .netrc files and never store passwords as
To avoid this problem, don't use .netrc files and never store passwords in
plain text anywhere.
Clear Text Passwords

View File

@@ -2,7 +2,7 @@
.\" nroff -man [file]
.\" $Id$
.\"
.TH curl_easy_init 3 "31 Jan 2001" "libcurl 7.9.4" "libcurl Manual"
.TH curl_easy_init 3 "25 Apr 2002" "libcurl 7.9.7" "libcurl Manual"
.SH NAME
curl_easy_getinfo - Extract information from a curl session (added in 7.4)
.SH SYNOPSIS
@@ -38,7 +38,9 @@ CURLOPT_FILETIME option to \fIcurl_easy_setopt(3)\fP. (Added in 7.5)
.TP
.B CURLINFO_TOTAL_TIME
Pass a pointer to a double to receive the total transaction time in seconds
for the previous transfer.
for the previous transfer. This time does not include the connect time, so if
you want the complete operation time, you should add the
CURLINFO_CONNECT_TIME.
.TP
.B CURLINFO_NAMELOOKUP_TIME
Pass a pointer to a double to receive the time, in seconds, it took from the
@@ -60,6 +62,16 @@ start until the first byte is just about to be transfered. This includes
CURLINFO_PRETRANSFER_TIME and also the time the server needs to calculate
the result.
.TP
.B CURLINFO_REDIRECT_TIME
Pass a pointer to a double to receive the total time, in seconds, it took for
all redirection steps include name lookup, connect, pretransfer and transfer
before final transaction was started. CURLINFO_REDIRECT_TIME contains the
complete execution time for multiple redirections. (Added in 7.9.7)
.TP
.B CURLINFO_REDIRECT_COUNT
Pass a pointer to a long to receive the total number of redirections that were
actually followed. (Added in 7.9.7)
.TP
.B CURLINFO_SIZE_UPLOAD
Pass a pointer to a double to receive the total amount of bytes that were
uploaded.

View File

@@ -2,7 +2,7 @@
.\" nroff -man [file]
.\" $Id$
.\"
.TH curl_easy_setopt 3 "12 Apr 2002" "libcurl 7.9.6" "libcurl Manual"
.TH curl_easy_setopt 3 "28 May 2002" "libcurl 7.9.8" "libcurl Manual"
.SH NAME
curl_easy_setopt - Set curl easy-session options
.SH SYNOPSIS
@@ -36,7 +36,7 @@ The \fIhandle\fP is the return code from a \fIcurl_easy_init(3)\fP or
.SH OPTIONS
The options are listed in a sort of random order, but you'll figure it out!
.TP 0.4i
.B CURLOPT_FILE
.B CURLOPT_WRITEDATA
Data pointer to pass to the file write function. Note that if you specify the
\fICURLOPT_WRITEFUNCTION\fP, this is the pointer you'll get as input. If you
don't use a callback, you must pass a 'FILE *' as libcurl will pass this to
@@ -45,6 +45,8 @@ fwrite() when writing data.
\fBNOTE:\fP If you're using libcurl as a win32 DLL, you MUST use the
\fICURLOPT_WRITEFUNCTION\fP if you set this option or you will experience
crashes.
This option is also known with the older name \fBCURLOPT_FILE\fP.
.TP
.B CURLOPT_WRITEFUNCTION
Function pointer that should match the following prototype: \fBsize_t
@@ -60,15 +62,18 @@ Set the \fIstream\fP argument with the \fBCURLOPT_FILE\fP option.
\fBNOTE:\fP you will be passed as much data as possible in all invokes, but
you cannot possibly make any assumptions. It may be one byte, it may be
thousands.
thousands. The maximum amount of data that can be passed to the write callback
is defined in the curl.h header file: CURL_MAX_WRITE_SIZE.
.TP
.B CURLOPT_INFILE
.B CURLOPT_READDATA
Data pointer to pass to the file read function. Note that if you specify the
\fICURLOPT_READFUNCTION\fP, this is the pointer you'll get as input. If you
don't specify a read callback, this must be a valid FILE *.
\fBNOTE:\fP If you're using libcurl as a win32 DLL, you MUST use a
\fICURLOPT_READFUNCTION\fP if you set this option.
This option is also known with the older name \fBCURLOPT_INFILE\fP.
.TP
.B CURLOPT_READFUNCTION
Function pointer that should match the following prototype: \fBsize_t
@@ -166,16 +171,49 @@ will imply this option.
A non-zero parameter tells the library to just list the names of an ftp
directory, instead of doing a full directory listing that would include file
sizes, dates etc.
This causes an FTP NLST command to be sent. Beware that some FTP servers
list only files in their response to NLST; they do not include
subdirectories and symbolic links.
.TP
.B CURLOPT_FTPAPPEND
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.
.TP
.B CURLOPT_NETRC
A non-zero parameter tells the library to scan your \fI~/.netrc\fP file to
find user name and password for the remote site you are about to access. Only
machine name, user name and password is taken into account (init macros and
similar things aren't supported).
This parameter controls the preference of libcurl between using user names and
passwords from your \fI~/.netrc\fP file, relative to user names and passwords
in the URL supplied with \fICURLOPT_URL\fP.
\fBNote:\fP libcurl uses a user name (and supplied or prompted password)
supplied with \fICURLOPT_USERPWD\fP in preference to any of the options
controlled by this parameter.
Pass a long, set to one of the values described below.
.RS
.TP 5
.B CURL_NETRC_OPTIONAL
The use of your \fI~/.netrc\fP file is optional,
and information in the URL is to be preferred. The file will be scanned
with the host and user name (to find the password only) or with the host only,
to find the first user name and password after that \fImachine\fP,
which ever information is not specified in the URL.
Undefined values of the option will have this effect.
.TP
.B CURL_NETRC_IGNORED
The library will ignore the file and use only the information in the URL.
This is the default.
.TP
.B CURL_NETRC_REQUIRED
This value tells the library that use of the file is required,
to ignore the information in the URL,
and to search the file with the host only.
.RE
.TP
Only machine name, user name and password are taken into account
(init macros and similar things aren't supported).
\fBNote:\fP libcurl does not verify that the file has the correct properties
set (as the standard Unix ftp client does). It should only be readable by
@@ -293,6 +331,13 @@ want the transfer to start from.
Pass a pointer to a zero terminated string as parameter. It will be used to
set a cookie in the http request. The format of the string should be
[NAME]=[CONTENTS]; Where NAME is the cookie name.
If you need to set mulitple cookies, you need to set them all using a single
option and thus you need to concat them all in one single string. Set multiple
cookies in one string like this: "name1=content1; name2=content2;" etc.
Using this option multiple times will only make the latest string override the
previously ones.
.TP
.B CURLOPT_HTTPHEADER
Pass a pointer to a linked list of HTTP headers to pass to the server in your
@@ -428,8 +473,8 @@ TIMECOND_IFUNMODSINCE. This is a HTTP-only feature. (TBD)
.TP
.B CURLOPT_TIMEVALUE
Pass a long as parameter. This should be the time in seconds since 1 jan 1970,
and the time will be used as specified in CURLOPT_TIMECONDITION or if that
isn't used, it will be TIMECOND_IFMODSINCE by default.
and the time will be used in a condition as specified with
CURLOPT_TIMECONDITION.
.TP
.B CURLOPT_CUSTOMREQUEST
Pass a pointer to a zero terminated string as parameter. It will be user
@@ -469,12 +514,20 @@ argument in the progress callback set with \fICURLOPT_PROGRESSFUNCTION\fP.
.B CURLOPT_SSL_VERIFYPEER
Pass a long that is set to a non-zero value to make curl verify the peer's
certificate. The certificate to verify against must be specified with the
CURLOPT_CAINFO option. (Added in 7.4.2)
CURLOPT_CAINFO option (Added in 7.4.2) or a certificate directory must be specified
with the CURLOPT_CAPATH option (Added in 7.9.8).
.TP
.B CURLOPT_CAINFO
Pass a char * to a zero terminated file naming holding the certificate to
verify the peer with. This only makes sense when used in combination with the
CURLOPT_SSL_VERIFYPEER option. (Added in 7.4.2)
Pass a char * to a zero terminated string naming a file holding one or more
certificates to verify the peer with. This only makes sense when used in
combination with the CURLOPT_SSL_VERIFYPEER option. (Added in 7.4.2)
.TP
.B CURLOPT_CAPATH
Pass a char * to a zero terminated string naming a directory holding multiple CA
certificates to verify the peer with. The certificate directory must be prepared using
the openssl c_rehash utility. This only makes sense when used in combination with the
CURLOPT_SSL_VERIFYPEER option. The CAPATH function apparently does not work in Windows
due to some limitation in openssl. (Added in 7.9.8)
.TP
.B CURLOPT_PASSWDFUNCTION
Pass a pointer to a \fIcurl_passwd_callback\fP function that will be called

View File

@@ -2,13 +2,13 @@
.\" nroff -man [file]
.\" $Id$
.\"
.TH curl_formadd 3 "1 Match 2002" "libcurl 7.9.1" "libcurl Manual"
.TH curl_formadd 3 "21 May 2002" "libcurl 7.9.8" "libcurl Manual"
.SH NAME
curl_formadd - add a section to a multipart/formdata HTTP POST
.SH SYNOPSIS
.B #include <curl/curl.h>
.sp
.BI "int curl_formadd(struct HttpPost ** " firstitem,
.BI "CURLFORMcode curl_formadd(struct HttpPost ** " firstitem,
.BI "struct HttpPost ** " lastitem, " ...);"
.ad
.SH DESCRIPTION
@@ -83,7 +83,9 @@ you call \fIcurl_form_free\fP and \fIcurl_easy_cleanup\fP.
See example below.
.SH RETURN VALUE
Returns non-zero if an error occurs.
0 means everything was ok, non-zero means an error occurred as
.I <curl/curl.h>
defines.
.SH EXAMPLE
.nf

View File

@@ -1,6 +1,6 @@
.\" $Id$
.\"
.TH curl_multi_fdset 3 "1 March 2002" "libcurl 7.9.5" "libcurl Manual"
.TH curl_multi_fdset 3 "3 May 2002" "libcurl 7.9.5" "libcurl Manual"
.SH NAME
curl_multi_fdset - add an easy handle to a multi session
.SH SYNOPSIS
@@ -17,6 +17,10 @@ This function extracts file descriptor information from a given multi_handle.
libcurl returns its fd_set sets. The application can use these to select() or
poll() on. The curl_multi_perform() function should be called as soon as one
of them are ready to be read from or written to.
NOTE that once this call is made, you must not remove the sets you point to,
as libcurl will need to be able to read them. It needs them after select()
calls, to know if certain sockets are readable or writable.
.SH RETURN VALUE
CURLMcode type, general libcurl multi interface error code.
.SH "SEE ALSO"

View File

@@ -65,6 +65,11 @@ struct curl_httppost {
long namelength; /* length of name length */
char *contents; /* pointer to allocated data contents */
long contentslength; /* length of contents field */
/* CMC: Added support for buffer uploads */
char *buffer; /* pointer to allocated buffer contents */
long bufferlength; /* length of buffer field */
char *contenttype; /* Content-Type */
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
@@ -76,6 +81,11 @@ struct curl_httppost {
do not free in formfree */
#define HTTPPOST_PTRCONTENTS (1<<3) /* contents is only stored pointer
do not free in formfree */
/* CMC: Added support for buffer uploads */
#define HTTPPOST_BUFFER (1<<4) /* upload file from buffer */
#define HTTPPOST_PTRBUFFER (1<<5) /* upload file from pointer contents */
char *showfilename; /* The file name to show. If not set, the actual
file name will be used (if this is a file part) */
};
@@ -86,6 +96,8 @@ typedef int (*curl_progress_callback)(void *clientp,
double ultotal,
double ulnow);
#define CURL_MAX_WRITE_SIZE 20480
typedef size_t (*curl_write_callback)(char *buffer,
size_t size,
size_t nitems,
@@ -377,7 +389,11 @@ typedef enum {
CINIT(FTPLISTONLY, LONG, 48), /* Use NLST when listing ftp dir */
CINIT(FTPAPPEND, LONG, 50), /* Append instead of overwrite on upload! */
CINIT(NETRC, LONG, 51), /* read user+password from .netrc */
/* Specify whether to read the user+password from the .netrc or the URL.
* This must be one of the CURL_NETRC_* enums below. */
CINIT(NETRC, LONG, 51),
CINIT(FOLLOWLOCATION, LONG, 52), /* use Location: Luke! */
/* This FTPASCII name is now obsolete, to be removed, use the TRANSFERTEXT
@@ -536,9 +552,21 @@ typedef enum {
/* set the data for the debug function */
CINIT(DEBUGDATA, OBJECTPOINT, 95),
/* mark this as start of a cookie session */
CINIT(COOKIESESSION, LONG, 96),
/* The CApath directory used to validate the peer certificate
this option is used only if SSL_VERIFYPEER is true */
CINIT(CAPATH, OBJECTPOINT, 97),
CURLOPT_LASTENTRY /* the last unusued */
} CURLoption;
/* two convenient "aliases" that follow the name scheme better */
#define CURLOPT_WRITEDATA CURLOPT_FILE
#define CURLOPT_READDATA CURLOPT_INFILE
/* These enums are for use with the CURLOPT_HTTP_VERSION option. */
enum {
CURL_HTTP_VERSION_NONE, /* setting this means we don't care, and that we'd
@@ -550,6 +578,18 @@ enum {
CURL_HTTP_VERSION_LAST /* *ILLEGAL* http version */
};
/* These enums are for use with the CURLOPT_NETRC option. */
enum CURL_NETRC_OPTION {
CURL_NETRC_IGNORED, /* The .netrc will never be read.
* This is the default. */
CURL_NETRC_OPTIONAL, /* A user:password in the URL will be preferred
* to one in the .netrc. */
CURL_NETRC_REQUIRED, /* A user:password in the URL will be ignored.
* Unless one is set programmatically, the .netrc
* will be queried. */
CURL_NETRC_LAST
};
enum {
CURL_SSLVERSION_DEFAULT,
CURL_SSLVERSION_TLSv1,
@@ -561,15 +601,26 @@ enum {
typedef enum {
TIMECOND_NONE,
CURL_TIMECOND_NONE,
TIMECOND_IFMODSINCE,
TIMECOND_IFUNMODSINCE,
TIMECOND_LASTMOD,
CURL_TIMECOND_IFMODSINCE,
CURL_TIMECOND_IFUNMODSINCE,
CURL_TIMECOND_LASTMOD,
TIMECOND_LAST
CURL_TIMECOND_LAST
} curl_TimeCond;
/* for backwards compatibility */
#ifndef TIMECOND_IFMODSINCE
#define TIMECOND_IFMODSINCE CURL_TIMECOND_IFMODSINCE
#endif
#ifndef TIMECOND_IFUNMODSINCE
#define TIMECOND_IFUNMODSINCE CURL_TIMECOND_IFUNMODSINCE
#endif
#ifndef TIMECOND_LASTMOD
#define TIMECOND_LASTMOD CURL_TIMECOND_LASTMOD
#endif
#ifdef __BEOS__
#include <support/SupportDefs.h>
#endif
@@ -617,6 +668,11 @@ typedef enum {
CFINIT(ARRAY),
CFINIT(OBSOLETE),
CFINIT(FILE),
CFINIT(BUFFER),
CFINIT(BUFFERPTR),
CFINIT(BUFFERLENGTH),
CFINIT(CONTENTTYPE),
CFINIT(CONTENTHEADER),
CFINIT(FILENAME),
@@ -635,7 +691,35 @@ struct curl_forms {
};
/* use this for multipart formpost building */
int curl_formadd(struct curl_httppost **httppost,
/* Returns code for curl_formadd()
*
* Returns:
* CURL_FORMADD_OK on success
* CURL_FORMADD_MEMORY if the FormInfo allocation fails
* CURL_FORMADD_OPTION_TWICE if one option is given twice for one Form
* CURL_FORMADD_NULL if a null pointer was given for a char
* CURL_FORMADD_MEMORY if the allocation of a FormInfo struct failed
* CURL_FORMADD_UNKNOWN_OPTION if an unknown option was used
* CURL_FORMADD_INCOMPLETE if the some FormInfo is not complete (or error)
* CURL_FORMADD_MEMORY if a HttpPost struct cannot be allocated
* CURL_FORMADD_MEMORY if some allocation for string copying failed.
* CURL_FORMADD_ILLEGAL_ARRAY if an illegal option is used in an array
*
***************************************************************************/
typedef enum {
CURL_FORMADD_OK, /* first, no error */
CURL_FORMADD_MEMORY,
CURL_FORMADD_OPTION_TWICE,
CURL_FORMADD_NULL,
CURL_FORMADD_UNKNOWN_OPTION,
CURL_FORMADD_INCOMPLETE,
CURL_FORMADD_ILLEGAL_ARRAY,
CURL_FORMADD_LAST /* last */
} CURLFORMcode;
CURLFORMcode curl_formadd(struct curl_httppost **httppost,
struct curl_httppost **last_post,
...);
@@ -663,8 +747,8 @@ CURLcode curl_global_init(long flags);
void curl_global_cleanup(void);
/* This is the version number */
#define LIBCURL_VERSION "7.9.6"
#define LIBCURL_VERSION_NUM 0x070906
#define LIBCURL_VERSION "7.9.8"
#define LIBCURL_VERSION_NUM 0x070908
/* linked-list structure for the CURLOPT_QUOTE option (and other) */
struct curl_slist {
@@ -718,9 +802,12 @@ typedef enum {
CURLINFO_CONTENT_TYPE = CURLINFO_STRING + 18,
CURLINFO_REDIRECT_TIME = CURLINFO_DOUBLE + 19,
CURLINFO_REDIRECT_COUNT = CURLINFO_LONG + 20,
/* Fill in new entries here! */
CURLINFO_LASTONE = 19
CURLINFO_LASTONE = 21
} CURLINFO;
/* unfortunately, the easy.h and multi.h include files need options and info

View File

@@ -61,7 +61,7 @@ libcurl.a: $(libcurl_a_OBJECTS) $(libcurl_a_DEPENDENCIES)
libcurl.dll libcurldll.a: libcurl.a libcurl.def dllinit.o
-@erase $@
dllwrap --dllname $@ --output-lib libcurldll.a --export-all --def libcurl.def $(libcurl_a_LIBRARIES) dllinit.o -L$(OPENSSL_PATH)/out $(DLL_LIBS) -lwsock32 -lws2_32
dllwrap --dllname $@ --output-lib libcurldll.a --export-all --def libcurl.def $(libcurl_a_LIBRARIES) dllinit.o -L$(OPENSSL_PATH)/out $(DLL_LIBS) -lwsock32 -lws2_32 -lwinmm
$(STRIP) $@
# remove the last line above to keep debug info

View File

@@ -198,7 +198,8 @@ X_OBJS= \
$(DIROBJ)\strtok.obj \
$(DIROBJ)\connect.obj \
$(DIROBJ)\hash.obj \
$(DIROBJ)\llist.obj
$(DIROBJ)\llist.obj \
$(DIROBJ)\multi.obj
all : $(TARGET)

View File

@@ -22,7 +22,7 @@
*
* $Id$
*****************************************************************************/
#ifndef CURL_DISABLE_TELNET
/*
* Telnet option defines. Add more here if in need.
*/
@@ -97,5 +97,5 @@ static const char *telnetcmds[]=
#define TELCMD_OK(x) ( ((unsigned int)(x) >= TELCMD_MINIMUM) && \
((unsigned int)(x) <= TELCMD_MAXIMUM) )
#define TELCMD(x) telnetcmds[(x)-TELCMD_MINIMUM]
#endif
#endif

View File

@@ -366,3 +366,6 @@
#define HAVE_MEMORY_H 1
#define HAVE_FIONBIO 1
/* Define if you have the `sigsetjmp' function. */
#define HAVE_SIGSETJMP 1

View File

@@ -179,6 +179,9 @@
/* Define if you have the RAND_screen function when using SSL */
#define HAVE_RAND_SCREEN 1
/* Define if you have the `RAND_status' function. */
#define HAVE_RAND_STATUS 1
/* Define this to if in_addr_t is not an available typedefed type */
#define in_addr_t unsigned long

View File

@@ -185,7 +185,6 @@ int waitconnect(int sockfd, /* socket */
return 0;
}
#ifndef ENABLE_IPV6
static CURLcode bindlocal(struct connectdata *conn,
int sockfd)
{
@@ -207,24 +206,30 @@ static CURLcode bindlocal(struct connectdata *conn,
*************************************************************/
if (strlen(data->set.device)<255) {
struct sockaddr_in sa;
struct hostent *h=NULL;
char *hostdataptr=NULL;
Curl_addrinfo *h=NULL;
size_t size;
char myhost[256] = "";
in_addr_t in;
if(Curl_if2ip(data->set.device, myhost, sizeof(myhost))) {
h = Curl_resolv(data, myhost, 0, &hostdataptr);
/*
* We now have the numerical IPv4-style x.y.z.w in the 'myhost' buffer
*/
h = Curl_resolv(data, myhost, 0);
}
else {
if(strlen(data->set.device)>1) {
h = Curl_resolv(data, data->set.device, 0, &hostdataptr);
}
/*
* This was not an interface, resolve the name as a host name
* or IP number
*/
h = Curl_resolv(data, data->set.device, 0);
if(h) {
/* we know data->set.device is shorter than the myhost array */
strcpy(myhost, data->set.device);
}
}
}
if(! *myhost) {
/* need to fix this
@@ -243,10 +248,13 @@ static CURLcode bindlocal(struct connectdata *conn,
if ( h ) {
memset((char *)&sa, 0, sizeof(sa));
memcpy((char *)&sa.sin_addr,
h->h_addr,
h->h_length);
#ifdef ENABLE_IPV6
memcpy((char *)&sa.sin_addr, h->ai_addr, h->ai_addrlen);
sa.sin_family = h->ai_family;
#else
memcpy((char *)&sa.sin_addr, h->h_addr, h->h_length);
sa.sin_family = AF_INET;
#endif
sa.sin_addr.s_addr = in;
sa.sin_port = 0; /* get any port */
@@ -314,7 +322,7 @@ static CURLcode bindlocal(struct connectdata *conn,
return CURLE_HTTP_PORT_FAILED;
}
#endif /* end of ipv4-specific section */
static
int socketerror(int sockfd)
@@ -345,6 +353,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */
int rc;
int sockfd=-1;
int aliasindex=0;
char *hostname;
struct timeval after;
struct timeval before = Curl_tvnow();
@@ -385,8 +394,8 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */
}
}
infof(data, "About to connect() to %s:%d\n",
data->change.proxy?conn->proxyhost:conn->hostname, port);
hostname = data->change.proxy?conn->proxyhost:conn->hostname;
infof(data, "About to connect() to %s:%d\n", hostname, port);
#ifdef ENABLE_IPV6
/*
@@ -401,6 +410,14 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */
if (sockfd < 0)
continue;
if(conn->data->set.device) {
/* user selected to bind the outgoing socket to a specified "device"
before doing connect */
CURLcode res = bindlocal(conn, sockfd);
if(res)
return res;
}
/* set socket non-blocking */
Curl_nonblock(sockfd, TRUE);
@@ -427,7 +444,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */
case ECONNREFUSED: /* no one listening */
default:
/* unknown error, fallthrough and try another address! */
failf(data, "Failed to connect: %d", error);
failf(data, "Failed connect to %s: %d", hostname, error);
break;
}
}
@@ -440,6 +457,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */
/* we are connected, awesome! */
break;
}
failf(data, "socket error: %d", err);
/* we are _not_ connected, it was a false alert, continue please */
}
@@ -457,10 +475,8 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */
before = after;
continue;
}
if (sockfd < 0) {
failf(data, "connect() failed");
if (sockfd < 0)
return CURLE_COULDNT_CONNECT;
}
/* leave the socket in non-blocking mode */
@@ -532,8 +548,8 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */
break;
default:
/* unknown error, fallthrough and try another address! */
failf(data, "Failed to connect to IP number %d: %d",
aliasindex+1, error);
failf(data, "Failed to connect to %s IP number %d: %d",
hostname, aliasindex+1, error);
break;
}
}
@@ -565,7 +581,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */
/* no good connect was made */
sclose(sockfd);
*sockconn = -1;
failf(data, "Couldn't connect to host");
failf(data, "Connect failed");
return CURLE_COULDNT_CONNECT;
}

View File

@@ -79,6 +79,8 @@ Example set of cookies:
#include "setup.h"
#ifndef CURL_DISABLE_HTTP
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
@@ -93,6 +95,21 @@ Example set of cookies:
#include "memdebug.h"
#endif
static void
free_cookiemess(struct Cookie *co)
{
if(co->domain)
free(co->domain);
if(co->path)
free(co->path);
if(co->name)
free(co->name);
if(co->value)
free(co->value);
free(co);
}
/****************************************************************************
*
* Curl_cookie_add()
@@ -326,22 +343,19 @@ Curl_cookie_add(struct CookieInfo *c,
if(7 != fields) {
/* we did not find the sufficient number of fields to recognize this
as a valid line, abort and go home */
if(co->domain)
free(co->domain);
if(co->path)
free(co->path);
if(co->name)
free(co->name);
if(co->value)
free(co->value);
free(co);
free_cookiemess(co);
return NULL;
}
}
if(!c->running && /* read from a file */
c->newsession && /* clean session cookies */
!co->expires) { /* this is a session cookie since it doesn't expire! */
free_cookiemess(co);
return NULL;
}
co->livecookie = c->running;
/* now, we have parsed the incoming line, we must now check if this
@@ -462,8 +476,12 @@ Curl_cookie_add(struct CookieInfo *c,
* Inits a cookie struct to read data from a local file. This is always
* called before any cookies are set. File may be NULL.
*
* If 'newsession' is TRUE, discard all "session cookies" on read from file.
*
****************************************************************************/
struct CookieInfo *Curl_cookie_init(char *file, struct CookieInfo *inc)
struct CookieInfo *Curl_cookie_init(char *file,
struct CookieInfo *inc,
bool newsession)
{
char line[MAX_COOKIE_LINE];
struct CookieInfo *c;
@@ -491,6 +509,8 @@ struct CookieInfo *Curl_cookie_init(char *file, struct CookieInfo *inc)
else
fp = file?fopen(file, "r"):NULL;
c->newsession = newsession; /* new session? */
if(fp) {
char *lineptr;
bool headerline;
@@ -743,6 +763,8 @@ int main(int argc, char **argv)
#endif
#endif /* CURL_DISABLE_HTTP */
/*
* local variables:
* eval: (load-file "../curl-mode.el")

View File

@@ -58,6 +58,7 @@ struct CookieInfo {
char *filename; /* file we read from/write to */
bool running; /* state info, for cookie adding information */
long numcookies; /* number of cookies in the "jar" */
bool newsession; /* new session, discard session cookies on load */
};
/* This is the maximum line length we accept for a cookie line */
@@ -75,7 +76,7 @@ struct CookieInfo {
struct Cookie *Curl_cookie_add(struct CookieInfo *, bool header, char *line,
char *domain);
struct CookieInfo *Curl_cookie_init(char *, struct CookieInfo *);
struct CookieInfo *Curl_cookie_init(char *, struct CookieInfo *, bool);
struct Cookie *Curl_cookie_getlist(struct CookieInfo *, char *, char *, bool);
void Curl_cookie_freelist(struct Cookie *);
void Curl_cookie_cleanup(struct CookieInfo *);

View File

@@ -54,7 +54,7 @@ BSC32=bscmake.exe
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
# ADD LINK32 kernel32.lib ws2_32.lib /nologo /dll /map /debug /machine:I386 /out:"Release/libcurl.dll"
# ADD LINK32 kernel32.lib ws2_32.lib winmm.lib /nologo /dll /map /debug /machine:I386 /out:"Release/libcurl.dll"
!ELSEIF "$(CFG)" == "curllib - Win32 Debug"
@@ -81,7 +81,7 @@ BSC32=bscmake.exe
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
# ADD LINK32 kernel32.lib ws2_32.lib /nologo /dll /incremental:no /map /debug /machine:I386 /out:"Debug/libcurl.dll" /pdbtype:sept
# ADD LINK32 kernel32.lib ws2_32.lib winmm.lib /nologo /dll /incremental:no /map /debug /machine:I386 /out:"Debug/libcurl.dll" /pdbtype:sept
# SUBTRACT LINK32 /nodefaultlib
!ENDIF

View File

@@ -23,7 +23,8 @@
*
* $Id$
*****************************************************************************/
#ifndef CURL_DISABLE_DICT
CURLcode Curl_dict(struct connectdata *conn);
CURLcode Curl_dict_done(struct connectdata *conn);
#endif
#endif

View File

@@ -238,7 +238,7 @@ CURLcode curl_easy_perform(CURL *curl)
data->hostcache = Curl_global_host_cache_get();
}
else {
data->hostcache = curl_hash_alloc(7, Curl_freeaddrinfo);
data->hostcache = Curl_hash_alloc(7, Curl_freeaddrinfo);
}
}
@@ -249,7 +249,7 @@ void curl_easy_cleanup(CURL *curl)
{
struct SessionHandle *data = (struct SessionHandle *)curl;
if (!Curl_global_host_cache_use(data)) {
curl_hash_destroy(data->hostcache);
Curl_hash_destroy(data->hostcache);
}
Curl_close(data);
}
@@ -312,7 +312,8 @@ CURL *curl_easy_duphandle(CURL *incurl)
/* If cookies are enabled in the parent handle, we enable them
in the clone as well! */
outcurl->cookies = Curl_cookie_init(data->cookies->filename,
outcurl->cookies);
outcurl->cookies,
data->set.cookiesession);
/* duplicate all values in 'change' */
if(data->change.url) {

View File

@@ -23,6 +23,7 @@
#include "setup.h"
#ifndef CURL_DISABLE_FILE
/* -- WIN32 approved -- */
#include <stdio.h>
#include <string.h>
@@ -140,7 +141,7 @@ CURLcode Curl_file(struct connectdata *conn)
*/
CURLcode res = CURLE_OK;
struct stat statbuf;
ssize_t expected_size=-1;
double expected_size=-1;
ssize_t nread;
struct SessionHandle *data = conn->data;
char *buf = data->state.buffer;
@@ -155,7 +156,7 @@ CURLcode Curl_file(struct connectdata *conn)
/*VMS?? -- This only works reliable for STREAMLF files */
if( -1 != fstat(fd, &statbuf)) {
/* we could stat it, then read out the size */
expected_size = statbuf.st_size;
expected_size = (double)statbuf.st_size;
}
/* The following is a shortcut implementation of file reading
@@ -204,3 +205,4 @@ CURLcode Curl_file(struct connectdata *conn)
* vim600: fdm=marker
* vim: et sw=2 ts=2 sts=2 tw=78
*/
#endif

View File

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

View File

@@ -109,6 +109,8 @@ Content-Disposition: form-data; name="FILECONTENT"
#include "setup.h"
#ifndef CURL_DISABLE_HTTP
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -398,6 +400,10 @@ int curl_formparse(char *input,
static struct curl_httppost *
AddHttpPost(char * name, long namelength,
char * value, long contentslength,
/* CMC: Added support for buffer uploads */
char * buffer, long bufferlength,
char *contenttype,
long flags,
struct curl_slist* contentHeader,
@@ -414,6 +420,11 @@ AddHttpPost(char * name, long namelength,
post->namelength = name?(namelength?namelength:(long)strlen(name)):0;
post->contents = value;
post->contentslength = contentslength;
/* CMC: Added support for buffer uploads */
post->buffer = buffer;
post->bufferlength = bufferlength;
post->contenttype = contenttype;
post->contentheader = contentHeader;
post->showfilename = showfilename;
@@ -602,39 +613,26 @@ static int AllocAndCopy (char **buffer, int buffer_length)
* CURLFORM_FILE, "filename1", CURLFORM_FILE, "filename2", CURLFORM_END);
*
* Returns:
* FORMADD_OK on success
* FORMADD_MEMORY if the FormInfo allocation fails
* FORMADD_OPTION_TWICE if one option is given twice for one Form
* FORMADD_NULL if a null pointer was given for a char
* FORMADD_MEMORY if the allocation of a FormInfo struct failed
* FORMADD_UNKNOWN_OPTION if an unknown option was used
* FORMADD_INCOMPLETE if the some FormInfo is not complete (or an error)
* FORMADD_MEMORY if a HttpPost struct cannot be allocated
* FORMADD_MEMORY if some allocation for string copying failed.
* FORMADD_ILLEGAL_ARRAY if an illegal option is used in an array
* CURL_FORMADD_OK on success
* CURL_FORMADD_MEMORY if the FormInfo allocation fails
* CURL_FORMADD_OPTION_TWICE if one option is given twice for one Form
* CURL_FORMADD_NULL if a null pointer was given for a char
* CURL_FORMADD_MEMORY if the allocation of a FormInfo struct failed
* CURL_FORMADD_UNKNOWN_OPTION if an unknown option was used
* CURL_FORMADD_INCOMPLETE if the some FormInfo is not complete (or an error)
* CURL_FORMADD_MEMORY if a HttpPost struct cannot be allocated
* CURL_FORMADD_MEMORY if some allocation for string copying failed.
* CURL_FORMADD_ILLEGAL_ARRAY if an illegal option is used in an array
*
***************************************************************************/
typedef enum {
FORMADD_OK, /* first, no error */
FORMADD_MEMORY,
FORMADD_OPTION_TWICE,
FORMADD_NULL,
FORMADD_UNKNOWN_OPTION,
FORMADD_INCOMPLETE,
FORMADD_ILLEGAL_ARRAY,
FORMADD_LAST /* last */
} FORMcode;
static
FORMcode FormAdd(struct curl_httppost **httppost,
CURLFORMcode FormAdd(struct curl_httppost **httppost,
struct curl_httppost **last_post,
va_list params)
{
FormInfo *first_form, *current_form, *form;
FORMcode return_value = FORMADD_OK;
CURLFORMcode return_value = CURL_FORMADD_OK;
const char *prevtype = NULL;
struct curl_httppost *post = NULL;
CURLformoption option;
@@ -655,7 +653,7 @@ FORMcode FormAdd(struct curl_httppost **httppost,
current_form = first_form;
}
else
return FORMADD_MEMORY;
return CURL_FORMADD_MEMORY;
/*
* Loop through all the options set.
@@ -663,7 +661,7 @@ FORMcode FormAdd(struct curl_httppost **httppost,
while (1) {
/* break if we have an error to report */
if (return_value != FORMADD_OK)
if (return_value != CURL_FORMADD_OK)
break;
/* first see if we have more parts of the array param */
@@ -690,13 +688,13 @@ FORMcode FormAdd(struct curl_httppost **httppost,
case CURLFORM_ARRAY:
if(array_state)
/* we don't support an array from within an array */
return_value = FORMADD_ILLEGAL_ARRAY;
return_value = CURL_FORMADD_ILLEGAL_ARRAY;
else {
forms = va_arg(params, struct curl_forms *);
if (forms)
array_state = TRUE;
else
return_value = FORMADD_NULL;
return_value = CURL_FORMADD_NULL;
}
break;
@@ -707,19 +705,19 @@ FORMcode FormAdd(struct curl_httppost **httppost,
current_form->flags |= HTTPPOST_PTRNAME; /* fall through */
case CURLFORM_COPYNAME:
if (current_form->name)
return_value = FORMADD_OPTION_TWICE;
return_value = CURL_FORMADD_OPTION_TWICE;
else {
char *name = array_state?
array_value:va_arg(params, char *);
if (name)
current_form->name = name; /* store for the moment */
else
return_value = FORMADD_NULL;
return_value = CURL_FORMADD_NULL;
}
break;
case CURLFORM_NAMELENGTH:
if (current_form->namelength)
return_value = FORMADD_OPTION_TWICE;
return_value = CURL_FORMADD_OPTION_TWICE;
else
current_form->namelength =
array_state?(long)array_value:va_arg(params, long);
@@ -732,19 +730,19 @@ FORMcode FormAdd(struct curl_httppost **httppost,
current_form->flags |= HTTPPOST_PTRCONTENTS; /* fall through */
case CURLFORM_COPYCONTENTS:
if (current_form->value)
return_value = FORMADD_OPTION_TWICE;
return_value = CURL_FORMADD_OPTION_TWICE;
else {
char *value =
array_state?array_value:va_arg(params, char *);
if (value)
current_form->value = value; /* store for the moment */
else
return_value = FORMADD_NULL;
return_value = CURL_FORMADD_NULL;
}
break;
case CURLFORM_CONTENTSLENGTH:
if (current_form->contentslength)
return_value = FORMADD_OPTION_TWICE;
return_value = CURL_FORMADD_OPTION_TWICE;
else
current_form->contentslength =
array_state?(long)array_value:va_arg(params, long);
@@ -753,7 +751,7 @@ FORMcode FormAdd(struct curl_httppost **httppost,
/* Get contents from a given file name */
case CURLFORM_FILECONTENT:
if (current_form->flags != 0)
return_value = FORMADD_OPTION_TWICE;
return_value = CURL_FORMADD_OPTION_TWICE;
else {
char *filename = array_state?
array_value:va_arg(params, char *);
@@ -762,7 +760,7 @@ FORMcode FormAdd(struct curl_httppost **httppost,
current_form->flags |= HTTPPOST_READFILE;
}
else
return_value = FORMADD_NULL;
return_value = CURL_FORMADD_NULL;
}
break;
@@ -777,23 +775,77 @@ FORMcode FormAdd(struct curl_httppost **httppost,
if (filename) {
if (!(current_form = AddFormInfo(strdup(filename),
NULL, current_form)))
return_value = FORMADD_MEMORY;
return_value = CURL_FORMADD_MEMORY;
}
else
return_value = FORMADD_NULL;
return_value = CURL_FORMADD_NULL;
}
else
return_value = FORMADD_OPTION_TWICE;
return_value = CURL_FORMADD_OPTION_TWICE;
}
else {
if (filename)
current_form->value = strdup(filename);
else
return_value = FORMADD_NULL;
return_value = CURL_FORMADD_NULL;
current_form->flags |= HTTPPOST_FILENAME;
}
break;
}
/* CMC: Added support for buffer uploads */
case CURLFORM_BUFFER:
{
char *filename = array_state?array_value:
va_arg(params, char *);
if (current_form->value) {
if (current_form->flags & HTTPPOST_BUFFER) {
if (filename) {
if (!(current_form = AddFormInfo(strdup(filename),
NULL, current_form)))
return_value = CURL_FORMADD_MEMORY;
}
else
return_value = CURL_FORMADD_NULL;
}
else
return_value = CURL_FORMADD_OPTION_TWICE;
}
else {
if (filename)
current_form->value = strdup(filename);
else
return_value = CURL_FORMADD_NULL;
current_form->flags |= HTTPPOST_BUFFER;
}
break;
}
/* CMC: Added support for buffer uploads */
case CURLFORM_BUFFERPTR:
current_form->flags |= HTTPPOST_PTRBUFFER;
if (current_form->buffer)
return_value = CURL_FORMADD_OPTION_TWICE;
else {
char *buffer =
array_state?array_value:va_arg(params, char *);
if (buffer)
current_form->buffer = buffer; /* store for the moment */
else
return_value = CURL_FORMADD_NULL;
}
break;
/* CMC: Added support for buffer uploads */
case CURLFORM_BUFFERLENGTH:
if (current_form->bufferlength)
return_value = CURL_FORMADD_OPTION_TWICE;
else
current_form->bufferlength =
array_state?(long)array_value:va_arg(params, long);
break;
case CURLFORM_CONTENTTYPE:
{
char *contenttype =
@@ -804,19 +856,19 @@ FORMcode FormAdd(struct curl_httppost **httppost,
if (!(current_form = AddFormInfo(NULL,
strdup(contenttype),
current_form)))
return_value = FORMADD_MEMORY;
return_value = CURL_FORMADD_MEMORY;
}
else
return_value = FORMADD_NULL;
return_value = CURL_FORMADD_NULL;
}
else
return_value = FORMADD_OPTION_TWICE;
return_value = CURL_FORMADD_OPTION_TWICE;
}
else {
if (contenttype)
current_form->contenttype = strdup(contenttype);
else
return_value = FORMADD_NULL;
return_value = CURL_FORMADD_NULL;
}
break;
}
@@ -829,7 +881,7 @@ FORMcode FormAdd(struct curl_httppost **httppost,
va_arg(params, struct curl_slist*);
if( current_form->contentheader )
return_value = FORMADD_OPTION_TWICE;
return_value = CURL_FORMADD_OPTION_TWICE;
else
current_form->contentheader = list;
@@ -840,17 +892,17 @@ FORMcode FormAdd(struct curl_httppost **httppost,
char *filename = array_state?array_value:
va_arg(params, char *);
if( current_form->showfilename )
return_value = FORMADD_OPTION_TWICE;
return_value = CURL_FORMADD_OPTION_TWICE;
else
current_form->showfilename = strdup(filename);
break;
}
default:
return_value = FORMADD_UNKNOWN_OPTION;
return_value = CURL_FORMADD_UNKNOWN_OPTION;
}
}
if(FORMADD_OK == return_value) {
if(CURL_FORMADD_OK == return_value) {
/* go through the list, check for copleteness and if everything is
* alright add the HttpPost item otherwise set return_value accordingly */
@@ -863,14 +915,21 @@ FORMcode FormAdd(struct curl_httppost **httppost,
(form->flags & HTTPPOST_FILENAME) ) ||
( (form->flags & HTTPPOST_FILENAME) &&
(form->flags & HTTPPOST_PTRCONTENTS) ) ||
/* CMC: Added support for buffer uploads */
( (!form->buffer) &&
(form->flags & HTTPPOST_BUFFER) &&
(form->flags & HTTPPOST_PTRBUFFER) ) ||
( (form->flags & HTTPPOST_READFILE) &&
(form->flags & HTTPPOST_PTRCONTENTS) )
) {
return_value = FORMADD_INCOMPLETE;
return_value = CURL_FORMADD_INCOMPLETE;
break;
}
else {
if ( (form->flags & HTTPPOST_FILENAME) &&
if ( ((form->flags & HTTPPOST_FILENAME) ||
(form->flags & HTTPPOST_BUFFER)) &&
!form->contenttype ) {
/* our contenttype is missing */
form->contenttype
@@ -880,28 +939,36 @@ FORMcode FormAdd(struct curl_httppost **httppost,
(form == first_form) ) {
/* copy name (without strdup; possibly contains null characters) */
if (AllocAndCopy(&form->name, form->namelength)) {
return_value = FORMADD_MEMORY;
return_value = CURL_FORMADD_MEMORY;
break;
}
}
if ( !(form->flags & HTTPPOST_FILENAME) &&
!(form->flags & HTTPPOST_READFILE) &&
!(form->flags & HTTPPOST_PTRCONTENTS) ) {
!(form->flags & HTTPPOST_PTRCONTENTS) &&
/* CMC: Added support for buffer uploads */
!(form->flags & HTTPPOST_PTRBUFFER) ) {
/* copy value (without strdup; possibly contains null characters) */
if (AllocAndCopy(&form->value, form->contentslength)) {
return_value = FORMADD_MEMORY;
return_value = CURL_FORMADD_MEMORY;
break;
}
}
post = AddHttpPost(form->name, form->namelength,
form->value, form->contentslength,
/* CMC: Added support for buffer uploads */
form->buffer, form->bufferlength,
form->contenttype, form->flags,
form->contentheader, form->showfilename,
post, httppost,
last_post);
if(!post)
return_value = FORMADD_MEMORY;
return_value = CURL_FORMADD_MEMORY;
if (form->contenttype)
prevtype = form->contenttype;
@@ -922,12 +989,12 @@ FORMcode FormAdd(struct curl_httppost **httppost,
return return_value;
}
int curl_formadd(struct curl_httppost **httppost,
CURLFORMcode curl_formadd(struct curl_httppost **httppost,
struct curl_httppost **last_post,
...)
{
va_list arg;
int result;
CURLFORMcode result;
va_start(arg, last_post);
result = FormAdd(httppost, last_post, arg);
va_end(arg);
@@ -1044,22 +1111,24 @@ void curl_formfree(struct curl_httppost *form)
} while((form=next)); /* continue */
}
struct FormData *Curl_getFormData(struct curl_httppost *post,
CURLcode Curl_getFormData(struct FormData **finalform,
struct curl_httppost *post,
int *sizep)
{
struct FormData *form = NULL;
struct FormData *firstform;
struct curl_httppost *file;
CURLcode result = CURLE_OK;
int size =0;
char *boundary;
char *fileboundary=NULL;
struct curl_slist* curList;
*finalform=NULL; /* default form is empty */
if(!post)
return NULL; /* no input => no output! */
return result; /* no input => no output! */
boundary = Curl_FormBoundary();
@@ -1116,7 +1185,11 @@ struct FormData *Curl_getFormData(struct curl_httppost *post,
(file->showfilename?file->showfilename:
file->contents));
}
else if(post->flags & HTTPPOST_FILENAME) {
else if((post->flags & HTTPPOST_FILENAME) ||
/* CMC: Added support for buffer uploads */
(post->flags & HTTPPOST_BUFFER)) {
size += AddFormDataf(&form,
"; filename=\"%s\"",
(post->showfilename?post->showfilename:
@@ -1166,19 +1239,29 @@ struct FormData *Curl_getFormData(struct curl_httppost *post,
/*VMS?? Stream files are OK, as are FIXED & VAR files WITHOUT implied CC */
/*VMS?? For implied CC, every record needs to have a \n appended & 1 added to SIZE */
if(fileread) {
while((nread = fread(buffer, 1, 1024, fileread))) {
size += AddFormData(&form,
buffer,
nread);
}
while((nread = fread(buffer, 1, 1024, fileread)))
size += AddFormData(&form, buffer, nread);
if(fileread != stdin)
fclose(fileread);
}
else {
#if 0
/* File wasn't found, add a nothing field! */
size += AddFormData(&form, "", 0);
#endif
Curl_formclean(firstform);
free(boundary);
*finalform = NULL;
return CURLE_READ_ERROR;
}
/* CMC: Added support for buffer uploads */
} else if (post->flags & HTTPPOST_BUFFER) {
/* include contents of buffer */
size += AddFormData(&form, post->buffer, post->bufferlength);
}
else {
/* include the contents we got */
size += AddFormData(&form, post->contents, post->contentslength);
@@ -1205,7 +1288,9 @@ struct FormData *Curl_getFormData(struct curl_httppost *post,
free(boundary);
return firstform;
*finalform=firstform;
return result;
}
int Curl_FormInit(struct Form *form, struct FormData *formdata )
@@ -1510,6 +1595,8 @@ int main(int argc, char **argv)
#endif
#endif /* CURL_DISABLE_HTTP */
/*
* local variables:
* eval: (load-file "../curl-mode.el")

View File

@@ -45,6 +45,10 @@ typedef struct FormInfo {
char *contenttype;
long flags;
/* CMC: Added support for buffer uploads */
char *buffer; /* pointer to existing buffer used for file upload */
long bufferlength;
char *showfilename; /* The file name to show. If not set, the actual
file name will be used */
struct curl_slist* contentheader;
@@ -53,7 +57,9 @@ typedef struct FormInfo {
int Curl_FormInit(struct Form *form, struct FormData *formdata );
struct FormData *Curl_getFormData(struct HttpPost *post,
CURLcode
Curl_getFormData(struct FormData **,
struct HttpPost *post,
int *size);
/* fread() emulation */

View File

@@ -23,6 +23,8 @@
#include "setup.h"
/* MN 06/07/02 */
#ifndef CURL_DISABLE_FTP
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
@@ -210,16 +212,6 @@ int Curl_GetFTPResponse(char *buf,
if (ftpcode)
*ftpcode = 0; /* 0 for errors */
if(data->set.timeout) {
/* if timeout is requested, find out how much remaining time we have */
timeout = data->set.timeout - /* timeout time */
Curl_tvdiff(Curl_tvnow(), conn->now)/1000; /* spent time */
if(timeout <=0 ) {
failf(data, "Transfer aborted due to timeout");
return -SELECT_TIMEOUT; /* already too little time */
}
}
FD_ZERO (&readfd); /* clear it */
FD_SET (sockfd, &readfd); /* read socket */
@@ -235,11 +227,22 @@ int Curl_GetFTPResponse(char *buf,
keepon=TRUE;
while((nread<BUFSIZE) && (keepon && !error)) {
/* check and reset timeout value every lap */
if(data->set.timeout) {
/* if timeout is requested, find out how much remaining time we have */
timeout = data->set.timeout - /* timeout time */
Curl_tvdiff(Curl_tvnow(), conn->now)/1000; /* spent time */
if(timeout <=0 ) {
failf(data, "Transfer aborted due to timeout");
return -SELECT_TIMEOUT; /* already too little time */
}
}
if(!ftp->cache) {
readfd = rkeepfd; /* set every lap */
interval.tv_sec = timeout;
interval.tv_usec = 0;
if(!ftp->cache)
switch (select (sockfd+1, &readfd, NULL, NULL, &interval)) {
case -1: /* select() error, stop reading */
error = SELECT_ERROR;
@@ -253,6 +256,7 @@ int Curl_GetFTPResponse(char *buf,
error = SELECT_OK;
break;
}
}
if(SELECT_OK == error) {
/*
* This code previously didn't use the kerberos sec_read() code
@@ -633,9 +637,9 @@ CURLcode Curl_ftp_done(struct connectdata *conn)
failf(data, "Received only partial file: %d bytes", *ftp->bytecountp);
return CURLE_PARTIAL_FILE;
}
else if(!conn->bits.resume_done &&
!data->set.no_body &&
(0 == *ftp->bytecountp)) {
else if(!ftp->dont_check &&
!*ftp->bytecountp &&
(conn->size>0)) {
/* We consider this an error, but there's no true FTP error received
why we need to continue to "read out" the server response too.
We don't want to leave a "waiting" server reply if we'll get told
@@ -652,9 +656,9 @@ CURLcode Curl_ftp_done(struct connectdata *conn)
sclose(conn->secondarysocket);
conn->secondarysocket = -1;
if(!data->set.no_body && !conn->bits.resume_done) {
/* now let's see what the server says about the transfer we
just performed: */
if(!data->set.no_body && !ftp->dont_check) {
/* now let's see what the server says about the transfer we just
performed: */
nread = Curl_GetFTPResponse(buf, conn, &ftpcode);
if(nread < 0)
return CURLE_OPERATION_TIMEOUTED;
@@ -665,6 +669,11 @@ CURLcode Curl_ftp_done(struct connectdata *conn)
return CURLE_FTP_WRITE_ERROR;
}
}
if(ftp->dont_check) {
/* if we don't check, we can't re-use this connection as it leaves the
control connection in a weird status */
conn->bits.close = TRUE;
}
conn->bits.resume_done = FALSE; /* clean this for next connection */
@@ -1065,13 +1074,13 @@ CURLcode ftp_use_port(struct connectdata *conn)
}
freeaddrinfo(res);
if (portsock < 0) {
failf(data, strerror(errno));
failf(data, "%s", strerror(errno));
return CURLE_FTP_PORT_FAILED;
}
sslen = sizeof(ss);
if (getsockname(portsock, sa, &sslen) < 0) {
failf(data, strerror(errno));
failf(data, "%s", strerror(errno));
return CURLE_FTP_PORT_FAILED;
}
@@ -1205,19 +1214,19 @@ CURLcode ftp_use_port(struct connectdata *conn)
if(data->set.ftpport) {
if(Curl_if2ip(data->set.ftpport, myhost, sizeof(myhost))) {
h = Curl_resolv(data, myhost, 0, &hostdataptr);
h = Curl_resolv(data, myhost, 0);
}
else {
int len = strlen(data->set.ftpport);
if(len>1)
h = Curl_resolv(data, data->set.ftpport, 0, &hostdataptr);
h = Curl_resolv(data, data->set.ftpport, 0);
if(h)
strcpy(myhost, data->set.ftpport); /* buffer overflow risk */
}
}
if(! *myhost) {
char *tmp_host = getmyhost(myhost, sizeof(myhost));
h=Curl_resolv(data, tmp_host, 0, &hostdataptr);
h=Curl_resolv(data, tmp_host, 0);
}
infof(data, "We connect from %s\n", myhost);
@@ -1360,7 +1369,6 @@ CURLcode ftp_use_pasv(struct connectdata *conn)
int modeoff;
unsigned short connectport; /* the local port connect() should use! */
unsigned short newport; /* remote port, not necessary the local one */
char *hostdataptr=NULL;
/* newhost must be able to hold a full IP-style address in ASCII, which
in the IPv6 case means 5*8-1 = 39 letters */
@@ -1369,7 +1377,7 @@ CURLcode ftp_use_pasv(struct connectdata *conn)
for (modeoff = (data->set.ftp_use_epsv?0:1);
mode[modeoff]; modeoff++) {
result = Curl_ftpsendf(conn, mode[modeoff]);
result = Curl_ftpsendf(conn, "%s", mode[modeoff]);
if(result)
return result;
nread = Curl_GetFTPResponse(buf, conn, &ftpcode);
@@ -1450,16 +1458,19 @@ CURLcode ftp_use_pasv(struct connectdata *conn)
if(data->change.proxy) {
/*
* This is a tunnel through a http proxy and we need to connect to the
* proxy again here. We already have the name info for it since the
* previous lookup.
* proxy again here.
*
* We don't want to rely on a former host lookup that might've expired
* now, instead we remake the lookup here and now!
*/
addr = conn->hostaddr;
addr = Curl_resolv(data, conn->proxyhost, conn->port);
connectport =
(unsigned short)conn->port; /* we connect to the proxy's port */
}
else {
/* normal, direct, ftp connection */
addr = Curl_resolv(data, newhostp, newport, &hostdataptr);
addr = Curl_resolv(data, newhostp, newport);
if(!addr) {
failf(data, "Can't resolve new host %s:%d", newhostp, newport);
return CURLE_FTP_CANT_GET_HOST;
@@ -1593,7 +1604,7 @@ CURLcode ftp_perform(struct connectdata *conn)
if(data->set.no_body)
/* don't transfer the data */
;
ftp->dont_check = TRUE;
/* Get us a second connection up and connected */
else if(data->set.ftp_use_port) {
/* We have chosen to use the PORT command */
@@ -1689,10 +1700,11 @@ CURLcode ftp_perform(struct connectdata *conn)
/* no data to transfer */
result=Curl_Transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
/* Set resume done so that we won't get any error in
* Curl_ftp_done() because we didn't transfer the amount of bytes
* that the local file file obviously is */
/* Set resume done and dont_check so that we won't get any error
* in Curl_ftp_done() because we didn't transfer the amount of
* bytes that the local file file obviously is */
conn->bits.resume_done = TRUE;
ftp->dont_check = TRUE;
return CURLE_OK;
}
@@ -1781,6 +1793,8 @@ CURLcode ftp_perform(struct connectdata *conn)
}
infof(data, "range-download from %d to %d, totally %d bytes\n",
from, to, totalsize);
conn->bits.resume_done = TRUE; /* to prevent some error due to this */
ftp->dont_check = TRUE; /* dont check for successful transfer */
}
if((data->set.ftp_list_only) || !ftp->file) {
@@ -1877,6 +1891,7 @@ CURLcode ftp_perform(struct connectdata *conn)
* because we didn't transfer the amount of bytes that the remote
* file obviously is */
conn->bits.resume_done = TRUE;
ftp->dont_check = TRUE;
return CURLE_OK;
}
@@ -2137,3 +2152,5 @@ CURLcode Curl_ftp_disconnect(struct connectdata *conn)
* vim600: fdm=marker
* vim: et sw=2 ts=2 sts=2 tw=78
*/
#endif /* CURL_DISABLE_FTP */

View File

@@ -23,6 +23,10 @@
*
* $Id$
*****************************************************************************/
/* MN 06/07/02 */
#ifndef CURL_DISABLE_FTP
CURLcode Curl_ftp(struct connectdata *conn);
CURLcode Curl_ftp_done(struct connectdata *conn);
CURLcode Curl_ftp_connect(struct connectdata *conn);
@@ -34,4 +38,8 @@ CURLcode Curl_ftpsendf(struct connectdata *, const char *fmt, ...);
int Curl_GetFTPResponse(char *buf, struct connectdata *conn,
int *ftpcode);
/* MN 06/07/02 */
#endif
#endif

View File

@@ -54,6 +54,7 @@ CURLcode Curl_initinfo(struct SessionHandle *data)
pro->t_pretransfer = 0;
pro->t_starttransfer = 0;
pro->timespent = 0;
pro->t_redirect = 0;
info->httpcode = 0;
info->httpversion=0;
@@ -148,6 +149,12 @@ CURLcode Curl_getinfo(struct SessionHandle *data, CURLINFO info, ...)
case CURLINFO_CONTENT_LENGTH_UPLOAD:
*param_doublep = data->progress.size_ul;
break;
case CURLINFO_REDIRECT_TIME:
*param_doublep = data->progress.t_redirect;
break;
case CURLINFO_REDIRECT_COUNT:
*param_longp = data->set.followlocation;
break;
case CURLINFO_CONTENT_TYPE:
*param_charp = data->info.contenttype;
break;

View File

@@ -72,7 +72,7 @@ _hash_element_dtor (void *user, void *element)
/* {{{ void curl_hash_init (curl_hash *, int, curl_hash_dtor)
*/
void
curl_hash_init (curl_hash *h, int slots, curl_hash_dtor dtor)
Curl_hash_init (curl_hash *h, int slots, curl_hash_dtor dtor)
{
int i;
@@ -82,7 +82,7 @@ curl_hash_init (curl_hash *h, int slots, curl_hash_dtor dtor)
h->table = (curl_llist **) malloc(slots * sizeof(curl_llist *));
for (i = 0; i < slots; ++i) {
h->table[i] = curl_llist_alloc((curl_llist_dtor) _hash_element_dtor);
h->table[i] = Curl_llist_alloc((curl_llist_dtor) _hash_element_dtor);
}
}
/* }}} */
@@ -90,7 +90,7 @@ curl_hash_init (curl_hash *h, int slots, curl_hash_dtor dtor)
/* {{{ curl_hash *curl_hash_alloc (int, curl_hash_dtor)
*/
curl_hash *
curl_hash_alloc (int slots, curl_hash_dtor dtor)
Curl_hash_alloc (int slots, curl_hash_dtor dtor)
{
curl_hash *h;
@@ -98,7 +98,7 @@ curl_hash_alloc (int slots, curl_hash_dtor dtor)
if (NULL == h)
return NULL;
curl_hash_init(h, slots, dtor);
Curl_hash_init(h, slots, dtor);
return h;
}
@@ -142,7 +142,7 @@ _mk_hash_element (curl_hash_element **e, char *key, size_t key_len, const void *
/* {{{ int curl_hash_add (curl_hash *, char *, size_t, const void *)
*/
int
curl_hash_add (curl_hash *h, char *key, size_t key_len, const void *p)
Curl_hash_add (curl_hash *h, char *key, size_t key_len, const void *p)
{
curl_hash_element *he;
curl_llist_element *le;
@@ -162,7 +162,7 @@ curl_hash_add (curl_hash *h, char *key, size_t key_len, const void *p)
if (_mk_hash_element(&he, key, key_len, p) != 0)
return 0;
if (curl_llist_insert_next(l, CURL_LLIST_TAIL(l), he)) {
if (Curl_llist_insert_next(l, CURL_LLIST_TAIL(l), he)) {
++h->size;
return 1;
}
@@ -174,7 +174,7 @@ curl_hash_add (curl_hash *h, char *key, size_t key_len, const void *p)
/* {{{ int curl_hash_delete (curl_hash *, char *, size_t)
*/
int
curl_hash_delete(curl_hash *h, char *key, size_t key_len)
Curl_hash_delete(curl_hash *h, char *key, size_t key_len)
{
curl_hash_element *he;
curl_llist_element *le;
@@ -185,7 +185,7 @@ curl_hash_delete(curl_hash *h, char *key, size_t key_len)
le = CURL_LLIST_NEXT(le)) {
he = CURL_LLIST_VALP(le);
if (_hash_key_compare(he->key, he->key_len, key, key_len)) {
curl_llist_remove(l, le, (void *) h);
Curl_llist_remove(l, le, (void *) h);
--h->size;
return 1;
}
@@ -198,7 +198,7 @@ curl_hash_delete(curl_hash *h, char *key, size_t key_len)
/* {{{ int curl_hash_find (curl_hash *, char *, size_t, void **)
*/
int
curl_hash_find(curl_hash *h, char *key, size_t key_len, void **p)
Curl_hash_find(curl_hash *h, char *key, size_t key_len, void **p)
{
curl_llist_element *le;
curl_hash_element *he;
@@ -221,13 +221,16 @@ curl_hash_find(curl_hash *h, char *key, size_t key_len, void **p)
/* {{{ void curl_hash_apply (curl_hash *, void *, void (*)(void *, curl_hash_element *))
*/
void
curl_hash_apply(curl_hash *h, void *user, void (*cb)(void *, curl_hash_element *))
Curl_hash_apply(curl_hash *h, void *user,
void (*cb)(void *, curl_hash_element *))
{
curl_llist_element *le;
int i;
for (i = 0; i < h->slots; ++i) {
for (le = CURL_LLIST_HEAD(h->table[i]); le != NULL; le = CURL_LLIST_NEXT(le)) {
for (le = CURL_LLIST_HEAD(h->table[i]);
le != NULL;
le = CURL_LLIST_NEXT(le)) {
cb(user, (curl_hash_element *) CURL_LLIST_VALP(le));
}
}
@@ -237,22 +240,47 @@ curl_hash_apply(curl_hash *h, void *user, void (*cb)(void *, curl_hash_element *
/* {{{ void curl_hash_clean (curl_hash *)
*/
void
curl_hash_clean(curl_hash *h)
Curl_hash_clean(curl_hash *h)
{
int i;
for (i = 0; i < h->slots; ++i) {
curl_llist_destroy(h->table[i], (void *) h);
Curl_llist_destroy(h->table[i], (void *) h);
}
free(h->table);
}
/* }}} */
/* {{{ void curl_hash_clean_with_criterium (curl_hash *, void *,
int (*)(void *, void *))
*/
void
Curl_hash_clean_with_criterium(curl_hash *h, void *user,
int (*comp)(void *, void *))
{
curl_llist_element *le;
curl_llist_element *lnext;
int i;
for (i = 0; i < h->slots; ++i) {
le = CURL_LLIST_HEAD(h->table[i]);
while(le != NULL)
if (comp(user, ((curl_hash_element *) CURL_LLIST_VALP(le))->ptr)) {
lnext = CURL_LLIST_NEXT(le);
Curl_llist_remove(h->table[i], le, (void *) h);
--h->size;
le = lnext;
}
else
le = CURL_LLIST_NEXT(le);
}
}
/* {{{ int curl_hash_count (curl_hash *)
*/
int
curl_hash_count(curl_hash *h)
Curl_hash_count(curl_hash *h)
{
return h->size;
}
@@ -261,12 +289,12 @@ curl_hash_count(curl_hash *h)
/* {{{ void curl_hash_destroy (curl_hash *)
*/
void
curl_hash_destroy(curl_hash *h)
Curl_hash_destroy(curl_hash *h)
{
if (!h)
return;
curl_hash_clean(h);
Curl_hash_clean(h);
free(h);
}
/* }}} */

View File

@@ -45,18 +45,18 @@ typedef struct _curl_hash_element {
} curl_hash_element;
void curl_hash_init(curl_hash *, int, curl_hash_dtor);
curl_hash *curl_hash_alloc(int, curl_hash_dtor);
int curl_hash_add(curl_hash *, char *, size_t, const void *);
int curl_hash_delete(curl_hash *h, char *key, size_t key_len);
int curl_hash_find(curl_hash *, char *, size_t, void **p);
void curl_hash_apply(curl_hash *h, void *user, void (*cb)(void *, curl_hash_element *));
int curl_hash_count(curl_hash *h);
void curl_hash_clean(curl_hash *h);
void curl_hash_destroy(curl_hash *h);
#define curl_hash_update curl_hash_add
void Curl_hash_init(curl_hash *, int, curl_hash_dtor);
curl_hash *Curl_hash_alloc(int, curl_hash_dtor);
int Curl_hash_add(curl_hash *, char *, size_t, const void *);
int Curl_hash_delete(curl_hash *h, char *key, size_t key_len);
int Curl_hash_find(curl_hash *, char *, size_t, void **p);
void Curl_hash_apply(curl_hash *h, void *user, void (*cb)(void *, curl_hash_element *));
int Curl_hash_count(curl_hash *h);
void Curl_hash_clean(curl_hash *h);
void Curl_hash_clean_with_criterium(curl_hash *h, void *user, int (*comp)(void *, void *));
void Curl_hash_destroy(curl_hash *h);
#define Curl_hash_update Curl_hash_add
#endif

View File

@@ -56,6 +56,10 @@
#endif
#endif
#ifdef HAVE_SETJMP_H
#include <setjmp.h>
#endif
#include "urldata.h"
#include "sendf.h"
#include "hostip.h"
@@ -79,7 +83,7 @@ static int host_cache_initialized;
void Curl_global_host_cache_init(void)
{
if (!host_cache_initialized) {
curl_hash_init(&hostname_cache, 7, Curl_freeaddrinfo);
Curl_hash_init(&hostname_cache, 7, Curl_freeaddrinfo);
host_cache_initialized = 1;
}
}
@@ -92,7 +96,7 @@ curl_hash *Curl_global_host_cache_get(void)
void Curl_global_host_cache_dtor(void)
{
if (host_cache_initialized) {
curl_hash_clean(&hostname_cache);
Curl_hash_clean(&hostname_cache);
host_cache_initialized = 0;
}
}
@@ -152,6 +156,38 @@ _create_hostcache_id(char *server, int port, ssize_t *entry_len)
return id;
}
struct hostcache_prune_data {
int cache_timeout;
int now;
};
static int
_curl_hostcache_timestamp_remove(void *datap, void *hc)
{
struct hostcache_prune_data *data =
(struct hostcache_prune_data *) datap;
struct curl_dns_cache_entry *c = (struct curl_dns_cache_entry *) hc;
if (data->now - c->timestamp < data->cache_timeout) {
return 0;
}
return 1;
}
static void
hostcache_prune(curl_hash *hostcache, int cache_timeout, int now)
{
struct hostcache_prune_data user;
user.cache_timeout = cache_timeout;
user.now = now;
Curl_hash_clean_with_criterium(hostcache,
(void *) &user,
_curl_hostcache_timestamp_remove);
}
/* Macro to save redundant free'ing of entry_id */
#define _hostcache_return(__v) \
{ \
@@ -159,53 +195,65 @@ _create_hostcache_id(char *server, int port, ssize_t *entry_len)
return (__v); \
}
#ifdef HAVE_SIGSETJMP
/* Beware this is a global and unique instance */
sigjmp_buf curl_jmpenv;
#endif
Curl_addrinfo *Curl_resolv(struct SessionHandle *data,
char *hostname,
int port,
char **bufp)
int port)
{
char *entry_id = NULL;
struct curl_dns_cache_entry *p = NULL;
ssize_t entry_len;
time_t now;
char *bufp;
#ifdef HAVE_SIGSETJMP
if(sigsetjmp(curl_jmpenv, 1) != 0) {
/* this is coming from a siglongjmp() */
failf(data, "name lookup time-outed");
return NULL;
}
#endif
/* If the host cache timeout is 0, we don't do DNS cach'ing
so fall through */
if (data->set.dns_cache_timeout == 0) {
return Curl_getaddrinfo(data, hostname, port, bufp);
return Curl_getaddrinfo(data, hostname, port, &bufp);
}
time(&now);
/* Remove outdated entries from the hostcache */
hostcache_prune(data->hostcache,
data->set.dns_cache_timeout,
now);
/* Create an entry id, based upon the hostname and port */
entry_len = strlen(hostname);
entry_id = _create_hostcache_id(hostname, port, &entry_len);
/* If we can't create the entry id, don't cache, just fall-through
to the plain Curl_getaddrinfo() */
if (!entry_id) {
return Curl_getaddrinfo(data, hostname, port, bufp);
return Curl_getaddrinfo(data, hostname, port, &bufp);
}
time(&now);
/* See if its already in our dns cache */
if (entry_id && curl_hash_find(data->hostcache, entry_id, entry_len+1, (void **) &p)) {
/* Do we need to check for a cache timeout? */
if (data->set.dns_cache_timeout != -1) {
/* Return if the entry has not timed out */
if ((now - p->timestamp) < data->set.dns_cache_timeout) {
if (entry_id &&
Curl_hash_find(data->hostcache, entry_id, entry_len+1, (void **) &p)) {
_hostcache_return(p->addr);
}
}
else {
_hostcache_return(p->addr);
}
}
/* Create a new cache entry */
p = (struct curl_dns_cache_entry *) malloc(sizeof(struct curl_dns_cache_entry));
p = (struct curl_dns_cache_entry *)
malloc(sizeof(struct curl_dns_cache_entry));
if (!p) {
_hostcache_return(NULL);
}
p->addr = Curl_getaddrinfo(data, hostname, port, bufp);
p->addr = Curl_getaddrinfo(data, hostname, port, &bufp);
if (!p->addr) {
free(p);
_hostcache_return(NULL);
@@ -213,7 +261,7 @@ Curl_addrinfo *Curl_resolv(struct SessionHandle *data,
p->timestamp = now;
/* Save it in our host cache */
curl_hash_update(data->hostcache, entry_id, entry_len+1, (const void *) p);
Curl_hash_update(data->hostcache, entry_id, entry_len+1, (const void *) p);
_hostcache_return(p->addr);
}
@@ -304,7 +352,7 @@ Curl_addrinfo *Curl_getaddrinfo(struct SessionHandle *data,
/* This seems to be an IPv6-capable stack, use PF_UNSPEC for the widest
* possible checks. And close the socket again.
*/
close(s);
sclose(s);
memset(&hints, 0, sizeof(hints));
hints.ai_family = pf;
@@ -313,7 +361,7 @@ Curl_addrinfo *Curl_getaddrinfo(struct SessionHandle *data,
snprintf(sbuf, sizeof(sbuf), "%d", port);
error = getaddrinfo(hostname, sbuf, &hints, &res);
if (error) {
infof(data, "getaddrinfo(3) failed for %s\n", hostname);
infof(data, "getaddrinfo(3) failed for %s:%d\n", hostname, port);
return NULL;
}
*bufp=(char *)res; /* make it point to the result struct */
@@ -323,22 +371,24 @@ Curl_addrinfo *Curl_getaddrinfo(struct SessionHandle *data,
#else /* following code is IPv4-only */
#ifndef HAVE_GETHOSTBYNAME_R
static void hostcache_fixoffset(struct hostent *h, int offset);
/**
* Performs a "deep" copy of a hostent into a buffer (returns a pointer to the
* copy). Make absolutely sure the destination buffer is big enough!
*
* Keith McGuigan
* 10/3/2001 */
static struct hostent* pack_hostent(char* buf, struct hostent* orig)
static struct hostent* pack_hostent(char** buf, struct hostent* orig)
{
char *bufptr;
char *newbuf;
struct hostent* copy;
int i;
char *str;
int len;
bufptr = buf;
bufptr = *buf;
copy = (struct hostent*)bufptr;
bufptr += sizeof(struct hostent);
@@ -348,10 +398,12 @@ static struct hostent* pack_hostent(char* buf, struct hostent* orig)
bufptr += len;
/* we align on even 64bit boundaries for safety */
#define MEMALIGN(x) (((unsigned long)(x)&0xfffffff8)+8)
#define MEMALIGN(x) ((x)+(8-(((unsigned long)(x))&0x7)))
/* This must be aligned properly to work on many CPU architectures! */
copy->h_aliases = (char**)MEMALIGN(bufptr);
bufptr = MEMALIGN(bufptr);
copy->h_aliases = (char**)bufptr;
/* Figure out how many aliases there are */
for (i = 0; orig->h_aliases[i] != NULL; ++i);
@@ -373,7 +425,7 @@ static struct hostent* pack_hostent(char* buf, struct hostent* orig)
copy->h_length = orig->h_length;
/* align it for (at least) 32bit accesses */
bufptr = (char *)MEMALIGN(bufptr);
bufptr = MEMALIGN(bufptr);
copy->h_addr_list = (char**)bufptr;
@@ -394,6 +446,18 @@ static struct hostent* pack_hostent(char* buf, struct hostent* orig)
}
copy->h_addr_list[i] = NULL;
/* now, shrink the allocated buffer to the size we actually need, which
most often is only a fraction of the original alloc */
newbuf=(char *)realloc(*buf, (int)bufptr-(int)(*buf));
/* if the alloc moved, we need to adjust things again */
if(newbuf != *buf)
hostcache_fixoffset((struct hostent*)newbuf, (int)newbuf-(int)*buf);
/* setup the return */
*buf = newbuf;
copy = (struct hostent*)newbuf;
return copy;
}
#endif
@@ -419,14 +483,30 @@ static char *MakeIP(unsigned long num,char *addr, int addr_len)
return (addr);
}
/* The original code to this function was once stolen from the Dancer source
code, written by Bjorn Reese, it has since been patched and modified
considerably. */
#ifndef INADDR_NONE
#define INADDR_NONE (in_addr_t) ~0
#endif
static void hostcache_fixoffset(struct hostent *h, int offset)
{
int i=0;
h->h_name=(char *)((long)h->h_name+offset);
h->h_aliases=(char **)((long)h->h_aliases+offset);
while(h->h_aliases[i]) {
h->h_aliases[i]=(char *)((long)h->h_aliases[i]+offset);
i++;
}
h->h_addr_list=(char **)((long)h->h_addr_list+offset);
i=0;
while(h->h_addr_list[i]) {
h->h_addr_list[i]=(char *)((long)h->h_addr_list[i]+offset);
i++;
}
}
/* The original code to this function was once stolen from the Dancer source
code, written by Bjorn Reese, it has since been patched and modified
considerably. */
Curl_addrinfo *Curl_getaddrinfo(struct SessionHandle *data,
char *hostname,
int port,
@@ -441,16 +521,15 @@ Curl_addrinfo *Curl_getaddrinfo(struct SessionHandle *data,
* everything. OSF1 is known to require at least 8872 bytes. The buffer
* required for storing all possible aliases and IP numbers is according to
* Stevens' Unix Network Programming 2nd editor, p. 304: 8192 bytes! */
int *buf = (int *)malloc(CURL_NAMELOOKUP_SIZE);
if(!buf)
return NULL; /* major failure */
*bufp = (char *)buf;
port=0; /* unused in IPv4 code */
ret = 0; /* to prevent the compiler warning */
if ( (in=inet_addr(hostname)) != INADDR_NONE ) {
struct in_addr *addrentry;
long *buf = (long *)malloc(sizeof(struct hostent)+128);
if(!buf)
return NULL; /* major failure */
*bufp = (char *)buf;
h = (struct hostent*)buf;
h->h_addr_list = (char**)(buf + sizeof(*h));
@@ -462,30 +541,79 @@ Curl_addrinfo *Curl_getaddrinfo(struct SessionHandle *data,
h->h_length = sizeof(*addrentry);
h->h_name = *(h->h_addr_list) + h->h_length;
/* bad one h->h_name = (char*)(h->h_addr_list + h->h_length); */
MakeIP(ntohl(in),h->h_name, CURL_NAMELOOKUP_SIZE - (long)(h->h_name) + (long)buf);
MakeIP(ntohl(in),h->h_name, sizeof(struct hostent)+128 -
(long)(h->h_name) + (long)buf);
}
#if defined(HAVE_GETHOSTBYNAME_R)
else {
int h_errnop;
int res=ERANGE;
int step_size=200;
int *buf = (int *)malloc(CURL_NAMELOOKUP_SIZE);
if(!buf)
return NULL; /* major failure */
*bufp=(char *)buf;
/* Workaround for gethostbyname_r bug in qnx nto. It is also _required_
for some of these functions. */
memset(buf, 0, CURL_NAMELOOKUP_SIZE);
#ifdef HAVE_GETHOSTBYNAME_R_5
/* Solaris, IRIX and more */
if ((h = gethostbyname_r(hostname,
while(!h) {
h = gethostbyname_r(hostname,
(struct hostent *)buf,
(char *)buf + sizeof(struct hostent),
CURL_NAMELOOKUP_SIZE - sizeof(struct hostent),
&h_errnop)) == NULL )
step_size - sizeof(struct hostent),
&h_errnop);
/* If the buffer is too small, it returns NULL and sets errno to
ERANGE. The errno is thread safe if this is compiled with
-D_REENTRANT as then the 'errno' variable is a macro defined to
get used properly for threads. */
if(h || (errno != ERANGE))
break;
step_size+=200;
}
#ifdef MALLOCDEBUG
infof(data, "gethostbyname_r() uses %d bytes\n", step_size);
#endif
if(h) {
int offset;
h=(struct hostent *)realloc(buf, step_size);
offset=(long)h-(long)buf;
hostcache_fixoffset(h, offset);
buf=(int *)h;
*bufp=(char *)buf;
}
else
#endif
#ifdef HAVE_GETHOSTBYNAME_R_6
/* Linux */
if( gethostbyname_r(hostname,
while((res=gethostbyname_r(hostname,
(struct hostent *)buf,
(char *)buf + sizeof(struct hostent),
CURL_NAMELOOKUP_SIZE - sizeof(struct hostent),
step_size - sizeof(struct hostent),
&h, /* DIFFERENCE */
&h_errnop))
&h_errnop))==ERANGE) {
step_size+=200;
}
#ifdef MALLOCDEBUG
infof(data, "gethostbyname_r() uses %d bytes\n", step_size);
#endif
if(!res) {
int offset;
h=(struct hostent *)realloc(buf, step_size);
offset=(long)h-(long)buf;
hostcache_fixoffset(h, offset);
buf=(int *)h;
*bufp=(char *)buf;
}
else
#endif
#ifdef HAVE_GETHOSTBYNAME_R_3
/* AIX, Digital Unix, HPUX 10, more? */
@@ -518,14 +646,17 @@ Curl_addrinfo *Curl_getaddrinfo(struct SessionHandle *data,
else {
if ((h = gethostbyname(hostname)) == NULL ) {
infof(data, "gethostbyname(2) failed for %s\n", hostname);
free(buf);
*bufp=NULL;
}
else
{
char *buf=(char *)malloc(CURL_NAMELOOKUP_SIZE);
/* we make a copy of the hostent right now, right here, as the
static one we got a pointer to might get removed when we don't
want/expect that */
h = pack_hostent((char *)buf, h);
h = pack_hostent(&buf, h);
*bufp=(char *)buf;
}
#endif
}
return (h);

View File

@@ -37,8 +37,7 @@ curl_hash *Curl_global_host_cache_get(void);
Curl_addrinfo *Curl_resolv(struct SessionHandle *data,
char *hostname,
int port,
char **bufp);
int port);
/* Get name info */
Curl_addrinfo *Curl_getaddrinfo(struct SessionHandle *data,

View File

@@ -23,6 +23,7 @@
#include "setup.h"
#ifndef CURL_DISABLE_HTTP
/* -- WIN32 approved -- */
#include <stdio.h>
#include <string.h>
@@ -161,7 +162,7 @@ CURLcode add_buffer_send(int sockfd, struct connectdata *conn, send_buffer *in,
free(in->buffer);
free(in);
*bytes_written = amount;
*bytes_written += amount;
return res;
}
@@ -562,7 +563,13 @@ CURLcode Curl_http(struct connectdata *conn)
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 */
http->sendit = Curl_getFormData(data->set.httppost, &http->postsize);
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:")) {
@@ -775,16 +782,16 @@ CURLcode Curl_http(struct connectdata *conn)
strcpy(buf, "no strftime() support");
#endif
switch(data->set.timecondition) {
case TIMECOND_IFMODSINCE:
case CURL_TIMECOND_IFMODSINCE:
default:
add_bufferf(req_buffer,
"If-Modified-Since: %s\r\n", buf);
break;
case TIMECOND_IFUNMODSINCE:
case CURL_TIMECOND_IFUNMODSINCE:
add_bufferf(req_buffer,
"If-Unmodified-Since: %s\r\n", buf);
break;
case TIMECOND_LASTMOD:
case CURL_TIMECOND_LASTMOD:
add_bufferf(req_buffer,
"Last-Modified: %s\r\n", buf);
break;
@@ -918,8 +925,9 @@ CURLcode Curl_http(struct connectdata *conn)
actually set your own */
add_bufferf(req_buffer,
"Content-Length: %d\r\n",
(data->set.postfieldsize?data->set.postfieldsize:
strlen(data->set.postfields)) );
data->set.postfieldsize?
data->set.postfieldsize:
(data->set.postfields?strlen(data->set.postfields):0) );
if(!checkheaders(data, "Content-Type:"))
add_bufferf(req_buffer,
@@ -980,3 +988,4 @@ CURLcode Curl_http(struct connectdata *conn)
* vim600: fdm=marker
* vim: et sw=2 ts=2 sts=2 tw=78
*/
#endif

View File

@@ -23,7 +23,7 @@
*
* $Id$
*****************************************************************************/
#ifndef CURL_DISABLE_HTTP
/* ftp can use this as well */
CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn,
int tunnelsocket,
@@ -38,5 +38,5 @@ CURLcode Curl_http_connect(struct connectdata *conn);
void Curl_httpchunk_init(struct connectdata *conn);
CHUNKcode Curl_httpchunk_read(struct connectdata *conn, char *datap,
ssize_t length, ssize_t *wrote);
#endif
#endif

View File

@@ -22,6 +22,7 @@
*****************************************************************************/
#include "setup.h"
#ifndef CURL_DISABLE_HTTP
/* -- WIN32 approved -- */
#include <stdio.h>
#include <string.h>
@@ -228,3 +229,4 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
* vim600: fdm=marker
* vim: et sw=2 ts=2 sts=2 tw=78
*/
#endif /* CURL_DISABLE_HTTP */

View File

@@ -40,6 +40,7 @@
#include "setup.h"
#ifndef CURL_DISABLE_FTP
#ifdef KRB4
#include "security.h"
@@ -197,7 +198,7 @@ krb4_auth(void *app_data, struct connectdata *conn)
int checksum;
u_int32_t cs;
struct krb4_data *d = app_data;
char *host = conn->hostaddr->h_name;
char *host = conn->hostname;
ssize_t nread;
int l = sizeof(conn->local_addr);
struct SessionHandle *data = conn->data;
@@ -362,7 +363,7 @@ void Curl_krb_kauth(struct connectdata *conn)
if (strcmp ((char*)tktcopy.dat + 8,
KRB_TICKET_GRANTING_TICKET) != 0) {
afs_string_to_key (passwd,
krb_realmofhost(conn->hostaddr->h_name),
krb_realmofhost(conn->hostname),
&key);
des_key_sched (&key, schedule);
des_pcbc_encrypt((des_cblock*)tkt.dat, (des_cblock*)tktcopy.dat,
@@ -391,6 +392,7 @@ void Curl_krb_kauth(struct connectdata *conn)
}
#endif /* KRB4 */
#endif /* CURL_DISABLE_FTP */
/*
* local variables:

View File

@@ -23,6 +23,7 @@
#include "setup.h"
#ifndef CURL_DISABLE_LDAP
/* -- WIN32 approved -- */
#include <stdio.h>
#include <string.h>
@@ -147,7 +148,7 @@ CURLcode Curl_ldap(struct connectdata *conn)
int ldaptext;
struct SessionHandle *data=conn->data;
infof(data, "LDAP: %s %s\n", data->change.url);
infof(data, "LDAP: %s\n", data->change.url);
DynaOpen();
if (libldap == NULL) {
@@ -229,3 +230,4 @@ CURLcode Curl_ldap(struct connectdata *conn)
* vim600: fdm=marker
* vim: et sw=2 ts=2 sts=2 tw=78
*/
#endif

View File

@@ -23,7 +23,8 @@
*
* $Id$
*****************************************************************************/
#ifndef CURL_DISABLE_LDAP
CURLcode Curl_ldap(struct connectdata *conn);
CURLcode Curl_ldap_done(struct connectdata *conn);
#endif
#endif /* __LDAP_H */

View File

@@ -33,7 +33,7 @@
#include "memdebug.h"
#endif
void
curl_llist_init(curl_llist *l, curl_llist_dtor dtor)
Curl_llist_init(curl_llist *l, curl_llist_dtor dtor)
{
l->size = 0;
l->dtor = dtor;
@@ -42,7 +42,7 @@ curl_llist_init(curl_llist *l, curl_llist_dtor dtor)
}
curl_llist *
curl_llist_alloc(curl_llist_dtor dtor)
Curl_llist_alloc(curl_llist_dtor dtor)
{
curl_llist *list;
@@ -50,13 +50,13 @@ curl_llist_alloc(curl_llist_dtor dtor)
if(NULL == list)
return NULL;
curl_llist_init(list, dtor);
Curl_llist_init(list, dtor);
return list;
}
int
curl_llist_insert_next(curl_llist *list, curl_llist_element *e, const void *p)
Curl_llist_insert_next(curl_llist *list, curl_llist_element *e, const void *p)
{
curl_llist_element *ne;
@@ -84,7 +84,7 @@ curl_llist_insert_next(curl_llist *list, curl_llist_element *e, const void *p)
}
int
curl_llist_insert_prev(curl_llist *list, curl_llist_element *e, const void *p)
Curl_llist_insert_prev(curl_llist *list, curl_llist_element *e, const void *p)
{
curl_llist_element *ne;
@@ -111,7 +111,7 @@ curl_llist_insert_prev(curl_llist *list, curl_llist_element *e, const void *p)
}
int
curl_llist_remove(curl_llist *list, curl_llist_element *e, void *user)
Curl_llist_remove(curl_llist *list, curl_llist_element *e, void *user)
{
if (e == NULL || list->size == 0)
return 1;
@@ -139,28 +139,28 @@ curl_llist_remove(curl_llist *list, curl_llist_element *e, void *user)
}
int
curl_llist_remove_next(curl_llist *list, curl_llist_element *e, void *user)
Curl_llist_remove_next(curl_llist *list, curl_llist_element *e, void *user)
{
return curl_llist_remove(list, e->next, user);
return Curl_llist_remove(list, e->next, user);
}
int
curl_llist_remove_prev(curl_llist *list, curl_llist_element *e, void *user)
Curl_llist_remove_prev(curl_llist *list, curl_llist_element *e, void *user)
{
return curl_llist_remove(list, e->prev, user);
return Curl_llist_remove(list, e->prev, user);
}
size_t
curl_llist_count(curl_llist *list)
Curl_llist_count(curl_llist *list)
{
return list->size;
}
void
curl_llist_destroy(curl_llist *list, void *user)
Curl_llist_destroy(curl_llist *list, void *user)
{
while (list->size > 0) {
curl_llist_remove(list, CURL_LLIST_TAIL(list), user);
Curl_llist_remove(list, CURL_LLIST_TAIL(list), user);
}
free(list);

View File

@@ -44,14 +44,14 @@ typedef struct _curl_llist {
size_t size;
} curl_llist;
void curl_llist_init(curl_llist *, curl_llist_dtor);
curl_llist *curl_llist_alloc(curl_llist_dtor);
int curl_llist_insert_next(curl_llist *, curl_llist_element *, const void *);
int curl_llist_insert_prev(curl_llist *, curl_llist_element *, const void *);
int curl_llist_remove(curl_llist *, curl_llist_element *, void *);
int curl_llist_remove_next(curl_llist *, curl_llist_element *, void *);
size_t curl_llist_count(curl_llist *);
void curl_llist_destroy(curl_llist *, void *);
void Curl_llist_init(curl_llist *, curl_llist_dtor);
curl_llist *Curl_llist_alloc(curl_llist_dtor);
int Curl_llist_insert_next(curl_llist *, curl_llist_element *, const void *);
int Curl_llist_insert_prev(curl_llist *, curl_llist_element *, const void *);
int Curl_llist_remove(curl_llist *, curl_llist_element *, void *);
int Curl_llist_remove_next(curl_llist *, curl_llist_element *, void *);
size_t Curl_llist_count(curl_llist *);
void Curl_llist_destroy(curl_llist *, void *);
#define CURL_LLIST_HEAD(__l) ((__l)->head)
#define CURL_LLIST_TAIL(__l) ((__l)->tail)

View File

@@ -49,7 +49,9 @@
struct memdebug {
int size;
char mem[1];
double mem[1];
/* I'm hoping this is the thing with the strictest alignment
* requirements. That also means we waste some space :-( */
};
/*

View File

@@ -1028,7 +1028,6 @@ static int alloc_addbyter(int output, FILE *data)
infop->len++;
return output; /* fputc() returns like this on success */
}
char *curl_maprintf(const char *format, ...)
@@ -1044,12 +1043,17 @@ char *curl_maprintf(const char *format, ...)
va_start(ap_save, format);
retcode = dprintf_formatf(&info, alloc_addbyter, format, ap_save);
va_end(ap_save);
if(info.len) {
if(-1 == retcode) {
if(info.alloc)
free(info.buffer);
return NULL;
}
if(info.alloc) {
info.buffer[info.len] = 0; /* we terminate this with a zero byte */
return info.buffer;
}
else
return NULL;
return strdup("");
}
char *curl_mvaprintf(const char *format, va_list ap_save)
@@ -1062,13 +1066,18 @@ char *curl_mvaprintf(const char *format, va_list ap_save)
info.alloc = 0;
retcode = dprintf_formatf(&info, alloc_addbyter, format, ap_save);
info.buffer[info.len] = 0; /* we terminate this with a zero byte */
if(info.len) {
if(-1 == retcode) {
if(info.alloc)
free(info.buffer);
return NULL;
}
if(info.alloc) {
info.buffer[info.len] = 0; /* we terminate this with a zero byte */
return info.buffer;
}
else
return NULL;
return strdup("");
}
static int storebuffer(int output, FILE *data)

View File

@@ -30,6 +30,11 @@
#include "transfer.h"
#include "url.h"
/* The last #include file should be: */
#ifdef MALLOCDEBUG
#include "memdebug.h"
#endif
struct Curl_message {
/* the 'CURLMsg' is the part that is visible to the external user */
struct CURLMsg extmsg;
@@ -57,6 +62,13 @@ struct Curl_one_easy {
CURLMstate state; /* the handle's state */
CURLcode result; /* previous result */
struct Curl_message *msg; /* A pointer to one single posted message.
Cleanup should be done on this pointer NOT on
the linked list in Curl_multi. This message
will be deleted when this handle is removed
from the multi-handle */
int msg_num; /* number of messages left in 'msg' to return */
};
@@ -76,10 +88,8 @@ struct Curl_multi {
/* This is the amount of entries in the linked list above. */
int num_easy;
/* this is a linked list of posted messages */
struct Curl_message *msgs;
/* amount of messages in the queue */
int num_msgs;
int num_msgs; /* total amount of messages in the easy handles */
/* Hostname cache */
curl_hash *hostcache;
};
@@ -169,6 +179,9 @@ CURLMcode curl_multi_remove_handle(CURLM *multi_handle,
/* If the 'state' is not INIT or COMPLETED, we might need to do something
nice to put the easy_handle in a good known state when this returns. */
/* clear out the usage of the shared DNS cache */
easy->easy_handle->hostcache = NULL;
/* make the previous node point to our next */
if(easy->prev)
easy->prev->next = easy->next;
@@ -178,6 +191,8 @@ CURLMcode curl_multi_remove_handle(CURLM *multi_handle,
/* NOTE NOTE NOTE
We do not touch the easy handle here! */
if (easy->msg)
free(easy->msg);
free(easy);
multi->num_easy--; /* one less to care about now */
@@ -235,6 +250,7 @@ CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
struct Curl_one_easy *easy;
bool done;
CURLMcode result=CURLM_OK;
struct Curl_message *msg = NULL;
*running_handles = 0; /* bump this once for every living handle */
@@ -259,7 +275,7 @@ CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
}
else {
if (multi->hostcache == NULL) {
multi->hostcache = curl_hash_alloc(7, Curl_freeaddrinfo);
multi->hostcache = Curl_hash_alloc(7, Curl_freeaddrinfo);
}
easy->easy_handle->hostcache = multi->hostcache;
@@ -301,10 +317,12 @@ CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
case CURLM_STATE_DONE:
/* post-transfer command */
easy->result = Curl_done(easy->easy_conn);
/* after we have DONE what we're supposed to do, go COMPLETED */
if(CURLE_OK == easy->result)
/* after we have DONE what we're supposed to do, go COMPLETED, and
it doesn't matter what the Curl_done() returned! */
easy->state = CURLM_STATE_COMPLETED;
break;
case CURLM_STATE_COMPLETED:
/* this is a completed transfer, it is likely to still be connected */
@@ -315,30 +333,66 @@ CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
return CURLM_INTERNAL_ERROR;
}
if((CURLM_STATE_COMPLETED != easy->state) &&
(CURLE_OK != easy->result)) {
if(CURLM_STATE_COMPLETED != easy->state) {
if(CURLE_OK != easy->result)
/*
* If an error was returned, and we aren't in completed now,
* then we go to completed and consider this transfer aborted.
*/
* If an error was returned, and we aren't in completed state now,
* then we go to completed and consider this transfer aborted. */
easy->state = CURLM_STATE_COMPLETED;
}
else if(CURLM_STATE_COMPLETED != easy->state)
else
/* this one still lives! */
(*running_handles)++;
}
if ((CURLM_STATE_COMPLETED == easy->state) && !easy->msg) {
/* clear out the usage of the shared DNS cache */
easy->easy_handle->hostcache = NULL;
/* now add a node to the Curl_message linked list with this info */
msg = (struct Curl_message *)malloc(sizeof(struct Curl_message));
if(!msg)
return CURLM_OUT_OF_MEMORY;
msg->extmsg.msg = CURLMSG_DONE;
msg->extmsg.easy_handle = easy->easy_handle;
msg->extmsg.data.result = easy->result;
msg->next=NULL;
easy->msg = msg;
easy->msg_num = 1; /* there is one unread message here */
multi->num_msgs++; /* increase message counter */
}
easy = easy->next; /* operate on next handle */
}
return result;
}
CURLMcode curl_multi_cleanup(CURLM *multi_handle)
{
struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
struct Curl_one_easy *easy;
struct Curl_one_easy *nexteasy;
if(GOOD_MULTI_HANDLE(multi)) {
multi->type = 0; /* not good anymore */
curl_hash_destroy(multi->hostcache);
Curl_hash_destroy(multi->hostcache);
/* remove all easy handles */
easy = multi->easy.next;
while(easy) {
nexteasy=easy->next;
/* clear out the usage of the shared DNS cache */
easy->easy_handle->hostcache = NULL;
if (easy->msg)
free(easy->msg);
free(easy);
easy = nexteasy;
}
free(multi);
@@ -348,7 +402,35 @@ CURLMcode curl_multi_cleanup(CURLM *multi_handle)
return CURLM_BAD_HANDLE;
}
CURLMsg *curl_multi_info_read(CURLM *multi_handle, int *msgs_in_queue);
CURLMsg *curl_multi_info_read(CURLM *multi_handle, int *msgs_in_queue)
{
struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
if(GOOD_MULTI_HANDLE(multi)) {
struct Curl_one_easy *easy;
if(!multi->num_msgs)
return NULL; /* no messages left to return */
easy=multi->easy.next;
while(easy) {
if(easy->msg_num) {
easy->msg_num--;
break;
}
easy = easy->next;
}
if(!easy)
return NULL; /* this means internal count confusion really */
multi->num_msgs--;
*msgs_in_queue = multi->num_msgs;
return &easy->msg->extmsg;
}
else
return NULL;
}
/*
* local variables:

View File

@@ -79,11 +79,14 @@ int Curl_parsenetrc(char *host,
char netrcbuffer[256];
int retcode=1;
int specific_login = (login[0] != 0);
char *home = NULL;
int state=NOTHING;
char state_login=0;
char state_password=0;
char state_login=0; /* Found a login keyword */
char state_password=0; /* Found a password keyword */
char state_our_login=0; /* With specific_login, found *our* login name */
#define NETRC DOT_CHAR "netrc"
@@ -116,6 +119,30 @@ int Curl_parsenetrc(char *host,
sprintf(netrcbuffer, "%s%s%s", home, DIR_CHAR, NETRC);
#ifdef MALLOCDEBUG
{
/* This is a hack to allow testing.
* If compiled with --enable-debug and CURL_DEBUG_NETRC is defined,
* then it's the path to a substitute .netrc for testing purposes *only* */
char *override = curl_getenv("CURL_DEBUG_NETRC");
if (override != NULL) {
printf("NETRC: overridden .netrc file: %s\n", home);
if (strlen(override)+1 > sizeof(netrcbuffer)) {
free(override);
if(NULL==pw)
free(home);
return -1;
}
strcpy(netrcbuffer, override);
free(override);
}
}
#endif /* MALLOCDEBUG */
file = fopen(netrcbuffer, "r");
if(file) {
char *tok;
@@ -123,6 +150,10 @@ int Curl_parsenetrc(char *host,
while(fgets(netrcbuffer, sizeof(netrcbuffer), file)) {
tok=strtok_r(netrcbuffer, " \t\n", &tok_buf);
while(tok) {
if (login[0] && password[0])
goto done;
switch(state) {
case NOTHING:
if(strequal("machine", tok)) {
@@ -149,17 +180,23 @@ int Curl_parsenetrc(char *host,
case HOSTVALID:
/* we are now parsing sub-keywords concerning "our" host */
if(state_login) {
if (specific_login) {
state_our_login = strequal(login, tok);
}else{
strncpy(login, tok, LOGINSIZE-1);
#ifdef _NETRC_DEBUG
printf("LOGIN: %s\n", login);
#endif
}
state_login=0;
}
else if(state_password) {
if (state_our_login || !specific_login) {
strncpy(password, tok, PASSWORDSIZE-1);
#ifdef _NETRC_DEBUG
printf("PASSWORD: %s\n", password);
#endif
}
state_password=0;
}
else if(strequal("login", tok))
@@ -169,13 +206,16 @@ int Curl_parsenetrc(char *host,
else if(strequal("machine", tok)) {
/* ok, there's machine here go => */
state = HOSTFOUND;
state_our_login = 0;
}
break;
} /* switch (state) */
tok = strtok_r(NULL, " \t\n", &tok_buf);
} /* while (tok) */
} /* while fgets() */
done:
fclose(file);
}

View File

@@ -25,4 +25,9 @@
int Curl_parsenetrc(char *host,
char *login,
char *password);
/* Assume: password[0]=0, host[0] != 0.
* If login[0] = 0, search for login and password within a machine section
* in the netrc.
* If login[0] != 0, search for password within machine and login.
*/
#endif

View File

@@ -45,6 +45,10 @@
#include "progress.h"
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
static void time2str(char *r, int t)
{
int h = (t/3600);
@@ -103,6 +107,15 @@ void Curl_pgrsDone(struct connectdata *conn)
}
}
/* reset all times except redirect */
void Curl_pgrsResetTimes(struct SessionHandle *data)
{
data->progress.t_nslookup = 0.0;
data->progress.t_connect = 0.0;
data->progress.t_pretransfer = 0.0;
data->progress.t_starttransfer = 0.0;
}
void Curl_pgrsTime(struct SessionHandle *data, timerid timer)
{
switch(timer) {
@@ -134,6 +147,10 @@ void Curl_pgrsTime(struct SessionHandle *data, timerid timer)
case TIMER_POSTRANSFER:
/* this is the normal end-of-transfer thing */
break;
case TIMER_REDIRECT:
data->progress.t_redirect =
(double)Curl_tvdiff(Curl_tvnow(), data->progress.start)/1000.0;
break;
}
}

View File

@@ -34,6 +34,7 @@ typedef enum {
TIMER_STARTTRANSFER,
TIMER_POSTRANSFER,
TIMER_STARTSINGLE,
TIMER_REDIRECT,
TIMER_LAST /* must be last */
} timerid;
@@ -44,6 +45,7 @@ void Curl_pgrsSetUploadSize(struct SessionHandle *data, double size);
void Curl_pgrsSetDownloadCounter(struct SessionHandle *data, double size);
void Curl_pgrsSetUploadCounter(struct SessionHandle *data, double size);
int Curl_pgrsUpdate(struct connectdata *);
void Curl_pgrsResetTimes(struct SessionHandle *data);
void Curl_pgrsTime(struct SessionHandle *data, timerid timer);

View File

@@ -40,6 +40,7 @@
#include "setup.h"
#ifndef CURL_DISABLE_FTP
#ifdef KRB4
#define _MPRINTF_REPLACE /* we want curl-functions instead of native ones */
@@ -552,6 +553,7 @@ Curl_sec_end(struct connectdata *conn)
}
#endif /* KRB4 */
#endif /* CURL_DISABLE_FTP */
/*
* local variables:

View File

@@ -392,13 +392,15 @@ int Curl_debug(struct SessionHandle *data, curl_infotype type,
return (*data->set.fdebug)(data, type, ptr, size,
data->set.debugdata);
if(type >= CURLINFO_DATA_IN)
/* don't do the data parts now */
return 0;
switch(type) {
case CURLINFO_TEXT:
case CURLINFO_HEADER_OUT:
fwrite(s_infotype[type], 2, 1, data->set.err);
fwrite(ptr, size, 1, data->set.err);
break;
default: /* nada */
break;
}
return 0;
}

View File

@@ -23,7 +23,17 @@
* $Id$
*****************************************************************************/
/* MN 06/07/02 */
/* #define HTTP_ONLY
*/
#ifdef HTTP_ONLY
#define CURL_DISABLE_FTP
#define CURL_DISABLE_LDAP
#define CURL_DISABLE_TELNET
#define CURL_DISABLE_DICT
#define CURL_DISABLE_FILE
#define CURL_DISABLE_GOPHER
#endif
#if !defined(WIN32) && defined(_WIN32)
/* This _might_ be a good Borland fix. Please report whether this works or

View File

@@ -55,6 +55,15 @@
#undef HAVE_USERDATA_IN_PWD_CALLBACK
#endif
#if OPENSSL_VERSION_NUMBER >= 0x00907001L
/* ENGINE_load_private_key() takes four arguments */
#define HAVE_ENGINE_LOAD_FOUR_ARGS
#else
/* ENGINE_load_private_key() takes three arguments */
#undef HAVE_ENGINE_LOAD_FOUR_ARGS
#endif
#ifndef HAVE_USERDATA_IN_PWD_CALLBACK
static char global_passwd[64];
#endif
@@ -223,30 +232,22 @@ int cert_stuff(struct connectdata *conn,
SSL_CTX_set_default_passwd_cb(conn->ssl.ctx, passwd_callback);
}
#if 0
if (SSL_CTX_use_certificate_file(conn->ssl.ctx,
cert_file,
SSL_FILETYPE_PEM) != 1) {
failf(data, "unable to set certificate file (wrong password?)");
return(0);
}
if (key_file == NULL)
key_file=cert_file;
if (SSL_CTX_use_PrivateKey_file(conn->ssl.ctx,
key_file,
SSL_FILETYPE_PEM) != 1) {
failf(data, "unable to set public key file");
return(0);
}
#else
/* The '#ifdef 0' section above was removed on 17-dec-2001 */
file_type = do_file_type(cert_type);
switch(file_type) {
case SSL_FILETYPE_PEM:
/* SSL_CTX_use_certificate_chain_file() only works on PEM files */
if (SSL_CTX_use_certificate_chain_file(conn->ssl.ctx,
cert_file) != 1) {
failf(data, "unable to set certificate file (wrong password?)");
return 0;
}
break;
case SSL_FILETYPE_ASN1:
/* SSL_CTX_use_certificate_file() works with either PEM or ASN1, but
we use the case above for PEM so this can only be performed with
ASN1 files. */
if (SSL_CTX_use_certificate_file(conn->ssl.ctx,
cert_file,
file_type) != 1) {
@@ -283,11 +284,17 @@ int cert_stuff(struct connectdata *conn,
{ /* XXXX still needs some work */
EVP_PKEY *priv_key = NULL;
if (conn && conn->data && conn->data->engine) {
#ifdef HAVE_ENGINE_LOAD_FOUR_ARGS
UI_METHOD *ui_method = UI_OpenSSL();
#endif
if (!key_file || !key_file[0]) {
failf(data, "no key set to load from crypto engine\n");
return 0;
}
priv_key = ENGINE_load_private_key(conn->data->engine,key_file,
#ifdef HAVE_ENGINE_LOAD_FOUR_ARGS
ui_method,
#endif
data->set.key_passwd);
if (!priv_key) {
failf(data, "failed to load private key from crypto engine\n");
@@ -315,8 +322,6 @@ int cert_stuff(struct connectdata *conn,
return 0;
}
#endif
ssl=SSL_new(conn->ssl.ctx);
x509=SSL_get_certificate(ssl);

View File

@@ -23,6 +23,7 @@
#include "setup.h"
#ifndef CURL_DISABLE_TELNET
/* -- WIN32 approved -- */
#include <stdio.h>
#include <string.h>
@@ -1211,3 +1212,4 @@ CURLcode Curl_telnet(struct connectdata *conn)
* vim600: fdm=marker
* vim: et sw=2 ts=2 sts=2 tw=78
*/
#endif

View File

@@ -23,7 +23,8 @@
*
* $Id$
*****************************************************************************/
#ifndef CURL_DISABLE_TELNET
CURLcode Curl_telnet(struct connectdata *conn);
CURLcode Curl_telnet_done(struct connectdata *conn);
#endif
#endif

View File

@@ -32,6 +32,7 @@
int
gettimeofday (struct timeval *tp, void *nothing)
{
#ifdef WITHOUT_MM_LIB
SYSTEMTIME st;
time_t tt;
struct tm tmtm;
@@ -47,6 +48,19 @@ gettimeofday (struct timeval *tp, void *nothing)
tt = mktime (&tmtm);
tp->tv_sec = tt;
tp->tv_usec = st.wMilliseconds * 1000;
#else
/**
** The earlier time calculations using GetLocalTime
** had a time resolution of 10ms.The timeGetTime, part
** of multimedia apis offer a better time resolution
** of 1ms.Need to link against winmm.lib for this
**/
unsigned long Ticks = 0;
Ticks = timeGetTime();
tp->tv_sec = Ticks%1000;
tp->tv_usec = (Ticks - (tp->tv_sec*1000))*1000;
#endif
return 1;
}
#define HAVE_GETTIMEOFDAY

View File

@@ -168,6 +168,10 @@ compareheader(char *headerline, /* line to check */
return FALSE; /* no match */
}
/* We keep this static and global since this is read-only and NEVER
changed. It should just remain a blanked-out timeout value. */
static struct timeval notimeout={0,0};
CURLcode Curl_readwrite(struct connectdata *conn,
bool *done)
{
@@ -177,9 +181,42 @@ CURLcode Curl_readwrite(struct connectdata *conn,
ssize_t nread; /* number of bytes read */
int didwhat=0;
/* These two are used only if no other select() or _fdset() have been
invoked before this. This typicly happens if you use the multi interface
and call curl_multi_perform() without calling curl_multi_fdset()
first. */
fd_set extrareadfd;
fd_set extrawritefd;
fd_set *readfdp = k->readfdp;
fd_set *writefdp = k->writefdp;
if((k->keepon & KEEP_READ) && !readfdp) {
/* reading is requested, but no socket descriptor pointer was set */
FD_ZERO(&extrareadfd);
FD_SET(conn->sockfd, &extrareadfd);
readfdp = &extrareadfd;
/* no write, no exceptions, no timeout */
select(conn->sockfd+1, readfdp, NULL, NULL, &notimeout);
}
if((k->keepon & KEEP_WRITE) && !writefdp) {
/* writing is requested, but no socket descriptor pointer was set */
FD_ZERO(&extrawritefd);
FD_SET(conn->writesockfd, &extrawritefd);
writefdp = &extrawritefd;
/* no read, no exceptions, no timeout */
select(conn->writesockfd+1, NULL, writefdp, NULL, &notimeout);
}
do {
/* If we still have reading to do, we check if we have a readable
socket. Sometimes the reafdp is NULL, it no fd_set was done using
the multi interface and then we can do nothing but to attempt a
read to be sure. */
if((k->keepon & KEEP_READ) &&
FD_ISSET(conn->sockfd, &k->readfd)) {
(FD_ISSET(conn->sockfd, readfdp))) {
/* read! */
result = Curl_read(conn, conn->sockfd, k->buf,
@@ -294,6 +331,7 @@ CURLcode Curl_readwrite(struct connectdata *conn,
*****/
if (('\n' == *k->p) || ('\r' == *k->p)) {
int headerlen;
/* Zero-length header line means end of headers! */
if ('\r' == *k->p)
@@ -341,14 +379,16 @@ CURLcode Curl_readwrite(struct connectdata *conn,
if (data->set.http_include_header)
k->writetype |= CLIENTWRITE_BODY;
headerlen = k->p - data->state.headerbuff;
result = Curl_client_write(data, k->writetype,
data->state.headerbuff,
k->p - data->state.headerbuff);
headerlen);
if(result)
return result;
data->info.header_size += k->p - data->state.headerbuff;
conn->headerbytecount += k->p - data->state.headerbuff;
data->info.header_size += headerlen;
conn->headerbytecount += headerlen;
if(!k->header) {
/*
@@ -591,6 +631,10 @@ CURLcode Curl_readwrite(struct connectdata *conn,
if (data->set.http_include_header)
k->writetype |= CLIENTWRITE_BODY;
if(data->set.verbose)
Curl_debug(data, CURLINFO_HEADER_IN,
k->p, k->hbuflen);
result = Curl_client_write(data, k->writetype, k->p,
k->hbuflen);
if(result)
@@ -680,6 +724,10 @@ CURLcode Curl_readwrite(struct connectdata *conn,
} /* this is the first time we write a body part */
k->bodywrites++;
/* pass data to the debug function before it gets "dechunked" */
if(data->set.verbose)
Curl_debug(data, CURLINFO_DATA_IN, k->str, nread);
if(conn->bits.chunk) {
/*
* Bless me father for I have sinned. Here comes a chunked
@@ -735,8 +783,12 @@ CURLcode Curl_readwrite(struct connectdata *conn,
} /* if (! header and data to read ) */
} /* if( read from socket ) */
/* If we still have writing to do, we check if we have a writable
socket. Sometimes the writefdp is NULL, it no fd_set was done using
the multi interface and then we can do nothing but to attempt a
write to be sure. */
if((k->keepon & KEEP_WRITE) &&
FD_ISSET(conn->writesockfd, &k->writefd)) {
(FD_ISSET(conn->writesockfd, writefdp)) ) {
/* write */
int i, si;
@@ -820,6 +872,11 @@ CURLcode Curl_readwrite(struct connectdata *conn,
conn->upload_present = 0; /* no more bytes left */
}
if(data->set.verbose)
Curl_debug(data, CURLINFO_DATA_OUT, conn->upload_fromhere,
bytes_written);
k->writebytecount += bytes_written;
Curl_pgrsSetUploadCounter(data, (double)k->writebytecount);
@@ -913,6 +970,9 @@ CURLcode Curl_readwrite_init(struct connectdata *conn)
Curl_pgrsTime(data, TIMER_PRETRANSFER);
Curl_speedinit(data);
Curl_pgrsSetUploadCounter(data, 0);
Curl_pgrsSetDownloadCounter(data, 0);
if (!conn->getheader) {
k->header = FALSE;
if(conn->size > 0)
@@ -958,11 +1018,13 @@ void Curl_single_fdset(struct connectdata *conn,
if(conn->keep.keepon & KEEP_READ) {
FD_SET(conn->sockfd, read_fd_set);
*max_fd = conn->sockfd;
conn->keep.readfdp = read_fd_set; /* store the address of the set */
}
if(conn->keep.keepon & KEEP_WRITE) {
FD_SET(conn->writesockfd, write_fd_set);
if(conn->writesockfd > *max_fd)
*max_fd = conn->writesockfd;
conn->keep.writefdp = write_fd_set; /* store the address of the set */
}
/* we don't use exceptions, only touch that one to prevent compiler
warnings! */
@@ -1002,6 +1064,9 @@ Transfer(struct connectdata *conn)
if(!conn->getheader && data->set.no_body)
return CURLE_OK;
k->writefdp = &k->writefd; /* store the address of the set */
k->readfdp = &k->readfd; /* store the address of the set */
while (!done) {
struct timeval interval;
k->readfd = k->rkeepfd; /* set these every lap in the loop */
@@ -1009,8 +1074,7 @@ Transfer(struct connectdata *conn)
interval.tv_sec = 1;
interval.tv_usec = 0;
switch (select (k->maxfd, &k->readfd, &k->writefd, NULL,
&interval)) {
switch (select (k->maxfd, k->readfdp, k->writefdp, NULL, &interval)) {
case -1: /* select() error, stop reading */
#ifdef EINTR
/* The EINTR is not serious, and it seems you might get this more
@@ -1124,12 +1188,20 @@ CURLcode Curl_perform(struct SessionHandle *data)
* may be free()ed in the Curl_done() function.
*/
newurl = conn->newurl?strdup(conn->newurl):NULL;
else
else {
/* The transfer phase returned error, we mark the connection to get
* closed to prevent being re-used. This is becasue we can't
* possibly know if the connection is in a good shape or not now. */
conn->bits.close = TRUE;
if(-1 !=conn->secondarysocket) {
/* if we failed anywhere, we must clean up the secondary socket if
it was used */
sclose(conn->secondarysocket);
conn->secondarysocket=-1;
}
}
/* Always run Curl_done(), even if some of the previous calls
failed, but return the previous (original) error code */
res2 = Curl_done(conn);
@@ -1262,7 +1334,6 @@ CURLcode Curl_perform(struct SessionHandle *data)
*/
switch(data->info.httpcode) {
case 300: /* Multiple Choices */
case 301: /* Moved Permanently */
case 306: /* Not used */
case 307: /* Temporary Redirect */
default: /* for all unknown ones */
@@ -1270,6 +1341,27 @@ CURLcode Curl_perform(struct SessionHandle *data)
* seem to be OK to POST to.
*/
break;
case 301: /* Moved Permanently */
/* (quote from RFC2616, section 10.3.2):
*
* Note: When automatically redirecting a POST request after
* receiving a 301 status code, some existing HTTP/1.0 user agents
* will erroneously change it into a GET request.
*
* ----
* Warning: Because most of importants user agents do this clear
* RFC2616 violation, many webservers expect this misbehavior. So
* these servers often answers to a POST request with an error page.
* To be sure that libcurl gets the page that most user agents
* would get, libcurl has to force GET:
*/
if( data->set.httpreq == HTTPREQ_POST
|| data->set.httpreq == HTTPREQ_POST_FORM) {
infof(data,
"Violate RFC 2616/10.3.2 and switch from POST to GET\n");
data->set.httpreq = HTTPREQ_GET;
}
break;
case 302: /* Found */
/* (From 10.3.3)
@@ -1291,8 +1383,11 @@ CURLcode Curl_perform(struct SessionHandle *data)
case 303: /* See Other */
/* Disable both types of POSTs, since doing a second POST when
* following isn't what anyone would want! */
if(data->set.httpreq != HTTPREQ_GET) {
data->set.httpreq = HTTPREQ_GET; /* enforce GET request */
infof(data, "Disables POST, goes with GET\n");
infof(data, "Disables POST, goes with %s\n",
data->set.no_body?"HEAD":"GET");
}
break;
case 304: /* Not Modified */
/* 304 means we did a conditional request and it was "Not modified".
@@ -1309,6 +1404,8 @@ CURLcode Curl_perform(struct SessionHandle *data)
*/
break;
}
Curl_pgrsTime(data, TIMER_REDIRECT);
Curl_pgrsResetTimes(data);
continue;
}
}

456
lib/url.c
View File

@@ -72,6 +72,10 @@
#include <inet.h>
#endif
#ifdef HAVE_SETJMP_H
#include <setjmp.h>
#endif
#ifndef HAVE_SELECT
#error "We can't compile without select() support!"
#endif
@@ -120,6 +124,7 @@
#ifdef KRB4
#include "security.h"
#endif
/* The last #include file should be: */
#ifdef MALLOCDEBUG
#include "memdebug.h"
@@ -138,11 +143,17 @@ static unsigned int ConnectionStore(struct SessionHandle *data,
#ifndef RETSIGTYPE
#define RETSIGTYPE void
#endif
#ifdef HAVE_SIGSETJMP
extern sigjmp_buf curl_jmpenv;
#endif
static
RETSIGTYPE alarmfunc(int signal)
{
/* this is for "-ansi -Wall -pedantic" to stop complaining! (rabe) */
(void)signal;
#ifdef HAVE_SIGSETJMP
siglongjmp(curl_jmpenv, 1);
#endif
return;
}
#endif
@@ -182,11 +193,13 @@ CURLcode Curl_close(struct SessionHandle *data)
if(data->state.headerbuff)
free(data->state.headerbuff);
#ifndef CURL_DISABLE_HTTP
if(data->set.cookiejar)
/* we have a "destination" for all the cookies to get dumped to */
Curl_cookie_output(data->cookies, data->set.cookiejar);
Curl_cookie_cleanup(data->cookies);
#endif
/* free the connection cache */
free(data->state.connects);
@@ -441,7 +454,7 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, ...)
/*
* Parse the $HOME/.netrc file
*/
data->set.use_netrc = va_arg(param, long)?TRUE:FALSE;
data->set.use_netrc = va_arg(param, long);
break;
case CURLOPT_FOLLOWLOCATION:
/*
@@ -495,13 +508,34 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, ...)
data->set.ssl.version = va_arg(param, long);
break;
case CURLOPT_COOKIESESSION:
/*
* Set this option to TRUE to start a new "cookie session". It will
* prevent the forthcoming read-cookies-from-file actions to accept
* cookies that are marked as being session cookies, as they belong to a
* previous session.
*
* In the original Netscape cookie spec, "session cookies" are cookies
* with no expire date set. RFC2109 describes the same action if no
* 'Max-Age' is set and RFC2965 includes the RFC2109 description and adds
* a 'Discard' action that can enforce the discard even for cookies that
* have a Max-Age.
*
* We run mostly with the original cookie spec, as hardly anyone implements
* anything else.
*/
data->set.cookiesession = (bool)va_arg(param, long);
break;
#ifndef CURL_DISABLE_HTTP
case CURLOPT_COOKIEFILE:
/*
* Set cookie file to read and parse. Can be used multiple times.
*/
cookiefile = (char *)va_arg(param, void *);
if(cookiefile)
data->cookies = Curl_cookie_init(cookiefile, data->cookies);
data->cookies = Curl_cookie_init(cookiefile, data->cookies,
data->set.cookiesession);
break;
case CURLOPT_COOKIEJAR:
@@ -514,8 +548,11 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, ...)
* Activate the cookie parser. This may or may not already
* have been made.
*/
data->cookies = Curl_cookie_init(NULL, data->cookies);
data->cookies = Curl_cookie_init(NULL, data->cookies,
data->set.cookiesession);
break;
#endif
case CURLOPT_WRITEHEADER:
/*
* Custom pointer to pass the header write callback function
@@ -819,6 +856,7 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, ...)
* defaults to CURLOPT_STDERR for normal operations.
*/
data->set.debugdata = va_arg(param, void *);
break;
case CURLOPT_STDERR:
/*
* Set to a FILE * that should receive all error writes. This
@@ -959,7 +997,13 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, ...)
* Set CA info for SSL connection. Specify file name of the CA certificate
*/
data->set.ssl.CAfile = va_arg(param, char *);
data->set.ssl.CApath = NULL; /*This does not work on windows.*/
break;
case CURLOPT_CAPATH:
/*
* Set CA path info for SSL connection. Specify directory name of the CA certificates
* which have been prepared using openssl c_rehash utility.
*/
data->set.ssl.CApath = va_arg(param, char *); /*This does not work on windows.*/
break;
case CURLOPT_TELNETOPTIONS:
/*
@@ -1241,7 +1285,8 @@ ConnectionStore(struct SessionHandle *data,
return i;
}
static CURLcode ConnectPlease(struct connectdata *conn)
static CURLcode ConnectPlease(struct connectdata *conn,
Curl_addrinfo *hostaddr)
{
CURLcode result;
Curl_ipconnect *addr;
@@ -1250,7 +1295,7 @@ static CURLcode ConnectPlease(struct connectdata *conn)
* Connect to server/proxy
*************************************************************/
result= Curl_connecthost(conn,
conn->hostaddr,
hostaddr,
conn->port,
&conn->firstsocket,
&addr);
@@ -1264,7 +1309,7 @@ static CURLcode ConnectPlease(struct connectdata *conn)
memset((char *) &conn->serv_addr, '\0', sizeof(conn->serv_addr));
memcpy((char *)&(conn->serv_addr.sin_addr),
(struct in_addr *)addr, sizeof(struct in_addr));
conn->serv_addr.sin_family = conn->hostaddr->h_addrtype;
conn->serv_addr.sin_family = hostaddr->h_addrtype;
conn->serv_addr.sin_port = htons(conn->port);
#endif
}
@@ -1272,7 +1317,8 @@ static CURLcode ConnectPlease(struct connectdata *conn)
return result;
}
static void verboseconnect(struct connectdata *conn)
static void verboseconnect(struct connectdata *conn,
Curl_addrinfo *hostaddr)
{
#ifdef HAVE_INET_NTOA_R
char ntoa_buf[64];
@@ -1281,6 +1327,7 @@ static void verboseconnect(struct connectdata *conn)
/* Figure out the ip-number and display the first host name it shows: */
#ifdef ENABLE_IPV6
(void)hostaddr; /* not used in the IPv6 enabled version */
{
char hbuf[NI_MAXHOST];
#ifdef NI_WITHSCOPEID
@@ -1305,7 +1352,8 @@ static void verboseconnect(struct connectdata *conn)
{
struct in_addr in;
(void) memcpy(&in.s_addr, &conn->serv_addr.sin_addr, sizeof (in.s_addr));
infof(data, "Connected to %s (%s) port %d\n", conn->hostaddr->h_name,
infof(data, "Connected to %s (%s) port %d\n",
hostaddr?hostaddr->h_name:"[re-used]",
#if defined(HAVE_INET_NTOA_R)
inet_ntoa_r(in, ntoa_buf, sizeof(ntoa_buf)),
#else
@@ -1325,8 +1373,8 @@ static CURLcode CreateConnection(struct SessionHandle *data,
char resumerange[40]="";
struct connectdata *conn;
struct connectdata *conn_temp;
char endbracket;
int urllen;
Curl_addrinfo *hostaddr;
#ifdef HAVE_ALARM
unsigned int prev_alarm;
#endif
@@ -1506,35 +1554,12 @@ static CURLcode CreateConnection(struct SessionHandle *data,
buf = data->state.buffer; /* this is our buffer */
/*************************************************************
* Take care of user and password authentication stuff
*************************************************************/
if(conn->bits.user_passwd && !data->set.use_netrc) {
data->state.user[0] =0;
data->state.passwd[0]=0;
if(*data->set.userpwd != ':') {
/* the name is given, get user+password */
sscanf(data->set.userpwd, "%127[^:]:%127[^\n]",
data->state.user, data->state.passwd);
}
else
/* no name given, get the password only */
sscanf(data->set.userpwd+1, "%127[^\n]", data->state.passwd);
/* check for password, if no ask for one */
if( !data->state.passwd[0] ) {
if(!data->set.fpasswd ||
data->set.fpasswd(data->set.passwd_client,
"password:", data->state.passwd,
sizeof(data->state.passwd)))
{
failf(data, "Bad password from password callback");
return CURLE_BAD_PASSWORD_ENTERED;
}
}
}
/*
* So if the URL was A://B/C,
* conn->protostr is A
* conn->gname is B
* conn->path is /C
*/
/*************************************************************
* Take care of proxy authentication stuff
@@ -1611,9 +1636,16 @@ static CURLcode CreateConnection(struct SessionHandle *data,
nope=no_proxy?strtok_r(no_proxy, ", ", &no_proxy_tok_buf):NULL;
while(nope) {
if(strlen(nope) <= strlen(conn->name)) {
unsigned int namelen;
char *endptr = strchr(conn->name, ':');
if(endptr)
namelen=endptr-conn->name;
else
namelen=strlen(conn->name);
if(strlen(nope) <= namelen) {
char *checkn=
conn->name + strlen(conn->name) - strlen(nope);
conn->name + namelen - strlen(nope);
if(strnequal(nope, checkn, strlen(nope))) {
/* no proxy for this host! */
break;
@@ -1696,6 +1728,7 @@ static CURLcode CreateConnection(struct SessionHandle *data,
conn->protocol &= ~PROT_MISSING; /* switch that one off again */
}
#ifndef CURL_DISABLE_HTTP
/************************************************************
* RESUME on a HTTP page is a tricky business. First, let's just check that
* 'range' isn't used, then set the range parameter and leave the resume as
@@ -1714,12 +1747,13 @@ static CURLcode CreateConnection(struct SessionHandle *data,
conn->bits.use_range = 1; /* switch on range usage */
}
}
#endif
/*************************************************************
* Setup internals depending on protocol
*************************************************************/
if (strequal(conn->protostr, "HTTP")) {
#ifndef CURL_DISABLE_HTTP
conn->port = (data->set.use_port && data->state.allow_port)?
data->set.use_port:PORT_HTTP;
conn->remote_port = PORT_HTTP;
@@ -1727,9 +1761,14 @@ static CURLcode CreateConnection(struct SessionHandle *data,
conn->curl_do = Curl_http;
conn->curl_done = Curl_http_done;
conn->curl_connect = Curl_http_connect;
#else
failf(data, LIBCURL_NAME
" was built with HTTP disabled, http: not supported!");
return CURLE_UNSUPPORTED_PROTOCOL;
#endif
}
else if (strequal(conn->protostr, "HTTPS")) {
#ifdef USE_SSLEAY
#if defined(USE_SSLEAY) && !defined(CURL_DISABLE_HTTP)
conn->port = (data->set.use_port && data->state.allow_port)?
data->set.use_port:PORT_HTTPS;
@@ -1747,6 +1786,7 @@ static CURLcode CreateConnection(struct SessionHandle *data,
#endif /* !USE_SSLEAY */
}
else if (strequal(conn->protostr, "GOPHER")) {
#ifndef CURL_DISABLE_GOPHER
conn->port = (data->set.use_port && data->state.allow_port)?
data->set.use_port:PORT_GOPHER;
conn->remote_port = PORT_GOPHER;
@@ -1759,9 +1799,16 @@ static CURLcode CreateConnection(struct SessionHandle *data,
conn->protocol |= PROT_GOPHER;
conn->curl_do = Curl_http;
conn->curl_done = Curl_http_done;
#else
failf(data, LIBCURL_NAME
" was built with GOPHER disabled, gopher: not supported!");
#endif
}
else if(strequal(conn->protostr, "FTP") ||
strequal(conn->protostr, "FTPS")) {
/* MN 06/07/02 */
#ifndef CURL_DISABLE_FTP
char *type;
if(strequal(conn->protostr, "FTPS")) {
@@ -1789,8 +1836,13 @@ static CURLcode CreateConnection(struct SessionHandle *data,
failf(data, "ftps does not work through http proxy!");
return CURLE_UNSUPPORTED_PROTOCOL;
}
#ifndef CURL_DISABLE_HTTP
conn->curl_do = Curl_http;
conn->curl_done = Curl_http_done;
#else
failf(data, "FTP over http proxy requires HTTP support built-in!");
return CURLE_UNSUPPORTED_PROTOCOL;
#endif
}
else {
conn->curl_do = Curl_ftp;
@@ -1809,7 +1861,7 @@ static CURLcode CreateConnection(struct SessionHandle *data,
}
if(type) {
char command;
*type=0;
*type=0; /* it was in the middle of the hostname */
command = toupper(type[6]);
switch(command) {
case 'A': /* ASCII mode */
@@ -1825,8 +1877,16 @@ static CURLcode CreateConnection(struct SessionHandle *data,
break;
}
}
/* MN 06/07/02 */
#else /* CURL_DISABLE_FTP */
failf(data, LIBCURL_NAME
" was built with FTP disabled, ftp/ftps: not supported!");
return CURLE_UNSUPPORTED_PROTOCOL;
#endif
}
else if(strequal(conn->protostr, "TELNET")) {
#ifndef CURL_DISABLE_TELNET
/* telnet testing factory */
conn->protocol |= PROT_TELNET;
@@ -1835,24 +1895,39 @@ static CURLcode CreateConnection(struct SessionHandle *data,
conn->remote_port = PORT_TELNET;
conn->curl_do = Curl_telnet;
conn->curl_done = Curl_telnet_done;
#else
failf(data, LIBCURL_NAME
" was built with TELNET disabled!");
#endif
}
else if (strequal(conn->protostr, "DICT")) {
#ifndef CURL_DISABLE_DICT
conn->protocol |= PROT_DICT;
conn->port = (data->set.use_port && data->state.allow_port)?
data->set.use_port:PORT_DICT;
conn->remote_port = PORT_DICT;
conn->curl_do = Curl_dict;
conn->curl_done = NULL; /* no DICT-specific done */
#else
failf(data, LIBCURL_NAME
" was built with DICT disabled!");
#endif
}
else if (strequal(conn->protostr, "LDAP")) {
#ifndef CURL_DISABLE_LDAP
conn->protocol |= PROT_LDAP;
conn->port = (data->set.use_port && data->state.allow_port)?
data->set.use_port:PORT_LDAP;
conn->remote_port = PORT_LDAP;
conn->curl_do = Curl_ldap;
conn->curl_done = NULL; /* no LDAP-specific done */
#else
failf(data, LIBCURL_NAME
" was built with LDAP disabled!");
#endif
}
else if (strequal(conn->protostr, "FILE")) {
#ifndef CURL_DISABLE_FILE
conn->protocol |= PROT_FILE;
conn->curl_do = Curl_file;
@@ -1869,6 +1944,10 @@ static CURLcode CreateConnection(struct SessionHandle *data,
}
return result;
#else
failf(data, LIBCURL_NAME
" was built with FILE disabled!");
#endif
}
else {
/* We fell through all checks and thus we don't support the specified
@@ -1877,86 +1956,6 @@ static CURLcode CreateConnection(struct SessionHandle *data,
return CURLE_UNSUPPORTED_PROTOCOL;
}
/*************************************************************
* .netrc scanning coming up
*************************************************************/
if(data->set.use_netrc) {
if(Curl_parsenetrc(conn->hostname,
data->state.user,
data->state.passwd)) {
infof(data, "Couldn't find host %s in the .netrc file, using defaults",
conn->hostname);
}
else
conn->bits.user_passwd = 1; /* enable user+password */
/* weather we failed or not, we don't know which fields that were filled
in anyway */
if(!data->state.user[0])
strcpy(data->state.user, CURL_DEFAULT_USER);
if(!data->state.passwd[0])
strcpy(data->state.passwd, CURL_DEFAULT_PASSWORD);
}
else if(!(conn->bits.user_passwd) &&
(conn->protocol & (PROT_FTP|PROT_HTTP)) ) {
/* This is a FTP or HTTP URL, and we haven't got the user+password in
* the extra parameter, we will now try to extract the possible
* user+password pair in a string like:
* ftp://user:password@ftp.my.site:8021/README */
char *ptr=NULL; /* assign to remove possible warnings */
if((ptr=strchr(conn->name, '@'))) {
/* there's a user+password given here, to the left of the @ */
data->state.user[0] =0;
data->state.passwd[0]=0;
if(*conn->name != ':') {
/* the name is given, get user+password */
sscanf(conn->name, "%127[^:@]:%127[^@]",
data->state.user, data->state.passwd);
}
else
/* no name given, get the password only */
sscanf(conn->name+1, "%127[^@]", data->state.passwd);
if(data->state.user[0]) {
char *newname=curl_unescape(data->state.user, 0);
if(strlen(newname) < sizeof(data->state.user)) {
strcpy(data->state.user, newname);
}
/* if the new name is longer than accepted, then just use
the unconverted name, it'll be wrong but what the heck */
free(newname);
}
/* check for password, if no ask for one */
if( !data->state.passwd[0] ) {
if(!data->set.fpasswd ||
data->set.fpasswd(data->set.passwd_client,
"password:", data->state.passwd,
sizeof(data->state.passwd))) {
failf(data, "Bad password from password callback");
return CURLE_BAD_PASSWORD_ENTERED;
}
}
else {
/* we have a password found in the URL, decode it! */
char *newpasswd=curl_unescape(data->state.passwd, 0);
if(strlen(newpasswd) < sizeof(data->state.passwd)) {
strcpy(data->state.passwd, newpasswd);
}
free(newpasswd);
}
conn->name = ++ptr;
conn->bits.user_passwd=TRUE; /* enable user+password */
}
else {
strcpy(data->state.user, CURL_DEFAULT_USER);
strcpy(data->state.passwd, CURL_DEFAULT_PASSWORD);
}
}
/*************************************************************
* Figure out the remote port number
*
@@ -1965,29 +1964,32 @@ static CURLcode CreateConnection(struct SessionHandle *data,
*
* To be able to detect port number flawlessly, we must not confuse them
* IPv6-specified addresses in the [0::1] style. (RFC2732)
*
* The conn->name is currently [user:passwd@]host[:port] where host could
* be a hostname, IPv4 address or IPv6 address.
*************************************************************/
if((1 == sscanf(conn->name, "[%*39[0-9a-fA-F:.]%c", &endbracket)) &&
(']' == endbracket)) {
/* This is a (IPv6-style) specified IP-address. We support _any_
IP within brackets to be really generic. */
conn->name++; /* pass the starting bracket */
tmp = strchr(conn->name, ']');
*tmp = 0; /* zero terminate */
tmp++; /* pass the ending bracket */
if(':' != *tmp)
tmp = NULL; /* no port number available */
}
else {
/* traditional IPv4-style port-extracting */
tmp = strchr(conn->name, ':');
}
tmp = strrchr(conn->name, ':');
if (tmp) {
*tmp++ = '\0'; /* cut off the name there */
conn->remote_port = atoi(tmp);
char *rest;
unsigned long port;
port=strtoul(tmp+1, &rest, 10); /* Port number must be decimal */
if (rest != (tmp+1) && *rest == '\0') {
/* The colon really did have only digits after it,
* so it is either a port number or a mistake */
if (port > 0xffff) { /* Single unix standard says port numbers are
* 16 bits long */
failf(data, "Port number too large: %lu", port);
return CURLE_URL_MALFORMAT;
}
*tmp = '\0'; /* cut off the name there */
conn->remote_port = port;
}
}
if(data->change.proxy) {
@@ -2041,6 +2043,138 @@ static CURLcode CreateConnection(struct SessionHandle *data,
free(proxydup); /* free the duplicate pointer and not the modified */
}
/*************************************************************
* Take care of user and password authentication stuff
*************************************************************/
/*
* Inputs: data->set.userpwd (CURLOPT_USERPWD)
* data->set.fpasswd (CURLOPT_PASSWDFUNCTION)
* data->set.use_netrc (CURLOPT_NETRC)
* conn->hostname
* netrc file
* hard-coded defaults
*
* Outputs: (almost :- all currently undefined)
* conn->bits.user_passwd - non-zero if non-default passwords exist
* conn->state.user - non-zero length if defined
* conn->state.passwd - ditto
* conn->hostname - remove user name and password
*/
/* At this point, we're hoping all the other special cases have
* been taken care of, so conn->hostname is at most
* [user[:password]]@]hostname
*
* We need somewhere to put the embedded details, so do that first.
*/
data->state.user[0] =0; /* to make everything well-defined */
data->state.passwd[0]=0;
if (conn->protocol & (PROT_FTP|PROT_HTTP)) {
/* This is a FTP or HTTP URL, we will now try to extract the possible
* user+password pair in a string like:
* ftp://user:password@ftp.my.site:8021/README */
char *ptr=strchr(conn->name, '@');
char *userpass = conn->name;
if(ptr != NULL) {
/* there's a user+password given here, to the left of the @ */
conn->name = conn->hostname = ++ptr;
/* So the hostname is sane. Only bother interpreting the
* results if we could care. It could still be wasted
* work because it might be overtaken by the programmatically
* set user/passwd, but doing that first adds more cases here :-(
*/
if (data->set.use_netrc != CURL_NETRC_REQUIRED) {
/* We could use the one in the URL */
conn->bits.user_passwd = 1; /* enable user+password */
if(*userpass != ':') {
/* the name is given, get user+password */
sscanf(userpass, "%127[^:@]:%127[^@]",
data->state.user, data->state.passwd);
}
else
/* no name given, get the password only */
sscanf(userpass, ":%127[^@]", data->state.passwd);
if(data->state.user[0]) {
char *newname=curl_unescape(data->state.user, 0);
if(strlen(newname) < sizeof(data->state.user)) {
strcpy(data->state.user, newname);
}
/* if the new name is longer than accepted, then just use
the unconverted name, it'll be wrong but what the heck */
free(newname);
}
if (data->state.passwd[0]) {
/* we have a password found in the URL, decode it! */
char *newpasswd=curl_unescape(data->state.passwd, 0);
if(strlen(newpasswd) < sizeof(data->state.passwd)) {
strcpy(data->state.passwd, newpasswd);
}
free(newpasswd);
}
}
}
}
/* Programmatically set password:
* - always applies, if available
* - takes precedence over the values we just set above
* so scribble it over the top.
* User-supplied passwords are assumed not to need unescaping.
*
* user_password is set in "inherite initial knowledge' above,
* so it doesn't have to be set in this block
*/
if (data->set.userpwd != NULL) {
if(*data->set.userpwd != ':') {
/* the name is given, get user+password */
sscanf(data->set.userpwd, "%127[^:]:%127[^\n]",
data->state.user, data->state.passwd);
}
else
/* no name given, get the password only */
sscanf(data->set.userpwd+1, "%127[^\n]", data->state.passwd);
}
if (data->set.use_netrc != CURL_NETRC_IGNORED &&
data->state.passwd[0] == '\0' ) { /* need passwd */
if(Curl_parsenetrc(conn->hostname,
data->state.user,
data->state.passwd)) {
infof(data, "Couldn't find host %s in the .netrc file, using defaults",
conn->hostname);
} else
conn->bits.user_passwd = 1; /* enable user+password */
}
/* if we have a user but no password, ask for one */
if(conn->bits.user_passwd &&
!data->state.passwd[0] ) {
if(!data->set.fpasswd ||
data->set.fpasswd(data->set.passwd_client,
"password:", data->state.passwd,
sizeof(data->state.passwd)))
return CURLE_BAD_PASSWORD_ENTERED;
}
/* So we could have a password but no user; that's just too bad. */
/* If our protocol needs a password and we have none, use the defaults */
if ( (conn->protocol & (PROT_FTP|PROT_HTTP)) &&
!conn->bits.user_passwd) {
strcpy(data->state.user, CURL_DEFAULT_USER);
strcpy(data->state.passwd, CURL_DEFAULT_PASSWORD);
/* This is the default password, so DON'T set conn->bits.user_passwd */
}
/*************************************************************
* Check the current list of connections to see if we can
* re-use an already existing one or if we have to create a
@@ -2064,6 +2198,10 @@ static CURLcode CreateConnection(struct SessionHandle *data,
free(old_conn->proxyhost);
conn = conn_temp; /* use this connection from now on */
/* If we speak over a proxy, we need to copy the host name too, as it
might be another remote host even when re-using a connection */
strcpy(conn->gname, old_conn->gname); /* safe strcpy() */
/* we need these pointers if we speak over a proxy */
conn->hostname = conn->gname;
conn->name = &conn->gname[old_conn->name - old_conn->gname];
@@ -2165,33 +2303,31 @@ static CURLcode CreateConnection(struct SessionHandle *data,
/*************************************************************
* Resolve the name of the server or proxy
*************************************************************/
if(!data->change.proxy) {
if(conn->bits.reuse) {
/* re-used connection, no resolving is necessary */
hostaddr = NULL;
}
else if(!data->change.proxy) {
/* If not connecting via a proxy, extract the port from the URL, if it is
* there, thus overriding any defaults that might have been set above. */
conn->port = conn->remote_port; /* it is the same port */
/* Resolve target host right on */
if(!conn->hostaddr) {
/* it might already be set if reusing a connection */
conn->hostaddr = Curl_resolv(data, conn->name, conn->port,
&conn->hostent_buf);
}
if(!conn->hostaddr) {
hostaddr = Curl_resolv(data, conn->name, conn->port);
if(!hostaddr) {
failf(data, "Couldn't resolve host '%s'", conn->name);
result = CURLE_COULDNT_RESOLVE_HOST;
/* don't return yet, we need to clean up the timeout first */
}
}
else if(!conn->hostaddr) {
/* This is a proxy that hasn't been resolved yet. It may be resolved
if we're reusing an existing connection. */
else {
/* This is a proxy that hasn't been resolved yet. */
/* resolve proxy */
/* it might already be set if reusing a connection */
conn->hostaddr = Curl_resolv(data, conn->proxyhost, conn->port,
&conn->hostent_buf);
hostaddr = Curl_resolv(data, conn->proxyhost, conn->port);
if(!conn->hostaddr) {
if(!hostaddr) {
failf(data, "Couldn't resolve proxy '%s'", conn->proxyhost);
result = CURLE_COULDNT_RESOLVE_PROXY;
/* don't return yet, we need to clean up the timeout first */
@@ -2275,14 +2411,14 @@ static CURLcode CreateConnection(struct SessionHandle *data,
if(-1 == conn->firstsocket) {
/* Connect only if not already connected! */
result = ConnectPlease(conn);
result = ConnectPlease(conn, hostaddr);
Curl_pgrsTime(data, TIMER_CONNECT); /* connect done, good or bad */
if(CURLE_OK != result)
return result;
if(data->set.verbose)
verboseconnect(conn);
verboseconnect(conn, hostaddr);
if(conn->curl_connect) {
/* is there a protocol-specific connect() procedure? */
@@ -2301,7 +2437,7 @@ static CURLcode CreateConnection(struct SessionHandle *data,
else {
Curl_pgrsTime(data, TIMER_CONNECT); /* we're connected already */
if(data->set.verbose)
verboseconnect(conn);
verboseconnect(conn, hostaddr);
}
conn->now = Curl_tvnow(); /* time this *after* the connect is done, we

View File

@@ -83,7 +83,7 @@
#include "http_chunks.h" /* for the structs and enum stuff */
/* Download buffer size, keep it fairly big for speed reasons */
#define BUFSIZE (1024*20)
#define BUFSIZE CURL_MAX_WRITE_SIZE
/* Initial size of the buffer to store headers in, it'll be enlarged in case
of need. */
@@ -180,6 +180,8 @@ struct FTP {
char *cache; /* data cache between getresponse()-calls */
size_t cache_size; /* size of cache in bytes */
bool dont_check; /* set to TRUE to prevent the final (post-transfer)
file size and 226/250 status check */
};
/****************************************************************************
@@ -249,6 +251,10 @@ struct Curl_transfer_keeper {
char *uploadbuf;
int maxfd;
/* pointers to the actual descriptors we check */
fd_set *readfdp;
fd_set *writefdp;
/* the file descriptors to play with */
fd_set readfd;
fd_set writefd;
@@ -282,9 +288,6 @@ struct connectdata {
#define PROT_FTPS (1<<9)
#define PROT_SSL (1<<10) /* protocol requires SSL */
Curl_addrinfo *hostaddr; /* IP-protocol independent host info pointer list */
char *hostent_buf; /* pointer to allocated memory for name info */
#ifdef ENABLE_IPV6
struct addrinfo *serv_addr; /* the particular host we use */
#else
@@ -451,6 +454,7 @@ struct Progress {
double t_connect;
double t_pretransfer;
double t_starttransfer;
double t_redirect;
struct timeval start;
struct timeval t_startsingle;
@@ -605,6 +609,7 @@ struct UserDefined {
char *key_passwd; /* plain text private key password */
char *crypto_engine; /* name of the crypto engine to use */
char *cookiejar; /* dump all cookies to this file */
bool cookiesession; /* new cookie session? */
bool crlf; /* convert crlf on ftp upload(?) */
struct curl_slist *quote; /* after connection is established */
struct curl_slist *postquote; /* after the transfer */
@@ -647,7 +652,8 @@ struct UserDefined {
bool no_body;
bool set_port;
bool upload;
bool use_netrc;
enum CURL_NETRC_OPTION
use_netrc; /* defined in include/curl.h */
bool verbose;
bool krb4; /* kerberos4 connection requested */
bool reuse_forbid; /* forbidden to be reused, close after use */

View File

@@ -11,7 +11,7 @@
CC = gcc
STRIP = strip -s
OPENSSL_PATH = ../../openssl-0.9.6b
OPENSSL_PATH = ../../openssl-0.9.6d
# We may need these someday
# PERL = perl
@@ -36,7 +36,7 @@ else
curl_DEPENDENCIES = ../lib/libcurl.a
curl_LDADD = -L../lib -lcurl
endif
curl_LDADD += -lwsock32 -lws2_32
curl_LDADD += -lwsock32 -lws2_32 -lwinmm
ifdef SSL
curl_LDADD += -L$(OPENSSL_PATH)/out -leay32 -lssl32 -lRSAglue
endif

View File

@@ -17,5 +17,11 @@
/* Define if you have the <utime.h> header file */
#undef HAVE_UTIME_H
/* Define if you have thhe <sys/utime.h> header file */
/* Define if you have the <sys/utime.h> header file */
#undef HAVE_SYS_UTIME_H
/* Define if you have the <sys/types.h> header file */
#undef HAVE_SYS_TYPES_H
/* Define if you have the <sys/select.h> header file */
#undef HAVE_SYS_SELECT_H

View File

@@ -117,6 +117,9 @@ typedef enum {
#define CONF_MUTE (1<<28) /* force NOPROGRESS */
#define CONF_NETRC_OPT (1<<29) /* read user+password from either
* .netrc or URL*/
#ifndef HAVE_STRDUP
/* Ultrix doesn't have strdup(), so make a quick clone: */
char *strdup(char *str)
@@ -336,14 +339,16 @@ static void help(void)
#endif
" -e/--referer Referer page (H)");
puts(" -E/--cert <cert[:passwd]> Specifies your certificate file and password (HTTPS)\n"
" --cert-type <type> Specifies your certificate file type (DER/PEM/ENG) (HTTPS)\n"
" --key <key> Specifies your private key file (HTTPS)\n"
" --key-type <type> Specifies your private key file type (DER/PEM/ENG) (HTTPS)\n"
" --pass <pass> Specifies your passphrase for the private key (HTTPS)");
" --cert-type <type> Specifies certificate file type (DER/PEM/ENG) (HTTPS)\n"
" --key <key> Specifies private key file (HTTPS)\n"
" --key-type <type> Specifies private key file type (DER/PEM/ENG) (HTTPS)\n"
" --pass <pass> Specifies passphrase for the private key (HTTPS)");
puts(" --engine <eng> Specifies the crypto engine to use (HTTPS)\n"
" --cacert <file> CA certifciate to verify peer against (SSL)\n"
" --ciphers <list> What SSL ciphers to use (SSL)\n"
" --connect-timeout <seconds> Maximum time allowed for connection\n"
" --capath <directory> CA directory (made using c_rehash) to verify\n"
" peer against (SSL, NOT Windows)\n"
" --ciphers <list> What SSL ciphers to use (SSL)");
puts(" --connect-timeout <seconds> Maximum time allowed for connection\n"
" -f/--fail Fail silently (no output at all) on errors (H)\n"
" -F/--form <name=content> Specify HTTP POST data (H)\n"
" -g/--globoff Disable URL sequences and ranges using {} and []\n"
@@ -351,7 +356,8 @@ static void help(void)
puts(" -h/--help This help text\n"
" -H/--header <line> Custom header to pass to server. (H)\n"
" -i/--include Include the HTTP-header in the output (H)\n"
" -I/--head Fetch document info only (HTTP HEAD/FTP SIZE)\n"
" -I/--head Fetch document info only (HTTP HEAD/FTP SIZE)");
puts(" -j/--junk-session-cookies Ignore session cookies read from file (H)\n"
" --interface <interface> Specify the interface to be used\n"
" --krb4 <level> Enable krb4 with specified security level (F)\n"
" -K/--config Specify which config file to read\n"
@@ -359,7 +365,8 @@ static void help(void)
puts(" -L/--location Follow Location: hints (H)\n"
" -m/--max-time <seconds> Maximum time allowed for the transfer\n"
" -M/--manual Display huge help text\n"
" -n/--netrc Read .netrc for user name and password\n"
" -n/--netrc Must read .netrc for user name and password\n"
" --netrc-optional Use either .netrc or URL; overrides -n\n"
" -N/--no-buffer Disables the buffering of the output stream");
puts(" -o/--output <file> Write output to <file> instead of stdout\n"
" -O/--remote-name Write output to a file named as the remote file\n"
@@ -370,16 +377,19 @@ static void help(void)
puts(" -r/--range <range> Retrieve a byte range from a HTTP/1.1 or FTP server\n"
" -R/--remote-time Set the remote file's time on the local output\n"
" -s/--silent Silent mode. Don't output anything\n"
" -S/--show-error Show error. With -s, make curl show errors when they occur\n"
" --stderr <file> Where to redirect stderr. - means stdout.\n"
" -S/--show-error Show error. With -s, make curl show errors when they occur");
puts(" --stderr <file> Where to redirect stderr. - means stdout.\n"
" -t/--telnet-option <OPT=val> Set telnet option\n"
" --trace <file> Dump a network/debug trace to the given file\n"
" --trace-ascii <file> Like --trace but without the hex output\n"
" -T/--upload-file <file> Transfer/upload <file> to remote site\n"
" --url <URL> Another way to specify URL to work with");
puts(" -u/--user <user[:password]> Specify user and password to use\n"
" Overrides -n and --netrc-optional\n"
" -U/--proxy-user <user[:password]> Specify Proxy authentication\n"
" -v/--verbose Makes the operation more talkative\n"
" -V/--version Outputs version number then quits\n"
" -w/--write-out [format] What to output after completion\n"
" -V/--version Outputs version number then quits");
puts(" -w/--write-out [format] What to output after completion\n"
" -x/--proxy <host[:port]> Use proxy. (Default port is 1080)\n"
" --random-file <file> File to use for reading random data from (SSL)\n"
" -X/--request <command> Specific request command to use");
@@ -409,6 +419,7 @@ struct Configurable {
char *cookie; /* single line with specified cookies */
char *cookiejar; /* write to this file */
char *cookiefile; /* read from this file */
bool cookiesession; /* new session? */
bool use_resume;
bool resume_from_current;
bool disable_epsv;
@@ -445,6 +456,7 @@ struct Configurable {
char *cert;
char *cert_type;
char *cacert;
char *capath;
char *key;
char *key_type;
char *key_passwd;
@@ -452,6 +464,11 @@ struct Configurable {
bool crlf;
char *customrequest;
char *krb4level;
char *trace_dump; /* file to dump the network trace to, or NULL */
FILE *trace_stream;
bool trace_fopened;
bool trace_ascii;
long httpversion;
bool progressmode;
bool nobuffer;
@@ -960,6 +977,8 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */
#ifdef USE_ENVIRONMENT
{"5f", "environment", FALSE},
#endif
{"5g", "trace", TRUE},
{"5h", "trace-ascii", TRUE},
{"0", "http1.0", FALSE},
{"1", "tlsv1", FALSE},
{"2", "sslv2", FALSE},
@@ -983,6 +1002,7 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */
{"Ed","key-type", TRUE},
{"Ee","pass", TRUE},
{"Ef","engine", TRUE},
{"Eg","capath ", TRUE},
{"f", "fail", FALSE},
{"F", "form", TRUE},
{"g", "globoff", FALSE},
@@ -991,12 +1011,14 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */
{"H", "header", TRUE},
{"i", "include", FALSE},
{"I", "head", FALSE},
{"j", "junk-session-cookies", FALSE},
{"K", "config", TRUE},
{"l", "list-only", FALSE},
{"L", "location", FALSE},
{"m", "max-time", TRUE},
{"M", "manual", FALSE},
{"n", "netrc", FALSE},
{"no", "netrc-optional", FALSE},
{"N", "no-buffer", FALSE},
{"o", "output", TRUE},
{"O", "remote-name", FALSE},
@@ -1140,6 +1162,13 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */
config->writeenv ^= TRUE;
break;
#endif
case 'g': /* --trace */
GetStr(&config->trace_dump, nextarg);
break;
case 'h': /* --trace-ascii */
GetStr(&config->trace_dump, nextarg);
config->trace_ascii = TRUE;
break;
default: /* the URL! */
{
struct getout *url;
@@ -1310,6 +1339,10 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */
case 'f': /* crypto engine */
GetStr(&config->engine, nextarg);
break;
case 'g': /* CA info PEM file */
/* CA cert directory */
GetStr(&config->capath, nextarg);
break;
default: /* certificate file */
{
char *ptr = strchr(nextarg, ':');
@@ -1372,6 +1405,9 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */
case 'i':
config->conf ^= CONF_HEADER; /* include the HTTP header as well */
break;
case 'j':
config->cookiesession ^= TRUE;
break;
case 'I':
/*
* This is a bit tricky. We either SET both bits, or we clear both
@@ -1411,10 +1447,18 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */
hugehelp();
return PARAM_HELP_REQUESTED;
case 'n':
switch(subletter) {
case 'o': /* CA info PEM file */
/* use .netrc or URL */
config->conf ^= CONF_NETRC_OPT;
break;
default:
/* pick info from .netrc, if this is used for http, curl will
automatically enfore user+password with the request */
config->conf ^= CONF_NETRC;
break;
}
break;
case 'N':
/* disable the output I/O buffering */
config->nobuffer ^= 1;
@@ -1504,7 +1548,8 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */
break;
case 't':
/* Telnet options */
config->telnet_options = curl_slist_append(config->telnet_options, nextarg);
config->telnet_options =
curl_slist_append(config->telnet_options, nextarg);
break;
case 'T':
/* we are uploading */
@@ -1571,16 +1616,16 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */
nextarg++;
default:
/* If-Modified-Since: (section 14.28 in RFC2068) */
config->timecond = TIMECOND_IFMODSINCE;
config->timecond = CURL_TIMECOND_IFMODSINCE;
break;
case '-':
/* If-Unmodified-Since: (section 14.24 in RFC2068) */
config->timecond = TIMECOND_IFUNMODSINCE;
config->timecond = CURL_TIMECOND_IFUNMODSINCE;
nextarg++;
break;
case '=':
/* Last-Modified: (section 14.29 in RFC2068) */
config->timecond = TIMECOND_LASTMOD;
config->timecond = CURL_TIMECOND_LASTMOD;
nextarg++;
break;
}
@@ -1591,7 +1636,7 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */
struct stat statbuf;
if(-1 == stat(nextarg, &statbuf)) {
/* failed, remove time condition */
config->timecond = TIMECOND_NONE;
config->timecond = CURL_TIMECOND_NONE;
}
else {
/* pull the time out from the file */
@@ -1914,6 +1959,101 @@ void progressbarinit(struct ProgressData *bar,
bar->out = config->errors;
}
static
void dump(const char *text,
FILE *stream, unsigned char *ptr, size_t size,
bool nohex)
{
size_t i;
size_t c;
unsigned int width=0x10;
if(nohex)
/* without the hex output, we can fit more on screen */
width = 0x40;
fprintf(stream, "%s, %d bytes (0x%x)\n", text, size, size);
for(i=0; i<size; i+= width) {
fprintf(stream, "%04x: ", i);
if(!nohex) {
/* hex not disabled, show it */
for(c = 0; c < width; c++)
if(i+c < size)
fprintf(stream, "%02x ", ptr[i+c]);
else
fputs(" ", stream);
}
for(c = 0; (c < width) && (i+c < size); c++) {
/* check for 0D0A; if found, skip past and start a new line of output */
if (nohex && (i+c+1 < size) && ptr[i+c]==0x0D && ptr[i+c+1]==0x0A) {
i+=(c+2-width);
break;
}
fprintf(stream, "%c",
(ptr[i+c]>=0x20) && (ptr[i+c]<0x80)?ptr[i+c]:'.');
/* check again for 0D0A, to avoid an extra \n if it's at width */
if (nohex && (i+c+2 < size) && ptr[i+c+1]==0x0D && ptr[i+c+2]==0x0A) {
i+=(c+3-width);
break;
}
}
fputc('\n', stream); /* newline */
}
}
static
int my_trace(CURL *handle, curl_infotype type,
unsigned char *data, size_t size,
void *userp)
{
struct Configurable *config = (struct Configurable *)userp;
FILE *output=config->errors;
const char *text;
(void)handle; /* prevent compiler warning */
if(!config->trace_stream) {
/* open for append */
if(strequal("-", config->trace_dump))
config->trace_stream = stdout;
else {
config->trace_stream = fopen(config->trace_dump, "w");
config->trace_fopened = TRUE;
}
}
if(config->trace_stream)
output = config->trace_stream;
switch (type) {
case CURLINFO_TEXT:
fprintf(output, "== Info: %s", data);
default: /* in case a new one is introduced to shock us */
return 0;
case CURLINFO_HEADER_OUT:
text = "=> Send header";
break;
case CURLINFO_DATA_OUT:
text = "=> Send data ";
break;
case CURLINFO_HEADER_IN:
text = "<= Recv header";
break;
case CURLINFO_DATA_IN:
text = "<= Recv data";
break;
}
dump(text, output, data, size, config->trace_ascii);
return 0;
}
void free_config_fields(struct Configurable *config)
{
if(config->random_file)
@@ -1950,6 +2090,8 @@ void free_config_fields(struct Configurable *config)
curl_formfree(config->httppost);
if(config->cacert)
free(config->cacert);
if(config->capath)
free(config->capath);
if(config->cookiejar)
free(config->cookiejar);
@@ -2125,6 +2267,18 @@ operate(struct Configurable *config, int argc, char *argv[])
urlnode = config->url_list;
if(config->headerfile) {
/* open file for output: */
if(strcmp(config->headerfile,"-")) {
heads.filename = config->headerfile;
headerfilep=NULL;
}
else
headerfilep=stdout;
heads.stream = headerfilep;
heads.config = config;
}
/* loop through the list of given URLs */
while(urlnode) {
@@ -2291,18 +2445,6 @@ operate(struct Configurable *config, int argc, char *argv[])
config->resume_from_current) {
config->resume_from = -1; /* -1 will then force get-it-yourself */
}
if(config->headerfile) {
/* open file for output: */
if(strcmp(config->headerfile,"-")) {
heads.filename = config->headerfile;
headerfilep=NULL;
}
else
headerfilep=stdout;
heads.stream = headerfilep;
heads.config = config;
}
if(outs.stream && isatty(fileno(outs.stream)) &&
!(config->conf&(CONF_UPLOAD|CONF_HTTPPOST)))
/* we send the output to a tty and it isn't an upload operation,
@@ -2377,7 +2519,6 @@ operate(struct Configurable *config, int argc, char *argv[])
curl_easy_setopt(curl, CURLOPT_INFILESIZE, infilesize);
curl_easy_setopt(curl, CURLOPT_URL, url); /* what to fetch */
curl_easy_setopt(curl, CURLOPT_PROXY, config->proxy); /* proxy to use */
curl_easy_setopt(curl, CURLOPT_VERBOSE, config->conf&CONF_VERBOSE);
curl_easy_setopt(curl, CURLOPT_HEADER, config->conf&CONF_HEADER);
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, config->conf&CONF_NOPROGRESS);
curl_easy_setopt(curl, CURLOPT_NOBODY, config->conf&CONF_NOBODY);
@@ -2387,7 +2528,14 @@ operate(struct Configurable *config, int argc, char *argv[])
curl_easy_setopt(curl, CURLOPT_FTPLISTONLY,
config->conf&CONF_FTPLISTONLY);
curl_easy_setopt(curl, CURLOPT_FTPAPPEND, config->conf&CONF_FTPAPPEND);
curl_easy_setopt(curl, CURLOPT_NETRC, config->conf&CONF_NETRC);
if (config->conf&CONF_NETRC_OPT)
curl_easy_setopt(curl, CURLOPT_NETRC, CURL_NETRC_OPTIONAL);
else if (config->conf&CONF_NETRC)
curl_easy_setopt(curl, CURLOPT_NETRC, CURL_NETRC_REQUIRED);
else
curl_easy_setopt(curl, CURLOPT_NETRC, CURL_NETRC_IGNORED);
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION,
config->conf&CONF_FOLLOWLOCATION);
curl_easy_setopt(curl, CURLOPT_TRANSFERTEXT, config->conf&CONF_GETTEXT);
@@ -2420,8 +2568,9 @@ operate(struct Configurable *config, int argc, char *argv[])
curl_easy_setopt(curl, CURLOPT_SSLKEYTYPE, config->key_type);
curl_easy_setopt(curl, CURLOPT_SSLKEYPASSWD, config->key_passwd);
if(config->cacert) {
curl_easy_setopt(curl, CURLOPT_CAINFO, config->cacert);
if(config->cacert || config->capath) {
if (config->cacert) curl_easy_setopt(curl, CURLOPT_CAINFO, config->cacert);
if (config->capath) curl_easy_setopt(curl, CURLOPT_CAPATH, config->capath);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, TRUE);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 2);
}
@@ -2447,6 +2596,9 @@ operate(struct Configurable *config, int argc, char *argv[])
curl_easy_setopt(curl, CURLOPT_COOKIEFILE, config->cookiefile);
/* cookie jar was added in 7.9 */
curl_easy_setopt(curl, CURLOPT_COOKIEJAR, config->cookiejar);
/* cookie session added in 7.9.7 */
curl_easy_setopt(curl, CURLOPT_COOKIESESSION, config->cookiesession);
curl_easy_setopt(curl, CURLOPT_SSLVERSION, config->ssl_version);
curl_easy_setopt(curl, CURLOPT_TIMECONDITION, config->timecond);
curl_easy_setopt(curl, CURLOPT_TIMEVALUE, config->condtime);
@@ -2486,6 +2638,14 @@ operate(struct Configurable *config, int argc, char *argv[])
/* disable it */
curl_easy_setopt(curl, CURLOPT_FTP_USE_EPSV, FALSE);
/* new in curl 7.9.7 */
if(config->trace_dump) {
curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, my_trace);
curl_easy_setopt(curl, CURLOPT_DEBUGDATA, config);
config->conf |= CONF_VERBOSE; /* force verbose */
}
curl_easy_setopt(curl, CURLOPT_VERBOSE, config->conf&CONF_VERBOSE);
res = curl_easy_perform(curl);
if((config->progressmode == CURL_PROGRESS_BAR) &&
@@ -2512,9 +2672,6 @@ operate(struct Configurable *config, int argc, char *argv[])
fprintf(config->errors, "curl: (%d) %s\n", res, errorbuffer);
#endif
if(config->headerfile && !headerfilep && heads.stream)
fclose(heads.stream);
if (outfile && !strequal(outfile, "-") && outs.stream)
fclose(outs.stream);
@@ -2568,6 +2725,12 @@ operate(struct Configurable *config, int argc, char *argv[])
} /* while-loop through all URLs */
if(config->headerfile && !headerfilep && heads.stream)
fclose(heads.stream);
if(config->trace_fopened)
fclose(config->trace_stream);
if(allocuseragent)
free(config->useragent);

View File

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

View File

@@ -21,9 +21,18 @@
* $Id$
*****************************************************************************/
#include "setup.h"
#include <stdio.h>
#include <string.h>
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif
#include <curl/curl.h>
#define _MPRINTF_REPLACE /* we want curl-functions instead of native ones */

View File

@@ -19,8 +19,10 @@ data to sent to the client on its request and later verified that it arrived
safely. Set the nocheck=1 to prevent the test script to verify the arrival
of this data.
</data>
<datacheck>
if the data is sent but this is what should be checked afterwards
<datacheck [nonewline=yes]>
if the data is sent but this is what should be checked afterwards. If
'nonewline' is set, we will cut off the trailing newline of this given data
before comparing with the one actually received by the client
</datacheck>
<size>
number to return on a ftp SIZE command

View File

@@ -15,5 +15,6 @@ test104 test113 test122 test18 test23 test301 test402 test9 \
test105 test114 test123 test19 test24 test302 test43 test31 \
test106 test115 test124 test190 test25 test303 test44 test38 \
test107 test116 test125 test2 test26 test33 test45 test126 \
test304 test39 test32 test128 test48
test304 test39 test32 test128 test48 \
test130 test131 test132 test133 test134 test135

49
tests/data/test130 Normal file
View File

@@ -0,0 +1,49 @@
#
# Server-side
<reply name="1">
<data>
total 20
drwxr-xr-x 8 98 98 512 Oct 22 13:06 .
drwxr-xr-x 8 98 98 512 Oct 22 13:06 ..
drwxr-xr-x 2 98 98 512 May 2 1996 .NeXT
-r--r--r-- 1 0 1 35 Jul 16 1996 README
lrwxrwxrwx 1 0 1 7 Dec 9 1999 bin -> usr/bin
dr-xr-xr-x 2 0 1 512 Oct 1 1997 dev
drwxrwxrwx 2 98 98 512 May 29 16:04 download.html
dr-xr-xr-x 2 0 1 512 Nov 30 1995 etc
drwxrwxrwx 2 98 1 512 Oct 30 14:33 pub
dr-xr-xr-x 5 0 1 512 Oct 1 1997 usr
</data>
</reply>
#
# Client-side
<client requires=netrc_debug>
<name>
FTP (optional .netrc; no user/pass) dir list PASV
</name>
<command>
--netrc-optional ftp://%HOSTIP:%FTPPORT/
</command>
<file name="log/netrc" >
# the following two lines were created while testing curl
machine %HOSTIP login user1 password passwd1
machine %HOSTIP login user2 password passwd2
</file>
</test>
#
# Verify data after the test has been "shot"
<verify>
<strip>
filter off really nothing
</strip>
<protocol>
USER user1
PASS passwd1
PWD
EPSV
TYPE A
LIST
</protocol>
</verify>

49
tests/data/test131 Normal file
View File

@@ -0,0 +1,49 @@
#
# Server-side
<reply name="1">
<data>
total 20
drwxr-xr-x 8 98 98 512 Oct 22 13:06 .
drwxr-xr-x 8 98 98 512 Oct 22 13:06 ..
drwxr-xr-x 2 98 98 512 May 2 1996 .NeXT
-r--r--r-- 1 0 1 35 Jul 16 1996 README
lrwxrwxrwx 1 0 1 7 Dec 9 1999 bin -> usr/bin
dr-xr-xr-x 2 0 1 512 Oct 1 1997 dev
drwxrwxrwx 2 98 98 512 May 29 16:04 download.html
dr-xr-xr-x 2 0 1 512 Nov 30 1995 etc
drwxrwxrwx 2 98 1 512 Oct 30 14:33 pub
dr-xr-xr-x 5 0 1 512 Oct 1 1997 usr
</data>
</reply>
#
# Client-side
<client requires=netrc_debug>
<name>
FTP (optional .netrc; user/no pass) dir list PASV
</name>
<command>
--netrc-optional ftp://user2@%HOSTIP:%FTPPORT/
</command>
<file name="log/netrc" >
# the following two lines were created while testing curl
machine %HOSTIP login user1 password passwd1
machine %HOSTIP login user2 password passwd2
</file>
</test>
#
# Verify data after the test has been "shot"
<verify>
<strip>
filter off really nothing
</strip>
<protocol>
USER user2
PASS passwd2
PWD
EPSV
TYPE A
LIST
</protocol>
</verify>

49
tests/data/test132 Normal file
View File

@@ -0,0 +1,49 @@
#
# Server-side
<reply name="1">
<data>
total 20
drwxr-xr-x 8 98 98 512 Oct 22 13:06 .
drwxr-xr-x 8 98 98 512 Oct 22 13:06 ..
drwxr-xr-x 2 98 98 512 May 2 1996 .NeXT
-r--r--r-- 1 0 1 35 Jul 16 1996 README
lrwxrwxrwx 1 0 1 7 Dec 9 1999 bin -> usr/bin
dr-xr-xr-x 2 0 1 512 Oct 1 1997 dev
drwxrwxrwx 2 98 98 512 May 29 16:04 download.html
dr-xr-xr-x 2 0 1 512 Nov 30 1995 etc
drwxrwxrwx 2 98 1 512 Oct 30 14:33 pub
dr-xr-xr-x 5 0 1 512 Oct 1 1997 usr
</data>
</reply>
#
# Client-side
<client requires=netrc_debug>
<name>
FTP (optional .netrc; user/passwd supplied) dir list PASV
</name>
<command>
--netrc-optional ftp://mary:mark@%HOSTIP:%FTPPORT/
</command>
<file name="log/netrc" >
# the following two lines were created while testing curl
machine %HOSTIP login user1 password passwd1
machine %HOSTIP login user2 password passwd2
</file>
</test>
#
# Verify data after the test has been "shot"
<verify>
<strip>
filter off really nothing
</strip>
<protocol>
USER mary
PASS mark
PWD
EPSV
TYPE A
LIST
</protocol>
</verify>

49
tests/data/test133 Normal file
View File

@@ -0,0 +1,49 @@
#
# Server-side
<reply name="1">
<data>
total 20
drwxr-xr-x 8 98 98 512 Oct 22 13:06 .
drwxr-xr-x 8 98 98 512 Oct 22 13:06 ..
drwxr-xr-x 2 98 98 512 May 2 1996 .NeXT
-r--r--r-- 1 0 1 35 Jul 16 1996 README
lrwxrwxrwx 1 0 1 7 Dec 9 1999 bin -> usr/bin
dr-xr-xr-x 2 0 1 512 Oct 1 1997 dev
drwxrwxrwx 2 98 98 512 May 29 16:04 download.html
dr-xr-xr-x 2 0 1 512 Nov 30 1995 etc
drwxrwxrwx 2 98 1 512 Oct 30 14:33 pub
dr-xr-xr-x 5 0 1 512 Oct 1 1997 usr
</data>
</reply>
#
# Client-side
<client requires=netrc_debug>
<name>
FTP (compulsory .netrc; ignored user/passwd) dir list PASV
</name>
<command>
-n ftp://mary:mark@%HOSTIP:%FTPPORT/
</command>
<file name="log/netrc" >
# the following two lines were created while testing curl
machine %HOSTIP login user1 password passwd1
machine %HOSTIP login user2 password passwd2
</file>
</test>
#
# Verify data after the test has been "shot"
<verify>
<strip>
filter off really nothing
</strip>
<protocol>
USER user1
PASS passwd1
PWD
EPSV
TYPE A
LIST
</protocol>
</verify>

49
tests/data/test134 Normal file
View File

@@ -0,0 +1,49 @@
#
# Server-side
<reply name="1">
<data>
total 20
drwxr-xr-x 8 98 98 512 Oct 22 13:06 .
drwxr-xr-x 8 98 98 512 Oct 22 13:06 ..
drwxr-xr-x 2 98 98 512 May 2 1996 .NeXT
-r--r--r-- 1 0 1 35 Jul 16 1996 README
lrwxrwxrwx 1 0 1 7 Dec 9 1999 bin -> usr/bin
dr-xr-xr-x 2 0 1 512 Oct 1 1997 dev
drwxrwxrwx 2 98 98 512 May 29 16:04 download.html
dr-xr-xr-x 2 0 1 512 Nov 30 1995 etc
drwxrwxrwx 2 98 1 512 Oct 30 14:33 pub
dr-xr-xr-x 5 0 1 512 Oct 1 1997 usr
</data>
</reply>
#
# Client-side
<client requires=netrc_debug>
<name>
FTP (optional .netrc; programmatic user/passwd) dir list PASV
</name>
<command>
--netrc-optional -u romulus:rhemus ftp://mary:mark@%HOSTIP:%FTPPORT/
</command>
<file name="log/netrc" >
# the following two lines were created while testing curl
machine %HOSTIP login user1 password passwd1
machine %HOSTIP login user2 password passwd2
</file>
</test>
#
# Verify data after the test has been "shot"
<verify>
<strip>
filter off really nothing
</strip>
<protocol>
USER romulus
PASS rhemus
PWD
EPSV
TYPE A
LIST
</protocol>
</verify>

39
tests/data/test135 Normal file
View File

@@ -0,0 +1,39 @@
# Server-side
<reply>
<data>
0123456789abcdef
0123456789abcdef
0123456789abcdef
0123456789abcdef
</data>
<datacheck nonewline=yes>
0123456789abc
</datacheck>
<size>
64
</size>
</reply>
# Client-side
<client>
<name>
FTP retrieve a byte-range
</name>
<command>
-r 4-16 ftp://%HOSTIP:%FTPPORT/135
</command>
</test>
# Verify data after the test has been "shot"
<verify>
<protocol>
USER anonymous
PASS curl_by_daniel@haxx.se
PWD
EPSV
TYPE I
SIZE 135
REST 4
RETR 135
</protocol>
</verify>

View File

@@ -7,6 +7,9 @@ my $warning=0;
my $trace=0;
sub getpartattr {
# if $part is undefined (ie only one argument) then
# return the attributes of the section
my ($section, $part)=@_;
my %hash;
@@ -19,7 +22,9 @@ sub getpartattr {
if(!$inside && ($_ =~ /^ *\<$section/)) {
$inside++;
}
elsif((1 ==$inside) && ($_ =~ /^ *\<$part([^>]*)/)) {
if((1 ==$inside) && ( ($_ =~ /^ *\<$part([^>]*)/) ||
!(defined($part)) )
) {
$inside++;
my $attr=$1;
my @p=split("[ \t]", $attr);

View File

@@ -1,4 +1,4 @@
#!/usr/bin/perl
#!/usr/bin/env perl
#
# Example input:
#

View File

@@ -7,6 +7,7 @@
# These should be the only variables that might be needed to get edited:
use strict;
#use warnings;
@INC=(@INC, $ENV{'srcdir'}, ".");
@@ -20,6 +21,7 @@ my $HTTPSPORT=8433; # this is the HTTPS server port
my $FTPPORT=8921; # this is the FTP server port
my $FTPSPORT=8821; # this is the FTPS server port
my $CURL="../src/curl"; # what curl executable to run on the tests
my $DBGCURL=$CURL; #"../src/.libs/curl"; # alternative for debugging
my $LOGDIR="log";
my $TESTDIR="data";
my $SERVERIN="$LOGDIR/server.input"; # what curl sent the server
@@ -48,6 +50,11 @@ my $perl="perl -I$srcdir";
# this gets set if curl is compiled with memory debugging:
my $memory_debug=0;
# this gets set if curl is compiled with netrc debugging:
# It has to be in the global symbol table because of the way 'requires' works
$main::netrc_debug=0;
my $netrc_debug = \$main::netrc_debug;
# name of the file that the memory debugging creates:
my $memdump="memdump";
@@ -58,6 +65,8 @@ my $checkstunnel = &checkstunnel;
my $ssl_version; # set if libcurl is built with SSL support
my $skipped=0; # number of tests skipped; reported in main loop
#######################################################################
# variables the command line options may set
#
@@ -390,14 +399,35 @@ sub displaydata {
# enabled and we shall verify that no memory leaks exist
# after each and every test!
$memory_debug=1;
# there's only one debug control in the configure script
# so hope netrc debugging is enabled and set it up
$$netrc_debug = 1;
$ENV{'CURL_DEBUG_NETRC'} = 'log/netrc';
}
printf("* Memory debugging: %s\n", $memory_debug?"ON":"OFF");
printf("* Netrc debugging: %s\n", $$netrc_debug?"ON":"OFF");
printf("* HTTPS server: %s\n", $checkstunnel?"ON":"OFF");
printf("* FTPS server: %s\n", $checkstunnel?"ON":"OFF");
printf("* libcurl SSL: %s\n", $ssl_version?"ON":"OFF");
print "***************************************** \n";
}
#######################################################################
# substitute the variable stuff into either a joined up file or
# a command, in either case passed by reference
#
sub subVariables {
my ($thing) = @_;
$$thing =~ s/%HOSTIP/$HOSTIP/g;
$$thing =~ s/%HOSTPORT/$HOSTPORT/g;
$$thing =~ s/%HTTPSPORT/$HTTPSPORT/g;
$$thing =~ s/%FTPPORT/$FTPPORT/g;
$$thing =~ s/%FTPSPORT/$FTPSPORT/g;
$$thing =~ s/%SRCDIR/$srcdir/g;
$$thing =~ s/%PWD/$pwd/g;
}
#######################################################################
# Run a single specified test case
#
@@ -414,12 +444,41 @@ sub singletest {
return -1;
}
{
my %hash = getpartattr("client");
my $requires = $hash{'requires'};
if (defined($requires)) {
no strict "refs";
my $value=${$requires};
# print "This test requires '$requires' with value '$value' \n";
if (${$requires}) {
# this test is OK
;
}else {
print "$testnum requires $requires, which is not set; skipping\n";
$skipped++;
return 0; # look successful
}
}
}
# extract the reply data
my @reply = getpart("reply", "data");
my @replycheck = getpart("reply", "datacheck");
if (@replycheck) {
# we use this file instead to check the final output against
my %hash = getpartattr("reply", "datacheck");
if($hash{'nonewline'}) {
# Yes, we must cut off the final newline from the final line
# of the datacheck
chomp($replycheck[$#replycheck]);
}
@reply=@replycheck;
}
@@ -471,13 +530,16 @@ sub singletest {
# make some nice replace operations
$cmd =~ s/\n//g; # no newlines please
$cmd =~ s/%HOSTIP/$HOSTIP/g;
$cmd =~ s/%HOSTPORT/$HOSTPORT/g;
$cmd =~ s/%HTTPSPORT/$HTTPSPORT/g;
$cmd =~ s/%FTPPORT/$FTPPORT/g;
$cmd =~ s/%FTPSPORT/$FTPSPORT/g;
$cmd =~ s/%SRCDIR/$srcdir/g;
$cmd =~ s/%PWD/$pwd/g;
subVariables \$cmd;
# $cmd =~ s/%HOSTIP/$HOSTIP/g;
# $cmd =~ s/%HOSTPORT/$HOSTPORT/g;
# $cmd =~ s/%HTTPSPORT/$HTTPSPORT/g;
# $cmd =~ s/%FTPPORT/$FTPPORT/g;
# $cmd =~ s/%FTPSPORT/$FTPSPORT/g;
# $cmd =~ s/%SRCDIR/$srcdir/g;
# $cmd =~ s/%PWD/$pwd/g;
#$cmd =~ s/%HOSTNAME/$HOSTNAME/g;
@@ -491,11 +553,17 @@ sub singletest {
my %hash = getpartattr("client", "file");
my $filename=$hash{'name'};
if(!$filename) {
print "ERROR: section client=>file has no name attribute!\n";
exit;
}
writearray($filename, \@inputfile);
my $fileContent = join('', @inputfile);
subVariables \$fileContent;
# print "DEBUG: writing file " . $filename . "\n";
open OUTFILE, ">$filename";
print OUTFILE $fileContent;
close OUTFILE;
}
my %cmdhash = getpartattr("client", "command");
@@ -537,7 +605,7 @@ sub singletest {
print GDBCMD "set args $cmdargs\n";
print GDBCMD "show args\n";
close(GDBCMD);
system("gdb $CURL -x log/gdbcmd");
system("gdb $DBGCURL -x log/gdbcmd");
$res =0; # makes it always continue after a debugged run
}
else {
@@ -909,7 +977,6 @@ my $failed;
my $testnum;
my $ok=0;
my $total=0;
my $skipped=0;
foreach $testnum (split(" ", $TESTCASES)) {

View File

@@ -4,8 +4,8 @@
#include <string.h>
#include <stdlib.h>
#define EAT_SPACE(ptr) while( ptr && *ptr && isspace(*ptr) ) ptr++
#define EAT_WORD(ptr) while( ptr && *ptr && !isspace(*ptr) && ('>' != *ptr)) ptr++
#define EAT_SPACE(ptr) while( ptr && *ptr && isspace((int)*ptr) ) ptr++
#define EAT_WORD(ptr) while( ptr && *ptr && !isspace((int)*ptr) && ('>' != *ptr)) ptr++
#ifdef DEBUG
#define show(x) printf x

View File

@@ -1,4 +1,32 @@
/* sws.c: simple (silly?) web server */
/*****************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* In order to be useful for every potential user, curl and libcurl are
* dual-licensed under the MPL and the MIT/X-derivate licenses.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the MPL or the MIT/X-derivate
* licenses. You may pick one of these licenses.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* $Id$
*****************************************************************************/
/* sws.c: simple (silly?) web server
This code was originally graciously donated to the project Juergen
Wilke. Thanks a bunch!
*/
#include <stdio.h>
#include <stdlib.h>
@@ -13,7 +41,10 @@
#include <netinet/in.h>
#include <netdb.h>
char *spitout(FILE *stream, char *main, char *sub, int *size);
const char *
spitout(FILE *stream,
const char *main,
const char *sub, int *size);
#define DEFAULT_PORT 8999
@@ -21,17 +52,14 @@ char *spitout(FILE *stream, char *main, char *sub, int *size);
#define DEFAULT_LOGFILE "log/sws.log"
#endif
#define DOCBUFSIZE 4
#define BUFFERSIZE (DOCBUFSIZE * 1024)
#define VERSION "cURL test suite HTTP server/0.1"
#define REQUEST_DUMP "log/server.input"
#define TEST_DATA_PATH "data/test%d"
static char *docfriends = "HTTP/1.1 200 Mighty fine indeed\r\n\r\nWE ROOLZ\r\n";
static char *doc404 = "HTTP/1.1 404 Not Found\n"
static const char *docfriends = "HTTP/1.1 200 Mighty fine indeed\r\n\r\nWE ROOLZ\r\n";
static const char *doc404 = "HTTP/1.1 404 Not Found\n"
"Server: " VERSION "\n"
"Connection: close\n"
"Content-Type: text/html\n"
@@ -44,7 +72,9 @@ static char *doc404 = "HTTP/1.1 404 Not Found\n"
"The requested URL was not found on this server.\n"
"<P><HR><ADDRESS>" VERSION "</ADDRESS>\n" "</BODY></HTML>\n";
static volatile int sigpipe, sigterm;
#ifdef HAVE_SIGNAL
static volatile int sigpipe;
#endif
static FILE *logfp;
@@ -56,27 +86,21 @@ static void logmsg(const char *msg)
strcpy(loctime, asctime(curr_time));
loctime[strlen(loctime) - 1] = '\0';
fprintf(logfp, "%s: pid %d: %s\n", loctime, getpid(), msg);
fprintf(logfp, "%s: pid %d: %s\n", loctime, (int)getpid(), msg);
#ifdef DEBUG
fprintf(stderr, "%s: pid %d: %s\n", loctime, getpid(), msg);
fprintf(stderr, "%s: pid %d: %s\n", loctime, (int)getpid(), msg);
#endif
fflush(logfp);
}
#ifdef HAVE_SIGNAL
static void sigpipe_handler(int sig)
{
(void)sig; /* prevent warning */
sigpipe = 1;
}
static void sigterm_handler(int sig)
{
char logbuf[100];
snprintf(logbuf, 100, "Got signal %d, terminating", sig);
logmsg(logbuf);
sigterm = 1;
}
#endif
int ProcessRequest(char *request)
{
@@ -136,12 +160,12 @@ void storerequest(char *reqbuf)
}
#define REQBUFSIZ 50000
#define REQBUFSIZ_TXT "49999"
#define REQBUFSIZ 150000
#define REQBUFSIZ_TXT "149999"
/* very-big-path support */
#define MAXDOCNAMELEN 40000
#define MAXDOCNAMELEN_TXT "39999"
#define MAXDOCNAMELEN 140000
#define MAXDOCNAMELEN_TXT "139999"
#define REQUEST_KEYWORD_SIZE 256
static int get_request(int sock, int *part)
@@ -240,7 +264,7 @@ static int send_doc(int sock, int doc, int part_no)
{
int written;
int count;
char *buffer;
const char *buffer;
char *ptr;
FILE *stream;
char *cmd=NULL;
@@ -274,7 +298,8 @@ static int send_doc(int sock, int doc, int part_no)
return 0;
}
else {
ptr = buffer = spitout(stream, "reply", partbuf, &count);
buffer = spitout(stream, "reply", partbuf, &count);
ptr = (char *)buffer;
fclose(stream);
}
@@ -286,7 +311,7 @@ static int send_doc(int sock, int doc, int part_no)
}
else {
/* get the custom server control "commands" */
cmd = spitout(stream, "reply", "postcmd", &cmdsize);
cmd = (char *)spitout(stream, "reply", "postcmd", &cmdsize);
fclose(stream);
}
}
@@ -333,7 +358,7 @@ int main(int argc, char *argv[])
struct sockaddr_in me;
int sock, msgsock, flag;
unsigned short port = DEFAULT_PORT;
char *logfile = DEFAULT_LOGFILE;
const char *logfile = DEFAULT_LOGFILE;
int part_no;
FILE *pidfile;
@@ -351,12 +376,8 @@ int main(int argc, char *argv[])
#ifdef HAVE_SIGNAL
/* FIX: make a more portable signal handler */
signal(SIGPIPE, sigpipe_handler);
signal(SIGINT, sigterm_handler);
signal(SIGTERM, sigterm_handler);
siginterrupt(SIGPIPE, 1);
siginterrupt(SIGINT, 1);
siginterrupt(SIGTERM, 1);
#endif
sock = socket(AF_INET, SOCK_STREAM, 0);
@@ -397,18 +418,13 @@ int main(int argc, char *argv[])
fprintf(stderr, "*** %s listening on port %u ***\n", VERSION, port);
while (!sigterm) {
while (1) {
int doc;
msgsock = accept(sock, NULL, NULL);
if (msgsock == -1) {
if (sigterm) {
break;
}
/* perror("accept"); */
if (msgsock == -1)
continue;
}
logmsg("New client connected");