Compare commits
148 Commits
curl-7_9_6
...
curl-7_9_8
Author | SHA1 | Date | |
---|---|---|---|
![]() |
67273eed9b | ||
![]() |
3c63e1d8d9 | ||
![]() |
cae555c977 | ||
![]() |
407583e8e2 | ||
![]() |
131645dc31 | ||
![]() |
dafd644fe7 | ||
![]() |
73cc1742af | ||
![]() |
87afd7686f | ||
![]() |
8ce10b5dfa | ||
![]() |
943e31b35c | ||
![]() |
20f85b94df | ||
![]() |
17b784381e | ||
![]() |
e3031fddb9 | ||
![]() |
38c994a7ae | ||
![]() |
85e2e96fb6 | ||
![]() |
be35b3ad03 | ||
![]() |
dbbd871ea1 | ||
![]() |
813911db59 | ||
![]() |
3c49b405de | ||
![]() |
4cfffd6c4a | ||
![]() |
e9f1c12f0f | ||
![]() |
4fe252847c | ||
![]() |
109cbbe9c5 | ||
![]() |
fd3881eaa6 | ||
![]() |
08ef208fb7 | ||
![]() |
8c45e2a641 | ||
![]() |
25dc520163 | ||
![]() |
fc37ef9e4b | ||
![]() |
11ba367fc9 | ||
![]() |
78473f71eb | ||
![]() |
8b77f40f99 | ||
![]() |
d866716565 | ||
![]() |
307d0effe2 | ||
![]() |
b47b053e54 | ||
![]() |
b79f01caf3 | ||
![]() |
0db227f55e | ||
![]() |
ac48b38842 | ||
![]() |
0cbb9365c6 | ||
![]() |
798b8c522b | ||
![]() |
15bc7e19f9 | ||
![]() |
0be3f1a063 | ||
![]() |
c0257c6721 | ||
![]() |
9aec0fc7de | ||
![]() |
bce5e0d82c | ||
![]() |
62032ee248 | ||
![]() |
775645f29b | ||
![]() |
99c0456872 | ||
![]() |
0236bee5de | ||
![]() |
59c11b82d5 | ||
![]() |
98871d1e9e | ||
![]() |
b40dc5d742 | ||
![]() |
17b0723713 | ||
![]() |
ec585e8907 | ||
![]() |
0aeb25ff3b | ||
![]() |
a928f2c4aa | ||
![]() |
51fcee6f81 | ||
![]() |
654be65590 | ||
![]() |
105ec79b2b | ||
![]() |
c759d8427a | ||
![]() |
c7b03d6479 | ||
![]() |
2080738883 | ||
![]() |
48bc73c271 | ||
![]() |
3d0969d1d1 | ||
![]() |
323f195036 | ||
![]() |
c3c392fc98 | ||
![]() |
5d2944c211 | ||
![]() |
fe3ba1dd11 | ||
![]() |
0c00eb93a0 | ||
![]() |
baa77ec13b | ||
![]() |
9263652c6d | ||
![]() |
bc74375543 | ||
![]() |
edb1756050 | ||
![]() |
5215f6f654 | ||
![]() |
1913b4eeed | ||
![]() |
b44a4da5df | ||
![]() |
919878fbb2 | ||
![]() |
06bdf83419 | ||
![]() |
2ff2810a92 | ||
![]() |
20d9c1b30d | ||
![]() |
bbe10cb0cb | ||
![]() |
daba8f3a70 | ||
![]() |
1458c3668d | ||
![]() |
980a47b42b | ||
![]() |
f7ca561b06 | ||
![]() |
cacd756efd | ||
![]() |
8539e76cb9 | ||
![]() |
3bbf694d5a | ||
![]() |
44debdde62 | ||
![]() |
c6cf2b8e93 | ||
![]() |
69c5452b25 | ||
![]() |
d321056e8d | ||
![]() |
d9a1a59f22 | ||
![]() |
0b898b5a8a | ||
![]() |
a9e0885be0 | ||
![]() |
57ff28c9b7 | ||
![]() |
86cc34c0de | ||
![]() |
39028f1bd4 | ||
![]() |
71f4c05665 | ||
![]() |
9ef9797998 | ||
![]() |
ab9374de57 | ||
![]() |
913e997061 | ||
![]() |
8e50d6b6f3 | ||
![]() |
2db0744a7b | ||
![]() |
2de0028349 | ||
![]() |
35d04c5398 | ||
![]() |
b1becd0ed5 | ||
![]() |
bd9650bc81 | ||
![]() |
969a25d1b2 | ||
![]() |
f144f77ba7 | ||
![]() |
abea1f8910 | ||
![]() |
8eaa7fec76 | ||
![]() |
fdace647e8 | ||
![]() |
d7531c18fc | ||
![]() |
ef3f978784 | ||
![]() |
e410860e0e | ||
![]() |
c64fca1b0c | ||
![]() |
15b2a3af91 | ||
![]() |
8358505b6d | ||
![]() |
1c42779845 | ||
![]() |
32823f17e0 | ||
![]() |
e1c2e3f5e9 | ||
![]() |
044755b30f | ||
![]() |
9aa22399a8 | ||
![]() |
f564905ac4 | ||
![]() |
00e4f81446 | ||
![]() |
8927ddec16 | ||
![]() |
f6525ae200 | ||
![]() |
0be7944d66 | ||
![]() |
47819ea86e | ||
![]() |
96ce3461ad | ||
![]() |
8b6d555421 | ||
![]() |
3b9ef8dfc8 | ||
![]() |
db6d4bcf47 | ||
![]() |
471f1d694f | ||
![]() |
495f6f6bd3 | ||
![]() |
36e35b6f60 | ||
![]() |
192606bc4b | ||
![]() |
53a9fdf078 | ||
![]() |
ef436bdbe8 | ||
![]() |
72d722b07b | ||
![]() |
21fc402c01 | ||
![]() |
381f77756d | ||
![]() |
a386562d9a | ||
![]() |
2bc84fb163 | ||
![]() |
08f8917acb | ||
![]() |
62d205a2ec | ||
![]() |
29e873b12d | ||
![]() |
95f78080ab |
285
CHANGES
285
CHANGES
@@ -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.
|
||||
|
21
acconfig.h
21
acconfig.h
@@ -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
|
||||
|
152
configure.in
152
configure.in
@@ -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
|
||||
@@ -82,7 +175,7 @@ dnl **********************************************************************
|
||||
AC_MSG_CHECKING([whether to enable ipv6])
|
||||
AC_ARG_ENABLE(ipv6,
|
||||
[ --enable-ipv6 Enable ipv6 (with ipv4) support
|
||||
--disable-ipv6 Disable ipv6 support],
|
||||
--disable-ipv6 Disable ipv6 support],
|
||||
[ case "$enableval" in
|
||||
no)
|
||||
AC_MSG_RESULT(no)
|
||||
@@ -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 \
|
||||
|
@@ -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
96
docs/BINDINGS
Normal 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
|
42
docs/BUGS
42
docs/BUGS
@@ -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.
|
||||
|
||||
|
84
docs/FAQ
84
docs/FAQ
@@ -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?
|
||||
|
11
docs/INSTALL
11
docs/INSTALL
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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:
|
||||
|
||||
|
@@ -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 >$@
|
||||
|
||||
|
@@ -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
|
||||
---------
|
||||
|
20
docs/TODO
20
docs/TODO
@@ -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
|
||||
|
||||
|
117
docs/curl.1
117
docs/curl.1
@@ -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
|
||||
|
@@ -4,11 +4,12 @@
|
||||
|
||||
AUTOMAKE_OPTIONS = foreign no-dependencies
|
||||
|
||||
EXTRA_DIST = README curlgtk.c sepheaders.c simple.c postit2.c \
|
||||
win32sockets.c 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
|
||||
EXTRA_DIST = README curlgtk.c sepheaders.c simple.c postit2.c \
|
||||
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-post.c \
|
||||
fopen.c
|
||||
|
||||
all:
|
||||
@echo "done"
|
||||
|
222
docs/examples/fopen.c
Normal file
222
docs/examples/fopen.c
Normal 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
126
docs/examples/multi-post.c
Normal 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;
|
||||
}
|
@@ -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 */
|
||||
}
|
@@ -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
|
||||
|
@@ -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.
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
||||
|
@@ -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"
|
||||
|
@@ -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
|
||||
@@ -535,10 +551,22 @@ 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
|
||||
|
@@ -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
|
||||
|
@@ -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)
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -366,3 +366,6 @@
|
||||
#define HAVE_MEMORY_H 1
|
||||
|
||||
#define HAVE_FIONBIO 1
|
||||
|
||||
/* Define if you have the `sigsetjmp' function. */
|
||||
#define HAVE_SIGSETJMP 1
|
||||
|
@@ -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
|
||||
|
||||
|
@@ -185,7 +185,6 @@ int waitconnect(int sockfd, /* socket */
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef ENABLE_IPV6
|
||||
static CURLcode bindlocal(struct connectdata *conn,
|
||||
int sockfd)
|
||||
{
|
||||
@@ -207,22 +206,28 @@ 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);
|
||||
}
|
||||
if(h) {
|
||||
/* we know data->set.device is shorter than the myhost array */
|
||||
strcpy(myhost, data->set.device);
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
48
lib/cookie.c
48
lib/cookie.c
@@ -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;
|
||||
@@ -513,7 +533,7 @@ struct CookieInfo *Curl_cookie_init(char *file, struct CookieInfo *inc)
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
c->running = TRUE; /* now, we're running */
|
||||
c->running = TRUE; /* now, we're running */
|
||||
|
||||
return c;
|
||||
}
|
||||
@@ -743,6 +763,8 @@ int main(int argc, char **argv)
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* CURL_DISABLE_HTTP */
|
||||
|
||||
/*
|
||||
* local variables:
|
||||
* eval: (load-file "../curl-mode.el")
|
||||
|
@@ -55,9 +55,10 @@ struct CookieInfo {
|
||||
/* linked list of cookies we know of */
|
||||
struct Cookie *cookies;
|
||||
|
||||
char *filename; /* file we read from/write to */
|
||||
bool running; /* state info, for cookie adding information */
|
||||
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 *);
|
||||
|
788
lib/curllib.dsp
788
lib/curllib.dsp
@@ -1,394 +1,394 @@
|
||||
# Microsoft Developer Studio Project File - Name="curllib" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
|
||||
|
||||
CFG=curllib - Win32 Debug
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "curllib.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "curllib.mak" CFG="curllib - Win32 Debug"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "curllib - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
|
||||
!MESSAGE "curllib - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
# PROP Scc_ProjName ""
|
||||
# PROP Scc_LocalPath ""
|
||||
CPP=cl.exe
|
||||
MTL=midl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "curllib - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "Release"
|
||||
# PROP BASE Intermediate_Dir "Release"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release"
|
||||
# PROP Intermediate_Dir "Release"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CURLLIB_EXPORTS" /YX /FD /c
|
||||
# ADD CPP /nologo /MD /W3 /GX /Zi /O2 /I "..\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CURLLIB_EXPORTS" /FR /FD /c
|
||||
# SUBTRACT CPP /YX
|
||||
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
|
||||
# ADD LINK32 kernel32.lib ws2_32.lib /nologo /dll /map /debug /machine:I386 /out:"Release/libcurl.dll"
|
||||
|
||||
!ELSEIF "$(CFG)" == "curllib - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "Debug"
|
||||
# PROP BASE Intermediate_Dir "Debug"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug"
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CURLLIB_EXPORTS" /YX /FD /GZ /c
|
||||
# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I "..\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CURLLIB_EXPORTS" /FR /FD /GZ /c
|
||||
# SUBTRACT CPP /WX /YX
|
||||
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
|
||||
# ADD LINK32 kernel32.lib ws2_32.lib /nologo /dll /incremental:no /map /debug /machine:I386 /out:"Debug/libcurl.dll" /pdbtype:sept
|
||||
# SUBTRACT LINK32 /nodefaultlib
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "curllib - Win32 Release"
|
||||
# Name "curllib - Win32 Debug"
|
||||
# Begin Group "Source Files"
|
||||
|
||||
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\base64.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\connect.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\cookie.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\dict.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\dllinit.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\easy.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\escape.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\file.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\formdata.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\ftp.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\getdate.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\getenv.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\getinfo.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\getpass.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\hash.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\hostip.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\http.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\http_chunks.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\if2ip.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\krb4.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\ldap.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\libcurl.def
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\llist.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\memdebug.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\mprintf.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\netrc.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\progress.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\security.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\sendf.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\speedcheck.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\ssluse.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\strequal.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\strtok.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\telnet.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\timeval.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\transfer.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\url.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\version.c
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Header Files"
|
||||
|
||||
# PROP Default_Filter "h;hpp;hxx;hm;inl"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\arpa_telnet.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\base64.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\connect.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\cookie.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\dict.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\escape.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\file.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\formdata.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\ftp.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\getdate.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\getenv.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\getpass.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\hostip.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\http.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\http_chunks.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\if2ip.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\inet_ntoa_r.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\krb4.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\ldap.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\memdebug.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\netrc.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\progress.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\security.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\sendf.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\setup.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\speedcheck.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\ssluse.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\strequal.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\strtok.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\telnet.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\timeval.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\transfer.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\url.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\urldata.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Resource Files"
|
||||
|
||||
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
|
||||
# End Group
|
||||
# End Target
|
||||
# End Project
|
||||
# Microsoft Developer Studio Project File - Name="curllib" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
|
||||
|
||||
CFG=curllib - Win32 Debug
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "curllib.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "curllib.mak" CFG="curllib - Win32 Debug"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "curllib - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
|
||||
!MESSAGE "curllib - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
# PROP Scc_ProjName ""
|
||||
# PROP Scc_LocalPath ""
|
||||
CPP=cl.exe
|
||||
MTL=midl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "curllib - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "Release"
|
||||
# PROP BASE Intermediate_Dir "Release"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release"
|
||||
# PROP Intermediate_Dir "Release"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CURLLIB_EXPORTS" /YX /FD /c
|
||||
# ADD CPP /nologo /MD /W3 /GX /Zi /O2 /I "..\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CURLLIB_EXPORTS" /FR /FD /c
|
||||
# SUBTRACT CPP /YX
|
||||
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
|
||||
# ADD LINK32 kernel32.lib ws2_32.lib winmm.lib /nologo /dll /map /debug /machine:I386 /out:"Release/libcurl.dll"
|
||||
|
||||
!ELSEIF "$(CFG)" == "curllib - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "Debug"
|
||||
# PROP BASE Intermediate_Dir "Debug"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug"
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CURLLIB_EXPORTS" /YX /FD /GZ /c
|
||||
# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I "..\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CURLLIB_EXPORTS" /FR /FD /GZ /c
|
||||
# SUBTRACT CPP /WX /YX
|
||||
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
|
||||
# ADD LINK32 kernel32.lib ws2_32.lib winmm.lib /nologo /dll /incremental:no /map /debug /machine:I386 /out:"Debug/libcurl.dll" /pdbtype:sept
|
||||
# SUBTRACT LINK32 /nodefaultlib
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "curllib - Win32 Release"
|
||||
# Name "curllib - Win32 Debug"
|
||||
# Begin Group "Source Files"
|
||||
|
||||
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\base64.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\connect.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\cookie.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\dict.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\dllinit.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\easy.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\escape.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\file.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\formdata.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\ftp.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\getdate.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\getenv.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\getinfo.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\getpass.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\hash.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\hostip.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\http.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\http_chunks.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\if2ip.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\krb4.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\ldap.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\libcurl.def
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\llist.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\memdebug.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\mprintf.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\netrc.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\progress.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\security.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\sendf.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\speedcheck.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\ssluse.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\strequal.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\strtok.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\telnet.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\timeval.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\transfer.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\url.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\version.c
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Header Files"
|
||||
|
||||
# PROP Default_Filter "h;hpp;hxx;hm;inl"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\arpa_telnet.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\base64.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\connect.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\cookie.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\dict.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\escape.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\file.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\formdata.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\ftp.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\getdate.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\getenv.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\getpass.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\hostip.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\http.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\http_chunks.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\if2ip.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\inet_ntoa_r.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\krb4.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\ldap.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\memdebug.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\netrc.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\progress.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\security.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\sendf.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\setup.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\speedcheck.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\ssluse.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\strequal.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\strtok.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\telnet.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\timeval.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\transfer.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\url.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\urldata.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Resource Files"
|
||||
|
||||
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
|
||||
# End Group
|
||||
# End Target
|
||||
# End Project
|
||||
|
@@ -1,29 +1,29 @@
|
||||
Microsoft Developer Studio Workspace File, Format Version 6.00
|
||||
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "curllib"=".\curllib.dsp" - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Global:
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<3>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Microsoft Developer Studio Workspace File, Format Version 6.00
|
||||
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "curllib"=".\curllib.dsp" - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Global:
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<3>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
|
@@ -23,7 +23,8 @@
|
||||
*
|
||||
* $Id$
|
||||
*****************************************************************************/
|
||||
#ifndef CURL_DISABLE_DICT
|
||||
CURLcode Curl_dict(struct connectdata *conn);
|
||||
CURLcode Curl_dict_done(struct connectdata *conn);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
@@ -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) {
|
||||
|
@@ -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
|
||||
|
@@ -23,6 +23,8 @@
|
||||
*
|
||||
* $Id$
|
||||
*****************************************************************************/
|
||||
#ifndef CURL_DISABLE_FILE
|
||||
CURLcode Curl_file(struct connectdata *conn);
|
||||
CURLcode Curl_file_connect(struct connectdata *conn);
|
||||
#endif
|
||||
#endif
|
||||
|
303
lib/formdata.c
303
lib/formdata.c
@@ -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,
|
||||
struct curl_httppost **last_post,
|
||||
va_list params)
|
||||
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,26 +775,80 @@ 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 =
|
||||
char *contenttype =
|
||||
array_state?array_value:va_arg(params, char *);
|
||||
if (current_form->contenttype) {
|
||||
if (current_form->flags & HTTPPOST_FILENAME) {
|
||||
@@ -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,
|
||||
int *sizep)
|
||||
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();
|
||||
|
||||
@@ -1094,9 +1163,9 @@ struct FormData *Curl_getFormData(struct curl_httppost *post,
|
||||
fileboundary = Curl_FormBoundary();
|
||||
|
||||
size += AddFormDataf(&form,
|
||||
"\r\nContent-Type: multipart/mixed,"
|
||||
" boundary=%s\r\n",
|
||||
fileboundary);
|
||||
"\r\nContent-Type: multipart/mixed,"
|
||||
" boundary=%s\r\n",
|
||||
fileboundary);
|
||||
}
|
||||
|
||||
file = post;
|
||||
@@ -1108,26 +1177,30 @@ struct FormData *Curl_getFormData(struct curl_httppost *post,
|
||||
local file name should be added. */
|
||||
|
||||
if(post->more) {
|
||||
/* if multiple-file */
|
||||
size += AddFormDataf(&form,
|
||||
"\r\n--%s\r\nContent-Disposition: "
|
||||
/* if multiple-file */
|
||||
size += AddFormDataf(&form,
|
||||
"\r\n--%s\r\nContent-Disposition: "
|
||||
"attachment; filename=\"%s\"",
|
||||
fileboundary,
|
||||
fileboundary,
|
||||
(file->showfilename?file->showfilename:
|
||||
file->contents));
|
||||
}
|
||||
else if(post->flags & HTTPPOST_FILENAME) {
|
||||
size += AddFormDataf(&form,
|
||||
"; filename=\"%s\"",
|
||||
(post->showfilename?post->showfilename:
|
||||
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:
|
||||
post->contents));
|
||||
}
|
||||
|
||||
if(file->contenttype) {
|
||||
/* we have a specified type */
|
||||
size += AddFormDataf(&form,
|
||||
"\r\nContent-Type: %s",
|
||||
file->contenttype);
|
||||
/* we have a specified type */
|
||||
size += AddFormDataf(&form,
|
||||
"\r\nContent-Type: %s",
|
||||
file->contenttype);
|
||||
}
|
||||
|
||||
curList = file->contentheader;
|
||||
@@ -1145,43 +1218,53 @@ struct FormData *Curl_getFormData(struct curl_httppost *post,
|
||||
*/
|
||||
|
||||
if(file->contenttype &&
|
||||
!strnequal("text/", file->contenttype, 5)) {
|
||||
/* this is not a text content, mention our binary encoding */
|
||||
size += AddFormData(&form, "\r\nContent-Transfer-Encoding: binary", 0);
|
||||
!strnequal("text/", file->contenttype, 5)) {
|
||||
/* this is not a text content, mention our binary encoding */
|
||||
size += AddFormData(&form, "\r\nContent-Transfer-Encoding: binary", 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
size += AddFormData(&form, "\r\n\r\n", 0);
|
||||
|
||||
if((post->flags & HTTPPOST_FILENAME) ||
|
||||
(post->flags & HTTPPOST_READFILE)) {
|
||||
/* we should include the contents from the specified file */
|
||||
FILE *fileread;
|
||||
char buffer[1024];
|
||||
int nread;
|
||||
(post->flags & HTTPPOST_READFILE)) {
|
||||
/* we should include the contents from the specified file */
|
||||
FILE *fileread;
|
||||
char buffer[1024];
|
||||
int nread;
|
||||
|
||||
fileread = strequal("-", file->contents)?stdin:
|
||||
fileread = strequal("-", file->contents)?stdin:
|
||||
/* binary read for win32 crap */
|
||||
/*VMS??*/ fopen(file->contents, "rb"); /* ONLY ALLOWS FOR STREAM FILES ON VMS */
|
||||
/*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);
|
||||
}
|
||||
/*VMS??*/ fopen(file->contents, "rb"); /* ONLY ALLOWS FOR STREAM FILES ON VMS */
|
||||
/*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);
|
||||
|
||||
if(fileread != stdin)
|
||||
fclose(fileread);
|
||||
}
|
||||
}
|
||||
else {
|
||||
#if 0
|
||||
/* File wasn't found, add a nothing field! */
|
||||
size += AddFormData(&form, "", 0);
|
||||
}
|
||||
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);
|
||||
|
||||
else {
|
||||
/* include the contents we got */
|
||||
size += AddFormData(&form, post->contents, post->contentslength);
|
||||
}
|
||||
} while((file = file->more)); /* for each specified file for this field */
|
||||
|
||||
@@ -1189,8 +1272,8 @@ struct FormData *Curl_getFormData(struct curl_httppost *post,
|
||||
/* this was a multiple-file inclusion, make a termination file
|
||||
boundary: */
|
||||
size += AddFormDataf(&form,
|
||||
"\r\n--%s--",
|
||||
fileboundary);
|
||||
"\r\n--%s--",
|
||||
fileboundary);
|
||||
free(fileboundary);
|
||||
}
|
||||
|
||||
@@ -1198,14 +1281,16 @@ struct FormData *Curl_getFormData(struct curl_httppost *post,
|
||||
|
||||
/* end-boundary for everything */
|
||||
size += AddFormDataf(&form,
|
||||
"\r\n--%s--\r\n",
|
||||
boundary);
|
||||
"\r\n--%s--\r\n",
|
||||
boundary);
|
||||
|
||||
*sizep = size;
|
||||
|
||||
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")
|
||||
|
@@ -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,8 +57,10 @@ typedef struct FormInfo {
|
||||
|
||||
int Curl_FormInit(struct Form *form, struct FormData *formdata );
|
||||
|
||||
struct FormData *Curl_getFormData(struct HttpPost *post,
|
||||
int *size);
|
||||
CURLcode
|
||||
Curl_getFormData(struct FormData **,
|
||||
struct HttpPost *post,
|
||||
int *size);
|
||||
|
||||
/* fread() emulation */
|
||||
int Curl_FormReader(char *buffer,
|
||||
|
89
lib/ftp.c
89
lib/ftp.c
@@ -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)) {
|
||||
readfd = rkeepfd; /* set every lap */
|
||||
interval.tv_sec = timeout;
|
||||
interval.tv_usec = 0;
|
||||
/* 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 */
|
||||
(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 */
|
||||
|
@@ -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
|
||||
|
@@ -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;
|
||||
|
60
lib/hash.c
60
lib/hash.c
@@ -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);
|
||||
}
|
||||
/* }}} */
|
||||
|
22
lib/hash.h
22
lib/hash.h
@@ -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
|
||||
|
||||
|
241
lib/hostip.c
241
lib/hostip.c
@@ -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) {
|
||||
_hostcache_return(p->addr);
|
||||
}
|
||||
}
|
||||
else {
|
||||
_hostcache_return(p->addr);
|
||||
}
|
||||
if (entry_id &&
|
||||
Curl_hash_find(data->hostcache, entry_id, entry_len+1, (void **) &p)) {
|
||||
_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 *bufptr;
|
||||
char *newbuf;
|
||||
struct hostent* copy;
|
||||
|
||||
int i;
|
||||
char* str;
|
||||
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,
|
||||
(struct hostent *)buf,
|
||||
(char *)buf + sizeof(struct hostent),
|
||||
CURL_NAMELOOKUP_SIZE - sizeof(struct hostent),
|
||||
&h_errnop)) == NULL )
|
||||
while(!h) {
|
||||
h = gethostbyname_r(hostname,
|
||||
(struct hostent *)buf,
|
||||
(char *)buf + sizeof(struct hostent),
|
||||
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,
|
||||
(struct hostent *)buf,
|
||||
(char *)buf + sizeof(struct hostent),
|
||||
CURL_NAMELOOKUP_SIZE - sizeof(struct hostent),
|
||||
&h, /* DIFFERENCE */
|
||||
&h_errnop))
|
||||
while((res=gethostbyname_r(hostname,
|
||||
(struct hostent *)buf,
|
||||
(char *)buf + sizeof(struct hostent),
|
||||
step_size - sizeof(struct hostent),
|
||||
&h, /* DIFFERENCE */
|
||||
&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? */
|
||||
@@ -498,8 +626,8 @@ Curl_addrinfo *Curl_getaddrinfo(struct SessionHandle *data,
|
||||
* size dilemma. */
|
||||
|
||||
ret = gethostbyname_r(hostname,
|
||||
(struct hostent *)buf,
|
||||
(struct hostent_data *)(buf + sizeof(struct hostent)));
|
||||
(struct hostent *)buf,
|
||||
(struct hostent_data *)(buf + sizeof(struct hostent)));
|
||||
else
|
||||
ret = -1; /* failure, too smallish buffer size */
|
||||
|
||||
@@ -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);
|
||||
|
@@ -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,
|
||||
|
23
lib/http.c
23
lib/http.c
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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 */
|
||||
|
@@ -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:
|
||||
|
@@ -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
|
||||
|
@@ -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 */
|
||||
|
26
lib/llist.c
26
lib/llist.c
@@ -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);
|
||||
|
16
lib/llist.h
16
lib/llist.h
@@ -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)
|
||||
|
@@ -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 :-( */
|
||||
};
|
||||
|
||||
/*
|
||||
|
@@ -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)
|
||||
|
122
lib/multi.c
122
lib/multi.c
@@ -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)
|
||||
easy->state = CURLM_STATE_COMPLETED;
|
||||
|
||||
/* 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 an error was returned, and we aren't in completed now,
|
||||
* then we go to completed and consider this transfer aborted.
|
||||
*/
|
||||
easy->state = CURLM_STATE_COMPLETED;
|
||||
if(CURLM_STATE_COMPLETED != easy->state) {
|
||||
if(CURLE_OK != easy->result)
|
||||
/*
|
||||
* 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
|
||||
/* 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 */
|
||||
}
|
||||
else if(CURLM_STATE_COMPLETED != easy->state)
|
||||
/* this one still lives! */
|
||||
(*running_handles)++;
|
||||
|
||||
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:
|
||||
|
52
lib/netrc.c
52
lib/netrc.c
@@ -78,12 +78,15 @@ int Curl_parsenetrc(char *host,
|
||||
FILE *file;
|
||||
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) {
|
||||
strncpy(login, tok, LOGINSIZE-1);
|
||||
if (specific_login) {
|
||||
state_our_login = strequal(login, tok);
|
||||
}else{
|
||||
strncpy(login, tok, LOGINSIZE-1);
|
||||
#ifdef _NETRC_DEBUG
|
||||
printf("LOGIN: %s\n", login);
|
||||
printf("LOGIN: %s\n", login);
|
||||
#endif
|
||||
}
|
||||
state_login=0;
|
||||
}
|
||||
else if(state_password) {
|
||||
strncpy(password, tok, PASSWORDSIZE-1);
|
||||
if (state_our_login || !specific_login) {
|
||||
strncpy(password, tok, PASSWORDSIZE-1);
|
||||
#ifdef _NETRC_DEBUG
|
||||
printf("PASSWORD: %s\n", password);
|
||||
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);
|
||||
}
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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);
|
||||
|
||||
|
||||
|
@@ -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:
|
||||
|
16
lib/sendf.c
16
lib/sendf.c
@@ -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;
|
||||
|
||||
fwrite(s_infotype[type], 2, 1, data->set.err);
|
||||
fwrite(ptr, size, 1, data->set.err);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
12
lib/setup.h
12
lib/setup.h
@@ -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
|
||||
|
47
lib/ssluse.c
47
lib/ssluse.c
@@ -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);
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -23,7 +23,8 @@
|
||||
*
|
||||
* $Id$
|
||||
*****************************************************************************/
|
||||
#ifndef CURL_DISABLE_TELNET
|
||||
CURLcode Curl_telnet(struct connectdata *conn);
|
||||
CURLcode Curl_telnet_done(struct connectdata *conn);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
@@ -32,22 +32,36 @@
|
||||
int
|
||||
gettimeofday (struct timeval *tp, void *nothing)
|
||||
{
|
||||
SYSTEMTIME st;
|
||||
time_t tt;
|
||||
struct tm tmtm;
|
||||
/* mktime converts local to UTC */
|
||||
GetLocalTime (&st);
|
||||
tmtm.tm_sec = st.wSecond;
|
||||
tmtm.tm_min = st.wMinute;
|
||||
tmtm.tm_hour = st.wHour;
|
||||
tmtm.tm_mday = st.wDay;
|
||||
tmtm.tm_mon = st.wMonth - 1;
|
||||
tmtm.tm_year = st.wYear - 1900;
|
||||
tmtm.tm_isdst = -1;
|
||||
tt = mktime (&tmtm);
|
||||
tp->tv_sec = tt;
|
||||
tp->tv_usec = st.wMilliseconds * 1000;
|
||||
return 1;
|
||||
#ifdef WITHOUT_MM_LIB
|
||||
SYSTEMTIME st;
|
||||
time_t tt;
|
||||
struct tm tmtm;
|
||||
/* mktime converts local to UTC */
|
||||
GetLocalTime (&st);
|
||||
tmtm.tm_sec = st.wSecond;
|
||||
tmtm.tm_min = st.wMinute;
|
||||
tmtm.tm_hour = st.wHour;
|
||||
tmtm.tm_mday = st.wDay;
|
||||
tmtm.tm_mon = st.wMonth - 1;
|
||||
tmtm.tm_year = st.wYear - 1900;
|
||||
tmtm.tm_isdst = -1;
|
||||
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
|
||||
#endif
|
||||
|
119
lib/transfer.c
119
lib/transfer.c
@@ -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)
|
||||
{
|
||||
@@ -176,10 +180,43 @@ CURLcode Curl_readwrite(struct connectdata *conn,
|
||||
int result;
|
||||
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, ¬imeout);
|
||||
}
|
||||
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, ¬imeout);
|
||||
}
|
||||
|
||||
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! */
|
||||
data->set.httpreq = HTTPREQ_GET; /* enforce GET request */
|
||||
infof(data, "Disables POST, goes with GET\n");
|
||||
if(data->set.httpreq != HTTPREQ_GET) {
|
||||
data->set.httpreq = HTTPREQ_GET; /* enforce GET request */
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
458
lib/url.c
458
lib/url.c
@@ -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
|
||||
@@ -1379,7 +1427,7 @@ static CURLcode CreateConnection(struct SessionHandle *data,
|
||||
connections, so we set this to force-close. Protocols that support
|
||||
this need to set this to FALSE in their "curl_do" functions. */
|
||||
conn->bits.close = TRUE;
|
||||
|
||||
|
||||
/* inherite initial knowledge from the data struct */
|
||||
conn->bits.user_passwd = data->set.userpwd?1:0;
|
||||
conn->bits.proxy_user_passwd = data->set.proxyuserpwd?1:0;
|
||||
@@ -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
|
||||
|
@@ -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. */
|
||||
@@ -179,7 +179,9 @@ struct FTP {
|
||||
char *entrypath; /* the PWD reply when we logged on */
|
||||
|
||||
char *cache; /* data cache between getresponse()-calls */
|
||||
size_t cache_size; /* size of cache in bytes */
|
||||
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 */
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
241
src/main.c
241
src/main.c
@@ -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,9 +1447,17 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */
|
||||
hugehelp();
|
||||
return PARAM_HELP_REQUESTED;
|
||||
case 'n':
|
||||
/* pick info from .netrc, if this is used for http, curl will
|
||||
automatically enfore user+password with the request */
|
||||
config->conf ^= CONF_NETRC;
|
||||
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 */
|
||||
@@ -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);
|
||||
@@ -2485,6 +2637,14 @@ operate(struct Configurable *config, int argc, char *argv[])
|
||||
if(config->disable_epsv)
|
||||
/* 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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
@@ -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 ") "
|
||||
|
@@ -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 */
|
||||
|
@@ -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
|
||||
|
@@ -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
49
tests/data/test130
Normal 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
49
tests/data/test131
Normal 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
49
tests/data/test132
Normal 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
49
tests/data/test133
Normal 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
49
tests/data/test134
Normal 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
39
tests/data/test135
Normal 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>
|
@@ -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);
|
||||
|
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/perl
|
||||
#!/usr/bin/env perl
|
||||
#
|
||||
# Example input:
|
||||
#
|
||||
|
@@ -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)) {
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -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)
|
||||
{
|
||||
sigpipe = 1;
|
||||
}
|
||||
|
||||
|
||||
static void sigterm_handler(int sig)
|
||||
{
|
||||
char logbuf[100];
|
||||
snprintf(logbuf, 100, "Got signal %d, terminating", sig);
|
||||
logmsg(logbuf);
|
||||
sigterm = 1;
|
||||
(void)sig; /* prevent warning */
|
||||
sigpipe = 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");
|
||||
|
||||
|
Reference in New Issue
Block a user